Skip to content

Commit

Permalink
hugolib: Extract date and slug from filename
Browse files Browse the repository at this point in the history
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
  • Loading branch information
bep committed Feb 21, 2018
1 parent 55bd46a commit af20b02
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
24 changes: 24 additions & 0 deletions hugolib/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
56 changes: 56 additions & 0 deletions hugolib/page_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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")
Expand Down

0 comments on commit af20b02

Please sign in to comment.