summaryrefslogtreecommitdiffstats
path: root/transform
diff options
context:
space:
mode:
authorNoah Campbell <noahcampbell@gmail.com>2013-09-17 13:04:28 -0700
committerNoah Campbell <noahcampbell@gmail.com>2013-09-17 13:04:28 -0700
commitc6fe87b14e06a46bbf3b94cfdf67e9127d51e2fe (patch)
tree764e519e3b6acd02c081d5af47d3e2ed6384ea34 /transform
parentc75da346e1c9257d05bebc91c13e08a93cda0294 (diff)
Add a transform step
This allows for the manipulation of the DOM. This is expected to be applied after the templates are rendered.
Diffstat (limited to 'transform')
-rw-r--r--transform/post.go46
-rw-r--r--transform/posttrans_test.go41
2 files changed, 87 insertions, 0 deletions
diff --git a/transform/post.go b/transform/post.go
new file mode 100644
index 000000000..f54688cb2
--- /dev/null
+++ b/transform/post.go
@@ -0,0 +1,46 @@
+package transform
+
+import (
+ "io"
+ "net/url"
+ htmltran "code.google.com/p/go-html-transform/html/transform"
+)
+
+type Transformer struct {
+ BaseURL string
+}
+
+func (t *Transformer) Apply(r io.Reader, w io.Writer) (err error) {
+ var tr *htmltran.Transformer
+
+ if tr, err = htmltran.NewFromReader(r); err != nil {
+ return
+ }
+
+ if err = t.absUrlify(tr); err != nil {
+ return
+ }
+
+ return tr.Render(w)
+}
+
+func (t *Transformer) absUrlify(tr *htmltran.Transformer) (err error) {
+ var baseURL, inURL *url.URL
+
+ if baseURL, err = url.Parse(t.BaseURL); err != nil {
+ return
+ }
+
+ replace := func(in string) string {
+ if inURL, err = url.Parse(in); err != nil {
+ return in + "?"
+ }
+ return baseURL.ResolveReference(inURL).String()
+ }
+
+ if err = tr.Apply(htmltran.TransformAttrib("src", replace), "script"); err != nil {
+ return
+ }
+
+ return tr.Apply(htmltran.TransformAttrib("href", replace), "a")
+}
diff --git a/transform/posttrans_test.go b/transform/posttrans_test.go
new file mode 100644
index 000000000..de2d2277c
--- /dev/null
+++ b/transform/posttrans_test.go
@@ -0,0 +1,41 @@
+package transform
+
+import (
+ "testing"
+ "strings"
+ "bytes"
+)
+
+const H5_JS_CONTENT_DOUBLE_QUOTE = "<!DOCTYPE html><html><head><script src=\"foobar.js\"></script></head><body><nav><h1>title</h1></nav><article>content <a href='/foobar'>foobar</a>. Follow up</article></body></html>"
+const H5_JS_CONTENT_SINGLE_QUOTE = "<!DOCTYPE html><html><head><script src='foobar.js'></script></head><body><nav><h1>title</h1></nav><article>content <a href='/foobar'>foobar</a>. Follow up</article></body></html>"
+const H5_JS_CONTENT_ABS_URL = "<!DOCTYPE html><html><head><script src=\"http://user@host:10234/foobar.js\"></script></head><body><nav><h1>title</h1></nav><article>content <a href=\"https://host/foobar\">foobar</a>. Follow up</article></body></html>"
+// URL doesn't recognize authorities. BUG?
+//const H5_JS_CONTENT_ABS_URL = "<!DOCTYPE html><html><head><script src=\"//host/foobar.js\"></script></head><body><nav><h1>title</h1></nav><article>content <a href=\"https://host/foobar\">foobar</a>. Follow up</article></body></html>"
+
+const CORRECT_OUTPUT_SRC_HREF = "<!DOCTYPE html><html><head><script src=\"http://base/foobar.js\"></script></head><body><nav><h1>title</h1></nav><article>content <a href=\"http://base/foobar\">foobar</a>. Follow up</article></body></html>"
+
+
+func TestAbsUrlify(t *testing.T) {
+ tests := []struct {
+ content string
+ expected string
+ }{
+ {H5_JS_CONTENT_DOUBLE_QUOTE, CORRECT_OUTPUT_SRC_HREF},
+ {H5_JS_CONTENT_SINGLE_QUOTE, CORRECT_OUTPUT_SRC_HREF},
+ {H5_JS_CONTENT_ABS_URL, H5_JS_CONTENT_ABS_URL},
+ }
+
+ for _, test := range tests {
+ tr := &Transformer{
+ BaseURL: "http://base",
+ }
+ out := new(bytes.Buffer)
+ err := tr.Apply(strings.NewReader(test.content), out)
+ if err != nil {
+ t.Errorf("Unexpected error: %s", err)
+ }
+ if test.expected != string(out.Bytes()) {
+ t.Errorf("Expected:\n%s\nGot:\n%s", test.expected, string(out.Bytes()))
+ }
+}
+}