mirror of
https://github.com/gohugoio/hugo.git
synced 2026-08-25 15:58:53 +00:00
Compare commits
91 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a663b1938 | |||
| e08d9af21e | |||
| cd7dc7a372 | |||
| c939c33fd3 | |||
| bb7b3d3cdb | |||
| 873a5cda1a | |||
| f42a4b6af5 | |||
| a5637831cd | |||
| 68586c891c | |||
| 51bb2fedab | |||
| 43307b07f8 | |||
| 346b60358d | |||
| 7f0f50b133 | |||
| 77a8e347bc | |||
| f704d75699 | |||
| 9d765e1b99 | |||
| 1f746a8724 | |||
| 6aa72acaf9 | |||
| 9885e7020d | |||
| 91101d24f2 | |||
| 637995ba8f | |||
| f1de5d2a04 | |||
| 4b0c194fb3 | |||
| 8de4ffb294 | |||
| 1f5a15aba0 | |||
| 8897113666 | |||
| e91d3cff98 | |||
| e7bd51698e | |||
| 1fad3832a9 | |||
| 8b52626915 | |||
| 81a7b63900 | |||
| 5c5508817f | |||
| 88ecc3b753 | |||
| 1191467c05 | |||
| 60c24fc5ee | |||
| 41137077bc | |||
| 5bb1564575 | |||
| 76993369a0 | |||
| de7137cc35 | |||
| a2edf04c27 | |||
| 956f915f77 | |||
| a2a4166f6d | |||
| 39f582f9f4 | |||
| 2501de7aab | |||
| 06cc8673fa | |||
| 71fae99189 | |||
| 8af04745fb | |||
| dde9d9d544 | |||
| 892b49110e | |||
| c5a63a3b4f | |||
| 61d3d20129 | |||
| b13d0a68e6 | |||
| d9594a96fc | |||
| 4a5cc2dd26 | |||
| 9cad8d38ca | |||
| cfa0801815 | |||
| f024a5050e | |||
| 80704bc9a1 | |||
| 3682027a51 | |||
| 44628616af | |||
| 0fc86783ee | |||
| e9fbadacc3 | |||
| 2a7bb1c7c9 | |||
| b7b49fb0f8 | |||
| 5f2adad2c7 | |||
| a837976731 | |||
| 0918e087ec | |||
| 4ea94c451d | |||
| 5d2cbee989 | |||
| 723e3f4342 | |||
| d913f46a8b | |||
| 2db43f841c | |||
| 46ce1f191b | |||
| aae02ca612 | |||
| 83cec785cf | |||
| 4e52be8b90 | |||
| 7888ac585c | |||
| eb1dbe0709 | |||
| 77824d704c | |||
| ec0caaec7c | |||
| 845b8885de | |||
| 43385d6aeb | |||
| a9b0b95ef4 | |||
| e229f4b387 | |||
| 020253904f | |||
| 4a5e94087b | |||
| 48a7aee961 | |||
| 6c583e3227 | |||
| 5d64b492f4 | |||
| b3f32949cb | |||
| 55ecd3a90e |
@@ -4,7 +4,7 @@ parameters:
|
||||
defaults: &defaults
|
||||
resource_class: large
|
||||
docker:
|
||||
- image: bepsays/ci-hugoreleaser:1.22300.20400
|
||||
- image: bepsays/ci-hugoreleaser:1.22301.20401
|
||||
environment: &buildenv
|
||||
GOMODCACHE: /root/project/gomodcache
|
||||
version: 2
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
environment:
|
||||
<<: [*buildenv]
|
||||
docker:
|
||||
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22300.20400
|
||||
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22301.20401
|
||||
steps:
|
||||
- *restore-cache
|
||||
- &attach-workspace
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
imports.*
|
||||
dist/
|
||||
public/
|
||||
.DS_Store
|
||||
@@ -66,8 +66,6 @@ See the [features] section of the documentation for a comprehensive summary of H
|
||||
<p float="left">
|
||||
<a href="https://www.linode.com/?utm_campaign=hugosponsor&utm_medium=banner&utm_source=hugogithub" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/linode-logo_standard_light_medium.png" width="200" alt="Linode"></a>
|
||||
|
||||
<a href="https://route4me.com/" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/Route4MeLogoBlueOnWhite.svg" width="200" alt="Route Planning & Route Optimization Software"></a>
|
||||
|
||||
<a href="https://www.jetbrains.com/go/?utm_source=OSS&utm_medium=referral&utm_campaign=hugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/goland.svg" width="200" alt="The complete IDE crafted for professional Go developers."></a>
|
||||
</p>
|
||||
|
||||
@@ -103,6 +101,7 @@ Build the extended edition:
|
||||
```text
|
||||
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@latest
|
||||
```
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#gohugoio/hugo&Timeline)
|
||||
@@ -156,7 +155,7 @@ github.com/bep/clocks="v0.5.0"
|
||||
github.com/bep/debounce="v1.2.0"
|
||||
github.com/bep/gitmap="v1.6.0"
|
||||
github.com/bep/goat="v0.5.0"
|
||||
github.com/bep/godartsass/v2="v2.3.0"
|
||||
github.com/bep/godartsass/v2="v2.3.2"
|
||||
github.com/bep/golibsass="v1.2.0"
|
||||
github.com/bep/gowebp="v0.3.0"
|
||||
github.com/bep/imagemeta="v0.8.3"
|
||||
@@ -191,7 +190,7 @@ github.com/gohugoio/locales="v0.14.0"
|
||||
github.com/gohugoio/localescompressed="v1.0.1"
|
||||
github.com/google/go-cmp="v0.6.0"
|
||||
github.com/gorilla/websocket="v1.5.3"
|
||||
github.com/hairyhenderson/go-codeowners="v0.6.1"
|
||||
github.com/hairyhenderson/go-codeowners="v0.7.0"
|
||||
github.com/hashicorp/golang-lru/v2="v2.0.7"
|
||||
github.com/invopop/yaml="v0.2.0"
|
||||
github.com/jdkato/prose="v1.2.1"
|
||||
@@ -220,30 +219,32 @@ github.com/russross/blackfriday/v2="v2.1.0"
|
||||
github.com/sass/dart-sass/compiler="1.81.0"
|
||||
github.com/sass/dart-sass/implementation="1.81.0"
|
||||
github.com/sass/dart-sass/protocol="3.1.0"
|
||||
github.com/sass/libsass="3.6.6"
|
||||
github.com/spf13/afero="v1.11.0"
|
||||
github.com/spf13/cast="v1.7.0"
|
||||
github.com/spf13/cast="v1.7.1"
|
||||
github.com/spf13/cobra="v1.8.1"
|
||||
github.com/spf13/fsync="v0.10.1"
|
||||
github.com/spf13/pflag="v1.0.5"
|
||||
github.com/tdewolff/minify/v2="v2.21.1"
|
||||
github.com/tdewolff/parse/v2="v2.7.18"
|
||||
github.com/tetratelabs/wazero="v1.8.1"
|
||||
github.com/tdewolff/minify/v2="v2.20.37"
|
||||
github.com/tdewolff/parse/v2="v2.7.15"
|
||||
github.com/tetratelabs/wazero="v1.8.2"
|
||||
github.com/webmproject/libwebp="v1.3.2"
|
||||
github.com/yuin/goldmark-emoji="v1.0.4"
|
||||
github.com/yuin/goldmark="v1.7.8"
|
||||
go.uber.org/automaxprocs="v1.5.3"
|
||||
golang.org/x/crypto="v0.29.0"
|
||||
golang.org/x/crypto="v0.31.0"
|
||||
golang.org/x/exp="v0.0.0-20221031165847-c99f073a8326"
|
||||
golang.org/x/image="v0.22.0"
|
||||
golang.org/x/mod="v0.22.0"
|
||||
golang.org/x/net="v0.31.0"
|
||||
golang.org/x/sync="v0.9.0"
|
||||
golang.org/x/sys="v0.27.0"
|
||||
golang.org/x/text="v0.20.0"
|
||||
golang.org/x/tools="v0.27.0"
|
||||
google.golang.org/protobuf="v1.35.1"
|
||||
golang.org/x/net="v0.33.0"
|
||||
golang.org/x/sync="v0.10.0"
|
||||
golang.org/x/sys="v0.28.0"
|
||||
golang.org/x/text="v0.21.0"
|
||||
golang.org/x/tools="v0.28.0"
|
||||
google.golang.org/protobuf="v1.35.2"
|
||||
gopkg.in/yaml.v2="v2.4.0"
|
||||
gopkg.in/yaml.v3="v3.0.1"
|
||||
howett.net/plist="v1.0.0"
|
||||
rsc.io/qr="v0.2.0"
|
||||
software.sslmate.com/src/go-pkcs12="v0.2.0"
|
||||
```
|
||||
</details>
|
||||
|
||||
@@ -447,6 +447,8 @@ func (r *rootCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Set up the global logger early to allow info deprecations during config load.
|
||||
loggers.InitGlobalLogger(r.logger.Level(), false)
|
||||
|
||||
r.changesFromBuild = make(chan []identity.Identity, 10)
|
||||
|
||||
@@ -538,6 +540,7 @@ Complete documentation is available at https://gohugo.io/.`
|
||||
cmd.PersistentFlags().StringP("themesDir", "", "", "filesystem path to themes directory")
|
||||
_ = cmd.MarkFlagDirname("themesDir")
|
||||
cmd.PersistentFlags().StringP("ignoreVendorPaths", "", "", "ignores any _vendor for module paths matching the given Glob pattern")
|
||||
cmd.PersistentFlags().BoolP("noBuildLock", "", false, "don't create .hugo_build.lock file")
|
||||
_ = cmd.RegisterFlagCompletionFunc("ignoreVendorPaths", cobra.NoFileCompletions)
|
||||
cmd.PersistentFlags().String("clock", "", "set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00")
|
||||
_ = cmd.RegisterFlagCompletionFunc("clock", cobra.NoFileCompletions)
|
||||
@@ -593,7 +596,6 @@ func applyLocalFlagsBuild(cmd *cobra.Command, r *rootCommand) {
|
||||
cmd.Flags().BoolVar(&r.forceSyncStatic, "forceSyncStatic", false, "copy all files when static is changed.")
|
||||
cmd.Flags().BoolP("noTimes", "", false, "don't sync modification time of files")
|
||||
cmd.Flags().BoolP("noChmod", "", false, "don't sync permission mode of files")
|
||||
cmd.Flags().BoolP("noBuildLock", "", false, "don't create .hugo_build.lock file")
|
||||
cmd.Flags().BoolP("printI18nWarnings", "", false, "print missing translations")
|
||||
cmd.Flags().BoolP("printPathWarnings", "", false, "print warnings on duplicate target paths etc.")
|
||||
cmd.Flags().BoolP("printUnusedTemplates", "", false, "print warnings on unused templates.")
|
||||
|
||||
+5
-3
@@ -43,8 +43,9 @@ func newConfigCommand() *configCommand {
|
||||
type configCommand struct {
|
||||
r *rootCommand
|
||||
|
||||
format string
|
||||
lang string
|
||||
format string
|
||||
lang string
|
||||
printZero bool
|
||||
|
||||
commands []simplecobra.Commander
|
||||
}
|
||||
@@ -78,7 +79,7 @@ func (c *configCommand) Run(ctx context.Context, cd *simplecobra.Commandeer, arg
|
||||
dec.SetIndent("", " ")
|
||||
dec.SetEscapeHTML(false)
|
||||
|
||||
if err := dec.Encode(parser.ReplacingJSONMarshaller{Value: config, KeysToLower: true, OmitEmpty: true}); err != nil {
|
||||
if err := dec.Encode(parser.ReplacingJSONMarshaller{Value: config, KeysToLower: true, OmitEmpty: !c.printZero}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -115,6 +116,7 @@ func (c *configCommand) Init(cd *simplecobra.Commandeer) error {
|
||||
cmd.Flags().StringVar(&c.format, "format", "toml", "preferred file format (toml, yaml or json)")
|
||||
_ = cmd.RegisterFlagCompletionFunc("format", cobra.FixedCompletions([]string{"toml", "yaml", "json"}, cobra.ShellCompDirectiveNoFileComp))
|
||||
cmd.Flags().StringVar(&c.lang, "lang", "", "the language to display config for. Defaults to the first language defined.")
|
||||
cmd.Flags().BoolVar(&c.printZero, "printZero", false, `include config options with zero values (e.g. false, 0, "") in the output`)
|
||||
_ = cmd.RegisterFlagCompletionFunc("lang", cobra.NoFileCompletions)
|
||||
applyLocalFlagsBuildConfig(cmd, c.r)
|
||||
|
||||
|
||||
+3
-1
@@ -75,7 +75,9 @@ See https://xyproto.github.io/splash/docs/all.html for a preview of the availabl
|
||||
return err
|
||||
}
|
||||
formatter := html.New(html.WithAllClasses(true))
|
||||
formatter.WriteCSS(os.Stdout, style)
|
||||
w := os.Stdout
|
||||
fmt.Fprintf(w, "/* Generated using: hugo %s */\n\n", strings.Join(os.Args[1:], " "))
|
||||
formatter.WriteCSS(w, style)
|
||||
return nil
|
||||
},
|
||||
withc: func(cmd *cobra.Command, r *rootCommand) {
|
||||
|
||||
@@ -62,7 +62,7 @@ type hugoBuilder struct {
|
||||
|
||||
// Currently only set when in "fast render mode".
|
||||
changeDetector *fileChangeDetector
|
||||
visitedURLs *types.EvictingStringQueue
|
||||
visitedURLs *types.EvictingQueue[string]
|
||||
|
||||
fullRebuildSem *semaphore.Weighted
|
||||
debounce func(f func())
|
||||
@@ -1103,7 +1103,7 @@ func (c *hugoBuilder) rebuildSites(events []fsnotify.Event) (err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = h.Build(hugolib.BuildCfg{NoBuildLock: true, RecentlyVisited: c.visitedURLs, ErrRecovery: c.errState.wasErr()}, events...)
|
||||
err = h.Build(hugolib.BuildCfg{NoBuildLock: true, RecentlyTouched: c.visitedURLs, ErrRecovery: c.errState.wasErr()}, events...)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1119,7 +1119,7 @@ func (c *hugoBuilder) rebuildSitesForChanges(ids []identity.Identity) (err error
|
||||
}
|
||||
whatChanged := &hugolib.WhatChanged{}
|
||||
whatChanged.Add(ids...)
|
||||
err = h.Build(hugolib.BuildCfg{NoBuildLock: true, WhatChanged: whatChanged, RecentlyVisited: c.visitedURLs, ErrRecovery: c.errState.wasErr()})
|
||||
err = h.Build(hugolib.BuildCfg{NoBuildLock: true, WhatChanged: whatChanged, RecentlyTouched: c.visitedURLs, ErrRecovery: c.errState.wasErr()})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
+8
-5
@@ -85,9 +85,9 @@ const (
|
||||
)
|
||||
|
||||
func newHugoBuilder(r *rootCommand, s *serverCommand, onConfigLoaded ...func(reloaded bool) error) *hugoBuilder {
|
||||
var visitedURLs *types.EvictingStringQueue
|
||||
var visitedURLs *types.EvictingQueue[string]
|
||||
if s != nil && !s.disableFastRender {
|
||||
visitedURLs = types.NewEvictingStringQueue(20)
|
||||
visitedURLs = types.NewEvictingQueue[string](20)
|
||||
}
|
||||
return &hugoBuilder{
|
||||
r: r,
|
||||
@@ -364,7 +364,10 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, net.Listener, string
|
||||
}
|
||||
|
||||
if f.c.fastRenderMode && f.c.errState.buildErr() == nil {
|
||||
if strings.HasSuffix(requestURI, "/") || strings.HasSuffix(requestURI, "html") || strings.HasSuffix(requestURI, "htm") {
|
||||
// Sec-Fetch-Mode should be sent by all recent browser versions, see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-Fetch-Mode#navigate
|
||||
// Fall back to the file extension if not set.
|
||||
// The main take here is that we don't want to have CSS/JS files etc. partake in this logic.
|
||||
if r.Header.Get("Sec-Fetch-Mode") == "navigate" || strings.HasSuffix(requestURI, "/") || strings.HasSuffix(requestURI, "html") || strings.HasSuffix(requestURI, "htm") {
|
||||
if !f.c.visitedURLs.Contains(requestURI) {
|
||||
// If not already on stack, re-render that single page.
|
||||
if err := f.c.partialReRender(requestURI); err != nil {
|
||||
@@ -838,7 +841,7 @@ func (c *serverCommand) partialReRender(urls ...string) (err error) {
|
||||
defer func() {
|
||||
c.errState.setWasErr(false)
|
||||
}()
|
||||
visited := types.NewEvictingStringQueue(len(urls))
|
||||
visited := types.NewEvictingQueue[string](len(urls))
|
||||
for _, url := range urls {
|
||||
visited.Add(url)
|
||||
}
|
||||
@@ -850,7 +853,7 @@ func (c *serverCommand) partialReRender(urls ...string) (err error) {
|
||||
}
|
||||
|
||||
// Note: We do not set NoBuildLock as the file lock is not acquired at this stage.
|
||||
err = h.Build(hugolib.BuildCfg{NoBuildLock: false, RecentlyVisited: visited, PartialReRender: true, ErrRecovery: c.errState.wasErr()})
|
||||
err = h.Build(hugolib.BuildCfg{NoBuildLock: false, RecentlyTouched: visited, PartialReRender: true, ErrRecovery: c.errState.wasErr()})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -38,6 +38,19 @@ func XXHashFromReader(r io.Reader) (uint64, int64, error) {
|
||||
return h.Sum64(), size, nil
|
||||
}
|
||||
|
||||
// XxHashFromReaderHexEncoded calculates the xxHash for the given reader
|
||||
// and returns the hash as a hex encoded string.
|
||||
func XxHashFromReaderHexEncoded(r io.Reader) (string, error) {
|
||||
h := getXxHashReadFrom()
|
||||
defer putXxHashReadFrom(h)
|
||||
_, err := io.Copy(h, r)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
hash := h.Sum(nil)
|
||||
return hex.EncodeToString(hash), nil
|
||||
}
|
||||
|
||||
// XXHashFromString calculates the xxHash for the given string.
|
||||
func XXHashFromString(s string) (uint64, error) {
|
||||
h := xxhash.New()
|
||||
@@ -70,6 +83,13 @@ func HashString(vs ...any) string {
|
||||
return strconv.FormatUint(hash, 10)
|
||||
}
|
||||
|
||||
// HashStringHex returns a hash from the given elements as a hex encoded string.
|
||||
// See HashString for more information.
|
||||
func HashStringHex(vs ...any) string {
|
||||
hash := HashUint64(vs...)
|
||||
return strconv.FormatUint(hash, 16)
|
||||
}
|
||||
|
||||
var hashOptsPool = sync.Pool{
|
||||
New: func() any {
|
||||
return &hashstructure.HashOptions{
|
||||
@@ -103,16 +123,24 @@ func HashUint64(vs ...any) uint64 {
|
||||
o = elements
|
||||
}
|
||||
|
||||
hashOpts := getHashOpts()
|
||||
defer putHashOpts(hashOpts)
|
||||
|
||||
hash, err := hashstructure.Hash(o, hashOpts)
|
||||
hash, err := Hash(o)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return hash
|
||||
}
|
||||
|
||||
// Hash returns a hash from vs.
|
||||
func Hash(vs ...any) (uint64, error) {
|
||||
hashOpts := getHashOpts()
|
||||
defer putHashOpts(hashOpts)
|
||||
var v any = vs
|
||||
if len(vs) == 1 {
|
||||
v = vs[0]
|
||||
}
|
||||
return hashstructure.Hash(v, hashOpts)
|
||||
}
|
||||
|
||||
type keyer interface {
|
||||
Key() string
|
||||
}
|
||||
|
||||
@@ -142,3 +142,16 @@ func BenchmarkHashString(b *testing.B) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHashMap(b *testing.B) {
|
||||
m := map[string]interface{}{}
|
||||
for i := 0; i < 1000; i++ {
|
||||
m[fmt.Sprintf("key%d", i)] = i
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
HashString(m)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,8 +258,27 @@ func openFile(filename string, fs afero.Fs) (afero.File, string, error) {
|
||||
return f, realFilename, nil
|
||||
}
|
||||
|
||||
// Cause returns the underlying error or itself if it does not implement Unwrap.
|
||||
// Cause returns the underlying error, that is,
|
||||
// it unwraps errors until it finds one that does not implement
|
||||
// the Unwrap method.
|
||||
// For a shallow variant, see Unwrap.
|
||||
func Cause(err error) error {
|
||||
type unwrapper interface {
|
||||
Unwrap() error
|
||||
}
|
||||
|
||||
for err != nil {
|
||||
cause, ok := err.(unwrapper)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
err = cause.Unwrap()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Unwrap returns the underlying error or itself if it does not implement Unwrap.
|
||||
func Unwrap(err error) error {
|
||||
if u := errors.Unwrap(err); u != nil {
|
||||
return u
|
||||
}
|
||||
@@ -267,7 +286,7 @@ func Cause(err error) error {
|
||||
}
|
||||
|
||||
func extractFileTypePos(err error) (string, text.Position) {
|
||||
err = Cause(err)
|
||||
err = Unwrap(err)
|
||||
|
||||
var fileType string
|
||||
|
||||
|
||||
+85
-17
@@ -26,7 +26,10 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/cli/safeexec"
|
||||
"github.com/gohugoio/hugo/common/loggers"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/config/security"
|
||||
)
|
||||
@@ -86,7 +89,7 @@ var WithEnviron = func(env []string) func(c *commandeer) {
|
||||
}
|
||||
|
||||
// New creates a new Exec using the provided security config.
|
||||
func New(cfg security.Config, workingDir string) *Exec {
|
||||
func New(cfg security.Config, workingDir string, log loggers.Logger) *Exec {
|
||||
var baseEnviron []string
|
||||
for _, v := range os.Environ() {
|
||||
k, _ := config.SplitEnvVar(v)
|
||||
@@ -96,9 +99,11 @@ func New(cfg security.Config, workingDir string) *Exec {
|
||||
}
|
||||
|
||||
return &Exec{
|
||||
sc: cfg,
|
||||
workingDir: workingDir,
|
||||
baseEnviron: baseEnviron,
|
||||
sc: cfg,
|
||||
workingDir: workingDir,
|
||||
infol: log.InfoCommand("exec"),
|
||||
baseEnviron: baseEnviron,
|
||||
newNPXRunnerCache: maps.NewCache[string, func(arg ...any) (Runner, error)](),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,12 +129,14 @@ func SafeCommand(name string, arg ...string) (*exec.Cmd, error) {
|
||||
type Exec struct {
|
||||
sc security.Config
|
||||
workingDir string
|
||||
infol logg.LevelLogger
|
||||
|
||||
// os.Environ filtered by the Exec.OsEnviron whitelist filter.
|
||||
baseEnviron []string
|
||||
|
||||
npxInit sync.Once
|
||||
npxAvailable bool
|
||||
newNPXRunnerCache *maps.Cache[string, func(arg ...any) (Runner, error)]
|
||||
npxInit sync.Once
|
||||
npxAvailable bool
|
||||
}
|
||||
|
||||
func (e *Exec) New(name string, arg ...any) (Runner, error) {
|
||||
@@ -155,25 +162,86 @@ func (e *Exec) new(name string, fullyQualifiedName string, arg ...any) (Runner,
|
||||
return cm.command(arg...)
|
||||
}
|
||||
|
||||
type binaryLocation int
|
||||
|
||||
func (b binaryLocation) String() string {
|
||||
switch b {
|
||||
case binaryLocationNodeModules:
|
||||
return "node_modules/.bin"
|
||||
case binaryLocationNpx:
|
||||
return "npx"
|
||||
case binaryLocationPath:
|
||||
return "PATH"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
const (
|
||||
binaryLocationNodeModules binaryLocation = iota + 1
|
||||
binaryLocationNpx
|
||||
binaryLocationPath
|
||||
)
|
||||
|
||||
// Npx will in order:
|
||||
// 1. Try fo find the binary in the WORKINGDIR/node_modules/.bin directory.
|
||||
// 2. If not found, and npx is available, run npx --no-install <name> <args>.
|
||||
// 3. Fall back to the PATH.
|
||||
// If name is "tailwindcss", we will try the PATH as the second option.
|
||||
func (e *Exec) Npx(name string, arg ...any) (Runner, error) {
|
||||
// npx is slow, so first try the common case.
|
||||
nodeBinFilename := filepath.Join(e.workingDir, nodeModulesBinPath, name)
|
||||
_, err := safeexec.LookPath(nodeBinFilename)
|
||||
if err == nil {
|
||||
return e.new(name, nodeBinFilename, arg...)
|
||||
if err := e.sc.CheckAllowedExec(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
e.checkNpx()
|
||||
if e.npxAvailable {
|
||||
r, err := e.npx(name, arg...)
|
||||
if err == nil {
|
||||
return r, nil
|
||||
|
||||
newRunner, err := e.newNPXRunnerCache.GetOrCreate(name, func() (func(...any) (Runner, error), error) {
|
||||
type tryFunc func() func(...any) (Runner, error)
|
||||
tryFuncs := map[binaryLocation]tryFunc{
|
||||
binaryLocationNodeModules: func() func(...any) (Runner, error) {
|
||||
nodeBinFilename := filepath.Join(e.workingDir, nodeModulesBinPath, name)
|
||||
_, err := safeexec.LookPath(nodeBinFilename)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return func(arg2 ...any) (Runner, error) {
|
||||
return e.new(name, nodeBinFilename, arg2...)
|
||||
}
|
||||
},
|
||||
binaryLocationNpx: func() func(...any) (Runner, error) {
|
||||
e.checkNpx()
|
||||
if !e.npxAvailable {
|
||||
return nil
|
||||
}
|
||||
return func(arg2 ...any) (Runner, error) {
|
||||
return e.npx(name, arg2...)
|
||||
}
|
||||
},
|
||||
binaryLocationPath: func() func(...any) (Runner, error) {
|
||||
if _, err := safeexec.LookPath(name); err != nil {
|
||||
return nil
|
||||
}
|
||||
return func(arg2 ...any) (Runner, error) {
|
||||
return e.New(name, arg2...)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
locations := []binaryLocation{binaryLocationNodeModules, binaryLocationNpx, binaryLocationPath}
|
||||
if name == "tailwindcss" {
|
||||
// See https://github.com/gohugoio/hugo/issues/13221#issuecomment-2574801253
|
||||
locations = []binaryLocation{binaryLocationNodeModules, binaryLocationPath, binaryLocationNpx}
|
||||
}
|
||||
for _, loc := range locations {
|
||||
if f := tryFuncs[loc](); f != nil {
|
||||
e.infol.Logf("resolve %q using %s", name, loc)
|
||||
return f, nil
|
||||
}
|
||||
}
|
||||
return nil, &NotFoundError{name: name, method: fmt.Sprintf("in %s", locations[len(locations)-1])}
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return e.New(name, arg...)
|
||||
|
||||
return newRunner(arg...)
|
||||
}
|
||||
|
||||
const (
|
||||
|
||||
@@ -48,16 +48,16 @@ func TestHasBytesWriter(t *testing.T) {
|
||||
|
||||
for i := 0; i < 22; i++ {
|
||||
h, w := neww()
|
||||
fmt.Fprintf(w, rndStr()+"abc __foobar"+rndStr())
|
||||
fmt.Fprint(w, rndStr()+"abc __foobar"+rndStr())
|
||||
c.Assert(h.Patterns[0].Match, qt.Equals, true)
|
||||
|
||||
h, w = neww()
|
||||
fmt.Fprintf(w, rndStr()+"abc __f")
|
||||
fmt.Fprintf(w, "oo bar"+rndStr())
|
||||
fmt.Fprint(w, rndStr()+"abc __f")
|
||||
fmt.Fprint(w, "oo bar"+rndStr())
|
||||
c.Assert(h.Patterns[0].Match, qt.Equals, true)
|
||||
|
||||
h, w = neww()
|
||||
fmt.Fprintf(w, rndStr()+"abc __moo bar")
|
||||
fmt.Fprint(w, rndStr()+"abc __moo bar")
|
||||
c.Assert(h.Patterns[0].Match, qt.Equals, false)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -423,7 +423,7 @@ func DeprecateLevel(item, alternative, version string, level logg.Level) {
|
||||
msg = fmt.Sprintf("%s was deprecated in Hugo %s and will be removed in a future release. %s", item, version, alternative)
|
||||
}
|
||||
|
||||
loggers.Log().Logger().WithLevel(level).WithField(loggers.FieldNameCmd, "deprecated").Logf(msg)
|
||||
loggers.Log().Logger().WithLevel(level).WithField(loggers.FieldNameCmd, "deprecated").Logf("%s", msg)
|
||||
}
|
||||
|
||||
// We usually do about one minor version a month.
|
||||
|
||||
@@ -17,7 +17,7 @@ package hugo
|
||||
// This should be the only one.
|
||||
var CurrentVersion = Version{
|
||||
Major: 0,
|
||||
Minor: 140,
|
||||
Minor: 143,
|
||||
PatchLevel: 0,
|
||||
Suffix: "",
|
||||
Suffix: "-DEV",
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ func (l *logAdapter) PrintTimerIfDelayed(start time.Time, name string) {
|
||||
if milli < 500 {
|
||||
return
|
||||
}
|
||||
l.Printf("%s in %v ms", name, milli)
|
||||
fmt.Fprintf(l.stdErr, "%s in %v ms", name, milli)
|
||||
}
|
||||
|
||||
func (l *logAdapter) Printf(format string, v ...any) {
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
// Copyright 2024 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.
|
||||
// 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 maps
|
||||
|
||||
import (
|
||||
"github.com/gohugoio/hugo/common/hashing"
|
||||
)
|
||||
|
||||
// Ordered is a map that can be iterated in the order of insertion.
|
||||
// Note that insertion order is not affected if a key is re-inserted into the map.
|
||||
// In a nil map, all operations are no-ops.
|
||||
// This is not thread safe.
|
||||
type Ordered[K comparable, T any] struct {
|
||||
// The keys in the order they were added.
|
||||
keys []K
|
||||
// The values.
|
||||
values map[K]T
|
||||
}
|
||||
|
||||
// NewOrdered creates a new Ordered map.
|
||||
func NewOrdered[K comparable, T any]() *Ordered[K, T] {
|
||||
return &Ordered[K, T]{values: make(map[K]T)}
|
||||
}
|
||||
|
||||
// Set sets the value for the given key.
|
||||
// Note that insertion order is not affected if a key is re-inserted into the map.
|
||||
func (m *Ordered[K, T]) Set(key K, value T) {
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
// Check if key already exists.
|
||||
if _, found := m.values[key]; !found {
|
||||
m.keys = append(m.keys, key)
|
||||
}
|
||||
m.values[key] = value
|
||||
}
|
||||
|
||||
// Get gets the value for the given key.
|
||||
func (m *Ordered[K, T]) Get(key K) (T, bool) {
|
||||
if m == nil {
|
||||
var v T
|
||||
return v, false
|
||||
}
|
||||
value, found := m.values[key]
|
||||
return value, found
|
||||
}
|
||||
|
||||
// Delete deletes the value for the given key.
|
||||
func (m *Ordered[K, T]) Delete(key K) {
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
delete(m.values, key)
|
||||
for i, k := range m.keys {
|
||||
if k == key {
|
||||
m.keys = append(m.keys[:i], m.keys[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Clone creates a shallow copy of the map.
|
||||
func (m *Ordered[K, T]) Clone() *Ordered[K, T] {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
clone := NewOrdered[K, T]()
|
||||
for _, k := range m.keys {
|
||||
clone.Set(k, m.values[k])
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
// Keys returns the keys in the order they were added.
|
||||
func (m *Ordered[K, T]) Keys() []K {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
return m.keys
|
||||
}
|
||||
|
||||
// Values returns the values in the order they were added.
|
||||
func (m *Ordered[K, T]) Values() []T {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
var values []T
|
||||
for _, k := range m.keys {
|
||||
values = append(values, m.values[k])
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// Len returns the number of items in the map.
|
||||
func (m *Ordered[K, T]) Len() int {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
return len(m.keys)
|
||||
}
|
||||
|
||||
// Range calls f sequentially for each key and value present in the map.
|
||||
// If f returns false, range stops the iteration.
|
||||
// TODO(bep) replace with iter.Seq2 when we bump go Go 1.24.
|
||||
func (m *Ordered[K, T]) Range(f func(key K, value T) bool) {
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
for _, k := range m.keys {
|
||||
if !f(k, m.values[k]) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hash calculates a hash from the values.
|
||||
func (m *Ordered[K, T]) Hash() (uint64, error) {
|
||||
if m == nil {
|
||||
return 0, nil
|
||||
}
|
||||
return hashing.Hash(m.values)
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// Copyright 2024 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.
|
||||
// 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 maps
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
qt "github.com/frankban/quicktest"
|
||||
)
|
||||
|
||||
func TestOrdered(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
m := NewOrdered[string, int]()
|
||||
m.Set("a", 1)
|
||||
m.Set("b", 2)
|
||||
m.Set("c", 3)
|
||||
|
||||
c.Assert(m.Keys(), qt.DeepEquals, []string{"a", "b", "c"})
|
||||
c.Assert(m.Values(), qt.DeepEquals, []int{1, 2, 3})
|
||||
|
||||
v, found := m.Get("b")
|
||||
c.Assert(found, qt.Equals, true)
|
||||
c.Assert(v, qt.Equals, 2)
|
||||
|
||||
m.Set("b", 22)
|
||||
c.Assert(m.Keys(), qt.DeepEquals, []string{"a", "b", "c"})
|
||||
c.Assert(m.Values(), qt.DeepEquals, []int{1, 22, 3})
|
||||
|
||||
m.Delete("b")
|
||||
|
||||
c.Assert(m.Keys(), qt.DeepEquals, []string{"a", "c"})
|
||||
c.Assert(m.Values(), qt.DeepEquals, []int{1, 3})
|
||||
}
|
||||
|
||||
func TestOrderedHash(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
m := NewOrdered[string, int]()
|
||||
m.Set("a", 1)
|
||||
m.Set("b", 2)
|
||||
m.Set("c", 3)
|
||||
|
||||
h1, err := m.Hash()
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
m.Set("d", 4)
|
||||
|
||||
h2, err := m.Hash()
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
c.Assert(h1, qt.Not(qt.Equals), h2)
|
||||
|
||||
m = NewOrdered[string, int]()
|
||||
m.Set("b", 2)
|
||||
m.Set("a", 1)
|
||||
m.Set("c", 3)
|
||||
|
||||
h3, err := m.Hash()
|
||||
c.Assert(err, qt.IsNil)
|
||||
// Order does not matter.
|
||||
c.Assert(h1, qt.Equals, h3)
|
||||
}
|
||||
|
||||
func TestOrderedNil(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
var m *Ordered[string, int]
|
||||
|
||||
m.Set("a", 1)
|
||||
c.Assert(m.Keys(), qt.IsNil)
|
||||
c.Assert(m.Values(), qt.IsNil)
|
||||
v, found := m.Get("a")
|
||||
c.Assert(found, qt.Equals, false)
|
||||
c.Assert(v, qt.Equals, 0)
|
||||
m.Delete("a")
|
||||
var b bool
|
||||
m.Range(func(k string, v int) bool {
|
||||
b = true
|
||||
return true
|
||||
})
|
||||
c.Assert(b, qt.Equals, false)
|
||||
c.Assert(m.Len(), qt.Equals, 0)
|
||||
c.Assert(m.Clone(), qt.IsNil)
|
||||
h, err := m.Hash()
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(h, qt.Equals, uint64(0))
|
||||
}
|
||||
+1
-1
@@ -228,7 +228,7 @@ func UrlFromFilename(filename string) (*url.URL, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// UrlToFilename converts the URL s to a filename.
|
||||
// UrlStringToFilename converts the URL s to a filename.
|
||||
// If ParseRequestURI fails, the input is just converted to OS specific slashes and returned.
|
||||
func UrlStringToFilename(s string) (string, bool) {
|
||||
u, err := url.ParseRequestURI(s)
|
||||
|
||||
@@ -18,24 +18,24 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// EvictingStringQueue is a queue which automatically evicts elements from the head of
|
||||
// EvictingQueue is a queue which automatically evicts elements from the head of
|
||||
// the queue when attempting to add new elements onto the queue and it is full.
|
||||
// This queue orders elements LIFO (last-in-first-out). It throws away duplicates.
|
||||
// Note: This queue currently does not contain any remove (poll etc.) methods.
|
||||
type EvictingStringQueue struct {
|
||||
type EvictingQueue[T comparable] struct {
|
||||
size int
|
||||
vals []string
|
||||
set map[string]bool
|
||||
vals []T
|
||||
set map[T]bool
|
||||
mu sync.Mutex
|
||||
zero T
|
||||
}
|
||||
|
||||
// NewEvictingStringQueue creates a new queue with the given size.
|
||||
func NewEvictingStringQueue(size int) *EvictingStringQueue {
|
||||
return &EvictingStringQueue{size: size, set: make(map[string]bool)}
|
||||
// NewEvictingQueue creates a new queue with the given size.
|
||||
func NewEvictingQueue[T comparable](size int) *EvictingQueue[T] {
|
||||
return &EvictingQueue[T]{size: size, set: make(map[T]bool)}
|
||||
}
|
||||
|
||||
// Add adds a new string to the tail of the queue if it's not already there.
|
||||
func (q *EvictingStringQueue) Add(v string) *EvictingStringQueue {
|
||||
func (q *EvictingQueue[T]) Add(v T) *EvictingQueue[T] {
|
||||
q.mu.Lock()
|
||||
if q.set[v] {
|
||||
q.mu.Unlock()
|
||||
@@ -54,7 +54,7 @@ func (q *EvictingStringQueue) Add(v string) *EvictingStringQueue {
|
||||
return q
|
||||
}
|
||||
|
||||
func (q *EvictingStringQueue) Len() int {
|
||||
func (q *EvictingQueue[T]) Len() int {
|
||||
if q == nil {
|
||||
return 0
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func (q *EvictingStringQueue) Len() int {
|
||||
}
|
||||
|
||||
// Contains returns whether the queue contains v.
|
||||
func (q *EvictingStringQueue) Contains(v string) bool {
|
||||
func (q *EvictingQueue[T]) Contains(v T) bool {
|
||||
if q == nil {
|
||||
return false
|
||||
}
|
||||
@@ -74,12 +74,12 @@ func (q *EvictingStringQueue) Contains(v string) bool {
|
||||
}
|
||||
|
||||
// Peek looks at the last element added to the queue.
|
||||
func (q *EvictingStringQueue) Peek() string {
|
||||
func (q *EvictingQueue[T]) Peek() T {
|
||||
q.mu.Lock()
|
||||
l := len(q.vals)
|
||||
if l == 0 {
|
||||
q.mu.Unlock()
|
||||
return ""
|
||||
return q.zero
|
||||
}
|
||||
elem := q.vals[l-1]
|
||||
q.mu.Unlock()
|
||||
@@ -87,9 +87,12 @@ func (q *EvictingStringQueue) Peek() string {
|
||||
}
|
||||
|
||||
// PeekAll looks at all the elements in the queue, with the newest first.
|
||||
func (q *EvictingStringQueue) PeekAll() []string {
|
||||
func (q *EvictingQueue[T]) PeekAll() []T {
|
||||
if q == nil {
|
||||
return nil
|
||||
}
|
||||
q.mu.Lock()
|
||||
vals := make([]string, len(q.vals))
|
||||
vals := make([]T, len(q.vals))
|
||||
copy(vals, q.vals)
|
||||
q.mu.Unlock()
|
||||
for i, j := 0, len(vals)-1; i < j; i, j = i+1, j-1 {
|
||||
@@ -99,9 +102,9 @@ func (q *EvictingStringQueue) PeekAll() []string {
|
||||
}
|
||||
|
||||
// PeekAllSet returns PeekAll as a set.
|
||||
func (q *EvictingStringQueue) PeekAllSet() map[string]bool {
|
||||
func (q *EvictingQueue[T]) PeekAllSet() map[T]bool {
|
||||
all := q.PeekAll()
|
||||
set := make(map[string]bool)
|
||||
set := make(map[T]bool)
|
||||
for _, v := range all {
|
||||
set[v] = true
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
func TestEvictingStringQueue(t *testing.T) {
|
||||
c := qt.New(t)
|
||||
|
||||
queue := NewEvictingStringQueue(3)
|
||||
queue := NewEvictingQueue[string](3)
|
||||
|
||||
c.Assert(queue.Peek(), qt.Equals, "")
|
||||
queue.Add("a")
|
||||
@@ -53,7 +53,7 @@ func TestEvictingStringQueueConcurrent(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
val := "someval"
|
||||
|
||||
queue := NewEvictingStringQueue(3)
|
||||
queue := NewEvictingQueue[string](3)
|
||||
|
||||
for j := 0; j < 100; j++ {
|
||||
wg.Add(1)
|
||||
|
||||
@@ -133,22 +133,3 @@ func NewBool(b bool) *bool {
|
||||
type PrintableValueProvider interface {
|
||||
PrintableValue() any
|
||||
}
|
||||
|
||||
var _ PrintableValueProvider = Result[any]{}
|
||||
|
||||
// Result is a generic result type.
|
||||
type Result[T any] struct {
|
||||
// The result value.
|
||||
Value T
|
||||
|
||||
// The error value.
|
||||
Err error
|
||||
}
|
||||
|
||||
// PrintableValue returns the value or panics if there is an error.
|
||||
func (r Result[T]) PrintableValue() any {
|
||||
if r.Err != nil {
|
||||
panic(r.Err)
|
||||
}
|
||||
return r.Value
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ type Config struct {
|
||||
|
||||
// The cascade configuration section contains the top level front matter cascade configuration options,
|
||||
// a slice of page matcher and params to apply to those pages.
|
||||
Cascade *config.ConfigNamespace[[]page.PageMatcherParamsConfig, map[page.PageMatcher]maps.Params] `mapstructure:"-"`
|
||||
Cascade *config.ConfigNamespace[[]page.PageMatcherParamsConfig, *maps.Ordered[page.PageMatcher, maps.Params]] `mapstructure:"-"`
|
||||
|
||||
// The segments defines segments for the site. Used for partial/segmented builds.
|
||||
Segments *config.ConfigNamespace[map[string]segments.SegmentConfig, segments.Segments] `mapstructure:"-"`
|
||||
@@ -301,6 +301,18 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
|
||||
}
|
||||
}
|
||||
|
||||
defaultOutputFormat := outputFormats[0]
|
||||
c.DefaultOutputFormat = strings.ToLower(c.DefaultOutputFormat)
|
||||
if c.DefaultOutputFormat != "" {
|
||||
f, found := outputFormats.GetByName(c.DefaultOutputFormat)
|
||||
if !found {
|
||||
return fmt.Errorf("unknown default output format %q", c.DefaultOutputFormat)
|
||||
}
|
||||
defaultOutputFormat = f
|
||||
} else {
|
||||
c.DefaultOutputFormat = defaultOutputFormat.Name
|
||||
}
|
||||
|
||||
disabledLangs := make(map[string]bool)
|
||||
for _, lang := range c.DisableLanguages {
|
||||
disabledLangs[lang] = true
|
||||
@@ -390,23 +402,46 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
|
||||
c.Pagination.Path = c.PaginatePath
|
||||
}
|
||||
|
||||
// Legacy privacy values.
|
||||
if c.Privacy.Twitter.Disable {
|
||||
hugo.Deprecate("site config key privacy.twitter.disable", "Use privacy.x.disable instead.", "v0.141.0")
|
||||
c.Privacy.X.Disable = c.Privacy.Twitter.Disable
|
||||
}
|
||||
|
||||
if c.Privacy.Twitter.EnableDNT {
|
||||
hugo.Deprecate("site config key privacy.twitter.enableDNT", "Use privacy.x.enableDNT instead.", "v0.141.0")
|
||||
c.Privacy.X.EnableDNT = c.Privacy.Twitter.EnableDNT
|
||||
}
|
||||
|
||||
if c.Privacy.Twitter.Simple {
|
||||
hugo.Deprecate("site config key privacy.twitter.simple", "Use privacy.x.simple instead.", "v0.141.0")
|
||||
c.Privacy.X.Simple = c.Privacy.Twitter.Simple
|
||||
}
|
||||
|
||||
// Legacy services values.
|
||||
if c.Services.Twitter.DisableInlineCSS {
|
||||
hugo.Deprecate("site config key services.twitter.disableInlineCSS", "Use services.x.disableInlineCSS instead.", "v0.141.0")
|
||||
c.Services.X.DisableInlineCSS = c.Services.Twitter.DisableInlineCSS
|
||||
}
|
||||
|
||||
c.C = &ConfigCompiled{
|
||||
Timeout: timeout,
|
||||
BaseURL: baseURL,
|
||||
BaseURLLiveReload: baseURL,
|
||||
DisabledKinds: disabledKinds,
|
||||
DisabledLanguages: disabledLangs,
|
||||
IgnoredLogs: ignoredLogIDs,
|
||||
KindOutputFormats: kindOutputFormats,
|
||||
ContentTypes: media.DefaultContentTypes.FromTypes(c.MediaTypes.Config),
|
||||
CreateTitle: helpers.GetTitleFunc(c.TitleCaseStyle),
|
||||
IsUglyURLSection: isUglyURL,
|
||||
IgnoreFile: ignoreFile,
|
||||
SegmentFilter: c.Segments.Config.Get(func(s string) { logger.Warnf("Render segment %q not found in configuration", s) }, c.RootConfig.RenderSegments...),
|
||||
MainSections: c.MainSections,
|
||||
Clock: clock,
|
||||
HTTPCache: httpCache,
|
||||
transientErr: transientErr,
|
||||
Timeout: timeout,
|
||||
BaseURL: baseURL,
|
||||
BaseURLLiveReload: baseURL,
|
||||
DisabledKinds: disabledKinds,
|
||||
DisabledLanguages: disabledLangs,
|
||||
IgnoredLogs: ignoredLogIDs,
|
||||
KindOutputFormats: kindOutputFormats,
|
||||
DefaultOutputFormat: defaultOutputFormat,
|
||||
ContentTypes: media.DefaultContentTypes.FromTypes(c.MediaTypes.Config),
|
||||
CreateTitle: helpers.GetTitleFunc(c.TitleCaseStyle),
|
||||
IsUglyURLSection: isUglyURL,
|
||||
IgnoreFile: ignoreFile,
|
||||
SegmentFilter: c.Segments.Config.Get(func(s string) { logger.Warnf("Render segment %q not found in configuration", s) }, c.RootConfig.RenderSegments...),
|
||||
MainSections: c.MainSections,
|
||||
Clock: clock,
|
||||
HTTPCache: httpCache,
|
||||
transientErr: transientErr,
|
||||
}
|
||||
|
||||
for _, s := range allDecoderSetups {
|
||||
@@ -430,22 +465,23 @@ func (c *Config) IsLangDisabled(lang string) bool {
|
||||
|
||||
// ConfigCompiled holds values and functions that are derived from the config.
|
||||
type ConfigCompiled struct {
|
||||
Timeout time.Duration
|
||||
BaseURL urls.BaseURL
|
||||
BaseURLLiveReload urls.BaseURL
|
||||
ServerInterface string
|
||||
KindOutputFormats map[string]output.Formats
|
||||
ContentTypes media.ContentTypes
|
||||
DisabledKinds map[string]bool
|
||||
DisabledLanguages map[string]bool
|
||||
IgnoredLogs map[string]bool
|
||||
CreateTitle func(s string) string
|
||||
IsUglyURLSection func(section string) bool
|
||||
IgnoreFile func(filename string) bool
|
||||
SegmentFilter segments.SegmentFilter
|
||||
MainSections []string
|
||||
Clock time.Time
|
||||
HTTPCache httpcache.ConfigCompiled
|
||||
Timeout time.Duration
|
||||
BaseURL urls.BaseURL
|
||||
BaseURLLiveReload urls.BaseURL
|
||||
ServerInterface string
|
||||
KindOutputFormats map[string]output.Formats
|
||||
DefaultOutputFormat output.Format
|
||||
ContentTypes media.ContentTypes
|
||||
DisabledKinds map[string]bool
|
||||
DisabledLanguages map[string]bool
|
||||
IgnoredLogs map[string]bool
|
||||
CreateTitle func(s string) string
|
||||
IsUglyURLSection func(section string) bool
|
||||
IgnoreFile func(filename string) bool
|
||||
SegmentFilter segments.SegmentFilter
|
||||
MainSections []string
|
||||
Clock time.Time
|
||||
HTTPCache httpcache.ConfigCompiled
|
||||
|
||||
// This is set to the last transient error found during config compilation.
|
||||
// With themes/modules we compute the configuration in multiple passes, and
|
||||
@@ -505,6 +541,10 @@ type RootConfig struct {
|
||||
// Set this to true to put all languages below their language ID.
|
||||
DefaultContentLanguageInSubdir bool
|
||||
|
||||
// The default output format to use for the site.
|
||||
// If not set, we will use the first output format.
|
||||
DefaultOutputFormat string
|
||||
|
||||
// Disable generation of redirect to the default language when DefaultContentLanguageInSubdir is enabled.
|
||||
DisableDefaultLanguageRedirect bool
|
||||
|
||||
@@ -726,15 +766,16 @@ type Configs struct {
|
||||
}
|
||||
|
||||
func (c *Configs) Validate(logger loggers.Logger) error {
|
||||
for p := range c.Base.Cascade.Config {
|
||||
c.Base.Cascade.Config.Range(func(p page.PageMatcher, params maps.Params) bool {
|
||||
page.CheckCascadePattern(logger, p)
|
||||
}
|
||||
return true
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
// transientErr returns the last transient error found during config compilation.
|
||||
func (c *Configs) transientErr() error {
|
||||
for _, l := range c.LanguageConfigSlice {
|
||||
for _, l := range c.LanguageConfigMap {
|
||||
if l.C.transientErr != nil {
|
||||
return l.C.transientErr
|
||||
}
|
||||
@@ -751,7 +792,6 @@ func (c *Configs) Init() error {
|
||||
var languages langs.Languages
|
||||
defaultContentLanguage := c.Base.DefaultContentLanguage
|
||||
for k, v := range c.LanguageConfigMap {
|
||||
c.LanguageConfigSlice = append(c.LanguageConfigSlice, v)
|
||||
languageConf := v.Languages[k]
|
||||
language, err := langs.NewLanguage(k, defaultContentLanguage, v.TimeZone, languageConf)
|
||||
if err != nil {
|
||||
|
||||
@@ -175,3 +175,43 @@ func TestMapUglyURLs(t *testing.T) {
|
||||
b.Assert(c.C.IsUglyURLSection("posts"), qt.IsTrue)
|
||||
b.Assert(c.C.IsUglyURLSection("blog"), qt.IsFalse)
|
||||
}
|
||||
|
||||
// Issue 13199
|
||||
func TestInvalidOutputFormat(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
||||
[outputs]
|
||||
home = ['html','foo']
|
||||
-- layouts/index.html --
|
||||
x
|
||||
`
|
||||
|
||||
b, err := hugolib.TestE(t, files)
|
||||
b.Assert(err, qt.IsNotNil)
|
||||
b.Assert(err.Error(), qt.Contains, `failed to create config: unknown output format "foo" for kind "home"`)
|
||||
}
|
||||
|
||||
// Issue 13201
|
||||
func TestLanguageConfigSlice(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
||||
[languages.en]
|
||||
title = 'TITLE_EN'
|
||||
weight = 2
|
||||
[languages.de]
|
||||
title = 'TITLE_DE'
|
||||
weight = 1
|
||||
[languages.fr]
|
||||
title = 'TITLE_FR'
|
||||
weight = 3
|
||||
`
|
||||
|
||||
b := hugolib.Test(t, files)
|
||||
b.Assert(b.H.Configs.LanguageConfigSlice[0].Title, qt.Equals, `TITLE_DE`)
|
||||
}
|
||||
|
||||
@@ -470,7 +470,7 @@ func (l *configLoader) loadModules(configs *Configs, ignoreModuleDoesNotExist bo
|
||||
ignoreVendor, _ = hglob.GetGlob(hglob.NormalizePath(s))
|
||||
}
|
||||
|
||||
ex := hexec.New(conf.Security, workingDir)
|
||||
ex := hexec.New(conf.Security, workingDir, l.Logger)
|
||||
|
||||
hook := func(m *modules.ModulesConfig) error {
|
||||
for _, tc := range m.AllModules {
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ import (
|
||||
func DecodeNamespace[S, C any](configSource any, buildConfig func(any) (C, any, error)) (*ConfigNamespace[S, C], error) {
|
||||
// Calculate the hash of the input (not including any defaults applied later).
|
||||
// This allows us to introduce new config options without breaking the hash.
|
||||
h := hashing.HashString(configSource)
|
||||
h := hashing.HashStringHex(configSource)
|
||||
|
||||
// Build the config
|
||||
c, ext, err := buildConfig(configSource)
|
||||
|
||||
@@ -43,7 +43,7 @@ func TestNamespace(t *testing.T) {
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(ns, qt.Not(qt.IsNil))
|
||||
c.Assert(ns.SourceStructure, qt.DeepEquals, map[string]interface{}{"foo": "bar"})
|
||||
c.Assert(ns.SourceHash, qt.Equals, "1450430416588600409")
|
||||
c.Assert(ns.SourceHash, qt.Equals, "1420f6c7782f7459")
|
||||
c.Assert(ns.Config, qt.DeepEquals, &tstNsExt{Foo: "bar"})
|
||||
c.Assert(ns.Signature(), qt.DeepEquals, []*tstNsExt(nil))
|
||||
}
|
||||
|
||||
@@ -30,9 +30,10 @@ type Config struct {
|
||||
Disqus Disqus
|
||||
GoogleAnalytics GoogleAnalytics
|
||||
Instagram Instagram
|
||||
Twitter Twitter
|
||||
Twitter Twitter // deprecated in favor of X in v0.141.0
|
||||
Vimeo Vimeo
|
||||
YouTube YouTube
|
||||
X X
|
||||
}
|
||||
|
||||
// Disqus holds the privacy configuration settings related to the Disqus template.
|
||||
@@ -58,7 +59,8 @@ type Instagram struct {
|
||||
Simple bool
|
||||
}
|
||||
|
||||
// Twitter holds the privacy configuration settingsrelated to the Twitter shortcode.
|
||||
// Twitter holds the privacy configuration settings related to the Twitter shortcode.
|
||||
// Deprecated in favor of X in v0.141.0.
|
||||
type Twitter struct {
|
||||
Service `mapstructure:",squash"`
|
||||
|
||||
@@ -70,7 +72,7 @@ type Twitter struct {
|
||||
Simple bool
|
||||
}
|
||||
|
||||
// Vimeo holds the privacy configuration settingsrelated to the Vimeo shortcode.
|
||||
// Vimeo holds the privacy configuration settings related to the Vimeo shortcode.
|
||||
type Vimeo struct {
|
||||
Service `mapstructure:",squash"`
|
||||
|
||||
@@ -84,7 +86,7 @@ type Vimeo struct {
|
||||
Simple bool
|
||||
}
|
||||
|
||||
// YouTube holds the privacy configuration settingsrelated to the YouTube shortcode.
|
||||
// YouTube holds the privacy configuration settings related to the YouTube shortcode.
|
||||
type YouTube struct {
|
||||
Service `mapstructure:",squash"`
|
||||
|
||||
@@ -94,6 +96,20 @@ type YouTube struct {
|
||||
PrivacyEnhanced bool
|
||||
}
|
||||
|
||||
// X holds the privacy configuration settings related to the X shortcode.
|
||||
type X struct {
|
||||
Service `mapstructure:",squash"`
|
||||
|
||||
// When set to true, the X post and its embedded page on your site are not
|
||||
// used for purposes that include personalized suggestions and personalized
|
||||
// ads.
|
||||
EnableDNT bool
|
||||
|
||||
// If simple mode is enabled, a static and no-JS version of the X post will
|
||||
// be built.
|
||||
Simple bool
|
||||
}
|
||||
|
||||
// DecodeConfig creates a privacy Config from a given Hugo configuration.
|
||||
func DecodeConfig(cfg config.Provider) (pc Config, err error) {
|
||||
if !cfg.IsSet(privacyConfigKey) {
|
||||
|
||||
@@ -40,6 +40,10 @@ simple = true
|
||||
disable = true
|
||||
enableDNT = true
|
||||
simple = true
|
||||
[privacy.x]
|
||||
disable = true
|
||||
enableDNT = true
|
||||
simple = true
|
||||
[privacy.vimeo]
|
||||
disable = true
|
||||
enableDNT = true
|
||||
@@ -61,7 +65,8 @@ simple = true
|
||||
pc.GoogleAnalytics.RespectDoNotTrack, pc.Instagram.Disable,
|
||||
pc.Instagram.Simple, pc.Twitter.Disable, pc.Twitter.EnableDNT,
|
||||
pc.Twitter.Simple, pc.Vimeo.Disable, pc.Vimeo.EnableDNT, pc.Vimeo.Simple,
|
||||
pc.YouTube.PrivacyEnhanced, pc.YouTube.Disable,
|
||||
pc.YouTube.PrivacyEnhanced, pc.YouTube.Disable, pc.X.Disable, pc.X.EnableDNT,
|
||||
pc.X.Simple,
|
||||
}
|
||||
|
||||
c.Assert(got, qt.All(qt.Equals), true)
|
||||
|
||||
@@ -31,7 +31,8 @@ type Config struct {
|
||||
Disqus Disqus
|
||||
GoogleAnalytics GoogleAnalytics
|
||||
Instagram Instagram
|
||||
Twitter Twitter
|
||||
Twitter Twitter // deprecated in favor of X in v0.141.0
|
||||
X X
|
||||
RSS RSS
|
||||
}
|
||||
|
||||
@@ -61,6 +62,7 @@ type Instagram struct {
|
||||
}
|
||||
|
||||
// Twitter holds the functional configuration settings related to the Twitter shortcodes.
|
||||
// Deprecated in favor of X in v0.141.0.
|
||||
type Twitter struct {
|
||||
// The Simple variant of Twitter is decorated with a basic set of inline styles.
|
||||
// This means that if you want to provide your own CSS, you want
|
||||
@@ -68,6 +70,14 @@ type Twitter struct {
|
||||
DisableInlineCSS bool
|
||||
}
|
||||
|
||||
// X holds the functional configuration settings related to the X shortcodes.
|
||||
type X struct {
|
||||
// The Simple variant of X is decorated with a basic set of inline styles.
|
||||
// This means that if you want to provide your own CSS, you want
|
||||
// to disable the inline CSS provided by Hugo.
|
||||
DisableInlineCSS bool
|
||||
}
|
||||
|
||||
// RSS holds the functional configuration settings related to the RSS feeds.
|
||||
type RSS struct {
|
||||
// Limit the number of pages.
|
||||
|
||||
@@ -36,6 +36,8 @@ id = "ga_id"
|
||||
disableInlineCSS = true
|
||||
[services.twitter]
|
||||
disableInlineCSS = true
|
||||
[services.x]
|
||||
disableInlineCSS = true
|
||||
`
|
||||
cfg, err := config.FromConfigString(tomlConfig, "toml")
|
||||
c.Assert(err, qt.IsNil)
|
||||
|
||||
+6
-4
@@ -82,11 +82,13 @@ func NewContent(h *hugolib.HugoSites, kind, targetPath string, force bool) error
|
||||
b.setArcheTypeFilenameToUse(ext)
|
||||
|
||||
withBuildLock := func() (string, error) {
|
||||
unlock, err := h.BaseFs.LockBuild()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to acquire a build lock: %s", err)
|
||||
if !h.Configs.Base.NoBuildLock {
|
||||
unlock, err := h.BaseFs.LockBuild()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to acquire a build lock: %s", err)
|
||||
}
|
||||
defer unlock()
|
||||
}
|
||||
defer unlock()
|
||||
|
||||
if b.isDir {
|
||||
return "", b.buildDir()
|
||||
|
||||
Vendored
+1
-1
@@ -188,7 +188,7 @@ func (d *Deps) Init() error {
|
||||
}
|
||||
|
||||
if d.ExecHelper == nil {
|
||||
d.ExecHelper = hexec.New(d.Conf.GetConfigSection("security").(security.Config), d.Conf.WorkingDir())
|
||||
d.ExecHelper = hexec.New(d.Conf.GetConfigSection("security").(security.Config), d.Conf.WorkingDir(), d.Log)
|
||||
}
|
||||
|
||||
if d.MemCache == nil {
|
||||
|
||||
@@ -23,3 +23,4 @@ MD046: false
|
||||
MD049: false
|
||||
MD050: false
|
||||
MD053: false
|
||||
MD055: false
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
}
|
||||
|
||||
code {
|
||||
padding: 0.2em;
|
||||
padding: 2px 3px;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
font-size: 93.75%;
|
||||
background-color: rgba(27,31,35,0.05);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
@@ -18,3 +18,8 @@ h6:first-of-type {
|
||||
h6 ~ p {
|
||||
margin: 0.5em 0 2em 0;
|
||||
}
|
||||
|
||||
/* QR codes */
|
||||
img.qrcode {
|
||||
width: initial;
|
||||
}
|
||||
|
||||
@@ -4769,9 +4769,9 @@ h6:hover .header-link {
|
||||
margin: 0;
|
||||
}
|
||||
code {
|
||||
padding: 0.2em;
|
||||
padding: 2px 3px;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
font-size: 93.75%;
|
||||
background-color: rgba(27, 31, 35, .05);
|
||||
border-radius: 3px;
|
||||
}
|
||||
@@ -5333,6 +5333,11 @@ h6:first-of-type {
|
||||
h6 ~ p {
|
||||
margin: 0.5em 0 2em 0;
|
||||
}
|
||||
/* QR codes */
|
||||
img.qrcode {
|
||||
width: auto;
|
||||
width: initial;
|
||||
}
|
||||
.nested-blockquote blockquote {
|
||||
border-left: 4px solid #0594CB;
|
||||
padding-left: 1em;
|
||||
|
||||
@@ -5,15 +5,6 @@
|
||||
utm_campaign = "hugosponsor"
|
||||
bgcolor = "#ffffff"
|
||||
|
||||
[[banners]]
|
||||
name = "Route4Me"
|
||||
link = "https://route4me.com/"
|
||||
title = "Route Planning & Route Optimization Software"
|
||||
no_query_params = true
|
||||
utm_campaign = "hugosponsor"
|
||||
bgcolor = "#334799"
|
||||
link_attr = "style='color: #ffffff; font-weight: bold; text-decoration: none; text-align: center'"
|
||||
|
||||
[[banners]]
|
||||
name = "GoLand"
|
||||
title = "The complete IDE crafted for professional Go developers."
|
||||
@@ -21,3 +12,11 @@
|
||||
link = "https://www.jetbrains.com/go/?utm_source=OSS&utm_medium=referral&utm_campaign=hugo"
|
||||
logo = "images/sponsors/goland.svg"
|
||||
bgcolor = "#f4f4f4"
|
||||
|
||||
[[banners]]
|
||||
name = "Your Company?"
|
||||
link = "https://bep.is/en/hugo-sponsor-2023-01/"
|
||||
utm_campaign = "hugosponsor"
|
||||
show_on_hover = true
|
||||
bgcolor = "#4e4f4f"
|
||||
link_attr = "style='color: #ffffff; font-weight: bold; text-decoration: none; text-align: center'"
|
||||
|
||||
+1
-6
@@ -98,12 +98,7 @@ either of these shortcodes in conjunction with this render hook.
|
||||
{{- end }}
|
||||
|
||||
{{- /* Determine content path for warning and error messages. */}}
|
||||
{{- $contentPath := "" }}
|
||||
{{- with .Page.File }}
|
||||
{{- $contentPath = .Path }}
|
||||
{{- else }}
|
||||
{{- $contentPath = .Path }}
|
||||
{{- end }}
|
||||
{{- $contentPath := .Page.String }}
|
||||
|
||||
{{- /* Parse destination. */}}
|
||||
{{- $u := urls.Parse .Destination }}
|
||||
|
||||
+4
-4
@@ -4,14 +4,14 @@
|
||||
|
||||
{{ $data := "" }}
|
||||
{{ $url := urls.JoinPath "https://api.github.com/users" $author }}
|
||||
{{ with resources.GetRemote $url }}
|
||||
{{ with try (resources.GetRemote $url) }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "%s" . }}
|
||||
{{ else }}
|
||||
{{ else with .Value }}
|
||||
{{ $data = . | transform.Unmarshal }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %q" $url }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %q" $url }}
|
||||
{{ end }}
|
||||
|
||||
<div class="tc">
|
||||
|
||||
Generated
+4
-4
@@ -4,14 +4,14 @@
|
||||
|
||||
{{ $data := "" }}
|
||||
{{ $url := urls.JoinPath "https://api.github.com/users" $author }}
|
||||
{{ with resources.GetRemote $url }}
|
||||
{{ with try (resources.GetRemote $url) }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "%s" . }}
|
||||
{{ else }}
|
||||
{{ else with .Value }}
|
||||
{{ $data = . | transform.Unmarshal }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %q" $url }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %q" $url }}
|
||||
{{ end }}
|
||||
|
||||
{{ with $data }}
|
||||
|
||||
Generated
+4
-4
@@ -11,13 +11,13 @@ Supports CSV, JSON, TOML, YAML, and XML.
|
||||
|
||||
{{ $url := . }}
|
||||
{{ $data := dict }}
|
||||
{{ with resources.GetRemote $url }}
|
||||
{{ with try (resources.GetRemote $url) }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "%s" . }}
|
||||
{{ else }}
|
||||
{{ else with .Value }}
|
||||
{{ $data = .Content | transform.Unmarshal }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %q" $url }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %q" $url }}
|
||||
{{ end }}
|
||||
{{ return $data }}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{{- /*
|
||||
Returns syntax-highlighted code from the given text.
|
||||
|
||||
This is useful as a terse way to highlight inline code snippets. Calling the
|
||||
highlight shortcode for inline snippets is verbose.
|
||||
*/}}
|
||||
|
||||
{{- $code := .Inner | strings.TrimSpace }}
|
||||
{{- $lang := or (.Get 0) "go" }}
|
||||
{{- $opts := dict "hl_inline" true "noClasses" true }}
|
||||
{{- transform.Highlight $code $lang $opts }}
|
||||
+18
-8
@@ -120,8 +120,8 @@ Renders the given image using the given filter, if any.
|
||||
|
||||
{{- $validFilters := slice
|
||||
"autoorient" "brightness" "colorbalance" "colorize" "contrast" "dither"
|
||||
"gamma" "gaussianblur" "grayscale" "hue" "invert" "none" "opacity" "overlay"
|
||||
"padding" "pixelate" "process" "saturation" "sepia" "sigmoid" "text"
|
||||
"gamma" "gaussianblur" "grayscale" "hue" "invert" "mask" "none" "opacity"
|
||||
"overlay" "padding" "pixelate" "process" "saturation" "sepia" "sigmoid" "text"
|
||||
"unsharpmask"
|
||||
}}
|
||||
|
||||
@@ -229,6 +229,12 @@ Renders the given image using the given filter, if any.
|
||||
{{- $ctx = merge $ctx (dict "argsRequired" 0) }}
|
||||
{{- template "validate-arg-count" $ctx }}
|
||||
{{- $f = images.Invert }}
|
||||
{{- else if eq $filter "mask" }}
|
||||
{{- $ctx = merge $ctx (dict "argsRequired" 1) }}
|
||||
{{- template "validate-arg-count" $ctx }}
|
||||
{{- $ctx := dict "src" (index $filterArgs 0) "name" .Name "position" .Position }}
|
||||
{{- $maskImage := partial "inline/get-resource.html" $ctx }}
|
||||
{{- $f = images.Mask $maskImage }}
|
||||
{{- else if eq $filter "opacity" }}
|
||||
{{- $ctx = merge $ctx (dict "argsRequired" 1) }}
|
||||
{{- template "validate-arg-count" $ctx }}
|
||||
@@ -322,11 +328,15 @@ Renders the given image using the given filter, if any.
|
||||
{{- end }}
|
||||
|
||||
{{- /* Render. */}}
|
||||
{{- $class := "di va b--black-20" }}
|
||||
{{- if eq $filter "mask" }}
|
||||
{{- $class = "di va" }}
|
||||
{{- end }}
|
||||
{{- if $example }}
|
||||
<p>Original</p>
|
||||
<img class='di ba b--black-20' style="width: initial;" src="{{ $i.RelPermalink }}" alt="{{ $alt }}">
|
||||
<img class="{{ $class}}" style="width: initial;" src="{{ $i.RelPermalink }}" alt="{{ $alt }}">
|
||||
<p>Processed</p>
|
||||
<img class='di ba b--black-20' style="width: initial;" src="{{ $fi.RelPermalink }}" alt="{{ $alt }}">
|
||||
<img class="{{ $class }}" style="width: initial;" src="{{ $fi.RelPermalink }}" alt="{{ $alt }}">
|
||||
{{- else -}}
|
||||
<img class='di' style="width: initial;" src="{{ $fi.RelPermalink }}" alt="{{ $alt }}">
|
||||
{{- end }}
|
||||
@@ -354,15 +364,15 @@ Renders the given image using the given filter, if any.
|
||||
{{- $u := urls.Parse .src }}
|
||||
{{- $msg := "The %q shortcode was unable to resolve %s. See %s" }}
|
||||
{{- if $u.IsAbs }}
|
||||
{{- with resources.GetRemote $u.String }}
|
||||
{{- with try (resources.GetRemote $u.String) }}
|
||||
{{- with .Err }}
|
||||
{{- errorf "%s" . }}
|
||||
{{- else }}
|
||||
{{- else with .Value }}
|
||||
{{- /* This is a remote resource. */}}
|
||||
{{- $r = . }}
|
||||
{{- else }}
|
||||
{{- errorf $msg $.name $u.String $.position }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- errorf $msg $.name $u.String $.position }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{- with .page.Resources.Get (strings.TrimPrefix "./" $u.Path) }}
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ You must call this shortcode using the {{% %}} notation.
|
||||
*/}}
|
||||
|
||||
{{- with .Get 0 }}
|
||||
{{- with site.GetPage . }}
|
||||
{{- with $.Page.GetPage . }}
|
||||
{{- .RenderShortcodes }}
|
||||
{{- else }}
|
||||
{{- errorf "The %q shortcode was unable to find %q. See %s" $.Name . $.Position }}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
# github.com/gohugoio/gohugoioTheme v0.0.0-20241119115653-b92d27ede3e1
|
||||
|
||||
# github.com/gohugoio/gohugoioTheme v0.0.0-20250116152525-2d382cae7743
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: {{ replace .File.ContentBaseName "-" " " }}
|
||||
---
|
||||
|
||||
<!--
|
||||
You can insert these definitions in other pages using the `glossary-term` shortcode, so they must be self-contained.
|
||||
|
||||
Do this:
|
||||
|
||||
A _foo_ is big bar.
|
||||
|
||||
Not this:
|
||||
|
||||
A big bar.
|
||||
|
||||
Italicize the term whenever you use it in the definition.
|
||||
|
||||
An exception to this rule occurs when a term is an alias for another. In such cases, it is sufficient to use the phrase 'See [page kind]'."
|
||||
-->
|
||||
@@ -20,7 +20,7 @@ byline: "[bep](https://github.com/bep), Hugo Lead"
|
||||
To complete this showcase:
|
||||
|
||||
1. Write the story about your site in this file.
|
||||
2. Add a summary to the `bio.md` file in this folder.
|
||||
2. Add a summary to the `bio.md` file in this directory.
|
||||
3. Replace the `featured-template.png` with a screenshot of your site. You can rename it, but it must contain the word `featured`.
|
||||
4. Create a new pull request in https://github.com/gohugoio/hugoDocs/pulls
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 134 KiB |
@@ -55,20 +55,26 @@ identifier = 'render-hooks'
|
||||
pageRef = '/render-hooks/'
|
||||
|
||||
[[docs]]
|
||||
name = 'Hugo Modules'
|
||||
name = 'Shortcodes'
|
||||
weight = 100
|
||||
identifier = 'shortcodes'
|
||||
pageRef = '/shortcodes/'
|
||||
|
||||
[[docs]]
|
||||
name = 'Hugo Modules'
|
||||
weight = 110
|
||||
identifier = 'modules'
|
||||
pageRef = '/hugo-modules/'
|
||||
|
||||
[[docs]]
|
||||
name = 'Hugo Pipes'
|
||||
weight = 110
|
||||
weight = 120
|
||||
identifier = 'hugo-pipes'
|
||||
pageRef = '/hugo-pipes/'
|
||||
|
||||
[[docs]]
|
||||
name = 'CLI'
|
||||
weight = 120
|
||||
weight = 130
|
||||
post = 'break'
|
||||
identifier = 'commands'
|
||||
pageRef = '/commands/'
|
||||
@@ -77,25 +83,25 @@ pageRef = '/commands/'
|
||||
|
||||
[[docs]]
|
||||
name = 'Troubleshooting'
|
||||
weight = 130
|
||||
weight = 140
|
||||
identifier = 'troubleshooting'
|
||||
pageRef = '/troubleshooting/'
|
||||
|
||||
[[docs]]
|
||||
name = 'Developer tools'
|
||||
weight = 140
|
||||
weight = 150
|
||||
identifier = 'developer-tools'
|
||||
pageRef = '/tools/'
|
||||
|
||||
[[docs]]
|
||||
name = 'Hosting and deployment'
|
||||
weight = 150
|
||||
weight = 160
|
||||
identifier = 'hosting-and-deployment'
|
||||
pageRef = '/hosting-and-deployment/'
|
||||
|
||||
[[docs]]
|
||||
name = 'Contribute'
|
||||
weight = 160
|
||||
weight = 170
|
||||
post = 'break'
|
||||
identifier = 'contribute'
|
||||
pageRef = '/contribute/'
|
||||
|
||||
@@ -55,7 +55,7 @@ toc: true
|
||||
: Use fenced code blocks and Markdown render hooks to include diagrams in your content.
|
||||
|
||||
[Mathematics]
|
||||
: Include mathematical equations and expressions in Markdown using LaTeX or TeX typesetting syntax.
|
||||
: Include mathematical equations and expressions in Markdown using LaTeX markup.
|
||||
|
||||
[Syntax highlighting]
|
||||
: Syntactically highlight code examples using Hugo's embedded syntax highlighter, enabled by default for fenced code blocks in Markdown. The syntax highlighter supports hundreds of code languages and dozens of styles.
|
||||
@@ -123,7 +123,7 @@ toc: true
|
||||
[Mathematics]: /content-management/mathematics/
|
||||
[Menus]: /content-management/menus/
|
||||
[Minification]: /getting-started/configuration/#configure-minify
|
||||
[Modules]: https://gohugo.io/hugo-modules/
|
||||
[Modules]: /hugo-modules/
|
||||
[Multilingual]: /content-management/multilingual/
|
||||
[Multiplatform]: /installation/
|
||||
[Output formats]: /templates/output-formats/
|
||||
@@ -134,6 +134,6 @@ toc: true
|
||||
[Syntax highlighting]: /content-management/syntax-highlighting/
|
||||
[Tailwind CSS processing]: /functions/css/tailwindcss/
|
||||
[Taxonomies]: /content-management/taxonomies/
|
||||
[Templates]: templates/introduction/
|
||||
[Templates]: /templates/introduction/
|
||||
[Themes]: https://themes.gohugo.io/
|
||||
[URL management]: /content-management/urls/
|
||||
|
||||
@@ -39,11 +39,11 @@ respectDoNotTrack = false
|
||||
[privacy.instagram]
|
||||
disable = false
|
||||
simple = false
|
||||
[privacy.twitter]
|
||||
[privacy.vimeo]
|
||||
disable = false
|
||||
enableDNT = false
|
||||
simple = false
|
||||
[privacy.vimeo]
|
||||
[privacy.x]
|
||||
disable = false
|
||||
enableDNT = false
|
||||
simple = false
|
||||
@@ -64,10 +64,10 @@ disable = true
|
||||
disable = true
|
||||
[privacy.instagram]
|
||||
disable = true
|
||||
[privacy.twitter]
|
||||
disable = true
|
||||
[privacy.vimeo]
|
||||
disable = true
|
||||
[privacy.x]
|
||||
disable = true
|
||||
[privacy.youtube]
|
||||
disable = true
|
||||
{{< /code-toggle >}}
|
||||
@@ -92,19 +92,19 @@ simple
|
||||
disableInlineCSS = true
|
||||
{{< /code-toggle >}}
|
||||
|
||||
### Twitter
|
||||
### X
|
||||
|
||||
enableDNT
|
||||
: Enabling this for the twitter/tweet shortcode, the tweet and its embedded page on your site are not used for purposes that include personalized suggestions and personalized ads.
|
||||
: Enabling this for the x shortcode, the post and its embedded page on your site are not used for purposes that include personalized suggestions and personalized ads.
|
||||
|
||||
simple
|
||||
: If simple mode is enabled, a static and no-JS version of a tweet will be built.
|
||||
: If simple mode is enabled, a static and no-JS version of a post will be built.
|
||||
|
||||
**Note:** If you use the _simple mode_ for Twitter, you may want to disable the inline styles provided by Hugo:
|
||||
**Note:** If you use the _simple mode_ for X, you may want to disable the inline styles provided by Hugo:
|
||||
|
||||
{{< code-toggle file=hugo >}}
|
||||
[services]
|
||||
[services.twitter]
|
||||
[services.x]
|
||||
disableInlineCSS = true
|
||||
{{< /code-toggle >}}
|
||||
|
||||
|
||||
@@ -72,7 +72,6 @@ hugo [flags]
|
||||
* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell
|
||||
* [hugo config](/commands/hugo_config/) - Display site configuration
|
||||
* [hugo convert](/commands/hugo_convert/) - Convert front matter to another format
|
||||
* [hugo deploy](/commands/hugo_deploy/) - Deploy your site to a cloud provider
|
||||
* [hugo env](/commands/hugo_env/) - Display version and environment info
|
||||
* [hugo gen](/commands/hugo_gen/) - Generate documentation and syntax highlighting styles
|
||||
* [hugo import](/commands/hugo_import/) - Import a site from another system
|
||||
|
||||
@@ -29,6 +29,7 @@ See each sub-command's help for details on how to use the generated script.
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -52,6 +52,7 @@ hugo completion bash
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -43,6 +43,7 @@ hugo completion fish [flags]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -40,6 +40,7 @@ hugo completion powershell [flags]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -54,6 +54,7 @@ hugo completion zsh [flags]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -24,6 +24,7 @@ hugo config [command] [flags]
|
||||
--format string preferred file format (toml, yaml or json) (default "toml")
|
||||
-h, --help help for config
|
||||
--lang string the language to display config for. Defaults to the first language defined.
|
||||
--printZero include config options with zero values (e.g. false, 0, "") in the output
|
||||
--renderSegments strings named segments to render (configured in the segments config)
|
||||
-t, --theme strings themes to use (located in /themes/THEMENAME/)
|
||||
```
|
||||
@@ -38,6 +39,7 @@ hugo config [command] [flags]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -32,6 +32,7 @@ hugo config mounts [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -31,6 +31,7 @@ See convert's subcommands toJSON, toTOML and toYAML for more information.
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -32,6 +32,7 @@ hugo convert toJSON [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
-o, --output string filesystem path to write files to
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
|
||||
@@ -32,6 +32,7 @@ hugo convert toTOML [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
-o, --output string filesystem path to write files to
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
|
||||
@@ -32,6 +32,7 @@ hugo convert toYAML [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
-o, --output string filesystem path to write files to
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
|
||||
@@ -42,6 +42,7 @@ hugo deploy [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -31,6 +31,7 @@ hugo env [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -27,6 +27,7 @@ Generate documentation for your project using Hugo's documentation engine, inclu
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -37,6 +37,7 @@ hugo gen chromastyles [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -37,6 +37,7 @@ hugo gen doc [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -34,6 +34,7 @@ hugo gen man [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -29,6 +29,7 @@ Import requires a subcommand, e.g. `hugo import jekyll jekyll_root_path target_p
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -34,6 +34,7 @@ hugo import jekyll [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -29,6 +29,7 @@ List requires a subcommand, e.g. hugo list drafts
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -31,6 +31,7 @@ hugo list all [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -31,6 +31,7 @@ hugo list drafts [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -31,6 +31,7 @@ hugo list expired [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -31,6 +31,7 @@ hugo list future [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -31,6 +31,7 @@ hugo list published [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -38,6 +38,7 @@ See https://gohugo.io/hugo-modules/ for more information.
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -38,6 +38,7 @@ hugo mod clean [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -62,6 +62,7 @@ hugo mod get [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -39,6 +39,7 @@ hugo mod graph [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -43,6 +43,7 @@ hugo mod init [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -31,6 +31,7 @@ hugo mod npm [command] [flags]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -46,6 +46,7 @@ hugo mod npm pack [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -32,6 +32,7 @@ hugo mod tidy [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -38,6 +38,7 @@ hugo mod vendor [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -37,6 +37,7 @@ hugo mod verify [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -34,6 +34,7 @@ Ensure you run this within the root directory of your site.
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -46,6 +46,7 @@ hugo new content [path] [flags]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -35,6 +35,7 @@ hugo new site [path] [flags]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -34,6 +34,7 @@ hugo new theme [name] [flags]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -50,7 +50,6 @@ hugo server [command] [flags]
|
||||
--liveReloadPort int port for live reloading (i.e. 443 in HTTPS proxy situations) (default -1)
|
||||
--minify minify any supported output format (HTML, XML etc.)
|
||||
-N, --navigateToChanged navigate to changed content file on live browser reload
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--noChmod don't sync permission mode of files
|
||||
--noHTTPCache prevent HTTP caching
|
||||
--noTimes don't sync modification time of files
|
||||
@@ -85,6 +84,7 @@ hugo server [command] [flags]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -28,6 +28,7 @@ hugo server trust [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -31,6 +31,7 @@ hugo version [flags] [args]
|
||||
-e, --environment string build environment
|
||||
--ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern
|
||||
--logLevel string log level (debug|info|warn|error)
|
||||
--noBuildLock don't create .hugo_build.lock file
|
||||
--quiet build in quiet mode
|
||||
-M, --renderToMemory render to memory (mostly useful when running the server)
|
||||
-s, --source string filesystem path to read files relative from
|
||||
|
||||
@@ -15,7 +15,7 @@ aliases: [/content/archetypes/]
|
||||
|
||||
## Overview
|
||||
|
||||
A content file consists of [front matter] and markup. The markup is typically Markdown, but Hugo also supports other [content formats]. Front matter can be TOML, YAML, or JSON.
|
||||
A content file consists of [front matter](g) and markup. The markup is typically Markdown, but Hugo also supports other [content formats](g). Front matter can be TOML, YAML, or JSON.
|
||||
|
||||
The `hugo new content` command creates a new file in the `content` directory, using an archetype as a template. This is the default archetype:
|
||||
|
||||
@@ -25,7 +25,7 @@ date = '{{ .Date }}'
|
||||
draft = true
|
||||
{{< /code-toggle >}}
|
||||
|
||||
When you create new content, Hugo evaluates the [template actions] within the archetype. For example:
|
||||
When you create new content, Hugo evaluates the [template actions](g) within the archetype. For example:
|
||||
|
||||
```sh
|
||||
hugo new content posts/my-first-post.md
|
||||
@@ -39,7 +39,7 @@ date = '2023-08-24T11:49:46-07:00'
|
||||
draft = true
|
||||
{{< /code-toggle >}}
|
||||
|
||||
You can create an archetype for one or more [content types]. For example, use one archetype for posts, and use the default archetype for everything else:
|
||||
You can create an archetype for one or more [content types](g). For example, use one archetype for posts, and use the default archetype for everything else:
|
||||
|
||||
```text
|
||||
archetypes/
|
||||
@@ -59,18 +59,18 @@ hugo new content posts/my-first-post.md
|
||||
|
||||
The archetype lookup order is:
|
||||
|
||||
1. archetypes/posts.md
|
||||
1. archetypes/default.md
|
||||
1. themes/my-theme/archetypes/posts.md
|
||||
1. themes/my-theme/archetypes/default.md
|
||||
1. `archetypes/posts.md`
|
||||
1. `archetypes/default.md`
|
||||
1. `themes/my-theme/archetypes/posts.md`
|
||||
1. `themes/my-theme/archetypes/default.md`
|
||||
|
||||
If none of these exists, Hugo uses a built-in default archetype.
|
||||
|
||||
## Functions and context
|
||||
|
||||
You can use any [template function] within an archetype. As shown above, the default archetype uses the [`replace`](/functions/strings/replace) function to replace hyphens with spaces when populating the title in front matter.
|
||||
You can use any template [function](g) within an archetype. As shown above, the default archetype uses the [`replace`](/functions/strings/replace) function to replace hyphens with spaces when populating the title in front matter.
|
||||
|
||||
Archetypes receive the following [context]:
|
||||
Archetypes receive the following [context](g):
|
||||
|
||||
Date
|
||||
: (`string`) The current date and time, formatted in compliance with RFC3339.
|
||||
@@ -79,9 +79,7 @@ File
|
||||
: (`hugolib.fileInfo`) Returns file information for the current page. See [details](/methods/page/file).
|
||||
|
||||
Type
|
||||
: (`string`) The [content type] inferred from the top-level directory name, or as specified by the `--kind` flag passed to the `hugo new content` command.
|
||||
|
||||
[content type]: /getting-started/glossary#content-type
|
||||
: (`string`) The [content type](g) inferred from the top-level directory name, or as specified by the `--kind` flag passed to the `hugo new content` command.
|
||||
|
||||
Site
|
||||
: (`page.Site`) The current site object. See [details](/methods/site/).
|
||||
@@ -130,11 +128,11 @@ One or more practical examples, each within a fenced code block.
|
||||
Additional information to clarify as needed.
|
||||
{{< /code >}}
|
||||
|
||||
Although you can include [template actions] within the content body, remember that Hugo evaluates these once---at the time of content creation. In most cases, place template actions in a [template] where Hugo evaluates the actions every time you [build](/getting-started/glossary/#build) the site.
|
||||
Although you can include [template actions](g) within the content body, remember that Hugo evaluates these once---at the time of content creation. In most cases, place template actions in a [template](g) where Hugo evaluates the actions every time you [build](g) the site.
|
||||
|
||||
## Leaf bundles
|
||||
|
||||
You can also create archetypes for [leaf bundles](/getting-started/glossary/#leaf-bundle).
|
||||
You can also create archetypes for [leaf bundles](g).
|
||||
|
||||
For example, in a photography site you might have a section (content type) for galleries. Each gallery is leaf bundle with content and images.
|
||||
|
||||
@@ -193,11 +191,3 @@ To create an article using the tutorials archetype:
|
||||
```sh
|
||||
hugo new content --kind tutorials articles/something.md
|
||||
```
|
||||
|
||||
[content formats]: /getting-started/glossary/#content-format
|
||||
[content types]: /getting-started/glossary/#content-type
|
||||
[context]: /getting-started/glossary/#context
|
||||
[front matter]: /getting-started/glossary/#front-matter
|
||||
[template actions]: /getting-started/glossary/#template-action
|
||||
[template]: /getting-started/glossary/#template
|
||||
[template function]: /getting-started/glossary/#function
|
||||
|
||||
@@ -21,7 +21,6 @@ publishResources = true
|
||||
render = 'always'
|
||||
{{< /code-toggle >}}
|
||||
|
||||
|
||||
list
|
||||
: When to include the page within page collections. Specify one of:
|
||||
|
||||
@@ -115,7 +114,7 @@ public/
|
||||
In the example above, note that:
|
||||
|
||||
1. Hugo did not publish an HTML file for the page.
|
||||
2. Despite setting `publishResources` to `false` in front matter, Hugo published the [page resources] because we invoked the [`RelPermalink`] method on each resource. This is the expected behavior.
|
||||
1. Despite setting `publishResources` to `false` in front matter, Hugo published the [page resources] because we invoked the [`RelPermalink`] method on each resource. This is the expected behavior.
|
||||
|
||||
## Example -- headless section
|
||||
|
||||
@@ -181,7 +180,7 @@ public/
|
||||
In the example above, note that:
|
||||
|
||||
1. Hugo did not publish an HTML file for the page.
|
||||
2. Despite setting `publishResources` to `false` in front matter, Hugo correctly published the [page resources] because we invoked the [`RelPermalink`] method on each resource. This is the expected behavior.
|
||||
1. Despite setting `publishResources` to `false` in front matter, Hugo correctly published the [page resources] because we invoked the [`RelPermalink`] method on each resource. This is the expected behavior.
|
||||
|
||||
## Example -- list without publishing
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ toc: true
|
||||
|
||||
A content adapter is a template that dynamically creates pages when building a site. For example, use a content adapter to create pages from a remote data source such as JSON, TOML, YAML, or XML.
|
||||
|
||||
Unlike templates that reside in the layouts directory, content adapters reside in the content directory, no more than one per directory per language. When a content adapter creates a page, the page's [logical path] will be relative to the content adapter.
|
||||
Unlike templates that reside in the `layouts` directory, content adapters reside in the `content` directory, no more than one per directory per language. When a content adapter creates a page, the page's [logical path](g) will be relative to the content adapter.
|
||||
|
||||
```text
|
||||
content/
|
||||
@@ -33,7 +33,7 @@ content/
|
||||
└── _index.md
|
||||
```
|
||||
|
||||
Each content adapter is named _content.gotmpl and uses the same [syntax] as templates in the layouts directory. You can use any of the [template functions] within a content adapter, as well as the methods described below.
|
||||
Each content adapter is named _content.gotmpl and uses the same [syntax] as templates in the `layouts` directory. You can use any of the [template functions] within a content adapter, as well as the methods described below.
|
||||
|
||||
## Methods
|
||||
|
||||
@@ -137,9 +137,8 @@ Key|Description|Required
|
||||
`dates.expiryDate`|The page expiry date as a `time.Time` value.|
|
||||
`dates.lastmod`|The page last modification date as a `time.Time` value.|
|
||||
`dates.publishDate`|The page publication date as a `time.Time` value.|
|
||||
`kind`|The [page kind]. Default is `page`.|
|
||||
`params`|A map of page parameters.|
|
||||
`path`|The page's [logical path] relative to the content adapter. Do not include a leading slash or file extension.|:heavy_check_mark:
|
||||
`path`|The page's [logical path](g) relative to the content adapter. Do not include a leading slash or file extension.|:heavy_check_mark:
|
||||
`title`|The page title.|
|
||||
|
||||
{{% note %}}
|
||||
@@ -158,7 +157,7 @@ Key|Description|Required
|
||||
`content.value`|The content value as a string or resource.|:heavy_check_mark:
|
||||
`name`|The resource name.|
|
||||
`params`|A map of resource parameters.|
|
||||
`path`|The resources's [logical path] relative to the content adapter. Do not include a leading slash.|:heavy_check_mark:
|
||||
`path`|The resources's [logical path](g) relative to the content adapter. Do not include a leading slash.|:heavy_check_mark:
|
||||
`title`|The resource title.|
|
||||
|
||||
{{% note %}}
|
||||
@@ -193,14 +192,14 @@ Step 3
|
||||
{{/* Get remote data. */}}
|
||||
{{ $data := dict }}
|
||||
{{ $url := "https://gohugo.io/shared/examples/data/books.json" }}
|
||||
{{ with resources.GetRemote $url }}
|
||||
{{ with try (resources.GetRemote $url) }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "Unable to get remote resource %s: %s" $url . }}
|
||||
{{ else }}
|
||||
{{ else with .Value }}
|
||||
{{ $data = . | transform.Unmarshal }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %s" $url }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %s" $url }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Add pages and page resources. */}}
|
||||
@@ -223,10 +222,10 @@ Step 3
|
||||
{{/* Add page resource. */}}
|
||||
{{ $item := . }}
|
||||
{{ with $url := $item.cover }}
|
||||
{{ with resources.GetRemote $url }}
|
||||
{{ with try (resources.GetRemote $url) }}
|
||||
{{ with .Err }}
|
||||
{{ errorf "Unable to get remote resource %s: %s" $url . }}
|
||||
{{ else }}
|
||||
{{ else with .Value }}
|
||||
{{ $content := dict "mediaType" .MediaType.Type "value" .Content }}
|
||||
{{ $params := dict "alt" $item.title }}
|
||||
{{ $resource := dict
|
||||
@@ -235,9 +234,9 @@ Step 3
|
||||
"path" (printf "%s/cover.%s" $item.title .MediaType.SubType)
|
||||
}}
|
||||
{{ $.AddResource $resource }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %s" $url }}
|
||||
{{ end }}
|
||||
{{ else }}
|
||||
{{ errorf "Unable to get remote resource %s" $url }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -281,7 +280,7 @@ Step 4
|
||||
With multilingual sites you can:
|
||||
|
||||
1. Create one content adapter for all languages using the [`EnableAllLanguages`](#enablealllanguages) method as described above.
|
||||
2. Create content adapters unique to each language. See the examples below.
|
||||
1. Create content adapters unique to each language. See the examples below.
|
||||
|
||||
### Translations by file name
|
||||
|
||||
@@ -352,8 +351,6 @@ To detect page collisions, use the `--printPathWarnings` flag when building your
|
||||
|
||||
[content formats]: /content-management/formats/#classification
|
||||
[front matter field]: /content-management/front-matter/#fields
|
||||
[logical path]: /getting-started/glossary/#logical-path
|
||||
[media type]: https://en.wikipedia.org/wiki/Media_type
|
||||
[page kind]: /getting-started/glossary/#page-kind
|
||||
[syntax]: /templates/introduction/
|
||||
[template functions]: /functions/
|
||||
|
||||
@@ -49,7 +49,7 @@ The pages can be referenced as follows:
|
||||
{{</* relref "/blog/my-post.md" */>}}
|
||||
```
|
||||
|
||||
index.md can be reference either by its path or by its containing folder without the ending `/`. \_index.md can be referenced only by its containing folder:
|
||||
`index.md` can be reference either by its path or by its containing directory without the ending `/`. `_index.md` can be referenced only by its containing directory:
|
||||
|
||||
```text
|
||||
{{</* ref "/about" */>}} <-- References /about/_index.md
|
||||
|
||||
@@ -12,21 +12,15 @@ toc: true
|
||||
aliases: [/extras/datafiles/,/extras/datadrivencontent/,/doc/datafiles/,/templates/data-templates/]
|
||||
---
|
||||
|
||||
Hugo can access and [unmarshal] local and remote data sources including CSV, JSON, TOML, YAML, and XML. Use this data to augment existing content or to create new content.
|
||||
Hugo can access and [unmarshal](g) local and remote data sources including CSV, JSON, TOML, YAML, and XML. Use this data to augment existing content or to create new content.
|
||||
|
||||
[unmarshal]: /getting-started/glossary/#unmarshal
|
||||
|
||||
A data source might be a file in the data directory, a [global resource], a [page resource], or a [remote resource].
|
||||
|
||||
[global resource]: /getting-started/glossary/#global-resource
|
||||
[page resource]: /getting-started/glossary/#page-resource
|
||||
[remote resource]: /getting-started/glossary/#remote-resource
|
||||
A data source might be a file in the `data` directory, a [global resource](g), a [page resource](g), or a [remote resource](g).
|
||||
|
||||
## Data directory
|
||||
|
||||
The data directory in the root of your project may contain one or more data files, in either a flat or nested tree. Hugo merges the data files to create a single data structure, accessible with the `Data` method on a `Site` object.
|
||||
The `data` directory in the root of your project may contain one or more data files, in either a flat or nested tree. Hugo merges the data files to create a single data structure, accessible with the `Data` method on a `Site` object.
|
||||
|
||||
Hugo also merges data directories from themes and modules into this single data structure, where the data directory in the root of your project takes precedence.
|
||||
Hugo also merges data directories from themes and modules into this single data structure, where the `data` directory in the root of your project takes precedence.
|
||||
|
||||
{{% note %}}
|
||||
Hugo reads the combined data structure into memory and keeps it there for the entire build. For data that is infrequently accessed, use global or page resources instead.
|
||||
@@ -42,7 +36,7 @@ project/
|
||||
```
|
||||
|
||||
{{% note %}}
|
||||
Do not place CSV files in the data directory. Access CSV files as page, global, or remote resources.
|
||||
Do not place CSV files in the `data` directory. Access CSV files as page, global, or remote resources.
|
||||
{{% /note %}}
|
||||
|
||||
See the documentation for the [`Data`] method on a `Site` object for details and examples.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user