aboutsummaryrefslogtreecommitdiffhomepage
path: root/hugolib/page.go
diff options
context:
space:
mode:
Diffstat (limited to 'hugolib/page.go')
-rw-r--r--hugolib/page.go166
1 files changed, 109 insertions, 57 deletions
diff --git a/hugolib/page.go b/hugolib/page.go
index 1e0d1ac83..e7dce9cf7 100644
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -111,6 +111,10 @@ type Page struct {
// provided by the Resource object.
Resources resource.Resources
+ // This is the raw front matter metadata that is going to be assigned to
+ // the Resources above.
+ resourcesMetadata []map[string]interface{}
+
// translations will contain references to this page in other language
// if available.
translations Pages
@@ -120,7 +124,7 @@ type Page struct {
translationKey string
// Params contains configuration defined in the params section of page frontmatter.
- Params map[string]interface{}
+ params map[string]interface{}
// Content sections
Content template.HTML
@@ -214,7 +218,7 @@ type Page struct {
Site *SiteInfo `json:"-"`
- Title string
+ title string
Description string
Keywords []string
Data map[string]interface{}
@@ -468,7 +472,7 @@ func (p *Page) Param(key interface{}) (interface{}, error) {
func (p *Page) traverseDirect(key string) (interface{}, error) {
keyStr := strings.ToLower(key)
- if val, ok := p.Params[keyStr]; ok {
+ if val, ok := p.params[keyStr]; ok {
return val, nil
}
@@ -476,7 +480,7 @@ func (p *Page) traverseDirect(key string) (interface{}, error) {
}
func (p *Page) traverseNested(keySegments []string) (interface{}, error) {
- result := traverse(keySegments, p.Params)
+ result := traverse(keySegments, p.params)
if result != nil {
return result, nil
}
@@ -519,7 +523,7 @@ func (p *Page) Author() Author {
}
func (p *Page) Authors() AuthorList {
- authorKeys, ok := p.Params["authors"]
+ authorKeys, ok := p.params["authors"]
if !ok {
return AuthorList{}
}
@@ -757,7 +761,7 @@ func (s *Site) newPageFromFile(fi *fileInfo) *Page {
contentType: "",
Source: Source{File: fi},
Keywords: []string{}, Sitemap: Sitemap{Priority: -1},
- Params: make(map[string]interface{}),
+ params: make(map[string]interface{}),
translations: make(Pages, 0),
sections: sectionsFromDir(fi.Dir()),
Site: &s.Info,
@@ -927,7 +931,7 @@ func (p *Page) LinkTitle() string {
if len(p.linkTitle) > 0 {
return p.linkTitle
}
- return p.Title
+ return p.title
}
func (p *Page) shouldBuild() bool {
@@ -988,6 +992,22 @@ func (p *Page) RelPermalink() string {
return p.relPermalink
}
+// See resource.Resource
+func (p *Page) Name() string {
+ if p.File != nil {
+ return p.File.BaseFileName()
+ }
+ return p.title
+}
+
+func (p *Page) Title() string {
+ return p.title
+}
+
+func (p *Page) Params() map[string]interface{} {
+ return p.params
+}
+
func (p *Page) subResourceTargetPathFactory(base string) string {
return path.Join(p.relTargetPathBase, base)
}
@@ -1094,39 +1114,39 @@ func (p *Page) update(f interface{}) error {
loki := strings.ToLower(k)
switch loki {
case "title":
- p.Title = cast.ToString(v)
- p.Params[loki] = p.Title
+ p.title = cast.ToString(v)
+ p.params[loki] = p.title
case "linktitle":
p.linkTitle = cast.ToString(v)
- p.Params[loki] = p.linkTitle
+ p.params[loki] = p.linkTitle
case "description":
p.Description = cast.ToString(v)
- p.Params[loki] = p.Description
+ p.params[loki] = p.Description
case "slug":
p.Slug = cast.ToString(v)
- p.Params[loki] = p.Slug
+ p.params[loki] = p.Slug
case "url":
if url := cast.ToString(v); strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
return fmt.Errorf("Only relative URLs are supported, %v provided", url)
}
p.URLPath.URL = cast.ToString(v)
p.URLPath.frontMatterURL = p.URLPath.URL
- p.Params[loki] = p.URLPath.URL
+ p.params[loki] = p.URLPath.URL
case "type":
p.contentType = cast.ToString(v)
- p.Params[loki] = p.contentType
+ p.params[loki] = p.contentType
case "extension", "ext":
p.extension = cast.ToString(v)
- p.Params[loki] = p.extension
+ p.params[loki] = p.extension
case "keywords":
p.Keywords = cast.ToStringSlice(v)
- p.Params[loki] = p.Keywords
+ p.params[loki] = p.Keywords
case "date":
p.Date, err = cast.ToTimeE(v)
if err != nil {
p.s.Log.ERROR.Printf("Failed to parse date '%v' in page %s", v, p.File.Path())
}
- p.Params[loki] = p.Date
+ p.params[loki] = p.Date
case "lastmod":
p.Lastmod, err = cast.ToTimeE(v)
if err != nil {
@@ -1135,10 +1155,10 @@ func (p *Page) update(f interface{}) error {
case "modified":
vv, err := cast.ToTimeE(v)
if err == nil {
- p.Params[loki] = vv
+ p.params[loki] = vv
modified = vv
} else {
- p.Params[loki] = cast.ToString(v)
+ p.params[loki] = cast.ToString(v)
}
case "outputs":
o := cast.ToStringSlice(v)
@@ -1150,17 +1170,16 @@ func (p *Page) update(f interface{}) error {
p.s.Log.ERROR.Printf("Failed to resolve output formats: %s", err)
} else {
p.outputFormats = outFormats
- p.Params[loki] = outFormats
+ p.params[loki] = outFormats
}
}
- //p.Params[loki] = p.Keywords
case "publishdate", "pubdate":
p.PublishDate, err = cast.ToTimeE(v)
if err != nil {
p.s.Log.ERROR.Printf("Failed to parse publishdate '%v' in page %s", v, p.File.Path())
}
- p.Params[loki] = p.PublishDate
+ p.params[loki] = p.PublishDate
case "expirydate", "unpublishdate":
p.ExpiryDate, err = cast.ToTimeE(v)
if err != nil {
@@ -1178,20 +1197,20 @@ func (p *Page) update(f interface{}) error {
vv, err := cast.ToTimeE(v)
if err == nil {
p.PublishDate = vv
- p.Params[loki] = p.PublishDate
+ p.params[loki] = p.PublishDate
} else {
- p.Params[loki] = cast.ToString(v)
+ p.params[loki] = cast.ToString(v)
}
}
case "layout":
p.Layout = cast.ToString(v)
- p.Params[loki] = p.Layout
+ p.params[loki] = p.Layout
case "markup":
p.Markup = cast.ToString(v)
- p.Params[loki] = p.Markup
+ p.params[loki] = p.Markup
case "weight":
p.Weight = cast.ToInt(v)
- p.Params[loki] = p.Weight
+ p.params[loki] = p.Weight
case "aliases":
p.Aliases = cast.ToStringSlice(v)
for _, alias := range p.Aliases {
@@ -1199,56 +1218,89 @@ func (p *Page) update(f interface{}) error {
return fmt.Errorf("Only relative aliases are supported, %v provided", alias)
}
}
- p.Params[loki] = p.Aliases
+ p.params[loki] = p.Aliases
case "status":
p.Status = cast.ToString(v)
- p.Params[loki] = p.Status
+ p.params[loki] = p.Status
case "sitemap":
p.Sitemap = parseSitemap(cast.ToStringMap(v))
- p.Params[loki] = p.Sitemap
+ p.params[loki] = p.Sitemap
case "iscjklanguage":
isCJKLanguage = new(bool)
*isCJKLanguage = cast.ToBool(v)
case "translationkey":
p.translationKey = cast.ToString(v)
- p.Params[loki] = p.translationKey
+ p.params[loki] = p.translationKey
+ case "resources":
+ var resources []map[string]interface{}
+ handled := true
+
+ switch vv := v.(type) {
+ case []map[interface{}]interface{}:
+ for _, vvv := range vv {
+ resources = append(resources, cast.ToStringMap(vvv))
+ }
+ case []map[string]interface{}:
+ for _, vvv := range vv {
+ resources = append(resources, vvv)
+ }
+ case []interface{}:
+ for _, vvv := range vv {
+ switch vvvv := vvv.(type) {
+ case map[interface{}]interface{}:
+ resources = append(resources, cast.ToStringMap(vvvv))
+ case map[string]interface{}:
+ resources = append(resources, vvvv)
+ }
+ }
+ default:
+ handled = false
+ }
+
+ if handled {
+ p.params[loki] = resources
+ p.resourcesMetadata = resources
+ break
+ }
+ fallthrough
+
default:
// If not one of the explicit values, store in Params
switch vv := v.(type) {
case bool:
- p.Params[loki] = vv
+ p.params[loki] = vv
case string:
- p.Params[loki] = vv
+ p.params[loki] = vv
case int64, int32, int16, int8, int:
- p.Params[loki] = vv
+ p.params[loki] = vv
case float64, float32:
- p.Params[loki] = vv
+ p.params[loki] = vv
case time.Time:
- p.Params[loki] = vv
+ p.params[loki] = vv
default: // handle array of strings as well
switch vvv := vv.(type) {
case []interface{}:
if len(vvv) > 0 {
switch vvv[0].(type) {
case map[interface{}]interface{}: // Proper parsing structured array from YAML based FrontMatter
- p.Params[loki] = vvv
+ p.params[loki] = vvv
case map[string]interface{}: // Proper parsing structured array from JSON based FrontMatter
- p.Params[loki] = vvv
+ p.params[loki] = vvv
case []interface{}:
- p.Params[loki] = vvv
+ p.params[loki] = vvv
default:
a := make([]string, len(vvv))
for i, u := range vvv {
a[i] = cast.ToString(u)
}
- p.Params[loki] = a
+ p.params[loki] = a
}
} else {
- p.Params[loki] = []string{}
+ p.params[loki] = []string{}
}
default:
- p.Params[loki] = vv
+ p.params[loki] = vv
}
}
}
@@ -1263,7 +1315,7 @@ func (p *Page) update(f interface{}) error {
} else if published != nil {
p.Draft = !*published
}
- p.Params["draft"] = p.Draft
+ p.params["draft"] = p.Draft
if p.Date.IsZero() {
p.Date = p.PublishDate
@@ -1277,7 +1329,7 @@ func (p *Page) update(f interface{}) error {
fi, err := p.s.Fs.Source.Stat(filepath.Join(p.s.PathSpec.AbsPathify(p.s.Cfg.GetString("contentDir")), p.File.Path()))
if err == nil {
p.Date = fi.ModTime()
- p.Params["date"] = p.Date
+ p.params["date"] = p.Date
}
}
@@ -1289,9 +1341,9 @@ func (p *Page) update(f interface{}) error {
}
}
- p.Params["lastmod"] = p.Lastmod
- p.Params["publishdate"] = p.PublishDate
- p.Params["expirydate"] = p.ExpiryDate
+ p.params["lastmod"] = p.Lastmod
+ p.params["publishdate"] = p.PublishDate
+ p.params["expirydate"] = p.ExpiryDate
if isCJKLanguage != nil {
p.isCJKLanguage = *isCJKLanguage
@@ -1302,7 +1354,7 @@ func (p *Page) update(f interface{}) error {
p.isCJKLanguage = false
}
}
- p.Params["iscjklanguage"] = p.isCJKLanguage
+ p.params["iscjklanguage"] = p.isCJKLanguage
return nil
@@ -1317,7 +1369,7 @@ func (p *Page) getParamToLower(key string) interface{} {
}
func (p *Page) getParam(key string, stringToLower bool) interface{} {
- v := p.Params[strings.ToLower(key)]
+ v := p.params[strings.ToLower(key)]
if v == nil {
return nil
@@ -1390,7 +1442,7 @@ func (p *Page) HasMenuCurrent(menuID string, me *MenuEntry) bool {
// The following logic is kept from back when Hugo had both Page and Node types.
// TODO(bep) consolidate / clean
- nme := MenuEntry{Page: p, Name: p.Title, URL: p.URL()}
+ nme := MenuEntry{Page: p, Name: p.title, URL: p.URL()}
for _, child := range me.Children {
if nme.IsSameResource(child) {
@@ -1421,7 +1473,7 @@ func (p *Page) IsMenuCurrent(menuID string, inme *MenuEntry) bool {
// The following logic is kept from back when Hugo had both Page and Node types.
// TODO(bep) consolidate / clean
- me := MenuEntry{Page: p, Name: p.Title, URL: p.URL()}
+ me := MenuEntry{Page: p, Name: p.title, URL: p.URL()}
if !me.IsSameResource(inme) {
return false
@@ -1465,7 +1517,7 @@ func (p *Page) Menus() PageMenus {
p.pageMenusInit.Do(func() {
p.pageMenus = PageMenus{}
- if ms, ok := p.Params["menu"]; ok {
+ if ms, ok := p.params["menu"]; ok {
link := p.RelPermalink()
me := MenuEntry{Page: p, Name: p.LinkTitle(), Weight: p.Weight, URL: link}
@@ -1494,16 +1546,16 @@ func (p *Page) Menus() PageMenus {
menus, err := cast.ToStringMapE(ms)
if err != nil {
- p.s.Log.ERROR.Printf("unable to process menus for %q\n", p.Title)
+ p.s.Log.ERROR.Printf("unable to process menus for %q\n", p.title)
}
for name, menu := range menus {
menuEntry := MenuEntry{Page: p, Name: p.LinkTitle(), URL: link, Weight: p.Weight, Menu: name}
if menu != nil {
- p.s.Log.DEBUG.Printf("found menu: %q, in %q\n", name, p.Title)
+ p.s.Log.DEBUG.Printf("found menu: %q, in %q\n", name, p.title)
ime, err := cast.ToStringMapE(menu)
if err != nil {
- p.s.Log.ERROR.Printf("unable to process menus for %q: %s", p.Title, err)
+ p.s.Log.ERROR.Printf("unable to process menus for %q: %s", p.title, err)
}
menuEntry.marshallMap(ime)
@@ -1805,7 +1857,7 @@ func (p *Page) RelRef(refs ...string) (string, error) {
}
func (p *Page) String() string {
- return fmt.Sprintf("Page(%q)", p.Title)
+ return fmt.Sprintf("Page(%q)", p.title)
}
type URLPath struct {
@@ -2003,5 +2055,5 @@ func (p *Page) pathOrTitle() string {
if p.Path() != "" {
return p.Path()
}
- return p.Title
+ return p.title
}