Skip to content

Commit 8783878

Browse files
committed
Add segments config + --renderSegments flag
Named segments can be defined in `hugo.toml`. * Eeach segment consists of zero or more `exclude` filters and zero or more `include` filters. * Eeach filter consists of one or more field Glob matchers. * Eeach filter in a section (`exclude` or `include`) is ORed together, each matcher in a filter is ANDed together. The current list of fields that can be filtered are: * path as defined in https://gohugo.io/methods/page/path/ * kind * lang * output (output format, e.g. html). It is recommended to put coarse grained filters (e.g. for language and output format) in the excludes section, e.g.: ```toml [segments.segment1] [[segments.segment1.excludes]] lang = "n*" [[segments.segment1.excludes]] no = "en" output = "rss" [[segments.segment1.includes]] term = "{home,term,taxonomy}" [[segments.segment1.includes]] path = "{/docs,/docs/**}" ``` By default, Hugo will render all segments, but you can enable filters by setting the `renderSegments` option or `--renderSegments` flag, e.g: ``` hugo --renderSegments segment1,segment2 ``` For segment `segment1` in the configuration above, this will: * Skip rendering of all languages matching `n*`, e.g. `no`. * Skip rendering of the output format `rss` for the `en` language. * It will render all pages of kind `home`, `term` or `taxonomy` * It will render the `/docs` section and all pages below. Fixes gohugoio#10106
1 parent ca31b95 commit 8783878

10 files changed

+499
-3
lines changed

commands/commandeer.go

+1
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ func applyLocalFlagsBuildConfig(cmd *cobra.Command, r *rootCommand) {
521521
cmd.Flags().StringP("cacheDir", "", "", "filesystem path to cache directory")
522522
_ = cmd.Flags().SetAnnotation("cacheDir", cobra.BashCompSubdirsInDir, []string{})
523523
cmd.Flags().StringP("contentDir", "c", "", "filesystem path to content directory")
524+
cmd.Flags().StringSliceP("renderSegments", "", []string{}, "named segments to render (configured in the segments config)")
524525
_ = cmd.Flags().SetAnnotation("theme", cobra.BashCompSubdirsInDir, []string{"themes"})
525526
}
526527

config/allconfig/allconfig.go

+10
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import (
3939
"github.com/gohugoio/hugo/config/services"
4040
"github.com/gohugoio/hugo/deploy/deployconfig"
4141
"github.com/gohugoio/hugo/helpers"
42+
"github.com/gohugoio/hugo/hugolib/segments"
4243
"github.com/gohugoio/hugo/langs"
4344
"github.com/gohugoio/hugo/markup/markup_config"
4445
"github.com/gohugoio/hugo/media"
@@ -137,6 +138,9 @@ type Config struct {
137138
// a slice of page matcher and params to apply to those pages.
138139
Cascade *config.ConfigNamespace[[]page.PageMatcherParamsConfig, map[page.PageMatcher]maps.Params] `mapstructure:"-"`
139140

141+
// The segments defines segments for the site. Used for partial/segmented builds.
142+
Segments *config.ConfigNamespace[map[string]segments.SegmentConfig, segments.Segments] `mapstructure:"-"`
143+
140144
// Menu configuration.
141145
// <docsmeta>{"refs": ["config:languages:menus"] }</docsmeta>
142146
Menus *config.ConfigNamespace[map[string]navigation.MenuConfig, navigation.Menus] `mapstructure:"-"`
@@ -364,6 +368,7 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
364368
CreateTitle: helpers.GetTitleFunc(c.TitleCaseStyle),
365369
IsUglyURLSection: isUglyURL,
366370
IgnoreFile: ignoreFile,
371+
SegmentFilter: c.Segments.Config.Get(c.RootConfig.RenderSegments...),
367372
MainSections: c.MainSections,
368373
Clock: clock,
369374
transientErr: transientErr,
@@ -400,6 +405,7 @@ type ConfigCompiled struct {
400405
CreateTitle func(s string) string
401406
IsUglyURLSection func(section string) bool
402407
IgnoreFile func(filename string) bool
408+
SegmentFilter segments.SegmentFilter
403409
MainSections []string
404410
Clock time.Time
405411

@@ -472,6 +478,10 @@ type RootConfig struct {
472478
// A list of languages to disable.
473479
DisableLanguages []string
474480

481+
// The named segments to render.
482+
// This needs to match the name of the segment in the segments configuration.
483+
RenderSegments []string
484+
475485
// Disable the injection of the Hugo generator tag on the home page.
476486
DisableHugoGeneratorInject bool
477487

config/allconfig/alldecoders.go

+10
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ import (
2525
"github.com/gohugoio/hugo/config/security"
2626
"github.com/gohugoio/hugo/config/services"
2727
"github.com/gohugoio/hugo/deploy/deployconfig"
28+
"github.com/gohugoio/hugo/hugolib/segments"
2829
"github.com/gohugoio/hugo/langs"
2930
"github.com/gohugoio/hugo/markup/markup_config"
3031
"github.com/gohugoio/hugo/media"
3132
"github.com/gohugoio/hugo/minifiers"
3233
"github.com/gohugoio/hugo/modules"
34+
3335
"github.com/gohugoio/hugo/navigation"
3436
"github.com/gohugoio/hugo/output"
3537
"github.com/gohugoio/hugo/related"
@@ -120,6 +122,14 @@ var allDecoderSetups = map[string]decodeWeight{
120122
return err
121123
},
122124
},
125+
"segments": {
126+
key: "segments",
127+
decode: func(d decodeWeight, p decodeConfig) error {
128+
var err error
129+
p.c.Segments, err = segments.DecodeSegments(p.p.GetStringMap(d.key))
130+
return err
131+
},
132+
},
123133
"server": {
124134
key: "server",
125135
decode: func(d decodeWeight, p decodeConfig) error {

hugolib/hugo_sites.go

+4
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,10 @@ type BuildCfg struct {
410410

411411
// shouldRender returns whether this output format should be rendered or not.
412412
func (cfg *BuildCfg) shouldRender(p *pageState) bool {
413+
if p.skipRender() {
414+
return false
415+
}
416+
413417
if !p.renderOnce {
414418
return true
415419
}

hugolib/hugo_sites_build.go

+13-2
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@ import (
2828
"github.com/bep/logg"
2929
"github.com/gohugoio/hugo/cache/dynacache"
3030
"github.com/gohugoio/hugo/deps"
31+
"github.com/gohugoio/hugo/hugofs"
3132
"github.com/gohugoio/hugo/hugofs/files"
3233
"github.com/gohugoio/hugo/hugofs/glob"
34+
"github.com/gohugoio/hugo/hugolib/segments"
3335
"github.com/gohugoio/hugo/identity"
3436
"github.com/gohugoio/hugo/output"
3537
"github.com/gohugoio/hugo/publisher"
3638
"github.com/gohugoio/hugo/source"
3739
"github.com/gohugoio/hugo/tpl"
3840

39-
"github.com/gohugoio/hugo/hugofs"
40-
4141
"github.com/gohugoio/hugo/common/herrors"
4242
"github.com/gohugoio/hugo/common/loggers"
4343
"github.com/gohugoio/hugo/common/para"
@@ -318,9 +318,20 @@ func (h *HugoSites) render(l logg.LevelLogger, config *BuildCfg) error {
318318

319319
i := 0
320320
for _, s := range h.Sites {
321+
segmentFilter := s.conf.C.SegmentFilter
322+
if segmentFilter.ShouldExcludeCoarse(segments.SegmentMatcherFields{Lang: s.language.Lang}) {
323+
l.Logf("skip language %q not matching segments set in --renderSegments", s.language.Lang)
324+
continue
325+
}
326+
321327
siteRenderContext.languageIdx = s.languagei
322328
h.currentSite = s
323329
for siteOutIdx, renderFormat := range s.renderFormats {
330+
if segmentFilter.ShouldExcludeCoarse(segments.SegmentMatcherFields{Output: renderFormat.Name, Lang: s.language.Lang}) {
331+
l.Logf("skip output format %q for language %q not matching segments set in --renderSegments", renderFormat.Name, s.language.Lang)
332+
continue
333+
}
334+
324335
siteRenderContext.outIdx = siteOutIdx
325336
siteRenderContext.sitesOutIdx = i
326337
i++

hugolib/page.go

+14
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222

2323
"github.com/gohugoio/hugo/hugofs"
2424
"github.com/gohugoio/hugo/hugolib/doctree"
25+
"github.com/gohugoio/hugo/hugolib/segments"
2526
"github.com/gohugoio/hugo/identity"
2627
"github.com/gohugoio/hugo/media"
2728
"github.com/gohugoio/hugo/output"
@@ -151,6 +152,19 @@ func (p *pageState) reusePageOutputContent() bool {
151152
return p.pageOutputTemplateVariationsState.Load() == 1
152153
}
153154

155+
func (p *pageState) skipRender() bool {
156+
b := p.s.conf.C.SegmentFilter.ShouldExcludeFine(
157+
segments.SegmentMatcherFields{
158+
Path: p.Path(),
159+
Kind: p.Kind(),
160+
Lang: p.Lang(),
161+
Output: p.pageOutput.f.Name,
162+
},
163+
)
164+
165+
return b
166+
}
167+
154168
func (po *pageState) isRenderedAny() bool {
155169
for _, o := range po.pageOutputs {
156170
if o.isRendered() {

0 commit comments

Comments
 (0)