diff options
author | Noah Campbell <noahcampbell@gmail.com> | 2013-09-17 13:04:28 -0700 |
---|---|---|
committer | Noah Campbell <noahcampbell@gmail.com> | 2013-09-17 13:04:28 -0700 |
commit | c6fe87b14e06a46bbf3b94cfdf67e9127d51e2fe (patch) | |
tree | 764e519e3b6acd02c081d5af47d3e2ed6384ea34 /transform | |
parent | c75da346e1c9257d05bebc91c13e08a93cda0294 (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.go | 46 | ||||
-rw-r--r-- | transform/posttrans_test.go | 41 |
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())) + } +} +} |