mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-20 21:31:32 +02:00
@@ -330,7 +330,7 @@ var allDecoderSetups = map[string]decodeWeight{
|
||||
key: "cascade",
|
||||
decode: func(d decodeWeight, p decodeConfig) error {
|
||||
var err error
|
||||
p.c.Cascade, err = page.DecodeCascadeConfig(nil, p.p.Get(d.key))
|
||||
p.c.Cascade, err = page.DecodeCascadeConfig(nil, true, p.p.Get(d.key))
|
||||
return err
|
||||
},
|
||||
},
|
||||
|
@@ -356,7 +356,7 @@ func (m *pageMap) addPagesFromGoTmplFi(fi hugofs.FileMetaInfo, buildConfig *Buil
|
||||
Watching: s.Conf.Watching(),
|
||||
HandlePage: func(pt *pagesfromdata.PagesFromTemplate, pc *pagemeta.PageConfig) error {
|
||||
s := pt.Site.(*Site)
|
||||
if err := pc.Compile(pt.GoTmplFi.Meta().PathInfo.Base(), true, "", s.Log, s.conf.OutputFormats.Config, s.conf.MediaTypes.Config); err != nil {
|
||||
if err := pc.CompileForPagesFromDataPre(pt.GoTmplFi.Meta().PathInfo.Base(), m.s.Log, s.conf.MediaTypes.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@@ -1695,9 +1695,11 @@ func (sa *sitePagesAssembler) assembleTermsAndTranslations() error {
|
||||
pathInfo: pi,
|
||||
pageMetaParams: &pageMetaParams{
|
||||
pageConfig: &pagemeta.PageConfig{
|
||||
PageConfigEarly: pagemeta.PageConfigEarly{
|
||||
Kind: kinds.KindTerm,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
n, pi, err := sa.h.newPage(m)
|
||||
if err != nil {
|
||||
@@ -1956,9 +1958,11 @@ func (sa *sitePagesAssembler) addStandalonePages() error {
|
||||
pathInfo: s.Conf.PathParser().Parse(files.ComponentFolderContent, key+f.MediaType.FirstSuffix.FullSuffix),
|
||||
pageMetaParams: &pageMetaParams{
|
||||
pageConfig: &pagemeta.PageConfig{
|
||||
PageConfigEarly: pagemeta.PageConfigEarly{
|
||||
Kind: kind,
|
||||
},
|
||||
},
|
||||
},
|
||||
standaloneOutputFormat: f,
|
||||
}
|
||||
|
||||
@@ -2082,9 +2086,11 @@ func (sa *sitePagesAssembler) addMissingRootSections() error {
|
||||
pathInfo: p,
|
||||
pageMetaParams: &pageMetaParams{
|
||||
pageConfig: &pagemeta.PageConfig{
|
||||
PageConfigEarly: pagemeta.PageConfigEarly{
|
||||
Kind: kinds.KindHome,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
n, p, err := sa.h.newPage(m)
|
||||
if err != nil {
|
||||
@@ -2115,9 +2121,11 @@ func (sa *sitePagesAssembler) addMissingTaxonomies() error {
|
||||
pathInfo: sa.Conf.PathParser().Parse(files.ComponentFolderContent, key+"/_index.md"),
|
||||
pageMetaParams: &pageMetaParams{
|
||||
pageConfig: &pagemeta.PageConfig{
|
||||
PageConfigEarly: pagemeta.PageConfigEarly{
|
||||
Kind: kinds.KindTaxonomy,
|
||||
},
|
||||
},
|
||||
},
|
||||
singular: viewName.singular,
|
||||
}
|
||||
p, _, _ := sa.h.newPage(m)
|
||||
|
@@ -72,12 +72,7 @@ type pageMeta struct {
|
||||
// Prepare for a rebuild of the data passed in from front matter.
|
||||
func (m *pageMeta) setMetaPostPrepareRebuild() {
|
||||
params := xmaps.Clone(m.paramsOriginal)
|
||||
m.pageMetaParams.pageConfig = &pagemeta.PageConfig{
|
||||
Kind: m.pageConfig.Kind,
|
||||
Lang: m.pageConfig.Lang,
|
||||
Path: m.pageConfig.Path,
|
||||
Params: params,
|
||||
}
|
||||
m.pageMetaParams.pageConfig = pagemeta.ClonePageConfigForRebuild(m.pageMetaParams.pageConfig, params)
|
||||
}
|
||||
|
||||
type pageMetaParams struct {
|
||||
@@ -94,7 +89,11 @@ type pageMetaParams struct {
|
||||
|
||||
func (m *pageMetaParams) init(preserveOriginal bool) {
|
||||
if preserveOriginal {
|
||||
m.paramsOriginal = xmaps.Clone[maps.Params](m.pageConfig.Params)
|
||||
if m.pageConfig.IsFromContentAdapter {
|
||||
m.paramsOriginal = xmaps.Clone(m.pageConfig.ContentAdapterData)
|
||||
} else {
|
||||
m.paramsOriginal = xmaps.Clone(m.pageConfig.Params)
|
||||
}
|
||||
m.cascadeOriginal = m.pageConfig.CascadeCompiled.Clone()
|
||||
}
|
||||
}
|
||||
@@ -254,7 +253,7 @@ func (p *pageMeta) setMetaPre(pi *contentParseInfo, logger loggers.Logger, conf
|
||||
// Check for any cascade define on itself.
|
||||
if cv, found := frontmatter["cascade"]; found {
|
||||
var err error
|
||||
cascade, err := page.DecodeCascade(logger, cv)
|
||||
cascade, err := page.DecodeCascade(logger, true, cv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -341,18 +340,29 @@ func (ps *pageState) setMetaPost(cascade *maps.Ordered[page.PageMatcher, maps.Pa
|
||||
}
|
||||
|
||||
// Cascade is also applied to itself.
|
||||
var err error
|
||||
cascade.Range(func(k page.PageMatcher, v maps.Params) bool {
|
||||
if !k.Matches(ps) {
|
||||
return true
|
||||
}
|
||||
for kk, vv := range v {
|
||||
if ps.m.pageConfig.IsFromContentAdapter {
|
||||
if _, found := ps.m.pageConfig.ContentAdapterData[kk]; !found {
|
||||
ps.m.pageConfig.ContentAdapterData[kk] = vv
|
||||
}
|
||||
} else {
|
||||
if _, found := ps.m.pageConfig.Params[kk]; !found {
|
||||
ps.m.pageConfig.Params[kk] = vv
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ps.setMetaPostParams(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -398,6 +408,12 @@ func (p *pageState) setMetaPostParams() error {
|
||||
PathOrTitle: p.pathOrTitle(),
|
||||
}
|
||||
|
||||
if isContentAdapter {
|
||||
if err := pm.pageConfig.Compile(ext, p.s.Log, p.s.conf.OutputFormats.Config, p.s.conf.MediaTypes.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the date separately
|
||||
// TODO(bep) we need to "do more" in this area so this can be split up and
|
||||
// more easily tested without the Page, but the coupling is strong.
|
||||
@@ -656,7 +672,7 @@ params:
|
||||
return err
|
||||
}
|
||||
|
||||
if err := pcfg.Compile("", false, ext, p.s.Log, p.s.conf.OutputFormats.Config, p.s.conf.MediaTypes.Config); err != nil {
|
||||
if err := pcfg.Compile(ext, p.s.Log, p.s.conf.OutputFormats.Config, p.s.conf.MediaTypes.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@@ -91,17 +91,20 @@ func (p *pagesFromDataTemplateContext) AddPage(v any) (string, error) {
|
||||
|
||||
pd := pagemeta.DefaultPageConfig
|
||||
pd.IsFromContentAdapter = true
|
||||
pd.ContentAdapterData = m
|
||||
|
||||
if err := mapstructure.WeakDecode(m, &pd); err != nil {
|
||||
return "", fmt.Errorf("failed to decode page map: %w", err)
|
||||
// The rest will be handled after the cascade is calculated and applied.
|
||||
if err := mapstructure.WeakDecode(pd.ContentAdapterData, &pd.PageConfigEarly); err != nil {
|
||||
err = fmt.Errorf("failed to decode page map: %w", err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
p.p.buildState.NumPagesAdded++
|
||||
|
||||
if err := pd.Validate(true); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
p.p.buildState.NumPagesAdded++
|
||||
|
||||
return "", p.p.HandlePage(p.p, &pd)
|
||||
}
|
||||
|
||||
|
@@ -821,3 +821,97 @@ outputs:
|
||||
b.AssertFileExists("public/p4/index.html", true)
|
||||
b.AssertFileExists("public/p4/index.json", false) // currently returns true
|
||||
}
|
||||
|
||||
func TestContentAdapterOutputsIssue13692(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
disableKinds = ['page','home','sitemap','taxonomy','term']
|
||||
[[cascade]]
|
||||
outputs = ['html','json']
|
||||
[cascade.target]
|
||||
path = '{/s2,/s4}'
|
||||
-- layouts/section.html --
|
||||
html: {{ .Title }}
|
||||
-- layouts/section.json --
|
||||
json: {{ .Title }}
|
||||
-- content/s1/_index.md --
|
||||
---
|
||||
title: s1
|
||||
---
|
||||
-- content/s2/_index.md --
|
||||
---
|
||||
title: s2
|
||||
---
|
||||
-- content/_content.gotmpl --
|
||||
{{ $page := dict "path" "s3" "title" "s3" "kind" "section" }}
|
||||
{{ $.AddPage $page }}
|
||||
|
||||
{{ $page := dict "path" "s4" "title" "s4" "kind" "section" }}
|
||||
{{ $.AddPage $page }}
|
||||
|
||||
{{ $page := dict "path" "s5" "title" "s5" "kind" "section" "outputs" (slice "html") }}
|
||||
{{ $.AddPage $page }}
|
||||
`
|
||||
|
||||
b := hugolib.Test(t, files)
|
||||
|
||||
b.AssertFileExists("public/s1/index.html", true)
|
||||
b.AssertFileExists("public/s1/index.json", false)
|
||||
b.AssertFileExists("public/s1/index.xml", true)
|
||||
|
||||
b.AssertFileExists("public/s2/index.html", true)
|
||||
b.AssertFileExists("public/s2/index.json", true)
|
||||
b.AssertFileExists("public/s2/index.xml", false)
|
||||
|
||||
b.AssertFileExists("public/s3/index.html", true)
|
||||
b.AssertFileExists("public/s3/index.json", false)
|
||||
b.AssertFileExists("public/s3/index.xml", true)
|
||||
|
||||
b.AssertFileExists("public/s4/index.html", true)
|
||||
b.AssertFileExists("public/s4/index.json", true)
|
||||
b.AssertFileExists("public/s4/index.xml", false)
|
||||
|
||||
b.AssertFileExists("public/s5/index.html", true)
|
||||
b.AssertFileExists("public/s5/index.json", false)
|
||||
b.AssertFileExists("public/s5/index.xml", false)
|
||||
}
|
||||
|
||||
func TestContentAdapterCascadeBasic(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
disableLiveReload = true
|
||||
-- content/_index.md --
|
||||
---
|
||||
cascade:
|
||||
- title: foo
|
||||
target:
|
||||
path: "**"
|
||||
---
|
||||
-- layouts/all.html --
|
||||
Title: {{ .Title }}|Content: {{ .Content }}|
|
||||
-- content/_content.gotmpl --
|
||||
{{ $content := dict
|
||||
"mediaType" "text/markdown"
|
||||
"value" "The _Hunchback of Notre Dame_ was written by Victor Hugo."
|
||||
}}
|
||||
|
||||
{{ $page := dict "path" "s1" "kind" "page" }}
|
||||
{{ $.AddPage $page }}
|
||||
{{ $page := dict "path" "s2" "kind" "page" "title" "bar" "content" $content }}
|
||||
{{ $.AddPage $page }}
|
||||
|
||||
`
|
||||
|
||||
b := hugolib.TestRunning(t, files)
|
||||
|
||||
b.AssertFileContent("public/s1/index.html", "Title: foo|")
|
||||
b.AssertFileContent("public/s2/index.html", "Title: bar|", "Content: <p>The <em>Hunchback of Notre Dame</em> was written by Victor Hugo.</p>")
|
||||
|
||||
b.EditFileReplaceAll("content/_index.md", "foo", "baz").Build()
|
||||
|
||||
b.AssertFileContent("public/s1/index.html", "Title: baz|")
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ package page
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
@@ -24,7 +25,6 @@ import (
|
||||
"github.com/gohugoio/hugo/hugofs/glob"
|
||||
"github.com/gohugoio/hugo/resources/kinds"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// A PageMatcher can be used to match a Page with Glob patterns.
|
||||
@@ -105,7 +105,7 @@ func CheckCascadePattern(logger loggers.Logger, m PageMatcher) {
|
||||
}
|
||||
}
|
||||
|
||||
func DecodeCascadeConfig(logger loggers.Logger, in any) (*config.ConfigNamespace[[]PageMatcherParamsConfig, *maps.Ordered[PageMatcher, maps.Params]], error) {
|
||||
func DecodeCascadeConfig(logger loggers.Logger, handleLegacyFormat bool, in any) (*config.ConfigNamespace[[]PageMatcherParamsConfig, *maps.Ordered[PageMatcher, maps.Params]], error) {
|
||||
buildConfig := func(in any) (*maps.Ordered[PageMatcher, maps.Params], any, error) {
|
||||
cascade := maps.NewOrdered[PageMatcher, maps.Params]()
|
||||
if in == nil {
|
||||
@@ -120,7 +120,15 @@ func DecodeCascadeConfig(logger loggers.Logger, in any) (*config.ConfigNamespace
|
||||
|
||||
for _, m := range ms {
|
||||
m = maps.CleanConfigStringMap(m)
|
||||
c, err := mapToPageMatcherParamsConfig(m)
|
||||
var (
|
||||
c PageMatcherParamsConfig
|
||||
err error
|
||||
)
|
||||
if handleLegacyFormat {
|
||||
c, err = mapToPageMatcherParamsConfigLegacy(m)
|
||||
} else {
|
||||
c, err = mapToPageMatcherParamsConfig(m)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -155,8 +163,8 @@ func DecodeCascadeConfig(logger loggers.Logger, in any) (*config.ConfigNamespace
|
||||
}
|
||||
|
||||
// DecodeCascade decodes in which could be either a map or a slice of maps.
|
||||
func DecodeCascade(logger loggers.Logger, in any) (*maps.Ordered[PageMatcher, maps.Params], error) {
|
||||
conf, err := DecodeCascadeConfig(logger, in)
|
||||
func DecodeCascade(logger loggers.Logger, handleLegacyFormat bool, in any) (*maps.Ordered[PageMatcher, maps.Params], error) {
|
||||
conf, err := DecodeCascadeConfig(logger, handleLegacyFormat, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -164,6 +172,26 @@ func DecodeCascade(logger loggers.Logger, in any) (*maps.Ordered[PageMatcher, ma
|
||||
}
|
||||
|
||||
func mapToPageMatcherParamsConfig(m map[string]any) (PageMatcherParamsConfig, error) {
|
||||
var pcfg PageMatcherParamsConfig
|
||||
for k, v := range m {
|
||||
switch strings.ToLower(k) {
|
||||
case "_target", "target":
|
||||
var target PageMatcher
|
||||
if err := decodePageMatcher(v, &target); err != nil {
|
||||
return pcfg, err
|
||||
}
|
||||
pcfg.Target = target
|
||||
default:
|
||||
if pcfg.Params == nil {
|
||||
pcfg.Params = make(maps.Params)
|
||||
}
|
||||
pcfg.Params[k] = v
|
||||
}
|
||||
}
|
||||
return pcfg, pcfg.init()
|
||||
}
|
||||
|
||||
func mapToPageMatcherParamsConfigLegacy(m map[string]any) (PageMatcherParamsConfig, error) {
|
||||
var pcfg PageMatcherParamsConfig
|
||||
for k, v := range m {
|
||||
switch strings.ToLower(k) {
|
||||
@@ -190,7 +218,6 @@ func mapToPageMatcherParamsConfig(m map[string]any) (PageMatcherParamsConfig, er
|
||||
}
|
||||
pcfg.Target = target
|
||||
default:
|
||||
// Legacy config.
|
||||
if pcfg.Params == nil {
|
||||
pcfg.Params = make(maps.Params)
|
||||
}
|
||||
|
@@ -84,7 +84,7 @@ func TestPageMatcher(t *testing.T) {
|
||||
|
||||
c.Run("mapToPageMatcherParamsConfig", func(c *qt.C) {
|
||||
fn := func(m map[string]any) PageMatcherParamsConfig {
|
||||
v, err := mapToPageMatcherParamsConfig(m)
|
||||
v, err := mapToPageMatcherParamsConfigLegacy(m)
|
||||
c.Assert(err, qt.IsNil)
|
||||
return v
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func TestDecodeCascadeConfig(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
got, err := DecodeCascadeConfig(loggers.NewDefault(), in)
|
||||
got, err := DecodeCascadeConfig(loggers.NewDefault(), true, in)
|
||||
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(got, qt.IsNotNil)
|
||||
@@ -143,7 +143,7 @@ func TestDecodeCascadeConfig(t *testing.T) {
|
||||
{Params: maps.Params{"b": string("bv")}, Target: PageMatcher{Kind: "page"}},
|
||||
})
|
||||
|
||||
got, err = DecodeCascadeConfig(loggers.NewDefault(), nil)
|
||||
got, err = DecodeCascadeConfig(loggers.NewDefault(), true, nil)
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(got, qt.IsNotNil)
|
||||
}
|
||||
|
@@ -33,6 +33,7 @@ import (
|
||||
"github.com/gohugoio/hugo/resources/kinds"
|
||||
"github.com/gohugoio/hugo/resources/page"
|
||||
"github.com/gohugoio/hugo/resources/resource"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
|
||||
@@ -75,20 +76,29 @@ func (d Dates) IsAllDatesZero() bool {
|
||||
return d.Date.IsZero() && d.Lastmod.IsZero() && d.PublishDate.IsZero() && d.ExpiryDate.IsZero()
|
||||
}
|
||||
|
||||
// Page config that needs to be set early. These cannot be modified by cascade.
|
||||
type PageConfigEarly struct {
|
||||
Kind string // The kind of page, e.g. "page", "section", "home" etc. This is usually derived from the content path.
|
||||
Path string // The canonical path to the page, e.g. /sect/mypage. Note: Leading slash, no trailing slash, no extensions or language identifiers.
|
||||
Lang string // The language code for this page. This is usually derived from the module mount or filename.
|
||||
Cascade []map[string]any
|
||||
|
||||
// Content holds the content for this page.
|
||||
Content Source
|
||||
}
|
||||
|
||||
// PageConfig configures a Page, typically from front matter.
|
||||
// Note that all the top level fields are reserved Hugo keywords.
|
||||
// Any custom configuration needs to be set in the Params map.
|
||||
type PageConfig struct {
|
||||
Dates Dates `json:"-"` // Dates holds the four core dates for this page.
|
||||
DatesStrings
|
||||
PageConfigEarly `mapstructure:",squash"`
|
||||
Title string // The title of the page.
|
||||
LinkTitle string // The link title of the page.
|
||||
Type string // The content type of the page.
|
||||
Layout string // The layout to use for to render this page.
|
||||
Weight int // The weight of the page, used in sorting if set to a non-zero value.
|
||||
Kind string // The kind of page, e.g. "page", "section", "home" etc. This is usually derived from the content path.
|
||||
Path string // The canonical path to the page, e.g. /sect/mypage. Note: Leading slash, no trailing slash, no extensions or language identifiers.
|
||||
Lang string // The language code for this page. This is usually derived from the module mount or filename.
|
||||
URL string // The URL to the rendered page, e.g. /sect/mypage.html.
|
||||
Slug string // The slug for this page.
|
||||
Description string // The description for this page.
|
||||
@@ -103,7 +113,6 @@ type PageConfig struct {
|
||||
|
||||
FrontMatterOnlyValues `mapstructure:"-" json:"-"`
|
||||
|
||||
Cascade []map[string]any
|
||||
Sitemap config.SitemapConfig
|
||||
Build BuildConfig
|
||||
Menus any // Can be a string, []string or map[string]any.
|
||||
@@ -111,8 +120,9 @@ type PageConfig struct {
|
||||
// User defined params.
|
||||
Params maps.Params
|
||||
|
||||
// Content holds the content for this page.
|
||||
Content Source
|
||||
// The raw data from the content adapter.
|
||||
// TODO(bep) clean up the ContentAdapterData vs Params.
|
||||
ContentAdapterData map[string]any `mapstructure:"-" json:"-"`
|
||||
|
||||
// Compiled values.
|
||||
CascadeCompiled *maps.Ordered[page.PageMatcher, maps.Params] `mapstructure:"-" json:"-"`
|
||||
@@ -121,6 +131,20 @@ type PageConfig struct {
|
||||
IsFromContentAdapter bool `mapstructure:"-" json:"-"`
|
||||
}
|
||||
|
||||
func ClonePageConfigForRebuild(p *PageConfig, params map[string]any) *PageConfig {
|
||||
pp := &PageConfig{
|
||||
PageConfigEarly: p.PageConfigEarly,
|
||||
IsFromContentAdapter: p.IsFromContentAdapter,
|
||||
}
|
||||
if pp.IsFromContentAdapter {
|
||||
pp.ContentAdapterData = params
|
||||
} else {
|
||||
pp.Params = params
|
||||
}
|
||||
|
||||
return pp
|
||||
}
|
||||
|
||||
var DefaultPageConfig = PageConfig{
|
||||
Build: DefaultBuildConfig,
|
||||
}
|
||||
@@ -151,8 +175,7 @@ func (p *PageConfig) Validate(pagesFromData bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Compile sets up the page configuration after all fields have been set.
|
||||
func (p *PageConfig) Compile(basePath string, pagesFromData bool, ext string, logger loggers.Logger, outputFormats output.Formats, mediaTypes media.Types) error {
|
||||
func (p *PageConfig) CompileForPagesFromDataPre(basePath string, logger loggers.Logger, mediaTypes media.Types) error {
|
||||
// In content adapters, we always get relative paths.
|
||||
if basePath != "" {
|
||||
p.Path = path.Join(basePath, p.Path)
|
||||
@@ -160,12 +183,32 @@ func (p *PageConfig) Compile(basePath string, pagesFromData bool, ext string, lo
|
||||
|
||||
if p.Params == nil {
|
||||
p.Params = make(maps.Params)
|
||||
} else if pagesFromData {
|
||||
p.Params = maps.PrepareParamsClone(p.Params)
|
||||
} else {
|
||||
maps.PrepareParams(p.Params)
|
||||
p.Params = maps.PrepareParamsClone(p.Params)
|
||||
}
|
||||
|
||||
if p.Kind == "" {
|
||||
p.Kind = kinds.KindPage
|
||||
}
|
||||
|
||||
if p.Cascade != nil {
|
||||
cascade, err := page.DecodeCascade(logger, false, p.Cascade)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode cascade: %w", err)
|
||||
}
|
||||
p.CascadeCompiled = cascade
|
||||
}
|
||||
|
||||
// Note that NormalizePathStringBasic will make sure that we don't preserve the unnormalized path.
|
||||
// We do that when we create pages from the file system; mostly for backward compatibility,
|
||||
// but also because people tend to use use the filename to name their resources (with spaces and all),
|
||||
// and this isn't relevant when creating resources from an API where it's easy to add textual meta data.
|
||||
p.Path = paths.NormalizePathStringBasic(p.Path)
|
||||
|
||||
return p.compilePrePost("", mediaTypes)
|
||||
}
|
||||
|
||||
func (p *PageConfig) compilePrePost(ext string, mediaTypes media.Types) error {
|
||||
if p.Content.Markup == "" && p.Content.MediaType == "" {
|
||||
if ext == "" {
|
||||
ext = "md"
|
||||
@@ -196,6 +239,29 @@ func (p *PageConfig) Compile(basePath string, pagesFromData bool, ext string, lo
|
||||
if p.Content.Markup == "" {
|
||||
p.Content.Markup = p.ContentMediaType.SubType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Compile sets up the page configuration after all fields have been set.
|
||||
func (p *PageConfig) Compile(ext string, logger loggers.Logger, outputFormats output.Formats, mediaTypes media.Types) error {
|
||||
if p.IsFromContentAdapter {
|
||||
if err := mapstructure.WeakDecode(p.ContentAdapterData, p); err != nil {
|
||||
err = fmt.Errorf("failed to decode page map: %w", err)
|
||||
return err
|
||||
}
|
||||
// Not needed anymore.
|
||||
p.ContentAdapterData = nil
|
||||
}
|
||||
|
||||
if p.Params == nil {
|
||||
p.Params = make(maps.Params)
|
||||
} else {
|
||||
maps.PrepareParams(p.Params)
|
||||
}
|
||||
|
||||
if err := p.compilePrePost(ext, mediaTypes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(p.Outputs) > 0 {
|
||||
outFormats, err := outputFormats.GetByNames(p.Outputs...)
|
||||
@@ -206,27 +272,6 @@ func (p *PageConfig) Compile(basePath string, pagesFromData bool, ext string, lo
|
||||
}
|
||||
}
|
||||
|
||||
if pagesFromData {
|
||||
if p.Kind == "" {
|
||||
p.Kind = kinds.KindPage
|
||||
}
|
||||
|
||||
// Note that NormalizePathStringBasic will make sure that we don't preserve the unnormalized path.
|
||||
// We do that when we create pages from the file system; mostly for backward compatibility,
|
||||
// but also because people tend to use use the filename to name their resources (with spaces and all),
|
||||
// and this isn't relevant when creating resources from an API where it's easy to add textual meta data.
|
||||
p.Path = paths.NormalizePathStringBasic(p.Path)
|
||||
|
||||
}
|
||||
|
||||
if p.Cascade != nil {
|
||||
cascade, err := page.DecodeCascade(logger, p.Cascade)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode cascade: %w", err)
|
||||
}
|
||||
p.CascadeCompiled = cascade
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -176,7 +176,7 @@ func TestContentMediaTypeFromMarkup(t *testing.T) {
|
||||
} {
|
||||
var pc pagemeta.PageConfig
|
||||
pc.Content.Markup = test.in
|
||||
c.Assert(pc.Compile("", true, "", logger, output.DefaultFormats, media.DefaultTypes), qt.IsNil)
|
||||
c.Assert(pc.Compile("", logger, output.DefaultFormats, media.DefaultTypes), qt.IsNil)
|
||||
c.Assert(pc.ContentMediaType.Type, qt.Equals, test.expected)
|
||||
}
|
||||
}
|
||||
|
@@ -460,6 +460,7 @@ title: p1 (de)
|
||||
}
|
||||
|
||||
func TestVimeoShortcode(t *testing.T) {
|
||||
t.Skip("Fix me: Upstream API changes")
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
|
Reference in New Issue
Block a user