shithub: hugo

Download patch

ref: 87188496fbb68c39567ec3ee3a55a9305a13e48b
parent: 0c4701f0effbf651891979b925073f6fc5d26a82
author: Bjørn Erik Pedersen <[email protected]>
date: Fri Mar 24 07:25:25 EDT 2017

hugolib, output: Handle aliases for all HTML formats

--- a/hugolib/alias.go
+++ b/hugolib/alias.go
@@ -88,18 +88,6 @@
 
 	isXHTML := strings.HasSuffix(path, ".xhtml")
 
-	if s.Info.relativeURLs {
-		// convert `permalink` into URI relative to location of `path`
-		baseURL := helpers.SanitizeURLKeepTrailingSlash(s.Cfg.GetString("baseURL"))
-		if strings.HasPrefix(permalink, baseURL) {
-			permalink = "/" + strings.TrimPrefix(permalink, baseURL)
-		}
-		permalink, err = helpers.GetRelativePath(permalink, path)
-		if err != nil {
-			s.Log.ERROR.Println("Failed to make a RelativeURL alias:", path, "redirecting to", permalink)
-		}
-		permalink = filepath.ToSlash(permalink)
-	}
 	s.Log.DEBUG.Println("creating alias:", path, "redirecting to", permalink)
 
 	targetPath, err := handler.targetPathAlias(path)
--- a/hugolib/alias_test.go
+++ b/hugolib/alias_test.go
@@ -29,6 +29,14 @@
 For some moments the old man did not reply. He stood with bowed head, buried in deep thought. But at last he spoke.
 `
 
+const pageWithAliasMultipleOutputs = `---
+title: Has Alias for HTML and AMP
+aliases: ["foo/bar/"]
+outputs: ["HTML", "AMP", "JSON"]
+---
+For some moments the old man did not reply. He stood with bowed head, buried in deep thought. But at last he spoke.
+`
+
 const basicTemplate = "<html><body>{{.Content}}</body></html>"
 const aliasTemplate = "<html><body>ALIASTEMPLATE</body></html>"
 
@@ -49,6 +57,32 @@
 	th.assertFileContent(filepath.Join("public", "page", "index.html"), "For some moments the old man")
 	// the alias redirector
 	th.assertFileContent(filepath.Join("public", "foo", "bar", "index.html"), "<meta http-equiv=\"refresh\" content=\"0; ")
+}
+
+func TestAliasMultipleOutputFormats(t *testing.T) {
+	t.Parallel()
+
+	var (
+		cfg, fs = newTestCfg()
+		th      = testHelper{cfg, fs, t}
+	)
+
+	writeSource(t, fs, filepath.Join("content", "page.md"), pageWithAliasMultipleOutputs)
+	writeSource(t, fs, filepath.Join("layouts", "_default", "single.html"), basicTemplate)
+	writeSource(t, fs, filepath.Join("layouts", "_default", "single.amp.html"), basicTemplate)
+	writeSource(t, fs, filepath.Join("layouts", "_default", "single.json"), basicTemplate)
+
+	buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{})
+
+	// the real pages
+	th.assertFileContent(filepath.Join("public", "page", "index.html"), "For some moments the old man")
+	th.assertFileContent(filepath.Join("public", "amp", "page", "index.html"), "For some moments the old man")
+	th.assertFileContent(filepath.Join("public", "page", "index.json"), "For some moments the old man")
+
+	// the alias redirectors
+	th.assertFileContent(filepath.Join("public", "foo", "bar", "index.html"), "<meta http-equiv=\"refresh\" content=\"0; ")
+	th.assertFileContent(filepath.Join("public", "foo", "bar", "amp", "index.html"), "<meta http-equiv=\"refresh\" content=\"0; ")
+	require.False(t, destinationExists(th.Fs, filepath.Join("public", "foo", "bar", "index.json")))
 }
 
 func TestAliasTemplate(t *testing.T) {
--- a/hugolib/page_output.go
+++ b/hugolib/page_output.go
@@ -152,15 +152,19 @@
 // OutputFormats gives the output formats for this Page.
 func (p *Page) OutputFormats() OutputFormats {
 	var o OutputFormats
-	isCanonical := len(p.outputFormats) == 1
 	for _, f := range p.outputFormats {
-		rel := f.Rel
-		if isCanonical {
-			rel = "canonical"
-		}
-		o = append(o, &OutputFormat{Rel: rel, f: f, p: p})
+		o = append(o, newOutputFormat(p, f))
 	}
 	return o
+}
+
+func newOutputFormat(p *Page, f output.Format) *OutputFormat {
+	rel := f.Rel
+	isCanonical := len(p.outputFormats) == 1
+	if isCanonical {
+		rel = "canonical"
+	}
+	return &OutputFormat{Rel: rel, f: f, p: p}
 }
 
 // OutputFormats gives the alternative output formats for this PageOutput.
--- a/hugolib/site_render.go
+++ b/hugolib/site_render.go
@@ -305,11 +305,23 @@
 			continue
 		}
 
-		plink := p.Permalink()
+		for _, f := range p.outputFormats {
+			if !f.IsHTML {
+				continue
+			}
 
-		for _, a := range p.Aliases {
-			if err := s.writeDestAlias(a, plink, p); err != nil {
-				return err
+			o := newOutputFormat(p, f)
+			plink := o.Permalink()
+
+			for _, a := range p.Aliases {
+				if f.Path != "" {
+					// Make sure AMP and similar doesn't clash with regular aliases.
+					a = path.Join(a, f.Path)
+				}
+
+				if err := s.writeDestAlias(a, plink, p); err != nil {
+					return err
+				}
 			}
 		}
 	}
--- a/output/outputFormat.go
+++ b/output/outputFormat.go
@@ -29,6 +29,7 @@
 		BaseName:  "index",
 		Path:      "amp",
 		Rel:       "amphtml",
+		IsHTML:    true,
 	}
 
 	CalendarType = Format{
@@ -52,6 +53,7 @@
 		MediaType: media.HTMLType,
 		BaseName:  "index",
 		Rel:       "canonical",
+		IsHTML:    true,
 	}
 
 	JSONType = Format{
@@ -112,6 +114,10 @@
 	// IsPlainText decides whether to use text/template or html/template
 	// as template parser.
 	IsPlainText bool
+
+	// IsHTML returns whether this format is int the HTML family. This includes
+	// HTML, AMP etc. This is used to decide when to create alias redirects etc.
+	IsHTML bool
 
 	// Enable to ignore the global uglyURLs setting.
 	NoUgly bool
--- a/output/outputFormat_test.go
+++ b/output/outputFormat_test.go
@@ -26,6 +26,7 @@
 	require.Equal(t, "webcal://", CalendarType.Protocol)
 	require.Empty(t, CalendarType.Path)
 	require.True(t, CalendarType.IsPlainText)
+	require.False(t, CalendarType.IsHTML)
 
 	require.Equal(t, "HTML", HTMLType.Name)
 	require.Equal(t, media.HTMLType, HTMLType.MediaType)
@@ -32,12 +33,22 @@
 	require.Empty(t, HTMLType.Path)
 	require.Empty(t, HTMLType.Protocol) // Will inherit the BaseURL protocol.
 	require.False(t, HTMLType.IsPlainText)
+	require.True(t, HTMLType.IsHTML)
 
+	require.Equal(t, "AMP", AMPType.Name)
+	require.Equal(t, media.HTMLType, AMPType.MediaType)
+	require.Equal(t, "amp", AMPType.Path)
+	require.Empty(t, AMPType.Protocol) // Will inherit the BaseURL protocol.
+	require.False(t, AMPType.IsPlainText)
+	require.True(t, AMPType.IsHTML)
+
 	require.Equal(t, "RSS", RSSType.Name)
 	require.Equal(t, media.RSSType, RSSType.MediaType)
 	require.Empty(t, RSSType.Path)
 	require.False(t, RSSType.IsPlainText)
 	require.True(t, RSSType.NoUgly)
+	require.False(t, CalendarType.IsHTML)
+
 }
 
 func TestGetType(t *testing.T) {