Compare commits

...

125 Commits

Author SHA1 Message Date
hugoreleaser 76a5e1880a releaser: Bump versions for release of 0.165.0
[ci skip]
2026-08-12 14:26:28 +00:00
dependabot[bot] 0bb337b22a build(deps): bump github.com/bep/imagemeta from 0.17.3 to 1.0.0
Bumps [github.com/bep/imagemeta](https://github.com/bep/imagemeta) from 0.17.3 to 1.0.0.
- [Release notes](https://github.com/bep/imagemeta/releases)
- [Commits](https://github.com/bep/imagemeta/compare/v0.17.3...v1.0.0)

---
updated-dependencies:
- dependency-name: github.com/bep/imagemeta
  dependency-version: 1.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-12 13:49:11 +02:00
dependabot[bot] 03dc9170b3 build(deps): bump github.com/evanw/esbuild from 0.28.1 to 0.28.2
Bumps [github.com/evanw/esbuild](https://github.com/evanw/esbuild) from 0.28.1 to 0.28.2.
- [Release notes](https://github.com/evanw/esbuild/releases)
- [Changelog](https://github.com/evanw/esbuild/blob/main/CHANGELOG.md)
- [Commits](https://github.com/evanw/esbuild/compare/v0.28.1...v0.28.2)

---
updated-dependencies:
- dependency-name: github.com/evanw/esbuild
  dependency-version: 0.28.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-12 13:48:55 +02:00
dependabot[bot] c829b736cc build(deps): bump github.com/tdewolff/minify/v2 from 2.24.14 to 2.24.16
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.24.14 to 2.24.16.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.24.14...v2.24.16)

---
updated-dependencies:
- dependency-name: github.com/tdewolff/minify/v2
  dependency-version: 2.24.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-12 11:38:40 +02:00
Bjørn Erik Pedersen 995a2159e5 resources: Resume chained resource transformations
This is a follow up the bug fix in #15189. With the example given in that issue, the `css.Build` would be performed twice, which was unfortunate.

This commit fixes that by resuming the transformation from the last executed transformation.

See #15189
2026-08-11 19:12:24 +02:00
Bjørn Erik Pedersen f88f0a9f59 resources/jsconfig: Drop source root mapping for the current source root
* Intellisense doesn't need it to do its work.
* This also avoids creating a jsconfig.js file in the common cases.

Fixes #15169
2026-08-11 15:57:03 +02:00
Bjørn Erik Pedersen dd3f2731e0 Remove Star History from README
Removed Star History section from README.

Closes #15190
2026-08-10 23:08:30 +02:00
Bjørn Erik Pedersen f772998fa3 Fix resource transformation chaining after content access
When a transformed resource had been initialized (e.g. via .Data, .Content
or .RelPermalink) before chaining another transformation, the new chain
would run on the transformed output instead of the original source,
re-running all transformations on their own output.

Fixes #15189

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-10 18:10:06 +02:00
Bjørn Erik Pedersen 8a55df7af2 Remove tailwindcss from the default security.exec.allow list (note)
Fixes #15178
Closes #15171
2026-08-10 15:59:57 +02:00
Bjørn Erik Pedersen 52c9bd7908 circleci: Upgrade to Go 1.26.5 2026-08-09 21:38:57 +02:00
Bjørn Erik Pedersen 44da086082 Add Data.Artifacts to css.Build and js.Build
Artifacts are the additional output files published as part of the build:
source maps and files emitted by ESBuild's file loader (e.g. fonts). Each
artifact provides Permalink, RelPermalink and MediaType, so e.g. font
preload links can be constructed in templates.

Also add media type definitions for source maps (application/source-map),
font/woff and font/woff2.

Fixes #15173

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-08 19:51:42 +02:00
Bjørn Erik Pedersen 2ffaf1fc1e Fix server static file detection for deleted files/directories in the static syncer
Related to #15174
2026-08-08 18:08:03 +02:00
Bjørn Erik Pedersen a808f6e40d Fix server errors when deleting static files or directories
Fixes #15174
2026-08-08 18:08:03 +02:00
dependabot[bot] 94f3908ec6 build(deps): bump github.com/getkin/kin-openapi from 0.145.0 to 0.146.0
Bumps [github.com/getkin/kin-openapi](https://github.com/getkin/kin-openapi) from 0.145.0 to 0.146.0.
- [Release notes](https://github.com/getkin/kin-openapi/releases)
- [Commits](https://github.com/getkin/kin-openapi/compare/v0.145.0...v0.146.0)

---
updated-dependencies:
- dependency-name: github.com/getkin/kin-openapi
  dependency-version: 0.146.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-07 11:31:51 +02:00
dependabot[bot] 75fcc7524a build(deps): bump github.com/rogpeppe/go-internal from 1.15.0 to 1.16.0
Bumps [github.com/rogpeppe/go-internal](https://github.com/rogpeppe/go-internal) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/rogpeppe/go-internal/releases)
- [Commits](https://github.com/rogpeppe/go-internal/compare/v1.15.0...v1.16.0)

---
updated-dependencies:
- dependency-name: github.com/rogpeppe/go-internal
  dependency-version: 1.16.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-08-07 11:31:37 +02:00
Bjørn Erik Pedersen 33d1f2c853 css: Add classDark and classLight options to css.ChromaStyles and gen chromastyles
Closes #15167
2026-08-05 16:04:48 +02:00
Bjørn Erik Pedersen 64da6d7c62 markup/highlight: Re-emit token colors dropped by Chroma's minifier
Chroma drops token rules whose color equals the style's default foreground
(e.g. .nx in github-dark). In a paired light/dark setup the other sheet's
explicit rule then leaks in, since an explicit declaration beats inheritance
from .chroma. Apply the chromaCSSOverrides custom CSS unconditionally so
these rules survive in modeSelector sheets too.

Updates #15161
2026-08-04 16:10:27 +02:00
Bjørn Erik Pedersen 70db201ed4 Add importContext option to css.Build, js.Build, css.Sass and css.TailwindCSS
This allows @import statements to be resolved in a set of user provided resources (e.g. from resources.FromString or css.ChromaStyles) before the assets filesystem.

The option also applies to css.PostCSS via the shared import inlining, and css.Sass requires the dartsass transpiler. The import context is part of the transformation cache key.

Fixes #15103

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 21:20:06 +02:00
Bjørn Erik Pedersen 8a468df065 Remove some old deprecations 2026-07-29 20:48:47 +02:00
dependabot[bot] b5fa03d3aa build(deps): bump github.com/mattn/go-isatty from 0.0.22 to 0.0.24
Bumps [github.com/mattn/go-isatty](https://github.com/mattn/go-isatty) from 0.0.22 to 0.0.24.
- [Commits](https://github.com/mattn/go-isatty/compare/v0.0.22...v0.0.24)

---
updated-dependencies:
- dependency-name: github.com/mattn/go-isatty
  dependency-version: 0.0.24
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-29 18:42:01 +02:00
dependabot[bot] 9da472dd3b build(deps): bump github.com/yuin/goldmark from 1.8.4 to 1.8.5
Bumps [github.com/yuin/goldmark](https://github.com/yuin/goldmark) from 1.8.4 to 1.8.5.
- [Release notes](https://github.com/yuin/goldmark/releases)
- [Commits](https://github.com/yuin/goldmark/compare/v1.8.4...v1.8.5)

---
updated-dependencies:
- dependency-name: github.com/yuin/goldmark
  dependency-version: 1.8.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-29 18:41:48 +02:00
Bjørn Erik Pedersen 615e45d6e8 Add css.ChromaStyles
Move the stylesheet generation from the gen chromastyles command into
markup/highlight and share it with the new template function.

Fixes #15112

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 18:41:31 +02:00
dependabot[bot] 635532a20f build(deps): bump golang.org/x/tools from 0.47.0 to 0.48.0
Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.47.0 to 0.48.0.
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.47.0...v0.48.0)

---
updated-dependencies:
- dependency-name: golang.org/x/tools
  dependency-version: 0.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-29 11:52:08 +02:00
Shantanav Mukherjee a243a6154c check.sh: Handle staticcheck not installed/in PATH 2026-07-28 12:31:02 +02:00
dependabot[bot] 9c71f600bf build(deps): bump github.com/kyokomi/emoji/v2 from 2.2.13 to 2.2.14
Bumps [github.com/kyokomi/emoji/v2](https://github.com/kyokomi/emoji) from 2.2.13 to 2.2.14.
- [Release notes](https://github.com/kyokomi/emoji/releases)
- [Commits](https://github.com/kyokomi/emoji/compare/v2.2.13...v2.2.14)

---
updated-dependencies:
- dependency-name: github.com/kyokomi/emoji/v2
  dependency-version: 2.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-28 12:29:19 +02:00
dependabot[bot] 420527fc6b build(deps): bump github.com/getkin/kin-openapi from 0.144.0 to 0.145.0
Bumps [github.com/getkin/kin-openapi](https://github.com/getkin/kin-openapi) from 0.144.0 to 0.145.0.
- [Release notes](https://github.com/getkin/kin-openapi/releases)
- [Commits](https://github.com/getkin/kin-openapi/compare/v0.144.0...v0.145.0)

---
updated-dependencies:
- dependency-name: github.com/getkin/kin-openapi
  dependency-version: 0.145.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-28 12:28:40 +02:00
dependabot[bot] 7fe786e3b0 build(deps): bump golang.org/x/image from 0.43.0 to 0.44.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.43.0 to 0.44.0.
- [Commits](https://github.com/golang/image/compare/v0.43.0...v0.44.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-version: 0.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-27 17:44:56 +02:00
dependabot[bot] 03b244fc0b build(deps): bump github.com/bep/imagemeta from 0.17.2 to 0.17.3
Bumps [github.com/bep/imagemeta](https://github.com/bep/imagemeta) from 0.17.2 to 0.17.3.
- [Release notes](https://github.com/bep/imagemeta/releases)
- [Commits](https://github.com/bep/imagemeta/compare/v0.17.2...v0.17.3)

---
updated-dependencies:
- dependency-name: github.com/bep/imagemeta
  dependency-version: 0.17.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-27 17:44:44 +02:00
dependabot[bot] 961181334f build(deps): bump github.com/tdewolff/minify/v2 from 2.24.13 to 2.24.14
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.24.13 to 2.24.14.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.24.13...v2.24.14)

---
updated-dependencies:
- dependency-name: github.com/tdewolff/minify/v2
  dependency-version: 2.24.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-27 17:44:32 +02:00
dependabot[bot] e35b7f049d build(deps): bump github.com/yuin/goldmark from 1.8.2 to 1.8.4
Bumps [github.com/yuin/goldmark](https://github.com/yuin/goldmark) from 1.8.2 to 1.8.4.
- [Release notes](https://github.com/yuin/goldmark/releases)
- [Commits](https://github.com/yuin/goldmark/compare/v1.8.2...v1.8.4)

---
updated-dependencies:
- dependency-name: github.com/yuin/goldmark
  dependency-version: 1.8.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-27 17:44:14 +02:00
Bjørn Erik Pedersen 7d90277a28 warpc: Improve AVIF error message on memory allocation failure
See https://discourse.gohugo.io/t/avif-conversion-fails-for-jpg-files-with-embedded-colour-profiles-when-not-resizing/57392/4
2026-07-27 17:44:01 +02:00
dependabot[bot] 0796fa7ace build(deps): bump golang.org/x/net from 0.56.0 to 0.57.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.56.0 to 0.57.0.
- [Commits](https://github.com/golang/net/compare/v0.56.0...v0.57.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.57.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-26 17:03:18 +02:00
Bjørn Erik Pedersen 6bf15241a1 Fix panic on server atomic save edits on MacOS
An atomic save (write temp file, rename into place) unlinks the inode the
watcher holds, so kqueue reports Remove for a file that's still on disk.
That took the delete branch and wiped the entire taxonomy subtree; the
following assemble then panicked in createMissingTaxonomies, where the
shifting tree.Get hit a not yet assembled *pageMetaSource.

Treat Remove of a path that still exists as an update, and use the
non-shifting GetRaw when checking for the auto created taxonomy node.

Fixes #15130

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-26 14:00:32 +02:00
Bjørn Erik Pedersen 861ede6d10 cache/filecache: Don't prune used cache entries with mixed-case dir names
On case-insensitive filesystems, entries created before we started lowercasing
the content paths in v0.123 are the same file as today's lowercased cache key,
and were removed on every hugo --gc.

Fixes #15101

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-07-26 11:40:27 +02:00
Bjørn Erik Pedersen f228c87d41 Drop symlinks in parent directories
Lstat only refrains from following the last element of a path, so a symlink
in an intermediate directory was still resolved, and reads could escape the
mount via e.g. resources.Get "symlinkdir/secret.txt".

Walk the directories up to the mount root and reject any that is a symlink.

Follow-up to cf9c8f93c and f8b5fa09a.
2026-07-25 18:17:06 +02:00
dependabot[bot] 1b701b72ca build(deps): bump golang.org/x/text from 0.38.0 to 0.40.0
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.38.0 to 0.40.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.38.0...v0.40.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-version: 0.40.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-25 18:14:11 +02:00
dependabot[bot] a32d70b712 build(deps): bump github.com/getkin/kin-openapi from 0.140.0 to 0.144.0
Bumps [github.com/getkin/kin-openapi](https://github.com/getkin/kin-openapi) from 0.140.0 to 0.144.0.
- [Release notes](https://github.com/getkin/kin-openapi/releases)
- [Commits](https://github.com/getkin/kin-openapi/compare/v0.140.0...v0.144.0)

---
updated-dependencies:
- dependency-name: github.com/getkin/kin-openapi
  dependency-version: 0.144.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-25 18:13:45 +02:00
dependabot[bot] 948cfb98f9 build(deps): bump google.golang.org/grpc from 1.80.0 to 1.82.1
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.80.0 to 1.82.1.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.80.0...v1.82.1)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-version: 1.82.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-25 18:12:39 +02:00
dependabot[bot] 8930802ef2 build(deps): bump golang.org/x/mod from 0.37.0 to 0.38.0
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.37.0 to 0.38.0.
- [Commits](https://github.com/golang/mod/compare/v0.37.0...v0.38.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-version: 0.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-25 16:45:18 +02:00
Bjørn Erik Pedersen 7df45f615a Delete .gemini 2026-07-25 11:30:55 +02:00
Joe Mooring f961093ea9 markup/asciidocext: Fix TOC parsing for asciidoctor-html5s
Closes #15121

Co-authored-by: mike.szewil <szewil_michael@bah.com>
2026-07-22 19:32:19 +02:00
Joe Mooring 89b8c32200 common/hugo: Include non-go dependencies in go env output
Closes #15116

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 10:58:38 +02:00
Joe Mooring 984358f047 snap: Fix snap home environment
Closes #15114
2026-07-13 10:57:03 +02:00
Joe Mooring d1f191c58d Update README.md
- Remove Go Report Card badge (services has been sunset)
- Updated dependencies section
2026-07-13 10:56:09 +02:00
hugoreleaser a198116669 releaser: Prepare repository for 0.165.0-DEV
[ci skip]
2026-07-06 17:47:51 +00:00
hugoreleaser ce2470e701 releaser: Bump versions for release of 0.164.0
[ci skip]
2026-07-06 16:39:30 +00:00
dependabot[bot] 921db7b52c build(deps): bump github.com/JohannesKaufmann/html-to-markdown/v2
Bumps [github.com/JohannesKaufmann/html-to-markdown/v2](https://github.com/JohannesKaufmann/html-to-markdown) from 2.5.1 to 2.5.2.
- [Release notes](https://github.com/JohannesKaufmann/html-to-markdown/releases)
- [Commits](https://github.com/JohannesKaufmann/html-to-markdown/compare/v2.5.1...v2.5.2)

---
updated-dependencies:
- dependency-name: github.com/JohannesKaufmann/html-to-markdown/v2
  dependency-version: 2.5.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 15:21:13 +02:00
dependabot[bot] 786ce71e59 build(deps): bump golang.org/x/tools from 0.45.0 to 0.47.0
Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.45.0 to 0.47.0.
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.45.0...v0.47.0)

---
updated-dependencies:
- dependency-name: golang.org/x/tools
  dependency-version: 0.47.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 13:34:38 +02:00
dependabot[bot] 5ad2846161 build(deps): bump golang.org/x/image from 0.42.0 to 0.43.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.42.0 to 0.43.0.
- [Commits](https://github.com/golang/image/compare/v0.42.0...v0.43.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-version: 0.43.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 13:33:50 +02:00
dependabot[bot] 36ad9f583a build(deps): bump golang.org/x/net from 0.55.0 to 0.56.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.55.0 to 0.56.0.
- [Commits](https://github.com/golang/net/compare/v0.55.0...v0.56.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.56.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 11:50:17 +02:00
dependabot[bot] 7c0a0bc979 build(deps): bump github.com/pelletier/go-toml/v2 from 2.4.2 to 2.4.3
Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.4.2 to 2.4.3.
- [Release notes](https://github.com/pelletier/go-toml/releases)
- [Commits](https://github.com/pelletier/go-toml/compare/v2.4.2...v2.4.3)

---
updated-dependencies:
- dependency-name: github.com/pelletier/go-toml/v2
  dependency-version: 2.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-06 11:49:16 +02:00
Bjørn Erik Pedersen d83ce27ae0 tpl/tplimpl: Support sub paths in layouts passed to .Render
E.g. {{ .Render "foo/mylayout" }} matches mylayout templates in
<dir>/foo for every dir from the page's layout path up to the layouts root.

Closes #15056

Co-authored-by: Joe Mooring <joe.mooring@veriphor.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-05 20:14:32 +02:00
Bjørn Erik Pedersen 5a5f4a5495 all: Rewrite deprecated constructs in tests 2026-07-04 23:10:26 +02:00
Bjørn Erik Pedersen c6acc246ab Add markup.rst.syntaxHighlight option
Fixes #5349
2026-07-04 22:27:29 +02:00
Bjørn Erik Pedersen 29ed932513 tpl/resources: Deprecate resources.PostProcess in favour of templates.Defer
Fixes #15086
2026-07-04 21:28:31 +02:00
Bjørn Erik Pedersen 7b4ddd1863 contributing: Add a note about co-authoring attributions when borrowing test cases 2026-07-04 18:10:03 +02:00
bejaratommy 671897ae91 tpl/collections: Include key in IsSet unsupported-type warning
The warning logged when calling IsSet with an unsupported type did not
identify which key triggered it, making it hard to locate the offending
template. Include the key in the message.

Fixes #11794
2026-07-04 15:18:42 +02:00
dependabot[bot] a879ebfaaa build(deps): bump github.com/getkin/kin-openapi from 0.139.0 to 0.140.0
Bumps [github.com/getkin/kin-openapi](https://github.com/getkin/kin-openapi) from 0.139.0 to 0.140.0.
- [Release notes](https://github.com/getkin/kin-openapi/releases)
- [Commits](https://github.com/getkin/kin-openapi/compare/v0.139.0...v0.140.0)

---
updated-dependencies:
- dependency-name: github.com/getkin/kin-openapi
  dependency-version: 0.140.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-04 14:43:32 +02:00
sjh9714 499794d19e create: Keep new content placeholders buildable
Fixes #15078
2026-07-04 14:31:54 +02:00
hexbinoct feb3d494b9 hugolib: Use the output format's suffix for alias paths
Alias generation hardcoded "index.html" and only recognized a ".html"
suffix, so an alias with an explicit ".htm" extension (or any other
suffix configured for the html media type) was written to the wrong
path. For example "d.htm" produced the directory "d.htm/index.html"
instead of the file "d.htm".

Build the alias file name from the output format's BaseName and the
media type's first suffix, and detect an explicit file by matching the
alias extension against the configured suffixes. The same check now
drives the uglyURLs case in Aliases.

Fixes #15066
2026-07-04 14:31:34 +02:00
Bjørn Erik Pedersen 65c82178b7 hugio: Speedup hasBytesWriter
The old implementation copied the incoming bytes into a fixed-size buffer
one byte at a time, and for every byte ran bytes.Contains for every
pattern over the whole buffer. That's O(n·patterns) scans of the buffer,
which showed up badly on large output (a full rendered page).

Scan each not-yet-matched pattern once per Write with bytes.Contains over
the chunk itself, in place, rather than per byte. The only carried state
is a small boundary window (the last maxPatternLen-1 bytes) joined with
the head of the next chunk, so a pattern straddling a Write boundary is
still detected. The chunk is never copied, so the extra allocation is
bounded by the longest pattern and independent of the output size. Once
all patterns have matched we mark done and drop the buffer.

patternLen summed the pattern lengths (to size the old buffer); the
boundary window only needs the longest pattern, so it's renamed
maxPatternLen and returns the max.

```bash
                  │ benchcmp.bench  │       fix-hasbytewriter.bench       │
                  │     sec/op      │    sec/op     vs base               │
HasBytesWriter-10   2473.095µ ± ∞ ¹   6.114µ ± ∞ ¹  -99.75% (p=0.029 n=4)
¹ need >= 6 samples for confidence interval at level 0.95

                  │ benchcmp.bench │       fix-hasbytewriter.bench        │
                  │      B/op      │     B/op      vs base                │
HasBytesWriter-10      48.00 ± ∞ ¹   128.00 ± ∞ ¹  +166.67% (p=0.029 n=4)
¹ need >= 6 samples for confidence interval at level 0.95

                  │ benchcmp.bench │       fix-hasbytewriter.bench       │
                  │   allocs/op    │  allocs/op   vs base                │
```
2026-07-04 13:25:35 +02:00
dependabot[bot] 332d5ec823 build(deps): bump golang.org/x/mod from 0.36.0 to 0.37.0
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.36.0 to 0.37.0.
- [Commits](https://github.com/golang/mod/compare/v0.36.0...v0.37.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  dependency-version: 0.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-04 12:54:41 +02:00
dependabot[bot] 212cc11ada build(deps): bump github.com/pelletier/go-toml/v2 from 2.3.1 to 2.4.2
Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.3.1 to 2.4.2.
- [Release notes](https://github.com/pelletier/go-toml/releases)
- [Commits](https://github.com/pelletier/go-toml/compare/v2.3.1...v2.4.2)

---
updated-dependencies:
- dependency-name: github.com/pelletier/go-toml/v2
  dependency-version: 2.4.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-04 12:54:04 +02:00
Bjørn Erik Pedersen dfb35dcd7a tpl/crypto: Add crypto.Hash
Add a generic crypto.Hash template function returning the hex-encoded
checksum of a string using one of md5, sha1, sha256 (default), sha384 or
sha512. The supported algorithms match those used for the SRI hash in
.Data.Integrity on fingerprinted resources, so an SRI hash can be built
by composing with encoding.HexDecode and encoding.Base64Encode.

Fixes #15072

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 18:03:05 +02:00
Bjørn Erik Pedersen ef053faa6a Merge commit 'af91eb1997ace34ef5eed0be31646e8483b78096' 2026-07-03 10:43:53 +02:00
Bjørn Erik Pedersen af91eb1997 Squashed 'docs/' changes from e17426e2b6..c85af679bf
c85af679bf content: Miscellaneous edits
43149dae59 content: Cleanup trailing spaces
2b161d600c content: Improve hosting guides
edc02f6402 content: Improve description of scheduled Cloudflare builds
83dff65d50 content: Fix typos
a93f8b956b content: Fix formatting
3dde5702c7 content: Add instructions for scheduled Cloudflare builds
b1075d9c77 content: Change wrangler config format in Cloudflare hosting guide
565d3292c3 content: Add .mjs and .cjs variants to mounted config files
4fc418d223 content: Update version references
bf2efc9114 content: Update hosting guides
0d8ff2dfe1 Update HUGO_VERSION to 0.163.3

git-subtree-dir: docs
git-subtree-split: c85af679bfe21dd7c01924c47933444f002bdc6b
2026-07-03 10:43:53 +02:00
Bjørn Erik Pedersen a5ec542393 Add encoding.HexDecode/Encode
Fixes #15068
See #15060
2026-06-28 21:39:51 +02:00
Bjørn Erik Pedersen 884439b9a2 deps: Upgrade github.com/evanw/esbuild v0.28.0 => v0.28.1
Test / test (1.26.x, ubuntu-latest) (push) Has been cancelled
Test / test (1.26.x, windows-latest) (push) Has been cancelled
Closes #15033
2026-06-28 19:07:48 +02:00
Joe Mooring 128fb17c2b markup/pandoc: Add citation support
Closes #15062

Co-authored-by: Sebastian Höffner <info@sebastian-hoeffner.de>
2026-06-28 15:37:21 +02:00
Joe Mooring e46d37a984 tpl/tplimpl: Make template name lookup case-insensitive
Closes #15057

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 15:36:29 +02:00
Bjørn Erik Pedersen 790a8aa474 deps: Add Chroma dark/light mode support
Test / test (1.26.x, ubuntu-latest) (push) Has been cancelled
Test / test (1.26.x, windows-latest) (push) Has been cancelled
Closes #15017
2026-06-27 18:21:20 +02:00
Joe Mooring fe06735214 hugolib: Return error from .Render when template not found
Closes #15052
2026-06-25 12:09:52 +02:00
hugoreleaser d15baf53a9 releaser: Prepare repository for 0.164.0-DEV
[ci skip]
2026-06-18 16:39:26 +00:00
hugoreleaser 4d22555aeb releaser: Bump versions for release of 0.163.3
[ci skip]
2026-06-18 16:18:24 +00:00
Bjørn Erik Pedersen ce1a7e0bce markup/highlight: Escape lang in default code block rendering 2026-06-18 18:14:40 +02:00
Bjørn Erik Pedersen c86d9f4aa8 Squashed 'docs/' changes from 1f8ddb8a52..e17426e2b6
e17426e2b6 content: Adjust Cloudflare hosting guide
02edafd770 content: Add build caching instructions for Cloudflare Workers
3430b3c154 content: Update version references
ed8f6930e6 content: Fix examples
3e1a3030ab content: Miscellaneous edits
77f12f75d7 Update HUGO_VERSION to 0.163.2
943417e8f2 content: Remove Hugo SFTP Upload from community tools
62d04f0440 content: Add --global to git config command in CI/CD examples
b9fd5b6cad content: Document GitInfo limitation
9d28aa9e0e content: Fix link references
66bba81f82 content: Fix link references
b08128c0aa content: Fix function reference
2da3083578 content: Miscellaneous edits
40e048f605 content: Use consistent terminology for configuration settings
1b8d67c3fe content: Add HUGO_ENVIRONMENT to the configuration introduction
a931241abe content: Remove erroneous config setting
d621e2c38b Update HUGO_VERSION to 0.163.1
a23a5a0465 content: Fix fenced code block
1122f0e8b5 content: Fix typo
076184e983 content: Miscellaneous standardization edits
b53b801061 theme: Adjust code language substitutions
6fe0cc5f77 content: Fix formatting
f6fc643110 content: Fix link
8e9cdfb9e9 content: Fix link
ae2e15a51e content: Fix links
c73fefee7a content: Fix formatting
9d0390e927 content: Fix link destinations
938a76e00f content: Update comments.md
01d66b670c content: Fix typos
d1e70b81cb content: Improve segmentation documentation
a2a2f89f7f content: Clarify applicability of format-specific imaging config keys
e6c487eb80 content: Remove outdated feature badge
39aebec026 content: Updates for v0.163.0
e9bd8eca6b Update HUGO_VERSION to 0.163.0
f088cf8d19 content: Update hosting guides
ce481a8798 content: Fix broken links
e1f09a8783 content: Remove hidden showcases
54f3a7651e content: Standardize link references
344f8d660e theme: Add nofollow to external links
a83ccec106 theme: Remove the qr transition
5e73f514b4 theme: Hide the search modal on pageswap
57f89ce22d theme: Trim https://gohugo.io from search results when running the server
f12aa1d1d0 content: Fix formatting in Defer
5ab496dd2a content: Add FastComments to the list of commenting systems
1819171668 theme: Remove some unused code
218754408b theme: Replace Turbo with Speculation Rules
bddc24beff content: Fix typos
1a3b527595 content: Fix typo
b72ccefbd9 content: Fix typo
4bfd6c937f content: Miscellaneous link edits
4b57ca8555 content: Clarify :filename slug inference in front matter config
5b1a03ff68 content: Remove outdated new-in badges
bcc6647be8 content: Fix link
263efb81ec content: Add front matter to core-methods.md
41e27e2e54 theme: Render function/method link titles as inline code
8875ef7fe6 content: Replace "scratch pad" with clearer data structure terminology
6e186e591d Update HUGO_VERSION to 0.162.1
30a90c961d content: Add missing configuration key data types
c8e5b9fd2d content: Replace h3 method sequences with description lists
8b44afbe31 content: Fix typo
04109b0921 content: Change collections.Dictionary note regarding nil map
9de560ca01 content: Remove Commento from comments integration list
d2d1506598 content: Update PostCSS examples
6c4bd3a096 content: Updates for v0.162.0
46e6e2c66d Update HUGO_VERSION to 0.162.0
6900d27eea content: Remove date from content file
2c1e04da4a theme: Darken inline code elements in content for better readability
1c5bd6a4b4 content: Clarify resources.Copy publication path
911c1c7549 content: Wrap relevant description list terms in backticks
740e887e05 misc: Remove VS Code extension suggestions

git-subtree-dir: docs
git-subtree-split: e17426e2b63dafe06354e7a204ce61506dc79dc3
2026-06-18 16:28:21 +02:00
Bjørn Erik Pedersen e8988c3141 Merge commit 'c86d9f4aa8a58931f52df6516f10b67c807505fb' 2026-06-18 16:28:21 +02:00
Bjørn Erik Pedersen 70a9068aa6 parser/pageparser: Preserve non-ASCII whitespace after e.g. summary divider
Make it insted consume just ASCII whitespace, which preserves e.g. ideographic space (U+3000) after the summary divider, which is important for e.g. Chinese and Japanese content, and possibly other Unicode whitespace characters with meaning.

Doing this is possibly breaking, but not likely, and obviously the correct thing to do.
2026-06-18 16:23:06 +02:00
Joe Mooring 9d66d513ce resources: Support babel/postcss config variants
Allow modules to use .mjs and .cjs file extensions for Babel and PostCSS
configuration files instead of just .js.

Closes #15039
Closes #15040
Closes #15043
2026-06-18 16:22:10 +02:00
Joe Mooring f013346667 hugolib: Fix page/section name collision regression
Fixes #15046

When a regular page (e.g. content/s1.md) and a section (content/s1/)
share the same tree key, the assembler must not overwrite the real page
with a synthetic section. Restore the existence guard that was present
in v0.152.2.

The fix checks if a node already exists at the section key before
inserting a synthetic section during root section creation.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-18 16:20:34 +02:00
hugoreleaser 96e06e1ab8 releaser: Prepare repository for 0.164.0-DEV
[ci skip]
2026-06-15 15:17:37 +00:00
hugoreleaser 19a5cec0b9 releaser: Bump versions for release of 0.163.2
[ci skip]
2026-06-15 14:55:00 +00:00
Bjørn Erik Pedersen 134674f00d Continue resolving on ERR_ACCESS_DENIED in Node's resolver
And then rethrow the ERR_ACCESS_DENIED if we cannot recover.

There's more details in #15041, but this error has been seen on Netlify with the CJS because of how Netlify has their node_modules cache folder set up.

Fixes #15041
2026-06-15 15:53:19 +02:00
Joe Mooring 147f605f7d markup: Standardize behavior when external converters are missing
Closes #14222
2026-06-13 20:19:47 +02:00
hugoreleaser 1f35beb918 releaser: Prepare repository for 0.164.0-DEV
[ci skip]
2026-06-11 15:55:44 +00:00
hugoreleaser 2a4fd58818 releaser: Bump versions for release of 0.163.1
[ci skip]
2026-06-11 15:34:40 +00:00
dependabot[bot] 93c8c7d345 build(deps): bump golang.org/x/image from 0.41.0 to 0.42.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.41.0 to 0.42.0.
- [Commits](https://github.com/golang/image/compare/v0.41.0...v0.42.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-version: 0.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-11 16:15:56 +02:00
Bjørn Erik Pedersen 95e5e9f4ab Fix multi --renderSegments merge behavior
Fixes #15024
2026-06-11 15:25:43 +02:00
Bjørn Erik Pedersen a00b5c72ac security: Normalize integer IPv4 host encodings in http.urls check
Canonicalize integer/hex/octal IPv4 hosts to dotted-decimal before
applying the security.http.urls policy so all encodings of an address
are treated alike.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 18:53:36 +02:00
Bjørn Erik Pedersen cf9c8f93ca Drop symlinks in os.ReadDir, os.ReadFile, os.Stat and os.FileExists
Fixes #15019
2026-06-10 18:53:36 +02:00
Bjørn Erik Pedersen 11f09f59fc Update CI workflow to exclude macOS
Removed macOS from the CI test matrix.
2026-06-09 14:34:07 +02:00
Joe Mooring 2602796cf1 commands: Fix convert command
Closes #15012
2026-06-09 13:02:26 +02:00
hugoreleaser 72495f9fba releaser: Prepare repository for 0.164.0-DEV
[ci skip]
2026-06-08 14:36:12 +00:00
hugoreleaser 4a9485336a releaser: Bump versions for release of 0.163.0
[ci skip]
2026-06-08 14:13:03 +00:00
anupamojha-eng 1d018ef857 pagesfromdata: Use relative path for content adapter template metrics
Fixes #14999
2026-06-08 15:56:47 +02:00
Bjørn Erik Pedersen 121bc6ceb2 ci: Re-add macos-latest to the test matrix
I suspect there will be some disk space issue, but let's try.
2026-06-08 15:55:43 +02:00
dependabot[bot] 0d29fc81bb build(deps): bump github.com/bits-and-blooms/bitset
Bumps [github.com/bits-and-blooms/bitset](https://github.com/bits-and-blooms/bitset) from 1.24.4 to 1.24.5.
- [Release notes](https://github.com/bits-and-blooms/bitset/releases)
- [Commits](https://github.com/bits-and-blooms/bitset/compare/v1.24.4...v1.24.5)

---
updated-dependencies:
- dependency-name: github.com/bits-and-blooms/bitset
  dependency-version: 1.24.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 11:32:09 +02:00
dependabot[bot] bb57404f3d build(deps): bump github.com/tetratelabs/wazero
Bumps [github.com/tetratelabs/wazero](https://github.com/tetratelabs/wazero) from 1.11.1-0.20260521072212-475a1f8f0dc3 to 1.12.0.
- [Release notes](https://github.com/tetratelabs/wazero/releases)
- [Commits](https://github.com/tetratelabs/wazero/commits/v1.12.0)

---
updated-dependencies:
- dependency-name: github.com/tetratelabs/wazero
  dependency-version: 1.12.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-08 11:31:32 +02:00
Bjørn Erik Pedersen 781fabf4e4 all: Run go fix ./... 2026-06-07 21:20:40 +02:00
Bjørn Erik Pedersen cf18b827e2 images: Deprecate Imaging.Compression and move it down to webp and avif configs
Also clean up and simplify the image config handling.

Closes #14998
2026-06-07 21:20:16 +02:00
Bjørn Erik Pedersen 98ad9b3c03 Only support the latest Go version
Which is currently Go 1.26.

Closes #14997
2026-06-07 17:01:04 +02:00
Bjørn Erik Pedersen ff2903a931 resources/jsconfig: Remove deprecated baseUrl setting
baseUrl is deprecated in TypeScript and is no longer required when
paths is set (TypeScript 4.1+).

Fixes #14991
Closes #14996
2026-06-07 13:35:25 +02:00
dependabot[bot] 7d1b1fb33d build(deps): bump github.com/rogpeppe/go-internal from 1.14.1 to 1.15.0
Bumps [github.com/rogpeppe/go-internal](https://github.com/rogpeppe/go-internal) from 1.14.1 to 1.15.0.
- [Release notes](https://github.com/rogpeppe/go-internal/releases)
- [Commits](https://github.com/rogpeppe/go-internal/compare/v1.14.1...v1.15.0)

---
updated-dependencies:
- dependency-name: github.com/rogpeppe/go-internal
  dependency-version: 1.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-05 19:05:57 +02:00
Bjørn Erik Pedersen b89e7fe675 page: Add IsBranch and deprecate IsNode
IsNode's meaning was murky. Add IsBranch, defined as the set of branch
node kinds (home, section, taxonomy, term), and make IsNode a deprecated
alias for it.

Fixes #11574

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 16:18:57 +02:00
Bjørn Erik Pedersen e8fefc8388 images: Force cache invalidation for AVIF target
Fixes #14990
2026-06-05 16:18:23 +02:00
Bjørn Erik Pedersen a043d3ec63 images: Add a per-format AVIF hint setting
The hint setting controls WebP encoding (preset) and AVIF encoding
(chroma subsampling), but only lived on imaging.webp. Add imaging.avif.hint
so it shows up under the AVIF section in the docs, with the same root-level
backwards compatibility as imaging.webp.hint. Per-image hint now resolves
from the target format.

Fixes #14992

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 16:16:38 +02:00
dependabot[bot] 77a1147056 build(deps): bump github.com/getkin/kin-openapi from 0.138.0 to 0.139.0
Bumps [github.com/getkin/kin-openapi](https://github.com/getkin/kin-openapi) from 0.138.0 to 0.139.0.
- [Release notes](https://github.com/getkin/kin-openapi/releases)
- [Commits](https://github.com/getkin/kin-openapi/compare/v0.138.0...v0.139.0)

---
updated-dependencies:
- dependency-name: github.com/getkin/kin-openapi
  dependency-version: 0.139.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-06-05 16:16:00 +02:00
Bjørn Erik Pedersen 341f575d2d images: Make AVIF chroma subsampling content-aware via the hint
Encode photo/picture hints (and the default) as YUV420 instead of YUV444,
keeping 444 for text/icon/drawing. Lossless stays 444.

This roughly halves the encoder's peak memory (42 -> 27 MiB/MP) and the
output size, while 444 remains available for sharp-edged content. A
3000x3000 image now needs ~239 MiB to encode, down from ~381 MiB (which
sat right at the 384 MiB WASM cap).

Closes #14987

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 18:54:56 +02:00
Bjørn Erik Pedersen 248241b6e1 Cap AVIF lossy quality at 99
Before this commit, lossy compression with 100 quality meant lossless compression, leading to a big gap between 99 and 100.

This commit caps the lossy quality at 99, ensuring that lossy compression is always lossy.

Fixes #14981
2026-06-04 14:42:08 +02:00
Bjørn Erik Pedersen 4e47d95db9 config: Deprecate the glogal imaging quality setting
In favour of the new per-image quality setting.

See #14979
2026-06-04 11:07:34 +02:00
Bjørn Erik Pedersen 03b4b54220 images: Make 60 the default quality for AVIF
AVIF's quality scale is not perceptually comparable to JPEG/WebP:
libavif anchors its "good" default at 60, where Hugo's universal 75
produced visibly higher quality and larger files. AVIF now defaults to
60 while JPEG and WebP keep 75. An explicit imaging.quality,
imaging.avif.quality or a per-image qNN still wins.

Fixes #14979

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 11:07:34 +02:00
Bjørn Erik Pedersen 79be0532f1 livereload: Disconnect from websocket server on pageswap
Fixes #14983
2026-06-04 11:04:39 +02:00
Bjørn Erik Pedersen 0f440460c8 tpl/tplimpl/embedded: Prevent leading newline in sitemap template
Fixes #14977
2026-06-04 11:03:03 +02:00
Bjørn Erik Pedersen 4e17421ec2 images: Recover from memory alloc errors in WASM image processors
Fixes #14985
2026-06-04 11:01:49 +02:00
Bjørn Erik Pedersen b01ecd4cd4 images: Add quality setting per image format
Allow setting quality per output format via imaging.jpeg.quality,
imaging.webp.quality and imaging.avif.quality. Each falls back to the
global imaging.quality when unset, and a per-image qNN still wins.

Fixes #14957

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 20:43:55 +02:00
Joe Mooring ca68936d61 all: Adjust tests for deprecated link and image render hook settings 2026-06-01 15:52:34 +02:00
Joe Mooring 45c00b7c16 misc: Remove duplicate words in comments
Closes #14936
Closes #14950
Closes #14965
2026-05-29 17:54:14 +02:00
Bjørn Erik Pedersen 28d882ab70 Add some PNG to AVIF golden test cases
Both 8 and 24 bit PNG to AVIF with vivid colors.

The output looks good to me ...

https://discourse.gohugo.io/t/v0-162-0-avif-image-processing-strips-washes-out-colors-on-vector-graphics/57210
2026-05-29 11:28:27 +02:00
hugoreleaser b0fd7ee2e1 releaser: Prepare repository for 0.163.0-DEV
[ci skip]
2026-05-28 18:03:30 +00:00
hugoreleaser bba860e3ed releaser: Bump versions for release of 0.162.1
[ci skip]
2026-05-28 17:40:44 +00:00
Joe Mooring 59f35cd985 modules/npm: Fix false stale warning after npm pack
Closes #14959

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 18:57:41 +02:00
Joe Mooring 21e9868fe2 tpl/tplimpl: Fix X shortcode test 2026-05-28 09:26:45 +02:00
Bjørn Erik Pedersen 2760288c6d tpl: Skip broken x shortcode test 2026-05-27 21:21:35 +02:00
Bjørn Erik Pedersen c270975049 Revert "tpl/collections: Make dict return nil when no values are provided"
This reverts commit 17a86ef5ed.

Closes #14958
2026-05-27 20:02:55 +02:00
Joe Mooring ea8b48af64 tpl/time: Fix locale-specific month abbreviations
Closes #14948
2026-05-27 12:38:21 +02:00
801 changed files with 12513 additions and 7528 deletions
+2 -2
View File
@@ -4,7 +4,7 @@ parameters:
defaults: &defaults
resource_class: large
docker:
- image: bepsays/ci-hugoreleaser:1.22600.20300
- image: bepsays/ci-hugoreleaser:1.22600.20500
environment: &buildenv
GOMODCACHE: /root/project/gomodcache
version: 2
@@ -58,7 +58,7 @@ jobs:
environment:
<<: [*buildenv]
docker:
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22600.20300
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22600.20500
steps:
- *restore-cache
- &attach-workspace
-13
View File
@@ -1,13 +0,0 @@
have_fun: false
memory_config:
disabled: false
code_review:
disable: false
comment_severity_threshold: HIGH
max_review_comments: -1
pull_request_opened:
help: true
summary: false
code_review: false
include_drafts: false
ignore_patterns: []
+4 -6
View File
@@ -16,8 +16,8 @@ jobs:
test:
strategy:
matrix:
go-version: [1.25.x, 1.26.x]
os: [ubuntu-latest, windows-latest] # macos disabled for now because of disk space issues.
go-version: [1.26.x]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- if: matrix.os == 'ubuntu-latest'
@@ -39,9 +39,6 @@ jobs:
go-version: ${{ matrix.go-version }}
check-latest: true
cache: true
cache-dependency-path: |
**/go.sum
**/go.mod
- name: Install Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
@@ -54,6 +51,7 @@ jobs:
run: |
gem install asciidoctor -v "2.0.26"
gem install asciidoctor-diagram -v "3.1.0"
gem install asciidoctor-html5s -v "0.5.1"
- name: Install GoAT
run: go install github.com/blampe/goat/cmd/goat@177de93b192b8ffae608e5d9ec421cc99bf68402
- name: Install Python
@@ -66,7 +64,7 @@ jobs:
run: go install github.com/gohugoio/gotmplfmt@latest
- name: Install docutils
run: |
pip install docutils
pip install docutils Pygments
rst2html --version
- if: matrix.os == 'ubuntu-latest'
name: Install pandoc on Linux
+2 -1
View File
@@ -5,4 +5,5 @@ dist/
public/
.DS_Store
cache/filecache/_gen/
.claude/
.claude/
dump.txt
+1
View File
@@ -12,6 +12,7 @@
* In tests, use `qt` matchers (e.g. `b.Assert(err, qt.ErrorMatches, ...)`) instead of raw `if`/`t.Fatal` checks.
* In tests, always use the latest Hugo specification, e.g. for layouts, it's `layouts/page.html` and not `layouts/_default/single.html`, `layouts/list.html` and not `layouts/_default/list.html`
* Never name tests `TestIssue1234`; always give the test function a descriptive name, e.g. `TestDisablePathToLower`, and add any issue reference as a Go doc function comment, e.g. `// See issue 1234.`.
* If you borrow a test case (e.g. from the issue), that test's author must be added as co-author in the commit.
* If you're a security researcher, read @SECURITY.md carefully.
* Brevity is good. This applies to code, comments and commit messages. Don't write a novel.
* Use `./check.sh ./somepackage/...` when iterating.
+1
View File
@@ -72,6 +72,7 @@ To make the contribution process as seamless as possible, we ask for the followi
* When youre ready to create a pull request, be sure to:
* Sign the [CLA](https://cla-assistant.io/gohugoio/hugo).
* Have test cases for the new code. If you have questions about how to do this, please ask in your pull request.
* If you borrow a test case (e.g. from the issue), that test's author must be added as [co-author](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors) in the commit.
* Run `go fmt`.
* Add documentation if you are adding new features or changing functionality. The docs site lives in `/docs`.
* Squash your commits into a single commit. `git rebase -i`. Its okay to force update your pull request with `git push -f`.
+123 -66
View File
@@ -37,7 +37,6 @@ A fast and flexible static site generator built with love by [bep][], [spf13][],
[![GoDoc](https://godoc.org/github.com/gohugoio/hugo?status.svg)](https://godoc.org/github.com/gohugoio/hugo)
[![Tests on Linux, MacOS and Windows](https://github.com/gohugoio/hugo/workflows/Test/badge.svg)](https://github.com/gohugoio/hugo/actions?query=workflow%3ATest)
[![Go Report Card](https://goreportcard.com/badge/github.com/gohugoio/hugo)](https://goreportcard.com/report/github.com/gohugoio/hugo)
[Website][] | [Installation][] | [Documentation][] | [Support][] | [Contributing][] | <a rel="me" href="https://fosstodon.org/@gohugoio">Mastodon</a>
@@ -105,7 +104,7 @@ Install Hugo from a [prebuilt binary][], package manager, or package repository.
To build Hugo from source you must install:
1. [Git][]
1. [Go][] version 1.25.0 or later
1. [Go][] version 1.26.0 or later
### Standard edition
@@ -139,10 +138,6 @@ To build and install the extended/deploy edition, first install a C compiler suc
CGO_ENABLED=1 go install -tags extended,withdeploy github.com/gohugoio/hugo@latest
```
## Star History
[![Star History Chart](https://api.star-history.com/svg?repos=gohugoio/hugo&type=Timeline)](https://star-history.com/#gohugoio/hugo&Timeline)
## Documentation
Hugo's [documentation][] includes installation instructions, a quick start guide, conceptual explanations, reference information, and examples.
@@ -195,10 +190,48 @@ Hugo stands on the shoulders of great open source libraries. Run `hugo env --log
<summary>See current dependencies</summary>
```text
cel.dev/expr="v0.25.1"
cloud.google.com/go/auth/oauth2adapt="v0.2.8"
cloud.google.com/go/auth="v0.20.0"
cloud.google.com/go/compute/metadata="v0.9.0"
cloud.google.com/go/iam="v1.5.3"
cloud.google.com/go/monitoring="v1.24.3"
cloud.google.com/go/storage="v1.57.2"
cloud.google.com/go="v0.123.0"
github.com/Azure/azure-sdk-for-go/sdk/azcore="v1.20.0"
github.com/Azure/azure-sdk-for-go/sdk/azidentity="v1.13.1"
github.com/Azure/azure-sdk-for-go/sdk/internal="v1.11.2"
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob="v1.6.3"
github.com/Azure/go-autorest/autorest/to="v0.4.1"
github.com/AzureAD/microsoft-authentication-library-for-go="v1.6.0"
github.com/BurntSushi/locker="v0.0.0-20171006230638-a6e239ea1c69"
github.com/JohannesKaufmann/dom="v0.2.0"
github.com/JohannesKaufmann/html-to-markdown/v2="v2.5.0"
github.com/alecthomas/chroma/v2="v2.21.1"
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp="v1.31.0"
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric="v0.54.0"
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping="v0.54.0"
github.com/JohannesKaufmann/dom="v0.3.1"
github.com/JohannesKaufmann/html-to-markdown/v2="v2.5.2"
github.com/alecthomas/chroma/v2="v2.27.0"
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream="v1.7.8"
github.com/aws/aws-sdk-go-v2/config="v1.32.2"
github.com/aws/aws-sdk-go-v2/credentials="v1.19.2"
github.com/aws/aws-sdk-go-v2/feature/ec2/imds="v1.18.14"
github.com/aws/aws-sdk-go-v2/feature/s3/manager="v1.20.12"
github.com/aws/aws-sdk-go-v2/internal/configsources="v1.4.22"
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2="v2.7.22"
github.com/aws/aws-sdk-go-v2/internal/ini="v1.8.4"
github.com/aws/aws-sdk-go-v2/internal/v4a="v1.4.22"
github.com/aws/aws-sdk-go-v2/service/cloudfront="v1.61.1"
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding="v1.13.7"
github.com/aws/aws-sdk-go-v2/service/internal/checksum="v1.9.13"
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url="v1.13.21"
github.com/aws/aws-sdk-go-v2/service/internal/s3shared="v1.19.21"
github.com/aws/aws-sdk-go-v2/service/s3="v1.97.3"
github.com/aws/aws-sdk-go-v2/service/signin="v1.0.2"
github.com/aws/aws-sdk-go-v2/service/sso="v1.30.5"
github.com/aws/aws-sdk-go-v2/service/ssooidc="v1.35.10"
github.com/aws/aws-sdk-go-v2/service/sts="v1.41.2"
github.com/aws/aws-sdk-go-v2="v1.41.6"
github.com/aws/smithy-go="v1.25.0"
github.com/aymerick/douceur="v0.2.0"
github.com/bep/clocks="v0.5.0"
github.com/bep/debounce="v1.2.0"
@@ -206,105 +239,129 @@ github.com/bep/gitmap="v1.9.0"
github.com/bep/goat="v0.5.0"
github.com/bep/godartsass/v2="v2.5.0"
github.com/bep/golibsass="v1.2.0"
github.com/bep/goportabletext="v0.1.0"
github.com/bep/helpers="v0.6.0"
github.com/bep/imagemeta="v0.12.0"
github.com/bep/lazycache="v0.8.0"
github.com/bep/golocales="v0.2.0"
github.com/bep/goportabletext="v0.2.0"
github.com/bep/helpers="v0.12.0"
github.com/bep/imagemeta="v0.17.2"
github.com/bep/lazycache="v0.8.1"
github.com/bep/logg="v0.4.0"
github.com/bep/mclib="v1.20400.20402"
github.com/bep/overlayfs="v0.10.0"
github.com/bep/simplecobra="v0.6.1"
github.com/bep/textandbinarywriter="v0.0.0-20251212174530-cd9f0732f60f"
github.com/bep/tmc="v0.5.1"
github.com/bits-and-blooms/bitset="v1.24.4"
github.com/bep/mclib="v1.20401.20400"
github.com/bep/overlayfs="v0.11.0"
github.com/bep/simplecobra="v0.7.0"
github.com/bep/textandbinarywriter="v0.1.0"
github.com/bep/tmc="v0.6.0"
github.com/bits-and-blooms/bitset="v1.24.5"
github.com/cespare/xxhash/v2="v2.3.0"
github.com/clbanning/mxj/v2="v2.7.0"
github.com/clipperhouse/displaywidth="v0.6.0"
github.com/clipperhouse/stringish="v0.1.1"
github.com/clipperhouse/uax29/v2="v2.3.0"
github.com/clipperhouse/displaywidth="v0.10.0"
github.com/clipperhouse/uax29/v2="v2.6.0"
github.com/cncf/xds/go="v0.0.0-20251210132809-ee656c7534f5"
github.com/cpuguy83/go-md2man/v2="v2.0.6"
github.com/disintegration/gift="v1.2.1"
github.com/dlclark/regexp2="v1.11.5"
github.com/evanw/esbuild="v0.27.2"
github.com/dlclark/regexp2/v2="v2.2.1"
github.com/dustin/go-humanize="v1.0.1"
github.com/envoyproxy/go-control-plane/envoy="v1.36.0"
github.com/envoyproxy/protoc-gen-validate="v1.3.0"
github.com/evanw/esbuild="v0.28.1"
github.com/fatih/color="v1.18.0"
github.com/felixge/httpsnoop="v1.0.4"
github.com/frankban/quicktest="v1.14.6"
github.com/fsnotify/fsnotify="v1.9.0"
github.com/getkin/kin-openapi="v0.133.0"
github.com/go-openapi/jsonpointer="v0.21.0"
github.com/go-openapi/swag="v0.23.0"
github.com/getkin/kin-openapi="v0.140.0"
github.com/go-jose/go-jose/v4="v4.1.4"
github.com/go-logr/logr="v1.4.3"
github.com/go-logr/stdr="v1.2.2"
github.com/go-openapi/jsonpointer="v0.22.5"
github.com/go-openapi/swag/jsonname="v0.25.5"
github.com/gobuffalo/flect="v1.0.3"
github.com/gobwas/glob="v0.2.3"
github.com/goccy/go-yaml="v1.19.1"
github.com/goccy/go-yaml="v1.19.2"
github.com/gohugoio/gift="v0.2.0"
github.com/gohugoio/go-i18n/v2="v2.1.3-0.20251018145728-cfcc22d823c6"
github.com/gohugoio/go-radix="v1.2.0"
github.com/gohugoio/hashstructure="v0.6.0"
github.com/gohugoio/httpcache="v0.8.0"
github.com/gohugoio/hugo-goldmark-extensions/extras="v0.5.0"
github.com/gohugoio/hugo-goldmark-extensions/passthrough="v0.3.1"
github.com/gohugoio/locales="v0.14.0"
github.com/gohugoio/localescompressed="v1.0.1"
github.com/gohugoio/hugo-goldmark-extensions/extras="v0.7.0"
github.com/gohugoio/hugo-goldmark-extensions/passthrough="v0.5.0"
github.com/golang-jwt/jwt/v5="v5.3.0"
github.com/google/go-cmp="v0.7.0"
github.com/google/s2a-go="v0.1.9"
github.com/google/uuid="v1.6.0"
github.com/google/wire="v0.7.0"
github.com/googleapis/enterprise-certificate-proxy="v0.3.14"
github.com/googleapis/gax-go/v2="v2.21.0"
github.com/gorilla/css="v1.0.1"
github.com/gorilla/websocket="v1.5.3"
github.com/hairyhenderson/go-codeowners="v0.7.0"
github.com/hashicorp/golang-lru/v2="v2.0.7"
github.com/jdkato/prose="v1.2.1"
github.com/josharian/intern="v1.0.0"
github.com/kr/pretty="v0.3.1"
github.com/kr/text="v0.2.0"
github.com/kylelemons/godebug="v1.1.0"
github.com/kyokomi/emoji/v2="v2.2.13"
github.com/mailru/easyjson="v0.7.7"
github.com/makeworld-the-better-one/dither/v2="v2.4.0"
github.com/marekm4/color-extractor="v1.2.1"
github.com/mattn/go-colorable="v0.1.13"
github.com/mattn/go-isatty="v0.0.20"
github.com/mattn/go-colorable="v0.1.14"
github.com/mattn/go-isatty="v0.0.22"
github.com/mattn/go-runewidth="v0.0.19"
github.com/microcosm-cc/bluemonday="v1.0.27"
github.com/mitchellh/mapstructure="v1.5.1-0.20231216201459-8508981c8b6c"
github.com/mohae/deepcopy="v0.0.0-20170929034955-c48cc78d4826"
github.com/muesli/smartcrop="v0.3.0"
github.com/niklasfasching/go-org="v1.9.1"
github.com/oasdiff/yaml3="v0.0.0-20250309153720-d2182401db90"
github.com/oasdiff/yaml="v0.0.0-20250309154309-f31be36b4037"
github.com/oasdiff/yaml3="v0.0.13"
github.com/oasdiff/yaml="v0.1.0"
github.com/olekukonko/cat="v0.0.0-20250911104152-50322a0618f6"
github.com/olekukonko/errors="v1.1.0"
github.com/olekukonko/ll="v0.1.3"
github.com/olekukonko/tablewriter="v1.1.2"
github.com/olekukonko/errors="v1.2.0"
github.com/olekukonko/ll="v0.1.6"
github.com/olekukonko/tablewriter="v1.1.4"
github.com/pbnjay/memory="v0.0.0-20210728143218-7b4eea64cf58"
github.com/pelletier/go-toml/v2="v2.2.4"
github.com/perimeterx/marshmallow="v1.1.5"
github.com/pelletier/go-toml/v2="v2.4.3"
github.com/pkg/browser="v0.0.0-20240102092130-5ac0b6a4141c"
github.com/pkg/errors="v0.9.1"
github.com/rogpeppe/go-internal="v1.14.1"
github.com/rogpeppe/go-internal="v1.15.0"
github.com/russross/blackfriday/v2="v2.1.0"
github.com/sass/dart-sass/compiler="1.97.1"
github.com/sass/dart-sass/implementation="1.97.1"
github.com/sass/dart-sass/protocol="3.2.0"
github.com/santhosh-tekuri/jsonschema/v6="v6.0.2"
github.com/spf13/afero="v1.15.0"
github.com/spf13/cast="v1.10.0"
github.com/spf13/cobra="v1.10.2"
github.com/spf13/fsync="v0.10.1"
github.com/spf13/pflag="v1.0.9"
github.com/tdewolff/minify/v2="v2.24.8"
github.com/tdewolff/parse/v2="v2.8.5"
github.com/tetratelabs/wazero="v1.10.1"
github.com/spf13/pflag="v1.0.10"
github.com/spiffe/go-spiffe/v2="v2.6.0"
github.com/tdewolff/minify/v2="v2.24.13"
github.com/tdewolff/parse/v2="v2.8.12"
github.com/tetratelabs/wazero="v1.12.0"
github.com/webmproject/libwebp="v1.6.0"
github.com/woodsbury/decimal128="v1.3.0"
github.com/yuin/goldmark-emoji="v1.0.6"
github.com/yuin/goldmark="v1.7.13"
github.com/yuin/goldmark="v1.8.2"
go.opentelemetry.io/auto/sdk="v1.2.1"
go.opentelemetry.io/contrib/detectors/gcp="v1.39.0"
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc="v0.67.0"
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp="v0.67.0"
go.opentelemetry.io/otel/metric="v1.43.0"
go.opentelemetry.io/otel/sdk/metric="v1.43.0"
go.opentelemetry.io/otel/sdk="v1.43.0"
go.opentelemetry.io/otel/trace="v1.43.0"
go.opentelemetry.io/otel="v1.43.0"
go.uber.org/automaxprocs="v1.5.3"
go.yaml.in/yaml/v3="v3.0.4"
golang.org/x/crypto="v0.46.0"
golang.org/x/image="v0.34.0"
golang.org/x/mod="v0.31.0"
golang.org/x/net="v0.48.0"
golang.org/x/sync="v0.19.0"
golang.org/x/sys="v0.39.0"
golang.org/x/text="v0.32.0"
golang.org/x/tools="v0.40.0"
google.golang.org/protobuf="v1.36.10"
gopkg.in/yaml.v3="v3.0.1"
gocloud.dev="v0.45.0"
golang.org/x/crypto="v0.53.0"
golang.org/x/image="v0.43.0"
golang.org/x/mod="v0.37.0"
golang.org/x/net="v0.56.0"
golang.org/x/oauth2="v0.36.0"
golang.org/x/sync="v0.21.0"
golang.org/x/sys="v0.46.0"
golang.org/x/text="v0.38.0"
golang.org/x/time="v0.15.0"
golang.org/x/tools="v0.47.0"
golang.org/x/xerrors="v0.0.0-20240903120638-7835f813f4da"
google.golang.org/api="v0.276.0"
google.golang.org/genproto/googleapis/api="v0.0.0-20260319201613-d00831a3d3e7"
google.golang.org/genproto/googleapis/rpc="v0.0.0-20260401024825-9d38bb4040a9"
google.golang.org/genproto="v0.0.0-20260319201613-d00831a3d3e7"
google.golang.org/grpc="v1.80.0"
google.golang.org/protobuf="v1.36.11"
rsc.io/qr="v0.2.0"
software.sslmate.com/src/go-pkcs12="v0.2.0"
software.sslmate.com/src/go-pkcs12="v0.7.0"
```
</details>
+54 -13
View File
@@ -17,6 +17,7 @@ import (
"fmt"
"io"
"os"
"strings"
"github.com/gohugoio/hugo/common/herrors"
"github.com/gohugoio/hugo/hugofs"
@@ -59,6 +60,29 @@ func (c *Cache) Prune(force bool) (int, error) {
counter := 0
seen := c.entryLocker.seen
seenByLower := make(map[string]string, seen.Len())
for id := range seen.All() {
seenByLower[strings.ToLower(id)] = id
}
// Names on disk matching a used cache key except for the case, and the used keys
// actually walked. See the note about case-insensitive filesystems below.
var candidates map[string]string
visited := make(map[string]bool, seen.Len())
remove := func(name string) error {
err := c.Fs.Remove(name)
if err == nil {
counter++
return nil
}
if !herrors.IsNotExist(err) {
return err
}
return nil
}
err := afero.Walk(c.Fs, "", func(name string, info os.FileInfo, err error) error {
if info == nil {
return nil
@@ -93,27 +117,44 @@ func (c *Cache) Prune(force bool) (int, error) {
shouldRemove := force || c.isExpired(info.ModTime())
if !shouldRemove && c.entryLocker.seen.Len() > 0 {
// Remove it if it's not been touched/used in the last build.
shouldRemove = !c.entryLocker.seen.Has(name)
if seen.Has(name) {
visited[name] = true
} else if !shouldRemove && seen.Len() > 0 {
if id, found := seenByLower[strings.ToLower(name)]; found {
// On case-insensitive filesystems this is the same file as id; e.g. an
// entry created before Hugo started lowercasing the content paths in
// v0.123 (content/MyBundle => _gen/images/MyBundle). Decided once the
// walk is done: if id is walked too, they are distinct files and this
// one is stale. See issue 15101.
if candidates == nil {
candidates = make(map[string]string)
}
candidates[name] = id
} else {
// Remove it if it's not been touched/used in the last build.
shouldRemove = true
}
}
if shouldRemove {
err := c.Fs.Remove(name)
if err == nil {
counter++
}
if err != nil && !herrors.IsNotExist(err) {
return err
}
return remove(name)
}
return nil
})
if err != nil {
return counter, err
}
return counter, err
for name, id := range candidates {
if visited[id] {
if err := remove(name); err != nil {
return counter, err
}
}
}
return counter, nil
}
func (c *Cache) pruneRootDirs(force bool) (int, error) {
+61
View File
@@ -20,11 +20,72 @@ import (
"time"
"github.com/gohugoio/hugo/cache/filecache"
"github.com/gohugoio/hugo/htesting"
"github.com/spf13/afero"
qt "github.com/frankban/quicktest"
)
// A cache entry created before Hugo started lowercasing content paths in v0.123
// (e.g. _gen/images/MyBundle) is on a case-insensitive filesystem the same file as
// the lowercased cache key used today, and must not be pruned.
// See issue 15101.
func TestPruneCacheEntryWithOtherCase(t *testing.T) {
t.Parallel()
c := qt.New(t)
dir := t.TempDir()
if isCaseInsensitive, err := htesting.IsCaseInsensitiveFs(dir); err != nil {
t.Fatal(err)
} else if !isCaseInsensitive {
t.Skip("skip test on case-sensitive filesystem")
}
fs := afero.NewBasePathFs(afero.NewOsFs(), dir)
newCache := func() *filecache.Cache {
return filecache.NewCache(fs, filecache.FileCacheConfig{Dir: "cache", MaxAge: -1})
}
c.Assert(newCache().SetBytes("MyBundle/i1", []byte("abc")), qt.IsNil)
cache := newCache()
_, b, err := cache.GetOrCreateBytes("mybundle/i1", func() ([]byte, error) {
return []byte("def"), nil
})
c.Assert(err, qt.IsNil)
c.Assert(string(b), qt.Equals, "abc")
count, err := cache.Prune(false)
c.Assert(err, qt.IsNil)
c.Assert(count, qt.Equals, 0)
c.Assert(cache.GetString("MyBundle/i1"), qt.Equals, "abc")
}
// On a case-sensitive filesystem the entries above are distinct files,
// and the one not used in this build should be pruned.
func TestPruneCacheEntryWithOtherCaseCaseSensitiveFs(t *testing.T) {
t.Parallel()
c := qt.New(t)
fs := afero.NewMemMapFs()
cache := filecache.NewCache(fs, filecache.FileCacheConfig{Dir: "cache", MaxAge: -1})
c.Assert(cache.SetBytes("MyBundle/i1", []byte("abc")), qt.IsNil)
cache = filecache.NewCache(fs, filecache.FileCacheConfig{Dir: "cache", MaxAge: -1})
_, b, err := cache.GetOrCreateBytes("mybundle/i1", func() ([]byte, error) {
return []byte("def"), nil
})
c.Assert(err, qt.IsNil)
c.Assert(string(b), qt.Equals, "def")
count, err := cache.Prune(false)
c.Assert(err, qt.IsNil)
c.Assert(count, qt.Equals, 1)
c.Assert(cache.GetString("MyBundle/i1"), qt.Equals, "")
c.Assert(cache.GetString("mybundle/i1"), qt.Equals, "def")
}
func TestPrune(t *testing.T) {
t.Parallel()
+10 -3
View File
@@ -38,13 +38,20 @@ run_gofmt() {
# Run staticcheck
run_staticcheck() {
# Check if staticcheck is installed, install if not
if ! command -v staticcheck &> /dev/null; then
local staticcheck_bin
if command -v staticcheck &> /dev/null; then
staticcheck_bin=$(command -v staticcheck)
else
echo "==> Installing staticcheck..."
go install honnef.co/go/tools/cmd/staticcheck@latest
staticcheck_bin="$(go env GOBIN)"
if [ -z "$staticcheck_bin" ]; then
staticcheck_bin="$(go env GOPATH)/bin"
fi
staticcheck_bin="$staticcheck_bin/staticcheck"
fi
echo "==> Running staticcheck..."
staticcheck $PACKAGES
"$staticcheck_bin" $PACKAGES
echo " OK"
}
+1 -3
View File
@@ -103,9 +103,7 @@ func (c *Inspector) MethodsFromTypes(include []reflect.Type, exclude []reflect.T
}
for _, t := range include {
for i := range t.NumMethod() {
m := t.Method(i)
for m := range t.Methods() {
if excludes[m.Name] || seen[m.Name] {
continue
}
+31 -3
View File
@@ -263,11 +263,39 @@ func (c *convertCommand) convertContents(format metadecoders.Format) error {
site := c.h.Sites[0]
var pagesBackedByFile page.Pages
for _, p := range site.AllPages() {
workingDir := c.h.Sites[0].Deps.Conf.WorkingDir() + string(filepath.Separator)
isConvertible := func(p page.Page) bool {
// Skip pages not backed by a content file.
if p.File() == nil {
return false
}
// Skip content adapters.
if p.File().IsContentAdapter() {
return false
}
// Skip content files provided by modules, including vendored modules.
if !p.File().FileInfo().Meta().IsProject {
return false
}
// Skip content files in project mounts outside the working directory.
if !strings.HasPrefix(p.File().Filename(), workingDir) {
return false
}
return true
}
seen := make(map[string]bool)
var pagesBackedByFile page.Pages
for _, p := range c.h.Pages() {
if !isConvertible(p) {
continue
}
filename := p.File().Filename()
if seen[filename] {
continue
}
seen[filename] = true
pagesBackedByFile = append(pagesBackedByFile, p)
}
@@ -278,7 +306,7 @@ func (c *convertCommand) convertContents(format metadecoders.Format) error {
}
site.Log.Println("processing", len(pagesBackedByFile), "content files")
for _, p := range site.AllPages() {
for _, p := range pagesBackedByFile {
if err := c.convertAndSavePage(p, site, format); err != nil {
return err
}
+28 -57
View File
@@ -21,12 +21,8 @@ import (
"os"
"path"
"path/filepath"
"slices"
"strings"
"github.com/alecthomas/chroma/v2"
"github.com/alecthomas/chroma/v2/formatters/html"
"github.com/alecthomas/chroma/v2/styles"
"github.com/bep/simplecobra"
"github.com/goccy/go-yaml"
"github.com/gohugoio/hugo/common/hugo"
@@ -34,6 +30,7 @@ import (
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/hugofs"
"github.com/gohugoio/hugo/hugolib"
"github.com/gohugoio/hugo/markup/highlight"
"github.com/gohugoio/hugo/parser"
"github.com/spf13/cobra"
"github.com/spf13/cobra/doc"
@@ -47,6 +44,10 @@ func newGenCommand() *genCommand {
// Chroma flags.
style string
mode string
modeSelector bool
classDark string
classLight string
highlightStyle string
lineNumbersInlineStyle string
lineNumbersTableStyle string
@@ -63,44 +64,41 @@ func newGenCommand() *genCommand {
See https://gohugo.io/quick-reference/syntax-highlighting-styles/ for a preview of the available styles.`,
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
style = strings.ToLower(style)
if !slices.Contains(styles.Names(), style) {
return fmt.Errorf("invalid style: %s", style)
}
builder := styles.Get(style).Builder()
if highlightStyle != "" {
builder.Add(chroma.LineHighlight, highlightStyle)
}
if lineNumbersInlineStyle != "" {
builder.Add(chroma.LineNumbers, lineNumbersInlineStyle)
}
if lineNumbersTableStyle != "" {
builder.Add(chroma.LineNumbersTable, lineNumbersTableStyle)
}
style, err := builder.Build()
if err != nil {
return err
}
if omitEmpty {
// See https://github.com/alecthomas/chroma/commit/5b2a4c5a26c503c79bc86ba3c4ae5b330028bd3d
hugo.Deprecate("--omitEmpty", "Flag is no longer needed, empty classes are now always omitted.", "v0.149.0")
}
options := []html.Option{
html.WithCSSComments(!omitClassComments),
html.WithCustomCSS(chromaCSSOverrides(style)),
css, err := highlight.ChromaStylesCSS(highlight.ChromaStylesOptions{
Style: style,
Mode: mode,
ModeSelector: modeSelector,
ClassDark: classDark,
ClassLight: classLight,
HighlightStyle: highlightStyle,
LineNumbersInlineStyle: lineNumbersInlineStyle,
LineNumbersTableStyle: lineNumbersTableStyle,
OmitClassComments: omitClassComments,
})
if err != nil {
return err
}
formatter := html.New(options...)
w := os.Stdout
fmt.Fprintf(w, "/* Generated using: hugo %s */\n\n", strings.Join(os.Args[1:], " "))
formatter.WriteCSS(w, style)
fmt.Printf("/* Generated using: hugo %s */\n\n", strings.Join(os.Args[1:], " "))
fmt.Print(css)
return nil
},
withc: func(cmd *cobra.Command, r *rootCommand) {
cmd.ValidArgsFunction = cobra.NoFileCompletions
cmd.PersistentFlags().StringVar(&style, "style", "friendly", "highlighter style")
_ = cmd.RegisterFlagCompletionFunc("style", cobra.NoFileCompletions)
cmd.PersistentFlags().StringVar(&mode, "mode", "", `style mode ("light", "dark")`)
_ = cmd.RegisterFlagCompletionFunc("mode", cobra.FixedCompletions([]string{"light", "dark"}, cobra.ShellCompDirectiveNoFileComp))
cmd.PersistentFlags().BoolVar(&modeSelector, "modeSelector", false, `scope selectors under a top level mode class, e.g. ".dark .chroma"`)
_ = cmd.RegisterFlagCompletionFunc("modeSelector", cobra.NoFileCompletions)
cmd.PersistentFlags().StringVar(&classDark, "classDark", "dark", `class name used by --modeSelector for dark styles`)
_ = cmd.RegisterFlagCompletionFunc("classDark", cobra.NoFileCompletions)
cmd.PersistentFlags().StringVar(&classLight, "classLight", "light", `class name used by --modeSelector for light styles`)
_ = cmd.RegisterFlagCompletionFunc("classLight", cobra.NoFileCompletions)
cmd.PersistentFlags().StringVar(&highlightStyle, "highlightStyle", "", `foreground and background colors for highlighted lines, e.g. --highlightStyle "#fff000 bg:#000fff"`)
_ = cmd.RegisterFlagCompletionFunc("highlightStyle", cobra.NoFileCompletions)
cmd.PersistentFlags().StringVar(&lineNumbersInlineStyle, "lineNumbersInlineStyle", "", `foreground and background colors for inline line numbers, e.g. --lineNumbersInlineStyle "#fff000 bg:#000fff"`)
@@ -276,33 +274,6 @@ url: %s
}
}
func chromaCSSOverrides(style *chroma.Style) map[chroma.TokenType]string {
bg := style.Get(chroma.Background)
m := make(map[chroma.TokenType]string)
for tt := range chroma.StandardTypes {
if tt == chroma.Background || !style.Has(tt) || !chromaLeafToken(tt) {
continue
}
entry := style.Get(tt)
if !entry.Sub(bg).IsZero() || !entry.Colour.IsSet() {
continue
}
if css := html.StyleEntryToCSS(chroma.StyleEntry{Colour: entry.Colour}); css != "" {
m[tt] = css
}
}
return m
}
func chromaLeafToken(tt chroma.TokenType) bool {
for other := range chroma.StandardTypes {
if other != tt && (other.Category() == tt || other.SubCategory() == tt) {
return false
}
}
return true
}
type genCommand struct {
rootCmd *rootCommand
+2 -2
View File
@@ -367,7 +367,7 @@ func (c *hugoBuilder) newWatcher(pollIntervalStr string, dirList ...string) (*wa
case changes := <-c.r.changesFromBuild:
unlock, err := h.LockBuild()
if err != nil {
c.r.logger.Errorln("Failed to acquire a build lock: %s", err)
c.r.logger.Errorf("Failed to acquire a build lock: %s", err)
return
}
c.changeDetector.PrepareNew()
@@ -387,7 +387,7 @@ func (c *hugoBuilder) newWatcher(pollIntervalStr string, dirList ...string) (*wa
case evs := <-watcher.Events:
unlock, err := h.LockBuild()
if err != nil {
c.r.logger.Errorln("Failed to acquire a build lock: %s", err)
c.r.logger.Errorf("Failed to acquire a build lock: %s", err)
return
}
c.handleEvents(watcher, staticSyncer, evs, configSet)
+1 -1
View File
@@ -1108,7 +1108,7 @@ func (s *staticSyncer) syncsStaticEvents(staticEvents []fsnotify.Event) error {
fromPath := ev.Name
relPath, found := sourceFs.MakePathRelative(fromPath, true)
relPath, found := sourceFs.MakePathRelative(fromPath, false)
if !found {
// Not member of this virtual host.
+41 -21
View File
@@ -18,6 +18,7 @@ import (
"crypto/md5"
"encoding/hex"
"io"
"reflect"
"strconv"
"sync"
@@ -105,6 +106,16 @@ func MD5FromStringHexEncoded(f string) string {
return hex.EncodeToString(h.Sum(nil))
}
// MD5FromReaderHexEncoded returns the MD5 hash of the given reader.
func MD5FromReaderHexEncoded(r io.Reader) string {
h := md5.New()
_, err := io.Copy(h, r)
if err != nil {
return ""
}
return hex.EncodeToString(h.Sum(nil))
}
// HashString returns a hash from the given elements.
// It will panic if the hash cannot be calculated.
// Note that this hash should be used primarily for identity, not for change detection as
@@ -124,11 +135,38 @@ func HashStringHex(vs ...any) string {
var hashOptsPool = sync.Pool{
New: func() any {
return &hashstructure.HashOptions{
Hasher: xxhash.New(),
Hasher: xxhash.New(),
UnwrapFunc: unwrapForHashing,
}
},
}
// hashstructure only sees exported struct fields, so rewrite known identity types before hashing,
// e.g. a Resource or Page nested in an options map hashes by its Key.
func unwrapForHashing(v reflect.Value) (reflect.Value, error) {
if v.Kind() != reflect.Struct {
return v, nil
}
var in any
if v.CanAddr() {
// The common case; pointer receiver methods on a struct
// reached through a pointer.
in = v.Addr().Interface()
} else {
in = v.Interface()
}
switch t := in.(type) {
case hashstructure.Hashable:
// Let hashstructure handle it.
return v, nil
case keyer:
return reflect.ValueOf(t.Key()), nil
case identity.IdentityProvider:
return reflect.ValueOf(t.GetIdentity()), nil
}
return v, nil
}
func getHashOpts() *hashstructure.HashOptions {
return hashOptsPool.Get().(*hashstructure.HashOptions)
}
@@ -145,15 +183,10 @@ func putHashOpts(opts *hashstructure.HashOptions) {
func HashUint64(vs ...any) uint64 {
var o any
if len(vs) == 1 {
o = toHashable(vs[0])
o = vs[0]
} else {
elements := make([]any, len(vs))
for i, e := range vs {
elements[i] = toHashable(e)
}
o = elements
o = vs
}
hash, err := Hash(o)
if err != nil {
panic(err)
@@ -176,19 +209,6 @@ type keyer interface {
Key() string
}
// For structs, hashstructure.Hash only works on the exported fields,
// so rewrite the input slice for known identity types.
func toHashable(v any) any {
switch t := v.(type) {
case keyer:
return t.Key()
case identity.IdentityProvider:
return t.GetIdentity()
default:
return v
}
}
type xxhashReadFrom struct {
buff []byte
*xxhash.Digest
-9
View File
@@ -62,15 +62,6 @@ func TestXxHashFromString(t *testing.T) {
c.Assert(got, qt.Equals, uint64(7148569436472236994))
}
func TestHashNilMapVsEmptyMap(t *testing.T) {
c := qt.New(t)
var m1 map[string]any = nil
m2 := map[string]any{}
c.Assert(HashString(m1), qt.Equals, HashString(m2))
}
func TestXxHashFromStringHexEncoded(t *testing.T) {
c := qt.New(t)
s := "The quick brown fox jumps over the lazy dog"
+11 -2
View File
@@ -9,7 +9,16 @@
// This hook makes the ESM resolver fall back to NODE_PATH for bare
// specifiers when Node's normal resolution fails. It is a no-op for
// relative/absolute paths and URL-scheme specifiers, and it never fires
// unless Node would itself have thrown ERR_MODULE_NOT_FOUND.
// unless Node would itself have thrown ERR_MODULE_NOT_FOUND or
// ERR_ACCESS_DENIED.
//
// ERR_ACCESS_DENIED is handled because Node's resolver walks up the
// directory tree looking for node_modules. Under the permission model that
// walk can hit a node_modules outside the allow-list (e.g. Netlify stores
// its node_modules cache in the same tree as the Hugo file cache), aborting
// resolution even though the package is reachable via NODE_PATH. If the
// NODE_PATH fallback also fails we re-throw the original error so the
// access-denied resource is still reported.
//
// Uses the synchronous registerHooks API so it runs on the main thread and
// does not require --allow-worker under the Node permission model.
@@ -38,7 +47,7 @@ registerHooks({
try {
return nextResolve(specifier, context);
} catch (err) {
if (err?.code !== 'ERR_MODULE_NOT_FOUND') throw err;
if (err?.code !== 'ERR_MODULE_NOT_FOUND' && err?.code !== 'ERR_ACCESS_DENIED') throw err;
if (!isBareSpecifier(specifier)) throw err;
for (const r of resolvers) {
try {
+1 -1
View File
@@ -1,7 +1,7 @@
package hiter
// Common iterator functions.
// Some of these are are based on this discsussion: https://github.com/golang/go/issues/61898
// Some of these are based on this discsussion: https://github.com/golang/go/issues/61898
import "iter"
+3 -7
View File
@@ -14,7 +14,6 @@
package hstore
import (
"reflect"
"sync"
"testing"
@@ -69,9 +68,8 @@ func TestScratchAddSlice(t *testing.T) {
sl := scratch.Get("intSlice")
expected := []int{1, 2, 3}
if !reflect.DeepEqual(expected, sl) {
t.Errorf("Slice difference, go %q expected %q", sl, expected)
}
c.Assert(sl, qt.DeepEquals, expected)
_, err = scratch.Add("intSlice", []int{4, 5})
c.Assert(err, qt.IsNil)
@@ -79,9 +77,7 @@ func TestScratchAddSlice(t *testing.T) {
sl = scratch.Get("intSlice")
expected = []int{1, 2, 3, 4, 5}
if !reflect.DeepEqual(expected, sl) {
t.Errorf("Slice difference, go %q expected %q", sl, expected)
}
c.Assert(sl, qt.DeepEquals, expected)
}
// https://github.com/gohugoio/hugo/issues/5275
+51 -28
View File
@@ -21,8 +21,9 @@ import (
type HasBytesWriter struct {
Patterns []*HasBytesPattern
i int
done bool
// The tail of the bytes written so far, retained so we can detect a
// pattern that straddles the boundary between two Write calls.
buff []byte
}
@@ -31,10 +32,13 @@ type HasBytesPattern struct {
Pattern []byte
}
func (h *HasBytesWriter) patternLen() int {
// maxPatternLen returns the length of the longest pattern.
func (h *HasBytesWriter) maxPatternLen() int {
l := 0
for _, p := range h.Patterns {
l += len(p.Pattern)
if len(p.Pattern) > l {
l = len(p.Pattern)
}
}
return l
}
@@ -44,36 +48,55 @@ func (h *HasBytesWriter) Write(p []byte) (n int, err error) {
return len(p), nil
}
if len(h.buff) == 0 {
h.buff = make([]byte, h.patternLen()*2)
keep := h.maxPatternLen() - 1
// Join the tail retained from previous Writes with the head of this chunk
// so a pattern straddling the boundary is still detected. Only the
// boundary window is copied; the chunk itself is scanned in place below.
var boundary []byte
if keep > 0 && len(h.buff) > 0 {
head := p
if len(head) > keep {
head = head[:keep]
}
boundary = make([]byte, 0, len(h.buff)+len(head))
boundary = append(boundary, h.buff...)
boundary = append(boundary, head...)
}
for i := range p {
h.buff[h.i] = p[i]
h.i++
if h.i == len(h.buff) {
// Shift left.
copy(h.buff, h.buff[len(h.buff)/2:])
h.i = len(h.buff) / 2
// Scan each not-yet-matched pattern once per Write instead of once per byte.
done := true
for _, pp := range h.Patterns {
if pp.Match {
continue
}
for _, pp := range h.Patterns {
if bytes.Contains(h.buff, pp.Pattern) {
pp.Match = true
done := true
for _, ppp := range h.Patterns {
if !ppp.Match {
done = false
break
}
}
if done {
h.done = true
}
return len(p), nil
}
if bytes.Contains(p, pp.Pattern) || bytes.Contains(boundary, pp.Pattern) {
pp.Match = true
continue
}
done = false
}
if done {
// All patterns found; no need to look at any more data.
h.done = true
h.buff = nil
return len(p), nil
}
// Retain the last keep bytes of (previous tail + this chunk) to detect a
// pattern straddling into the next Write.
switch {
case keep <= 0:
h.buff = h.buff[:0]
case len(p) >= keep:
h.buff = append(h.buff[:0], p[len(p)-keep:]...)
default:
// Chunk shorter than keep: slide the window over the retained tail.
if total := len(h.buff) + len(p); total > keep {
h.buff = h.buff[total-keep:]
}
h.buff = append(h.buff, p...)
}
return len(p), nil
+58
View File
@@ -65,3 +65,61 @@ func TestHasBytesWriter(t *testing.T) {
fmt.Fprintf(w, "__foo")
c.Assert(h.Patterns[0].Match, qt.Equals, true)
}
func TestHasBytesWriterMultiplePatterns(t *testing.T) {
c := qt.New(t)
neww := func() (*HasBytesWriter, io.Writer) {
var b bytes.Buffer
h := &HasBytesWriter{
Patterns: []*HasBytesPattern{
{Pattern: []byte("__hdeferred/")},
{Pattern: []byte("__h_pp_l1")},
},
}
return h, io.MultiWriter(&b, h)
}
// Neither pattern present.
h, w := neww()
fmt.Fprint(w, "the quick brown fox jumps over the lazy dog")
c.Assert(h.Patterns[0].Match, qt.Equals, false)
c.Assert(h.Patterns[1].Match, qt.Equals, false)
c.Assert(h.done, qt.Equals, false)
// Only the second pattern present; the writer must not report a match
// for the first, and must not prematurely mark itself done.
h, w = neww()
fmt.Fprint(w, "prefix __h_pp_l1 suffix")
c.Assert(h.Patterns[0].Match, qt.Equals, false)
c.Assert(h.Patterns[1].Match, qt.Equals, true)
c.Assert(h.done, qt.Equals, false)
// Both patterns present across multiple writes; done once all match.
h, w = neww()
fmt.Fprint(w, "aaa __hdef")
fmt.Fprint(w, "erred/xyz bbb __h_p")
fmt.Fprint(w, "p_l1 ccc")
c.Assert(h.Patterns[0].Match, qt.Equals, true)
c.Assert(h.Patterns[1].Match, qt.Equals, true)
c.Assert(h.done, qt.Equals, true)
}
func BenchmarkHasBytesWriter(b *testing.B) {
// A large chunk of output containing neither pattern is the common case
// (a normal rendered page): the writer must scan all of it.
content := []byte(strings.Repeat("<div class=\"nav\"><a href=\"/foo/bar\">baz</a></div>\n", 4000))
b.ResetTimer()
for range b.N {
h := &HasBytesWriter{
Patterns: []*HasBytesPattern{
{Pattern: []byte("__hdeferred/")},
{Pattern: []byte("__h_pp_l1")},
},
}
if _, err := h.Write(content); err != nil {
b.Fatal(err)
}
}
}
+7 -2
View File
@@ -33,6 +33,7 @@ import (
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/version"
"github.com/gohugoio/hugo/hugofs/files"
"github.com/gohugoio/hugo/internal/warpc"
"github.com/spf13/afero"
@@ -211,7 +212,10 @@ func GetDependencyList() []string {
// GetDependencyListNonGo returns a list of non-Go dependencies.
func GetDependencyListNonGo() []string {
deps := []string{formatDep("github.com/webmproject/libwebp", "v1.6.0")} // via WASM. TODO(bep) get versions from the plugin setup.
var deps []string
for _, dep := range warpc.GetWASMDeps() {
deps = append(deps, formatDep(dep[0], dep[1]))
}
if IsExtended {
deps = append(
@@ -225,7 +229,8 @@ func GetDependencyListNonGo() []string {
if IsDartSassGeV2() {
dartSassPath = "github.com/sass/dart-sass"
}
deps = append(deps,
deps = append(
deps,
formatDep(dartSassPath+"/protocol", dartSass.ProtocolVersion),
formatDep(dartSassPath+"/compiler", dartSass.CompilerVersion),
formatDep(dartSassPath+"/implementation", dartSass.ImplementationVersion),
+2 -2
View File
@@ -35,8 +35,8 @@ func TestDeprecationLogLevelFromVersion(t *testing.T) {
c.Assert(deprecationLogLevelFromVersion(ver.String()), qt.Equals, logg.LevelError)
// Added just to find the threshold for where we can remove deprecated items.
// Subtract 5 from the minor version of the first ERRORed version => 0.136.0.
c.Assert(deprecationLogLevelFromVersion("0.141.0"), qt.Equals, logg.LevelError)
// Subtract 5 from the minor version of the first ERRORed version => 0.145.0.
c.Assert(deprecationLogLevelFromVersion("0.150.0"), qt.Equals, logg.LevelError)
}
func TestMarkupScope(t *testing.T) {
+1 -1
View File
@@ -19,7 +19,7 @@ import "github.com/gohugoio/hugo/common/version"
// This should be the only one.
var CurrentVersion = version.Version{
Major: 0,
Minor: 162,
Minor: 165,
PatchLevel: 0,
Suffix: "",
}
-5
View File
@@ -134,11 +134,6 @@ func (l LowHigh[S]) Value(source S) S {
// This is only used for debugging purposes.
var InvocationCounter atomic.Int64
// NewTrue returns a pointer to b.
func NewBool(b bool) *bool {
return &b
}
// WeightProvider provides a weight.
type WeightProvider interface {
Weight() int
-30
View File
@@ -458,36 +458,6 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
}
}
// Legacy privacy values.
if c.Privacy.Twitter.Disable {
hugo.DeprecateWithLogger("project config key privacy.twitter.disable", "Use privacy.x.disable instead.", "v0.141.0", logger.Logger())
c.Privacy.X.Disable = c.Privacy.Twitter.Disable
}
if c.Privacy.Twitter.EnableDNT {
hugo.DeprecateWithLogger("project config key privacy.twitter.enableDNT", "Use privacy.x.enableDNT instead.", "v0.141.0", logger.Logger())
c.Privacy.X.EnableDNT = c.Privacy.Twitter.EnableDNT
}
if c.Privacy.Twitter.Simple {
hugo.DeprecateWithLogger("project config key privacy.twitter.simple", "Use privacy.x.simple instead.", "v0.141.0", logger.Logger())
c.Privacy.X.Simple = c.Privacy.Twitter.Simple
}
// Legacy services values.
if c.Services.Twitter.DisableInlineCSS {
hugo.DeprecateWithLogger("project config key services.twitter.disableInlineCSS", "Use services.x.disableInlineCSS instead.", "v0.141.0", logger.Logger())
c.Services.X.DisableInlineCSS = c.Services.Twitter.DisableInlineCSS
}
// Legacy permalink tokens
for _, pc := range c.Permalinks {
if strings.Contains(pc.Pattern, ":filename") {
hugo.DeprecateWithLogger("the \":filename\" permalink token", "Use \":contentbasename\" instead.", "0.144.0", logger.Logger())
}
if strings.Contains(pc.Pattern, ":slugorfilename") {
hugo.DeprecateWithLogger("the \":slugorfilename\" permalink token", "Use \":slugorcontentbasename\" instead.", "0.144.0", logger.Logger())
}
}
// Legacy render hook values.
alternativeDetails := fmt.Sprintf(
"Set to %q if previous value was false, or set to %q if previous value was true.",
+38 -16
View File
@@ -9,7 +9,6 @@ import (
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/config/allconfig"
"github.com/gohugoio/hugo/hugolib"
gc "github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
"github.com/gohugoio/hugo/media"
)
@@ -26,11 +25,13 @@ weight = 2
[[module.mounts]]
source = 'content/en'
target = 'content'
lang = 'en'
[module.mounts.sites.matrix]
languages = 'en'
[[module.mounts]]
source = 'content/sv'
target = 'content'
lang = 'sv'
[module.mounts.sites.matrix]
languages = 'sv'
-- content/en/p1.md --
---
title: "p1"
@@ -360,25 +361,46 @@ weight = 3
// Issue 13535
// We changed enablement of the embedded link and image render hooks from
// booleans to enums in v0.148.0.
// booleans to enums in v0.148.0. This should throw error with v0.163.0 and later.
func TestLegacyEmbeddedRenderHookEnablement(t *testing.T) {
files := `
-- hugo.toml --
[markup.goldmark.renderHooks.image]
#KEY_VALUE
#KEY_VALUE_IMAGE
[markup.goldmark.renderHooks.link]
#KEY_VALUE
#KEY_VALUE_LINK
`
f := strings.ReplaceAll(files, "#KEY_VALUE", "enableDefault = false")
b := hugolib.Test(t, f)
c := b.H.Configs.Base.Markup.Goldmark.RenderHooks
b.Assert(c.Link.UseEmbedded, qt.Equals, gc.RenderHookUseEmbeddedNever)
b.Assert(c.Image.UseEmbedded, qt.Equals, gc.RenderHookUseEmbeddedNever)
f = strings.ReplaceAll(files, "#KEY_VALUE", "enableDefault = true")
b = hugolib.Test(t, f)
c = b.H.Configs.Base.Markup.Goldmark.RenderHooks
b.Assert(c.Link.UseEmbedded, qt.Equals, gc.RenderHookUseEmbeddedFallback)
b.Assert(c.Image.UseEmbedded, qt.Equals, gc.RenderHookUseEmbeddedFallback)
replacer := strings.NewReplacer(
"#KEY_VALUE_IMAGE", "enableDefault = false",
"#KEY_VALUE_LINK", "",
)
f := replacer.Replace(files)
b, _ := hugolib.TestE(t, f)
b.AssertLogContains("ERROR deprecated")
replacer = strings.NewReplacer(
"#KEY_VALUE_IMAGE", "enableDefault = true",
"#KEY_VALUE_LINK", "",
)
f = replacer.Replace(files)
b, _ = hugolib.TestE(t, f)
b.AssertLogContains("ERROR deprecated")
replacer = strings.NewReplacer(
"#KEY_VALUE_IMAGE", "",
"#KEY_VALUE_LINK", "enableDefault = false",
)
f = replacer.Replace(files)
b, _ = hugolib.TestE(t, f)
b.AssertLogContains("ERROR deprecated")
replacer = strings.NewReplacer(
"#KEY_VALUE_IMAGE", "",
"#KEY_VALUE_LINK", "enableDefault = true",
)
f = replacer.Replace(files)
b, _ = hugolib.TestE(t, f)
b.AssertLogContains("ERROR deprecated")
}
+12 -1
View File
@@ -24,6 +24,7 @@ import (
"github.com/gohugoio/hugo/cache/httpcache"
"github.com/gohugoio/hugo/common/hmaps"
"github.com/gohugoio/hugo/common/hstrings"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/config"
@@ -87,8 +88,18 @@ var allDecoderSetups = map[string]decodeWeight{
"imaging": {
key: "imaging",
decode: func(d decodeWeight, p decodeConfig) error {
m := p.p.GetStringMap(d.key)
if _, found := m["quality"]; found {
hugo.DeprecateWithLogger("project config key imaging.quality", "Set the quality per format instead with imaging.jpeg.quality, imaging.webp.quality and/or imaging.avif.quality.", "v0.163.0", p.logger.Logger())
}
if _, found := m["compression"]; found {
hugo.DeprecateWithLogger("project config key imaging.compression", "Set the compression type per format instead with imaging.webp.compression and/or imaging.avif.compression.", "v0.163.0", p.logger.Logger())
}
if _, found := m["hint"]; found {
hugo.DeprecateWithLogger("project config key imaging.hint", "Set the hint per format instead with imaging.webp.hint and/or imaging.avif.hint.", "v0.163.0", p.logger.Logger())
}
var err error
p.c.Imaging, err = images.DecodeConfig(p.p.GetStringMap(d.key))
p.c.Imaging, err = images.DecodeConfig(m)
return err
},
},
+1 -1
View File
@@ -19,7 +19,7 @@ import (
"github.com/gohugoio/hugo/docshelper"
)
// This is is just some helpers used to create some JSON used in the Hugo docs.
// This is just a helper used to create some JSON used in the Hugo docs.
func init() {
docsProvider := func() docshelper.DocProvider {
cfg := config.New()
+8 -4
View File
@@ -19,19 +19,23 @@ defaultContentLanguage = 'en'
[[module.mounts]]
source = 'content/en'
target = 'content/en'
lang = 'en'
[module.mounts.sites.matrix]
languages = 'en'
[[module.mounts]]
source = 'content/nn'
target = 'content/nn'
lang = 'nn'
[module.mounts.sites.matrix]
languages = 'nn'
[[module.mounts]]
source = 'content/no'
target = 'content/no'
lang = 'no'
[module.mounts.sites.matrix]
languages = 'no'
[[module.mounts]]
source = 'content/sv'
target = 'content/sv'
lang = 'sv'
[module.mounts.sites.matrix]
languages = 'sv'
[[module.mounts]]
source = 'layouts'
target = 'layouts'
+1 -1
View File
@@ -88,7 +88,7 @@ var defaultBuild = BuildConfig{
CacheBusters: []CacheBuster{
{
Source: `(postcss|tailwind)\.config\.js`,
Source: `(postcss|tailwind)\.config\.(js|mjs|cjs)`,
Target: cssTargetCachebusterRe,
},
},
-14
View File
@@ -30,7 +30,6 @@ type Config struct {
Disqus Disqus
GoogleAnalytics GoogleAnalytics
Instagram Instagram
Twitter Twitter `json:"-"` // deprecated in favor of X in v0.141.0
Vimeo Vimeo
YouTube YouTube
X X
@@ -59,19 +58,6 @@ type Instagram struct {
Simple bool
}
// 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"`
// When set to true, the Tweet 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 Tweet will be built.
Simple bool
}
// Vimeo holds the privacy configuration settings related to the Vimeo shortcode.
type Vimeo struct {
Service `mapstructure:",squash"`
+95 -8
View File
@@ -18,8 +18,11 @@ import (
"encoding/json"
"errors"
"fmt"
"net/netip"
"net/url"
"reflect"
"slices"
"strconv"
"strings"
"github.com/gohugoio/hugo/common/herrors"
@@ -36,12 +39,11 @@ const securityConfigKey = "security"
var DefaultConfig = Config{
Exec: Exec{
Allow: MustNewWhitelist(
"^(dart-)?sass(-embedded)?$", // sass, dart-sass, dart-sass-embedded.
"^go$", // for Go Modules
"^git$", // For Git info
"^node$", // Used as the runtime for Node tools.
"^(dart-)?sass$", // sass, dart-sass
"^go$", // for Go Modules
"^git$", // For Git info
"^node$", // Used as the runtime for Node tools.
"^postcss$",
"^tailwindcss$",
),
// These have been tested to work with Hugo's external programs
// on Windows, Linux and MacOS.
@@ -189,17 +191,102 @@ func (c Config) CheckAllowedGetEnv(name string) error {
return nil
}
func (c Config) CheckAllowedHTTPURL(url string) error {
if !c.HTTP.URLs.Accept(url) {
func (c Config) CheckAllowedHTTPURL(u string) error {
deny := func(name string) error {
return &AccessDeniedError{
name: url,
name: name,
path: "security.http.urls",
policies: c.ToTOML(),
}
}
if !c.HTTP.URLs.Accept(u) {
return deny(u)
}
// A host can be written as an integer/hex/octal IPv4 literal
// (e.g. http://2130706433/ == http://127.0.0.1/) that has no dot and
// thus slips past IP-literal deny rules. Re-check the canonical form so
// the policy treats every encoding of the same address alike.
if canon, ok := canonicalIPv4URL(u); ok && !c.HTTP.URLs.Accept(canon) {
return deny(u)
}
return nil
}
// canonicalIPv4URL rewrites an integer/hex/octal IPv4 host in rawURL to its
// canonical dotted-decimal form (inet_aton semantics), returning ok=false when
// the host is a normal name or already dotted-decimal.
func canonicalIPv4URL(rawURL string) (string, bool) {
u, err := url.Parse(rawURL)
if err != nil {
return "", false
}
host := u.Hostname()
ip, ok := parseInetAtonIPv4(host)
if !ok || ip.String() == host {
return "", false
}
if port := u.Port(); port != "" {
u.Host = ip.String() + ":" + port
} else {
u.Host = ip.String()
}
return u.String(), true
}
// parseInetAtonIPv4 parses the inet_aton IPv4 forms (14 dot-separated parts,
// each decimal, octal "0..." or hex "0x..."), e.g. "2130706433", "0x7f.0.0.1".
func parseInetAtonIPv4(host string) (netip.Addr, bool) {
if host == "" {
return netip.Addr{}, false
}
parts := strings.Split(host, ".")
if len(parts) > 4 {
return netip.Addr{}, false
}
vals := make([]uint64, len(parts))
for i, p := range parts {
v, ok := parseCInt(p)
if !ok {
return netip.Addr{}, false
}
vals[i] = v
}
maxLast := []uint64{0xffffffff, 0xffffff, 0xffff, 0xff}[len(parts)-1]
var n uint64
for i, v := range vals {
if i == len(parts)-1 {
if v > maxLast {
return netip.Addr{}, false
}
n |= v
} else {
if v > 0xff {
return netip.Addr{}, false
}
n |= v << (8 * (3 - i))
}
}
return netip.AddrFrom4([4]byte{byte(n >> 24), byte(n >> 16), byte(n >> 8), byte(n)}), true
}
func parseCInt(s string) (uint64, bool) {
base := 10
switch {
case len(s) >= 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'):
base, s = 16, s[2:]
case len(s) >= 2 && s[0] == '0':
base, s = 8, s[1:]
}
if s == "" {
return 0, false
}
v, err := strconv.ParseUint(s, base, 64)
if err != nil {
return 0, false
}
return v, true
}
func (c Config) CheckAllowedHTTPMethod(method string) error {
if !c.HTTP.Methods.Accept(method) {
return &AccessDeniedError{
+36 -1
View File
@@ -135,7 +135,7 @@ func TestToTOML(t *testing.T) {
got := DefaultConfig.ToTOML()
c.Assert(got, qt.Equals,
"[security]\n allowContent = ['! ^text/html$']\n enableInlineShortcodes = false\n\n [security.exec]\n allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^git$', '^node$', '^postcss$', '^tailwindcss$']\n osEnv = ['(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE|PROGRAMDATA)$']\n\n [security.funcs]\n getenv = ['^HUGO_', '^CI$']\n\n [security.http]\n methods = ['(?i)GET|POST']\n urls = ['(?i)^https?://[a-z0-9]', '! ^https?://\\d+\\.', '! (?i)localhost', '! (?i)^https?://[^/?#]*@']\n\n [security.node]\n [security.node.permissions]\n allowAddons = ['tailwindcss']\n allowChildProcess = ['tailwindcss']\n allowRead = ['.']\n allowWorker = ['tailwindcss']\n allowWrite = []\n disable = false",
"[security]\n allowContent = ['! ^text/html$']\n enableInlineShortcodes = false\n\n [security.exec]\n allow = ['^(dart-)?sass$', '^go$', '^git$', '^node$', '^postcss$']\n osEnv = ['(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE|PROGRAMDATA)$']\n\n [security.funcs]\n getenv = ['^HUGO_', '^CI$']\n\n [security.http]\n methods = ['(?i)GET|POST']\n urls = ['(?i)^https?://[a-z0-9]', '! ^https?://\\d+\\.', '! (?i)localhost', '! (?i)^https?://[^/?#]*@']\n\n [security.node]\n [security.node.permissions]\n allowAddons = ['tailwindcss']\n allowChildProcess = ['tailwindcss']\n allowRead = ['.']\n allowWorker = ['tailwindcss']\n allowWrite = []\n disable = false",
)
}
@@ -298,6 +298,41 @@ func TestCheckAllowedHTTPURLDigitHostnameIssue14837(t *testing.T) {
}
}
// Integer/hex/octal IPv4 encodings must be denied just like their dotted-decimal
// literals; digit-leading hostnames must still be allowed. See issue 14856.
func TestCheckAllowedHTTPURLIntegerIPEncodings(t *testing.T) {
t.Parallel()
c := qt.New(t)
pc, err := DecodeConfig(config.New())
c.Assert(err, qt.IsNil)
for _, u := range []string{
"http://2130706433/", // 127.0.0.1 decimal
"http://2130706433:9777/x", // 127.0.0.1 decimal, port
"http://2852039166/", // 169.254.169.254 (cloud metadata)
"http://0x7f000001/", // 127.0.0.1 hex
"http://017700000001/", // 127.0.0.1 octal
"http://0x7f.0.0.1/", // 127.0.0.1 dotted hex
"http://0177.0.0.1/", // 127.0.0.1 dotted octal
"http://127.1/", // 127.0.0.1 short form
"http://0/", // 0.0.0.0
"http://0xa9fea9fe/", // 169.254.169.254 hex
} {
err := pc.CheckAllowedHTTPURL(u)
c.Assert(err, qt.IsNotNil, qt.Commentf(u))
}
for _, u := range []string{
"https://1password.com/",
"https://37signals.com/foo",
"https://3com.com/",
"https://0x.tools/",
} {
c.Assert(pc.CheckAllowedHTTPURL(u), qt.IsNil, qt.Commentf(u))
}
}
func TestCheckAllowedContent(t *testing.T) {
t.Parallel()
c := qt.New(t)
-10
View File
@@ -31,7 +31,6 @@ type Config struct {
Disqus Disqus
GoogleAnalytics GoogleAnalytics
Instagram Instagram `json:"-"` // the embedded instagram shortcode no longer uses this
Twitter Twitter `json:"-"` // deprecated in favor of X in v0.141.0
X X
RSS RSS
}
@@ -61,15 +60,6 @@ type Instagram struct {
AccessToken string // this is no longer used by the embedded instagram shortcode
}
// 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
// to disable the inline CSS provided by Hugo.
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.
+37 -6
View File
@@ -74,7 +74,6 @@ func TestNewContentFromFile(t *testing.T) {
c := qt.New(t)
for i, cas := range cases {
c.Run(cas.name, func(c *qt.C) {
c.Parallel()
@@ -109,7 +108,6 @@ func TestNewContentFromFile(t *testing.T) {
}
}
})
}
}
@@ -159,6 +157,37 @@ site RegularPages: {{ len site.RegularPages }}
cContains(c, readFileFromFs(t, fs.Source, filepath.Join("content", "mypage.md")), `draft: true`)
}
// See issue 15078.
func TestNewContentWithBuildCascade(t *testing.T) {
t.Parallel()
mm := afero.NewMemMapFs()
c := qt.New(t)
c.Assert(initFs(mm), qt.IsNil)
c.Assert(mm.MkdirAll(filepath.Join("content", "posts", "drafts"), 0o755), qt.IsNil)
c.Assert(afero.WriteFile(mm, filepath.Join("content", "posts", "drafts", "_index.md"), []byte(`---
title: Drafts
build:
render: never
cascade:
draft: true
build:
render: link
draft: true
---
`), 0o755), qt.IsNil)
cfg, fs := newTestCfg(c, mm)
conf := testconfig.GetTestConfigs(fs.Source, cfg)
h, err := hugolib.NewHugoSites(deps.DepsCfg{Configs: conf, Fs: fs})
c.Assert(err, qt.IsNil)
const target = "posts/drafts/trip-to-puebla/index.md"
c.Assert(create.NewContent(h, "", target, false), qt.IsNil)
c.Assert(readFileFromFs(c, fs.Source, filepath.Join("content", target)), qt.Contains, `title: "Trip to Puebla"`)
}
func initFs(fs afero.Fs) error {
perm := os.FileMode(0o755)
var err error
@@ -308,10 +337,10 @@ theme = "mytheme"
[languages]
[languages.en]
weight = 1
languageName = "English"
label = "English"
[languages.nn]
weight = 2
languageName = "Nynorsk"
label = "Nynorsk"
[module]
[[module.mounts]]
@@ -320,11 +349,13 @@ languageName = "Nynorsk"
[[module.mounts]]
source = 'content'
target = 'content'
lang = 'en'
[module.mounts.sites.matrix]
languages = 'en'
[[module.mounts]]
source = 'content_nn'
target = 'content'
lang = 'nn'
[module.mounts.sites.matrix]
languages = 'nn'
`
if mm == nil {
mm = afero.NewMemMapFs()
+18
View File
@@ -435,10 +435,28 @@ type DepsCfg struct {
// Build triggered by the IntegrationTest framework.
IsIntegrationTest bool
// TestCfg holds configuration used only in tests.
// It is a programming error to set this when IsIntegrationTest is not set,
// and doing so will panic.
TestCfg TestConfig
// ChangesFromBuild for changes passed back to the server/watch process.
ChangesFromBuild chan []identity.Identity
}
// TestConfig holds configuration used only in tests.
// See DepsCfg.TestCfg.
type TestConfig struct {
// WarpcMemory, if set, overrides the memory limit in MiB for the WASM based
// image processors (WebP and AVIF). Used to provoke memory allocation failures.
WarpcMemory int
}
// IsZero reports whether c holds no test configuration.
func (c TestConfig) IsZero() bool {
return c == TestConfig{}
}
// BuildState are state used during a build.
type BuildState struct {
counter uint64
+2
View File
@@ -104,6 +104,8 @@
// ------------------------------------------------------------------------
// cspell: ignore foreign language words
// ------------------------------------------------------------------------
"Bokmål",
"Norsk",
"bezpieczeństwo",
"blatt",
"buch",
+1 -1
View File
@@ -1,7 +1,7 @@
---
title: {{ replace .File.ContentBaseName "-" " " }}
params:
reference:
reference:
---
<!--
+1 -1
View File
@@ -27,7 +27,7 @@
/* pre */
@apply prose-pre:text-gray-800 prose-pre:border-1 prose-pre:border-gray-100 prose-pre:bg-light dark:prose-pre:bg-dark dark:prose-pre:ring-1 dark:prose-pre:ring-slate-300/10;
/* code */
@apply prose-code:px-0.5 prose-code:text-gray-500 prose-code:dark:text-gray-300 border-none;
@apply prose-code:px-0.5 prose-code:text-gray-600 prose-code:dark:text-gray-300 border-none;
@apply prose-code:before:hidden prose-code:after:hidden prose-code:font-mono;
@apply prose-table:prose-th:prose-code:text-white;
/* tables */
+17 -13
View File
@@ -1,20 +1,24 @@
/* Opt in to native cross-document view transitions on navigation. */
@view-transition {
navigation: auto;
}
/* Global slight fade */
::view-transition-old(root),
::view-transition-new(root) {
animation-duration: 200ms;
}
::view-transition-old(qr),
::view-transition-new(qr) {
animation-duration: 800ms;
animation-delay: 250ms;
}
.view-transition-qr {
view-transition-name: qr;
}
/* Turbo styles */
.turbo-progress-bar {
visibility: hidden;
/*
* Persistent chrome (header/footer) is named so it gets its own snapshot
* instead of being part of the root crossfade. Holding it static prevents
* the flicker that the sticky header otherwise shows on every navigation.
*/
::view-transition-group(site-header),
::view-transition-group(site-footer),
::view-transition-old(site-header),
::view-transition-new(site-header),
::view-transition-old(site-footer),
::view-transition-new(site-footer) {
animation: none;
}
-123
View File
@@ -1,123 +0,0 @@
var debug = 0 ? console.log.bind(console, '[explorer]') : function () {};
// This is currently not used, but kept in case I change my mind.
export const explorer = (Alpine) => ({
uiState: {
containerScrollTop: -1,
lastActiveRef: '',
},
treeState: {
// The href of the current page.
currentNode: '',
// The state of each node in the tree.
nodes: {},
// We currently only list the sections, not regular pages, in the side bar.
// This strikes me as the right balance. The pages gets listed on the section pages.
// This array is sorted by length, so we can find the longest prefix of the current page
// without having to iterate over all the keys.
nodeRefsByLength: [],
},
async init() {
let keys = Reflect.ownKeys(this.$refs);
for (let key of keys) {
let n = {
open: false,
active: false,
};
this.treeState.nodes[key] = n;
this.treeState.nodeRefsByLength.push(key);
}
this.treeState.nodeRefsByLength.sort((a, b) => b.length - a.length);
this.setCurrentActive();
},
longestPrefix(ref) {
let longestPrefix = '';
for (let key of this.treeState.nodeRefsByLength) {
if (ref.startsWith(key)) {
longestPrefix = key;
break;
}
}
return longestPrefix;
},
setCurrentActive() {
let ref = this.longestPrefix(window.location.pathname);
let activeChanged = this.uiState.lastActiveRef !== ref;
debug('setCurrentActive', this.uiState.lastActiveRef, window.location.pathname, '=>', ref, activeChanged);
this.uiState.lastActiveRef = ref;
if (this.uiState.containerScrollTop === -1 && activeChanged) {
// Navigation outside of the explorer menu.
let el = document.querySelector(`[x-ref="${ref}"]`);
if (el) {
this.$nextTick(() => {
debug('scrolling to', ref);
el.scrollIntoView({ behavior: 'smooth', block: 'center' });
});
}
}
this.treeState.currentNode = ref;
for (let key in this.treeState.nodes) {
let n = this.treeState.nodes[key];
n.active = false;
n.open = ref == key || ref.startsWith(key);
if (n.open) {
debug('open', key);
}
}
let n = this.treeState.nodes[this.longestPrefix(ref)];
if (n) {
n.active = true;
}
},
getScrollingContainer() {
return document.getElementById('leftsidebar');
},
onLoad() {
debug('onLoad', this.uiState.containerScrollTop);
if (this.uiState.containerScrollTop >= 0) {
debug('onLoad: scrolling to', this.uiState.containerScrollTop);
this.getScrollingContainer().scrollTo(0, this.uiState.containerScrollTop);
}
this.uiState.containerScrollTop = -1;
},
onBeforeRender() {
debug('onBeforeRender', this.uiState.containerScrollTop);
this.setCurrentActive();
},
toggleNode(ref) {
this.uiState.containerScrollTop = this.getScrollingContainer().scrollTop;
this.uiState.lastActiveRef = '';
debug('toggleNode', ref, this.uiState.containerScrollTop);
let node = this.treeState.nodes[ref];
if (!node) {
debug('node not found', ref);
return;
}
let wasOpen = node.open;
},
isCurrent(ref) {
let n = this.treeState.nodes[ref];
return n && n.active;
},
isOpen(ref) {
let node = this.treeState.nodes[ref];
if (!node) return false;
if (node.open) {
debug('isOpen', ref);
}
return node.open;
},
});
+7 -2
View File
@@ -10,7 +10,7 @@ const groupByLvl0 = (array) => {
}, {});
};
const applyHelperFuncs = (array) => {
const adjustHits = (array, isServer) => {
if (!array) return [];
return array.map((item) => {
item.getHeadingHTML = function () {
@@ -30,6 +30,11 @@ const applyHelperFuncs = (array) => {
return `${lvl2.value} <span class="text-gray-500">&nbsp;>&nbsp;</span> ${lvl3.value}`;
};
if (isServer) {
// Trim https://gohugo.io from the url to make it work locally.
item.url = item.url.replace('https://gohugo.io', '');
}
return item;
});
};
@@ -99,7 +104,7 @@ export const search = (Alpine, cfg) => ({
})
.then((response) => response.json())
.then((data) => {
this.result = groupByLvl0(applyHelperFuncs(data.results[0].hits));
this.result = groupByLvl0(adjustHits(data.results[0].hits, cfg.params.isServer));
this.cache.put(this.query, this.result);
});
},
@@ -1,67 +0,0 @@
export function bridgeTurboAndAlpine(Alpine) {
document.addEventListener('turbo:before-render', (event) => {
event.detail.newBody.querySelectorAll('[data-alpine-generated]').forEach((el) => {
if (el.hasAttribute('data-alpine-generated')) {
el.removeAttribute('data-alpine-generated');
el.remove();
}
});
});
document.addEventListener('turbo:render', () => {
if (document.documentElement.hasAttribute('data-turbo-preview')) {
return;
}
document.querySelectorAll('[data-alpine-ignored]').forEach((el) => {
el.removeAttribute('x-ignore');
el.removeAttribute('data-alpine-ignored');
});
document.body.querySelectorAll('[x-data]').forEach((el) => {
if (el.hasAttribute('data-turbo-permanent')) {
return;
}
Alpine.initTree(el);
});
Alpine.startObservingMutations();
});
// Cleanup Alpine state on navigation.
document.addEventListener('turbo:before-cache', () => {
// This will be restarted in turbo:render.
Alpine.stopObservingMutations();
document.body.querySelectorAll('[data-turbo-permanent]').forEach((el) => {
if (!el.hasAttribute('x-ignore')) {
el.setAttribute('x-ignore', true);
el.setAttribute('data-alpine-ignored', true);
}
});
document.body.querySelectorAll('[x-for],[x-if],[x-teleport]').forEach((el) => {
if (el.hasAttribute('x-for') && el._x_lookup) {
Object.values(el._x_lookup).forEach((el) => el.setAttribute('data-alpine-generated', true));
}
if (el.hasAttribute('x-if') && el._x_currentIfEl) {
el._x_currentIfEl.setAttribute('data-alpine-generated', true);
}
if (el.hasAttribute('x-teleport') && el._x_teleport) {
el._x_teleport.setAttribute('data-alpine-generated', true);
}
});
document.body.querySelectorAll('[x-data]').forEach((el) => {
if (!el.hasAttribute('data-turbo-permanent')) {
Alpine.destroyTree(el);
// Turbo leaks DOM elements via their data-turbo-permanent handling.
// That needs to be fixed upstream, but until then.
let clone = el.cloneNode(true);
el.replaceWith(clone);
}
});
});
}
+1 -1
View File
@@ -5,7 +5,7 @@ export const scrollToActive = (when) => {
}
els.forEach((el) => {
// Find scrolling container.
let container = el.closest('[data-turbo-preserve-scroll-container]');
let container = el.closest('[data-preserve-scroll-container]');
if (container) {
// Avoid scrolling if el is already in view.
if (el.offsetTop >= container.scrollTop && el.offsetTop <= container.scrollTop + container.clientHeight) {
-1
View File
@@ -1,3 +1,2 @@
export * from './bridgeTurboAndAlpine';
export * from './helpers';
export * from './lrucache';
+12 -36
View File
@@ -1,10 +1,10 @@
import Alpine from 'alpinejs';
import { registerMagics } from './alpinejs/magics/index';
import { navbar, search, toc } from './alpinejs/data/index';
import { navStore, initColorScheme } from './alpinejs/stores/index';
import { bridgeTurboAndAlpine } from './helpers/index';
import { navStore } from './alpinejs/stores/index';
import persist from '@alpinejs/persist';
import focus from '@alpinejs/focus';
import * as params from '@params';
var debug = 0 ? console.log.bind(console, '[index]') : function () {};
@@ -28,6 +28,7 @@ var debug = 0 ? console.log.bind(console, '[index]') : function () {};
index: 'hugodocs',
app_id: 'D1BPLZHGYQ',
api_key: '6df94e1e5d55d258c56f60d974d10314',
params: params,
};
Alpine.data('navbar', () => navbar(Alpine));
@@ -43,39 +44,14 @@ var debug = 0 ? console.log.bind(console, '[index]') : function () {};
// Start AlpineJS.
Alpine.start();
// Start the Turbo-Alpine bridge.
bridgeTurboAndAlpine(Alpine);
{
let containerScrollTops = {};
// To preserve scroll position in scrolling elements on navigation add data-turbo-preserve-scroll-container="somename" to the scrolling container.
addEventListener('turbo:click', () => {
document.querySelectorAll('[data-turbo-preserve-scroll-container]').forEach((el2) => {
containerScrollTops[el2.dataset.turboPreserveScrollContainer] = el2.scrollTop;
});
// On cross-document navigation the browser snapshots the current page for
// the view transition. An open overlay (e.g. the search modal) would
// otherwise linger in that outgoing snapshot while the page crossfades.
// `pageswap` runs right before the snapshot is taken, so hide such
// elements here to make them disappear instantly on navigation.
window.addEventListener('pageswap', () => {
document.querySelectorAll('[data-hide-on-navigate]').forEach((el) => {
el.classList.add('hidden');
});
addEventListener('turbo:render', () => {
document.querySelectorAll('[data-turbo-preserve-scroll-container]').forEach((ele) => {
const containerScrollTop = containerScrollTops[ele.dataset.turboPreserveScrollContainer];
if (containerScrollTop) {
ele.scrollTop = containerScrollTop;
} else {
let els = ele.querySelectorAll('.scroll-active');
if (els.length) {
els.forEach((el) => {
// Avoid scrolling if el is already in view.
if (el.offsetTop >= ele.scrollTop && el.offsetTop <= ele.scrollTop + ele.clientHeight) {
return;
}
ele.scrollTop = el.offsetTop - ele.offsetTop;
});
}
}
});
containerScrollTops = {};
});
}
});
})();
-1
View File
@@ -1 +0,0 @@
import * as Turbo from '@hotwired/turbo';
-1
View File
@@ -1,6 +1,5 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"*": [
"*"
@@ -2,7 +2,7 @@
_comment: Do not remove front matter.
---
locale
`locale`
: (`string`) The language tag as described in [RFC 5646][]. This is the primary value used by the [`language.Translate`][] function to select a translation table, and for localization of dates, currencies, numbers, and percentages, falling back to the [language key][] in both cases.
Hugo also uses this value to populate:
@@ -4,19 +4,19 @@ _comment: Do not remove front matter.
A _page matcher_ filters pages by logical path, page kind, environment, or site. Specify filtering criteria using any combination of the following keywords.
environment
`environment`
: (`string`) A [glob pattern](g) matching the build [environment](g). For example: `{staging,production}`.
kind
`kind`
: (`string`) A [glob pattern](g) matching the [page kind](g). For example: `{taxonomy,term}`.
lang
`lang`
: {{< deprecated-in 0.153.0 />}}
: Use [`sites`](#sites) instead.
: Use the [`sites`](#sites) setting instead.
path
`path`
: (`string`) A [glob pattern](g) matching the page's [logical path](g). For example: `{/books,/books/**}`.
sites
`sites`
: {{< new-in 0.153.0 />}}
: (`map`) A [sites matrix](g) matching any combination of [content dimensions](g) including language, version, and role.
@@ -0,0 +1,7 @@
---
_comment: Do not remove front matter.
---
When the `images` front matter parameter is set, Hugo processes each value. For internal paths, it searches page resources then global resources, using the resource permalink if found or converting the path to an absolute URL if not. External URLs are used as-is.
When `images` is not set, Hugo searches page resources for a name matching `*feature*`, falling back to `*cover*` or `*thumbnail*` if none is found. If still no image is found, Hugo uses the first entry in the site configuration's `params.images` array, if present, and processes it as described above.
+2 -2
View File
@@ -2,7 +2,7 @@
_comment: Do not remove front matter.
---
> [!note]
> The [page collections quick reference guide] describes methods and functions to filter, sort, and group page collections.
> [!NOTE]
> The [page collections quick reference guide][] describes methods and functions to filter, sort, and group page collections.
[page collections quick reference guide]: /quick-reference/page-collections/
@@ -10,5 +10,5 @@ By default, Hugo uses the `html/template` package when rendering HTML files.
To generate HTML output that is safe against code injection, the `html/template` package escapes strings in certain contexts.
[`text/template`]: https://pkg.go.dev/text/template
[`html/template`]: https://pkg.go.dev/html/template
[`text/template`]: https://pkg.go.dev/text/template
@@ -2,9 +2,7 @@
_comment: Do not remove front matter.
---
Apply the filter using the [`images.Filter`] function:
[`images.Filter`]: /functions/images/filter/
Apply the filter using the [`images.Filter`][] function:
```go-html-template
{{ with resources.Get "images/original.jpg" }}
@@ -14,9 +12,7 @@ Apply the filter using the [`images.Filter`] function:
{{ end }}
```
You can also apply the filter using the [`Filter`] method on a `Resource` object:
[`Filter`]: /methods/resource/filter/
You can also apply the filter using the [`Filter`][] method on a `Resource` object:
```go-html-template
{{ with resources.Get "images/original.jpg" }}
@@ -25,3 +21,6 @@ You can also apply the filter using the [`Filter`] method on a `Resource` object
{{ end }}
{{ end }}
```
[`Filter`]: /methods/resource/filter/
[`images.Filter`]: /functions/images/filter/
+15 -15
View File
@@ -2,13 +2,13 @@
_comment: Do not remove front matter.
---
params
`params`
: (`map` or `slice`) Params that can be imported as JSON in your JS files, e.g.
```go-html-template
{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }}
```
And then in your JS file:
```js
@@ -17,17 +17,17 @@ params
Note that this is meant for small data sets, e.g., configuration settings. For larger data sets, please put/mount the files into `assets` and import them directly.
minify
`minify`
: (`bool`) Whether to minify the generated JS code. Default is `false`.
loaders
`loaders`
: {{< new-in 0.140.0 />}}
: (`map`) Configuring a loader for a given file type lets you load that file type with an `import` statement or a `require` call. For example, configuring the `.png` file extension to use the data URL loader means importing a `.png` file gives you a data URL containing the contents of that image. Loaders available are `none`, `base64`, `binary`, `copy`, `css`, `dataurl`, `default`, `empty`, `file`, `global-css`, `js`, `json`, `jsx`, `local-css`, `text`, `ts`, `tsx`. See <https://esbuild.github.io/api/#loader>.
inject
`inject`
: (`slice`) This option allows you to automatically replace a global variable with an import from another file. The path names must be relative to `assets`. See <https://esbuild.github.io/api/#inject>.
shims
`shims`
: (`map`) This option allows swapping out a component with another. A common use case is to load dependencies like React from a CDN (with _shims_) when in production, but running with the full bundled `node_modules` dependency during development:
```go-html-template
@@ -54,39 +54,39 @@ shims
import * as ReactDOM from 'react-dom/client';
```
target
`target`
: (`string`) The language target. One of: `es5`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020`, `es2021`, `es2022`, `es2023`, `es2024`, or `esnext`. Default is `esnext`.
platform
`platform`
: {{< new-in 0.140.0 />}}
: (`string`) One of `browser`, `node`, `neutral`. Default is `browser`. See <https://esbuild.github.io/api/#platform>.
externals
`externals`
: (`slice`) External dependencies. Use this to trim dependencies you know will never be executed. See <https://esbuild.github.io/api/#external>.
defines
`defines`
: (`map`) This option allows you to define a set of string replacements to be performed when building. It must be a map where each key will be replaced by its value.
```go-html-template
{{ $defines := dict "process.env.NODE_ENV" `"development"` }}
```
drop
`drop`
: {{< new-in 0.144.0 />}}
: (`string`) Edit your source code before building to drop certain constructs: One of `debugger` or `console`.
: See <https://esbuild.github.io/api/#drop>
sourceMap
`sourceMap`
: (`string`) The type of source map to generate. One of `external`, `inline`, `linked`, or `none`. Default is `none`. Linked and external source maps will be written to the target with the output file name + ".map". When `linked` a `sourceMappingURL` will also be written to the output file.
sourcesContent
`sourcesContent`
: {{< new-in 0.140.0 />}}
: (`bool`) Whether to include the content of the source files in the source map. Default is `true`.
JSX
`JSX`
: (`string`) How to handle/transform JSX syntax. One of: `transform`, `preserve`, `automatic`. Default is `transform`. Notably, the `automatic` transform was introduced in React 17+ and will cause the necessary JSX helper functions to be imported automatically. See <https://esbuild.github.io/api/#jsx>.
JSXImportSource
`JSXImportSource`
: (`string`) Which library to use to automatically import its JSX helper functions from. This only works if `JSX` is set to `automatic`. The specified library needs to be installed through npm and expose certain exports. See <https://esbuild.github.io/api/#jsx-import-source>.
The combination of `JSX` and `JSXImportSource` is helpful if you want to use a non-React JSX library like Preact, e.g.:
+1 -1
View File
@@ -2,7 +2,7 @@
_comment: Do not remove front matter.
---
> [!note]
> [!NOTE]
> Localization of dates, currencies, numbers, and percentages is performed by the [`bep/golocales`][] package. Hugo determines the locale using the [`locale`][] configuration setting, falling back to the language key itself. The resolved value must be a locale supported by the package.
[`bep/golocales`]: https://github.com/bep/golocales
@@ -14,7 +14,7 @@ The table below shows the values these functions return for various file formats
|Format|IsImageResource|IsImageResourceProcessable|IsImageResourceWithMeta|
|:-----|:--------------|:-------------------------|:----------------------|
|AVIF |true |**false** |true |
|AVIF |true |true |true |
|BMP |true |true |true |
|GIF |true |true |true |
|HEIC |true |**false** |true |
@@ -44,6 +44,6 @@ This contrived example demonstrates how to iterate through resources and use the
{{ end }}
```
[`reflect.IsImageResource`]: /functions/reflect/isimageresource/
[`reflect.IsImageResourceProcessable`]: /functions/reflect/isimageresourceprocessable/
[`reflect.IsImageResourceWithMeta`]: /functions/reflect/isimageresourcewithmeta/
[`reflect.IsImageResource`]: /functions/reflect/isimageresource/
@@ -2,11 +2,11 @@
_comment: Do not remove front matter.
---
When specifying the regular expression, use a raw [string literal] (backticks) instead of an interpreted string literal (double quotes) to simplify the syntax. With an interpreted string literal you must escape backslashes.
When specifying the regular expression, use a raw [string literal][] (backticks) instead of an interpreted string literal (double quotes) to simplify the syntax. With an interpreted string literal you must escape backslashes.
Go's regular expression package implements the [RE2 syntax]. The RE2 syntax is a subset of that accepted by [PCRE], roughly speaking, and with various [caveats]. Note that the RE2 `\C` escape sequence is not supported.
Go's regular expression package implements the [RE2 syntax][]. The RE2 syntax is a subset of that accepted by [PCRE][], roughly speaking, and with various [caveats][]. Note that the RE2 `\C` escape sequence is not supported.
[caveats]: https://swtch.com/~rsc/regexp/regexp3.html#caveats
[PCRE]: https://www.pcre.org/
[RE2 syntax]: https://github.com/google/re2/wiki/Syntax/
[caveats]: https://swtch.com/~rsc/regexp/regexp3.html#caveats
[string literal]: https://go.dev/ref/spec#String_literals
@@ -2,10 +2,7 @@
_comment: Do not remove front matter.
---
The [`anchorize`] and [`urlize`] functions are similar:
[`anchorize`]: /functions/urls/anchorize/
[`urlize`]: /functions/urls/urlize/
The [`anchorize`][] and [`urlize`][] functions are similar:
- Use the `anchorize` function to generate an HTML `id` attribute value
- Use the `urlize` function to sanitize a string for usage in a URL
@@ -33,3 +30,6 @@ For example:
{{ $s | anchorize }} → hugö
{{ $s | urlize }} → hug%C3%B6
```
[`anchorize`]: /functions/urls/anchorize/
[`urlize`]: /functions/urls/urlize/
@@ -0,0 +1,8 @@
---
_comment: Do not remove front matter.
---
> [!NOTE]
> Do not commit the contents of the [`publishDir`][] directory to your repository. Hugo recreates this directory when you build your project.
[`publishDir`]: /configuration/all/#publishdir
+7 -5
View File
@@ -2,13 +2,15 @@
_comment: Do not remove front matter.
---
> [!note] Hugo Modules are Go Modules
> You need [Go] version 1.18 or later and [Git] to use Hugo Modules. For older sites hosted on Netlify, please ensure the `GO_VERSION` environment variable is set to `1.18` or higher.
> [!NOTE] Hugo modules are Go modules
> You need [Go][] version 1.18 or later and [Git][] to use Hugo modules. For older sites hosted on Netlify, please ensure the `GO_VERSION` environment variable is set to `1.18` or higher.
>
> Go Modules resources:
> Go module resources:
>
> - [go.dev/wiki/Modules](https://go.dev/wiki/Modules)
> - [blog.golang.org/using-go-modules](https://go.dev/blog/using-go-modules)
> - [go.dev/wiki/Modules][]
> - [blog.golang.org/using-go-modules][]
[Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
[Go]: https://go.dev/doc/install
[blog.golang.org/using-go-modules]: https://go.dev/blog/using-go-modules
[go.dev/wiki/Modules]: https://go.dev/wiki/Modules
@@ -14,10 +14,10 @@ LibSass support (3)|:x:|:x:|:heavy_check_mark:|:heavy_check_mark:
(1) {{< new-in v0.159.2 />}}
(2) Deploy your site directly to a Google Cloud Storage bucket, an AWS S3 bucket, or an Azure Storage container. See&nbsp;[details].
(2) Deploy your site directly to a Google Cloud Storage bucket, an AWS S3 bucket, or an Azure Storage container. See [details][].
(3) [Transpile Sass to CSS] via embedded LibSass. Note that embedded LibSass was deprecated in v0.153.0 and will be removed in a future release. Use the [Dart Sass] transpiler instead, which is compatible with any edition.
(3) [Transpile Sass to CSS][] via embedded LibSass. Note that embedded LibSass was deprecated in v0.153.0 and will be removed in a future release. Use the [Dart Sass][] transpiler instead, which is compatible with any edition.
[dart sass]: /functions/css/sass/#dart-sass
[transpile sass to css]: /functions/css/sass/
[Dart Sass]: /functions/css/sass/#dart-sass
[Transpile Sass to CSS]: /functions/css/sass/
[details]: /host-and-deploy/deploy-with-hugo-deploy/
@@ -4,20 +4,20 @@ _comment: Do not remove front matter.
## Prerequisites
Although not required in all cases, [Git], [Go], and [Dart Sass] are commonly used when working with Hugo.
Although not required in all cases, [Git][], [Go][], and [Dart Sass][] are commonly used when working with Hugo.
Git is required to:
- Build Hugo from source
- Use the [Hugo Modules] feature
- Use [Hugo modules][]
- Install a theme as a Git submodule
- Access [commit information] from a local Git repository
- Access [commit information][] from a local Git repository
- Host your site on [CI/CD](g) platforms such as [Cloudflare][], [GitHub Pages][], [GitLab Pages][], [Netlify][], [Render][], or [Vercel][]
Go is required to:
- Build Hugo from source
- Use the Hugo Modules feature
- Use Hugo modules
Dart Sass is required to transpile Sass to CSS when using the latest features of the Sass language.
@@ -28,16 +28,16 @@ Please refer to the relevant documentation for installation instructions:
- [Dart Sass][dart sass install]
[Cloudflare]: /host-and-deploy/host-on-cloudflare/
[commit information]: /methods/page/GitInfo
[dart sass install]: /functions/css/sass/#dart-sass
[dart sass]: https://sass-lang.com/dart-sass
[git install]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
[git]: https://git-scm.com/
[Dart Sass]: https://sass-lang.com/dart-sass
[GitHub Pages]: /host-and-deploy/host-on-github-pages/
[GitLab Pages]: /host-and-deploy/host-on-gitlab-pages/
[go install]: https://go.dev/doc/install
[go]: https://go.dev/
[hugo modules]: /hugo-modules/
[Git]: https://git-scm.com/
[Go]: https://go.dev/
[Hugo modules]: /hugo-modules/
[Netlify]: /host-and-deploy/host-on-netlify/
[Render]: /host-and-deploy/host-on-render/
[Vercel]: /host-and-deploy/host-on-vercel/
[commit information]: /methods/page/GitInfo/
[dart sass install]: /functions/css/sass/#dart-sass
[git install]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
[go install]: https://go.dev/doc/install
@@ -4,7 +4,7 @@ _comment: Do not remove front matter.
## Prebuilt binaries
Prebuilt binaries are available for a variety of operating systems and architectures. Visit the [latest release] page, and scroll down to the Assets section.
Prebuilt binaries are available for a variety of operating systems and architectures. Visit the [latest release][] page, and scroll down to the Assets section.
1. Download the archive for the desired edition, operating system, and architecture
1. Extract the archive
@@ -6,8 +6,8 @@ _comment: Do not remove front matter.
To build Hugo from source you must install:
1. [Git]
1. [Go] version 1.25.0 or later
1. [Git][]
1. [Go][] version {{% current-go-version %}} or later
### Standard edition
@@ -29,7 +29,7 @@ CGO_ENABLED=0 go install -tags withdeploy github.com/gohugoio/hugo@latest
### Extended edition
To build and install the extended edition, first install a C compiler such as [GCC] or [Clang] and then run the following command:
To build and install the extended edition, first install a C compiler such as [GCC][] or [Clang][] and then run the following command:
```sh
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@latest
@@ -37,7 +37,7 @@ CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@latest
### Extended/deploy edition
To build and install the extended/deploy edition, first install a C compiler such as [GCC] or [Clang] and then run the following command:
To build and install the extended/deploy edition, first install a C compiler such as [GCC][] or [Clang][] and then run the following command:
```sh
CGO_ENABLED=1 go install -tags extended,withdeploy github.com/gohugoio/hugo@latest
@@ -4,7 +4,7 @@ _comment: Do not remove front matter.
### Homebrew
[Homebrew] is a free and open-source package manager for macOS and Linux. To install the extended/deploy edition of Hugo:
[Homebrew][] is a free and open-source package manager for macOS and Linux. To install the extended/deploy edition of Hugo:
```sh
brew install hugo
@@ -2,7 +2,7 @@
_comment: Do not remove front matter.
---
In this project configuration we enable rendering of [emoji shortcodes], and add emoji shortcodes before (pre) and after (post) each menu entry:
In this project configuration we enable rendering of [emoji shortcodes][], and add emoji shortcodes before (pre) and after (post) each menu entry:
{{< code-toggle file=hugo >}}
enableEmoji = true
@@ -6,26 +6,26 @@ _comment: Do not remove front matter.
This description list intentionally excludes the `pageRef` and `url` properties. Add those properties manually after using the include shortcode to include this list.
-->
identifier
`identifier`
: (`string`) Required when two or more menu entries have the same `name`, or when localizing the `name` using translation tables. Must start with a letter, followed by letters, digits, or underscores.
name
`name`
: (`string`) The text to display when rendering the menu entry.
params
`params`
: (`map`) User-defined properties for the menu entry.
parent
`parent`
: (`string`) The `identifier` of the parent menu entry. If `identifier` is not defined, use `name`. Required for child entries in a nested menu.
post
`post`
: (`string`) The HTML to append when rendering the menu entry.
pre
`pre`
: (`string`) The HTML to prepend when rendering the menu entry.
title
`title`
: (`string`) The HTML `title` attribute of the rendered menu entry.
weight
`weight`
: (`int`) A non-zero integer indicating the entry's position relative the root of the menu, or to its parent for a child entry. Lighter entries float to the top, while heavier entries sink to the bottom.
@@ -0,0 +1,18 @@
---
_comment: Do not remove front matter.
---
`Type`
: (`string`) Returns the media type.
`MainType`
: (`string`) Returns the main type of the media type.
`SubType`
: (`string`) Returns the subtype of the media type.
`Suffixes`
: (`slice`) Returns a slice of possible file suffixes for the media type.
`FirstSuffix.Suffix`
: (`string`) Returns the first of the possible file suffixes for the media type.
@@ -6,21 +6,16 @@ Hugo determines the _next_ and _previous_ page by sorting the site's collection
Field|Precedence|Sort direction
:--|:--|:--
[`weight`]|1|descending
[`date`]|2|descending
[`linkTitle`]|3|descending
[`path`]|4|descending
[`date`]: /methods/page/date/
[`weight`]: /methods/page/weight/
[`linkTitle`]: /methods/page/linktitle/
[`path`]: /methods/page/path/
[`weight`][]|1|descending
[`date`][]|2|descending
[`linkTitle`][]|3|descending
[`path`][]|4|descending
The sorted page collection used to determine the _next_ and _previous_ page is independent of other page collections, which may lead to unexpected behavior.
For example, with this content structure:
```text
```tree
content/
├── pages/
│ ├── _index.md
@@ -53,8 +48,12 @@ When you visit page-2:
- The `Prev` method points to page-3
- The `Next` method points to page-1
To reverse the meaning of _next_ and _previous_ you can change the sort direction in your [project configuration], or use the [`Next`] and [`Prev`] methods on a `Pages` object for more flexibility.
To reverse the meaning of _next_ and _previous_ you can change the sort direction in your [project configuration][], or use the [`Next`][] and [`Prev`][] methods on a `Pages` object for more flexibility.
[`Next`]: /methods/pages/next/
[`Prev`]: /methods/pages/prev/
[`date`]: /methods/page/date/
[`linkTitle`]: /methods/page/linktitle/
[`path`]: /methods/page/path/
[`weight`]: /methods/page/weight/
[project configuration]: /configuration/page/
[`Next`]: /methods/pages/prev
[`Prev`]: /methods/pages/prev
@@ -6,21 +6,16 @@ Hugo determines the _next_ and _previous_ page by sorting the current section's
Field|Precedence|Sort direction
:--|:--|:--
[`weight`]|1|descending
[`date`]|2|descending
[`linkTitle`]|3|descending
[`path`]|4|descending
[`date`]: /methods/page/date/
[`weight`]: /methods/page/weight/
[`linkTitle`]: /methods/page/linktitle/
[`path`]: /methods/page/path/
[`weight`][]|1|descending
[`date`][]|2|descending
[`linkTitle`][]|3|descending
[`path`][]|4|descending
The sorted page collection used to determine the _next_ and _previous_ page is independent of other page collections, which may lead to unexpected behavior.
For example, with this content structure:
```text
```tree
content/
├── pages/
│ ├── _index.md
@@ -53,11 +48,7 @@ When you visit page-2:
- The `PrevInSection` method points to page-3
- The `NextInSection` method points to page-1
To reverse the meaning of _next_ and _previous_ you can change the sort direction in your [project configuration], or use the [`Next`] and [`Prev`] methods on a `Pages` object for more flexibility.
[project configuration]: /configuration/page/
[`Next`]: /methods/pages/prev
[`Prev`]: /methods/pages/prev
To reverse the meaning of _next_ and _previous_ you can change the sort direction in your [project configuration][], or use the [`Next`][] and [`Prev`][] methods on a `Pages` object for more flexibility.
## Example
@@ -75,4 +66,12 @@ Code defensively by checking for page existence:
## Alternative
Use the [`Next`] and [`Prev`] methods on a `Pages` object for more flexibility.
Use the [`Next`][] and [`Prev`][] methods on a `Pages` object for more flexibility.
[`Next`]: /methods/pages/next/
[`Prev`]: /methods/pages/prev/
[`date`]: /methods/page/date/
[`linkTitle`]: /methods/page/linktitle/
[`path`]: /methods/page/path/
[`weight`]: /methods/page/weight/
[project configuration]: /configuration/page/
@@ -6,21 +6,16 @@ Hugo determines the _next_ and _previous_ page by sorting the page collection ac
Field|Precedence|Sort direction
:--|:--|:--
[`weight`]|1|descending
[`date`]|2|descending
[`linkTitle`]|3|descending
[`path`]|4|descending
[`date`]: /methods/page/date/
[`weight`]: /methods/page/weight/
[`linkTitle`]: /methods/page/linktitle/
[`path`]: /methods/page/path/
[`weight`][]|1|descending
[`date`][]|2|descending
[`linkTitle`][]|3|descending
[`path`][]|4|descending
The sorted page collection used to determine the _next_ and _previous_ page is independent of other page collections, which may lead to unexpected behavior.
For example, with this content structure:
```text
```tree
content/
├── pages/
│ ├── _index.md
@@ -55,7 +50,7 @@ When you visit page-2:
- The `Prev` method points to page-3
- The `Next` method points to page-1
To reverse the meaning of _next_ and _previous_ you can chain the [`Reverse`] method to the page collection definition:
To reverse the meaning of _next_ and _previous_ you can chain the [`Reverse`][] method to the page collection definition:
```go-html-template {file="layouts/page.html"}
{{ $pages := .CurrentSection.Pages.ByWeight.Reverse }}
@@ -70,3 +65,7 @@ To reverse the meaning of _next_ and _previous_ you can chain the [`Reverse`] me
```
[`Reverse`]: /methods/pages/reverse/
[`date`]: /methods/page/date/
[`linkTitle`]: /methods/page/linktitle/
[`path`]: /methods/page/path/
[`weight`]: /methods/page/weight/
@@ -2,5 +2,5 @@
_comment: Do not remove front matter.
---
> [!note]
> [!NOTE]
> Use this method with [global resources](g), [page resources](g), or [remote resources](g).
@@ -7,26 +7,26 @@ _comment: Do not remove front matter.
The processing specification is a space-delimited, case-insensitive list containing one or more of the following options in any sequence:
action
: Specify one of `crop`, `fill`, `fit`, or `resize`. This is applicable to the [`Process`][] method and the [`images.Process`][] filter. If you specify an action, you must also provide dimensions.
: Specify one of `crop`, `fill`, `fit`, or `resize`. This is applicable to the [`Process`][] method and the [`images.Process`][] filter. If you specify an action, you must also provide [`dimensions`](#dimensions).
anchor
: The focal point used when cropping or filling an image. Valid options include `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`. The `Smart` option utilizes the [`muesli/smartcrop`][] package to identify the most interesting area of the image. This defaults to the [`anchor`][] parameter in your project configuration.
: The focal point used when cropping or filling an image. Valid options include `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`. The `Smart` option utilizes the [`muesli/smartcrop`][] package to identify the most interesting area of the image. This defaults to the `anchor` setting in your [imaging configuration][].
background color
: The background color used when converting transparent images to formats that do not support transparency, such as PNG to JPEG. This color also fills the empty space created when rotating an image by a non-orthogonal angle if the space is not transparent and a background color is not specified in the processing specification. The value must be an RGB [hexadecimal color][]. This defaults to the [`bgColor`][] parameter in your project configuration.
: The background color used when converting transparent images to formats that do not support transparency, such as PNG to JPEG. This color also fills the empty space created when rotating an image by a non-orthogonal angle if the space is not transparent and a background color is not specified in the processing specification. The value must be an RGB [hexadecimal color][]. This defaults to the `bgColor` setting in your [imaging configuration][].
compression
: {{< new-in 0.153.5 />}}
: The encoding strategy used for the image. Options are `lossy` or `lossless`. Note that `lossless` is only supported by the WebP format. This defaults to the [`compression`][] parameter in your project configuration.
: The encoding strategy, applicable to AVIF and WebP images. Options are `lossy` or `lossless`. This defaults to the format-specific `compression` setting in your [imaging configuration][].
dimensions
: The dimensions of the resulting image, in pixels. The format is `WIDTHxHEIGHT` where `WIDTH` and `HEIGHT` are whole numbers. When resizing an image, you may specify only the width (such as `600x`) or only the height (such as `x400`) for proportional scaling. Specifying both width and height when resizing an image may result in non-proportional scaling. When cropping, fitting, or filling, you must provide both width and height such as `600x400`.
format
: The format of the resulting image. Valid options include `bmp`, `gif`, `jpeg`, `png`, `tiff`, or `webp`. This defaults to the format of the source image.
: The format of the resulting image. Valid options include `avif`, `bmp`, `gif`, `jpeg`, `png`, `tiff`, or `webp`. This defaults to the format of the source image.
hint
: The encoding preset used when processing WebP images, equivalent to the `-preset` flag for the [`cwebp`][] CLI. Valid options include `drawing`, `icon`, `photo`, `picture`, or `text`. This defaults to the [`hint`][] parameter in your project configuration.
: The content hint, applicable to AVIF and WebP images. Valid options include `drawing`, `icon`, `photo`, `picture`, or `text`. This defaults to the format-specific `hint` setting in your [imaging configuration][].
Value|Example
:--|:--
@@ -37,10 +37,10 @@ hint
`text`|Image that is primarily text
quality
: The visual fidelity of the image, applicable to JPEG and WebP formats when using `lossy` compression. The format is `qQUALITY` where `QUALITY` is a whole number between `1` and `100`, inclusive. Lower numbers prioritize smaller file size, while higher numbers prioritize visual clarity. This defaults to the [`quality`][] parameter in your project configuration.
: The visual fidelity, applicable to JPEG images and to AVIF and WebP images when using `lossy` compression. The format is `qQUALITY` where `QUALITY` is a whole number between `1` and `100`, inclusive. Lower numbers prioritize smaller file size, while higher numbers prioritize visual clarity. This defaults to the format-specific `quality` setting in your [imaging configuration][].
resampling filter
: The algorithm used to calculate new pixels when resizing, fitting, or filling an image. Common options include `box`, `lanczos`, `catmullRom`, `mitchellNetravali`, `linear`, or `nearestNeighbor`. This defaults to the [`resampleFilter`][] parameter in your project configuration.
: The algorithm used to calculate new pixels when resizing, fitting, or filling an image. Common options include `box`, `lanczos`, `catmullRom`, `mitchellNetravali`, `linear`, or `nearestNeighbor`. This defaults to the `resampleFilter` setting in your [imaging configuration][].
Filter|Description
:--|:--
@@ -56,18 +56,12 @@ resampling filter
rotation
: The number of whole degrees to rotate an image counter-clockwise. The format is `rDEGREES` where `DEGREES` is a whole number. Hugo performs rotation before any other transformations, so your [target dimensions](#dimensions) and any [anchor](#anchor) should refer to the image orientation after rotation. Use `r90`, `r180`, or `r270` for orthogonal rotations, or arbitrary angles such as `r45`. To rotate clockwise, use a negative number such as `r-45`. To automatically rotate an image based on its Exif orientation tag, use the [`images.AutoOrient`][] filter instead of manual rotation.
Rotating by non-orthogonal values increases the image extents to fit the rotated corners. For formats supporting alpha channels such as PNG or WebP, this resulting empty space is transparent by default. If the target format does not support transparency such as JPEG, or if you explicitly specify a [background color](#background-color) in the processing specification, the space is filled. If a color is required but not specified in the processing string, it defaults to the [`bgColor`][] parameter in your project configuration.
Rotating by non-orthogonal values increases the image extents to fit the rotated corners. For formats supporting alpha channels such as AVIF, PNG, or WebP, this resulting empty space is transparent by default. If the target format does not support transparency such as JPEG, or if you explicitly specify a [background color](#background-color) in the processing specification, the space is filled. If a color is required but not specified in the processing string, it defaults to the `bgColor` setting in your [imaging configuration][].
[`anchor`]: /configuration/imaging/#anchor
[`bgcolor`]: /configuration/imaging/#bgcolor
[`compression`]: /configuration/imaging/#compression
[`cwebp`]: https://developers.google.com/speed/webp/docs/cwebp
[`muesli/smartcrop`]: https://github.com/muesli/smartcrop
[`hint`]: /configuration/imaging/#hint
[`Process`]: /methods/resource/process/
[`images.AutoOrient`]: /functions/images/autoorient/
[`images.Process`]: /functions/images/process/
[`Process`]: /methods/resource/process
[`quality`]: /configuration/imaging/#quality
[`resampleFilter`]: /configuration/imaging/#resamplefilter
[`muesli/smartcrop`]: https://github.com/muesli/smartcrop
[hexadecimal color]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color
[imaging configuration]: /configuration/imaging/
[source documentation]: https://github.com/disintegration/imaging#image-resizing
@@ -16,7 +16,7 @@ author = 'authors'
And this content structure:
```text
```tree
content/
├── books/
│ ├── and-then-there-were-none.md --> genres: suspense
@@ -26,13 +26,13 @@ content/
└── _index.md
```
To capture the "genres" `Taxonomy` object from within any template, use the [`Taxonomies`] method on a `Site` object.
To capture the "genres" `Taxonomy` object from within any template, use the [`Taxonomies`][] method on a `Site` object.
```go-html-template
{{ $taxonomyObject := .Site.Taxonomies.genres }}
```
To capture the "genres" `Taxonomy` object when rendering its page with a _taxonomy_ template, use the [`Terms`] method on the page's [`Data`] object:
To capture the "genres" `Taxonomy` object when rendering its page with a _taxonomy_ template, use the [`Terms`][] method on the page's [`Data`][] object:
```go-html-template {file="layouts/taxonomy.html"}
{{ $taxonomyObject := .Data.Terms }}
@@ -44,7 +44,7 @@ To inspect the data structure:
<pre>{{ debug.Dump $taxonomyObject }}</pre>
```
Although the [`Alphabetical`] and [`ByCount`] methods provide a better data structure for ranging through the taxonomy, you can render the weighted pages by term directly from the `Taxonomy` object:
Although the [`Alphabetical`][] and [`ByCount`][] methods provide a better data structure for ranging through the taxonomy, you can render the weighted pages by term directly from the `Taxonomy` object:
```go-html-template
{{ range $term, $weightedPages := $taxonomyObject }}
@@ -61,7 +61,6 @@ In the example above, the first anchor element is a link to the term page.
[`Alphabetical`]: /methods/taxonomy/alphabetical/
[`ByCount`]: /methods/taxonomy/bycount/
[`data`]: /methods/page/data/
[`terms`]: /methods/page/data/#in-a-taxonomy-template
[`taxonomies`]: /methods/site/taxonomies/
[`Data`]: /methods/page/data/
[`Taxonomies`]: /methods/site/taxonomies/
[`Terms`]: /methods/page/data/#in-a-taxonomy-template
@@ -6,19 +6,19 @@ An ordered taxonomy is a slice, where each element is an object that contains th
Each element of the slice provides these methods:
Count
`Count`
: (`int`) Returns the number of pages to which the term is assigned.
Page
`Page`
: (`page.Page`) Returns the term's `Page` object, useful for linking to the term page.
Pages
: (`page.Pages`) Returns a `Pages` object containing the `Page` objects to which the term is assigned, sorted by [taxonomic weight](g). To sort or group, use any of the [methods] available to the `Pages` object. For example, sort by the last modification date.
`Pages`
: (`page.Pages`) Returns a `Pages` object containing the `Page` objects to which the term is assigned, sorted by [taxonomic weight](g). To sort or group, use any of the [methods][] available to the `Pages` object. For example, sort by the last modification date.
Term
`Term`
: (`string`) Returns the term name.
WeightedPages
`WeightedPages`
: (`page.WeightedPages`) Returns a slice of weighted pages to which the term is assigned, sorted by taxonomic weight. The `Pages` method above is more flexible, allowing you to sort and group.
[methods]: /methods/pages/
+8 -9
View File
@@ -45,27 +45,26 @@ _comment: Do not remove front matter.
`:filename`
: {{< deprecated-in v0.144.0 />}}
: Use `:contentbasename` instead.
: Use the [`:contentbasename`](#contentbasename) token instead.
`:slugorfilename`
: {{< deprecated-in v0.144.0 />}}
: Use `:slugorcontentbasename` instead.
: Use the [`:slugorcontentbasename`](#slugorcontentbasename) token instead.
`:contentbasename`
: {{< new-in 0.144.0 />}}
: The [content base name].
[content base name]: /methods/page/file/#contentbasename
: The [content base name][].
`:slugorcontentbasename`
: {{< new-in 0.144.0 />}}
: The `slug` as defined in front matter, else the [content base name].
: The `slug` as defined in front matter, else the [content base name][].
For time-related values, you can also use the layout string components defined in Go's [time package]. For example:
[time package]: https://pkg.go.dev/time#pkg-constants
For time-related values, you can also use the layout string components defined in Go's [time package][]. For example:
{{< code-toggle file=hugo >}}
permalinks:
posts: /:06/:1/:2/:title/
{{< /code-toggle >}}
[content base name]: /methods/page/file/#contentbasename
[time package]: https://pkg.go.dev/time#pkg-constants
@@ -2,11 +2,11 @@
_comment: Do not remove front matter.
---
path
`path`
: (`string`) The path to the target page. Paths without a leading slash (`/`) are resolved first relative to the current page, and then relative to the rest of the site.
lang
`lang`
: (`string`) The language of the target page. Default is the current language. Optional.
outputFormat
`outputFormat`
: (`string`) The output format of the target page. Default is the current output format. Optional.
@@ -20,7 +20,7 @@ The primary use case for `PageInner` is to resolve links and [page resources](g)
Then call the shortcode in your Markdown:
```text {file="content/posts/post-1.md"}
```md {file="content/posts/post-1.md"}
{{%/* include "/posts/post-2" */%}}
```
@@ -31,15 +31,15 @@ Any render hook triggered while rendering `/posts/post-2` will get:
`PageInner` falls back to the value of `Page` if not relevant, and always returns a value.
> [!note]
> The `PageInner` method is only relevant for shortcodes that invoke the [`RenderShortcodes`] method, and you must call the shortcode using [Markdown notation].
> [!NOTE]
> The `PageInner` method is only relevant for shortcodes that invoke the [`RenderShortcodes`][] method, and you must call the shortcode using [Markdown notation][].
As a practical example, Hugo's embedded link and image render hooks use the `PageInner` method to resolve markdown link and image destinations. See the source code for each:
- [Embedded link render hook]
- [Embedded image render hook]
- [Embedded link render hook][]
- [Embedded image render hook][]
[`RenderShortcodes`]: /methods/page/rendershortcodes/
[Markdown notation]: /content-management/shortcodes/#notation
[Embedded link render hook]: <{{% eturl render-link %}}>
[Embedded image render hook]: <{{% eturl render-image %}}>
[Embedded link render hook]: <{{% eturl render-link %}}>
[Markdown notation]: /content-management/shortcodes/#notation
[`RenderShortcodes`]: /methods/page/rendershortcodes/
+11 -11
View File
@@ -4,18 +4,18 @@ _comment: Do not remove front matter.
## Scope
The method or function used to create a scratch pad determines its scope. For example, use the `Store` method on a `Page` object to create a scratch pad scoped to the page.
The method or function used to create the data structure determines its scope. For example, use the `Store` method on a `Page` object to create a data structure scoped to the page.
Scope|Method or function
:--|:--
page|[`PAGE.Store`]
site|[`SITE.Store`]
global|[`hugo.Store`]
local|[`collections.NewScratch`]
shortcode|[`SHORTCODE.Store`]
page|[`PAGE.Store`][]
site|[`SITE.Store`][]
global|[`hugo.Store`][]
local|[`collections.NewScratch`][]
shortcode|[`SHORTCODE.Store`][]
[`page.store`]: /methods/page/store
[`site.store`]: /methods/site/store
[`hugo.store`]: /functions/hugo/store
[`collections.newscratch`]: functions/collections/newscratch
[`shortcode.store`]: /methods/shortcode/store
[`PAGE.Store`]: /methods/page/store/
[`SHORTCODE.Store`]: /methods/shortcode/store/
[`SITE.Store`]: /methods/site/store/
[`collections.NewScratch`]: /functions/collections/newscratch/
[`hugo.Store`]: /functions/hugo/store/
+63 -68
View File
@@ -4,83 +4,78 @@
## Methods
### Set
Use these methods on the data structure.
Sets the value of the given key.
`Set`
: Sets the value of the given key.
```go-html-template
{{ .Store.Set "greeting" "Hello" }}
```
### Get
Gets the value of the given key.
```go-html-template
{{ .Store.Set "greeting" "Hello" }}
{{ .Store.Get "greeting" }} → Hello
```
### Add
Adds the given value to the existing value(s) of the given key.
For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be appended to that list.
```go-html-template
{{ .Store.Set "greeting" "Hello" }}
{{ .Store.Add "greeting" "Welcome" }}
{{ .Store.Get "greeting" }} → HelloWelcome
```
```go-html-template
{{ .Store.Set "total" 3 }}
{{ .Store.Add "total" 7 }}
{{ .Store.Get "total" }} → 10
```
```go-html-template
{{ .Store.Set "greetings" (slice "Hello") }}
{{ .Store.Add "greetings" (slice "Welcome" "Cheers") }}
{{ .Store.Get "greetings" }} → [Hello Welcome Cheers]
```
### SetInMap
Takes a `key`, `mapKey` and `value` and adds a map of `mapKey` and `value` to the given `key`.
```go-html-template
{{ .Store.SetInMap "greetings" "english" "Hello" }}
{{ .Store.SetInMap "greetings" "french" "Bonjour" }}
{{ .Store.Get "greetings" }} → map[english:Hello french:Bonjour]
```go-html-template
{{ .Store.Set "greeting" "Hello" }}
```
### DeleteInMap
`Get`
: (`any`) Gets the value of the given key.
Takes a `key` and `mapKey` and removes the map of `mapKey` from the given `key`.
```go-html-template
{{ .Store.Set "greeting" "Hello" }}
{{ .Store.Get "greeting" }} → Hello
```
```go-html-template
{{ .Store.SetInMap "greetings" "english" "Hello" }}
{{ .Store.SetInMap "greetings" "french" "Bonjour" }}
{{ .Store.DeleteInMap "greetings" "english" }}
{{ .Store.Get "greetings" }} → map[french:Bonjour]
```
`Add`
: Adds the given value to the existing value(s) of the given key.
### GetSortedMapValues
For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be appended to that list.
Returns an array of values from `key` sorted by `mapKey`.
```go-html-template
{{ .Store.Set "greeting" "Hello" }}
{{ .Store.Add "greeting" "Welcome" }}
{{ .Store.Get "greeting" }} → HelloWelcome
```
```go-html-template
{{ .Store.SetInMap "greetings" "english" "Hello" }}
{{ .Store.SetInMap "greetings" "french" "Bonjour" }}
{{ .Store.GetSortedMapValues "greetings" }} → [Hello Bonjour]
```
```go-html-template
{{ .Store.Set "total" 3 }}
{{ .Store.Add "total" 7 }}
{{ .Store.Get "total" }} → 10
```
### Delete
```go-html-template
{{ .Store.Set "greetings" (slice "Hello") }}
{{ .Store.Add "greetings" (slice "Welcome" "Cheers") }}
{{ .Store.Get "greetings" }} → [Hello Welcome Cheers]
```
Removes the given key.
`SetInMap`
: Takes a `key`, `mapKey` and `value` and adds a map of `mapKey` and `value` to the given `key`.
```go-html-template
{{ .Store.Set "greeting" "Hello" }}
{{ .Store.Delete "greeting" }}
```
```go-html-template
{{ .Store.SetInMap "greetings" "english" "Hello" }}
{{ .Store.SetInMap "greetings" "french" "Bonjour" }}
{{ .Store.Get "greetings" }} → map[english:Hello french:Bonjour]
```
`DeleteInMap`
: Takes a `key` and `mapKey` and removes the map of `mapKey` from the given `key`.
```go-html-template
{{ .Store.SetInMap "greetings" "english" "Hello" }}
{{ .Store.SetInMap "greetings" "french" "Bonjour" }}
{{ .Store.DeleteInMap "greetings" "english" }}
{{ .Store.Get "greetings" }} → map[french:Bonjour]
```
`GetSortedMapValues`
: (`[]any`) Returns an array of values from `key` sorted by `mapKey`.
```go-html-template
{{ .Store.SetInMap "greetings" "english" "Hello" }}
{{ .Store.SetInMap "greetings" "french" "Bonjour" }}
{{ .Store.GetSortedMapValues "greetings" }} → [Hello Bonjour]
```
`Delete`
: Removes the given key.
```go-html-template
{{ .Store.Set "greeting" "Hello" }}
{{ .Store.Delete "greeting" }}
```
+21
View File
@@ -0,0 +1,21 @@
---
_comment: Do not remove front matter.
---
## Scope
The method or function used to create the data structure determines its scope. For example, use the `Store` method on a `Page` object to create a data structure scoped to the page.
Scope|Method or function
:--|:--
page|[`PAGE.Store`][]
site|[`SITE.Store`][]
global|[`hugo.Store`][]
local|[`collections.NewScratch`][]
shortcode|[`SHORTCODE.Store`][]
[`PAGE.Store`]: /methods/page/store/
[`SHORTCODE.Store`]: /methods/shortcode/store/
[`SITE.Store`]: /methods/site/store/
[`collections.NewScratch`]: /functions/collections/newscratch/
[`hugo.Store`]: /functions/hugo/store/
@@ -2,31 +2,31 @@
_comment: Do not remove front matter.
---
anchorLineNos
`anchorLineNos`
: (`bool`) Whether to render each line number as an HTML anchor element, setting the `id` attribute of the surrounding `span` element to the line number. Irrelevant if `lineNos` is `false`. Default is `false`.
codeFences
`codeFences`
: (`bool`) Whether to highlight fenced code blocks. Default is `true`.
guessSyntax
`guessSyntax`
: (`bool`) Whether to automatically detect the language if the `LANG` argument is blank or set to a language for which there is no corresponding [lexer](g). Falls back to a plain text lexer if unable to automatically detect the language. Default is `false`.
> [!note]
> [!NOTE]
> The syntax highlighter includes lexers for approximately 300 languages, but only 5 of these have implemented automatic language detection.
hl_Lines
`hl_Lines`
: (`string`) A space-delimited list of lines to emphasize within the highlighted code. To emphasize lines 2, 3, 4, and 7, set this value to `2-4 7`. This option is independent of the `lineNoStart` option.
hl_inline
`hl_inline`
: (`bool`) Whether to render the highlighted code without a wrapping container. Default is `false`.
lineAnchors
`lineAnchors`
: (`string`) When rendering a line number as an HTML anchor element, prepend this value to the `id` attribute of the surrounding `span` element. This provides unique `id` attributes when a page contains two or more code blocks. Irrelevant if `lineNos` or `anchorLineNos` is `false`.
lineNoStart
`lineNoStart`
: (`int`) The number to display at the beginning of the first line. Irrelevant if `lineNos` is `false`. Default is `1`.
lineNos
`lineNos`
: (`any`) Controls line number display. Default is `false`.
- `true`: Enable line numbers, controlled by `lineNumbersInTable`.
@@ -34,23 +34,23 @@ lineNos
- `inline`: Enable inline line numbers (sets `lineNumbersInTable` to `false`).
- `table`: Enable table-based line numbers (sets `lineNumbersInTable` to `true`).
lineNumbersInTable
`lineNumbersInTable`
: (`bool`) Whether to render the highlighted code in an HTML table with two cells. The left table cell contains the line numbers, while the right table cell contains the code. Irrelevant if `lineNos` is `false`. Default is `true`.
noClasses
`noClasses`
: (`bool`) Whether to use inline CSS styles instead of an external CSS file. Default is `true`. To use an external CSS file, set this value to `false` and generate the CSS file from the command line:
```text
```sh
hugo gen chromastyles --style=monokai > syntax.css
```
style
`style`
: (`string`) The CSS styles to apply to the highlighted code. This value is case-insensitive. Default is `monokai`. See [syntax highlighting styles][].
tabWidth
`tabWidth`
: (`int`) Substitute this number of spaces for each tab character in your highlighted code. Irrelevant if `noClasses` is `false`. Default is `4`.
wrapperClass
`wrapperClass`
: {{< new-in 0.140.2 />}}
: (`string`) The class or classes to use for the outermost element of the highlighted code. Default is `highlight`.
@@ -2,9 +2,7 @@
_comment: Do not remove front matter.
---
Format a `time.Time` value based on [Go's reference time]:
[Go's reference time]: https://pkg.go.dev/time#pkg-constants
Format a `time.Time` value based on [Go's reference time][]:
```text
Mon Jan 2 15:04:05 MST 2006
@@ -36,7 +34,7 @@ Time zone offsets|`"Z0700" "Z07:00" "Z07" "Z070000" "Z07:00:00"`
{{ $t = time.AsTime $t }}
{{ $t = $t.Format "Jan 02, 2006 3:04 PM Z07:00" }}
{{ $t }} → Jan 27, 2023 11:44 PM -08:00
{{ $t }} → Jan 27, 2023 11:44 PM -08:00
```
Strings such as `PST` and `CET` are not time zones. They are time zone _abbreviations_.
@@ -44,3 +42,5 @@ Strings such as `PST` and `CET` are not time zones. They are time zone _abbrevia
Strings such as `-07:00` and `+01:00` are not time zones. They are time zone _offsets_.
A time zone is a geographic area with the same local time. For example, the time zone abbreviated by `PST` and `PDT` (depending on Daylight Savings Time) is `America/Los_Angeles`.
[Go's reference time]: https://pkg.go.dev/time#pkg-constants
+55 -59
View File
@@ -8,137 +8,133 @@ weight: 20
## Framework
[Multiplatform]
[Multiplatform][]
: Install Hugo's single executable on Linux, macOS, Windows, and more.
[Multilingual]
[Multilingual][]
: Localize your project for each language and region, including translations, images, dates, currencies, numbers, percentages, and collation sequence. Hugo's multilingual framework supports single-host and multihost configurations.
[Output formats]
[Output formats][]
: Render each page of your project to one or more output formats, with granular control by page kind, section, and path. While HTML is the default output format, you can add JSON, RSS, CSV, and more. For example, create a REST API to access content.
[Templates]
[Templates][]
: Create templates using variables, functions, and methods to transform your content, resources, and data into a published page. While HTML templates are the most common, you can create templates for any output format.
[Themes]
[Themes][]
: Reduce development time and cost by using one of the hundreds of themes contributed by the Hugo community. Themes are available for corporate sites, documentation projects, image portfolios, landing pages, personal and professional blogs, resumes, CVs, and more.
[Modules]
[Modules][]
: Reduce development time and cost by creating or importing packaged combinations of archetypes, assets, content, data, templates, translation tables, static files, or configuration settings. A module may serve as the basis for a new project, or to augment an existing project.
[Privacy]
[Privacy][]
: Configure your project to help comply with regional privacy regulations.
[Security]
[Security][]
: Hugo's security model is based on the premise that template and configuration authors are trusted, but content authors are not. This model enables generation of HTML output safe against code injection. Other protections prevent "shelling out" to arbitrary applications, limit access to specific environment variables, prevent connections to arbitrary remote data sources, and more.
## Content authoring
[Content formats]
: Create your content using Markdown, HTML, AsciiDoc, Emacs Org Mode, Pandoc, or reStructuredText. Markdown is the default content format, conforming to the [CommonMark] and [GitHub Flavored Markdown] specifications.
[Content formats][]
: Create your content using Markdown, HTML, AsciiDoc, Emacs Org Mode, Pandoc, or reStructuredText. Markdown is the default content format, conforming to the [CommonMark][] and [GitHub Flavored Markdown][] specifications.
[Markdown attributes]
[Markdown attributes][]
: Apply HTML attributes such as `class` and `id` to Markdown images and block elements including blockquotes, fenced code blocks, headings, horizontal rules, lists, paragraphs, and tables.
[Markdown extensions]
[Markdown extensions][]
: Leverage the embedded Markdown extensions to create tables, definition lists, footnotes, task lists, inserted text, mark text, subscripts, superscripts, and more.
[Markdown render hooks]
[Markdown render hooks][]
: Override the conversion of Markdown to HTML when rendering blockquotes, fenced code blocks, headings, images, links, and tables. For example, render every standalone image as an HTML `figure` element.
[Diagrams]
[Diagrams][]
: Use fenced code blocks and Markdown render hooks to include diagrams in your content.
[Mathematics]
[Mathematics][]
: Include mathematical equations and expressions in Markdown using LaTeX markup.
[Syntax highlighting]
[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.
[Shortcodes]
[Shortcodes][]
: Use Hugo's embedded shortcodes, or create your own, to insert complex content. For example, use shortcodes to include `audio` and `video` elements, render tables from local or remote data sources, insert snippets from other pages, and more.
## Content management
[Multidimensional content model]
[Multidimensional content model][]
: Generate pages across any combination of language, version, and role from a single source. This allows a single piece of content to be published to multiple [sites](g) within your project, removing the need to duplicate files for different audiences or versions.
[Content adapters]
[Content adapters][]
: Create content adapters to dynamically add content when building your project. For example, use a content adapter to create pages from a remote data source such as JSON, TOML, YAML, or XML.
[Taxonomies]
[Taxonomies][]
: Classify content to establish simple or complex logical relationships between pages. For example, create an authors taxonomy, and assign one or more authors to each page. Among other uses, the taxonomy system provides an inverted, weighted index to render a list of related pages, ordered by relevance.
[Data]
[Data][]
: Augment your content using local or remote data sources including CSV, JSON, TOML, YAML, and XML. For example, create a shortcode to render an HTML table from a remote CSV file.
[Menus]
[Menus][]
: Provide rapid access to content via Hugo's menu system, configured automatically, globally, or on a page-by-page basis. The menu system is a key component of Hugo's multilingual architecture.
[URL management]
[URL management][]
: Serve any page from any path via global configuration or on a page-by-page basis.
## Asset pipelines
[CSS Processing]
[CSS Processing][]
: Bundle, transform, minify, create source maps, perform SRI hashing, and integrate with PostCSS.
[Image processing]
[Image processing][]
: Convert, resize, crop, rotate, adjust colors, apply filters, overlay text and images, and extract metadata.
[JavaScript bundling]
[JavaScript bundling][]
: Transpile TypeScript and JSX to JavaScript, bundle, tree shake, minify, create source maps, and perform SRI hashing.
[Sass processing]
[Sass processing][]
: Transpile Sass to CSS, bundle, tree shake, minify, create source maps, perform SRI hashing, and integrate with PostCSS.
[Tailwind CSS processing]
[Tailwind CSS processing][]
: Compile Tailwind CSS utility classes into standard CSS, bundle, tree shake, optimize, minify, perform SRI hashing, and integrate with PostCSS.
## Performance
[Caching]
[Caching][]
: Reduce build time and cost by rendering a _partial_ template once then cache the result, either globally or within a given context. For example, cache the result of an asset pipeline to prevent reprocessing on every rendered page.
[Segmentation]
[Segmentation][]
: Reduce build time and cost by partitioning your sites into segments. For example, render the home page and the "news section" every hour, and render the entire project once a week.
[Minification]
[Minification][]
: Minify HTML, CSS, and JavaScript to reduce file size, bandwidth consumption, and loading times.
[Multilingual]: /content-management/multilingual/
[Multiplatform]: /installation/
[Output formats]: /configuration/output-formats/
[Templates]: /templates/introduction/
[Themes]: https://themes.gohugo.io/
[Modules]: /hugo-modules/
[Privacy]: /configuration/privacy/
[Security]: /about/security/
[Content formats]: /content-management/formats/
[CSS Processing]: /functions/css/build/
[Caching]: /functions/partials/includecached/
[CommonMark]: https://spec.commonmark.org/current/
[Content adapters]: /content-management/content-adapters/
[Content formats]: /content-management/formats/
[Data]: /content-management/data-sources/
[Diagrams]: /content-management/diagrams/
[GitHub Flavored Markdown]: https://github.github.com/gfm/
[Image processing]: /content-management/image-processing/
[JavaScript bundling]: /functions/js/build/
[Markdown attributes]: /content-management/markdown-attributes/
[Markdown extensions]: /configuration/markup/#extensions
[Markdown render hooks]: /render-hooks/introduction/
[Diagrams]: /content-management/diagrams/
[Mathematics]: /content-management/mathematics/
[Syntax highlighting]: /content-management/syntax-highlighting/
[Shortcodes]: /content-management/shortcodes/
[Multidimensional content model]: /quick-reference/glossary/#sites-matrix
[Content adapters]: /content-management/content-adapters/
[Taxonomies]: /content-management/taxonomies/
[Data]: /content-management/data-sources/
[Menus]: /content-management/menus/
[URL management]: /content-management/urls/
[CSS processing]: /functions/css/build/
[Image processing]: /content-management/image-processing/
[JavaScript bundling]: /functions/js/build/
[Sass processing]: /functions/css/sass/
[Tailwind CSS processing]: /functions/css/tailwindcss/
[Caching]: /functions/partials/includecached/
[Segmentation]: /configuration/segments/
[Minification]: /configuration/minify/
[Modules]: /hugo-modules/
[Multidimensional content model]: /quick-reference/glossary/#sites-matrix
[Multilingual]: /content-management/multilingual/
[Multiplatform]: /installation/
[Output formats]: /configuration/output-formats/
[Privacy]: /configuration/privacy/
[Sass processing]: /functions/css/sass/
[Security]: /about/security/
[Segmentation]: /configuration/segments/
[Shortcodes]: /content-management/shortcodes/
[Syntax highlighting]: /content-management/syntax-highlighting/
[Tailwind CSS processing]: /functions/css/tailwindcss/
[Taxonomies]: /content-management/taxonomies/
[Templates]: /templates/introduction/
[Themes]: https://themes.gohugo.io/
[URL management]: /content-management/urls/
+10 -10
View File
@@ -7,7 +7,7 @@ weight: 10
aliases: [/about/what-is-hugo/,/about/benefits/]
---
Hugo is a [static site generator] written in [Go], optimized for speed and designed for flexibility. With its advanced templating system and fast asset pipelines, Hugo renders a complete site in seconds, often less.
Hugo is a [static site generator][] written in [Go][], optimized for speed and designed for flexibility. With its advanced templating system and fast asset pipelines, Hugo renders a complete site in seconds, often less.
Due to its flexible framework, multilingual support, and powerful taxonomy system, Hugo is widely used to create:
@@ -20,15 +20,15 @@ Due to its flexible framework, multilingual support, and powerful taxonomy syste
Use Hugo's embedded web server during development to instantly see changes to content, structure, behavior, and presentation. Then deploy the site to your host, or push changes to your Git provider for automated builds and deployment.
And with [Hugo Modules], you can share content, assets, data, translations, themes, templates, and configuration with other projects via public or private Git repositories.
And with [modules][] you can share content, assets, data, translations, themes, templates, and configuration with other projects via public or private Git repositories.
Learn more about Hugo's [features], [privacy protections], and [security model].
[Go]: https://go.dev
[Hugo Modules]: /hugo-modules/
[static site generator]: https://en.wikipedia.org/wiki/Static_site_generator
[features]: /about/features/
[security model]: /about/security/
[privacy protections]: /configuration/privacy
Learn more about Hugo's [features][], [privacy protections][], and [security model][].
{{< youtube 0RKpf3rK57I >}}
[Go]: https://go.dev
[features]: /about/features/
[modules]: /hugo-modules/
[privacy protections]: /configuration/privacy/
[security model]: /about/security/
[static site generator]: https://en.wikipedia.org/wiki/Static_site_generator
+1 -1
View File
@@ -8,7 +8,7 @@ weight: 40
## Apache License
_Version 2.0, January 2004_
_Version 2.0, January 2004_
_<http://www.apache.org/licenses/>_
### Terms and Conditions for use, reproduction, and distribution
+15 -14
View File
@@ -1,6 +1,6 @@
---
title: Security model
linkTitle: Security
linkTitle: Security
description: A summary of Hugo's security model.
categories: []
keywords: []
@@ -31,32 +31,33 @@ This combination of sandboxing and strict defaults effectively minimizes potenti
## Dependency security
Hugo utilizes [Go Modules][] to manage its dependencies, compiling as a static binary. Go Modules create a `go.sum` file, a critical security feature. This file acts as a database, storing the expected cryptographic checksums of all dependencies, including those required indirectly (transitive dependencies).
Hugo utilizes [Go modules][] to manage its dependencies, compiling as a static binary. Go modules create a `go.sum` file, a critical security feature. This file acts as a database, storing the expected cryptographic checksums of all dependencies, including those required indirectly (transitive dependencies).
[Hugo Modules][], which extend Go Modules' functionality, also produce a `go.sum` file. To ensure dependency integrity, commit this `go.sum` file to your version control. If Hugo detects a checksum mismatch during the build process, it will fail, indicating a possible attempt to [tamper with your project's dependencies][].
[Hugo modules][], which extend the functionality of Go modules, also produce a `go.sum` file. To ensure dependency integrity, commit this `go.sum` file to your version control. If Hugo detects a checksum mismatch during the build process, it will fail, indicating a possible attempt to [tamper with your project's dependencies][].
## Web application security
Hugo's security philosophy is rooted in established security standards, primarily aligning with the threats defined by [OWASP][]. For HTML output, Hugo operates under a clear trust model. This model assumes that template and configuration authors, the developers, are trustworthy. However, the data supplied to these templates is inherently considered untrusted. This distinction is crucial for understanding how Hugo handles potential security risks.
To prevent unintended escaping of data that developers know is safe, Hugo provides [`safe`][] functions, such as [`safeHTML`][]. These functions allow developers to explicitly mark data as trusted, bypassing the default escaping mechanisms. This is essential for scenarios where data is generated or sourced from reliable sources. However, an exception exists: enabling [inline shortcodes][]. By activating this feature, you are implicitly trusting the logic within the shortcodes and the data contained within your content files.
To prevent unintended escaping of data that developers know is safe, Hugo provides [`safe`][] functions, such as [`safe.HTML`][]. These functions allow developers to explicitly mark data as trusted, bypassing the default escaping mechanisms. This is essential for scenarios where data is generated or sourced from reliable sources. However, an exception exists: enabling [inline shortcodes][]. By activating this feature, you are implicitly trusting the logic within the shortcodes and the data contained within your content files.
It's vital to remember that Hugo is a static site generator. This architectural choice significantly reduces the attack surface by eliminating the complexities and vulnerabilities associated with dynamic user input. Unlike dynamic websites, Hugo generates static HTML files, minimizing the risk of real-time attacks. Regarding content, Hugo's default Markdown renderer is [configured to sanitize][] potentially unsafe content. This default behavior ensures that potentially malicious code or scripts are removed or escaped. However, this setting can be reconfigured if you have a high degree of confidence in the safety of your content sources.
In essence, Hugo prioritizes secure output by establishing a clear trust boundary between developers and data. By default, it errs on the side of caution, sanitizing potentially unsafe content and escaping data. Developers have the flexibility to adjust these defaults through [`safe`][] functions and [configuration options][], but they must do so with a clear understanding of the security implications. Hugo's static site generation model further strengthens its security posture by minimizing dynamic vulnerabilities.
In essence, Hugo prioritizes secure output by establishing a clear trust boundary between developers and data. By default, it errs on the side of caution, sanitizing potentially unsafe content and escaping data. Developers have the flexibility to adjust these defaults through [`safe`][] functions and [configuration settings][], but they must do so with a clear understanding of the security implications. Hugo's static site generation model further strengthens its security posture by minimizing dynamic vulnerabilities.
## Configuration
See [configure security](/configuration/security/).
See [configure security][].
[`safe`]: /functions/safe
[`safeHTML`]: /functions/safe/html/
[content adapters]: /content-management/content-adapters/
[configuration options]: /configuration/security
[configured to sanitize]: /configuration/markup/#rendererunsafe
[Go Modules]: https://go.dev/wiki/Modules#modules
[Hugo Modules]: /hugo-modules/
[inline shortcodes]: /content-management/shortcodes/#inline
[Go modules]: https://go.dev/wiki/Modules#modules
[Hugo modules]: /hugo-modules/
[OWASP]: https://en.wikipedia.org/wiki/OWASP
[`safe.HTML`]: /functions/safe/html/
[`safe`]: /functions/safe/
[configuration settings]: /configuration/security/
[configure security]: /configuration/security/
[configured to sanitize]: /configuration/markup/#rendererunsafe
[content adapters]: /content-management/content-adapters/
[inline shortcodes]: /content-management/shortcodes/#inline
[security policy]: /configuration/security/
[tamper with your project's dependencies]: https://julienrenaux.fr/2019/12/20/github-actions-security-risk/
+129 -138
View File
@@ -9,320 +9,317 @@ aliases: [/getting-started/configuration/]
## Settings
archetypeDir
`archetypeDir`
: (`string`) The designated directory for [archetypes](g). Default is `archetypes`. {{% module-mounts-note %}}
assetDir
`assetDir`
: (`string`) The designated directory for [global resources](g). Default is `assets`. {{% module-mounts-note %}}
baseURL
`baseURL`
: (`string`) The absolute URL of your published site including the protocol, host, path, and a trailing slash.
build
`build`
: See [configure build][].
buildDrafts
`buildDrafts`
: (`bool`) Whether to include draft content when building a site. Default is `false`.
buildExpired
`buildExpired`
: (`bool`) Whether to include expired content when building a site. Default is `false`.
buildFuture
`buildFuture`
: (`bool`) Whether to include future content when building a site. Default is `false`.
cacheDir
: (`string`) The designated cache directory. See&nbsp;[details](#cache-directory).
`cacheDir`
: (`string`) The designated cache directory. See [details](#cache-directory).
caches
`caches`
: See [configure file caches][].
canonifyURLs
: (`bool`) See&nbsp;[details](/content-management/urls/#canonical-urls) before enabling this feature. Default is `false`.
`canonifyURLs`
: (`bool`) See [details][canonical-urls] before enabling this feature. Default is `false`.
capitalizeListTitles
: (`bool`) Whether to capitalize automatic list titles. Applicable to section, taxonomy, and term pages. Use the [`titleCaseStyle`][] setting to configure capitalization rules. Default is `true`.
`capitalizeListTitles`
: (`bool`) Whether to capitalize automatic list titles. Applicable to section, taxonomy, and term pages. Use the [`titleCaseStyle`](#titlecasestyle) setting to configure capitalization rules. Default is `true`.
cascade
`cascade`
: See [configure cascade][].
cleanDestinationDir
: (`bool`) Whether to remove files from the [`publishDir`][] that do not exist in the [`staticDir`][] when building the site. This setting will not take effect if the `staticDir` does not exist. Note that `.gitignore` and `.gitattributes` files, along with directories named `.git`, are always preserved in the `publishDir`. Default is `false`.
`cleanDestinationDir`
: (`bool`) Whether to remove files from the [`publishDir`](#publishdir) that do not exist in the [`staticDir`](#staticdir) when building the site. This setting will not take effect if the `staticDir` does not exist. Note that `.gitignore` and `.gitattributes` files, along with directories named `.git`, are always preserved in the `publishDir`. Default is `false`.
contentDir
`contentDir`
: (`string`) The designated directory for content files. Default is `content`. {{% module-mounts-note %}}
copyright
`copyright`
: (`string`) The copyright notice for a site, typically displayed in the footer.
dataDir
`dataDir`
: (`string`) The designated directory for data files. Default is `data`. {{% module-mounts-note %}}
defaultContentLanguage
`defaultContentLanguage`
: (`string`) The projects's [default language](g), conforming to the syntax described in [RFC 5646][].
defaultContentLanguageInSubdir
: (`bool`) Whether to publish the default content language to a subdirectory matching the [`defaultContentLanguage`][]. Default is `false`.
`defaultContentLanguageInSubdir`
: (`bool`) Whether to publish the default content language to a subdirectory matching the [`defaultContentLanguage`](#defaultcontentlanguage). Default is `false`.
defaultContentRole
`defaultContentRole`
: {{< new-in 0.153.0 />}}
: (`string`) The project's [default role](g).
defaultContentRoleInSubdir
`defaultContentRoleInSubdir`
: {{< new-in 0.153.0 />}}
: (`bool`) Whether to publish the default content [role](g) to a subdirectory matching the [`defaultContentRole`][]. Default is `false`.
: (`bool`) Whether to publish the default content [role](g) to a subdirectory matching the [`defaultContentRole`](#defaultcontentrole). Default is `false`.
defaultContentVersion
`defaultContentVersion`
: {{< new-in 0.153.0 />}}
: (`string`) The project's [default version](g).
defaultContentVersionInSubdir
`defaultContentVersionInSubdir`
: {{< new-in 0.153.0 />}}
: (`bool`) Whether to publish the default content version to a subdirectory matching the [`defaultContentVersion`][]. Default is `false`.
: (`bool`) Whether to publish the default content version to a subdirectory matching the [`defaultContentVersion`](#defaultcontentversion). Default is `false`.
defaultOutputFormat
`defaultOutputFormat`
: (`string`) The default output format for the site. If unspecified, the first available format in the defined order (by weight, then alphabetically) will be used.
deployment
`deployment`
: See [configure deployment][].
disableAliases
`disableAliases`
: (`bool`) Whether to disable the generation of HTML redirect files for each path defined in the [`aliases`][aliases_front_matter] front matter field. When `true`, Hugo will not create physical files for [client-side redirection][], but the alias data remains available via the [`Aliases`][aliases_page_method] method on a `Page` object. Default is `false`.
disableDefaultLanguageRedirect
`disableDefaultLanguageRedirect`
: {{< new-in 0.140.0 />}}
: (`bool`) Whether to disable generation of the alias redirect for the default content language. When [`defaultContentLanguageInSubdir`][] is `true`, this setting prevents the root directory from redirecting to the language subdirectory. Conversely, when `defaultContentLanguageInSubdir` is `false`, this setting prevents the language subdirectory from redirecting to the root directory. This is superseded by the more general [`disableDefaultSiteRedirect`][] setting. Default is `false`.
: (`bool`) Whether to disable generation of the alias redirect for the default content language. When [`defaultContentLanguageInSubdir`](#defaultcontentlanguageinsubdir) is `true`, this setting prevents the root directory from redirecting to the language subdirectory. Conversely, when `defaultContentLanguageInSubdir` is `false`, this setting prevents the language subdirectory from redirecting to the root directory. This is superseded by the more general [`disableDefaultSiteRedirect`](#disabledefaultsiteredirect) setting. Default is `false`.
disableDefaultSiteRedirect
`disableDefaultSiteRedirect`
: {{< new-in 0.154.5 />}}
: (`bool`) Whether to disable generation of the alias redirect to the [default site](g). When [`defaultContentLanguageInSubdir`][], [`defaultContentRoleInSubdir`][], or [`defaultContentVersionInSubdir`][] is `true`, this prevents the root directory from redirecting to the default site's subdirectory. Conversely, when these are `false`, it prevents the subdirectories from redirecting back to the root. Default is `false`.
: (`bool`) Whether to disable generation of the alias redirect to the [default site](g). When [`defaultContentLanguageInSubdir`](#defaultcontentlanguageinsubdir), [`defaultContentRoleInSubdir`](#defaultcontentroleinsubdir), or [`defaultContentVersionInSubdir`](#defaultcontentversioninsubdir) is `true`, this prevents the root directory from redirecting to the default site's subdirectory. Conversely, when these are `false`, it prevents the subdirectories from redirecting back to the root. Default is `false`.
disableHugoGeneratorInject
`disableHugoGeneratorInject`
: (`bool`) Whether to disable injection of a `<meta name="generator">` tag into the home page. Default is `false`.
disableKinds
`disableKinds`
: (`[]string`) A slice of page [kinds](g) to disable during the build process, any of `404`, `home`, `page`, `robotstxt`, `rss`, `section`, `sitemap`, `taxonomy`, or `term`.
disableLanguages
`disableLanguages`
: (`[]string`) A slice of language keys representing the languages to disable during the build process. Although this is functional, consider using the [`disabled`][] key under each language instead.
disableLiveReload
`disableLiveReload`
: (`bool`) Whether to disable automatic live reloading of the browser window. Default is `false`.
disablePathToLower
`disablePathToLower`
: (`bool`) Whether to disable transformation of page URLs to lower case. Default is `false`.
enableEmoji
`enableEmoji`
: (`bool`) Whether to allow emoji in Markdown. Default is `false`.
enableGitInfo
`enableGitInfo`
: (`bool`) Whether to retrieve commit metadata from the Git history of your local project and any [modules](g). This enables the [`GitInfo`][] method on a `Page` object. With the default front matter configuration, the [`Lastmod`][] method on a `Page` object returns the Git author date of the last commit for that file. Default is `false`.
enableMissingTranslationPlaceholders
`enableMissingTranslationPlaceholders`
: (`bool`) Whether to show a placeholder instead of the default value or an empty string if a translation is missing. Default is `false`.
enableRobotsTXT
`enableRobotsTXT`
: (`bool`) Whether to enable generation of a `robots.txt` file. Default is `false`.
environment
: (`string`) The build environment. Default is `production` when running `hugo build` and `development` when running `hugo server`.
frontmatter
`frontmatter`
: See [configure front matter][].
hasCJKLanguage
`hasCJKLanguage`
: (`bool`) Whether to automatically detect [CJK](g) languages in content. Affects the values returned by the [`WordCount`][] and [`FuzzyWordCount`][] methods. Default is `false`.
HTTPCache
`HTTPCache`
: See [configure HTTP cache][].
i18nDir
`i18nDir`
: (`string`) The designated directory for translation tables. Default is `i18n`. {{% module-mounts-note %}}
ignoreCache
`ignoreCache`
: (`bool`) Whether to ignore the configured file caches. Default is `false`.
ignoreFiles
`ignoreFiles`
: (`[]string`) A slice of [regular expressions](g) used to exclude specific files from a build. These expressions are matched against the absolute file path and apply to files within the `content`, `data`, and `i18n` directories. For more advanced file exclusion options, see the section on [module mounts][].
ignoreLogs
`ignoreLogs`
: (`[]string`) A slice of message identifiers corresponding to warnings and errors you wish to suppress. See [`erroridf`][] and [`warnidf`][].
ignoreVendorPaths
`ignoreVendorPaths`
: (`string`) A [glob pattern](g) matching the module paths to exclude from the `_vendor` directory.
imaging
`imaging`
: See [configure imaging][].
languageCode
`languageCode`
: {{<deprecated-in 0.158.0 />}}
: Use [`locale`](#locale) instead.
languages
`languages`
: See [configure languages][].
layoutDir
`layoutDir`
: (`string`) The designated directory for templates. Default is `layouts`. {{% module-mounts-note %}}
{{% include "/_common/configuration/locale.md" %}}
For a multilingual project, specify this value independently for each language key. See [configure languages][].
mainSections
`mainSections`
: (`string` or `[]string`) The main sections of a site. If set, the [`MainSections`][] method on the `Site` object returns the given sections, otherwise it returns the section with the most pages.
markup
`markup`
: See [configure markup][].
mediaTypes
`mediaTypes`
: See [configure media types][].
menus
`menus`
: See [configure menus][].
minify
`minify`
: See [configure minify][].
module
`module`
: See [configure modules][].
newContentEditor
`newContentEditor`
: (`string`) The editor to use when creating new content.
noBuildLock
`noBuildLock`
: (`bool`) Whether to disable creation of the `.hugo_build.lock` file. Default is `false`.
noChmod
`noChmod`
: (`bool`) Whether to disable synchronization of file permission modes. Default is `false`.
noTimes
`noTimes`
: (`bool`) Whether to disable synchronization of file modification times. Default is `false`.
outputFormats
`outputFormats`
: See [configure output formats][].
outputs
`outputs`
: See [configure outputs][].
page
`page`
: See [configure page][].
pagination
`pagination`
: See [configure pagination][].
panicOnWarning
`panicOnWarning`
: (`bool`) Whether to panic on the first WARNING. Default is `false`.
params
`params`
: See [configure params][].
permalinks
`permalinks`
: See [configure permalinks][].
pluralizeListTitles
`pluralizeListTitles`
: (`bool`) Whether to pluralize automatic list titles. Applicable to section pages. Default is `true`.
printI18nWarnings
`printI18nWarnings`
: (`bool`) Whether to log WARNINGs for each missing translation. Default is `false`.
printPathWarnings
`printPathWarnings`
: (`bool`) Whether to log WARNINGs when Hugo publishes two or more files to the same path. Default is `false`.
printUnusedTemplates
`printUnusedTemplates`
: (`bool`) Whether to log WARNINGs for each unused template. Default is `false`.
privacy
`privacy`
: See [configure privacy][].
publishDir
`publishDir`
: (`string`) The designated directory for publishing the site. Default is `public`.
refLinksErrorLevel
`refLinksErrorLevel`
: (`string`) The logging error level to use when the `ref` and `relref` functions, methods, and shortcodes are unable to resolve a reference to a page. Either `ERROR` or `WARNING`. Any `ERROR` will fail the build. Default is `ERROR`.
refLinksNotFoundURL
`refLinksNotFoundURL`
: (`string`) The URL to return when the `ref` and `relref` functions, methods, and shortcodes are unable to resolve a reference to a page.
related
`related`
: See [configure related content][].
relativeURLs
: (`bool`) See&nbsp;[details](/content-management/urls/#relative-urls) before enabling this feature. Default is `false`.
`relativeURLs`
: (`bool`) See [details][relative-urls] before enabling this feature. Default is `false`.
removePathAccents
`removePathAccents`
: (`bool`) Whether to remove [non-spacing marks][] from [composite characters][] in content paths. Default is `false`.
renderSegments
`renderSegments`
: (`[]string`) A slice of [segments](g) to render. If omitted, all segments are rendered. This option is typically set via a command-line flag, such as `hugo build --renderSegments segment1,segment2`. The provided segment names must correspond to those defined in the [`segments`][] configuration.
resourceDir
`resourceDir`
: (`string`) The designated directory for caching output from [asset pipelines](g). Default is `resources`.
roles
`roles`
: See [configure roles][].
security
`security`
: See [configure security][].
sectionPagesMenu
: (`string`) When set, each top-level section will be added to the menu identified by the provided value. See&nbsp;[details](/content-management/menus/#define-automatically).
`sectionPagesMenu`
: (`string`) When set, each top-level section will be added to the menu identified by the provided value. See [details][define-automatically].
segments
`segments`
: See [configure segments][].
server
`server`
: See [configure server][].
services
`services`
: See [configure services][].
sitemap
`sitemap`
: See [configure sitemap][].
staticDir
`staticDir`
: (`string`) The designated directory for static files. Default is `static`. {{% module-mounts-note %}}
summaryLength
`summaryLength`
: (`int`) Applicable to [automatic summaries][], the minimum number of words returned by the [`Summary`][] method on a `Page` object. The `Summary` method will return content truncated at the paragraph boundary closest to the specified `summaryLength`, but at least this minimum number of words. Default is `70`.
taxonomies
`taxonomies`
: See [configure taxonomies][].
templateMetrics
: (`bool`) Whether to print template execution metrics to the console. Default is `false`. See&nbsp;[details](/troubleshooting/performance/#template-metrics).
`templateMetrics`
: (`bool`) Whether to print template execution metrics to the console. Default is `false`. See [details][template-metrics].
templateMetricsHints
: (`bool`) Whether to print template execution improvement hints to the console. Applicable when `templateMetrics` is `true`. Default is `false`. See&nbsp;[details](/troubleshooting/performance/#template-metrics).
`templateMetricsHints`
: (`bool`) Whether to print template execution improvement hints to the console. Applicable when `templateMetrics` is `true`. Default is `false`. See [details][template-metrics].
theme
: (`string` or `[]string`) The [theme](g) to use. Multiple themes can be listed, with precedence given from left to right. See&nbsp;[details](/hugo-modules/theme-components/).
`theme`
: (`string` or `[]string`) The [theme](g) to use. Multiple themes can be listed, with precedence given from left to right. See [details][].
themesDir
`themesDir`
: (`string`) The designated directory for themes. Default is `themes`.
timeout
`timeout`
: (`string`) The timeout for generating page content, either as a [duration][] or in seconds. This timeout is used to prevent infinite recursion during content generation. You may need to increase this value if your pages take a long time to generate, for example, due to extensive image processing or reliance on remote content. Default is `60s`.
timeZone
: (`string`) The time zone used to parse dates without time zone offsets, including front matter date fields and values passed to the [`time.AsTime`][] and [`time.Format`][] template functions. The list of valid values may be system dependent, but should include `UTC`, `Local`, and any location in the [IANA Time Zone Database][]. For example, `America/Los_Angeles` and `Europe/Oslo` are valid time zones.
`timeZone`
: (`string`) The time zone used to parse dates without time zone offsets, including front matter date fields and values passed to the [`time.AsTime`][] and [`time.Format`][] functions. The list of valid values may be system dependent, but should include `UTC`, `Local`, and any location in the [IANA Time Zone Database][]. For example, `America/Los_Angeles` and `Europe/Oslo` are valid time zones.
title
`title`
: (`string`) The site title.
titleCaseStyle
: (`string`) The capitalization rules to follow when Hugo automatically generates a section title, or when using the [`strings.Title`][] function. One of `ap`, `chicago`, `go`, `firstupper`, or `none`. Default is `ap`. See&nbsp;[details](#title-case-style).
`titleCaseStyle`
: (`string`) The capitalization rules to follow when Hugo automatically generates a section title, or when using the [`strings.Title`][] function. One of `ap`, `chicago`, `go`, `firstupper`, or `none`. Default is `ap`. See [details](#title-case-style).
uglyurls
`uglyurls`
: See [configure ugly URLs][].
versions
`versions`
: See [configure versions][].
## Cache directory
Hugo's file cache directory is configurable via the [`cacheDir`][] configuration option or the `HUGO_CACHEDIR` environment variable. If neither is set, Hugo will use, in order of preference:
Hugo's file cache directory is configurable via the [`cacheDir`](#cachedir) setting or the `HUGO_CACHEDIR` environment variable. If neither is set, Hugo will use, in order of preference:
1. If running on Netlify: `/opt/build/cache/hugo_cache/`. This means that if you run your builds on Netlify, all caches configured with `:cacheDir` will be saved and restored on the next build. For other [CI/CD](g) platforms, please read their documentation. For a CircleCI example, see [this configuration][].
1. In a `hugo_cache` directory below the OS user cache directory as defined by Go's [os.UserCacheDir][] function. On Unix systems, per the [XDG base directory specification][], this is `$XDG_CACHE_HOME` if non-empty, else `$HOME/.cache`. On MacOS, this is `$HOME/Library/Caches`. On Windows, this is`%LocalAppData%`. On Plan 9, this is `$home/lib/cache`.
1. In a `hugo_cache` directory below the OS user cache directory as defined by Go's [`os.UserCacheDir`][] function. On Unix systems, per the [XDG base directory specification][], this is `$XDG_CACHE_HOME` if non-empty, else `$HOME/.cache`. On MacOS, this is `$HOME/Library/Caches`. On Windows, this is`%LocalAppData%`. On Plan 9, this is `$home/lib/cache`.
1. In a `hugo_cache_$USER` directory below the OS temp dir.
To determine the current `cacheDir`:
@@ -333,21 +330,21 @@ hugo config | grep cachedir
## Title case style
Hugo's [`titleCaseStyle`][] setting governs capitalization for automatically generated section titles and the [`strings.Title`][] function. By default, it follows the capitalization rules published in the Associated Press Stylebook. Change this setting to use other capitalization rules.
Hugo's [`titleCaseStyle`](#titlecasestyle) setting governs capitalization for automatically generated section titles and the [`strings.Title`][] function. By default, it follows the capitalization rules published in the Associated Press Stylebook. Change this setting to use other capitalization rules.
ap
`ap`
: Use the capitalization rules published in the [Associated Press Stylebook][]. This is the default.
chicago
`chicago`
: Use the capitalization rules published in the [Chicago Manual of Style][].
go
`go`
: Capitalize the first letter of every word.
firstupper
`firstupper`
: Capitalize the first letter of the first word.
none
`none`
: Disable transformation of automatic section titles, and disable the transformation performed by the `strings.Title` function. This is useful if you would prefer to manually capitalize section titles as needed, and to bypass opinionated theme usage of the `strings.Title` function.
## Localized settings
@@ -365,27 +362,18 @@ Some configuration settings, such as menus and custom parameters, can be defined
[`MainSections`]: /methods/site/mainsections/
[`Summary`]: /methods/page/summary/
[`WordCount`]: /methods/page/wordcount/
[`cacheDir`]: #cachedir
[`defaultContentLanguageInSubdir`]: #defaultcontentlanguageinsubdir
[`defaultContentLanguage`]: #defaultcontentlanguage
[`defaultContentRoleInSubdir`]: #defaultcontentroleinsubdir
[`defaultContentRole`]: #defaultcontentrole
[`defaultContentVersionInSubdir`]: #defaultcontentversioninsubdir
[`defaultContentVersion`]: #defaultcontentversion
[`disableDefaultSiteRedirect`]: #disabledefaultsiteredirect
[`disabled`]: /configuration/languages/#disabled
[`erroridf`]: /functions/fmt/erroridf/
[`publishDir`]: #publishdir
[`os.UserCacheDir`]: https://pkg.go.dev/os#UserCacheDir
[`segments`]: /configuration/segments/
[`staticDir`]: #staticdir
[`strings.Title`]: /functions/strings/title/
[`time.AsTime`]: /functions/time/astime/
[`time.Format`]: /functions/time/format/
[`titleCaseStyle`]: #titlecasestyle
[`warnidf`]: /functions/fmt/warnidf/
[aliases_front_matter]: /content-management/front-matter/#aliases
[aliases_page_method]: /methods/page/aliases/
[automatic summaries]: /content-management/summaries/#automatic-summary
[canonical-urls]: /content-management/urls/#canonical-urls
[client-side redirection]: /content-management/urls/#client-side-redirection
[composite characters]: https://en.wikipedia.org/wiki/Precomposed_character
[configure HTTP cache]: /configuration/http-cache/
@@ -408,7 +396,7 @@ Some configuration settings, such as menus and custom parameters, can be defined
[configure params]: /configuration/params/
[configure permalinks]: /configuration/permalinks/
[configure privacy]: /configuration/privacy/
[configure related content]: /configuration/related-content
[configure related content]: /configuration/related-content/
[configure roles]: /configuration/roles/
[configure security]: /configuration/security/
[configure segments]: /configuration/segments/
@@ -418,8 +406,11 @@ Some configuration settings, such as menus and custom parameters, can be defined
[configure taxonomies]: /configuration/taxonomies/
[configure ugly URLs]: /configuration/ugly-urls/
[configure versions]: /configuration/versions/
[define-automatically]: /content-management/menus/#define-automatically
[details]: /hugo-modules/theme-components/
[duration]: https://pkg.go.dev/time#Duration
[module mounts]: /configuration/module/#mounts
[non-spacing marks]: https://www.compart.com/en/unicode/category/Mn
[os.UserCacheDir]: https://pkg.go.dev/os#UserCacheDir
[relative-urls]: /content-management/urls/#relative-urls
[template-metrics]: /troubleshooting/performance/#template-metrics
[this configuration]: https://github.com/bep/hugo-sass-test/blob/6c3960a8f4b90e8938228688bc49bdcdd6b2d99e/.circleci/config.yml
+21 -19
View File
@@ -7,25 +7,25 @@ keywords: []
aliases: [/getting-started/configuration-build/]
---
The `build` configuration section contains global build-related configuration options.
This is the default configuration:
{{< code-toggle config=build />}}
buildStats
`buildStats`
: See the [build stats](#build-stats) section below.
cachebusters
`cachebusters`
: See the [cache busters](#cache-busters) section below.
noJSConfigInAssets
: (`bool`) Whether to disable writing a `jsconfig.json` in your `assets` directory with mapping of imports from running [js.Build](/hugo-pipes/js). This file is intended to help with intellisense/navigation inside code editors such as [VS Code](https://code.visualstudio.com/). Note that if you do not use `js.Build`, no file will be written.
`noJSConfigInAssets`
: (`bool`) Whether to disable writing a `jsconfig.json` in your `assets` directory with mapping of imports from running [js.Build][]. This file is intended to help with intellisense/navigation inside code editors such as [VS Code][]. Note that if you do not use `js.Build`, no file will be written.
useResourceCacheWhen
`useResourceCacheWhen`
: (`string`) When to use the resource file cache, one of `never`, `fallback`, or `always`. Applicable when transpiling Sass to CSS. Default is `fallback`.
## Cache busters
The `build.cachebusters` configuration option was added to support development using Tailwind 3.x's JIT compiler where a `build` configuration may look like this:
The `build.cachebusters` setting was added to support development using Tailwind 3.x's JIT compiler where a `build` configuration may look like this:
<!-- markdownlint-disable MD049 -->
{{< code-toggle file=hugo >}}
@@ -47,37 +47,39 @@ The `build.cachebusters` configuration option was added to support development u
{{< /code-toggle >}}
<!-- markdownlint-enable MD049 -->
When `buildStats` is enabled, Hugo writes a `hugo_stats.json` file on each build with HTML classes etc. that's used in the rendered output. Changes to this file will trigger a rebuild of the `styles.css` file. You also need to add `hugo_stats.json` to Hugo's server watcher. See [Hugo Starter Tailwind Basic](https://github.com/bep/hugo-starter-tailwind-basic) for a running example.
When `buildStats` is enabled, Hugo writes a `hugo_stats.json` file on each build with HTML classes etc. that's used in the rendered output. Changes to this file will trigger a rebuild of the `styles.css` file. You also need to add `hugo_stats.json` to Hugo's server watcher. See [Hugo Starter Tailwind Basic][] for a running example.
source
`source`
: (`string`) A [regular expression](g) matching file(s) relative to one of the virtual component directories in Hugo, typically `assets/...`.
target
`target`
: (`string`) A [regular expression](g) matching the keys in the resource cache that should be expired when `source` changes. You can use the matching regexp groups from `source` in the expression, e.g. `$1`.
## Build stats
{{< code-toggle config=build.buildStats />}}
enable
: (`bool`) Whether to create a `hugo_stats.json` file in the root of your project. This file contains arrays of the `class` attributes, `id` attributes, and tags of every HTML element within your published site. Use this file as data source when [removing unused CSS] from your site. This process is also known as pruning, purging, or tree shaking. Default is `false`.
`enable`
: (`bool`) Whether to create a `hugo_stats.json` file in the root of your project. This file contains arrays of the `class` attributes, `id` attributes, and tags of every HTML element within your published site. Use this file as data source when [removing unused CSS][] from your site. This process is also known as pruning, purging, or tree shaking. Default is `false`.
[removing unused CSS]: /functions/resources/postprocess/
disableIDs
`disableIDs`
: (`bool`) Whether to exclude `id` attributes. Default is `false`.
disableTags
`disableTags`
: (`bool`) Whether to exclude element tags. Default is `false`.
disableClasses
`disableClasses`
: (`bool`) Whether to exclude `class` attributes. Default is `false`.
> [!note]
> Given that CSS purging is typically limited to production builds, place the `buildStats` object below [`config/production`].
> [!NOTE]
> Given that CSS purging is typically limited to production builds, place the `buildStats` object below [`config/production`][].
>
> Built for speed, there may be "false positive" detections (e.g., HTML elements that are not HTML elements) while parsing the published site. These "false positives" are infrequent and inconsequential.
Due to the nature of partial server builds, new HTML entities are added while the server is running, but old values will not be removed until you restart the server or run `hugo build`.
[Hugo Starter Tailwind Basic]: https://github.com/bep/hugo-starter-tailwind-basic
[VS Code]: https://code.visualstudio.com/
[`config/production`]: /configuration/introduction/#configuration-directory
[js.Build]: /functions/js/build/
[removing unused CSS]: /functions/resources/postprocess/
+13 -11
View File
@@ -14,48 +14,50 @@ This is the default configuration:
Hugo uses file caches to store data on disk, avoiding repeated operations within the same build and persisting data from one build to the next.
assets
`assets`
: Caches processed CSS and Sass resources.
getresource
`getresource`
: Caches files fetched from remote URLs via the [`resources.GetRemote`][] function.
images
`images`
: Caches processed images.
misc
`misc`
: Caches miscellaneous data.
modulegitinfo
`modulegitinfo`
: Caches Git information for modules.
modulequeries
`modulequeries`
: Caches the results of module resolution queries.
modules
`modules`
: Caches downloaded modules.
## Keys
dir
`dir`
: (`string`) The absolute file system path where Hugo stores the cached files. You can begin the path with the `:cacheDir` or `:resourceDir` [tokens](#tokens) to anchor the cache to specific system or project locations.
maxAge
`maxAge`
: (`string`) The duration a cached entry remains valid before being evicted, expressed as a [duration](g). A value of `0` disables the cache for that key, and a value of `-1` means the cache entry never expires. Default is `-1`.
## Tokens
`:cacheDir`
: (`string`) The designated cache directory. See [details](/configuration/all/#cachedir).
: (`string`) The designated cache directory. See [details][cachedir].
`:project`
: (`string`) The base directory name of the current Hugo project. This ensures isolated file caches for each project, preventing the `hugo build --gc` command from affecting other projects on the same machine.
`:resourceDir`
: (`string`) The designated directory for caching output from [asset pipelines](g). See [details](/configuration/all/#resourcedir).
: (`string`) The designated directory for caching output from [asset pipelines](g). See [details][resourcedir].
## Garbage collection
As you modify your site or change your configuration, cached files from previous builds may remain on disk, consuming unnecessary space. Use the `hugo build --gc` command to remove these expired or unused entries from the file cache.
[`resources.GetRemote`]: /functions/resources/getremote/
[cachedir]: /configuration/all/#cachedir
[resourcedir]: /configuration/all/#resourcedir
+5 -4
View File
@@ -6,10 +6,10 @@ categories: []
keywords: []
---
You can configure your site to cascade front matter values to the home page and any of its descendants. However, this cascading will be prevented if the descendant already defines the field, or if a closer ancestor [node](g) has already cascaded a value for the same field through its front matter's `cascade` key.
You can configure your site to cascade front matter values to the home page and any of its descendants. However, this cascading will be prevented if the descendant already defines the field, or if a closer ancestor [branch](g) has already cascaded a value for the same field through its front matter's `cascade` key.
> [!note]
> You can also configure cascading behavior within a page's front matter. See&nbsp;[details][].
> [!NOTE]
> You can also configure cascading behavior within a page's front matter. See [details][].
For example, to cascade the `color` page parameter to all pages:
@@ -21,7 +21,8 @@ color = 'red'
## Target
<!-- TODO
We deprecated the `_target` front matter key in favor of `target` in v0.156.0 on 2026-02-17. Remove footnote #1 on or after 2027-05-17 (15 months after deprecation).
We deprecated the `_target` front matter key in favor of `target` in v0.156.0 on 2026-02-17. Remove footnote #1 somewhere after v0.171.0, 15 minor releases
after deprecation.
-->
The `target` key accepts a [page matcher](g) to limit cascaded values to a subset of pages.[^1] If a target is omitted, values cascade to all pages.
@@ -16,7 +16,7 @@ These can be used as either page content or [page resources](g). When used as pa
Consider this example of a [page bundle](g):
```text
```tree
content/
└── example/
├── index.md <-- content
@@ -34,7 +34,7 @@ The `index.md` file is the page's content, while the other files are page resour
When you build a site, Hugo does not publish page resources having a resource type of `page`. For example, this is the result of building the site above:
```text
```tree
public/
├── example/
│ ├── g.jpg
+40 -40
View File
@@ -6,68 +6,68 @@ categories: []
keywords: []
---
> [!note]
> This configuration is only relevant when running `hugo deploy`. See&nbsp;[details](/host-and-deploy/deploy-with-hugo-deploy/).
> [!NOTE]
> This configuration is only relevant when running `hugo deploy`. See [details][hugo deploy].
## Top-level options
## Top-level settings
These settings control the overall behavior of the deployment process. This is the default configuration:
{{< code-toggle file=hugo config=deployment />}}
confirm
`confirm`
: (`bool`) Whether to prompt for confirmation before deploying. Default is `false`.
dryRun
`dryRun`
: (`bool`) Whether to simulate the deployment without any remote changes. Default is `false`.
force
`force`
: (`bool`) Whether to re-upload all files. Default is `false`.
invalidateCDN
`invalidateCDN`
: (`bool`) Whether to invalidate the CDN cache listed in the deployment target. Default is `true`.
maxDeletes
`maxDeletes`
: (`int`) The maximum number of files to delete, or `-1` to disable. Default is `256`.
matchers
`matchers`
: (`[]*Matcher`) A slice of [matchers](#matchers-1).
order
`order`
: (`[]string`) An ordered slice of [regular expressions](g) that determines upload priority (left to right). Files not matching any expression are uploaded last in an arbitrary order.
target
`target`
: (`string`) The target deployment [`name`](#name). Defaults to the first target.
targets
`targets`
: (`[]*Target`) A slice of [targets](#targets-1).
workers
`workers`
: (`int`) The number of concurrent workers to use when uploading files. Default is `10`.
## Targets
A target represents a deployment target such as "staging" or "production".
cloudFrontDistributionID
`cloudFrontDistributionID`
: (`string`) The CloudFront Distribution ID, applicable if you are using the Amazon Web Services CloudFront CDN. Hugo will invalidate the CDN when deploying this target.
exclude
`exclude`
: (`string`) A [glob pattern](g) matching files to exclude when deploying to this target. Local files failing the include/exclude filters are not uploaded, and remote files failing these filters are not deleted.
googleCloudCDNOrigin
`googleCloudCDNOrigin`
: (`string`) The Google Cloud project and CDN origin to invalidate when deploying this target, specified as `<project>/<origin>`.
include
`include`
: (`string`) A [glob pattern](g) matching files to include when deploying to this target. Local files failing the include/exclude filters are not uploaded, and remote files failing these filters are not deleted.
name
`name`
: (`string`) An arbitrary name for this target.
stripIndexHTML
`stripIndexHTML`
: (`bool`) Whether to map files named `<dir>/index.html` to `<dir>` on the remote (except for the root `index.html`). This is useful for key-value cloud storage (e.g., Amazon S3, Google Cloud Storage, Azure Blob Storage) to align canonical URLs with object keys. Default is `false`.
url
`url`
: (`string`) The [destination URL](#destination-urls) for deployment.
## Matchers
@@ -75,28 +75,24 @@ url
A Matcher represents a configuration to be applied to files whose paths match
the specified pattern.
cacheControl
: (`string`) The caching attributes to use when serving the blob. See&nbsp;[details][cacheControl].
`cacheControl`
: (`string`) The caching attributes to use when serving the blob. See [details][cacheControl].
contentEncoding
: (`string`) The encoding used for the blob's content, if any. See&nbsp;[details][contentEncoding].
`contentEncoding`
: (`string`) The encoding used for the blob's content, if any. See [details][contentEncoding].
contentType
: (`string`) The media type of the blob being written. See&nbsp;[details][contentType].
`contentType`
: (`string`) The media type of the blob being written. See [details][contentType].
force
`force`
: (`bool`) Whether matching files should be re-uploaded. Useful when other route-determined metadata (e.g., `contentType`) has changed. Default is `false`.
gzip
`gzip`
: (`bool`) Whether the file should be gzipped before upload. If so, the `ContentEncoding` field will automatically be set to `gzip`. Default is `false`.
pattern
`pattern`
: (`string`) A [regular expression](g) used to match paths. Paths are converted to use forward slashes (`/`) before matching.
[cacheControl]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
[contentEncoding]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding
[contentType]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
## Destination URLs
Service|URL example
@@ -113,13 +109,9 @@ gs://my-bucket?prefix=a/subdirectory
You can also to deploy to storage servers compatible with Amazon S3 such as:
- [Ceph]
- [MinIO]
- [SeaweedFS]
[Ceph]: https://ceph.com/
[Minio]: https://www.minio.io/
[SeaweedFS]: https://github.com/chrislusf/seaweedfs
- [Ceph][]
- [MinIO][]
- [SeaweedFS][]
For example, the `url` for a MinIO deployment target might resemble this:
@@ -157,3 +149,11 @@ s3://my-bucket?endpoint=https://my.minio.instance&awssdk=v2&use_path_style=true&
exclude = '**.{heic,psd}'
name = 'staging'
{{< /code-toggle >}}
[Ceph]: https://ceph.com/
[MinIO]: https://www.minio.io/
[SeaweedFS]: https://github.com/chrislusf/seaweedfs
[cacheControl]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
[contentEncoding]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding
[contentType]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
[hugo deploy]: /host-and-deploy/deploy-with-hugo-deploy/
@@ -17,11 +17,6 @@ Method|Description
[`Lastmod`][]|Returns the last modification date of the given page.
[`PublishDate`][]|Returns the publish date of the given page.
[`Date`]: /methods/page/date
[`ExpiryDate`]: /methods/page/expirydate
[`Lastmod`]: /methods/page/lastmod
[`PublishDate`]: /methods/page/publishdate
Hugo determines the values to return based on this configuration:
{{< code-toggle config=frontmatter />}}
@@ -76,7 +71,9 @@ Hugo provides the following [tokens](g) to help you configure your front matter:
Within the `YYYY-MM-DD-HH-MM-SS` format, the date and time values may be separated by any character including a space (e.g., `2025-02-01T14-30-00`).
Hugo resolves the extracted date to the [`timeZone`][] defined in your project configuration, falling back to the system time zone. After extracting the date, Hugo uses the remaining part of the file name to generate the page's [`slug`][], but only if you haven't already specified a slug in the page's front matter.
Hugo resolves the extracted date to the [`timeZone`][] defined in your project configuration, falling back to the system time zone. Hugo also derives the page [`slug`][] from the remaining file name, unless the page already defines a `slug` in its front matter.
Slug inference only occurs when `:filename` is the winning date source. If an earlier entry in the list provides a valid date, Hugo skips `:filename` entirely. For example, with `date = ["date", ":filename"]`, a page that defines `date` in its front matter will use that value, and the slug will not be inferred from the file name.
For example, if you name your file `2025-02-01-article.md`, Hugo will set the date to `2025-02-01` and the slug to `article`.
@@ -98,6 +95,10 @@ To determine `date` and `publishDate`, Hugo tries to extract the value from the
To determine `lastmod`, Hugo looks for a `lastmod` field in front matter, falling back to the file's last modification timestamp.
[`Date`]: /methods/page/date/
[`ExpiryDate`]: /methods/page/expirydate/
[`Lastmod`]: /methods/page/lastmod/
[`PublishDate`]: /methods/page/publishdate/
[`enableGitInfo`]: /configuration/all/#enablegitinfo
[`slug`]: /content-management/front-matter/#slug
[`timeZone`]: /configuration/all/#timezone
+26 -26
View File
@@ -6,8 +6,8 @@ categories: []
keywords: []
---
> [!note]
> This configuration is only relevant when using the [`resources.GetRemote`] function.
> [!NOTE]
> This configuration is only relevant when using the [`resources.GetRemote`][] function.
## Layered caching
@@ -30,13 +30,13 @@ Hugo employs a layered caching system.
```
Dynacache
: An in-memory cache employing a Least Recently Used (LRU) eviction policy. Entries are removed from the cache when changes occur, when they match [cache-busting] patterns, or under low-memory conditions.
: An in-memory cache employing a Least Recently Used (LRU) eviction policy. Entries are removed from the cache when changes occur, when they match [cache-busting][] patterns, or under low-memory conditions.
HTTP Cache
: An HTTP cache for remote resources as specified in [RFC 9111]. Optimal performance is achieved when resources include appropriate HTTP cache headers. The HTTP cache utilizes the file cache for storage and retrieval of cached resources.
: An HTTP cache for remote resources as specified in [RFC 9111][]. Optimal performance is achieved when resources include appropriate HTTP cache headers. The HTTP cache utilizes the file cache for storage and retrieval of cached resources.
File cache
: See [configure file caches].
: See [configure file caches][].
The HTTP cache involves two key aspects: determining which content to cache (the caching process itself) and defining the frequency with which to check for updates (the polling strategy).
@@ -48,36 +48,36 @@ This is the default configuration for HTTP caching:
{{< code-toggle config=HTTPCache />}}
respectCacheControlNoStoreInRequest
`respectCacheControlNoStoreInRequest`
: {{< new-in 0.151.0 />}}
: (`bool`) Whether to respect the `no-store` directive in the server's `Cache-Control` request header when fetching remote resources via the [`resources.GetRemote`][] function. Default is `true`.
respectCacheControlNoStoreInResponse
`respectCacheControlNoStoreInResponse`
: {{< new-in 0.151.0 />}}
: (`bool`) Whether to respect the `no-store` directive in the server's `Cache-Control` response header when fetching remote resources via the [`resources.GetRemote`][] function. Default is `false`.
cache.for.excludes
`cache.for.excludes`
: (`[]string`) A slice of [glob patterns](g) to exclude from caching. In its default configuration HTTP caching excludes all files.
cache.for.includes
`cache.for.includes`
: (`[]string`) A slice of [glob patterns](g) to cache.
polls
: A slice of polling configurations.
`polls`
: (`[]PollConfig`) A slice of polling configurations.
polls.disable
`polls.disable`
: (`bool`) Whether to disable polling for this configuration. Default is `true`.
polls.high
`polls.high`
: (`string`) The maximum polling interval expressed as a [duration](g). This is used when the resource is considered stable. Default is `0s`.
polls.low
`polls.low`
: (`string`) The minimum polling interval expressed as a [duration](g). This is used after a recent change and gradually increases towards `polls.high`. Default is `0s`.
polls.for.excludes
`polls.for.excludes`
: (`[]string`) A slice of [glob patterns](g) to exclude from polling for this configuration.
polls.for.includes
`polls.for.includes`
: (`[]string`) A slice of [glob patterns](g) to include in polling for this configuration.
## HTTP polling
@@ -96,22 +96,22 @@ includes = ['**']
excludes = []
{{< /code-toggle >}}
polls
: A slice of polling configurations.
`polls`
: (`[]PollConfig`) A slice of polling configurations.
polls.disable
`polls.disable`
: (`bool`) Whether to disable polling for this configuration. Default is `true`.
polls.high
`polls.high`
: (`string`) The maximum polling interval expressed as a [duration](g). This is used when the resource is considered stable. Default is `0s`.
polls.low
`polls.low`
: (`string`) The minimum polling interval expressed as a [duration](g). This is used after a recent change and gradually increases towards `polls.high`. Default is `0s`.
polls.for.excludes
`polls.for.excludes`
: (`[]string`) A list of [glob patterns](g) to exclude from polling for this configuration.
polls.for.includes
`polls.for.includes`
: (`[]string`) A list of [glob patterns](g) to include in polling for this configuration.
## Behavior
@@ -120,10 +120,10 @@ Polling and HTTP caching interact as follows:
- With polling enabled, rebuilds are triggered only by actual changes, detected via `eTag` changes (Hugo generates an MD5 hash if the server doesn't provide one).
- If polling is enabled but HTTP caching is disabled, the remote is checked for changes only after the file cache's TTL expires (e.g., a `maxAge` of `10h` with a `1s` polling interval is inefficient).
- If both polling and HTTP caching are enabled, changes are checked for even before the file cache's TTL expires. Cached `eTag` and `last-modified` values are sent in `if-none-match` and `if-modified-since` headers, respectively, and a cached response is returned on HTTP [304].
- If both polling and HTTP caching are enabled, changes are checked for even before the file cache's TTL expires. Cached `eTag` and `last-modified` values are sent in `if-none-match` and `if-modified-since` headers, respectively, and a cached response is returned on HTTP [304][].
[`resources.GetRemote`]: /functions/resources/getremote/
[304]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304
[RFC 9111]: https://datatracker.ietf.org/doc/html/rfc9111
[`resources.GetRemote`]: /functions/resources/getremote/
[cache-busting]: /configuration/build/#cache-busters
[configure file caches]: /configuration/caches/
[RFC 9111]: https://datatracker.ietf.org/doc/html/rfc9111
+100 -36
View File
@@ -10,25 +10,30 @@ These are the default settings for processing images:
{{< code-toggle config=imaging />}}
## Top-level options
## Top-level settings
These global settings define how Hugo handles the fundamental aspects of image manipulation, such as cropping logic, background colors, and general output quality.
These settings apply to all image formats.
anchor
`anchor`
: (`string`) The focal point used when cropping or filling an image. Valid case-insensitive options include `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`. The `Smart` option utilizes the [`muesli/smartcrop`][] package to identify the most interesting area of the image. Default is `smart`.
bgColor
: (string) The background color used when converting transparent images to formats that do not support transparency, such as PNG to JPEG. This color also fills the empty space created when rotating an image by a non-orthogonal angle if the space is not transparent and a background color is not specified in the processing specification. The value must be an RGB [hexadecimal color][]. Default is `#ffffff`.
`bgColor`
: (`string`) The background color used when converting transparent images to formats that do not support transparency, such as PNG to JPEG. This color also fills the empty space created when rotating an image by a non-orthogonal angle if the space is not transparent and a background color is not specified in the processing specification. The value must be an RGB [hexadecimal color][]. Default is `#ffffff`.
compression
: {{< new-in 0.153.5 />}}
: (`string`) The encoding strategy used for the image. Options are `lossy` or `lossless`. Note that `lossless` is only supported by the WebP format. Default is `lossy`.
`compression`
: {{< deprecated-in 0.163.0 />}}
: Use the format-specific `compression` setting instead, applicable to [AVIF](#avif) and [WebP](#webp) images.
quality
: (`int`) The visual fidelity of the image, applicable to JPEG and WebP formats when using `lossy` compression. Expressed as a whole number from `1` to `100`, inclusive. Lower numbers prioritize smaller file size, while higher numbers prioritize visual clarity. Default is `75`.
`hint`
: {{< deprecated-in 0.163.0 />}}
: Use the format-specific `hint` setting instead, applicable to [AVIF](#avif) and [WebP](#webp) images.
resampleFilter
: (`string`) The algorithm used to calculate new pixels when resizing, fitting, or filling an image. Common options include `box`, `lanczos`, `catmullRom`, `mitchellNetravali`, `linear`, or `nearestNeighbor`. Default is `box`.
`quality`
: {{< deprecated-in 0.163.0 />}}
: Use the format-specific `quality` setting instead, applicable to [AVIF](#avif), [JPEG](#jpeg), and [WebP](#webp) images.
`resampleFilter`
: (`string`) The algorithm used to calculate new pixels when resizing, fitting, or filling an image. Common case-insensitive options include `box`, `lanczos`, `catmullRom`, `mitchellNetravali`, `linear`, or `nearestNeighbor`. Default is `box`.
Filter|Description
:--|:--
@@ -41,35 +46,30 @@ resampleFilter
Refer to the [source documentation][] for a complete list of available resampling filters. If you wish to improve image quality at the expense of performance, you may wish to experiment with the alternative filters.
## Exif method
## AVIF
{{< deprecated-in 0.155.0 >}}
Use [`Meta`](/methods/resource/meta/) instead.
{{< /deprecated-in >}}
{{< new-in 0.162.0 />}}
## Meta method
These settings apply when encoding AVIF images.
{{< new-in 0.155.0 />}}
> [!NOTE]
> When exporting HDR AVIF images from Lightroom, in the Export dialog under File Settings, uncheck Maximize Compatibility to improve Hugo's AVIF decoding speed.
The following parameters allow you to control how Hugo extracts and filters metadata when using the [`Meta`][] method, helping you balance data granularity with build performance.
> [!NOTE]
> Encoding animated images to AVIF produces a single-frame (static) image. Converting an animated AVIF to another format such as GIF works as expected.
fields
: (`[]string`) A [glob slice](g) matching the fields to include when extracting metadata. If empty, a default set excluding technical metadata is used. Set&nbsp;to&nbsp;`['**']`&nbsp;to include all fields.
{{< code-toggle config=imaging.avif />}}
> [!note]
> By default, to improve performance and decrease cache size, Hugo excludes the following fields: `ColorSpace`, `Contrast`, `Exif`, `ExposureBias`, `ExposureMode`, `ExposureProgram`, `Flash`, `GPS`, `JPEG`, `Metering`, `Resolution`, `Saturation`, `Sensing`, `Sharp`, and `WhiteBalance`.
`compression`
: {{< new-in 0.163.0 />}}
: (`string`) The encoding strategy. Options are `lossy` or `lossless`. Default is `lossy`.
sources
: (`[]string`) The metadata sources to include, one or more of `exif`, `iptc`, or `xmp`. Default is `['exif', 'iptc']`. The XMP metadata is excluded by default to improve performance.
`encoderSpeed`
: (`int`) The encoder speed. Expressed as a whole number from `1` to `10`, inclusive, equivalent to the `-s` flag for the [`avifenc`][] CLI. Lower numbers reduce file size at the cost of build time. At typical web image sizes, quality is indistinguishable across settings. Values below `5` may cause significantly longer build times. Default is `10`.
## WebP images
{{< new-in 0.155.0 />}}
These specialized settings provide granular control over the WebP encoding process, allowing you to optimize compression based on the specific visual characteristics of your imagery.
hint
: (`string`) The encoding preset used when processing WebP images, equivalent to the `-preset` flag for the [`cwebp`][] CLI. Valid options include `drawing`, `icon`, `photo`, `picture`, or `text`. Default is `photo`.
`hint`
: {{< new-in 0.163.0 />}}
: (`string`) The content hint. Valid options include `drawing`, `icon`, `photo`, `picture`, or `text`. Hugo uses the `4:2:0` chroma subsampling format with `photo` and `picture`, and `4:4:4` with the remaining options. Default is `photo`.
Value|Example
:--|:--
@@ -79,12 +79,76 @@ hint
`picture`|Indoor photograph such as a portrait
`text`|Image that is primarily text
method
: (`int`) The effort level of the compression algorithm. Expressed as a whole number from `0` to `6`, inclusive, equivalent to the `-m` flag for the [`cwebp`][] CLI. Lower numbers prioritize processing speed, while higher numbers prioritize compression efficiency. Default is `2`.
`quality`
: {{< new-in 0.163.0 />}}
: (`int`) The visual fidelity when using `lossy` compression. Expressed as a whole number from `1` to `100`, inclusive. Lower numbers prioritize smaller file size, while higher numbers prioritize visual clarity. Default is `60`. Quality values are encoder-specific and not directly comparable across formats; a value of `60` for AVIF is perceptually similar to `75` for JPEG.
useSharpYuv
## JPEG
{{< new-in 0.163.0 />}}
These settings apply when encoding JPEG images.
{{< code-toggle config=imaging.jpeg />}}
`quality`
: (`int`) The visual fidelity. Expressed as a whole number from `1` to `100`, inclusive. Lower numbers prioritize smaller file size, while higher numbers prioritize visual clarity. Default is `75`.
## WebP
{{< new-in 0.155.0 />}}
These settings apply when encoding WebP images.
{{< code-toggle config=imaging.webp />}}
`compression`
: {{< new-in 0.163.0 />}}
: (`string`) The encoding strategy. Options are `lossy` or `lossless`. Default is `lossy`.
`hint`
: (`string`) The content hint, equivalent to the `-preset` flag for the [`cwebp`][] CLI. Valid options include `drawing`, `icon`, `photo`, `picture`, or `text`. Default is `photo`.
Value|Example
:--|:--
`drawing`|Hand or line drawing with high-contrast details
`icon`|Small colorful image
`photo`|Outdoor photograph with natural lighting
`picture`|Indoor photograph such as a portrait
`text`|Image that is primarily text
`method`
: (`int`) The effort level of the compression algorithm. Expressed as a whole number from `0` to `6`, inclusive, equivalent to the `-m` flag for the [`cwebp`][] CLI. Lower numbers prioritize processing speed, while higher numbers prioritize compression efficiency and image quality. Default is `2`.
`quality`
: {{< new-in 0.163.0 />}}
: (`int`) The visual fidelity when using `lossy` compression. Expressed as a whole number from `1` to `100`, inclusive. Lower numbers prioritize smaller file size, while higher numbers prioritize visual clarity. Default is `75`.
`useSharpYuv`
: (`bool`) The conversion method used for RGB-to-YUV encoding, equivalent to the `-sharp_yuv` flag for the [`cwebp`][] CLI. Enabling this prioritizes image sharpness at the expense of processing speed. Default is `false`.
## Exif method
{{< deprecated-in 0.155.0 >}}
Use the [`Meta`](#meta-method) method instead.
{{< /deprecated-in >}}
## Meta method
{{< new-in 0.155.0 />}}
The following parameters allow you to control how Hugo extracts and filters metadata when using the [`Meta`][] method, helping you balance data granularity with build performance.
`fields`
: (`[]string`) A [glob slice](g) matching the fields to include when extracting metadata. If empty, a default set excluding technical metadata is used. Set&nbsp;to&nbsp;`['**']`&nbsp;to include all fields.
> [!NOTE]
> By default, to improve performance and decrease cache size, Hugo excludes the following fields: `ColorSpace`, `Contrast`, `Exif`, `ExposureBias`, `ExposureMode`, `ExposureProgram`, `Flash`, `GPS`, `JPEG`, `Metering`, `Resolution`, `Saturation`, `Sensing`, `Sharp`, and `WhiteBalance`.
`sources`
: (`[]string`) The metadata sources to include, one or more of `exif`, `iptc`, or `xmp`. Default is `['exif', 'iptc']`. The XMP metadata is excluded by default to improve performance.
[`avifenc`]: https://github.com/aomediacodec/libavif
[`cwebp`]: https://developers.google.com/speed/webp/docs/cwebp
[`muesli/smartcrop`]: https://github.com/muesli/smartcrop
[hexadecimal color]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color
+60 -36
View File
@@ -8,7 +8,7 @@ weight: 10
## Sensible defaults
Hugo offers many configuration options, but its defaults are often sufficient. A new project requires only these settings:
Hugo offers many configuration settings, but its defaults are often sufficient. A new project requires only these settings:
{{< code-toggle file=hugo >}}
baseURL = 'https://example.org/'
@@ -18,21 +18,18 @@ title = 'My New Hugo Site'
Only define settings that deviate from the defaults. A smaller configuration file is easier to read, understand, and debug. Keep your configuration concise.
> [!note]
> [!NOTE]
> The best configuration file is a short configuration file.
## Configuration file
Create a project configuration file in the root of your project directory, naming it `hugo.toml`, `hugo.yaml`, or `hugo.json`, with that order of precedence.
```text
```tree
my-project/
└── hugo.toml
```
> [!note]
> For versions v0.109.0 and earlier, the project configuration file was named `config`. While you can still use this name, it's recommended to switch to the newer naming convention, `hugo`.
A simple example:
{{< code-toggle file=hugo >}}
@@ -58,14 +55,14 @@ Combine two or more configuration files, with left-to-right precedence:
hugo build --config a.toml,b.yaml,c.json
```
> [!note]
> See the specifications for each file format: [TOML], [YAML], and [JSON].
> [!NOTE]
> See the specifications for each file format: [TOML][], [YAML][], and [JSON][].
## Configuration directory
Instead of a single project configuration file, split your configuration by [environment](g), root configuration key, and language. For example:
```text
```tree
my-project/
└── config/
├── _default/
@@ -79,14 +76,11 @@ my-project/
The root configuration keys are {{< root-configuration-keys >}}.
> [!note]
> You must define `cascade` tables in the root configuration file. You cannot define `cascade` tables in a dedicated file. See issue [#12899] for details.
### Root key
[#12899]: https://github.com/gohugoio/hugo/issues/12899
{{< new-in 0.162.0 />}}
### Omit the root key
When splitting the configuration by root key, omit the root key in the component file. For example, these are equivalent:
When splitting the configuration by root key, you may omit or include the root key in the component file. For example, these are equivalent:
{{< code-toggle file=config/_default/hugo >}}
[params]
@@ -97,11 +91,40 @@ foo = 'bar'
foo = 'bar'
{{< /code-toggle >}}
This also applies to keys whose values are maps of slices, such as `menus`. For example, these are equivalent:
{{< code-toggle file=config/_default/menus >}}
[[main]]
name = 'Home'
pageRef = '/'
weight = 10
{{< /code-toggle >}}
{{< code-toggle file=config/_default/menus >}}
[[menus.main]]
name = 'Home'
pageRef = '/'
weight = 10
{{< /code-toggle >}}
For pure slice-typed keys such as `cascade` and `permalinks`, including the root key is required. For example:
{{< code-toggle file=config/_default/cascade >}}
[[cascade]]
[cascade.params]
color = 'red'
[cascade.target]
path = '/articles/**'
{{< /code-toggle >}}
> [!NOTE]
> Hugo unwraps the root key only when it is the sole top-level key in the file and matches the file's basename.
### Recursive parsing
Hugo parses the `config` directory recursively, allowing you to organize the files into subdirectories. For example:
```text
```tree
my-project/
└── config/
└── _default/
@@ -113,7 +136,7 @@ my-project/
### Example
```text
```tree
my-project/
└── config/
├── _default/
@@ -131,7 +154,7 @@ my-project/
Considering the structure above, when running `hugo build --environment staging`, Hugo will use every setting from `config/_default` and merge `staging`'s on top of those.
Let's take an example to understand this better. Let's say you are using Google Analytics for your website. This requires you to specify a [Google tag ID] in your project configuration:
Let's take an example to understand this better. Let's say you are using Google Analytics for your website. This requires you to specify a [Google tag ID][] in your project configuration:
{{< code-toggle file=hugo >}}
[services.googleAnalytics]
@@ -177,7 +200,7 @@ To satisfy these requirements, configure your site as follows:
Hugo merges configuration settings from themes and modules, prioritizing the project's own settings. Given this simplified project structure with two themes:
```text
```tree
project/
├── themes/
│ ├── theme-a/
@@ -206,20 +229,20 @@ The `_merge` setting within each top-level configuration key controls _which_ se
The value for `_merge` can be one of:
none
`none`
: No merge.
shallow
`shallow`
: Only add values for new keys.
deep
`deep`
: Add values for new keys, merge existing.
Note that you don't need to be so verbose as in the default setup below; a `_merge` value higher up will be inherited if not set.
{{< code-toggle file=hugo dataKey="config_helpers.mergeStrategy" skipHeader=true />}}
> [!note]
> [!NOTE]
> Hugo can merge map configuration values from modules and themes into the project configuration, but cannot merge slice values. This applies to top-level slice keys such as `menus`, as well as to map keys whose values are slices, such as the per-kind format lists in `outputs`.
## Environment variables
@@ -229,36 +252,38 @@ You can also configure settings using operating system environment variables:
```sh
export HUGO_BASEURL=https://example.org/
export HUGO_ENABLEGITINFO=true
export HUGO_ENVIRONMENT=staging
hugo
```
The above sets the [`baseURL`], [`enableGitInfo`], and [`environment`] configuration options and then builds your site.
The above configures the [`baseURL`][] and [`enableGitInfo`][] settings and then builds your site.
> [!note]
> [!NOTE]
> An environment variable takes precedence over the values set in the configuration file. This means that if you set a configuration value with both an environment variable and in the configuration file, the value in the environment variable will be used.
Environment variables simplify configuration for [CI/CD](g) platforms by allowing you to set values directly within their respective configuration and workflow files.
> [!note]
> [!NOTE]
> Environment variable names must be prefixed with `HUGO_`.
>
> To set custom site parameters, prefix the name with `HUGO_PARAMS_`.
For snake_case variable names, the standard `HUGO_` prefix won't work. Hugo infers the delimiter from the first character following `HUGO`. This allows for variations like `HUGOxPARAMSxAPI_KEY=abcdefgh` using any [permitted delimiter].
For snake_case variable names, the standard `HUGO_` prefix won't work. Hugo infers the delimiter from the first character following `HUGO`. This allows for variations like `HUGOxPARAMSxAPI_KEY=abcdefgh` using any [permitted delimiter][].
In addition to configuring standard settings, environment variables may be used to override default values for certain internal settings:
DART_SASS_BINARY
`DART_SASS_BINARY`
: (`string`) The absolute path to the Dart Sass executable. By default, Hugo searches for the executable in each of the paths in the `PATH` environment variable.
HUGO_FILE_LOG_FORMAT
`HUGO_ENVIRONMENT`
: (`string`) The build environment. Default is `production` when running `hugo build` and `development` when running `hugo server`.
`HUGO_FILE_LOG_FORMAT`
: (`string`) A format string for the file path, line number, and column number displayed when reporting errors, or when calling the `Position` method from a shortcode or Markdown render hook. Valid tokens are `:file`, `:line`, and `:col`. Default is `:file::line::col`.
HUGO_MEMORYLIMIT
`HUGO_MEMORYLIMIT`
: (`int`) The maximum amount of system memory, in gigabytes, that Hugo can use while rendering your site. Default is 25% of total system memory. Note that `HUGO_MEMORYLIMIT` is a "best effort" setting. Don't expect Hugo to build a million pages with only 1 GB of memory. You can get more information about how this behaves during the build by running `hugo build --logLevel info` and look for the `dynacache` label.
HUGO_NUMWORKERMULTIPLIER
`HUGO_NUMWORKERMULTIPLIER`
: (`int`) The number of workers used in parallel processing. Default is the number of logical CPUs.
## Current configuration
@@ -281,11 +306,10 @@ Display the configured file mounts with:
hugo config mounts
```
[`baseURL`]: /configuration/all#baseurl
[`enableGitInfo`]: /configuration/all#enablegitinfo
[`environment`]: /configuration/all#environment
[Google tag ID]: https://support.google.com/tagmanager/answer/12326985?hl=en
[JSON]: https://datatracker.ietf.org/doc/html/rfc7159
[permitted delimiter]: https://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html
[TOML]: https://toml.io/en/latest
[YAML]: https://yaml.org/spec/
[`baseURL`]: /configuration/all#baseurl
[`enableGitInfo`]: /configuration/all#enablegitinfo
[permitted delimiter]: https://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html

Some files were not shown because too many files have changed in this diff Show More