summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands/hugo.go4
-rw-r--r--commands/import_jekyll.go2
-rw-r--r--commands/undraft.go2
-rw-r--r--commands/undraft_test.go2
-rw-r--r--hugolib/page.go22
-rw-r--r--hugolib/page_test.go47
-rw-r--r--parser/frontmatter.go12
-rw-r--r--parser/page.go7
8 files changed, 56 insertions, 42 deletions
diff --git a/commands/hugo.go b/commands/hugo.go
index 758106faf..c9f073483 100644
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -1231,9 +1231,7 @@ func (c *commandeer) isThemeVsHugoVersionMismatch() (mismatch bool, requiredMinV
return
}
- config := tomlMeta.(map[string]interface{})
-
- if minVersion, ok := config["min_version"]; ok {
+ if minVersion, ok := tomlMeta["min_version"]; ok {
return helpers.CompareVersion(minVersion) > 0, fmt.Sprint(minVersion)
}
diff --git a/commands/import_jekyll.go b/commands/import_jekyll.go
index 98094dbb7..327bf6095 100644
--- a/commands/import_jekyll.go
+++ b/commands/import_jekyll.go
@@ -255,7 +255,7 @@ func loadJekyllConfig(fs afero.Fs, jekyllRoot string) map[string]interface{} {
return nil
}
- return c.(map[string]interface{})
+ return c
}
func createConfigFromJekyll(fs afero.Fs, inpath string, kind string, jekyllConfig map[string]interface{}) (err error) {
diff --git a/commands/undraft.go b/commands/undraft.go
index fbd2d4c3a..53861f456 100644
--- a/commands/undraft.go
+++ b/commands/undraft.go
@@ -99,7 +99,7 @@ func undraftContent(p parser.Page) (bytes.Buffer, error) {
var isDraft, gotDate bool
var date string
L:
- for k, v := range meta.(map[string]interface{}) {
+ for k, v := range meta {
switch k {
case "draft":
if !v.(bool) {
diff --git a/commands/undraft_test.go b/commands/undraft_test.go
index 259e3479b..889f36567 100644
--- a/commands/undraft_test.go
+++ b/commands/undraft_test.go
@@ -69,7 +69,7 @@ func TestUndraftContent(t *testing.T) {
t.Errorf("[%d] unexpected error %q", i, err)
continue
}
- for k, v := range meta.(map[string]interface{}) {
+ for k, v := range meta {
if k == "draft" {
if v.(bool) {
t.Errorf("[%d] Expected %q to be \"false\", got \"true\"", i, k)
diff --git a/hugolib/page.go b/hugolib/page.go
index fe998219c..468353ebc 100644
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -1108,19 +1108,18 @@ func (p *Page) prepareForRender(cfg *BuildCfg) error {
var ErrHasDraftAndPublished = errors.New("both draft and published parameters were found in page's frontmatter")
-func (p *Page) update(f interface{}) error {
- if f == nil {
- return errors.New("no metadata found")
+func (p *Page) update(frontmatter map[string]interface{}) error {
+ if frontmatter == nil {
+ return errors.New("missing frontmatter data")
}
- m := f.(map[string]interface{})
// Needed for case insensitive fetching of params values
- helpers.ToLowerMap(m)
+ helpers.ToLowerMap(frontmatter)
var modified time.Time
var err error
var draft, published, isCJKLanguage *bool
- for k, v := range m {
+ for k, v := range frontmatter {
loki := strings.ToLower(k)
switch loki {
case "title":
@@ -1371,7 +1370,6 @@ func (p *Page) update(f interface{}) error {
p.params["iscjklanguage"] = p.isCJKLanguage
return nil
-
}
func (p *Page) GetParam(key string) interface{} {
@@ -1614,14 +1612,12 @@ func (p *Page) parse(reader io.Reader) error {
if err != nil {
return fmt.Errorf("failed to parse page metadata for %q: %s", p.File.Path(), err)
}
-
- if meta != nil {
- if err = p.update(meta); err != nil {
- return err
- }
+ if meta == nil {
+ // missing frontmatter equivalent to empty frontmatter
+ meta = map[string]interface{}{}
}
- return nil
+ return p.update(meta)
}
func (p *Page) RawContent() string {
diff --git a/hugolib/page_test.go b/hugolib/page_test.go
index cfaf13406..033051498 100644
--- a/hugolib/page_test.go
+++ b/hugolib/page_test.go
@@ -912,8 +912,8 @@ const (
L = "2017-09-03T22:22:22Z"
M = "2018-01-24T12:21:39Z"
E = "2025-12-31T23:59:59Z"
- o = "0001-01-01T00:00:00Z"
- x = ""
+ o = "0001-01-01T00:00:00Z" // zero value of type Time, default for some date fields
+ x = "" // nil date value, default for some date fields
p_D____ = `---
title: Simple
@@ -981,20 +981,41 @@ Page With Date, PublishDate and LastMod`
---
Page With empty front matter`
+
+ zero_FM = "Page With empty front matter"
)
func TestMetadataDates(t *testing.T) {
t.Parallel()
var tests = []struct {
- text string
- filename string
- fallback bool
- expDate string
- expPub string
- expLast string
- expMod string
- expExp string
- }{ // D P L M E
+ text string
+ filename string
+ modFallback bool
+ expDate string
+ expPub string
+ expLast string
+ expMod string
+ expExp string
+ }{
+ // The three columns on the left are the test case inputs:
+ // page content: The name indicates which dates are set in the front matter,
+ // (D)ate, (P)ublishDate, (L)astModified
+ // (M)odified, (E)xpiryDate. So, for example,
+ // p__PL__ is content with PublishDate and LastModified
+ // specified in the front matter.
+ // file path: For when we start deriving metadata from it
+ // modFallback: Whether or not useModTimeAsFallback is enabled.
+ //
+ // The single character columns on the right are the expected outputs
+ // for each metadata date given by the column heading.
+ // Since each date type (D/P/L/M/E) in the input is always set
+ // to the same value (the constants referenced in these columns), it
+ // is easy to visualize and test which input date gets copied to which
+ // output date fields. "s" signifies the file's filesystem time stamp,
+ // "x" signifies a nil value, and "o" the "zero date".
+ //
+ // ------- inputs --------|--- outputs ---|
+ //content filename modfb? D P L M E
{p_D____, "test.md", false, D, D, D, x, x}, // date copied across
{p_D____, "testy.md", true, D, D, D, x, x},
{p__P___, "test.md", false, P, P, P, x, x}, // pubdate copied across
@@ -1010,12 +1031,14 @@ func TestMetadataDates(t *testing.T) {
{p_DPLME, "testy.md", true, D, P, L, M, E}, // all dates
{emptyFM, "test.md", false, o, o, o, x, x}, // 3 year-one dates, 2 empty dates
+ {zero_FM, "test.md", false, o, o, o, x, x},
{emptyFM, "testy.md", true, s, o, s, x, x}, // 2 filesys, 1 year-one, 2 empty
+ {zero_FM, "testy.md", true, s, o, s, x, x}, // Issue #4320
}
for i, test := range tests {
s := newTestSite(t)
- s.Cfg.Set("useModTimeAsFallback", test.fallback)
+ s.Cfg.Set("useModTimeAsFallback", test.modFallback)
fs := hugofs.NewMem(s.Cfg)
writeToFs(t, fs.Source, test.filename, test.text)
diff --git a/parser/frontmatter.go b/parser/frontmatter.go
index ab56b14d1..7560a734a 100644
--- a/parser/frontmatter.go
+++ b/parser/frontmatter.go
@@ -31,7 +31,7 @@ import (
// FrontmatterType represents a type of frontmatter.
type FrontmatterType struct {
// Parse decodes content into a Go interface.
- Parse func([]byte) (interface{}, error)
+ Parse func([]byte) (map[string]interface{}, error)
markstart, markend []byte // starting and ending delimiters
includeMark bool // include start and end mark in output
@@ -168,7 +168,7 @@ func DetectFrontMatter(mark rune) (f *FrontmatterType) {
// HandleTOMLMetaData unmarshals TOML-encoded datum and returns a Go interface
// representing the encoded data structure.
-func HandleTOMLMetaData(datum []byte) (interface{}, error) {
+func HandleTOMLMetaData(datum []byte) (map[string]interface{}, error) {
m := map[string]interface{}{}
datum = removeTOMLIdentifier(datum)
@@ -198,7 +198,7 @@ func removeTOMLIdentifier(datum []byte) []byte {
// HandleYAMLMetaData unmarshals YAML-encoded datum and returns a Go interface
// representing the encoded data structure.
-func HandleYAMLMetaData(datum []byte) (interface{}, error) {
+func HandleYAMLMetaData(datum []byte) (map[string]interface{}, error) {
m := map[string]interface{}{}
err := yaml.Unmarshal(datum, &m)
return m, err
@@ -206,7 +206,7 @@ func HandleYAMLMetaData(datum []byte) (interface{}, error) {
// HandleJSONMetaData unmarshals JSON-encoded datum and returns a Go interface
// representing the encoded data structure.
-func HandleJSONMetaData(datum []byte) (interface{}, error) {
+func HandleJSONMetaData(datum []byte) (map[string]interface{}, error) {
if datum == nil {
// Package json returns on error on nil input.
// Return an empty map to be consistent with our other supported
@@ -214,13 +214,13 @@ func HandleJSONMetaData(datum []byte) (interface{}, error) {
return make(map[string]interface{}), nil
}
- var f interface{}
+ var f map[string]interface{}
err := json.Unmarshal(datum, &f)
return f, err
}
// HandleOrgMetaData unmarshals org-mode encoded datum and returns a Go
// interface representing the encoded data structure.
-func HandleOrgMetaData(datum []byte) (interface{}, error) {
+func HandleOrgMetaData(datum []byte) (map[string]interface{}, error) {
return goorgeous.OrgHeaders(datum)
}
diff --git a/parser/page.go b/parser/page.go
index 1537915f4..17378840d 100644
--- a/parser/page.go
+++ b/parser/page.go
@@ -74,7 +74,7 @@ type Page interface {
IsRenderable() bool
// Metadata returns the unmarshalled frontmatter data.
- Metadata() (interface{}, error)
+ Metadata() (map[string]interface{}, error)
}
// page implements the Page interface.
@@ -100,16 +100,13 @@ func (p *page) IsRenderable() bool {
}
// Metadata returns the unmarshalled frontmatter data.
-func (p *page) Metadata() (meta interface{}, err error) {
+func (p *page) Metadata() (meta map[string]interface{}, err error) {
frontmatter := p.FrontMatter()
if len(frontmatter) != 0 {
fm := DetectFrontMatter(rune(frontmatter[0]))
if fm != nil {
meta, err = fm.Parse(frontmatter)
- if err != nil {
- return
- }
}
}
return