From af20b02dbc29e2a5c9c4d6a1b7d6f6769a8a3daf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Wed, 21 Feb 2018 11:09:08 +0100 Subject: [PATCH] hugolib: Extract date and slug from filename This commit adds a new config option which, when enabled and no date is set in front matter, will make Hugo try to parse the date from the content filename. Also, the filenames in these cases will make for very poor permalinks, so we will also use the remaining part as the page `slug` if that value is not set in front matter. This should make it easier to move content from Jekyll to Hugo. To enable, put this in your `config.toml`: ```toml [frontmatter] dateFallbacks = ["filename"] ``` Fixes #285 Closes #3310 Closes #3762 --- hugolib/page.go | 24 +++++++++++++++++++ hugolib/page_test.go | 56 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/hugolib/page.go b/hugolib/page.go index fd6278bb443..7582db8cf92 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -1373,6 +1373,30 @@ func (p *Page) update(frontmatter map[string]interface{}) error { return nil } +// A Zero date is a signal that the name can not be parsed. +// This follows the format as outlined in Jekyll, https://jekyllrb.com/docs/posts/: +// "Where YEAR is a four-digit number, MONTH and DAY are both two-digit numbers" +func dateAndSlugFromBaseFilename(name string) (time.Time, string) { + withoutExt, _ := helpers.FileAndExt(name) + + if len(withoutExt) < 10 { + // This can not be a date. + return time.Time{}, "" + } + + // Note: Hugo currently have no custom timezone support. + // We will have to revisit this when that is in place. + d, err := time.Parse("2006-01-02", withoutExt[:10]) + if err != nil { + return time.Time{}, "" + } + + // Be a little lenient with the format here. + slug := strings.Trim(withoutExt[10:], " -_") + + return d, slug +} + func (p *Page) GetParam(key string) interface{} { return p.getParam(key, false) } diff --git a/hugolib/page_test.go b/hugolib/page_test.go index 814556c6c59..0a15b901801 100644 --- a/hugolib/page_test.go +++ b/hugolib/page_test.go @@ -985,6 +985,25 @@ Page With empty front matter` zero_FM = "Page With empty front matter" ) +func TestPageWithFilenameDateAsFallback(t *testing.T) { + t.Parallel() + cfg, fs := newTestCfg() + + var tests = []struct { + }{} + + writeSource(t, fs, filepath.Join("content", "simple.md"), simplePageRFC3339Date) + + s := buildSingleSite(t, deps.DepsCfg{Fs: fs, Cfg: cfg}, BuildCfg{SkipRender: true}) + + require.Len(t, s.RegularPages, 1) + + p := s.RegularPages[0] + d, _ := time.Parse(time.RFC3339, "2013-05-17T16:59:30Z") + + checkPageDate(t, p, d) +} + func TestMetadataDates(t *testing.T) { t.Parallel() var tests = []struct { @@ -1873,6 +1892,43 @@ tags: } } +func TestDateAndSlugFromBaseFilename(t *testing.T) { + t.Parallel() + + assert := require.New(t) + + tests := []struct { + name string + date string + slug string + }{ + {"page.md", "0001-01-01", ""}, + {"2012-09-12-page.md", "2012-09-12", "page"}, + {"2018-02-28-page.md", "2018-02-28", "page"}, + {"2018-02-28_page.md", "2018-02-28", "page"}, + {"2018-02-28 page.md", "2018-02-28", "page"}, + {"2018-02-28page.md", "2018-02-28", "page"}, + {"2018-02-28-.md", "2018-02-28", ""}, + {"2018-02-28-.md", "2018-02-28", ""}, + {"2018-02-28.md", "2018-02-28", ""}, + {"2018-02-28-page", "2018-02-28", "page"}, + {"2012-9-12-page.md", "0001-01-01", ""}, + {"asdfasdf.md", "0001-01-01", ""}, + } + + for i, test := range tests { + expectedDate, err := time.Parse("2006-01-02", test.date) + assert.NoError(err) + + errMsg := fmt.Sprintf("Test %d", i) + gotDate, gotSlug := dateAndSlugFromBaseFilename(test.name) + + assert.Equal(expectedDate, gotDate, errMsg) + assert.Equal(test.slug, gotSlug, errMsg) + + } +} + func BenchmarkParsePage(b *testing.B) { s := newTestSite(b) f, _ := os.Open("testdata/redis.cn.md")