Skip to content

Commit

Permalink
Fallback to filename dates if variable is missing in frontmatter
Browse files Browse the repository at this point in the history
Parses filenames for a given date format and parses it into the date variable. Applied using the useFilenameDateAsFallback configuration option which defaults to false for backwards compatibility. Useful for content migration (e.g. from Jekyll et. al.) where date values are provided in filenames and not in frontmatter. Additional config values filenameDateFallbackPattern and filenameDateFallbackFormat allow custom date formats.

Partially addresses functionality discussed in gohugoio#285

fix tests
  • Loading branch information
devjack authored and maxandersen committed Jul 31, 2017
1 parent 8fb594b commit 00ca9a6
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 3 deletions.
1 change: 1 addition & 0 deletions docs/content/content-management/front-matter.md
Expand Up @@ -196,3 +196,4 @@ It's possible to set some options for Markdown rendering in a content's front ma
[urls]: /content-management/urls/
[variables]: /variables/
[yaml]: http://yaml.org/spec/ "Specification for YAML, YAML Ain't Markup Language"

8 changes: 7 additions & 1 deletion docs/content/getting-started/configuration.md
Expand Up @@ -245,6 +245,10 @@ disablePathToLower = false
enableEmoji = false
# Show a placeholder instead of the default value or an empty string if a translation is missing
enableMissingTranslationPlaceholders = false
# Regex to use for dates in filenames. Only used with `useFilenameDateAsFallback`
filenameDateFallbackPattern = "(?P<year>\\d{4})\\-(?P<month>\\d{2})\\-(?P<day>\\d{2})"
# Time format for custom dates in filenames. Only used with `useFilenameDateAsFallback` and must match `filenameDateFallbackPattern`
filenameDateFallbackFormat = "2006-01-02"
footnoteAnchorPrefix = ""
footnoteReturnLinkContents = ""
# google analytics tracking id
Expand Down Expand Up @@ -298,6 +302,8 @@ theme = ""
title = ""
# if true, use /filename.html instead of /filename/
uglyURLs = false
#if true, use dates in filenames e.g. 2017-01-31-mypostname.md
useFilenameDateAsFallback = false
# verbose output
verbose = false
# verbose logging
Expand Down Expand Up @@ -392,4 +398,4 @@ Hugo v0.20 introduced the ability to render your content to multiple output form
[Output Formats]: /templates/output-formats/
[templates]: /templates/
[toml]: https://github.com/toml-lang/toml
[yaml]: http://yaml.org/spec/
[yaml]: http://yaml.org/spec/
4 changes: 3 additions & 1 deletion docs/content/variables/page.md
Expand Up @@ -36,7 +36,9 @@ See [`.Scratch`](/functions/scratch/) for page-scoped, writable variables.
: the data specific to this type of page.

`.Date`
: the date associated with the page; `.Date` pulls from the `date` field in a content's front matter. See also `.ExpiryDate`, `.PublishDate`, and `.Lastmod`.
: the date associated with the page; `.Date` pulls from the `date` field in a content's front matter.
If you're migrating content to Hugo, you may have content with dates in the filename. For example `2017-01-31-myblog.md`. You can optionally enable the `useFilenameDateAsFallback` configuration option. This will attempt to parse the datestamp in the filename and use it as a fallback to providing a date variable in the front matter.
See also `.ExpiryDate`, `.PublishDate`, and `.Lastmod`.

`.Description`
: the description for the page.
Expand Down
3 changes: 3 additions & 0 deletions hugolib/config.go
Expand Up @@ -127,6 +127,9 @@ func loadDefaultSettingsFor(v *viper.Viper) {
v.SetDefault("enableEmoji", false)
v.SetDefault("pygmentsCodeFencesGuessSyntax", false)
v.SetDefault("useModTimeAsFallback", false)
v.SetDefault("useFilenameDateAsFallback", false)
v.SetDefault("filenameDateFallbackPattern", "(?P<year>\\d{4})\\-(?P<month>\\d{2})\\-(?P<day>\\d{2})")
v.SetDefault("filenameDateFallbackFormat", "2006-01-02")
v.SetDefault("defaultContentLanguage", "en")
v.SetDefault("defaultContentLanguageInSubdir", false)
v.SetDefault("enableMissingTranslationPlaceholders", false)
Expand Down
8 changes: 8 additions & 0 deletions hugolib/page.go
Expand Up @@ -1075,6 +1075,14 @@ func (p *Page) update(f interface{}) error {
p.Date = fi.ModTime()
p.Params["date"] = p.Date
}
} else if p.Date.IsZero() && p.s.Cfg.GetBool("useFilenameDateAsFallback") {
dateExp := regexp.MustCompile(p.s.Cfg.GetString("filenameDateFallbackPattern"))
dateString := dateExp.FindString(p.File.Path())
filenameDate, err := time.Parse(p.s.Cfg.GetString("filenameDateFallbackFormat"), dateString)
if err == nil {
p.Date = filenameDate
p.Params["date"] = p.Date
}
}

if p.Lastmod.IsZero() {
Expand Down
17 changes: 17 additions & 0 deletions hugolib/page_test.go
Expand Up @@ -81,6 +81,7 @@ Content of the file goes Here
`

simplePageRFC3339Date = "---\ntitle: RFC3339 Date\ndate: \"2013-05-17T16:59:30Z\"\n---\nrfc3339 content"
simplePageNoDate = "---\ntitle: Path Date\n---\n Date param from url"
simplePageJSONMultiple = `
{
"title": "foobar",
Expand Down Expand Up @@ -856,6 +857,22 @@ func TestPageWithDate(t *testing.T) {
checkPageDate(t, p, d)
}

func TestPageWithDateInFilename(t *testing.T) {
t.Parallel()
cfg, fs := newTestCfg()

writeSource(t, fs, filepath.Join("content", "2017-01-31-simple.md"), simplePageNoDate)

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, "2017-01-31")

checkPageDate(t, p, d)
}

func TestWordCountWithAllCJKRunesWithoutHasCJKLanguage(t *testing.T) {
t.Parallel()
assertFunc := func(t *testing.T, ext string, pages Pages) {
Expand Down

0 comments on commit 00ca9a6

Please sign in to comment.