shithub: hugo

Download patch

ref: 6b0752e8c0334dfb2275a2edb975ec13a2724134
parent: c6fe87b14e06a46bbf3b94cfdf67e9127d51e2fe
author: Noah Campbell <[email protected]>
date: Tue Sep 17 10:16:06 EDT 2013

Move AbUrlify to post content transformation

Currently the a@href and script@src elements will have BaseUrl applied
to their elements prior to being written to disk.

--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -14,6 +14,7 @@
 package hugolib
 
 import (
+	"io"
 	"bitbucket.org/pkg/inflect"
 	"bytes"
 	"fmt"
@@ -21,6 +22,7 @@
 	"github.com/spf13/hugo/target"
 	helpers "github.com/spf13/hugo/template"
 	"github.com/spf13/hugo/template/bundle"
+	"github.com/spf13/hugo/transform"
 	"github.com/spf13/nitro"
 	"html/template"
 	"os"
@@ -75,6 +77,7 @@
 	Info       SiteInfo
 	Shortcodes map[string]ShortcodeFunc
 	timer      *nitro.B
+	Transformer *transform.Transformer
 	Target     target.Output
 	Alias      target.AliasPublisher
 }
@@ -154,7 +157,6 @@
 	s.timerStep("render and write aliases")
 	s.ProcessShortcodes()
 	s.timerStep("render shortcodes")
-	s.AbsUrlify()
 	s.timerStep("absolute URLify")
 	if err = s.RenderIndexes(); err != nil {
 		return
@@ -246,20 +248,6 @@
 	}
 }
 
-func (s *Site) AbsUrlify() {
-	baseWithoutTrailingSlash := strings.TrimRight(s.Config.BaseUrl, "/")
-	baseWithSlash := baseWithoutTrailingSlash + "/"
-	for _, page := range s.Pages {
-		content := string(page.Content)
-		content = strings.Replace(content, " src=\"/", " src=\""+baseWithSlash, -1)
-		content = strings.Replace(content, " src='/", " src='"+baseWithSlash, -1)
-		content = strings.Replace(content, " href='/", " href='"+baseWithSlash, -1)
-		content = strings.Replace(content, " href=\"/", " href=\""+baseWithSlash, -1)
-		content = strings.Replace(content, baseWithoutTrailingSlash+"//", baseWithSlash, -1)
-		page.Content = template.HTML(content)
-	}
-}
-
 func (s *Site) CreatePages() (err error) {
 	for _, file := range s.Source.Files() {
 		page, err := ReadFrom(file.Contents, file.Name)
@@ -418,7 +406,7 @@
 		if err != nil {
 			return err
 		}
-		err = s.WritePublic(p.OutFile, content.Bytes())
+		err = s.WritePublic(p.OutFile, content)
 		if err != nil {
 			return err
 		}
@@ -447,7 +435,7 @@
 
 			var base string
 			base = plural + "/" + k
-			err = s.WritePublic(base+".html", x.Bytes())
+			err = s.WritePublic(base+".html", x)
 			if err != nil {
 				return err
 			}
@@ -458,7 +446,7 @@
 				n.Url = helpers.Urlize(plural + "/" + k + ".xml")
 				n.Permalink = permalink(s, n.Url)
 				s.Tmpl.ExecuteTemplate(y, "rss.xml", n)
-				err = s.WritePublic(base+".xml", y.Bytes())
+				err = s.WritePublic(base+".xml", y)
 				if err != nil {
 					return err
 				}
@@ -487,7 +475,7 @@
 				return err
 			}
 
-			err = s.WritePublic(plural+"/index.html", x.Bytes())
+			err = s.WritePublic(plural+"/index.html", x)
 			if err != nil {
 				return err
 			}
@@ -511,7 +499,7 @@
 		if err != nil {
 			return err
 		}
-		err = s.WritePublic(section, content.Bytes())
+		err = s.WritePublic(section, content)
 		if err != nil {
 			return err
 		}
@@ -522,7 +510,7 @@
 			n.Permalink = template.HTML(string(n.Site.BaseUrl) + n.Url)
 			y := s.NewXMLBuffer()
 			s.Tmpl.ExecuteTemplate(y, "rss.xml", n)
-			err = s.WritePublic(section+"/index.xml", y.Bytes())
+			err = s.WritePublic(section+"/index.xml", y)
 			return err
 		}
 	}
@@ -547,7 +535,7 @@
 	if err != nil {
 		return err
 	}
-	err = s.WritePublic("/", x.Bytes())
+	err = s.WritePublic("/", x)
 	if err != nil {
 		return err
 	}
@@ -559,7 +547,7 @@
 		n.Permalink = permalink(s, "index.xml")
 		y := s.NewXMLBuffer()
 		s.Tmpl.ExecuteTemplate(y, "rss.xml", n)
-		err = s.WritePublic("index.xml", y.Bytes())
+		err = s.WritePublic("index.xml", y)
 		return err
 	}
 
@@ -571,7 +559,7 @@
 		if err != nil {
 			return err
 		}
-		err = s.WritePublic("404.html", x.Bytes())
+		err = s.WritePublic("404.html", x)
 		return err
 	}
 
@@ -631,7 +619,7 @@
 	}
 }
 
-func (s *Site) WritePublic(path string, content []byte) (err error) {
+func (s *Site) WritePublic(path string, content io.Reader) (err error) {
 	s.initTarget()
 
 	if s.Config.Verbose {
@@ -638,7 +626,12 @@
 		fmt.Println(path)
 	}
 
-	return s.Target.Publish(path, bytes.NewReader(content))
+	if s.Transformer == nil {
+		s.Transformer = &transform.Transformer{BaseURL: s.Config.BaseUrl}
+	}
+	final := new(bytes.Buffer)
+	s.Transformer.Apply(content, final)
+	return s.Target.Publish(path, final)
 }
 
 func (s *Site) WriteAlias(path string, permalink template.HTML) (err error) {
--- a/hugolib/site_test.go
+++ b/hugolib/site_test.go
@@ -19,6 +19,7 @@
 var TEMPLATE_CONTENT = "{{ .Content }}"
 var TEMPLATE_DATE = "{{ .Date }}"
 var INVALID_TEMPLATE_FORMAT_DATE = "{{ .Date.Format time.RFC3339 }}"
+var TEMPLATE_WITH_URL = "<a href=\"foobar.jpg\">Going</a>"
 
 var PAGE_URL_SPECIFIED = `---
 title: simple template
@@ -183,5 +184,40 @@
 
 	if p.OutFile != "mycategory/my-whatever-content/index.html" {
 		t.Errorf("Outfile does not match.  Expected '%s', got '%s'", expected, p.OutFile)
+	}
+}
+
+func TestAbsUrlify(t *testing.T) {
+	files := make(map[string][]byte)
+	target := &InMemoryTarget{files: files}
+	s := &Site{
+		Target: target,
+		Config: Config{BaseUrl: "http://auth/bub/"},
+		Source: &inMemorySource{urlFakeSource},
+	}
+	s.initializeSiteInfo()
+	s.prepTemplates()
+	must(s.addTemplate("blue/single.html", TEMPLATE_WITH_URL))
+
+	if err := s.CreatePages(); err != nil {
+		t.Fatalf("Unable to create pages: %s", err)
+	}
+
+	if err := s.BuildSiteMeta(); err != nil {
+		t.Fatalf("Unable to build site metadata: %s", err)
+	}
+
+	if err := s.RenderPages(); err != nil {
+		t.Fatalf("Unable to render pages. %s", err)
+	}
+
+	content, ok := target.files["content/blue/slug-doc-1.html"]
+	if !ok {
+		t.Fatalf("Unable to locate rendered content")
+	}
+
+	expected := "<html><head></head><body><a href=\"http://auth/bub/foobar.jpg\">Going</a></body></html>"
+	if string(content) != expected {
+		t.Errorf("Expected: %q, got: %q", expected, string(content))
 	}
 }
--- a/hugolib/site_url_test.go
+++ b/hugolib/site_url_test.go
@@ -96,8 +96,9 @@
 		t.Errorf("No indexed rendered. %v", target.files)
 	}
 
-	if len(blueIndex) != 2 {
-		t.Errorf("Number of pages does not equal 2, got %d. %q", len(blueIndex), blueIndex)
+	expected := "<html><head></head><body>..</body></html>"
+	if string(blueIndex) != expected {
+		t.Errorf("Index template does not match expected: %q, got: %q", expected, string(blueIndex))
 	}
 
 	for _, s := range []string{
--- a/transform/post.go
+++ b/transform/post.go
@@ -17,7 +17,7 @@
 		return
 	}
 
-	if err = t.absUrlify(tr); err != nil {
+	if err = t.absUrlify(tr, elattr{"a", "href"}, elattr{"script", "src"}); err != nil {
 		return
 	}
 
@@ -24,7 +24,11 @@
 	return tr.Render(w)
 }
 
-func (t *Transformer) absUrlify(tr *htmltran.Transformer) (err error) {
+type elattr struct {
+	tag, attr string
+}
+
+func (t *Transformer) absUrlify(tr *htmltran.Transformer, selectors ...elattr) (err error) {
 	var baseURL, inURL *url.URL
 
 	if baseURL, err = url.Parse(t.BaseURL); err != nil {
@@ -38,9 +42,11 @@
 		return baseURL.ResolveReference(inURL).String()
 	}
 
-	if err = tr.Apply(htmltran.TransformAttrib("src", replace), "script"); err != nil {
-		return
+	for _, el := range selectors {
+		if err = tr.Apply(htmltran.TransformAttrib(el.attr, replace), el.tag); err != nil {
+			return
+		}
 	}
 
-	return tr.Apply(htmltran.TransformAttrib("href", replace), "a")
+	return
 }