diff --git a/docs/content/en/content-management/build-options.md b/docs/content/en/content-management/build-options.md index b01568d39a2..93da7c4214d 100644 --- a/docs/content/en/content-management/build-options.md +++ b/docs/content/en/content-management/build-options.md @@ -20,13 +20,24 @@ They are stored in a reserved Front Matter object named `_build` with the follow ```yaml _build: - render: true + render: always list: always publishResources: true ``` #### render -If true, the page will be treated as a published page, holding its dedicated output files (`index.html`, etc...) and permalink. +If `always`, the page will be treated as a published page, holding its dedicated output files (`index.html`, etc...) and permalink. + +{{< new-in "0.76.0" >}} We extended this property from a boolean to an enum in Hugo 0.76.0. Valid values are: + +never +: The page will not be included in any page collection. + +always (default) +: The page will be rendered to disk and get a `RelPermalink` etc. + +link +: The page will be not be rendered to disk, but will get a `RelPermalink`. #### list diff --git a/hugolib/disableKinds_test.go b/hugolib/disableKinds_test.go index 4f12ee2b5b4..381442d692d 100644 --- a/hugolib/disableKinds_test.go +++ b/hugolib/disableKinds_test.go @@ -54,7 +54,15 @@ title: No List _build: render: false --- -`, "sect/no-publishresources/index.md", ` +`, + "sect/no-render-link.md", ` +--- +title: No Render Link +_build: + render: link +--- +`, + "sect/no-publishresources/index.md", ` --- title: No Publish Resources _build: @@ -303,6 +311,20 @@ title: Headless Local Lists Sub b.Assert(getPageInPagePages(sect, ref), qt.Not(qt.IsNil)) }) + c.Run("Build config, no render link", func(c *qt.C) { + b := newSitesBuilder(c, disableKind) + b.Build(BuildCfg{}) + ref := "/sect/no-render-link.md" + b.Assert(b.CheckExists("public/sect/no-render/index.html"), qt.Equals, false) + p := getPage(b, ref) + b.Assert(p, qt.Not(qt.IsNil)) + b.Assert(p.RelPermalink(), qt.Equals, "/blog/sect/no-render-link/") + b.Assert(p.OutputFormats(), qt.HasLen, 0) + b.Assert(getPageInSitePages(b, ref), qt.Not(qt.IsNil)) + sect := getPage(b, "/sect") + b.Assert(getPageInPagePages(sect, ref), qt.Not(qt.IsNil)) + }) + c.Run("Build config, no publish resources", func(c *qt.C) { b := newSitesBuilder(c, disableKind) b.Build(BuildCfg{}) diff --git a/hugolib/page__meta.go b/hugolib/page__meta.go index c7a8db3d5f3..631d4233b42 100644 --- a/hugolib/page__meta.go +++ b/hugolib/page__meta.go @@ -506,7 +506,7 @@ func (pm *pageMeta) setMetadata(parentBucket *pagesMapBucket, p *pageState, fron pm.params[loki] = isHeadless if p.File().TranslationBaseName() == "index" && isHeadless { pm.buildConfig.List = pagemeta.Never - pm.buildConfig.Render = false + pm.buildConfig.Render = pagemeta.Never } case "outputs": o := cast.ToStringSlice(v) @@ -683,7 +683,11 @@ func (p *pageMeta) getListFilter(local bool) contentTreeNodeCallback { } func (p *pageMeta) noRender() bool { - return !p.buildConfig.Render + return p.buildConfig.Render != pagemeta.Always +} + +func (p *pageMeta) noLink() bool { + return p.buildConfig.Render == pagemeta.Never } func (p *pageMeta) applyDefaultValues(n *contentNode) error { diff --git a/hugolib/page__paths.go b/hugolib/page__paths.go index d0bf26961df..535c60ba0aa 100644 --- a/hugolib/page__paths.go +++ b/hugolib/page__paths.go @@ -51,9 +51,11 @@ func newPagePaths( var relPermalink, permalink string - // If a page is headless or marked as "no render", or bundled in another, + // If a page is headless or bundled in another, // it will not get published on its own and it will have no links. - if !pm.noRender() && !pm.bundled { + // We also check the build options if it's set to not render or have + // a link. + if !pm.noLink() && !pm.bundled { relPermalink = paths.RelPermalink(s.PathSpec) permalink = paths.PermalinkForOutputFormat(s.PathSpec, f) } diff --git a/resources/page/pagemeta/pagemeta.go b/resources/page/pagemeta/pagemeta.go index 4e09b5ed743..19a0a7ae904 100644 --- a/resources/page/pagemeta/pagemeta.go +++ b/resources/page/pagemeta/pagemeta.go @@ -28,11 +28,12 @@ const ( Never = "never" Always = "always" ListLocally = "local" + Link = "link" ) var defaultBuildConfig = BuildConfig{ List: Always, - Render: true, + Render: Always, PublishResources: true, set: true, } @@ -49,7 +50,10 @@ type BuildConfig struct { List string // Whether to render it. - Render bool + // Valid values: never, always, link. + // The value link means it will not be rendered, but it will get a RelPermalink/Permalink. + // Note that before 0.76.0 this was a bool, so we accept those too. + Render string // Whether to publish its resources. These will still be published on demand, // but enabling this can be useful if the originals (e.g. images) are @@ -62,7 +66,7 @@ type BuildConfig struct { // Disable sets all options to their off value. func (b *BuildConfig) Disable() { b.List = Never - b.Render = false + b.Render = Never b.PublishResources = false b.set = true } @@ -91,5 +95,16 @@ func DecodeBuildConfig(m interface{}) (BuildConfig, error) { b.List = Always } + // In 0.76.0 we changed the Render from bool to a string. + switch b.Render { + case "0": + b.Render = Never + case "1": + b.Render = Always + case Always, Never, Link: + default: + b.Render = Always + } + return b, err } diff --git a/resources/page/pagemeta/pagemeta_test.go b/resources/page/pagemeta/pagemeta_test.go index a66a1f432a3..c251e7dabd6 100644 --- a/resources/page/pagemeta/pagemeta_test.go +++ b/resources/page/pagemeta/pagemeta_test.go @@ -31,33 +31,61 @@ func TestDecodeBuildConfig(t *testing.T) { configTempl := ` [_build] -render = true +render = %s list = %s publishResources = true` for _, test := range []struct { - list interface{} - expect string + args []interface{} + expect BuildConfig }{ - {"true", Always}, - {"false", Never}, - {`"always"`, Always}, - {`"local"`, ListLocally}, - {`"asdfadf"`, Always}, + { + []interface{}{"true", "true"}, + BuildConfig{ + Render: Always, + List: Always, + PublishResources: true, + set: true, + }}, + {[]interface{}{"true", "false"}, BuildConfig{ + Render: Always, + List: Never, + PublishResources: true, + set: true, + }}, + {[]interface{}{`"always"`, `"always"`}, BuildConfig{ + Render: Always, + List: Always, + PublishResources: true, + set: true, + }}, + {[]interface{}{`"never"`, `"never"`}, BuildConfig{ + Render: Never, + List: Never, + PublishResources: true, + set: true, + }}, + {[]interface{}{`"link"`, `"local"`}, BuildConfig{ + Render: Link, + List: ListLocally, + PublishResources: true, + set: true, + }}, + {[]interface{}{`"always"`, `"asdfadf"`}, BuildConfig{ + Render: Always, + List: Always, + PublishResources: true, + set: true, + }}, } { - cfg, err := config.FromConfigString(fmt.Sprintf(configTempl, test.list), "toml") + cfg, err := config.FromConfigString(fmt.Sprintf(configTempl, test.args...), "toml") c.Assert(err, qt.IsNil) bcfg, err := DecodeBuildConfig(cfg.Get("_build")) c.Assert(err, qt.IsNil) eq := qt.CmpEquals(hqt.DeepAllowUnexported(BuildConfig{})) - c.Assert(bcfg, eq, BuildConfig{ - Render: true, - List: test.expect, - PublishResources: true, - set: true, - }) + c.Assert(bcfg, eq, test.expect) }