aboutsummaryrefslogtreecommitdiffhomepage
path: root/modules/config.go
diff options
context:
space:
mode:
Diffstat (limited to 'modules/config.go')
-rw-r--r--modules/config.go254
1 files changed, 114 insertions, 140 deletions
diff --git a/modules/config.go b/modules/config.go
index 9d516e841..f8faf7969 100644
--- a/modules/config.go
+++ b/modules/config.go
@@ -20,10 +20,9 @@ import (
"strings"
"github.com/gohugoio/hugo/common/hugo"
+ "github.com/gohugoio/hugo/hugofs/files"
"github.com/gohugoio/hugo/config"
- "github.com/gohugoio/hugo/hugofs/files"
- "github.com/gohugoio/hugo/langs"
"github.com/mitchellh/mapstructure"
)
@@ -58,12 +57,9 @@ var DefaultModuleConfig = Config{
// ApplyProjectConfigDefaults applies default/missing module configuration for
// the main project.
-func ApplyProjectConfigDefaults(cfg config.Provider, mod Module) error {
- moda := mod.(*moduleAdapter)
+func ApplyProjectConfigDefaults(mod Module, cfgs ...config.AllProvider) error {
- // Map legacy directory config into the new module.
- languages := cfg.Get("languagesSortedDefaultFirst").(langs.Languages)
- isMultiHost := languages.IsMultihost()
+ moda := mod.(*moduleAdapter)
// To bridge between old and new configuration format we need
// a way to make sure all of the core components are configured on
@@ -75,121 +71,92 @@ func ApplyProjectConfigDefaults(cfg config.Provider, mod Module) error {
}
}
- type dirKeyComponent struct {
- key string
- component string
- multilingual bool
- }
-
- dirKeys := []dirKeyComponent{
- {"contentDir", files.ComponentFolderContent, true},
- {"dataDir", files.ComponentFolderData, false},
- {"layoutDir", files.ComponentFolderLayouts, false},
- {"i18nDir", files.ComponentFolderI18n, false},
- {"archetypeDir", files.ComponentFolderArchetypes, false},
- {"assetDir", files.ComponentFolderAssets, false},
- {"", files.ComponentFolderStatic, isMultiHost},
- }
+ var mounts []Mount
- createMountsFor := func(d dirKeyComponent, cfg config.Provider) []Mount {
- var lang string
- if language, ok := cfg.(*langs.Language); ok {
- lang = language.Lang
+ for _, component := range []string{
+ files.ComponentFolderContent,
+ files.ComponentFolderData,
+ files.ComponentFolderLayouts,
+ files.ComponentFolderI18n,
+ files.ComponentFolderArchetypes,
+ files.ComponentFolderAssets,
+ files.ComponentFolderStatic,
+ } {
+ if componentsConfigured[component] {
+ continue
}
- // Static mounts are a little special.
- if d.component == files.ComponentFolderStatic {
- var mounts []Mount
- staticDirs := getStaticDirs(cfg)
- if len(staticDirs) > 0 {
- componentsConfigured[d.component] = true
+ first := cfgs[0]
+ dirsBase := first.DirsBase()
+ isMultiHost := first.IsMultihost()
+
+ for i, cfg := range cfgs {
+ dirs := cfg.Dirs()
+ var dir string
+ var dropLang bool
+ switch component {
+ case files.ComponentFolderContent:
+ dir = dirs.ContentDir
+ dropLang = dir == dirsBase.ContentDir
+ case files.ComponentFolderData:
+ dir = dirs.DataDir
+ case files.ComponentFolderLayouts:
+ dir = dirs.LayoutDir
+ case files.ComponentFolderI18n:
+ dir = dirs.I18nDir
+ case files.ComponentFolderArchetypes:
+ dir = dirs.ArcheTypeDir
+ case files.ComponentFolderAssets:
+ dir = dirs.AssetDir
+ case files.ComponentFolderStatic:
+ // For static dirs, we only care about the language in multihost setups.
+ dropLang = !isMultiHost
}
- for _, dir := range staticDirs {
- mounts = append(mounts, Mount{Lang: lang, Source: dir, Target: d.component})
+ var perLang bool
+ switch component {
+ case files.ComponentFolderContent, files.ComponentFolderStatic:
+ perLang = true
+ default:
+ }
+ if i > 0 && !perLang {
+ continue
}
- return mounts
-
- }
-
- if cfg.IsSet(d.key) {
- source := cfg.GetString(d.key)
- componentsConfigured[d.component] = true
-
- return []Mount{{
- // No lang set for layouts etc.
- Source: source,
- Target: d.component,
- }}
- }
-
- return nil
- }
-
- createMounts := func(d dirKeyComponent) []Mount {
- var mounts []Mount
- if d.multilingual {
- if d.component == files.ComponentFolderContent {
- seen := make(map[string]bool)
- hasContentDir := false
- for _, language := range languages {
- if language.ContentDir != "" {
- hasContentDir = true
- break
- }
- }
+ var lang string
+ if perLang && !dropLang {
+ lang = cfg.Language().Lang
+ }
- if hasContentDir {
- for _, language := range languages {
- contentDir := language.ContentDir
- if contentDir == "" {
- contentDir = files.ComponentFolderContent
- }
- if contentDir == "" || seen[contentDir] {
- continue
- }
- seen[contentDir] = true
- mounts = append(mounts, Mount{Lang: language.Lang, Source: contentDir, Target: d.component})
- }
+ // Static mounts are a little special.
+ if component == files.ComponentFolderStatic {
+ staticDirs := cfg.StaticDirs()
+ for _, dir := range staticDirs {
+ mounts = append(mounts, Mount{Lang: lang, Source: dir, Target: component})
}
+ continue
+ }
- componentsConfigured[d.component] = len(seen) > 0
-
- } else {
- for _, language := range languages {
- mounts = append(mounts, createMountsFor(d, language)...)
- }
+ if dir != "" {
+ mounts = append(mounts, Mount{Lang: lang, Source: dir, Target: component})
}
- } else {
- mounts = append(mounts, createMountsFor(d, cfg)...)
}
-
- return mounts
}
- var mounts []Mount
- for _, dirKey := range dirKeys {
- if componentsConfigured[dirKey.component] {
- continue
- }
-
- mounts = append(mounts, createMounts(dirKey)...)
+ moda.mounts = append(moda.mounts, mounts...)
- }
-
- // Add default configuration
- for _, dirKey := range dirKeys {
- if componentsConfigured[dirKey.component] {
+ // Temporary: Remove duplicates.
+ seen := make(map[string]bool)
+ var newMounts []Mount
+ for _, m := range moda.mounts {
+ key := m.Source + m.Target + m.Lang
+ if seen[key] {
continue
}
- mounts = append(mounts, Mount{Source: dirKey.component, Target: dirKey.component})
+ seen[key] = true
+ newMounts = append(newMounts, m)
}
-
- // Prepend the mounts from configuration.
- mounts = append(moda.mounts, mounts...)
-
- moda.mounts = mounts
+ moda.mounts = newMounts
return nil
}
@@ -275,7 +242,6 @@ func decodeConfig(cfg config.Provider, pathReplacements map[string]string) (Conf
Path: imp,
})
}
-
}
return c, nil
@@ -283,7 +249,10 @@ func decodeConfig(cfg config.Provider, pathReplacements map[string]string) (Conf
// Config holds a module config.
type Config struct {
- Mounts []Mount
+ // File system mounts.
+ Mounts []Mount
+
+ // Module imports.
Imports []Import
// Meta info about this module (license information etc.).
@@ -292,8 +261,7 @@ type Config struct {
// Will be validated against the running Hugo version.
HugoVersion HugoVersion
- // A optional Glob pattern matching module paths to skip when vendoring, e.g.
- // "github.com/**".
+ // Optional Glob pattern matching module paths to skip when vendoring, e.g. “github.com/**”
NoVendor string
// When enabled, we will pick the vendored module closest to the module
@@ -303,21 +271,31 @@ type Config struct {
// so once it is in use it cannot be redefined.
VendorClosest bool
+ // A comma separated (or a slice) list of module path to directory replacement mapping,
+ // e.g. github.com/bep/my-theme -> ../..,github.com/bep/shortcodes -> /some/path.
+ // This is mostly useful for temporary locally development of a module, and then it makes sense to set it as an
+ // OS environment variable, e.g: env HUGO_MODULE_REPLACEMENTS="github.com/bep/my-theme -> ../..".
+ // Any relative path is relate to themesDir, and absolute paths are allowed.
Replacements []string
replacementsMap map[string]string
- // Configures GOPROXY.
+ // Defines the proxy server to use to download remote modules. Default is direct, which means “git clone” and similar.
+ // Configures GOPROXY when running the Go command for module operations.
Proxy string
- // Configures GONOPROXY.
+
+ // Comma separated glob list matching paths that should not use the proxy configured above.
+ // Configures GONOPROXY when running the Go command for module operations.
NoProxy string
- // Configures GOPRIVATE.
+
+ // Comma separated glob list matching paths that should be treated as private.
+ // Configures GOPRIVATE when running the Go command for module operations.
Private string
// Defaults to "off".
// Set to a work file, e.g. hugo.work, to enable Go "Workspace" mode.
// Can be relative to the working directory or absolute.
- // Requires Go 1.18+
- // See https://tip.golang.org/doc/go1.18
+ // Requires Go 1.18+.
+ // Note that this can also be set via OS env, e.g. export HUGO_MODULE_WORKSPACE=/my/hugo.work.
Workspace string
}
@@ -387,21 +365,33 @@ func (v HugoVersion) IsValid() bool {
}
type Import struct {
- Path string // Module path
- pathProjectReplaced bool // Set when Path is replaced in project config.
- IgnoreConfig bool // Ignore any config in config.toml (will still follow imports).
- IgnoreImports bool // Do not follow any configured imports.
- NoMounts bool // Do not mount any folder in this import.
- NoVendor bool // Never vendor this import (only allowed in main project).
- Disable bool // Turn off this module.
- Mounts []Mount
+ // Module path
+ Path string
+ // Set when Path is replaced in project config.
+ pathProjectReplaced bool
+ // Ignore any config in config.toml (will still follow imports).
+ IgnoreConfig bool
+ // Do not follow any configured imports.
+ IgnoreImports bool
+ // Do not mount any folder in this import.
+ NoMounts bool
+ // Never vendor this import (only allowed in main project).
+ NoVendor bool
+ // Turn off this module.
+ Disable bool
+ // File mounts.
+ Mounts []Mount
}
type Mount struct {
- Source string // relative path in source repo, e.g. "scss"
- Target string // relative target path, e.g. "assets/bootstrap/scss"
+ // Relative path in source repo, e.g. "scss".
+ Source string
- Lang string // any language code associated with this mount.
+ // Relative target path, e.g. "assets/bootstrap/scss".
+ Target string
+
+ // Any file in this mount will be associated with this language.
+ Lang string
// Include only files matching the given Glob patterns (string or slice).
IncludeFiles any
@@ -423,19 +413,3 @@ func (m Mount) ComponentAndName() (string, string) {
c, n, _ := strings.Cut(m.Target, fileSeparator)
return c, n
}
-
-func getStaticDirs(cfg config.Provider) []string {
- var staticDirs []string
- for i := -1; i <= 10; i++ {
- staticDirs = append(staticDirs, getStringOrStringSlice(cfg, "staticDir", i)...)
- }
- return staticDirs
-}
-
-func getStringOrStringSlice(cfg config.Provider, key string, id int) []string {
- if id >= 0 {
- key = fmt.Sprintf("%s%d", key, id)
- }
-
- return config.GetStringSlicePreserveString(cfg, key)
-}