summaryrefslogtreecommitdiffstats
path: root/hugolib
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-01-04 18:24:36 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-05-16 18:01:29 +0200
commit241b21b0fd34d91fccb2ce69874110dceae6f926 (patch)
treed4e0118eac7e9c42f065815447a70805f8d6ad3e /hugolib
parent6aededf6b42011c3039f5f66487a89a8dd65e0e7 (diff)
Create a struct with all of Hugo's config options
Primary motivation is documentation, but it will also hopefully simplify the code. Also, * Lower case the default output format names; this is in line with the custom ones (map keys) and how it's treated all the places. This avoids doing `stringds.EqualFold` everywhere. Closes #10896 Closes #10620
Diffstat (limited to 'hugolib')
-rw-r--r--hugolib/alias.go2
-rw-r--r--hugolib/breaking_changes_test.go118
-rw-r--r--hugolib/cascade_test.go54
-rw-r--r--hugolib/codeowners.go5
-rw-r--r--hugolib/config.go670
-rw-r--r--hugolib/config_test.go577
-rw-r--r--hugolib/configdir_test.go153
-rw-r--r--hugolib/content_map.go2
-rw-r--r--hugolib/content_map_page.go10
-rw-r--r--hugolib/datafiles_test.go444
-rw-r--r--hugolib/dates_test.go2
-rw-r--r--hugolib/embedded_shortcodes_test.go422
-rw-r--r--hugolib/filesystems/basefs.go24
-rw-r--r--hugolib/filesystems/basefs_test.go231
-rw-r--r--hugolib/gitinfo.go4
-rw-r--r--hugolib/hugo_modules_test.go35
-rw-r--r--hugolib/hugo_sites.go343
-rw-r--r--hugolib/hugo_sites_build.go100
-rw-r--r--hugolib/hugo_sites_build_errors_test.go1
-rw-r--r--hugolib/hugo_sites_build_test.go19
-rw-r--r--hugolib/hugo_sites_multihost_test.go2
-rw-r--r--hugolib/hugo_smoke_test.go26
-rw-r--r--hugolib/integrationtest_builder.go67
-rw-r--r--hugolib/language_content_dir_test.go2
-rw-r--r--hugolib/menu_test.go33
-rw-r--r--hugolib/minify_publisher_test.go2
-rw-r--r--hugolib/multilingual.go82
-rw-r--r--hugolib/page.go17
-rw-r--r--hugolib/page__common.go6
-rw-r--r--hugolib/page__meta.go56
-rw-r--r--hugolib/page__new.go5
-rw-r--r--hugolib/page__paginator.go7
-rw-r--r--hugolib/page__paths.go4
-rw-r--r--hugolib/page__per_output.go2
-rw-r--r--hugolib/page_kinds.go4
-rw-r--r--hugolib/page_permalink_test.go35
-rw-r--r--hugolib/page_test.go170
-rw-r--r--hugolib/pagebundler_test.go51
-rw-r--r--hugolib/pagecollections_test.go21
-rw-r--r--hugolib/pages_capture.go5
-rw-r--r--hugolib/pages_capture_test.go27
-rw-r--r--hugolib/pages_process.go3
-rw-r--r--hugolib/paths/baseURL.go87
-rw-r--r--hugolib/paths/baseURL_test.go67
-rw-r--r--hugolib/paths/paths.go173
-rw-r--r--hugolib/paths/paths_test.go50
-rw-r--r--hugolib/prune_resources.go2
-rw-r--r--hugolib/robotstxt_test.go2
-rw-r--r--hugolib/rss_test.go12
-rw-r--r--hugolib/shortcode_test.go5
-rw-r--r--hugolib/site.go847
-rw-r--r--hugolib/site_benchmark_new_test.go8
-rw-r--r--hugolib/site_new.go458
-rw-r--r--hugolib/site_output_test.go36
-rw-r--r--hugolib/site_render.go27
-rw-r--r--hugolib/site_sections.go4
-rw-r--r--hugolib/site_sections_test.go7
-rw-r--r--hugolib/site_test.go204
-rw-r--r--hugolib/site_url_test.go45
-rw-r--r--hugolib/sitemap_test.go31
-rw-r--r--hugolib/taxonomy_test.go7
-rw-r--r--hugolib/template_test.go15
-rw-r--r--hugolib/testhelpers_test.go123
63 files changed, 1913 insertions, 4140 deletions
diff --git a/hugolib/alias.go b/hugolib/alias.go
index 071f73d41..1bc0e5424 100644
--- a/hugolib/alias.go
+++ b/hugolib/alias.go
@@ -101,7 +101,7 @@ func (s *Site) publishDestAlias(allowRoot bool, path, permalink string, outputFo
OutputFormat: outputFormat,
}
- if s.Info.relativeURLs || s.Info.canonifyURLs {
+ if s.conf.RelativeURLs || s.conf.CanonifyURLs {
pd.AbsURLPath = s.absURLPath(targetPath)
}
diff --git a/hugolib/breaking_changes_test.go b/hugolib/breaking_changes_test.go
index 495baff3e..533205deb 100644
--- a/hugolib/breaking_changes_test.go
+++ b/hugolib/breaking_changes_test.go
@@ -1,4 +1,4 @@
-// Copyright 2020 The Hugo Authors. All rights reserved.
+// Copyright 2023 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,119 +12,3 @@
// limitations under the License.
package hugolib
-
-import (
- "fmt"
- "testing"
-
- qt "github.com/frankban/quicktest"
-)
-
-func Test073(t *testing.T) {
- assertDisabledTaxonomyAndTerm := func(b *sitesBuilder, taxonomy, term bool) {
- b.Assert(b.CheckExists("public/tags/index.html"), qt.Equals, taxonomy)
- b.Assert(b.CheckExists("public/tags/tag1/index.html"), qt.Equals, term)
- }
-
- assertOutputTaxonomyAndTerm := func(b *sitesBuilder, taxonomy, term bool) {
- b.Assert(b.CheckExists("public/tags/index.json"), qt.Equals, taxonomy)
- b.Assert(b.CheckExists("public/tags/tag1/index.json"), qt.Equals, term)
- }
-
- for _, this := range []struct {
- name string
- config string
- assert func(err error, out string, b *sitesBuilder)
- }{
- {
- "Outputs for both taxonomy and taxonomyTerm",
- `[outputs]
- taxonomy = ["JSON"]
- taxonomyTerm = ["JSON"]
-
-`,
- func(err error, out string, b *sitesBuilder) {
- b.Assert(err, qt.IsNil)
- assertOutputTaxonomyAndTerm(b, true, true)
- },
- },
- {
- "Outputs for taxonomyTerm",
- `[outputs]
-taxonomyTerm = ["JSON"]
-
-`,
- func(err error, out string, b *sitesBuilder) {
- b.Assert(err, qt.IsNil)
- assertOutputTaxonomyAndTerm(b, true, false)
- },
- },
- {
- "Outputs for taxonomy only",
- `[outputs]
-taxonomy = ["JSON"]
-
-`,
- func(err error, out string, b *sitesBuilder) {
- b.Assert(err, qt.Not(qt.IsNil))
- b.Assert(out, qt.Contains, `ignoreErrors = ["error-output-taxonomy"]`)
- },
- },
- {
- "Outputs for taxonomy only, ignore error",
- `
-ignoreErrors = ["error-output-taxonomy"]
-[outputs]
-taxonomy = ["JSON"]
-
-`,
- func(err error, out string, b *sitesBuilder) {
- b.Assert(err, qt.IsNil)
- assertOutputTaxonomyAndTerm(b, true, false)
- },
- },
- {
- "Disable both taxonomy and taxonomyTerm",
- `disableKinds = ["taxonomy", "taxonomyTerm"]`,
- func(err error, out string, b *sitesBuilder) {
- b.Assert(err, qt.IsNil)
- assertDisabledTaxonomyAndTerm(b, false, false)
- },
- },
- {
- "Disable only taxonomyTerm",
- `disableKinds = ["taxonomyTerm"]`,
- func(err error, out string, b *sitesBuilder) {
- b.Assert(err, qt.IsNil)
- assertDisabledTaxonomyAndTerm(b, false, true)
- },
- },
- {
- "Disable only taxonomy",
- `disableKinds = ["taxonomy"]`,
- func(err error, out string, b *sitesBuilder) {
- b.Assert(err, qt.Not(qt.IsNil))
- b.Assert(out, qt.Contains, `ignoreErrors = ["error-disable-taxonomy"]`)
- },
- },
- {
- "Disable only taxonomy, ignore error",
- `disableKinds = ["taxonomy"]
- ignoreErrors = ["error-disable-taxonomy"]`,
- func(err error, out string, b *sitesBuilder) {
- b.Assert(err, qt.IsNil)
- assertDisabledTaxonomyAndTerm(b, false, true)
- },
- },
- } {
- t.Run(this.name, func(t *testing.T) {
- b := newTestSitesBuilder(t).WithConfigFile("toml", this.config)
- b.WithTemplatesAdded("_default/list.json", "JSON")
- out, err := captureStdout(func() error {
- return b.BuildE(BuildCfg{})
- })
- fmt.Println(out)
- this.assert(err, out, b)
- })
- }
-}
diff --git a/hugolib/cascade_test.go b/hugolib/cascade_test.go
index dff2082b6..0f607ecb5 100644
--- a/hugolib/cascade_test.go
+++ b/hugolib/cascade_test.go
@@ -159,33 +159,33 @@ func TestCascade(t *testing.T) {
b.Build(BuildCfg{})
b.AssertFileContent("public/index.html", `
-12|term|categories/cool/_index.md|Cascade Category|cat.png|categories|HTML-|
-12|term|categories/catsect1|catsect1|cat.png|categories|HTML-|
-12|term|categories/funny|funny|cat.png|categories|HTML-|
-12|taxonomy|categories/_index.md|My Categories|cat.png|categories|HTML-|
-32|term|categories/sad/_index.md|Cascade Category|sad.png|categories|HTML-|
-42|term|tags/blue|blue|home.png|tags|HTML-|
-42|taxonomy|tags|Cascade Home|home.png|tags|HTML-|
-42|section|sectnocontent|Cascade Home|home.png|sectnocontent|HTML-|
-42|section|sect3|Cascade Home|home.png|sect3|HTML-|
-42|page|bundle1/index.md|Cascade Home|home.png|page|HTML-|
-42|page|p2.md|Cascade Home|home.png|page|HTML-|
-42|page|sect2/p2.md|Cascade Home|home.png|sect2|HTML-|
-42|page|sect3/nofrontmatter.md|Cascade Home|home.png|sect3|HTML-|
-42|page|sect3/p1.md|Cascade Home|home.png|sect3|HTML-|
-42|page|sectnocontent/p1.md|Cascade Home|home.png|sectnocontent|HTML-|
-42|section|sectnofrontmatter/_index.md|Cascade Home|home.png|sectnofrontmatter|HTML-|
-42|term|tags/green|green|home.png|tags|HTML-|
-42|home|_index.md|Home|home.png|page|HTML-|
-42|page|p1.md|p1|home.png|page|HTML-|
-42|section|sect1/_index.md|Sect1|sect1.png|stype|HTML-|
-42|section|sect1/s1_2/_index.md|Sect1_2|sect1.png|stype|HTML-|
-42|page|sect1/s1_2/p1.md|Sect1_2_p1|sect1.png|stype|HTML-|
-42|page|sect1/s1_2/p2.md|Sect1_2_p2|sect1.png|stype|HTML-|
-42|section|sect2/_index.md|Sect2|home.png|sect2|HTML-|
-42|page|sect2/p1.md|Sect2_p1|home.png|sect2|HTML-|
-52|page|sect4/p1.md|Cascade Home|home.png|sect4|RSS-|
-52|section|sect4/_index.md|Sect4|home.png|sect4|RSS-|
+12|term|categories/cool/_index.md|Cascade Category|cat.png|categories|html-|
+12|term|categories/catsect1|catsect1|cat.png|categories|html-|
+12|term|categories/funny|funny|cat.png|categories|html-|
+12|taxonomy|categories/_index.md|My Categories|cat.png|categories|html-|
+32|term|categories/sad/_index.md|Cascade Category|sad.png|categories|html-|
+42|term|tags/blue|blue|home.png|tags|html-|
+42|taxonomy|tags|Cascade Home|home.png|tags|html-|
+42|section|sectnocontent|Cascade Home|home.png|sectnocontent|html-|
+42|section|sect3|Cascade Home|home.png|sect3|html-|
+42|page|bundle1/index.md|Cascade Home|home.png|page|html-|
+42|page|p2.md|Cascade Home|home.png|page|html-|
+42|page|sect2/p2.md|Cascade Home|home.png|sect2|html-|
+42|page|sect3/nofrontmatter.md|Cascade Home|home.png|sect3|html-|
+42|page|sect3/p1.md|Cascade Home|home.png|sect3|html-|
+42|page|sectnocontent/p1.md|Cascade Home|home.png|sectnocontent|html-|
+42|section|sectnofrontmatter/_index.md|Cascade Home|home.png|sectnofrontmatter|html-|
+42|term|tags/green|green|home.png|tags|html-|
+42|home|_index.md|Home|home.png|page|html-|
+42|page|p1.md|p1|home.png|page|html-|
+42|section|sect1/_index.md|Sect1|sect1.png|stype|html-|
+42|section|sect1/s1_2/_index.md|Sect1_2|sect1.png|stype|html-|
+42|page|sect1/s1_2/p1.md|Sect1_2_p1|sect1.png|stype|html-|
+42|page|sect1/s1_2/p2.md|Sect1_2_p2|sect1.png|stype|html-|
+42|section|sect2/_index.md|Sect2|home.png|sect2|html-|
+42|page|sect2/p1.md|Sect2_p1|home.png|sect2|html-|
+52|page|sect4/p1.md|Cascade Home|home.png|sect4|rss-|
+52|section|sect4/_index.md|Sect4|home.png|sect4|rss-|
`)
// Check that type set in cascade gets the correct layout.
diff --git a/hugolib/codeowners.go b/hugolib/codeowners.go
index 162ee16ae..c1a6a2b7b 100644
--- a/hugolib/codeowners.go
+++ b/hugolib/codeowners.go
@@ -18,7 +18,6 @@ import (
"path"
"github.com/gohugoio/hugo/common/herrors"
- "github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/resources/page"
"github.com/hairyhenderson/go-codeowners"
"github.com/spf13/afero"
@@ -52,9 +51,7 @@ func (c *codeownerInfo) forPage(p page.Page) []string {
return c.owners.Owners(p.File().Filename())
}
-func newCodeOwners(cfg config.Provider) (*codeownerInfo, error) {
- workingDir := cfg.GetString("workingDir")
-
+func newCodeOwners(workingDir string) (*codeownerInfo, error) {
r, err := findCodeOwnersFile(workingDir)
if err != nil || r == nil {
return nil, err
diff --git a/hugolib/config.go b/hugolib/config.go
index 059424e85..af3f0647f 100644
--- a/hugolib/config.go
+++ b/hugolib/config.go
@@ -16,526 +16,170 @@ package hugolib
import (
"os"
"path/filepath"
- "strings"
-
- "github.com/gohugoio/hugo/common/hexec"
- "github.com/gohugoio/hugo/common/types"
-
- "github.com/gohugoio/hugo/common/maps"
- cpaths "github.com/gohugoio/hugo/common/paths"
-
- "github.com/gobwas/glob"
- hglob "github.com/gohugoio/hugo/hugofs/glob"
-
- "github.com/gohugoio/hugo/common/loggers"
-
- "github.com/gohugoio/hugo/cache/filecache"
-
- "github.com/gohugoio/hugo/parser/metadecoders"
-
- "errors"
-
- "github.com/gohugoio/hugo/common/herrors"
- "github.com/gohugoio/hugo/common/hugo"
- "github.com/gohugoio/hugo/langs"
- "github.com/gohugoio/hugo/modules"
"github.com/gohugoio/hugo/config"
- "github.com/gohugoio/hugo/config/privacy"
- "github.com/gohugoio/hugo/config/security"
- "github.com/gohugoio/hugo/config/services"
- "github.com/gohugoio/hugo/helpers"
+ "github.com/gohugoio/hugo/config/allconfig"
"github.com/spf13/afero"
)
-var ErrNoConfigFile = errors.New("Unable to locate config file or config directory. Perhaps you need to create a new site.\n Run `hugo help new` for details.\n")
-
-// LoadConfig loads Hugo configuration into a new Viper and then adds
-// a set of defaults.
-func LoadConfig(d ConfigSourceDescriptor, doWithConfig ...func(cfg config.Provider) error) (config.Provider, []string, error) {
- if d.Environment == "" {
- d.Environment = hugo.EnvironmentProduction
- }
-
- if len(d.Environ) == 0 && !hugo.IsRunningAsTest() {
- d.Environ = os.Environ()
- }
-
- var configFiles []string
-
- l := configLoader{ConfigSourceDescriptor: d, cfg: config.New()}
- // Make sure we always do this, even in error situations,
- // as we have commands (e.g. "hugo mod init") that will
- // use a partial configuration to do its job.
- defer l.deleteMergeStrategies()
-
- names := d.configFilenames()
-
- if names != nil {
- for _, name := range names {
- var filename string
- filename, err := l.loadConfig(name)
- if err == nil {
- configFiles = append(configFiles, filename)
- } else if err != ErrNoConfigFile {
- return nil, nil, l.wrapFileError(err, filename)
- }
- }
- } else {
- for _, name := range config.DefaultConfigNames {
- var filename string
- filename, err := l.loadConfig(name)
- if err == nil {
- configFiles = append(configFiles, filename)
- break
- } else if err != ErrNoConfigFile {
- return nil, nil, l.wrapFileError(err, filename)
- }
- }
- }
-
- if d.AbsConfigDir != "" {
-
- dcfg, dirnames, err := config.LoadConfigFromDir(l.Fs, d.AbsConfigDir, l.Environment)
-
- if err == nil {
- if len(dirnames) > 0 {
- l.cfg.Set("", dcfg.Get(""))
- configFiles = append(configFiles, dirnames...)
- }
- } else if err != ErrNoConfigFile {
- if len(dirnames) > 0 {
- return nil, nil, l.wrapFileError(err, dirnames[0])
- }
- return nil, nil, err
- }
- }
-
- if err := l.applyConfigDefaults(); err != nil {
- return l.cfg, configFiles, err
- }
-
- l.cfg.SetDefaultMergeStrategy()
-
- // We create languages based on the settings, so we need to make sure that
- // all configuration is loaded/set before doing that.
- for _, d := range doWithConfig {
- if err := d(l.cfg); err != nil {
- return l.cfg, configFiles, err
- }
- }
-
- // Some settings are used before we're done collecting all settings,
- // so apply OS environment both before and after.
- if err := l.applyOsEnvOverrides(d.Environ); err != nil {
- return l.cfg, configFiles, err
- }
-
- modulesConfig, err := l.loadModulesConfig()
+// DefaultConfig returns the default configuration.
+func DefaultConfig() *allconfig.Config {
+ fs := afero.NewMemMapFs()
+ all, err := allconfig.LoadConfig(allconfig.ConfigSourceDescriptor{Fs: fs})
if err != nil {
- return l.cfg, configFiles, err
- }
-
- // Need to run these after the modules are loaded, but before
- // they are finalized.
- collectHook := func(m *modules.ModulesConfig) error {
- // We don't need the merge strategy configuration anymore,
- // remove it so it doesn't accidentally show up in other settings.
- l.deleteMergeStrategies()
-
- if err := l.loadLanguageSettings(nil); err != nil {
- return err
- }
-
- mods := m.ActiveModules
-
- // Apply default project mounts.
- if err := modules.ApplyProjectConfigDefaults(l.cfg, mods[0]); err != nil {
- return err
- }
-
- return nil
- }
-
- _, modulesConfigFiles, modulesCollectErr := l.collectModules(modulesConfig, l.cfg, collectHook)
+ panic(err)
+ }
+ return all.Base
+}
+
+// ExampleConfig returns the some example configuration for documentation.
+func ExampleConfig() (*allconfig.Config, error) {
+ // Apply some example settings for