mirror of
				https://github.com/gohugoio/hugo.git
				synced 2024-05-11 05:54:58 +00:00 
			
		
		
		
	Add canonifyurls config option.
				
					
				
			Be able to inhibit AbsURL canonicalization of content, on a site configuration basis. Advantages of being able to inhibit this include making it easier to rendering on other hostnames, and being able to include resources on http or https depending on how this page was retrieved, avoiding mixed-mode client complaints without adding latency for plain http.
This commit is contained in:
		
							
								
								
									
										21
									
								
								docs/content/extras/urls.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								docs/content/extras/urls.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
---
 | 
			
		||||
title: "URLs"
 | 
			
		||||
date: "2014-01-03"
 | 
			
		||||
aliases:
 | 
			
		||||
  - "/doc/urls/"
 | 
			
		||||
groups: ["extras"]
 | 
			
		||||
groups_weight: 40
 | 
			
		||||
---
 | 
			
		||||
By default, all relative URLs encountered in the input will be canonicalized
 | 
			
		||||
using `baseurl`, so that a link `/css/foo.css` becomes
 | 
			
		||||
`http://yoursite.example.com/css/foo.css`.
 | 
			
		||||
 | 
			
		||||
Setting `canonifyurls` to `false` will prevent this canonicalization.
 | 
			
		||||
 | 
			
		||||
Benefits of canonicalization include fixing all URLs to be absolute, which may
 | 
			
		||||
aid with some parsing tasks.  Note though that all real browsers handle this
 | 
			
		||||
client-side without issues.
 | 
			
		||||
 | 
			
		||||
Benefits of non-canonicalization include being able to have resource inclusion
 | 
			
		||||
be scheme-relative, so that http vs https can be decided based on how this
 | 
			
		||||
page was retrieved.
 | 
			
		||||
@@ -30,6 +30,7 @@ indexes:
 | 
			
		||||
   category: "categories"
 | 
			
		||||
   tag: "tags"
 | 
			
		||||
baseurl: "http://yoursite.example.com/"
 | 
			
		||||
canonifyurls: true
 | 
			
		||||
...
 | 
			
		||||
{{% /highlight %}}
 | 
			
		||||
 | 
			
		||||
@@ -46,6 +47,7 @@ The following is an example of a json config file with the default values:
 | 
			
		||||
       "tag": "tags"
 | 
			
		||||
    },
 | 
			
		||||
    "baseurl": "http://yoursite.example.com/"
 | 
			
		||||
    "canonifyurls": true
 | 
			
		||||
}
 | 
			
		||||
{{% /highlight %}}
 | 
			
		||||
 | 
			
		||||
@@ -56,6 +58,7 @@ The following is an example of a toml config file with the default values:
 | 
			
		||||
    publishdir = "public"
 | 
			
		||||
    builddrafts = false
 | 
			
		||||
    baseurl = "http://yoursite.example.com/"
 | 
			
		||||
    canonifyurls = true
 | 
			
		||||
    [indexes]
 | 
			
		||||
       category = "categories"
 | 
			
		||||
       tag = "tags"
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,7 @@ type Config struct {
 | 
			
		||||
	Params                                     map[string]interface{}
 | 
			
		||||
	Permalinks                                 PermalinkOverrides
 | 
			
		||||
	BuildDrafts, UglyUrls, Verbose             bool
 | 
			
		||||
	CanonifyUrls							   bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var c Config
 | 
			
		||||
@@ -61,6 +62,7 @@ func SetupConfig(cfgfile *string, path *string) *Config {
 | 
			
		||||
	c.BuildDrafts = false
 | 
			
		||||
	c.UglyUrls = false
 | 
			
		||||
	c.Verbose = false
 | 
			
		||||
	c.CanonifyUrls = true
 | 
			
		||||
 | 
			
		||||
	c.readInConfig()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -573,11 +573,17 @@ func (s *Site) render(d interface{}, out string, layouts ...string) (err error)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	absURL, err := transform.AbsURL(s.Config.BaseUrl)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	transformLinks := transform.NewEmptyTransforms()
 | 
			
		||||
 | 
			
		||||
	if s.Config.CanonifyUrls {
 | 
			
		||||
		absURL, err := transform.AbsURL(s.Config.BaseUrl)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		transformLinks = append(transformLinks, absURL...)
 | 
			
		||||
	}
 | 
			
		||||
	transformer := transform.NewChain(absURL...)
 | 
			
		||||
 | 
			
		||||
	transformer := transform.NewChain(transformLinks...)
 | 
			
		||||
 | 
			
		||||
	var renderBuffer *bytes.Buffer
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -234,7 +234,11 @@ func TestSkipRender(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	s := &Site{
 | 
			
		||||
		Target: target,
 | 
			
		||||
		Config: Config{Verbose: true, BaseUrl: "http://auth/bub"},
 | 
			
		||||
		Config: Config{
 | 
			
		||||
			Verbose: true,
 | 
			
		||||
			BaseUrl: "http://auth/bub",
 | 
			
		||||
			CanonifyUrls: true,
 | 
			
		||||
		},
 | 
			
		||||
		Source: &source.InMemorySource{sources},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -290,43 +294,52 @@ func TestAbsUrlify(t *testing.T) {
 | 
			
		||||
		{"sect/doc1.html", []byte("<!doctype html><html><head></head><body><a href=\"#frag1\">link</a></body></html>"), "sect"},
 | 
			
		||||
		{"content/blue/doc2.html", []byte("---\nf: t\n---\n<!doctype html><html><body>more content</body></html>"), "blue"},
 | 
			
		||||
	}
 | 
			
		||||
	s := &Site{
 | 
			
		||||
		Target: target,
 | 
			
		||||
		Config: Config{BaseUrl: "http://auth/bub"},
 | 
			
		||||
		Source: &source.InMemorySource{sources},
 | 
			
		||||
	}
 | 
			
		||||
	s.initializeSiteInfo()
 | 
			
		||||
	s.prepTemplates()
 | 
			
		||||
	must(s.addTemplate("blue/single.html", TEMPLATE_WITH_URL_ABS))
 | 
			
		||||
	for _, canonify := range []bool{true, false} {
 | 
			
		||||
		s := &Site{
 | 
			
		||||
			Target: target,
 | 
			
		||||
			Config: Config{
 | 
			
		||||
				BaseUrl: "http://auth/bub",
 | 
			
		||||
				CanonifyUrls: canonify,
 | 
			
		||||
			},
 | 
			
		||||
			Source: &source.InMemorySource{sources},
 | 
			
		||||
		}
 | 
			
		||||
		t.Logf("Rendering with BaseUrl %q and CanonifyUrls set %v", s.Config.BaseUrl, canonify)
 | 
			
		||||
		s.initializeSiteInfo()
 | 
			
		||||
		s.prepTemplates()
 | 
			
		||||
		must(s.addTemplate("blue/single.html", TEMPLATE_WITH_URL_ABS))
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		file, expected string
 | 
			
		||||
	}{
 | 
			
		||||
		{"content/blue/doc2.html", "<a href=\"http://auth/bub/foobar.jpg\">Going</a>"},
 | 
			
		||||
		{"sect/doc1.html", "<!doctype html><html><head></head><body><a href=\"#frag1\">link</a></body></html>"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		content, ok := target.Files[test.file]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			t.Fatalf("Unable to locate rendered content: %s", test.file)
 | 
			
		||||
		if err := s.CreatePages(); err != nil {
 | 
			
		||||
			t.Fatalf("Unable to create pages: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		expected := test.expected
 | 
			
		||||
		if string(content) != expected {
 | 
			
		||||
			t.Errorf("AbsUrlify content expected:\n%q\ngot\n%q", expected, string(content))
 | 
			
		||||
		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)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		tests := []struct {
 | 
			
		||||
			file, expected string
 | 
			
		||||
		}{
 | 
			
		||||
			{"content/blue/doc2.html", "<a href=\"http://auth/bub/foobar.jpg\">Going</a>"},
 | 
			
		||||
			{"sect/doc1.html", "<!doctype html><html><head></head><body><a href=\"#frag1\">link</a></body></html>"},
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, test := range tests {
 | 
			
		||||
			content, ok := target.Files[test.file]
 | 
			
		||||
			if !ok {
 | 
			
		||||
				t.Fatalf("Unable to locate rendered content: %s", test.file)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			expected := test.expected
 | 
			
		||||
			if !canonify {
 | 
			
		||||
				expected = strings.Replace(expected, s.Config.BaseUrl, "", -1)
 | 
			
		||||
			}
 | 
			
		||||
			if string(content) != expected {
 | 
			
		||||
				t.Errorf("AbsUrlify content expected:\n%q\ngot\n%q", expected, string(content))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,10 @@ func NewChain(trs ...link) chain {
 | 
			
		||||
	return trs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewEmptyTransforms() []link {
 | 
			
		||||
	return make([]link, 0, 20)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *chain) Apply(w io.Writer, r io.Reader) (err error) {
 | 
			
		||||
 | 
			
		||||
	buffer := new(bytes.Buffer)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user