"slugorfilename": p.pageToPermalinkSlugElseFilename,
"filename": p.pageToPermalinkFilename,
"contentbasename": p.pageToPermalinkContentBaseName,
- "contentbasenameorslug": p.pageToPermalinkContentBaseNameOrSlug,
+ "slugorcontentbasename": p.pageToPermalinkSlugOrContentBaseName,
}
p.expanders = make(map[string]map[string]func(Page) (string, error))
// pageToPermalinkContentBaseName returns the URL-safe form of the content base name.
func (l PermalinkExpander) pageToPermalinkContentBaseName(p Page, _ string) (string, error) {
- if p.File() == nil {
- return "", nil
- }
- return l.urlize(p.File().ContentBaseName()), nil
+ return l.urlize(p.PathInfo().BaseNameNoIdentifier()), nil
}
-// pageToPermalinkContentBaseNameOrSlug returns the URL-safe form of the content base name, or the slug.
-func (l PermalinkExpander) pageToPermalinkContentBaseNameOrSlug(p Page, a string) (string, error) {
+// pageToPermalinkSlugOrContentBaseName returns the URL-safe form of the slug, content base name.
+func (l PermalinkExpander) pageToPermalinkSlugOrContentBaseName(p Page, a string) (string, error) {
+ if p.Slug() != "" {
+ return l.urlize(p.Slug()), nil
+ }
name, err := l.pageToPermalinkContentBaseName(p, a)
if err != nil {
return "", nil
}
- if name != "" {
- return name, nil
- }
- return l.pageToPermalinkSlugElseTitle(p, a)
+ return name, nil
}
func (l PermalinkExpander) translationBaseName(p Page) string {
// We strip colons from paths constructed by Hugo (they are not supported on Windows).
b.AssertFileExists("public/cd/p2/index.html", true)
}
+
+func TestPermalinksContentbasenameContentAdapter(t *testing.T) {
+ t.Parallel()
+
+ files := `
+-- hugo.toml --
+[permalinks]
+[permalinks.page]
+a = "/:slugorcontentbasename/"
+b = "/:sections/:contentbasename/"
+-- content/_content.gotmpl --
+{{ $.AddPage (dict "kind" "page" "path" "a/b/contentbasename1" "title" "My A Page No Slug") }}
+{{ $.AddPage (dict "kind" "page" "path" "a/b/contentbasename2" "slug" "myslug" "title" "My A Page With Slug") }}
+ {{ $.AddPage (dict "kind" "section" "path" "b/c" "title" "My B Section") }}
+{{ $.AddPage (dict "kind" "page" "path" "b/c/contentbasename3" "title" "My B Page No Slug") }}
+-- layouts/_default/single.html --
+{{ .Title }}|{{ .RelPermalink }}|{{ .Kind }}|
+`
+ b := hugolib.Test(t, files)
+
+ b.AssertFileContent("public/contentbasename1/index.html", "My A Page No Slug|/contentbasename1/|page|")
+ b.AssertFileContent("public/myslug/index.html", "My A Page With Slug|/myslug/|page|")
+}
+
+func TestPermalinksContentbasenameWithAndWithoutFile(t *testing.T) {
+ t.Parallel()
+
+ files := `
+-- hugo.toml --
+[permalinks.section]
+a = "/mya/:contentbasename/"
+[permalinks.page]
+a = "/myapage/:contentbasename/"
+[permalinks.term]
+categories = "/myc/:slugorcontentbasename/"
+-- content/b/c/_index.md --
+---
+title: "C section"
+---
+-- content/a/b/index.md --
+---
+title: "My Title"
+categories: ["c1", "c2"]
+---
+-- content/categories/c2/_index.md --
+---
+title: "C2"
+slug: "c2slug"
+---
+-- layouts/_default/single.html --
+{{ .Title }}|{{ .RelPermalink }}|{{ .Kind }}|
+-- layouts/_default/list.html --
+{{ .Title }}|{{ .RelPermalink }}|{{ .Kind }}|
+`
+ b := hugolib.Test(t, files)
+
+ // Sections.
+ b.AssertFileContent("public/mya/a/index.html", "As|/mya/a/|section|")
+
+ // Pages.
+ b.AssertFileContent("public/myapage/b/index.html", "My Title|/myapage/b/|page|")
+
+ // Taxonomies.
+ b.AssertFileContent("public/myc/c1/index.html", "C1|/myc/c1/|term|")
+ b.AssertFileContent("public/myc/c2slug/index.html", "C2|/myc/c2slug/|term|")
+}
"time"
qt "github.com/frankban/quicktest"
+ "github.com/gohugoio/hugo/source"
)
// testdataPermalinks is used by a couple of tests; the expandsTo content is
var testdataPermalinks = []struct {
spec string
valid bool
+ withPage func(p *testPage)
expandsTo string
}{
- {":title", true, "spf13-vim-3.0-release-and-new-website"},
- {"/:year-:month-:title", true, "/2012-04-spf13-vim-3.0-release-and-new-website"},
- {"/:year/:yearday/:month/:monthname/:day/:weekday/:weekdayname/", true, "/2012/97/04/April/06/5/Friday/"}, // Dates
- {"/:section/", true, "/blue/"}, // Section
- {"/:title/", true, "/spf13-vim-3.0-release-and-new-website/"}, // Title
- {"/:slug/", true, "/the-slug/"}, // Slug
- {"/:slugorfilename/", true, "/the-slug/"}, // Slug or filename
- {"/:filename/", true, "/test-page/"}, // Filename
- {"/:06-:1-:2-:Monday", true, "/12-4-6-Friday"}, // Dates with Go formatting
- {"/:2006_01_02_15_04_05.000", true, "/2012_04_06_03_01_59.000"}, // Complicated custom date format
- {"/:sections/", true, "/a/b/c/"}, // Sections
- {"/:sections[last]/", true, "/c/"}, // Sections
- {"/:sections[0]/:sections[last]/", true, "/a/c/"}, // Sections
- {"/\\:filename", true, "/:filename"}, // Escape sequence
- {"/special\\::slug/", true, "/special:the-slug/"}, // Escape sequence
- {"/:contentbasename/", true, "/index/"}, // Content base name
- {"/:contentbasenameorslug/", true, "/index/"}, // Content base name or slug
-
+ {":title", true, nil, "spf13-vim-3.0-release-and-new-website"},
+ {"/:year-:month-:title", true, nil, "/2012-04-spf13-vim-3.0-release-and-new-website"},
+ {"/:year/:yearday/:month/:monthname/:day/:weekday/:weekdayname/", true, nil, "/2012/97/04/April/06/5/Friday/"}, // Dates
+ {"/:section/", true, nil, "/blue/"}, // Section
+ {"/:title/", true, nil, "/spf13-vim-3.0-release-and-new-website/"}, // Title
+ {"/:slug/", true, nil, "/the-slug/"}, // Slug
+ {"/:slugorfilename/", true, nil, "/the-slug/"}, // Slug or filename
+ {"/:filename/", true, nil, "/test-page/"}, // Filename
+ {"/:06-:1-:2-:Monday", true, nil, "/12-4-6-Friday"}, // Dates with Go formatting
+ {"/:2006_01_02_15_04_05.000", true, nil, "/2012_04_06_03_01_59.000"}, // Complicated custom date format
+ {"/:sections/", true, nil, "/a/b/c/"}, // Sections
+ {"/:sections[last]/", true, nil, "/c/"}, // Sections
+ {"/:sections[0]/:sections[last]/", true, nil, "/a/c/"}, // Sections
+ {"/\\:filename", true, nil, "/:filename"}, // Escape sequence
+ {"/special\\::slug/", true, nil, "/special:the-slug/"},
+ // contentbasename. // Escape sequence
+ {"/:contentbasename/", true, nil, "/test-page/"},
+ // slug, contentbasename. // Content base name
+ {"/:slugorcontentbasename/", true, func(p *testPage) {
+ p.slug = ""
+ }, "/test-page/"},
+ {"/:slugorcontentbasename/", true, func(p *testPage) {
+ p.slug = "myslug"
+ }, "/myslug/"},
+ {"/:slugorcontentbasename/", true, func(p *testPage) {
+ p.slug = ""
+ p.title = "mytitle"
+ p.file = source.NewContentFileInfoFrom("/", "_index.md")
+ }, "/test-page/"},
// Failures
- {"/blog/:fred", false, ""},
- {"/:year//:title", false, ""},
- {"/:TITLE", false, ""}, // case is not normalized
- {"/:2017", false, ""}, // invalid date format
- {"/:2006-01-02", false, ""}, // valid date format but invalid attribute name
+ {"/blog/:fred", false, nil, ""},
+ {"/:year//:title", false, nil, ""},
+ {"/:TITLE", false, nil, ""}, // case is not normalized
+ {"/:2017", false, nil, ""}, // invalid date format
+ {"/:2006-01-02", false, nil, ""}, // valid date format but invalid attribute name
}
func urlize(uri string) string {
c := qt.New(t)
- page := newTestPageWithFile("/test-page/index.md")
- page.title = "Spf13 Vim 3.0 Release and new website"
- d, _ := time.Parse("2006-01-02 15:04:05", "2012-04-06 03:01:59")
- page.date = d
- page.section = "blue"
- page.slug = "The Slug"
- page.kind = "page"
+ newPage := func() *testPage {
+ page := newTestPageWithFile("/test-page/index.md")
+ page.title = "Spf13 Vim 3.0 Release and new website"
+ d, _ := time.Parse("2006-01-02 15:04:05", "2012-04-06 03:01:59")
+ page.date = d
+ page.section = "blue"
+ page.slug = "The Slug"
+ page.kind = "page"
+ // page.pathInfo
+ return page
+ }
- for _, item := range testdataPermalinks {
+ for i, item := range testdataPermalinks {
if !item.valid {
continue
}
+ page := newPage()
+ if item.withPage != nil {
+ item.withPage(page)
+ }
+
specNameCleaner := regexp.MustCompile(`[\:\/\[\]]`)
- name := specNameCleaner.ReplaceAllString(item.spec, "")
+ name := fmt.Sprintf("[%d] %s", i, specNameCleaner.ReplaceAllString(item.spec, "_"))
c.Run(name, func(c *qt.C) {
patterns := map[string]map[string]string{