mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-17 21:01:26 +02:00
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
This commit is contained in:
@@ -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
|
||||
panic(err)
|
||||
}
|
||||
return all.Base
|
||||
}
|
||||
|
||||
// ExampleConfig returns the some example configuration for documentation.
|
||||
func ExampleConfig() (*allconfig.Config, error) {
|
||||
// Apply some example settings for the settings that does not come with a sensible default.
|
||||
configToml := `
|
||||
title = 'My Blog'
|
||||
baseURL = "https://example.com/"
|
||||
disableKinds = ["term", "taxonomy"]
|
||||
|
||||
[outputs]
|
||||
home = ['html', 'html', 'rss']
|
||||
page = ['html']
|
||||
|
||||
[imaging]
|
||||
bgcolor = '#ffffff'
|
||||
hint = 'photo'
|
||||
quality = 81
|
||||
resamplefilter = 'CatmullRom'
|
||||
[imaging.exif]
|
||||
disableDate = true
|
||||
disableLatLong = true
|
||||
excludeFields = 'ColorSpace|Metering'
|
||||
|
||||
[params]
|
||||
color = 'blue'
|
||||
style = 'dark'
|
||||
|
||||
|
||||
[languages]
|
||||
[languages.ar]
|
||||
languagedirection = 'rtl'
|
||||
title = 'مدونتي'
|
||||
weight = 2
|
||||
[languages.en]
|
||||
weight = 1
|
||||
[languages.fr]
|
||||
weight = 2
|
||||
[languages.fr.params]
|
||||
linkedin = 'https://linkedin.com/fr/whoever'
|
||||
color = 'green'
|
||||
[[languages.fr.menus.main]]
|
||||
name = 'Des produits'
|
||||
pageRef = '/products'
|
||||
weight = 20
|
||||
|
||||
[menus]
|
||||
[[menus.main]]
|
||||
name = 'Home'
|
||||
pageRef = '/'
|
||||
weight = 10
|
||||
[[menus.main]]
|
||||
name = 'Products'
|
||||
pageRef = '/products'
|
||||
weight = 20
|
||||
[[menus.main]]
|
||||
name = 'Services'
|
||||
pageRef = '/services'
|
||||
weight = 30
|
||||
|
||||
[deployment]
|
||||
order = [".jpg$", ".gif$"]
|
||||
[[deployment.targets]]
|
||||
name = "mydeployment"
|
||||
url = "s3://mybucket?region=us-east-1"
|
||||
cloudFrontDistributionID = "mydistributionid"
|
||||
[[deployment.matchers]]
|
||||
pattern = "^.+\\.(js|css|svg|ttf)$"
|
||||
cacheControl = "max-age=31536000, no-transform, public"
|
||||
gzip = true
|
||||
[[deployment.matchers]]
|
||||
pattern = "^.+\\.(png|jpg)$"
|
||||
cacheControl = "max-age=31536000, no-transform, public"
|
||||
gzip = false
|
||||
[[deployment.matchers]]
|
||||
pattern = "^sitemap\\.xml$"
|
||||
contentType = "application/xml"
|
||||
gzip = true
|
||||
[[deployment.matchers]]
|
||||
pattern = "^.+\\.(html|xml|json)$"
|
||||
gzip = true
|
||||
|
||||
[permalinks]
|
||||
posts = '/posts/:year/:month/:title/'
|
||||
|
||||
[taxonomies]
|
||||
category = 'categories'
|
||||
series = 'series'
|
||||
tag = 'tags'
|
||||
|
||||
[module]
|
||||
[module.hugoVersion]
|
||||
min = '0.80.0'
|
||||
[[module.imports]]
|
||||
path = "github.com/bep/hugo-mod-misc/dummy-content"
|
||||
ignoreconfig = true
|
||||
ignoreimports = true
|
||||
[[module.mounts]]
|
||||
source = "content/blog"
|
||||
target = "content"
|
||||
|
||||
[minify]
|
||||
[minify.tdewolff]
|
||||
[minify.tdewolff.json]
|
||||
precision = 2
|
||||
|
||||
[[cascade]]
|
||||
background = 'yosemite.jpg'
|
||||
[cascade._target]
|
||||
kind = 'page'
|
||||
path = '/blog/**'
|
||||
[[cascade]]
|
||||
background = 'goldenbridge.jpg'
|
||||
[cascade._target]
|
||||
kind = 'section'
|
||||
|
||||
|
||||
`
|
||||
|
||||
goMod := `
|
||||
module github.com/bep/mymod
|
||||
`
|
||||
|
||||
cfg := config.New()
|
||||
|
||||
tempDir := os.TempDir()
|
||||
cacheDir := filepath.Join(tempDir, "hugocache")
|
||||
if err := os.MkdirAll(cacheDir, 0777); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg.Set("cacheDir", cacheDir)
|
||||
cfg.Set("workingDir", tempDir)
|
||||
defer func() {
|
||||
os.RemoveAll(tempDir)
|
||||
}()
|
||||
|
||||
fs := afero.NewOsFs()
|
||||
|
||||
if err := afero.WriteFile(fs, filepath.Join(tempDir, "hugo.toml"), []byte(configToml), 0644); err != nil {
|
||||
return nil, 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
|
||||
if err := afero.WriteFile(fs, filepath.Join(tempDir, "go.mod"), []byte(goMod), 0644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, modulesConfigFiles, modulesCollectErr := l.collectModules(modulesConfig, l.cfg, collectHook)
|
||||
conf, err := allconfig.LoadConfig(allconfig.ConfigSourceDescriptor{Fs: fs, Flags: cfg})
|
||||
if err != nil {
|
||||
return l.cfg, configFiles, err
|
||||
return nil, err
|
||||
}
|
||||
return conf.Base, err
|
||||
|
||||
configFiles = append(configFiles, modulesConfigFiles...)
|
||||
|
||||
if err := l.applyOsEnvOverrides(d.Environ); err != nil {
|
||||
return l.cfg, configFiles, err
|
||||
}
|
||||
|
||||
if err = l.applyConfigAliases(); err != nil {
|
||||
return l.cfg, configFiles, err
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
err = modulesCollectErr
|
||||
}
|
||||
|
||||
return l.cfg, configFiles, err
|
||||
}
|
||||
|
||||
// LoadConfigDefault is a convenience method to load the default "hugo.toml" config.
|
||||
func LoadConfigDefault(fs afero.Fs) (config.Provider, error) {
|
||||
v, _, err := LoadConfig(ConfigSourceDescriptor{Fs: fs})
|
||||
return v, err
|
||||
}
|
||||
|
||||
// ConfigSourceDescriptor describes where to find the config (e.g. config.toml etc.).
|
||||
type ConfigSourceDescriptor struct {
|
||||
Fs afero.Fs
|
||||
Logger loggers.Logger
|
||||
|
||||
// Path to the config file to use, e.g. /my/project/config.toml
|
||||
Filename string
|
||||
|
||||
// The path to the directory to look for configuration. Is used if Filename is not
|
||||
// set or if it is set to a relative filename.
|
||||
Path string
|
||||
|
||||
// The project's working dir. Is used to look for additional theme config.
|
||||
WorkingDir string
|
||||
|
||||
// The (optional) directory for additional configuration files.
|
||||
AbsConfigDir string
|
||||
|
||||
// production, development
|
||||
Environment string
|
||||
|
||||
// Defaults to os.Environ if not set.
|
||||
Environ []string
|
||||
}
|
||||
|
||||
func (d ConfigSourceDescriptor) configFileDir() string {
|
||||
if d.Path != "" {
|
||||
return d.Path
|
||||
}
|
||||
return d.WorkingDir
|
||||
}
|
||||
|
||||
func (d ConfigSourceDescriptor) configFilenames() []string {
|
||||
if d.Filename == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(d.Filename, ",")
|
||||
}
|
||||
|
||||
// SiteConfig represents the config in .Site.Config.
|
||||
type SiteConfig struct {
|
||||
// This contains all privacy related settings that can be used to
|
||||
// make the YouTube template etc. GDPR compliant.
|
||||
Privacy privacy.Config
|
||||
|
||||
// Services contains config for services such as Google Analytics etc.
|
||||
Services services.Config
|
||||
}
|
||||
|
||||
type configLoader struct {
|
||||
cfg config.Provider
|
||||
ConfigSourceDescriptor
|
||||
}
|
||||
|
||||
// Handle some legacy values.
|
||||
func (l configLoader) applyConfigAliases() error {
|
||||
aliases := []types.KeyValueStr{{Key: "taxonomies", Value: "indexes"}}
|
||||
|
||||
for _, alias := range aliases {
|
||||
if l.cfg.IsSet(alias.Key) {
|
||||
vv := l.cfg.Get(alias.Key)
|
||||
l.cfg.Set(alias.Value, vv)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l configLoader) applyConfigDefaults() error {
|
||||
defaultSettings := maps.Params{
|
||||
"cleanDestinationDir": false,
|
||||
"watch": false,
|
||||
"resourceDir": "resources",
|
||||
"publishDir": "public",
|
||||
"publishDirOrig": "public",
|
||||
"themesDir": "themes",
|
||||
"buildDrafts": false,
|
||||
"buildFuture": false,
|
||||
"buildExpired": false,
|
||||
"environment": hugo.EnvironmentProduction,
|
||||
"uglyURLs": false,
|
||||
"verbose": false,
|
||||
"ignoreCache": false,
|
||||
"canonifyURLs": false,
|
||||
"relativeURLs": false,
|
||||
"removePathAccents": false,
|
||||
"titleCaseStyle": "AP",
|
||||
"taxonomies": maps.Params{"tag": "tags", "category": "categories"},
|
||||
"permalinks": maps.Params{},
|
||||
"sitemap": maps.Params{"priority": -1, "filename": "sitemap.xml"},
|
||||
"disableLiveReload": false,
|
||||
"pluralizeListTitles": true,
|
||||
"forceSyncStatic": false,
|
||||
"footnoteAnchorPrefix": "",
|
||||
"footnoteReturnLinkContents": "",
|
||||
"newContentEditor": "",
|
||||
"paginate": 10,
|
||||
"paginatePath": "page",
|
||||
"summaryLength": 70,
|
||||
"rssLimit": -1,
|
||||
"sectionPagesMenu": "",
|
||||
"disablePathToLower": false,
|
||||
"hasCJKLanguage": false,
|
||||
"enableEmoji": false,
|
||||
"defaultContentLanguage": "en",
|
||||
"defaultContentLanguageInSubdir": false,
|
||||
"enableMissingTranslationPlaceholders": false,
|
||||
"enableGitInfo": false,
|
||||
"ignoreFiles": make([]string, 0),
|
||||
"disableAliases": false,
|
||||
"debug": false,
|
||||
"disableFastRender": false,
|
||||
"timeout": "30s",
|
||||
"enableInlineShortcodes": false,
|
||||
}
|
||||
|
||||
l.cfg.SetDefaults(defaultSettings)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l configLoader) applyOsEnvOverrides(environ []string) error {
|
||||
if len(environ) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
const delim = "__env__delim"
|
||||
|
||||
// Extract all that start with the HUGO prefix.
|
||||
// The delimiter is the following rune, usually "_".
|
||||
const hugoEnvPrefix = "HUGO"
|
||||
var hugoEnv []types.KeyValueStr
|
||||
for _, v := range environ {
|
||||
key, val := config.SplitEnvVar(v)
|
||||
if strings.HasPrefix(key, hugoEnvPrefix) {
|
||||
delimiterAndKey := strings.TrimPrefix(key, hugoEnvPrefix)
|
||||
if len(delimiterAndKey) < 2 {
|
||||
continue
|
||||
}
|
||||
// Allow delimiters to be case sensitive.
|
||||
// It turns out there isn't that many allowed special
|
||||
// chars in environment variables when used in Bash and similar,
|
||||
// so variables on the form HUGOxPARAMSxFOO=bar is one option.
|
||||
key := strings.ReplaceAll(delimiterAndKey[1:], delimiterAndKey[:1], delim)
|
||||
key = strings.ToLower(key)
|
||||
hugoEnv = append(hugoEnv, types.KeyValueStr{
|
||||
Key: key,
|
||||
Value: val,
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for _, env := range hugoEnv {
|
||||
existing, nestedKey, owner, err := maps.GetNestedParamFn(env.Key, delim, l.cfg.Get)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if existing != nil {
|
||||
val, err := metadecoders.Default.UnmarshalStringTo(env.Value, existing)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if owner != nil {
|
||||
owner[nestedKey] = val
|
||||
} else {
|
||||
l.cfg.Set(env.Key, val)
|
||||
}
|
||||
} else if nestedKey != "" {
|
||||
owner[nestedKey] = env.Value
|
||||
} else {
|
||||
// The container does not exist yet.
|
||||
l.cfg.Set(strings.ReplaceAll(env.Key, delim, "."), env.Value)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l configLoader) collectModules(modConfig modules.Config, v1 config.Provider, hookBeforeFinalize func(m *modules.ModulesConfig) error) (modules.Modules, []string, error) {
|
||||
workingDir := l.WorkingDir
|
||||
if workingDir == "" {
|
||||
workingDir = v1.GetString("workingDir")
|
||||
}
|
||||
|
||||
themesDir := cpaths.AbsPathify(l.WorkingDir, v1.GetString("themesDir"))
|
||||
|
||||
var ignoreVendor glob.Glob
|
||||
if s := v1.GetString("ignoreVendorPaths"); s != "" {
|
||||
ignoreVendor, _ = hglob.GetGlob(hglob.NormalizePath(s))
|
||||
}
|
||||
|
||||
filecacheConfigs, err := filecache.DecodeConfig(l.Fs, v1)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
secConfig, err := security.DecodeConfig(v1)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ex := hexec.New(secConfig)
|
||||
|
||||
v1.Set("filecacheConfigs", filecacheConfigs)
|
||||
|
||||
var configFilenames []string
|
||||
|
||||
hook := func(m *modules.ModulesConfig) error {
|
||||
for _, tc := range m.ActiveModules {
|
||||
if len(tc.ConfigFilenames()) > 0 {
|
||||
if tc.Watch() {
|
||||
configFilenames = append(configFilenames, tc.ConfigFilenames()...)
|
||||
}
|
||||
|
||||
// Merge from theme config into v1 based on configured
|
||||
// merge strategy.
|
||||
v1.Merge("", tc.Cfg().Get(""))
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if hookBeforeFinalize != nil {
|
||||
return hookBeforeFinalize(m)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
modulesClient := modules.NewClient(modules.ClientConfig{
|
||||
Fs: l.Fs,
|
||||
Logger: l.Logger,
|
||||
Exec: ex,
|
||||
HookBeforeFinalize: hook,
|
||||
WorkingDir: workingDir,
|
||||
ThemesDir: themesDir,
|
||||
Environment: l.Environment,
|
||||
CacheDir: filecacheConfigs.CacheDirModules(),
|
||||
ModuleConfig: modConfig,
|
||||
IgnoreVendor: ignoreVendor,
|
||||
})
|
||||
|
||||
v1.Set("modulesClient", modulesClient)
|
||||
|
||||
moduleConfig, err := modulesClient.Collect()
|
||||
|
||||
// Avoid recreating these later.
|
||||
v1.Set("allModules", moduleConfig.ActiveModules)
|
||||
|
||||
// We want to watch these for changes and trigger rebuild on version
|
||||
// changes etc.
|
||||
if moduleConfig.GoModulesFilename != "" {
|
||||
|
||||
configFilenames = append(configFilenames, moduleConfig.GoModulesFilename)
|
||||
}
|
||||
|
||||
if moduleConfig.GoWorkspaceFilename != "" {
|
||||
configFilenames = append(configFilenames, moduleConfig.GoWorkspaceFilename)
|
||||
|
||||
}
|
||||
|
||||
return moduleConfig.ActiveModules, configFilenames, err
|
||||
}
|
||||
|
||||
func (l configLoader) loadConfig(configName string) (string, error) {
|
||||
baseDir := l.configFileDir()
|
||||
var baseFilename string
|
||||
if filepath.IsAbs(configName) {
|
||||
baseFilename = configName
|
||||
} else {
|
||||
baseFilename = filepath.Join(baseDir, configName)
|
||||
}
|
||||
|
||||
var filename string
|
||||
if cpaths.ExtNoDelimiter(configName) != "" {
|
||||
exists, _ := helpers.Exists(baseFilename, l.Fs)
|
||||
if exists {
|
||||
filename = baseFilename
|
||||
}
|
||||
} else {
|
||||
for _, ext := range config.ValidConfigFileExtensions {
|
||||
filenameToCheck := baseFilename + "." + ext
|
||||
exists, _ := helpers.Exists(filenameToCheck, l.Fs)
|
||||
if exists {
|
||||
filename = filenameToCheck
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if filename == "" {
|
||||
return "", ErrNoConfigFile
|
||||
}
|
||||
|
||||
m, err := config.FromFileToMap(l.Fs, filename)
|
||||
if err != nil {
|
||||
return filename, err
|
||||
}
|
||||
|
||||
// Set overwrites keys of the same name, recursively.
|
||||
l.cfg.Set("", m)
|
||||
|
||||
return filename, nil
|
||||
}
|
||||
|
||||
func (l configLoader) deleteMergeStrategies() {
|
||||
l.cfg.WalkParams(func(params ...config.KeyParams) bool {
|
||||
params[len(params)-1].Params.DeleteMergeStrategy()
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func (l configLoader) loadLanguageSettings(oldLangs langs.Languages) error {
|
||||
_, err := langs.LoadLanguageSettings(l.cfg, oldLangs)
|
||||
return err
|
||||
}
|
||||
|
||||
func (l configLoader) loadModulesConfig() (modules.Config, error) {
|
||||
modConfig, err := modules.DecodeConfig(l.cfg)
|
||||
if err != nil {
|
||||
return modules.Config{}, err
|
||||
}
|
||||
|
||||
return modConfig, nil
|
||||
}
|
||||
|
||||
func (configLoader) loadSiteConfig(cfg config.Provider) (scfg SiteConfig, err error) {
|
||||
privacyConfig, err := privacy.DecodeConfig(cfg)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
servicesConfig, err := services.DecodeConfig(cfg)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
scfg.Privacy = privacyConfig
|
||||
scfg.Services = servicesConfig
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (l configLoader) wrapFileError(err error, filename string) error {
|
||||
fe := herrors.UnwrapFileError(err)
|
||||
if fe != nil {
|
||||
pos := fe.Position()
|
||||
pos.Filename = filename
|
||||
fe.UpdatePosition(pos)
|
||||
return err
|
||||
}
|
||||
return herrors.NewFileErrorFromFile(err, filename, l.Fs, nil)
|
||||
}
|
||||
|
Reference in New Issue
Block a user