hugolib, output: Handle aliases for all HTML formats
This commit is contained in:
parent
0c4701f0ef
commit
87188496fb
6 changed files with 77 additions and 22 deletions
|
@ -88,18 +88,6 @@ func (s *Site) publishDestAlias(allowRoot bool, path, permalink string, p *Page)
|
||||||
|
|
||||||
isXHTML := strings.HasSuffix(path, ".xhtml")
|
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)
|
s.Log.DEBUG.Println("creating alias:", path, "redirecting to", permalink)
|
||||||
|
|
||||||
targetPath, err := handler.targetPathAlias(path)
|
targetPath, err := handler.targetPathAlias(path)
|
||||||
|
|
|
@ -29,6 +29,14 @@ aliases: ["foo/bar/"]
|
||||||
For some moments the old man did not reply. He stood with bowed head, buried in deep thought. But at last he spoke.
|
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 basicTemplate = "<html><body>{{.Content}}</body></html>"
|
||||||
const aliasTemplate = "<html><body>ALIASTEMPLATE</body></html>"
|
const aliasTemplate = "<html><body>ALIASTEMPLATE</body></html>"
|
||||||
|
|
||||||
|
@ -51,6 +59,32 @@ func TestAlias(t *testing.T) {
|
||||||
th.assertFileContent(filepath.Join("public", "foo", "bar", "index.html"), "<meta http-equiv=\"refresh\" content=\"0; ")
|
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) {
|
func TestAliasTemplate(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
|
|
@ -152,17 +152,21 @@ func (o OutputFormat) MediaType() media.Type {
|
||||||
// OutputFormats gives the output formats for this Page.
|
// OutputFormats gives the output formats for this Page.
|
||||||
func (p *Page) OutputFormats() OutputFormats {
|
func (p *Page) OutputFormats() OutputFormats {
|
||||||
var o OutputFormats
|
var o OutputFormats
|
||||||
isCanonical := len(p.outputFormats) == 1
|
|
||||||
for _, f := range p.outputFormats {
|
for _, f := range p.outputFormats {
|
||||||
rel := f.Rel
|
o = append(o, newOutputFormat(p, f))
|
||||||
if isCanonical {
|
|
||||||
rel = "canonical"
|
|
||||||
}
|
|
||||||
o = append(o, &OutputFormat{Rel: rel, f: f, p: p})
|
|
||||||
}
|
}
|
||||||
return o
|
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.
|
// OutputFormats gives the alternative output formats for this PageOutput.
|
||||||
func (p *PageOutput) AlternativeOutputFormats() (OutputFormats, error) {
|
func (p *PageOutput) AlternativeOutputFormats() (OutputFormats, error) {
|
||||||
var o OutputFormats
|
var o OutputFormats
|
||||||
|
|
|
@ -305,11 +305,23 @@ func (s *Site) renderAliases() error {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
plink := p.Permalink()
|
for _, f := range p.outputFormats {
|
||||||
|
if !f.IsHTML {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
for _, a := range p.Aliases {
|
o := newOutputFormat(p, f)
|
||||||
if err := s.writeDestAlias(a, plink, p); err != nil {
|
plink := o.Permalink()
|
||||||
return err
|
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ var (
|
||||||
BaseName: "index",
|
BaseName: "index",
|
||||||
Path: "amp",
|
Path: "amp",
|
||||||
Rel: "amphtml",
|
Rel: "amphtml",
|
||||||
|
IsHTML: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
CalendarType = Format{
|
CalendarType = Format{
|
||||||
|
@ -52,6 +53,7 @@ var (
|
||||||
MediaType: media.HTMLType,
|
MediaType: media.HTMLType,
|
||||||
BaseName: "index",
|
BaseName: "index",
|
||||||
Rel: "canonical",
|
Rel: "canonical",
|
||||||
|
IsHTML: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONType = Format{
|
JSONType = Format{
|
||||||
|
@ -113,6 +115,10 @@ type Format struct {
|
||||||
// as template parser.
|
// as template parser.
|
||||||
IsPlainText bool
|
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.
|
// Enable to ignore the global uglyURLs setting.
|
||||||
NoUgly bool
|
NoUgly bool
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,18 +26,29 @@ func TestDefaultTypes(t *testing.T) {
|
||||||
require.Equal(t, "webcal://", CalendarType.Protocol)
|
require.Equal(t, "webcal://", CalendarType.Protocol)
|
||||||
require.Empty(t, CalendarType.Path)
|
require.Empty(t, CalendarType.Path)
|
||||||
require.True(t, CalendarType.IsPlainText)
|
require.True(t, CalendarType.IsPlainText)
|
||||||
|
require.False(t, CalendarType.IsHTML)
|
||||||
|
|
||||||
require.Equal(t, "HTML", HTMLType.Name)
|
require.Equal(t, "HTML", HTMLType.Name)
|
||||||
require.Equal(t, media.HTMLType, HTMLType.MediaType)
|
require.Equal(t, media.HTMLType, HTMLType.MediaType)
|
||||||
require.Empty(t, HTMLType.Path)
|
require.Empty(t, HTMLType.Path)
|
||||||
require.Empty(t, HTMLType.Protocol) // Will inherit the BaseURL protocol.
|
require.Empty(t, HTMLType.Protocol) // Will inherit the BaseURL protocol.
|
||||||
require.False(t, HTMLType.IsPlainText)
|
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, "RSS", RSSType.Name)
|
||||||
require.Equal(t, media.RSSType, RSSType.MediaType)
|
require.Equal(t, media.RSSType, RSSType.MediaType)
|
||||||
require.Empty(t, RSSType.Path)
|
require.Empty(t, RSSType.Path)
|
||||||
require.False(t, RSSType.IsPlainText)
|
require.False(t, RSSType.IsPlainText)
|
||||||
require.True(t, RSSType.NoUgly)
|
require.True(t, RSSType.NoUgly)
|
||||||
|
require.False(t, CalendarType.IsHTML)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetType(t *testing.T) {
|
func TestGetType(t *testing.T) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue