pagemeta: Make BuildConfig.Render an enum
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 6 Oct 2020 09:19:31 +0000 (11:19 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 6 Oct 2020 12:06:10 +0000 (14:06 +0200)
Allowing links on pages without rendering them.

Fixes #7783

docs/content/en/content-management/build-options.md
hugolib/disableKinds_test.go
hugolib/page__meta.go
hugolib/page__paths.go
resources/page/pagemeta/pagemeta.go
resources/page/pagemeta/pagemeta_test.go

index b01568d39a21fab866cd645426bbbde0d3c25044..93da7c4214d1bccecc75bb0a210d3f5c7fe19864 100644 (file)
@@ -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
 
index 4f12ee2b5b4ae10b343100f615675a6fa8945bae..381442d692da88e231277ec7494e825c068b6ea8 100644 (file)
@@ -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{})
index c7a8db3d5f3105a72aee82f7c6ab38f97d676e43..631d4233b426942e8751488baa989841161ae579 100644 (file)
@@ -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 {
index d0bf26961dfa78af4860d6e07f16f6ad0fc6ee60..535c60ba0aa6315cefab3bcdca36665317452cac 100644 (file)
@@ -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)
                }
index 4e09b5ed743e2caf6e8dd20814cd335433b8e15e..19a0a7ae9042778283602e0983b4506c6aaa74ac 100644 (file)
@@ -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
 }
index a66a1f432a3b77210dbf6c2be66e666ff9275da5..c251e7dabd609dcb0f48f041c7c03dfe3b094566 100644 (file)
@@ -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)
 
        }