2019-01-02 06:33:26 -05:00
// Copyright 2019 The Hugo Authors. All rights reserved.
2016-08-05 05:04:52 -04:00
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package hugolib
import (
2018-11-15 03:28:02 -05:00
"os"
"path/filepath"
2017-09-25 02:59:02 -04:00
"strings"
2021-12-12 06:11:11 -05:00
"github.com/gohugoio/hugo/common/hexec"
2020-11-24 08:11:42 -05:00
"github.com/gohugoio/hugo/common/types"
2021-03-21 05:54:30 -04:00
"github.com/gohugoio/hugo/common/maps"
2021-06-18 04:27:27 -04:00
cpaths "github.com/gohugoio/hugo/common/paths"
2021-03-21 05:54:30 -04:00
2020-09-09 10:51:13 -04:00
"github.com/gobwas/glob"
hglob "github.com/gohugoio/hugo/hugofs/glob"
Add Hugo Modules
This commit implements Hugo Modules.
This is a broad subject, but some keywords include:
* A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project.
* A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects.
* Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running.
* Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions.
* A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`.
All of the above is backed by Go Modules.
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
Fixes #6074
Fixes #6082
Fixes #6092
2019-05-03 03:16:58 -04:00
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/cache/filecache"
2018-11-15 03:28:02 -05:00
"github.com/gohugoio/hugo/parser/metadecoders"
2018-10-22 14:20:48 -04:00
2022-05-02 10:07:52 -04:00
"errors"
2018-11-15 03:28:02 -05:00
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/common/hugo"
Add support for theme composition and inheritance
This commit adds support for theme composition and inheritance in Hugo.
With this, it helps thinking about a theme as a set of ordered components:
```toml
theme = ["my-shortcodes", "base-theme", "hyde"]
```
The theme definition example above in `config.toml` creates a theme with the 3 components with presedence from left to right.
So, Hugo will, for any given file, data entry etc., look first in the project, and then in `my-shortcode`, `base-theme` and lastly `hyde`.
Hugo uses two different algorithms to merge the filesystems, depending on the file type:
* For `i18n` and `data` files, Hugo merges deeply using the translation id and data key inside the files.
* For `static`, `layouts` (templates) and `archetypes` files, these are merged on file level. So the left-most file will be chosen.
The name used in the `theme` definition above must match a folder in `/your-site/themes`, e.g. `/your-site/themes/my-shortcodes`. There are plans to improve on this and get a URL scheme so this can be resolved automatically.
Also note that a component that is part of a theme can have its own configuration file, e.g. `config.toml`. There are currently some restrictions to what a theme component can configure:
* `params` (global and per language)
* `menu` (global and per language)
* `outputformats` and `mediatypes`
The same rules apply here: The left-most param/menu etc. with the same ID will win. There are some hidden and experimental namespace support in the above, which we will work to improve in the future, but theme authors are encouraged to create their own namespaces to avoid naming conflicts.
A final note: Themes/components can also have a `theme` definition in their `config.toml` and similar, which is the "inheritance" part of this commit's title. This is currently not supported by the Hugo theme site. We will have to wait for some "auto dependency" feature to be implemented for that to happen, but this can be a powerful feature if you want to create your own theme-variant based on others.
Fixes #4460
Fixes #4450
2018-03-01 09:01:25 -05:00
"github.com/gohugoio/hugo/langs"
Add Hugo Modules
This commit implements Hugo Modules.
This is a broad subject, but some keywords include:
* A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project.
* A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects.
* Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running.
* Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions.
* A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`.
All of the above is backed by Go Modules.
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
Fixes #6074
Fixes #6082
Fixes #6092
2019-05-03 03:16:58 -04:00
"github.com/gohugoio/hugo/modules"
Add support for theme composition and inheritance
This commit adds support for theme composition and inheritance in Hugo.
With this, it helps thinking about a theme as a set of ordered components:
```toml
theme = ["my-shortcodes", "base-theme", "hyde"]
```
The theme definition example above in `config.toml` creates a theme with the 3 components with presedence from left to right.
So, Hugo will, for any given file, data entry etc., look first in the project, and then in `my-shortcode`, `base-theme` and lastly `hyde`.
Hugo uses two different algorithms to merge the filesystems, depending on the file type:
* For `i18n` and `data` files, Hugo merges deeply using the translation id and data key inside the files.
* For `static`, `layouts` (templates) and `archetypes` files, these are merged on file level. So the left-most file will be chosen.
The name used in the `theme` definition above must match a folder in `/your-site/themes`, e.g. `/your-site/themes/my-shortcodes`. There are plans to improve on this and get a URL scheme so this can be resolved automatically.
Also note that a component that is part of a theme can have its own configuration file, e.g. `config.toml`. There are currently some restrictions to what a theme component can configure:
* `params` (global and per language)
* `menu` (global and per language)
* `outputformats` and `mediatypes`
The same rules apply here: The left-most param/menu etc. with the same ID will win. There are some hidden and experimental namespace support in the above, which we will work to improve in the future, but theme authors are encouraged to create their own namespaces to avoid naming conflicts.
A final note: Themes/components can also have a `theme` definition in their `config.toml` and similar, which is the "inheritance" part of this commit's title. This is currently not supported by the Hugo theme site. We will have to wait for some "auto dependency" feature to be implemented for that to happen, but this can be a powerful feature if you want to create your own theme-variant based on others.
Fixes #4460
Fixes #4450
2018-03-01 09:01:25 -05:00
2017-11-02 03:25:20 -04:00
"github.com/gohugoio/hugo/config"
2018-05-22 08:00:36 -04:00
"github.com/gohugoio/hugo/config/privacy"
2021-12-12 06:11:11 -05:00
"github.com/gohugoio/hugo/config/security"
2018-05-22 08:40:06 -04:00
"github.com/gohugoio/hugo/config/services"
2017-06-13 12:42:45 -04:00
"github.com/gohugoio/hugo/helpers"
2017-06-13 13:07:35 -04:00
"github.com/spf13/afero"
2016-08-05 05:04:52 -04:00
)
2021-06-09 04:58:18 -04:00
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" )
2018-05-22 08:40:06 -04:00
2021-06-09 04:58:18 -04:00
// 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
}
2021-06-16 12:58:40 -04:00
if len ( d . Environ ) == 0 && ! hugo . IsRunningAsTest ( ) {
2021-06-09 04:58:18 -04:00
d . Environ = os . Environ ( )
}
var configFiles [ ] string
l := configLoader { ConfigSourceDescriptor : d , cfg : config . New ( ) }
2021-06-27 06:03:43 -04:00
// 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 ( )
2021-06-09 04:58:18 -04:00
2023-01-15 12:45:51 -05:00
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 )
}
2021-06-09 04:58:18 -04:00
}
}
if d . AbsConfigDir != "" {
2023-01-15 12:45:51 -05:00
2021-06-16 13:11:01 -04:00
dcfg , dirnames , err := config . LoadConfigFromDir ( l . Fs , d . AbsConfigDir , l . Environment )
2023-01-15 12:45:51 -05:00
2021-06-09 04:58:18 -04:00
if err == nil {
2021-06-16 13:11:01 -04:00
if len ( dirnames ) > 0 {
l . cfg . Set ( "" , dcfg . Get ( "" ) )
configFiles = append ( configFiles , dirnames ... )
}
2021-06-09 04:58:18 -04:00
} else if err != ErrNoConfigFile {
2021-06-16 13:11:01 -04:00
if len ( dirnames ) > 0 {
return nil , nil , l . wrapFileError ( err , dirnames [ 0 ] )
}
2021-06-09 04:58:18 -04:00
return nil , nil , err
}
}
2021-07-15 09:31:50 -04:00
if err := l . applyConfigDefaults ( ) ; err != nil {
return l . cfg , configFiles , err
}
2021-06-09 04:58:18 -04:00
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 ( )
2018-05-22 08:40:06 -04:00
if err != nil {
2021-06-09 04:58:18 -04:00
return l . cfg , configFiles , err
2018-05-22 08:40:06 -04:00
}
2021-06-09 04:58:18 -04:00
// 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,
2022-03-09 23:01:05 -05:00
// remove it so it doesn't accidentally show up in other settings.
2021-06-27 06:03:43 -04:00
l . deleteMergeStrategies ( )
2021-06-09 04:58:18 -04:00
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
}
2021-08-31 06:08:11 -04:00
_ , modulesConfigFiles , modulesCollectErr := l . collectModules ( modulesConfig , l . cfg , collectHook )
2018-05-22 08:40:06 -04:00
if err != nil {
2021-06-09 04:58:18 -04:00
return l . cfg , configFiles , err
2018-05-22 08:40:06 -04:00
}
2021-06-09 04:58:18 -04:00
configFiles = append ( configFiles , modulesConfigFiles ... )
2018-05-22 08:40:06 -04:00
2021-06-09 04:58:18 -04:00
if err := l . applyOsEnvOverrides ( d . Environ ) ; err != nil {
return l . cfg , configFiles , err
}
if err = l . applyConfigAliases ( ) ; err != nil {
return l . cfg , configFiles , err
}
2021-08-31 06:08:11 -04:00
if err == nil {
err = modulesCollectErr
}
2021-06-09 04:58:18 -04:00
return l . cfg , configFiles , err
}
2023-01-15 12:45:51 -05:00
// LoadConfigDefault is a convenience method to load the default "hugo.toml" config.
2021-06-09 04:58:18 -04:00
func LoadConfigDefault ( fs afero . Fs ) ( config . Provider , error ) {
2023-01-15 12:45:51 -05:00
v , _ , err := LoadConfig ( ConfigSourceDescriptor { Fs : fs } )
2021-06-09 04:58:18 -04:00
return v , err
2018-05-22 08:00:36 -04:00
}
2018-03-18 05:32:29 -04:00
// ConfigSourceDescriptor describes where to find the config (e.g. config.toml etc.).
type ConfigSourceDescriptor struct {
Add Hugo Modules
This commit implements Hugo Modules.
This is a broad subject, but some keywords include:
* A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project.
* A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects.
* Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running.
* Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions.
* A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`.
All of the above is backed by Go Modules.
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
Fixes #6074
Fixes #6082
Fixes #6092
2019-05-03 03:16:58 -04:00
Fs afero . Fs
2020-10-21 05:17:48 -04:00
Logger loggers . Logger
2018-03-18 06:07:24 -04:00
2018-11-15 03:28:02 -05:00
// Path to the config file to use, e.g. /my/project/config.toml
2018-03-18 06:07:24 -04:00
Filename string
// The path to the directory to look for configuration. Is used if Filename is not
2018-11-15 03:28:02 -05:00
// set or if it is set to a relative filename.
2018-03-18 06:07:24 -04:00
Path string
// The project's working dir. Is used to look for additional theme config.
WorkingDir string
2018-11-15 03:28:02 -05:00
// The (optional) directory for additional configuration files.
AbsConfigDir string
// production, development
Environment string
Add Hugo Modules
This commit implements Hugo Modules.
This is a broad subject, but some keywords include:
* A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project.
* A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects.
* Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running.
* Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions.
* A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`.
All of the above is backed by Go Modules.
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
Fixes #6074
Fixes #6082
Fixes #6092
2019-05-03 03:16:58 -04:00
// Defaults to os.Environ if not set.
Environ [ ] string
2018-03-18 05:32:29 -04:00
}
2021-06-09 04:58:18 -04:00
func ( d ConfigSourceDescriptor ) configFileDir ( ) string {
if d . Path != "" {
return d . Path
}
return d . WorkingDir
}
2018-03-18 05:32:29 -04:00
func ( d ConfigSourceDescriptor ) configFilenames ( ) [ ] string {
2018-11-15 03:28:02 -05:00
if d . Filename == "" {
2023-01-15 12:45:51 -05:00
return nil
2018-11-15 03:28:02 -05:00
}
2018-03-18 06:07:24 -04:00
return strings . Split ( d . Filename , "," )
2018-03-18 05:32:29 -04:00
}
2021-06-09 04:58:18 -04:00
// 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
2018-11-15 03:28:02 -05:00
}
2021-06-09 04:58:18 -04:00
type configLoader struct {
cfg config . Provider
ConfigSourceDescriptor
2018-03-18 05:32:29 -04:00
}
2021-06-09 04:58:18 -04:00
// Handle some legacy values.
func ( l configLoader ) applyConfigAliases ( ) error {
aliases := [ ] types . KeyValueStr { { Key : "taxonomies" , Value : "indexes" } }
Add support for theme composition and inheritance
This commit adds support for theme composition and inheritance in Hugo.
With this, it helps thinking about a theme as a set of ordered components:
```toml
theme = ["my-shortcodes", "base-theme", "hyde"]
```
The theme definition example above in `config.toml` creates a theme with the 3 components with presedence from left to right.
So, Hugo will, for any given file, data entry etc., look first in the project, and then in `my-shortcode`, `base-theme` and lastly `hyde`.
Hugo uses two different algorithms to merge the filesystems, depending on the file type:
* For `i18n` and `data` files, Hugo merges deeply using the translation id and data key inside the files.
* For `static`, `layouts` (templates) and `archetypes` files, these are merged on file level. So the left-most file will be chosen.
The name used in the `theme` definition above must match a folder in `/your-site/themes`, e.g. `/your-site/themes/my-shortcodes`. There are plans to improve on this and get a URL scheme so this can be resolved automatically.
Also note that a component that is part of a theme can have its own configuration file, e.g. `config.toml`. There are currently some restrictions to what a theme component can configure:
* `params` (global and per language)
* `menu` (global and per language)
* `outputformats` and `mediatypes`
The same rules apply here: The left-most param/menu etc. with the same ID will win. There are some hidden and experimental namespace support in the above, which we will work to improve in the future, but theme authors are encouraged to create their own namespaces to avoid naming conflicts.
A final note: Themes/components can also have a `theme` definition in their `config.toml` and similar, which is the "inheritance" part of this commit's title. This is currently not supported by the Hugo theme site. We will have to wait for some "auto dependency" feature to be implemented for that to happen, but this can be a powerful feature if you want to create your own theme-variant based on others.
Fixes #4460
Fixes #4450
2018-03-01 09:01:25 -05:00
2021-06-09 04:58:18 -04:00
for _ , alias := range aliases {
if l . cfg . IsSet ( alias . Key ) {
vv := l . cfg . Get ( alias . Key )
l . cfg . Set ( alias . Value , vv )
}
2018-11-15 03:28:02 -05:00
}
2021-06-09 04:58:18 -04:00
return nil
}
Add Hugo Modules
This commit implements Hugo Modules.
This is a broad subject, but some keywords include:
* A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project.
* A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects.
* Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running.
* Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions.
* A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`.
All of the above is backed by Go Modules.
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
Fixes #6074
Fixes #6082
Fixes #6092
2019-05-03 03:16:58 -04:00
2021-06-09 04:58:18 -04:00
func ( l configLoader ) applyConfigDefaults ( ) error {
defaultSettings := maps . Params {
"cleanDestinationDir" : false ,
"watch" : false ,
"resourceDir" : "resources" ,
"publishDir" : "public" ,
2022-12-22 03:43:53 -05:00
"publishDirOrig" : "public" ,
2021-06-09 04:58:18 -04:00
"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" ,
2021-07-03 04:40:59 -04:00
"taxonomies" : maps . Params { "tag" : "tags" , "category" : "categories" } ,
"permalinks" : maps . Params { } ,
"sitemap" : maps . Params { "priority" : - 1 , "filename" : "sitemap.xml" } ,
2021-06-09 04:58:18 -04:00
"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 ,
}
2021-06-22 03:53:37 -04:00
l . cfg . SetDefaults ( defaultSettings )
2018-03-18 06:07:24 -04:00
2021-06-09 04:58:18 -04:00
return nil
}
2018-03-18 05:32:29 -04:00
2021-06-09 04:58:18 -04:00
func ( l configLoader ) applyOsEnvOverrides ( environ [ ] string ) error {
if len ( environ ) == 0 {
return nil
2018-03-18 06:07:24 -04:00
}
2021-06-09 04:58:18 -04:00
const delim = "__env__delim"
2016-08-05 05:04:52 -04:00
2021-06-09 04:58:18 -04:00
// 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 ,
} )
2016-08-05 05:04:52 -04:00
2018-04-07 05:27:22 -04:00
}
}
2021-06-09 04:58:18 -04:00
for _ , env := range hugoEnv {
existing , nestedKey , owner , err := maps . GetNestedParamFn ( env . Key , delim , l . cfg . Get )
if err != nil {
return err
2021-03-21 08:29:11 -04:00
}
2021-03-21 05:54:30 -04:00
2021-06-09 04:58:18 -04:00
if existing != nil {
val , err := metadecoders . Default . UnmarshalStringTo ( env . Value , existing )
2021-03-21 08:29:11 -04:00
if err != nil {
2021-06-09 04:58:18 -04:00
continue
2021-03-21 08:29:11 -04:00
}
2021-06-09 04:58:18 -04:00
if owner != nil {
owner [ nestedKey ] = val
2021-03-21 08:29:11 -04:00
} else {
2021-06-09 04:58:18 -04:00
l . cfg . Set ( env . Key , val )
2021-03-21 05:54:30 -04:00
}
2021-06-09 04:58:18 -04:00
} else if nestedKey != "" {
owner [ nestedKey ] = env . Value
} else {
// The container does not exist yet.
l . cfg . Set ( strings . ReplaceAll ( env . Key , delim , "." ) , env . Value )
2021-03-21 05:54:30 -04:00
}
2021-06-09 04:58:18 -04:00
}
2021-03-21 05:54:30 -04:00
2021-06-09 04:58:18 -04:00
return nil
}
2021-03-21 05:54:30 -04:00
2021-06-09 04:58:18 -04:00
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" )
2021-03-21 05:54:30 -04:00
}
2022-03-21 04:35:15 -04:00
themesDir := cpaths . AbsPathify ( l . WorkingDir , v1 . GetString ( "themesDir" ) )
2021-03-21 05:54:30 -04:00
2021-06-09 04:58:18 -04:00
var ignoreVendor glob . Glob
if s := v1 . GetString ( "ignoreVendorPaths" ) ; s != "" {
ignoreVendor , _ = hglob . GetGlob ( hglob . NormalizePath ( s ) )
2021-03-19 06:05:17 -04:00
}
2021-06-09 04:58:18 -04:00
filecacheConfigs , err := filecache . DecodeConfig ( l . Fs , v1 )
2021-03-19 06:05:17 -04:00
if err != nil {
2021-06-09 04:58:18 -04:00
return nil , nil , err
2021-03-19 06:05:17 -04:00
}
2021-12-12 06:11:11 -05:00
secConfig , err := security . DecodeConfig ( v1 )
if err != nil {
return nil , nil , err
}
ex := hexec . New ( secConfig )
2021-06-09 04:58:18 -04:00
v1 . Set ( "filecacheConfigs" , filecacheConfigs )
2021-03-19 06:05:17 -04:00
2021-06-09 04:58:18 -04:00
var configFilenames [ ] string
2021-03-19 06:05:17 -04:00
2021-06-09 04:58:18 -04:00
hook := func ( m * modules . ModulesConfig ) error {
for _ , tc := range m . ActiveModules {
2021-06-16 13:11:01 -04:00
if len ( tc . ConfigFilenames ( ) ) > 0 {
2021-06-09 04:58:18 -04:00
if tc . Watch ( ) {
2021-06-16 13:11:01 -04:00
configFilenames = append ( configFilenames , tc . ConfigFilenames ( ) ... )
2021-06-09 04:58:18 -04:00
}
// Merge from theme config into v1 based on configured
// merge strategy.
v1 . Merge ( "" , tc . Cfg ( ) . Get ( "" ) )
}
}
if hookBeforeFinalize != nil {
return hookBeforeFinalize ( m )
2021-03-19 06:05:17 -04:00
}
return nil
}
2021-06-09 04:58:18 -04:00
modulesClient := modules . NewClient ( modules . ClientConfig {
Fs : l . Fs ,
Logger : l . Logger ,
2021-12-12 06:11:11 -05:00
Exec : ex ,
2021-06-09 04:58:18 -04:00
HookBeforeFinalize : hook ,
WorkingDir : workingDir ,
ThemesDir : themesDir ,
2021-06-16 13:11:01 -04:00
Environment : l . Environment ,
2021-06-09 04:58:18 -04:00
CacheDir : filecacheConfigs . CacheDirModules ( ) ,
ModuleConfig : modConfig ,
IgnoreVendor : ignoreVendor ,
} )
2021-03-19 06:05:17 -04:00
2021-06-09 04:58:18 -04:00
v1 . Set ( "modulesClient" , modulesClient )
2021-03-19 06:05:17 -04:00
2021-06-09 04:58:18 -04:00
moduleConfig , err := modulesClient . Collect ( )
Add Hugo Modules
This commit implements Hugo Modules.
This is a broad subject, but some keywords include:
* A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project.
* A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects.
* Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running.
* Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions.
* A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`.
All of the above is backed by Go Modules.
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
Fixes #6074
Fixes #6082
Fixes #6092
2019-05-03 03:16:58 -04:00
2021-06-09 04:58:18 -04:00
// Avoid recreating these later.
v1 . Set ( "allModules" , moduleConfig . ActiveModules )
Add Hugo Modules
This commit implements Hugo Modules.
This is a broad subject, but some keywords include:
* A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project.
* A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects.
* Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running.
* Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions.
* A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`.
All of the above is backed by Go Modules.
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
Fixes #6074
Fixes #6082
Fixes #6092
2019-05-03 03:16:58 -04:00
2022-12-19 09:50:53 -05:00
// We want to watch these for changes and trigger rebuild on version
// changes etc.
2021-06-09 04:58:18 -04:00
if moduleConfig . GoModulesFilename != "" {
2022-12-19 09:50:53 -05:00
2021-06-09 04:58:18 -04:00
configFilenames = append ( configFilenames , moduleConfig . GoModulesFilename )
}
2018-11-15 03:28:02 -05:00
2022-12-19 09:50:53 -05:00
if moduleConfig . GoWorkspaceFilename != "" {
configFilenames = append ( configFilenames , moduleConfig . GoWorkspaceFilename )
}
2021-06-09 04:58:18 -04:00
return moduleConfig . ActiveModules , configFilenames , err
2018-11-15 03:28:02 -05:00
}
2021-06-09 04:58:18 -04:00
func ( l configLoader ) loadConfig ( configName string ) ( string , error ) {
2018-11-15 03:28:02 -05:00
baseDir := l . configFileDir ( )
var baseFilename string
if filepath . IsAbs ( configName ) {
baseFilename = configName
} else {
baseFilename = filepath . Join ( baseDir , configName )
}
var filename string
2021-06-18 04:27:27 -04:00
if cpaths . ExtNoDelimiter ( configName ) != "" {
2018-11-15 03:28:02 -05:00
exists , _ := helpers . Exists ( baseFilename , l . Fs )
if exists {
filename = baseFilename
}
} else {
2019-01-31 07:06:18 -05:00
for _ , ext := range config . ValidConfigFileExtensions {
2018-11-15 03:28:02 -05:00
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 {
2022-05-15 15:01:36 -04:00
return filename , err
2018-11-15 03:28:02 -05:00
}
2021-06-09 04:58:18 -04:00
// Set overwrites keys of the same name, recursively.
l . cfg . Set ( "" , m )
2018-11-15 03:28:02 -05:00
return filename , nil
}
2021-06-27 06:03:43 -04:00
func ( l configLoader ) deleteMergeStrategies ( ) {
l . cfg . WalkParams ( func ( params ... config . KeyParams ) bool {
params [ len ( params ) - 1 ] . Params . DeleteMergeStrategy ( )
return false
} )
}
2021-06-09 04:58:18 -04:00
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 )
Add Hugo Modules
This commit implements Hugo Modules.
This is a broad subject, but some keywords include:
* A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project.
* A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects.
* Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running.
* Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions.
* A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`.
All of the above is backed by Go Modules.
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
Fixes #6074
Fixes #6082
Fixes #6092
2019-05-03 03:16:58 -04:00
if err != nil {
return modules . Config { } , err
2017-11-12 04:03:56 -05:00
}
Add Hugo Modules
This commit implements Hugo Modules.
This is a broad subject, but some keywords include:
* A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project.
* A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects.
* Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running.
* Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions.
* A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`.
All of the above is backed by Go Modules.
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
Fixes #6074
Fixes #6082
Fixes #6092
2019-05-03 03:16:58 -04:00
return modConfig , nil
}
2018-01-19 02:24:10 -05:00
2021-06-09 04:58:18 -04:00
func ( configLoader ) loadSiteConfig ( cfg config . Provider ) ( scfg SiteConfig , err error ) {
privacyConfig , err := privacy . DecodeConfig ( cfg )
Add Hugo Modules
This commit implements Hugo Modules.
This is a broad subject, but some keywords include:
* A new `module` configuration section where you can import almost anything. You can configure both your own file mounts nd the file mounts of the modules you import. This is the new recommended way of configuring what you earlier put in `configDir`, `staticDir` etc. And it also allows you to mount folders in non-Hugo-projects, e.g. the `SCSS` folder in the Bootstrap GitHub project.
* A module consists of a set of mounts to the standard 7 component types in Hugo: `static`, `content`, `layouts`, `data`, `assets`, `i18n`, and `archetypes`. Yes, Theme Components can now include content, which should be very useful, especially in bigger multilingual projects.
* Modules not in your local file cache will be downloaded automatically and even "hot replaced" while the server is running.
* Hugo Modules supports and encourages semver versioned modules, and uses the minimal version selection algorithm to resolve versions.
* A new set of CLI commands are provided to manage all of this: `hugo mod init`, `hugo mod get`, `hugo mod graph`, `hugo mod tidy`, and `hugo mod vendor`.
All of the above is backed by Go Modules.
Fixes #5973
Fixes #5996
Fixes #6010
Fixes #5911
Fixes #5940
Fixes #6074
Fixes #6082
Fixes #6092
2019-05-03 03:16:58 -04:00
if err != nil {
2018-03-18 06:07:24 -04:00
return
}
2021-06-09 04:58:18 -04:00
servicesConfig , err := services . DecodeConfig ( cfg )
if err != nil {
2018-03-18 06:07:24 -04:00
return
}
2021-06-09 04:58:18 -04:00
scfg . Privacy = privacyConfig
scfg . Services = servicesConfig
2018-03-18 06:07:24 -04:00
2021-06-09 04:58:18 -04:00
return
2018-03-18 06:07:24 -04:00
}
2021-06-09 04:58:18 -04:00
func ( l configLoader ) wrapFileError ( err error , filename string ) error {
2022-05-15 15:01:36 -04:00
fe := herrors . UnwrapFileError ( err )
if fe != nil {
pos := fe . Position ( )
pos . Filename = filename
fe . UpdatePosition ( pos )
return err
}
2022-05-14 09:51:04 -04:00
return herrors . NewFileErrorFromFile ( err , filename , l . Fs , nil )
2016-08-05 05:04:52 -04:00
}