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) {