hugo

Unnamed repository; edit this file 'description' to name the repository.

git clone git://git.shimmy1996.com/hugo.git
commit 634938908ec8f393b9a05d26b4cfe19ca7abb0d0
parent c63db7f1f6774a2d661af1d8197c6fe377e3ad25
Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Date:   Tue,  6 Oct 2020 11:19:31 +0200

pagemeta: Make BuildConfig.Render an enum

Allowing links on pages without rendering them.

Fixes #7783

Diffstat:
Mdocs/content/en/content-management/build-options.md | 15+++++++++++++--
Mhugolib/disableKinds_test.go | 24+++++++++++++++++++++++-
Mhugolib/page__meta.go | 8++++++--
Mhugolib/page__paths.go | 6++++--
Mresources/page/pagemeta/pagemeta.go | 21++++++++++++++++++---
Mresources/page/pagemeta/pagemeta_test.go | 58+++++++++++++++++++++++++++++++++++++++++++---------------
6 files changed, 107 insertions(+), 25 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
 
 	}