Compare commits

...

210 Commits

Author SHA1 Message Date
hugoreleaser 06bc2c16c0 releaser: Bump versions for release of 0.152.0
[ci skip]
2025-10-21 16:29:49 +00:00
Bjørn Erik Pedersen d51adca26a Merge branch 'release-0.151.2' 2025-10-21 16:08:23 +02:00
Bjørn Erik Pedersen a1307700dd config: Clone language map entries before modifying them
Now, with YAML anchor and alias support, these can point to shared data,
which must not be modified in place.

Fixes #14072
2025-10-21 13:34:15 +02:00
Bjørn Erik Pedersen 9425b939c6 Skip flaky test for now
See #14072
2025-10-21 10:32:52 +02:00
Bjørn Erik Pedersen bd50c9c7e7 Misc YAML adjustments
Closes #14067
2025-10-20 16:05:05 +02:00
Bjørn Erik Pedersen a8e0ca9254 hugofs: Make sure that non-project module mounts are local paths
Fixes #14069
2025-10-19 20:27:10 +02:00
Joe Mooring 559a029de7 langs/i18n: Improve reserved key error message
Closes #14061
2025-10-19 13:47:04 +02:00
Bjørn Erik Pedersen 184b10ed45 deps: Upgrade github.com/gohugoio/go-i18n/v2
Gets the fork line with https://github.com/nicksnyder/go-i18n/commit/28dedbee2baafdef1b89b46fc5b729d09232e245 + patch.
2025-10-18 18:21:14 +02:00
Bjørn Erik Pedersen 5bad0d523e langs: Add test case using a "reserved" i18n code
See #14061
2025-10-18 15:28:33 +02:00
Bjørn Erik Pedersen a3d9548469 Replace to gopkg.in/yaml with github.com/goccy/go-yaml (note)
This commit also adds validation to prevent the "Billion Laughs" attack (see https://github.com/goccy/go-yaml/issues/461). The limit of non-scalar aliases to the same node is set to 10,000. See benchmarks below.

```                                                            │        sec/op         │
UnmarshalBillionLaughs/Billion_Laughs_no_validation-10                 125.2µ ± ∞ ¹
UnmarshalBillionLaughs/Billion_Laughs_with_validation-10               655.8µ ± ∞ ¹
UnmarshalBillionLaughs/YAML_Front_Matter_no_validation-10              9.223µ ± ∞ ¹
UnmarshalBillionLaughs/YAML_Front_Matter_with_validation-10            9.443µ ± ∞ ¹
geomean                                                                51.71µ
¹ need >= 6 samples for confidence interval at level 0.95

                                                            │ fix-goyaml-8822.bench │
                                                            │         B/op          │
UnmarshalBillionLaughs/Billion_Laughs_no_validation-10                177.0Ki ± ∞ ¹
UnmarshalBillionLaughs/Billion_Laughs_with_validation-10              177.0Ki ± ∞ ¹
UnmarshalBillionLaughs/YAML_Front_Matter_no_validation-10             11.67Ki ± ∞ ¹
UnmarshalBillionLaughs/YAML_Front_Matter_with_validation-10           11.67Ki ± ∞ ¹
geomean                                                               45.45Ki
¹ need >= 6 samples for confidence interval at level 0.95

                                                            │ fix-goyaml-8822.bench │
                                                            │       allocs/op       │
UnmarshalBillionLaughs/Billion_Laughs_no_validation-10                 3.302k ± ∞ ¹
UnmarshalBillionLaughs/Billion_Laughs_with_validation-10               3.305k ± ∞ ¹
UnmarshalBillionLaughs/YAML_Front_Matter_no_validation-10               253.0 ± ∞ ¹
UnmarshalBillionLaughs/YAML_Front_Matter_with_validation-10             253.0 ± ∞ ¹
````

Fixes #8822
Fixes #13043
Fixes #14053
Fixes ##8427
2025-10-18 13:52:22 +02:00
dependabot[bot] 9e344bbe49 build(deps): bump github.com/tdewolff/minify/v2 from 2.24.3 to 2.24.4
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.24.3 to 2.24.4.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.24.3...v2.24.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-17 18:44:56 +02:00
hugoreleaser 1ec0e2ebec releaser: Prepare repository for 0.152.0-DEV
[ci skip]
2025-10-16 17:06:05 +00:00
hugoreleaser a3574f6f70 releaser: Bump versions for release of 0.151.2
[ci skip]
2025-10-16 16:52:34 +00:00
Bjørn Erik Pedersen 989454a52d parser/pageparser: Add a testcase for nested shortcodes of the same name
See #14054
2025-10-16 18:50:02 +02:00
Bjørn Erik Pedersen 1e91e46520 parser/pageparser: Fix shortcode nesting regression
This reverts commit a133393eda.

While that commit fixed a bug, it introduced a worse one.

Closes #14054
2025-10-16 18:50:02 +02:00
Bjørn Erik Pedersen 8a57d0f15f testscripts: Add and improve commands tests for static mounts 2025-10-16 12:39:11 +02:00
hugoreleaser b76c50ac18 releaser: Prepare repository for 0.152.0-DEV
[ci skip]
2025-10-15 15:06:42 +00:00
hugoreleaser 1cdd17882c releaser: Bump versions for release of 0.151.1
[ci skip]
2025-10-15 14:51:34 +00:00
Bjørn Erik Pedersen e2fb0b0e80 Upgrade Go to 1.25.3
See https://go.dev/doc/devel/release#go1.25.3
2025-10-15 13:00:33 +02:00
Kazuo Oishi 88aea56683 tpl: Fix strings/truncate CJK handling
Fix truncate position for mix of CJK and non-CJK text.

Fixes #14039
2025-10-15 13:00:10 +02:00
dependabot[bot] f4c11571bb build(deps): bump github.com/gohugoio/hashstructure from 0.5.0 to 0.6.0
Bumps [github.com/gohugoio/hashstructure](https://github.com/gohugoio/hashstructure) from 0.5.0 to 0.6.0.
- [Release notes](https://github.com/gohugoio/hashstructure/releases)
- [Commits](https://github.com/gohugoio/hashstructure/compare/v0.5.0...v0.6.0)

---
updated-dependencies:
- dependency-name: github.com/gohugoio/hashstructure
  dependency-version: 0.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-15 11:00:35 +02:00
dependabot[bot] 54075acc29 build(deps): bump golang.org/x/image from 0.30.0 to 0.32.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.30.0 to 0.32.0.
- [Commits](https://github.com/golang/image/compare/v0.30.0...v0.32.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-15 10:59:28 +02:00
dependabot[bot] 8b52303e31 build(deps): bump github.com/evanw/esbuild from 0.25.10 to 0.25.11
Bumps [github.com/evanw/esbuild](https://github.com/evanw/esbuild) from 0.25.10 to 0.25.11.
- [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.25.10...v0.25.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-15 10:57:33 +02:00
dependabot[bot] 3d45d30a41 build(deps): bump golang.org/x/tools from 0.37.0 to 0.38.0
Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.37.0 to 0.38.0.
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.37.0...v0.38.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-14 22:10:08 +02:00
dependabot[bot] 095157cd65 build(deps): bump golang.org/x/mod from 0.28.0 to 0.29.0
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.28.0 to 0.29.0.
- [Commits](https://github.com/golang/mod/compare/v0.28.0...v0.29.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-14 16:34:43 +02:00
Sardorbek Imomaliev 29cf87444f create/skeletons: Wrap section and home lists with section tags
Avoiding issues with tag leakage when using .Summary
See issue #14044 for details.
2025-10-14 11:54:45 +02:00
Joe Mooring 1b4dd436dd markup/goldmark: Align blockquote default output with Goldmark
Closes #14046
2025-10-14 09:38:29 +02:00
Bjørn Erik Pedersen 4414ef73f3 parser/pageparser: Store shortcode names as unique.Handle[string] to save memory allocations
```
                        │ stash.bench  │        perf-pagelexer.bench        │
                        │    sec/op    │    sec/op     vs base              │
ShortcodeLexer-10         68.87µ ± ∞ ¹   65.91µ ± ∞ ¹       ~ (p=0.200 n=4)
Parse-10                  7.421µ ± ∞ ¹   7.030µ ± ∞ ¹  -5.28% (p=0.029 n=4)
HasShortcode/Match-10     70.42n ± ∞ ¹   77.37n ± ∞ ¹  +9.86% (p=0.029 n=4)
HasShortcode/NoMatch-10   14.32n ± ∞ ¹   14.38n ± ∞ ¹       ~ (p=0.086 n=4)
geomean                   847.2n         847.3n        +0.01%
¹ need >= 6 samples for confidence interval at level 0.95

                        │  stash.bench  │         perf-pagelexer.bench          │
                        │     B/op      │     B/op       vs base                │
ShortcodeLexer-10         181.3Ki ± ∞ ¹   177.4Ki ± ∞ ¹  -2.19% (p=0.029 n=4)
Parse-10                  24.56Ki ± ∞ ¹   24.19Ki ± ∞ ¹  -1.53% (p=0.029 n=4)
HasShortcode/Match-10       0.000 ± ∞ ¹     0.000 ± ∞ ¹       ~ (p=1.000 n=4) ²
HasShortcode/NoMatch-10     0.000 ± ∞ ¹     0.000 ± ∞ ¹       ~ (p=1.000 n=4) ²
geomean                               ³                  -0.93%               ³
¹ need >= 6 samples for confidence interval at level 0.95
² all samples are equal
³ summaries must be >0 to compute geomean

                        │ stash.bench  │         perf-pagelexer.bench         │
                        │  allocs/op   │  allocs/op   vs base                 │
ShortcodeLexer-10         1004.0 ± ∞ ¹   921.0 ± ∞ ¹   -8.27% (p=0.029 n=4)
Parse-10                   34.00 ± ∞ ¹   14.00 ± ∞ ¹  -58.82% (p=0.029 n=4)
HasShortcode/Match-10      0.000 ± ∞ ¹   0.000 ± ∞ ¹        ~ (p=1.000 n=4) ²
HasShortcode/NoMatch-10    0.000 ± ∞ ¹   0.000 ± ∞ ¹        ~ (p=1.000 n=4) ²
```
2025-10-05 19:06:46 +02:00
Bjørn Erik Pedersen a133393eda parser/pagerparser: Fix closing shortcode error handling when repeated 2025-10-05 19:06:46 +02:00
Bjørn Erik Pedersen 9197debbfe testscripts: Make test assertion less specific 2025-10-05 18:08:52 +02:00
hugoreleaser c29897fac0 releaser: Prepare repository for 0.152.0-DEV
[ci skip]
2025-10-02 13:45:36 +00:00
hugoreleaser c70ab27ceb releaser: Bump versions for release of 0.151.0
[ci skip]
2025-10-02 13:30:36 +00:00
Bjørn Erik Pedersen 510d98b778 Adjust the terminal progress reporter a little
Mostly to reduce the amount of OSC 9;4 sequences written to stdout.
2025-10-02 14:57:42 +02:00
Andrii Chubatiuk 7fd6762c16 transform/livereloadinject: Skip livereload.js injection if no tags found (note)
This change is mainly motivated to support sites built by HTML fragments with e.g. a JS framework.

Now we don't inject the script if we don't find any of `doctype` (the only one required by the HTML 5 spec), `html` or `head`.

Co-authored-by: bep <bjorn.erik.pedersen@gmail.com>
2025-10-02 13:39:35 +02:00
dependabot[bot] 584f052f39 build(deps): bump google.golang.org/api from 0.248.0 to 0.251.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.248.0 to 0.251.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.248.0...v0.251.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-version: 0.251.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 23:05:48 +02:00
dependabot[bot] b76d71761e build(deps): bump github.com/aws/aws-sdk-go-v2/service/cloudfront
Bumps [github.com/aws/aws-sdk-go-v2/service/cloudfront](https://github.com/aws/aws-sdk-go-v2) from 1.53.0 to 1.54.4.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/s3/v1.53.0...service/s3/v1.54.4)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/cloudfront
  dependency-version: 1.54.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 23:05:36 +02:00
Bjørn Erik Pedersen c5dca3bdee Add transform.HTMLToMarkdown
Fixes #13946
2025-10-01 19:17:26 +02:00
Bjørn Erik Pedersen ec463c0977 Report OSC 9;4 progress when building
As supported by the Ghostty terminal and others.
2025-10-01 14:27:23 +02:00
dependabot[bot] 4d2743e4c8 build(deps): bump github.com/aws/aws-sdk-go-v2 from 1.38.1 to 1.39.2
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.38.1 to 1.39.2.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.38.1...v1.39.2)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-version: 1.39.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-30 21:13:50 +02:00
dependabot[bot] c20f70d9a3 build(deps): bump golang.org/x/tools from 0.36.0 to 0.37.0
Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.36.0 to 0.37.0.
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.36.0...v0.37.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-30 21:11:37 +02:00
dependabot[bot] 1b556216a8 build(deps): bump github.com/spf13/afero from 1.14.0 to 1.15.0
Bumps [github.com/spf13/afero](https://github.com/spf13/afero) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/spf13/afero/releases)
- [Commits](https://github.com/spf13/afero/compare/v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/afero
  dependency-version: 1.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-30 21:11:14 +02:00
dependabot[bot] 106c8e6de6 build(deps): bump github.com/tdewolff/minify/v2 from 2.24.2 to 2.24.3
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.24.2 to 2.24.3.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.24.2...v2.24.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-30 21:10:54 +02:00
Bjørn Erik Pedersen 03b33ecb5e Fix file caching for 404 responses in resources.GetRemote
Fixes #14019
2025-09-30 20:43:05 +02:00
dependabot[bot] 9928122eb8 build(deps): bump github.com/evanw/esbuild from 0.25.9 to 0.25.10
Bumps [github.com/evanw/esbuild](https://github.com/evanw/esbuild) from 0.25.9 to 0.25.10.
- [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.25.9...v0.25.10)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-30 17:43:39 +02:00
Dr. Tobias Quathamer 105d3bc32f tpl: Workaround s390x precision of Atan and Tan
On s390x, math.Atan(1) and math.Tan(1) give values that slightly differ
from other architectures, causing TestTemplateFuncsExamples to fail.

The golang math package states in the overview:
"This package does not guarantee bit-identical results across architectures."
2025-09-29 17:09:29 +02:00
Bjørn Erik Pedersen 3e46ba5ce2 cache/httpcache: Add respectCacheControlNoStoreInResponse and respectCacheControlNoStoreInRequest options
This cache is used by `resources.GetRemote`.

Default values are:

* respectCacheControlNoStoreInResponse: false
* respectCacheControlNoStoreInRequest: true

This is a slightly breaking change, but the current behaviour is confusing, as:

* Many servers set the `no-store` header without much consideration, see https://developer.chrome.com/docs/web-platform/bfcache-ccns for more context
* We almost always want to cache the `resources.GetRemote` to disk.

Fixes #13990
2025-09-29 17:06:50 +02:00
Bjørn Erik Pedersen 4d1303512b common/hreflect: Speed up IsTrutfulValue
By caching the calculation of whether a type implements `IsZero`:

```
IsTruthFulVAlue-10    467.95n ± ∞ ¹   79.13n ± ∞ ¹  -83.09% (p=0.029 n=4)
```
2025-09-29 17:06:50 +02:00
dependabot[bot] 9943c1bef0 build(deps): bump golang.org/x/text from 0.28.0 to 0.29.0
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.28.0 to 0.29.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.28.0...v0.29.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-29 15:09:06 +02:00
dependabot[bot] 766757310a build(deps): bump github.com/olekukonko/tablewriter from 1.0.9 to 1.1.0
Bumps [github.com/olekukonko/tablewriter](https://github.com/olekukonko/tablewriter) from 1.0.9 to 1.1.0.
- [Commits](https://github.com/olekukonko/tablewriter/compare/v1.0.9...v1.1.0)

---
updated-dependencies:
- dependency-name: github.com/olekukonko/tablewriter
  dependency-version: 1.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-29 15:08:34 +02:00
dependabot[bot] d71c07cf3c build(deps): bump github.com/spf13/cast from 1.9.2 to 1.10.0
Bumps [github.com/spf13/cast](https://github.com/spf13/cast) from 1.9.2 to 1.10.0.
- [Release notes](https://github.com/spf13/cast/releases)
- [Commits](https://github.com/spf13/cast/compare/v1.9.2...v1.10.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cast
  dependency-version: 1.10.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-29 15:07:36 +02:00
Joe Mooring b462980ac2 markup/goldmark: Enhance footnote extension with backlinkHTML option
This commit introduces a new option, backlinkHTML, to the Goldmark
footnote extension. This allows users to the set custom text for
footnote backlink anchors.

Closes #11434
2025-09-29 12:21:17 +02:00
Joe Mooring 47678d8cbd markup/goldmark: Enhance footnote extension with auto-prefixing option
This commit introduces a new option, enableAutoIDPrefix, to the Goldmark
footnote extension. When enabled, it prepends a unique prefix to
footnote IDs, preventing clashes when multiple documents are rendered
together. This prefix is unique to each logical path, which means that
the prefix is not unique across content dimensions such as language.
This change also refactors the extension's configuration from a boolean
to a struct.

Closes #8045
2025-09-27 18:16:42 +02:00
hugoreleaser 18b9b6488b releaser: Prepare repository for 0.151.0-DEV
[ci skip]
2025-09-25 10:45:05 +00:00
hugoreleaser ce44a8e835 releaser: Bump versions for release of 0.150.1
[ci skip]
2025-09-25 10:26:04 +00:00
Joe Mooring 64f40731f1 hugolib: Change duplicate content path warning to an info log
Improves #13993
2025-09-20 20:13:08 +02:00
Joe Mooring 1140314be1 hugolib: Restore integration test
Closes #13991
2025-09-18 18:02:13 +02:00
Joe Mooring 404fd9e512 commands: Map --minify CLI flag to the correct configuration key
Closes #13988
2025-09-18 16:50:47 +02:00
Max Kapur b1b0cdee3a snap: Add desktop plug 2025-09-18 06:22:39 -07:00
Max Kapur 3eea082903 test(deps): Update setup-ruby action to v1.257.0 2025-09-17 09:30:21 -07:00
hugoreleaser 0f18cbe990 releaser: Prepare repository for 0.151.0-DEV
[ci skip]
2025-09-08 13:16:24 +00:00
hugoreleaser 3f5473b7d4 releaser: Bump versions for release of 0.150.0
[ci skip]
2025-09-08 13:01:12 +00:00
dependabot[bot] d1f6a1dc59 build(deps): bump golang.org/x/mod from 0.27.0 to 0.28.0
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.27.0 to 0.28.0.
- [Commits](https://github.com/golang/mod/compare/v0.27.0...v0.28.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 11:23:39 +02:00
Bjørn Erik Pedersen 747cf4ad65 modules: Add support for direct version module imports in hugo.toml
Fixes #13964
2025-09-07 22:47:25 +02:00
Joe Mooring d8774d7fc3 resources/page: Fix truncated summary logic
Fixes #13967
Fixes #13968
2025-09-07 11:07:41 +02:00
Joe Mooring 3b8947d821 config/security: Add PROGRAMDATA to the osenv allowlist 2025-09-06 18:11:38 +02:00
hugoreleaser 321a66ef19 releaser: Prepare repository for 0.150.0-DEV
[ci skip]
2025-09-04 14:18:57 +00:00
hugoreleaser 57a784e027 releaser: Bump versions for release of 0.149.1
[ci skip]
2025-09-04 14:04:46 +00:00
Lukáš Zapletal 25c0f2408a Remove noindex meta tag from alias.html
Google does not behave as expected when an alias is used. It does not index the client-side alias page, but on top of that it also does not index the original page.

Google does not require noindex to be present and since alias pages do not have any content, it makes little sense to provide it. Therefore, this patch removes the line completely.

https://developers.google.com/search/docs/crawling-indexing/301-redirects
2025-09-04 15:58:23 +02:00
Bjørn Erik Pedersen 4f2d2b2cc4 Fix nilpointer on ToC heading
Fixes #11843

Co-authored-by: Joe Mooring <joe.mooring@veriphor.com>
2025-09-04 14:01:51 +02:00
Bjørn Erik Pedersen b8eb45c9df tpl/collections: Require collections.D args to be ints
Fixes #13952

Co-authored-by: Joe Mooring <joe.mooring@veriphor.com>
2025-09-04 14:01:51 +02:00
Bjørn Erik Pedersen 1d90afff1b Upgrade to Go 1.25.1
Fixes #13960
2025-09-04 11:11:29 +02:00
PikachuTW e751afa9bd Fix config env handling for some slice options
Fixes #13950
2025-09-04 10:49:14 +02:00
Joe Mooring a09b8a60eb minifiers: Update deprecation handling
1. With minify.tdewolff.css and minify.tdewolff.svg, check
   for "decimals" instead of "decimal"

2. Add deprecation messages for:

  - minify.tdewolff.css.decimals
  - minify.tdewolff.svg.decimals
  - minify.tdewolff.html.keepconditionalcomments
  - config root minify (bool)
  - config root minifyoutput (bool)

3. Deprecate minify.tdewolff.css.keepcss2 in favor
   of minify.tdewolff.css.version

4. Refactor minify configuration tests

Closes #11893
Closes #13947
Closes #13948
2025-09-03 10:56:32 +02:00
Bjørn Erik Pedersen 0071b47b8b Update README.md 2025-09-01 17:11:08 +02:00
hugoreleaser 70d62993ee releaser: Prepare repository for 0.150.0-DEV
[ci skip]
2025-08-27 15:51:44 +00:00
hugoreleaser 66240338f1 releaser: Bump versions for release of 0.149.0
[ci skip]
2025-08-27 15:37:16 +00:00
Bjørn Erik Pedersen 84b5123912 tpl/collections: Add an integration test for collections.D
Also
* improve the handling if invalid input
* add a sanity check for number of elements asked for in D (1000000).
2025-08-27 17:25:05 +02:00
Joe Mooring 2912415955 misc: Update Go version to 1.24.0 in README
Update Go version requirements for building Hugo.
2025-08-27 16:46:38 +02:00
Justus Perlwitz bb4e66cd7c create: Fix new content command with future dates
Fixes #12599
2025-08-27 09:33:17 +02:00
dependabot[bot] 45ec2f88bb build(deps): bump github.com/getkin/kin-openapi from 0.132.0 to 0.133.0
Bumps [github.com/getkin/kin-openapi](https://github.com/getkin/kin-openapi) from 0.132.0 to 0.133.0.
- [Release notes](https://github.com/getkin/kin-openapi/releases)
- [Commits](https://github.com/getkin/kin-openapi/compare/v0.132.0...v0.133.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-27 09:31:02 +02:00
Bjørn Erik Pedersen 1ba80874e4 tpl/collections: Add collections.D using Vitter's Method D for sequential random sampling 2025-08-26 20:37:08 +02:00
dependabot[bot] 84dd495f2b build(deps): bump google.golang.org/api from 0.247.0 to 0.248.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.247.0 to 0.248.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.247.0...v0.248.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-version: 0.248.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-26 09:54:26 +02:00
dependabot[bot] 327bbc613f build(deps): bump github.com/evanw/esbuild from 0.25.6 to 0.25.9
Bumps [github.com/evanw/esbuild](https://github.com/evanw/esbuild) from 0.25.6 to 0.25.9.
- [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.25.6...v0.25.9)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-26 09:54:07 +02:00
dependabot[bot] 2447138f1d build(deps): bump gocloud.dev from 0.40.0 to 0.43.0
Bumps [gocloud.dev](https://github.com/google/go-cloud) from 0.40.0 to 0.43.0.
- [Release notes](https://github.com/google/go-cloud/releases)
- [Commits](https://github.com/google/go-cloud/compare/v0.40.0...v0.43.0)

---
updated-dependencies:
- dependency-name: gocloud.dev
  dependency-version: 0.43.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-25 20:47:05 +02:00
Bjørn Erik Pedersen 61ec7a20a5 commands: Deprecate --omitEmpty on chromastyles command
It's no longer needed -- empty classes are now always omitted.

See  See https://github.com/alecthomas/chroma/commit/5b2a4c5a26c503c79bc86ba3c4ae5b330028bd3d
2025-08-25 18:24:07 +02:00
Bjørn Erik Pedersen c289fcaaaa commands: Add --omitClassComments to the chromastyles command 2025-08-25 18:24:07 +02:00
Bjørn Erik Pedersen cfc38ecfed deps: Upgrade github.com/alecthomas/chroma/v2 v2.19.0 => v2.20.0
CLoses #13917
2025-08-25 18:24:07 +02:00
dependabot[bot] 22e579e050 build(deps): bump github.com/aws/aws-sdk-go-v2/service/cloudfront
Bumps [github.com/aws/aws-sdk-go-v2/service/cloudfront](https://github.com/aws/aws-sdk-go-v2) from 1.44.10 to 1.53.0.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/service/macie2/v1.44.10...service/s3/v1.53.0)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2/service/cloudfront
  dependency-version: 1.53.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-25 15:32:19 +02:00
dependabot[bot] b886615d1b build(deps): bump github.com/tdewolff/minify/v2 from 2.23.11 to 2.24.0
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.23.11 to 2.24.0.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.23.11...v2.24.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-25 15:29:50 +02:00
minxinyi ecdef2be70 all: Use slices.Equal 2025-08-24 20:35:18 +02:00
Bjørn Erik Pedersen ff3ae62933 Merge commit 'bfa74537929f409fca841540b971125b7678963a' 2025-08-23 12:39:28 +02:00
Bjørn Erik Pedersen bfa7453792 Squashed 'docs/' changes from 60dd993a6..71f739460
71f739460 content: Reformat procedures to use description lists instead of H3 elements
420a78802 content: Remove 21YunBox hosting guide
abeea342f content: Add hosting guide for Vercel
3aaca6c0a content: Add hosting guide for Render
d77b06aa6 content: Fix formatting
82885415f content: Change build.sh file perms in Cloudflare hosting docs
0569c68ca content: Fix typo
8f14be5da content: Remove duplicate list items
e76f17815 misc: Fix typo in configuration for the Markdown linter
32e450b7c misc: Fix typo in configuration for the Markdown linter
81bd0056a mics: Update configuration for the Markdown linter
480ae9014 content: Improve file names in the PageInner description
b17999021 content: Adjust Markdown to pass linter tests
1d9d56897 misc: Implement Markdown linter
91fc34c58 content: Miscellaneous edits
b7c60ae0b content: Add admonition for outdated learning resources
51b6df588 misc: Activate stale action
84a897f5f misc: Implement stale action
167ea9713 content: Update GitHub Pages workflow example
3672d9116 misc: Use actions/checkout@v5 in workflows
2f2b4c968 misc: Update spellcheck configs
55a8ff7ae content: Fix typo
36e3d7b7b Adjust sponsors
51014e6b9 content: Fix link
37cfc093f content: Add Cloudflare Worker hosting instructions
09862ffad content: Update hosting considerations related to GitInfo
477f3e7c0 misc: Update cspell config
7a7bb4874 content: Miscellaneous edits
48486d5ac content: Remove Cloudflare Pages documentation
382f8052d content: Remove KeyCDN documentation
8ecbc985c content: Update hosting workflow files
57fd362bf content: Clarify applicability of the slug front matter field
0dcfff9c7 content: Update directory-structure.md
58e3609a0 content: Fix typo
22fb43695 content: Fix search/replace errors
fba8342a8 content: Fix missing link refs
97e035006 Update netlify.toml
6ab5ae6df content: Improve GitLab Pages compression performance
172bfbc4b content: Differentiate content view templates from other templates
978770fc8 content: Clarify handling of goldmark extensions conflict
cb74aa4c7 content: Improve Codeberg Pages hosting instructions
794477792 content: Add custom domain instructions to Codeberg Pages setup
235fac27d content: Improve description of code block render hook options map
35a507d31 content: Improve WP2Hugo description
8191f4dcf content: Improve WP2Hugo description
25cca30fd content: Fix type
e955652ae content: Improve base template description
922aa91bd content: Improve description of partial lookup logic
072536ef6 content: Update template type documentation
5bf153531 Update netlify.toml
cdd20a433 content: Indicate language sort order for relevant page methods
fc9a868c9 content: Add Sitepins to list of commercial CMS platforms
b6077449c content: Update version references
b71388cac content: Fix typo
c27dfdef3 content: Move link reference
d008ea6ac content: Fix typo
040f14a3c content: Fix typo
1ac119d26 content: Fix typo
a5a4fa907 content: More updates for v0.148.0
b7247a8ea content: Remove command chaining from GitHub Actions workflow
6ecb96bcd content: Updates for v0.148.0
aea9e4c29 netlify: Update Hugo version
4e71546d1 Add Ancestors (plural) method to GitInfo, rename Ancestor field to Parent
68620a6c2 source: Expose Ancestor in GitInfo

git-subtree-dir: docs
git-subtree-split: 71f739460f
2025-08-23 12:36:13 +02:00
Dustin Fischer 12ace3ad5c resources/page: Add :sectionslug and :sectionslugs permalink tokens
Add slugified section permalink tokens with fallback behavior and slice syntax support.

Fixes #13788
2025-08-23 12:35:21 +02:00
Bjørn Erik Pedersen c14fdddada Upgrade to Go 1.25
Fixes #13924
Fixes #13931
2025-08-22 18:17:10 +02:00
Bjørn Erik Pedersen 186934feb4 common/hcontext: Replace with external package 2025-08-22 09:13:46 +02:00
Bjørn Erik Pedersen 13b43e6117 Fix server rebuild when adding a new leaf bundle with resources in one go
E.g. `cp -r`.

Note that this was not an issue if you first created the bundle, waited, and then created the resource(s).

Fixes #13925
2025-08-21 21:52:31 +02:00
cui bff4dddb12 resources/page: Use reflect.TypeFor 2025-08-20 13:20:14 +02:00
dependabot[bot] 885cd299b7 build(deps): bump github.com/tdewolff/minify/v2 from 2.23.8 to 2.23.11
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.23.8 to 2.23.11.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.23.8...v2.23.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 11:42:54 +02:00
Bjørn Erik Pedersen 80e973ea5c Remove test with deprecated path usage
This now creates a warning and flaky CI tests.
2025-08-20 11:36:10 +02:00
dependabot[bot] debf3c559a build(deps): bump github.com/olekukonko/tablewriter from 1.0.8 to 1.0.9
Bumps [github.com/olekukonko/tablewriter](https://github.com/olekukonko/tablewriter) from 1.0.8 to 1.0.9.
- [Commits](https://github.com/olekukonko/tablewriter/compare/v1.0.8...v1.0.9)

---
updated-dependencies:
- dependency-name: github.com/olekukonko/tablewriter
  dependency-version: 1.0.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 11:29:31 +02:00
Bjørn Erik Pedersen 01b0eda96c Update README.md 2025-08-16 10:51:26 +02:00
Bjørn Erik Pedersen 87e100e61f Fix rebuild when deleting a content adapter file 2025-08-15 17:32:42 +02:00
dependabot[bot] 1649f3126f build(deps): bump google.golang.org/api from 0.237.0 to 0.247.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.237.0 to 0.247.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.237.0...v0.247.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-version: 0.247.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-15 15:26:53 +02:00
dependabot[bot] ccd6a4b71e build(deps): bump github.com/aws/aws-sdk-go-v2 from 1.36.4 to 1.38.0
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.36.4 to 1.38.0.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.36.4...v1.38.0)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-version: 1.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-15 14:51:29 +02:00
dependabot[bot] 6dc1a1752b build(deps): bump golang.org/x/tools from 0.35.0 to 0.36.0
Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.35.0 to 0.36.0.
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.35.0...v0.36.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-15 14:02:06 +02:00
dependabot[bot] 806d4848c3 build(deps): bump github.com/bep/simplecobra from 0.6.0 to 0.6.1
Bumps [github.com/bep/simplecobra](https://github.com/bep/simplecobra) from 0.6.0 to 0.6.1.
- [Release notes](https://github.com/bep/simplecobra/releases)
- [Commits](https://github.com/bep/simplecobra/compare/v0.6.0...v0.6.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-15 14:01:33 +02:00
Nigel van Keulen 348aae91e8 tpl/strings: Remove unnecessary error check 2025-08-15 13:43:16 +02:00
Joe Mooring 61482cfab6 markup/goldmark: Apply Hugo Goldmark Extras when rendering TOC
Closes #12605
2025-08-14 22:39:14 +02:00
dependabot[bot] 04ee1b9784 build(deps): bump golang.org/x/mod from 0.25.0 to 0.27.0
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.25.0 to 0.27.0.
- [Commits](https://github.com/golang/mod/compare/v0.25.0...v0.27.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 11:29:34 +02:00
dependabot[bot] 7a86fe9905 build(deps): bump github.com/yuin/goldmark from 1.7.12 to 1.7.13
Bumps [github.com/yuin/goldmark](https://github.com/yuin/goldmark) from 1.7.12 to 1.7.13.
- [Release notes](https://github.com/yuin/goldmark/releases)
- [Commits](https://github.com/yuin/goldmark/compare/v1.7.12...v1.7.13)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 11:28:53 +02:00
Joe Mooring 5fdcc09062 markup/goldmark: Sanitize TOC heading titles
Fixes #13401
2025-08-13 11:23:30 +02:00
dependabot[bot] f5245a7d5f build(deps): bump golang.org/x/image from 0.28.0 to 0.30.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.28.0 to 0.30.0.
- [Commits](https://github.com/golang/image/compare/v0.28.0...v0.30.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-12 14:46:29 +02:00
Joe Mooring 5029676aca deps: Upgrade github.com/niklasfasching/go-org v1.8.0 => v1.9.1
Fixes #13846
2025-08-11 10:54:00 +02:00
n1xx1 2216028620 Add a key to the partialCached deadlock prevention
Fixes #13889
2025-08-07 11:17:14 +02:00
n1xx1 ecc3dd1f53 transform: Add support for "format" option in transform.Unmarshal
Fixes #13887
2025-08-05 22:19:51 +02:00
Bjørn Erik Pedersen de4a7f1e04 Skip flakey test on CI 2025-08-05 19:45:46 +02:00
hugoreleaser 3aa22b0942 releaser: Prepare repository for 0.149.0-DEV
[ci skip]
2025-07-27 12:59:26 +00:00
hugoreleaser 40c3d8233d releaser: Bump versions for release of 0.148.2
[ci skip]
2025-07-27 12:43:24 +00:00
Bjørn Erik Pedersen 7ff5ec734c tpl: Add test for recent template selection regression
Closes #13868

Co-authored-by: Joe Mooring <joe.mooring@veriphor.com>
2025-07-27 14:39:39 +02:00
Bjørn Erik Pedersen 3937ab24d0 Revert "hugolib: Honor implicit "page" type during template selection"
This reverts commit cfc8d315b4.

See #13868
2025-07-27 14:39:39 +02:00
Bjørn Erik Pedersen 9c57af1351 Fix regression with hyphenated codeblock templates, e.g. render-codeblock-go-html-template.html
Fixes #13864

Co-authored-by: Joe Mooring <joe.mooring@veriphor.com>
2025-07-27 14:39:39 +02:00
Bjørn Erik Pedersen d240a705d6 commands: Avoid full browser refresh on simple CSS changes 2025-07-27 14:39:26 +02:00
hugoreleaser bbcc2a7973 releaser: Prepare repository for 0.149.0-DEV
[ci skip]
2025-07-11 13:13:44 +00:00
hugoreleaser 98ba786f2f releaser: Bump versions for release of 0.148.1
[ci skip]
2025-07-11 12:56:21 +00:00
Bjørn Erik Pedersen 6f42cfbc9b Fix assignment to entry in nil map
Fixes #13853
2025-07-11 14:21:53 +02:00
Bjørn Erik Pedersen a84beee429 deps: Downgrade github.com/niklasfasching/go-org v1.9.0 => v1.8.0
See #13846
2025-07-11 11:10:48 +02:00
hugoreleaser 65893efd8d releaser: Prepare repository for 0.149.0-DEV
[ci skip]
2025-07-08 13:51:56 +00:00
hugoreleaser c0d9bebacc releaser: Bump versions for release of 0.148.0
[ci skip]
2025-07-08 13:34:49 +00:00
Bjørn Erik Pedersen 3e2f1cdfdb Add Ancestors (plural) method to GitInfo, rename Ancestor field to Parent
Fixes #13839
2025-07-08 15:08:09 +02:00
dependabot[bot] 0a5b870281 build(deps): bump github.com/evanw/esbuild from 0.25.5 to 0.25.6
Bumps [github.com/evanw/esbuild](https://github.com/evanw/esbuild) from 0.25.5 to 0.25.6.
- [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.25.5...v0.25.6)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-08 12:01:51 +02:00
Bjørn Erik Pedersen bba6996e15 Allow creating home pages from content adapters
* Allow "" (empty string) or "/" to represent the home page path.
* Be a little more lenient about path validation.
2025-07-07 18:41:45 +02:00
dependabot[bot] 94e2c276a8 build(deps): bump github.com/olekukonko/tablewriter from 1.0.7 to 1.0.8
Bumps [github.com/olekukonko/tablewriter](https://github.com/olekukonko/tablewriter) from 1.0.7 to 1.0.8.
- [Commits](https://github.com/olekukonko/tablewriter/compare/v1.0.7...v1.0.8)

---
updated-dependencies:
- dependency-name: github.com/olekukonko/tablewriter
  dependency-version: 1.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-07 14:59:20 +02:00
Bjørn Erik Pedersen 90d397b142 Remove the internal GitInfo type and make Page.GitInf() return a pointer
See #5693
2025-07-07 14:49:27 +02:00
Jens Broekens 61e6c730dd source: Expose Ancestor in GitInfo
Also updates docs and bumps bep/gitmap to v1.7.0

Closes #5693

Co-authored-by: bep <bjorn.erik.pedersen@gmail.com>
2025-07-07 14:49:27 +02:00
Bjørn Erik Pedersen e4f6b9eef8 Merge commit 'bb147f91ee9078e6a55e8c32ab4b2e5dbc5cee45' 2025-07-07 13:17:48 +02:00
Bjørn Erik Pedersen bb147f91ee Squashed 'docs/' changes from b654fcba0..60dd993a6
60dd993a6 content: Update GitHub Pages workflow
6247e3590 content: Fix typo
a22255b0b content: Update version references
21afec198 content: Update version reference
6226532c8 content: Update version reference
80d26621a content: Update version reference
cda7135b5 content: Fix typo
70c509e8a content: Fix typo
136b20310 content: Change render hook example
038246c2f content: Fix accidental removal
441375fa4 netlify: Hugo 0.147.9
4a620931c content: Note that config/env/cascade.xxx is not supported
6d3a7587f config: Ignore front matter param override warnings
623b48624 content: Set searchable param to false for content/en/documentation.md
d1b2aad69 content: Fix Codeberg deployment article
5e3d849b8 search: Use front matter parameter to control search indexing
b4f90e39d content: Note that PATH segments must exclude project directory
a81406e26 content: Create aliases for deleted template pages
7c3adc9ad content: Change order of template types
e093eb036 content: Remove admonition from template types page
0015e7a9b content: Update to align with v0.146.0 template system (phase 1)
cf986240d content: Update templates.Defer note
ab51fdcc7 content: Use consistent templates.Defer examples
b4f8e492f content: Fix formatting
62aa94add content: Fix typo
83747f36b content: Update FAQs
fc644d894 Update netlify.toml
4151f3a5b content: Fix typo
9452bca92 content: Update description ToMath strict option
982b863c3 content: Add instructions about deploying to root of user's Codeberg Pages
fc7cd2878 theme: Generate QR code once per page
784891b87 content: Update links to the CommonMark specification
741113fb5 content: Fix incorrect link to Shortcodes tutorial
c4962f1ac content: Update transform.ToMath
ad7b87223 Update netlify.toml
2d64e57ae theme: Remove bullet from new-in badge
55a832f8e Update ToMath.md
e1e624f49 content: Document transform.ToMath strict mode
2df6218f8 netlify: Hugo 0.147.6
0259b88f1 Revert "theme: Display date on news items from content adapter"
43b35e56a theme: Adjust admonition dark mode colors
2f15e9c34 theme: Add link to Mastodon
d99e979d4 theme: Display date on news items from content adapter
6c93dac97 content: Clarify the AddResource content value
49006468e content: Describe Codeberg's Forgejo Actions
be80c3b82 content: Update css.TailwindCSS opts
b3ba4329c theme: Update css.TailwindCSS opts and remove tailwind.config.js
902e360b0 content: Update stylesheet link for katex.js
8b9e1ba3e content: Update stylesheet link for katex.js
7dae3b0e8 content: Update TailwindCSS instructions
cb093d210 Update netlify.toml
577d6fbb1 content: Remove GitCMS for now
8352af6cd Updates for v0.147.4
2240f07a5 content: Fix typo
677b3fed3 Correct openapi3.Unmarshal example
580477aa5 content: Fix typo
0dc43b481 content: Add GitCMS to commercial front ends list
ac4179f2b content: Fix relref shortcode examples
a699d267b Fix typos
7e28c4380 Make sponsor logo responsive
8e05f0425 Update MaxInt64.md
f715265d3 content: Document math.MaxInt64
0d57ff7d4 Update netlify.toml
d210e3476 theme: Adjust sponsor
e73444b43 content: Clarify page title values
fd4c292b8 content: Fix links to Pandoc
dd074dc67 content: Bump version in GitHub Pages example
fe5537bb2 content: Describe the pandoc format
10834529e theme: Remove duplicate meta element
838706d6e theme: More changes related to new template system
b0b6b1e69 Update new-templatesystem-overview.md
e719d2360 Update new-templatesystem-overview.md
ec2bbd395 Update new-templatesystem-overview.md
53319a681 Add a one pager about the new template system
e17416c05 Fix the spelling issue on the Host on Render description
e8e1c82aa content: Document range-over-int introduced in v0.123.0
bc478f98f content: Fix editing errors
606547b48 Update netlify.toml
e224f3f82 content: Fix formatting
24e4acc41 content: Fix typo
1e773f34b content: Fix typo
5ef94a725 content: Document alternative to shuffle for large collections
7fe42d76c content: Fix sample code formatting
5d601448f content: Update mathematical markup guidance
63b4fe2c0 content: Update version references
722da91f1 content: Fix GO_VERSION in Netlify hosting example
8cc589c3a theme: Add current Hugo version to the header
37aa24ac5 netlify: Hugo 0.147.1
a80b25e24 content: Remove dated new-in
89dcf0f92 content: Fix path formatting
1a5191d78 content: Update transformation examples
3327065ab Update Text.md
557c10dd2 content: Miscellaneous updates for v0.147.0
0dae1a185 netlify: Hugo 0.147.0
9b44821c3 Merge branch 'tempv0.147.0'
f1481e8c3 content: Update GitLab Pages workflow example
2e61a0360 content: Update content format descriptions
fb42d7c2a images: Add option for vertical alignment to images.Text

git-subtree-dir: docs
git-subtree-split: 60dd993a65
2025-07-07 13:16:31 +02:00
Ruslan Semagin 266d46dccc config: Increase test coverage 2025-07-07 11:27:34 +02:00
dependabot[bot] e77b2ad8fd build(deps): bump github.com/niklasfasching/go-org from 1.8.0 to 1.9.0
Bumps [github.com/niklasfasching/go-org](https://github.com/niklasfasching/go-org) from 1.8.0 to 1.9.0.
- [Commits](https://github.com/niklasfasching/go-org/compare/v1.8.0...v1.9.0)

---
updated-dependencies:
- dependency-name: github.com/niklasfasching/go-org
  dependency-version: 1.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-07 11:23:08 +02:00
dependabot[bot] 9487acf6ab build(deps): bump github.com/alecthomas/chroma/v2 from 2.18.0 to 2.19.0
Bumps [github.com/alecthomas/chroma/v2](https://github.com/alecthomas/chroma) from 2.18.0 to 2.19.0.
- [Release notes](https://github.com/alecthomas/chroma/releases)
- [Changelog](https://github.com/alecthomas/chroma/blob/master/.goreleaser.yml)
- [Commits](https://github.com/alecthomas/chroma/compare/v2.18.0...v2.19.0)

---
updated-dependencies:
- dependency-name: github.com/alecthomas/chroma/v2
  dependency-version: 2.19.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-07 11:22:29 +02:00
Joe Mooring 84b31721bf markup/goldmark: Change link and image render hook enablement to enums
Closes #13535
2025-07-07 11:19:34 +02:00
Bjørn Erik Pedersen b8ba33ca95 Fix some uglyURLs issues for home, section and taxonomy kind (note)
Fixes #4428
Fixes #7497

Co-authored-by: Joe Mooring <joe.mooring@veriphor.com>
2025-07-05 18:11:28 +02:00
Bjørn Erik Pedersen f967212b72 Fix branch paths when OutputFormat.Path is configured (note)
Fixes #13829

Co-authored-by: Joe Mooring <joe.mooring@veriphor.com>
2025-07-05 18:11:28 +02:00
Joe Mooring 1b4c423667 resources/page: Allow full datetime prefix in filenames
Allow YYYY-MM-DD-HH-MM-SS prefix when extracting date from file names.
This is in addition to the YYYY-MM-DD prefix that is already supported.

Closes #13830
2025-07-05 11:26:35 +02:00
dependabot[bot] 1e9a0b93e3 build(deps): bump golang.org/x/tools from 0.32.0 to 0.34.0
Bumps [golang.org/x/tools](https://github.com/golang/tools) from 0.32.0 to 0.34.0.
- [Release notes](https://github.com/golang/tools/releases)
- [Commits](https://github.com/golang/tools/compare/v0.32.0...v0.34.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-03 10:46:37 +02:00
Joe Mooring cfc8d315b4 hugolib: Honor implicit "page" type during template selection
Closes #13826
2025-07-02 13:43:40 +02:00
David Jones dd6e2c8724 deploy: walkLocal worker pool for performance 2025-06-29 16:41:56 +02:00
hugoreleaser 762417617c releaser: Prepare repository for 0.148.0-DEV
[ci skip]
2025-06-23 08:38:21 +00:00
hugoreleaser 29bdbde19c releaser: Bump versions for release of 0.147.9
[ci skip]
2025-06-23 08:22:20 +00:00
Bjørn Erik Pedersen 6a4a3ab8f8 Remove WARN with false negatives
Fixes #13806
2025-06-22 16:55:43 +02:00
Bjørn Erik Pedersen 36f6f987a9 resources/page: Make sure a map is always initialized
Fixes #13810
2025-06-21 14:38:06 +02:00
Joe Mooring 18a9ca7d7a tpl/tplimpl: Copy embedded HTML table render hook to each output format
Closes #13351
2025-06-21 14:37:47 +02:00
Joe Mooring b6c8dfa9dc tpl/tplimpl: Change resources.GetRemote errors to suppressible warnings
Closes #13803
2025-06-17 07:35:14 -07:00
dependabot[bot] 621ea42f3c build(deps): bump google.golang.org/api from 0.221.0 to 0.237.0
Bumps [google.golang.org/api](https://github.com/googleapis/google-api-go-client) from 0.221.0 to 0.237.0.
- [Release notes](https://github.com/googleapis/google-api-go-client/releases)
- [Changelog](https://github.com/googleapis/google-api-go-client/blob/main/CHANGES.md)
- [Commits](https://github.com/googleapis/google-api-go-client/compare/v0.221.0...v0.237.0)

---
updated-dependencies:
- dependency-name: google.golang.org/api
  dependency-version: 0.237.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-13 13:53:25 +02:00
Bjørn Erik Pedersen 4ef5720141 hugolib: Remove test for deprecated future 2025-06-13 12:17:06 +02:00
dependabot[bot] 34e83789f7 build(deps): bump github.com/aws/aws-sdk-go-v2 from 1.36.1 to 1.36.4
Bumps [github.com/aws/aws-sdk-go-v2](https://github.com/aws/aws-sdk-go-v2) from 1.36.1 to 1.36.4.
- [Release notes](https://github.com/aws/aws-sdk-go-v2/releases)
- [Changelog](https://github.com/aws/aws-sdk-go-v2/blob/main/changelog-template.json)
- [Commits](https://github.com/aws/aws-sdk-go-v2/compare/v1.36.1...v1.36.4)

---
updated-dependencies:
- dependency-name: github.com/aws/aws-sdk-go-v2
  dependency-version: 1.36.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-13 11:25:11 +02:00
dependabot[bot] 4d3ebe4d21 build(deps): bump golang.org/x/image from 0.27.0 to 0.28.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.27.0 to 0.28.0.
- [Commits](https://github.com/golang/image/compare/v0.27.0...v0.28.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-12 14:17:16 +02:00
Joe Mooring b5c0383bda deps: Upgrade github.com/spf13/cast v1.8.0 => v1.9.2 2025-06-12 10:07:09 +02:00
Joe Mooring 4217fee4b0 common/terminal: Enable color output on windows
Closes #8209
2025-06-09 11:44:13 +02:00
hugoreleaser fad57964aa releaser: Prepare repository for 0.148.0-DEV
[ci skip]
2025-06-07 13:13:56 +00:00
hugoreleaser 10da2bd765 releaser: Bump versions for release of 0.147.8
[ci skip]
2025-06-07 12:59:52 +00:00
Joe Mooring 01241d5dc9 hugolib: Emit ignorable warning when home page is a leaf bundle
Closes #13538
2025-06-07 13:02:28 +02:00
Bjørn Erik Pedersen 8e61f1fe12 dockerfile: Update Alpine
Closes #13783
2025-06-06 08:16:30 +02:00
Bjørn Erik Pedersen f37412a575 dockerfile: Update Go version
FIxes #13780
2025-06-04 16:52:17 +02:00
dependabot[bot] 21a4a9acd7 build(deps): bump github.com/evanw/esbuild from 0.25.3 to 0.25.5
Bumps [github.com/evanw/esbuild](https://github.com/evanw/esbuild) from 0.25.3 to 0.25.5.
- [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.25.3...v0.25.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-03 11:27:57 +02:00
dependabot[bot] 7a4a4790e5 build(deps): bump github.com/niklasfasching/go-org from 1.7.0 to 1.8.0
Bumps [github.com/niklasfasching/go-org](https://github.com/niklasfasching/go-org) from 1.7.0 to 1.8.0.
- [Commits](https://github.com/niklasfasching/go-org/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/niklasfasching/go-org
  dependency-version: 1.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-03 11:26:51 +02:00
dependabot[bot] 54065b7ef8 build(deps): bump golang.org/x/net from 0.39.0 to 0.40.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.39.0 to 0.40.0.
- [Commits](https://github.com/golang/net/compare/v0.39.0...v0.40.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-03 09:01:37 +02:00
dependabot[bot] e333836f49 build(deps): bump github.com/yuin/goldmark from 1.7.11 to 1.7.12
Bumps [github.com/yuin/goldmark](https://github.com/yuin/goldmark) from 1.7.11 to 1.7.12.
- [Release notes](https://github.com/yuin/goldmark/releases)
- [Commits](https://github.com/yuin/goldmark/compare/v1.7.11...v1.7.12)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 18:18:44 +02:00
dependabot[bot] cc7bfeea32 build(deps): bump github.com/tdewolff/minify/v2 from 2.23.5 to 2.23.8
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.23.5 to 2.23.8.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.23.5...v2.23.8)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-02 18:18:24 +02:00
Bjørn Erik Pedersen 32eb1a8ad4 all: Replace _build with build in tests
_build is deprecated and now shows up as warning.
2025-06-02 16:35:37 +02:00
hugoreleaser 32af02cd3e releaser: Prepare repository for 0.148.0-DEV
[ci skip]
2025-05-31 12:55:24 +00:00
hugoreleaser 189453612e releaser: Bump versions for release of 0.147.7
[ci skip]
2025-05-31 12:41:12 +00:00
Bjørn Erik Pedersen 5273a884d4 Fix language handling in shortcode templates
Fixes #13767
2025-05-31 13:57:00 +02:00
Bjørn Erik Pedersen 6334948515 Handle KaTeX warnings (#13760)
Co-authored-by: Joe Mooring <joe.mooring@veriphor.com>

Fixes #13735
2025-05-30 20:57:54 +02:00
dependabot[bot] 75259636c8 build(deps): bump golang.org/x/image from 0.26.0 to 0.27.0
Bumps [golang.org/x/image](https://github.com/golang/image) from 0.26.0 to 0.27.0.
- [Commits](https://github.com/golang/image/compare/v0.26.0...v0.27.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-30 15:13:21 +02:00
dependabot[bot] 0df9f3510f build(deps): bump golang.org/x/text from 0.24.0 to 0.25.0
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.24.0 to 0.25.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.24.0...v0.25.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-30 12:50:09 +02:00
dependabot[bot] 302e6a726b build(deps): bump github.com/spf13/cast from 1.7.1 to 1.8.0
Bumps [github.com/spf13/cast](https://github.com/spf13/cast) from 1.7.1 to 1.8.0.
- [Release notes](https://github.com/spf13/cast/releases)
- [Commits](https://github.com/spf13/cast/compare/v1.7.1...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cast
  dependency-version: 1.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-30 08:34:09 +02:00
dependabot[bot] 202fe0d45c build(deps): bump github.com/alecthomas/chroma/v2 from 2.17.2 to 2.18.0
Bumps [github.com/alecthomas/chroma/v2](https://github.com/alecthomas/chroma) from 2.17.2 to 2.18.0.
- [Release notes](https://github.com/alecthomas/chroma/releases)
- [Changelog](https://github.com/alecthomas/chroma/blob/master/.goreleaser.yml)
- [Commits](https://github.com/alecthomas/chroma/compare/v2.17.2...v2.18.0)

---
updated-dependencies:
- dependency-name: github.com/alecthomas/chroma/v2
  dependency-version: 2.18.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-29 22:12:58 +02:00
Joe Mooring 843ffeb48d resources/page: Respect disablePathToLower for permalink tokens
Fixes #13755
2025-05-29 22:10:03 +02:00
Ruslan Semagin bff5d19121 common/collections: Increase test coverage 2025-05-29 09:17:13 +02:00
Ruslan Semagin da370d30de parser/pageparser: Add coverage for all IsX methods of Item
Added tests for all boolean methods on Item, increasing overall code coverage.
2025-05-28 21:53:17 +02:00
Bjørn Erik Pedersen 6bd328c584 resources: Remove unused interface 2025-05-28 19:32:28 +02:00
Bjørn Erik Pedersen 766a2e7868 Make sure that unreferenced but changed bundle resources gets republished
Fixes #13748
2025-05-28 19:32:28 +02:00
Bjørn Erik Pedersen 13e1617557 deps: Upgrade github.com/olekukonko/tablewriter v0.0.5 => v1.0.7 2025-05-28 18:07:14 +02:00
hugoreleaser 463e440c7a releaser: Prepare repository for 0.148.0-DEV
[ci skip]
2025-05-27 11:31:53 +00:00
hugoreleaser 0a5fd8ebb8 releaser: Bump versions for release of 0.147.6
[ci skip]
2025-05-27 11:17:16 +00:00
Andreas Deininger e57dcd3795 Improve warning message on superfluous prefix when using function 'partials.Include' 2025-05-27 12:16:26 +02:00
Bjørn Erik Pedersen eaf5ace30d Fix recent regression with cascading of params to content adapters
Fixes #13743
2025-05-26 21:26:19 +02:00
Bjørn Erik Pedersen 9ad26b69ad Fix it so e.g. de in layouts/_shortcodes/de.html is not interpreted as a language code
Fixes #13740
2025-05-26 20:26:56 +02:00
Bjørn Erik Pedersen f47193669d commands: Make sure the browser gets refreshed on changes when --disableFastRender is set
Fixes #13727
2025-05-23 19:46:16 +02:00
Joe Mooring 013c8cfb25 tpl/transform: Expose the KaTeX strict option
Closes #13729
2025-05-23 19:21:38 +02:00
hugoreleaser e25db38467 releaser: Prepare repository for 0.148.0-DEV
[ci skip]
2025-05-22 11:51:47 +00:00
hugoreleaser 7766fc6241 releaser: Bump versions for release of 0.147.5
[ci skip]
2025-05-22 11:37:19 +00:00
Bjørn Erik Pedersen 4a48facef4 Merge branch 'release-0.147.4' 2025-05-22 13:19:34 +02:00
Bjørn Erik Pedersen 0c7b1a3f26 Fix live reload when editing inline partials
Fixes #13723
2025-05-22 13:15:41 +02:00
dependabot[bot] 970b887ba1 build(deps): bump github.com/tdewolff/minify/v2 from 2.20.37 to 2.23.5
Bumps [github.com/tdewolff/minify/v2](https://github.com/tdewolff/minify) from 2.20.37 to 2.23.5.
- [Release notes](https://github.com/tdewolff/minify/releases)
- [Commits](https://github.com/tdewolff/minify/compare/v2.20.37...v2.23.5)

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

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-20 14:49:06 +02:00
hugoreleaser b9b95e5aec releaser: Prepare repository for 0.148.0-DEV
[ci skip]
2025-05-20 10:55:43 +00:00
hugoreleaser 84c8426f32 releaser: Bump versions for release of 0.147.4
[ci skip]
2025-05-20 10:41:19 +00:00
Bjørn Erik Pedersen a03a245f0c Fix it so css.TailwindCSS inlineImports options isn't always enabled
To avoid breaking existing setup and to make a better default option, the option is now `disableInlineImports` (default false).
Fixes #13719
2025-05-19 19:36:48 +02:00
Bjørn Erik Pedersen 5a81a3a4cf tpl: Add a test case
I'm not able to reproduce this, but leaving it in.

Closes #13699
2025-05-18 12:48:24 +02:00
Bjørn Erik Pedersen 61317821e4 tpl: Narrow down the usage of plain text shortcodes when rendering HTML
After this commit, if you want to resolve `layouts/_shortcodes/myshortcode.txt` when rendering HTML content, you need to use the `{{%` shortcode delimiter:

```
{{% myshortcode %}}
```

This should be what people would do anyway, but we have also as part of this improved the error message to inform about what needs to be done.

Note that this is not relevant for partials.

Fixes #13698
2025-05-18 12:48:24 +02:00
Bjørn Erik Pedersen 6142bc701c tpl: Fix theme overrides when theme has old layout setup (e.g. _default)
Fixes #13715
2025-05-18 12:48:24 +02:00
hugoreleaser e6574cf7a7 releaser: Prepare repository for 0.148.0-DEV
[ci skip]
2025-05-12 12:40:04 +00:00
hugoreleaser 05417512bd releaser: Bump versions for release of 0.147.3
[ci skip]
2025-05-12 12:25:03 +00:00
Joe Mooring 81426998b8 tpl/tplimpl: Change calls to simple versions of embedded shortcodes
Closes #13700
2025-05-12 14:19:11 +02:00
Bjørn Erik Pedersen 6def5a1ba9 Update README.md 2025-05-12 12:10:27 +02:00
Bjørn Erik Pedersen bc98e7a80d config: Fix env override of slices
Fixes #13707
2025-05-11 19:24:24 +02:00
Bjørn Erik Pedersen c745a3e108 Fix/implement cascade for content adapters
Fixes #13692
2025-05-10 15:12:24 +02:00
Joe Mooring 9d1d8c8899 commands: Fix description of new theme commands
Fixes #13701
2025-05-09 20:03:21 +02:00
Joe Mooring 84d7a108e8 tpl/tplimpl: Fix vimeo shortcode test to accommodate API changes
Fixes #13687
2025-05-09 10:02:00 -07:00
Joe Mooring 325a0dba63 tpl/math: Add MaxInt64 function
Closes #13693
2025-05-07 19:40:29 +02:00
484 changed files with 10174 additions and 5922 deletions
+2 -2
View File
@@ -4,7 +4,7 @@ parameters:
defaults: &defaults
resource_class: large
docker:
- image: bepsays/ci-hugoreleaser:1.22400.20000
- image: bepsays/ci-hugoreleaser:1.22500.20300
environment: &buildenv
GOMODCACHE: /root/project/gomodcache
version: 2
@@ -58,7 +58,7 @@ jobs:
environment:
<<: [*buildenv]
docker:
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22400.20000
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22500.20300
steps:
- *restore-cache
- &attach-workspace
+2 -2
View File
@@ -16,7 +16,7 @@ jobs:
test:
strategy:
matrix:
go-version: [1.23.x, 1.24.x]
go-version: [1.24.x, 1.25.x]
os: [ubuntu-latest, windows-latest] # macos disabled for now because of disk space issues.
runs-on: ${{ matrix.os }}
steps:
@@ -45,7 +45,7 @@ jobs:
**/go.sum
**/go.mod
- name: Install Ruby
uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0
uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0
with:
ruby-version: "2.7"
bundler-cache: true #
+4 -4
View File
@@ -2,8 +2,8 @@
# Twitter: https://twitter.com/gohugoio
# Website: https://gohugo.io/
ARG GO_VERSION="1.23.2"
ARG ALPINE_VERSION="3.20"
ARG GO_VERSION="1.25"
ARG ALPINE_VERSION="3.22"
ARG DART_SASS_VERSION="1.79.3"
FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0 AS xx
@@ -19,7 +19,7 @@ RUN apk add clang lld
COPY --from=xx / /
ARG TARGETPLATFORM
RUN xx-apk add musl-dev gcc g++
RUN xx-apk add musl-dev gcc g++
# Optionally set HUGO_BUILD_TAGS to "none" or "withdeploy" when building like so:
# docker build --build-arg HUGO_BUILD_TAGS=withdeploy .
@@ -72,7 +72,7 @@ RUN mkdir -p /var/hugo/bin /cache && \
adduser -Sg hugo -u 1000 -h /var/hugo hugo && \
chown -R hugo: /var/hugo /cache && \
# For the Hugo's Git integration to work.
runuser -u hugo -- git config --global --add safe.directory /project && \
runuser -u hugo -- git config --global --add safe.directory /project && \
# See https://github.com/gohugoio/hugo/issues/9810
runuser -u hugo -- git config --global core.quotepath false
+7 -5
View File
@@ -65,9 +65,11 @@ See the [features] section of the documentation for a comprehensive summary of H
<p>&nbsp;</p>
<p float="left">
<a href="https://www.linode.com/?utm_campaign=hugosponsor&utm_medium=banner&utm_source=hugogithub" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/linode-logo_standard_light_medium.png" width="200" alt="Linode"></a>
<a href="https://www.linode.com/?utm_campaign=hugosponsor&utm_medium=banner&utm_source=hugogithub" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/hugoDocs/master/assets/images/sponsors/linode-logo_standard_light_medium.png" width="200" alt="Linode"></a>
&nbsp;&nbsp;&nbsp;
<a href="https://www.jetbrains.com/go/?utm_source=OSS&utm_medium=referral&utm_campaign=hugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/goland.svg" width="200" alt="The complete IDE crafted for professional Go developers."></a>
<a href="https://www.jetbrains.com/go/?utm_source=OSS&utm_medium=referral&utm_campaign=hugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/hugoDocs/master/assets/images/sponsors/goland.svg" width="200" alt="The complete IDE crafted for professional Go developers."></a>
&nbsp;&nbsp;&nbsp;
<a href="https://cloudcannon.com/hugo-cms/?utm_campaign=HugoSponsorship&utm_source=sponsor&utm_content=gohugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/hugoDocs/master/assets/images/sponsors/cloudcannon-cms-logo.svg" width="200" alt="CloudCannon"></a>
</p>
## Editions
@@ -100,9 +102,9 @@ Install Hugo from a [prebuilt binary], package manager, or package repository. P
Prerequisites to build Hugo from source:
- Standard edition: Go 1.23.0 or later
- Extended edition: Go 1.23.0 or later, and GCC
- Extended/deploy edition: Go 1.23.0 or later, and GCC
- Standard edition: Go 1.24.0 or later
- Extended edition: Go 1.24.0 or later, and GCC
- Extended/deploy edition: Go 1.24.0 or later, and GCC
Build the standard edition:
+13 -2
View File
@@ -25,6 +25,8 @@ import (
// DefaultConfig holds the default configuration for the HTTP cache.
var DefaultConfig = Config{
RespectCacheControlNoStoreInRequest: true,
RespectCacheControlNoStoreInResponse: false,
Cache: Cache{
For: GlobMatcher{
Excludes: []string{"**"},
@@ -42,7 +44,13 @@ var DefaultConfig = Config{
// Config holds the configuration for the HTTP cache.
type Config struct {
// Configures the HTTP cache behavior (RFC 9111).
// When enabled and there's a Cache-Control: no-store directive in the request, response will never be stored in disk cache.
RespectCacheControlNoStoreInRequest bool
// When enabled and there's a Cache-Control: no-store directive in the response, response will never be stored in disk cache.
RespectCacheControlNoStoreInResponse bool
// Enables HTTP cache behavior (RFC 9111) for these resources.
// When this is not enabled for a resource, Hugo will go straight to the file cache.
Cache Cache
@@ -57,7 +65,9 @@ type Cache struct {
}
func (c *Config) Compile() (ConfigCompiled, error) {
var cc ConfigCompiled
cc := ConfigCompiled{
Base: *c,
}
p, err := c.Cache.For.CompilePredicate()
if err != nil {
@@ -127,6 +137,7 @@ func (gm GlobMatcher) IsZero() bool {
}
type ConfigCompiled struct {
Base Config
For predicate.P[string]
PollConfigs []PollConfigCompiled
}
+11 -6
View File
@@ -28,6 +28,7 @@ import (
"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"
"github.com/gohugoio/hugo/docshelper"
"github.com/gohugoio/hugo/helpers"
@@ -36,7 +37,6 @@ import (
"github.com/gohugoio/hugo/parser"
"github.com/spf13/cobra"
"github.com/spf13/cobra/doc"
"gopkg.in/yaml.v2"
)
func newGenCommand() *genCommand {
@@ -51,6 +51,7 @@ func newGenCommand() *genCommand {
lineNumbersInlineStyle string
lineNumbersTableStyle string
omitEmpty bool
omitClassComments bool
)
newChromaStyles := func() simplecobra.Commander {
@@ -81,12 +82,14 @@ See https://xyproto.github.io/splash/docs/all.html for a preview of the availabl
return err
}
var formatter *html.Formatter
if omitEmpty {
formatter = html.New(html.WithClasses(true))
} else {
formatter = html.New(html.WithAllClasses(true))
// 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),
}
formatter := html.New(options...)
w := os.Stdout
fmt.Fprintf(w, "/* Generated using: hugo %s */\n\n", strings.Join(os.Args[1:], " "))
@@ -103,8 +106,10 @@ See https://xyproto.github.io/splash/docs/all.html for a preview of the availabl
_ = cmd.RegisterFlagCompletionFunc("lineNumbersInlineStyle", cobra.NoFileCompletions)
cmd.PersistentFlags().StringVar(&lineNumbersTableStyle, "lineNumbersTableStyle", "", `foreground and background colors for table line numbers, e.g. --lineNumbersTableStyle "#fff000 bg:#000fff"`)
_ = cmd.RegisterFlagCompletionFunc("lineNumbersTableStyle", cobra.NoFileCompletions)
cmd.PersistentFlags().BoolVar(&omitEmpty, "omitEmpty", false, `omit empty CSS rules`)
cmd.PersistentFlags().BoolVar(&omitEmpty, "omitEmpty", false, `omit empty CSS rules (deprecated, no longer needed)`)
_ = cmd.RegisterFlagCompletionFunc("omitEmpty", cobra.NoFileCompletions)
cmd.PersistentFlags().BoolVar(&omitClassComments, "omitClassComments", false, `omit CSS class comment prefixes in the generated CSS`)
_ = cmd.RegisterFlagCompletionFunc("omitClassComments", cobra.NoFileCompletions)
},
}
}
+1 -1
View File
@@ -76,7 +76,7 @@ func flagsToCfgWithAdditionalConfigBase(cd *simplecobra.Commandeer, cfg config.P
// Flags with a different name in the config.
keyMap := map[string]string{
"minify": "minifyOutput",
"minify": "minify.minifyOutput",
"destination": "publishDir",
"editor": "newContentEditor",
}
+24 -1
View File
@@ -27,6 +27,7 @@ import (
"sync/atomic"
"time"
"github.com/bep/debounce"
"github.com/bep/simplecobra"
"github.com/fsnotify/fsnotify"
"github.com/gohugoio/hugo/common/herrors"
@@ -515,6 +516,14 @@ func (c *hugoBuilder) doWithPublishDirs(f func(sourceFs *filesystems.SourceFiles
return langCount, nil
}
func (c *hugoBuilder) progressIntermediate() {
terminal.ReportProgress(c.r.StdOut, terminal.ProgressIntermediate, 0)
}
func (c *hugoBuilder) progressHidden() {
terminal.ReportProgress(c.r.StdOut, terminal.ProgressHidden, 0)
}
func (c *hugoBuilder) fullBuild(noBuildLock bool) error {
var (
g errgroup.Group
@@ -962,7 +971,7 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
lrl.Logf("no page to navigate to, force refresh")
livereload.ForceRefresh()
}
} else if len(otherChanges) > 0 {
} else if len(otherChanges) > 0 || len(cssChanges) > 0 {
if len(otherChanges) == 1 {
// Allow single changes to be refreshed without a full page reload.
pathToRefresh := h.PathSpec.RelURL(paths.ToSlashTrimLeading(otherChanges[0]), false)
@@ -972,6 +981,9 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
lrl.Logf("force refresh")
livereload.ForceRefresh()
}
} else {
lrl.Logf("force refresh")
livereload.ForceRefresh()
}
if len(cssChanges) > 0 {
@@ -1024,6 +1036,17 @@ func (c *hugoBuilder) hugoTry() *hugolib.HugoSites {
}
func (c *hugoBuilder) loadConfig(cd *simplecobra.Commandeer, running bool) error {
if terminal.PrintANSIColors(os.Stdout) {
defer c.progressHidden()
// If the configuration takes a while to load, we want to show some progress.
// This is typically loading of external modules.
d := debounce.New(500 * time.Millisecond)
d(func() {
c.progressIntermediate()
})
defer d(func() {})
}
cfg := config.New()
cfg.Set("renderToMemory", c.r.renderToMemory)
watch := c.r.buildWatch || (c.s != nil && c.s.serverWatch)
+8 -10
View File
@@ -53,7 +53,9 @@ Ensure you run this within the root directory of your site.`,
if len(args) < 1 {
return newUserError("path needs to be provided")
}
h, err := r.Hugo(flagsToCfg(cd, nil))
cfg := flagsToCfg(cd, nil)
cfg.Set("BuildFuture", true)
h, err := r.Hugo(cfg)
if err != nil {
return err
}
@@ -76,10 +78,8 @@ Ensure you run this within the root directory of your site.`,
&simpleCommand{
name: "site",
use: "site [path]",
short: "Create a new site (skeleton)",
long: `Create a new site in the provided directory.
The new site will have the correct structure, but no content or theme yet.
Use ` + "`hugo new [contentPath]`" + ` to create new content.`,
short: "Create a new site",
long: `Create a new site at the specified path.`,
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
if len(args) < 1 {
return newUserError("path needs to be provided")
@@ -124,11 +124,9 @@ Use ` + "`hugo new [contentPath]`" + ` to create new content.`,
&simpleCommand{
name: "theme",
use: "theme [name]",
short: "Create a new theme (skeleton)",
long: `Create a new theme (skeleton) called [name] in ./themes.
New theme is a skeleton. Please add content to the touched files. Add your
name to the copyright line in the license and adjust the theme.toml file
according to your needs.`,
short: "Create a new theme",
long: `Create a new theme with the specified name in the ./themes directory.
This generates a functional theme including template examples and sample content.`,
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
if len(args) < 1 {
return newUserError("theme name needs to be provided")
-1
View File
@@ -1166,7 +1166,6 @@ func chmodFilter(dst, src os.FileInfo) bool {
}
func cleanErrorLog(content string) string {
content = strings.ReplaceAll(content, "\n", " ")
content = logReplacer.Replace(content)
content = logDuplicateTemplateExecuteRe.ReplaceAllString(content, "")
content = logDuplicateTemplateParseRe.ReplaceAllString(content, "")
+65
View File
@@ -15,6 +15,7 @@ package collections
import (
"html/template"
"reflect"
"testing"
qt "github.com/frankban/quicktest"
@@ -77,6 +78,7 @@ func TestAppend(t *testing.T) {
{[]string{"a", "b"}, []any{nil}, []any{"a", "b", nil}},
{[]string{"a", "b"}, []any{nil, "d", nil}, []any{"a", "b", nil, "d", nil}},
{[]any{"a", nil, "c"}, []any{"d", nil, "f"}, []any{"a", nil, "c", "d", nil, "f"}},
{[]string{"a", "b"}, []any{}, []string{"a", "b"}},
} {
result, err := Append(test.start, test.addend...)
@@ -146,3 +148,66 @@ func TestAppendShouldMakeACopyOfTheInputSlice(t *testing.T) {
c.Assert(result, qt.DeepEquals, []string{"a", "b", "c"})
c.Assert(slice, qt.DeepEquals, []string{"d", "b"})
}
func TestIndirect(t *testing.T) {
t.Parallel()
c := qt.New(t)
type testStruct struct {
Field string
}
var (
nilPtr *testStruct
nilIface interface{} = nil
nonNilIface interface{} = &testStruct{Field: "hello"}
)
tests := []struct {
name string
input any
wantKind reflect.Kind
wantNil bool
}{
{
name: "nil pointer",
input: nilPtr,
wantKind: reflect.Ptr,
wantNil: true,
},
{
name: "nil interface",
input: nilIface,
wantKind: reflect.Invalid,
wantNil: false,
},
{
name: "non-nil pointer to struct",
input: &testStruct{Field: "abc"},
wantKind: reflect.Struct,
wantNil: false,
},
{
name: "non-nil interface holding pointer",
input: nonNilIface,
wantKind: reflect.Struct,
wantNil: false,
},
{
name: "plain value",
input: testStruct{Field: "xyz"},
wantKind: reflect.Struct,
wantNil: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
v := reflect.ValueOf(tt.input)
got, isNil := indirect(v)
c.Assert(got.Kind(), qt.Equals, tt.wantKind)
c.Assert(isNil, qt.Equals, tt.wantNil)
})
}
}
+34
View File
@@ -136,3 +136,37 @@ func TestSortedStringSlice(t *testing.T) {
c.Assert(s.Count("z"), qt.Equals, 0)
c.Assert(s.Count("a"), qt.Equals, 1)
}
func TestStringSliceToInterfaceSlice(t *testing.T) {
t.Parallel()
c := qt.New(t)
tests := []struct {
name string
in []string
want []any
}{
{
name: "empty slice",
in: []string{},
want: []any{},
},
{
name: "single element",
in: []string{"hello"},
want: []any{"hello"},
},
{
name: "multiple elements",
in: []string{"a", "b", "c"},
want: []any{"a", "b", "c"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := StringSliceToInterfaceSlice(tt.in)
c.Assert(got, qt.DeepEquals, tt.want)
})
}
}
+77
View File
@@ -0,0 +1,77 @@
package collections
import (
"testing"
qt "github.com/frankban/quicktest"
)
func TestNewStack(t *testing.T) {
t.Parallel()
c := qt.New(t)
s := NewStack[int]()
c.Assert(s, qt.IsNotNil)
}
func TestStackBasic(t *testing.T) {
t.Parallel()
c := qt.New(t)
s := NewStack[int]()
c.Assert(s.Len(), qt.Equals, 0)
s.Push(1)
s.Push(2)
s.Push(3)
c.Assert(s.Len(), qt.Equals, 3)
top, ok := s.Peek()
c.Assert(ok, qt.Equals, true)
c.Assert(top, qt.Equals, 3)
popped, ok := s.Pop()
c.Assert(ok, qt.Equals, true)
c.Assert(popped, qt.Equals, 3)
c.Assert(s.Len(), qt.Equals, 2)
_, _ = s.Pop()
_, _ = s.Pop()
_, ok = s.Pop()
c.Assert(ok, qt.Equals, false)
}
func TestStackDrain(t *testing.T) {
t.Parallel()
c := qt.New(t)
s := NewStack[string]()
s.Push("a")
s.Push("b")
got := s.Drain()
c.Assert(got, qt.DeepEquals, []string{"a", "b"})
c.Assert(s.Len(), qt.Equals, 0)
}
func TestStackDrainMatching(t *testing.T) {
t.Parallel()
c := qt.New(t)
s := NewStack[int]()
s.Push(1)
s.Push(2)
s.Push(3)
s.Push(4)
got := s.DrainMatching(func(v int) bool { return v%2 == 0 })
c.Assert(got, qt.DeepEquals, []int{4, 2})
c.Assert(s.Drain(), qt.DeepEquals, []int{1, 3})
}
+1
View File
@@ -24,6 +24,7 @@ const (
WarnRenderShortcodesInHTML = "warning-rendershortcodes-in-html"
WarnGoldmarkRawHTML = "warning-goldmark-raw-html"
WarnPartialSuperfluousPrefix = "warning-partial-superfluous-prefix"
WarnHomePageIsLeafBundle = "warning-home-page-is-leaf-bundle"
)
// Field/method names with special meaning.
-46
View File
@@ -1,46 +0,0 @@
// Copyright 2024 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package hcontext
import "context"
// ContextDispatcher is a generic interface for setting and getting values from a context.
type ContextDispatcher[T any] interface {
Set(ctx context.Context, value T) context.Context
Get(ctx context.Context) T
}
// NewContextDispatcher creates a new ContextDispatcher with the given key.
func NewContextDispatcher[T any, R comparable](key R) ContextDispatcher[T] {
return keyInContext[T, R]{
id: key,
}
}
type keyInContext[T any, R comparable] struct {
zero T
id R
}
func (f keyInContext[T, R]) Get(ctx context.Context) T {
v := ctx.Value(f.id)
if v == nil {
return f.zero
}
return v.(T)
}
func (f keyInContext[T, R]) Set(ctx context.Context, value T) context.Context {
return context.WithValue(ctx, f.id, value)
}
+61
View File
@@ -0,0 +1,61 @@
// Copyright 2025 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package hdebug
import (
"fmt"
"strings"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/htesting"
)
// Printf is a debug print function that should be removed before committing code to the repository.
func Printf(format string, args ...any) {
panicIfRealCI()
if len(args) == 1 && !strings.Contains(format, "%") {
format = format + ": %v"
}
if !strings.HasSuffix(format, "\n") {
format = format + "\n"
}
fmt.Printf(format, args...)
}
func AssertNotNil(a ...any) {
panicIfRealCI()
for _, v := range a {
if types.IsNil(v) {
panic("hdebug.AssertNotNil: value is nil")
}
}
}
func Panicf(format string, args ...any) {
panicIfRealCI()
// fmt.Println(stack())
if len(args) == 1 && !strings.Contains(format, "%") {
format = format + ": %v"
}
if !strings.HasSuffix(format, "\n") {
format = format + "\n"
}
panic(fmt.Sprintf(format, args...))
}
func panicIfRealCI() {
if htesting.IsRealCI() {
panic("This debug statement should be removed before committing code!")
}
}
+9 -10
View File
@@ -110,11 +110,11 @@ func (fe *fileError) UpdateContent(r io.Reader, linematcher LineMatcherFn) FileE
fe.errorContext = ectx
if ectx.Position.LineNumber > 0 {
if ectx.Position.LineNumber > 0 && ectx.Position.LineNumber > fe.position.LineNumber {
fe.position.LineNumber = ectx.Position.LineNumber
}
if ectx.Position.ColumnNumber > 0 {
if ectx.Position.ColumnNumber > 0 && ectx.Position.ColumnNumber > fe.position.ColumnNumber {
fe.position.ColumnNumber = ectx.Position.ColumnNumber
}
@@ -177,6 +177,7 @@ func NewFileErrorFromName(err error, name string) FileError {
// Filetype is used to determine the Chroma lexer to use.
fileType, pos := extractFileTypePos(err)
pos.Filename = name
if fileType == "" {
_, fileType = paths.FileAndExtNoDelimiter(filepath.Clean(name))
}
@@ -234,7 +235,9 @@ func NewFileErrorFromFile(err error, filename string, fs afero.Fs, linematcher L
return NewFileErrorFromName(err, realFilename)
}
defer f.Close()
return NewFileErrorFromName(err, realFilename).UpdateContent(f, linematcher)
fe := NewFileErrorFromName(err, realFilename)
fe = fe.UpdateContent(f, linematcher)
return fe
}
func openFile(filename string, fs afero.Fs) (afero.File, string, error) {
@@ -321,13 +324,9 @@ func extractFileTypePos(err error) (string, text.Position) {
}
// Look in the error message for the line number.
for _, handle := range lineNumberExtractors {
lno, col := handle(err)
if lno > 0 {
pos.ColumnNumber = col
pos.LineNumber = lno
break
}
if lno, col := commonLineNumberExtractor(err); lno > 0 {
pos.ColumnNumber = col
pos.LineNumber = lno
}
if fileType == "" && pos.Filename != "" {
+13 -3
View File
@@ -19,17 +19,27 @@ import (
)
var lineNumberExtractors = []lineNumberExtractor{
// YAML parse errors.
newLineNumberErrHandlerFromRegexp(`\[(\d+):(\d+)\]`),
// Template/shortcode parse errors
newLineNumberErrHandlerFromRegexp(`:(\d+):(\d*):`),
newLineNumberErrHandlerFromRegexp(`:(\d+):`),
// YAML parse errors
newLineNumberErrHandlerFromRegexp(`line (\d+):`),
// i18n bundle errors
newLineNumberErrHandlerFromRegexp(`\((\d+),\s(\d*)`),
}
func commonLineNumberExtractor(e error) (int, int) {
for _, handler := range lineNumberExtractors {
lno, col := handler(e)
if lno > 0 {
return lno, col
}
}
return 0, 0
}
type lineNumberExtractor func(e error) (int, int)
func newLineNumberErrHandlerFromRegexp(expression string) lineNumberExtractor {
@@ -0,0 +1,31 @@
// Copyright 2025 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package herrors
import (
"errors"
"testing"
qt "github.com/frankban/quicktest"
)
func TestCommonLineNumberExtractor(t *testing.T) {
t.Parallel()
c := qt.New(t)
lno, col := commonLineNumberExtractor(errors.New("[4:9] value is not allowed in this context"))
c.Assert(lno, qt.Equals, 4)
c.Assert(col, qt.Equals, 9)
}
+17 -1
View File
@@ -86,6 +86,18 @@ func IsSlice(v any) bool {
var zeroType = reflect.TypeOf((*types.Zeroer)(nil)).Elem()
var isZeroCache sync.Map
func implementsIsZero(tp reflect.Type) bool {
v, ok := isZeroCache.Load(tp)
if ok {
return v.(bool)
}
implements := tp.Implements(zeroType)
isZeroCache.Store(tp, implements)
return implements
}
// IsTruthfulValue returns whether the given value has a meaningful truth value.
// This is based on template.IsTrue in Go's stdlib, but also considers
// IsZero and any interface value will be unwrapped before it's considered
@@ -101,7 +113,11 @@ func IsTruthfulValue(val reflect.Value) (truth bool) {
return
}
if val.Type().Implements(zeroType) {
if val.Kind() == reflect.Pointer && val.IsNil() {
return
}
if implementsIsZero(val.Type()) {
return !val.Interface().(types.Zeroer).IsZero()
}
+33 -5
View File
@@ -22,13 +22,29 @@ import (
qt "github.com/frankban/quicktest"
)
type zeroStruct struct {
zero bool
}
func (z zeroStruct) IsZero() bool {
return z.zero
}
func TestIsTruthful(t *testing.T) {
c := qt.New(t)
var nilpointerZero *zeroStruct
c.Assert(IsTruthful(true), qt.Equals, true)
c.Assert(IsTruthful(false), qt.Equals, false)
c.Assert(IsTruthful(time.Now()), qt.Equals, true)
c.Assert(IsTruthful(time.Time{}), qt.Equals, false)
c.Assert(IsTruthful(&zeroStruct{zero: false}), qt.Equals, true)
c.Assert(IsTruthful(&zeroStruct{zero: true}), qt.Equals, false)
c.Assert(IsTruthful(zeroStruct{zero: false}), qt.Equals, true)
c.Assert(IsTruthful(zeroStruct{zero: true}), qt.Equals, false)
c.Assert(IsTruthful(nil), qt.Equals, false)
c.Assert(IsTruthful(nilpointerZero), qt.Equals, false)
}
func TestGetMethodByName(t *testing.T) {
@@ -90,14 +106,26 @@ func BenchmarkIsContextType(b *testing.B) {
})
}
func BenchmarkIsTruthFul(b *testing.B) {
v := reflect.ValueOf("Hugo")
func BenchmarkIsTruthFulValue(b *testing.B) {
var (
stringHugo = reflect.ValueOf("Hugo")
stringEmpty = reflect.ValueOf("")
zero = reflect.ValueOf(time.Time{})
timeNow = reflect.ValueOf(time.Now())
boolTrue = reflect.ValueOf(true)
boolFalse = reflect.ValueOf(false)
nilPointer = reflect.ValueOf((*zeroStruct)(nil))
)
b.ResetTimer()
for i := 0; i < b.N; i++ {
if !IsTruthfulValue(v) {
b.Fatal("not truthful")
}
IsTruthfulValue(stringHugo)
IsTruthfulValue(stringEmpty)
IsTruthfulValue(zero)
IsTruthfulValue(timeNow)
IsTruthfulValue(boolTrue)
IsTruthfulValue(boolFalse)
IsTruthfulValue(nilPointer)
}
}
+3 -2
View File
@@ -28,12 +28,13 @@ import (
"github.com/bep/logg"
"github.com/bep/godartsass/v2"
"github.com/gohugoio/hugo/common/hcontext"
"github.com/gohugoio/hugo/common/hexec"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/hugofs/files"
"github.com/bep/helpers/contexthelpers"
"github.com/spf13/afero"
iofs "io/fs"
@@ -145,7 +146,7 @@ const (
contextKeyMarkupScope contextKey = iota
)
var markupScope = hcontext.NewContextDispatcher[string](contextKeyMarkupScope)
var markupScope = contexthelpers.NewContextDispatcher[string](contextKeyMarkupScope)
type Context struct{}
+2 -2
View File
@@ -17,7 +17,7 @@ package hugo
// This should be the only one.
var CurrentVersion = Version{
Major: 0,
Minor: 148,
Minor: 152,
PatchLevel: 0,
Suffix: "-DEV",
Suffix: "",
}
+25 -2
View File
@@ -20,13 +20,27 @@ import (
// Cache is a simple thread safe cache backed by a map.
type Cache[K comparable, T any] struct {
m map[K]T
opts CacheOptions
hasBeenInitialized bool
sync.RWMutex
}
// NewCache creates a new Cache.
// CacheOptions are the options for the Cache.
type CacheOptions struct {
// If set, the cache will not grow beyond this size.
Size uint64
}
var defaultCacheOptions = CacheOptions{}
// NewCache creates a new Cache with default options.
func NewCache[K comparable, T any]() *Cache[K, T] {
return &Cache[K, T]{m: make(map[K]T)}
return &Cache[K, T]{m: make(map[K]T), opts: defaultCacheOptions}
}
// NewCacheWithOptions creates a new Cache with the given options.
func NewCacheWithOptions[K comparable, T any](opts CacheOptions) *Cache[K, T] {
return &Cache[K, T]{m: make(map[K]T), opts: opts}
}
// Delete deletes the given key from the cache.
@@ -65,6 +79,7 @@ func (c *Cache[K, T]) GetOrCreate(key K, create func() (T, error)) (T, error) {
if err != nil {
return v, err
}
c.clearIfNeeded()
c.m[key] = v
return v, nil
}
@@ -127,7 +142,15 @@ func (c *Cache[K, T]) SetIfAbsent(key K, value T) {
}
}
func (c *Cache[K, T]) clearIfNeeded() {
if c.opts.Size > 0 && uint64(len(c.m)) >= c.opts.Size {
// clear the map
clear(c.m)
}
}
func (c *Cache[K, T]) set(key K, value T) {
c.clearIfNeeded()
c.m[key] = value
}
+57
View File
@@ -0,0 +1,57 @@
// Copyright 2024 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package maps
import (
"testing"
qt "github.com/frankban/quicktest"
)
func TestCacheSize(t *testing.T) {
c := qt.New(t)
cache := NewCacheWithOptions[string, string](CacheOptions{Size: 10})
for i := 0; i < 30; i++ {
cache.Set(string(rune('a'+i)), "value")
}
c.Assert(len(cache.m), qt.Equals, 10)
for i := 20; i < 50; i++ {
cache.GetOrCreate(string(rune('a'+i)), func() (string, error) {
return "value", nil
})
}
c.Assert(len(cache.m), qt.Equals, 10)
for i := 100; i < 200; i++ {
cache.SetIfAbsent(string(rune('a'+i)), "value")
}
c.Assert(len(cache.m), qt.Equals, 10)
cache.InitAndGet("foo", func(
get func(key string) (string, bool), set func(key string, value string),
) error {
for i := 50; i < 100; i++ {
set(string(rune('a'+i)), "value")
}
return nil
})
c.Assert(len(cache.m), qt.Equals, 10)
}
+43 -4
View File
@@ -14,6 +14,7 @@
package maps
import (
"errors"
"fmt"
"strings"
@@ -40,6 +41,14 @@ func (p Params) GetNested(indices ...string) any {
// SetParams overwrites values in dst with values in src for common or new keys.
// This is done recursively.
func SetParams(dst, src Params) {
setParams(dst, src, 0)
}
func setParams(dst, src Params, depth int) {
const maxDepth = 1000
if depth > maxDepth {
panic(errors.New("max depth exceeded"))
}
for k, v := range src {
vv, found := dst[k]
if !found {
@@ -48,7 +57,7 @@ func SetParams(dst, src Params) {
switch vvv := vv.(type) {
case Params:
if pv, ok := v.(Params); ok {
SetParams(vvv, pv)
setParams(vvv, pv, depth+1)
} else {
dst[k] = v
}
@@ -101,7 +110,6 @@ func (p Params) merge(ps ParamsMergeStrategy, pp Params) {
noUpdate = noUpdate || (ps != "" && ps == ParamsMergeStrategyShallow)
for k, v := range pp {
if k == MergeStrategyKey {
continue
}
@@ -266,9 +274,17 @@ func CleanConfigStringMapString(m map[string]string) map[string]string {
// CleanConfigStringMap is the same as CleanConfigStringMapString but for
// map[string]any.
func CleanConfigStringMap(m map[string]any) map[string]any {
return doCleanConfigStringMap(m, 0)
}
func doCleanConfigStringMap(m map[string]any, depth int) map[string]any {
if len(m) == 0 {
return m
}
const maxDepth = 1000
if depth > maxDepth {
panic(errors.New("max depth exceeded"))
}
if _, found := m[MergeStrategyKey]; !found {
return m
}
@@ -280,9 +296,9 @@ func CleanConfigStringMap(m map[string]any) map[string]any {
}
switch v2 := v.(type) {
case map[string]any:
m2[k] = CleanConfigStringMap(v2)
m2[k] = doCleanConfigStringMap(v2, depth+1)
case Params:
var p Params = CleanConfigStringMap(v2)
var p Params = doCleanConfigStringMap(v2, depth+1)
m2[k] = p
case map[string]string:
m2[k] = CleanConfigStringMapString(v2)
@@ -344,6 +360,29 @@ func PrepareParams(m Params) {
}
}
// CloneParamsDeep does a deep clone of the given Params,
// meaning that any nested Params will be cloned as well.
func CloneParamsDeep(m Params) Params {
return cloneParamsDeep(m, 0)
}
func cloneParamsDeep(m Params, depth int) Params {
const maxDepth = 1000
if depth > maxDepth {
panic(errors.New("max depth exceeded"))
}
m2 := make(Params)
for k, v := range m {
switch vv := v.(type) {
case Params:
m2[k] = cloneParamsDeep(vv, depth+1)
default:
m2[k] = v
}
}
return m2
}
// PrepareParamsClone is like PrepareParams, but it does not modify the input.
func PrepareParamsClone(m Params) Params {
m2 := make(Params)
+19 -13
View File
@@ -120,15 +120,20 @@ func (pp *PathParser) parse(component, s string) (*Path, error) {
return p, nil
}
func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot int) {
func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot, numDots int, isLast bool) {
if p.posContainerHigh != -1 {
return
}
mayHaveLang := p.posIdentifierLanguage == -1 && pp.LanguageIndex != nil
mayHaveLang := numDots > 1 && p.posIdentifierLanguage == -1 && pp.LanguageIndex != nil
mayHaveLang = mayHaveLang && (component == files.ComponentFolderContent || component == files.ComponentFolderLayouts)
mayHaveOutputFormat := component == files.ComponentFolderLayouts
mayHaveKind := p.posIdentifierKind == -1 && mayHaveOutputFormat
mayHaveLayout := component == files.ComponentFolderLayouts
var mayHaveLayout bool
if p.pathType == TypeShortcode {
mayHaveLayout = !isLast && component == files.ComponentFolderLayouts
} else {
mayHaveLayout = component == files.ComponentFolderLayouts
}
var found bool
var high int
@@ -167,7 +172,6 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot i
if langFound {
p.identifiersKnown = append(p.identifiersKnown, id)
p.posIdentifierLanguage = len(p.identifiersKnown) - 1
}
}
@@ -234,19 +238,24 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
p.s = s
slashCount := 0
lastDot := 0
lastSlashIdx := strings.LastIndex(s, "/")
numDots := strings.Count(s[lastSlashIdx+1:], ".")
if strings.Contains(s, "/_shortcodes/") {
p.pathType = TypeShortcode
}
for i := len(s) - 1; i >= 0; i-- {
c := s[i]
switch c {
case '.':
pp.parseIdentifier(component, s, p, i, lastDot)
pp.parseIdentifier(component, s, p, i, lastDot, numDots, false)
lastDot = i
case '/':
slashCount++
if p.posContainerHigh == -1 {
if lastDot > 0 {
pp.parseIdentifier(component, s, p, i, lastDot)
pp.parseIdentifier(component, s, p, i, lastDot, numDots, true)
}
p.posContainerHigh = i + 1
} else if p.posContainerLow == -1 {
@@ -282,10 +291,9 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
p.pathType = TypeContentData
}
}
}
if component == files.ComponentFolderLayouts {
if p.pathType < TypeMarkup && component == files.ComponentFolderLayouts {
if p.posIdentifierBaseof != -1 {
p.pathType = TypeBaseof
} else {
@@ -301,12 +309,10 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
}
if p.pathType == TypeShortcode && p.posIdentifierLayout != -1 {
// myshortcode or myshortcode.html, no layout.
if len(p.identifiersKnown) <= 2 {
id := p.identifiersKnown[p.posIdentifierLayout]
if id.Low == p.posContainerHigh {
// First identifier is shortcode name.
p.posIdentifierLayout = -1
} else {
// First is always the name.
p.posIdentifierLayout--
}
}
+26 -6
View File
@@ -434,12 +434,12 @@ func TestParseLayouts(t *testing.T) {
},
{
"Layout multiple",
"/maylayout.list.section.no.html",
"/mylayout.list.section.no.html",
func(c *qt.C, p *Path) {
c.Assert(p.Layout(), qt.Equals, "maylayout")
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "no", "section", "list", "maylayout"})
c.Assert(p.Layout(), qt.Equals, "mylayout")
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "no", "section", "list", "mylayout"})
c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{})
c.Assert(p.Base(), qt.Equals, "/maylayout.html")
c.Assert(p.Base(), qt.Equals, "/mylayout.html")
c.Assert(p.Lang(), qt.Equals, "no")
},
},
@@ -487,7 +487,8 @@ func TestParseLayouts(t *testing.T) {
func(c *qt.C, p *Path) {
c.Assert(p.Base(), qt.Equals, "/_shortcodes/myshortcode.html")
c.Assert(p.Type(), qt.Equals, TypeShortcode)
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "list", "myshortcode"})
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "list"})
c.Assert(p.Layout(), qt.Equals, "list")
c.Assert(p.PathNoIdentifier(), qt.Equals, "/_shortcodes/myshortcode")
c.Assert(p.PathBeforeLangAndOutputFormatAndExt(), qt.Equals, "/_shortcodes/myshortcode.list")
c.Assert(p.Lang(), qt.Equals, "")
@@ -563,11 +564,30 @@ func TestParseLayouts(t *testing.T) {
c.Assert(p.Type(), qt.Equals, TypePartial)
},
},
{
"Shortcode lang in root",
"/_shortcodes/no.html",
func(c *qt.C, p *Path) {
c.Assert(p.Type(), qt.Equals, TypeShortcode)
c.Assert(p.Lang(), qt.Equals, "")
c.Assert(p.NameNoIdentifier(), qt.Equals, "no")
},
},
{
"Shortcode lang layout",
"/_shortcodes/myshortcode.no.html",
func(c *qt.C, p *Path) {
c.Assert(p.Type(), qt.Equals, TypeShortcode)
c.Assert(p.Lang(), qt.Equals, "no")
c.Assert(p.Layout(), qt.Equals, "")
c.Assert(p.NameNoIdentifier(), qt.Equals, "myshortcode")
},
},
}
for _, test := range tests {
c.Run(test.name, func(c *qt.C) {
if test.name != "Baseof" {
if test.name != "Shortcode lang layout" {
// return
}
test.assert(c, testParser.Parse(files.ComponentFolderLayouts, test.path))
+25 -5
View File
@@ -16,8 +16,8 @@ package terminal
import (
"fmt"
"io"
"os"
"runtime"
"strings"
isatty "github.com/mattn/go-isatty"
@@ -41,10 +41,6 @@ func PrintANSIColors(f *os.File) bool {
// IsTerminal return true if the file descriptor is terminal and the TERM
// environment variable isn't a dumb one.
func IsTerminal(f *os.File) bool {
if runtime.GOOS == "windows" {
return false
}
fd := f.Fd()
return os.Getenv("TERM") != "dumb" && (isatty.IsTerminal(fd) || isatty.IsCygwinTerminal(fd))
}
@@ -77,3 +73,27 @@ func doublePercent(str string) string {
func singlePercent(str string) string {
return strings.Replace(str, "%%", "%", -1)
}
type ProgressState int
const (
ProgressHidden ProgressState = iota
ProgressNormal
ProgressError
ProgressIntermediate
ProgressWarning
)
// ReportProgress writes OSC 9;4 sequence to w.
func ReportProgress(w io.Writer, state ProgressState, progress float64) {
if progress < 0 {
progress = 0.0
}
if progress > 1 {
progress = 1.0
}
pi := int(progress * 100)
fmt.Fprintf(w, "\033]9;4;%d;%d\007", state, pi)
}
+60 -16
View File
@@ -20,6 +20,7 @@ import (
"fmt"
"reflect"
"regexp"
"slices"
"sort"
"strconv"
"strings"
@@ -32,7 +33,6 @@ import (
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/common/urls"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/config/privacy"
@@ -42,6 +42,7 @@ import (
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/hugolib/segments"
"github.com/gohugoio/hugo/langs"
gc "github.com/gohugoio/hugo/markup/goldmark/goldmark_config"
"github.com/gohugoio/hugo/markup/markup_config"
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/minifiers"
@@ -54,8 +55,6 @@ import (
"github.com/gohugoio/hugo/resources/page"
"github.com/gohugoio/hugo/resources/page/pagemeta"
"github.com/spf13/afero"
xmaps "golang.org/x/exp/maps"
)
// InternalConfig is the internal configuration for Hugo, not read from any user provided config file.
@@ -146,7 +145,7 @@ type Config struct {
// The cascade configuration section contains the top level front matter cascade configuration options,
// a slice of page matcher and params to apply to those pages.
Cascade *config.ConfigNamespace[[]page.PageMatcherParamsConfig, *maps.Ordered[page.PageMatcher, maps.Params]] `mapstructure:"-"`
Cascade *config.ConfigNamespace[[]page.PageMatcherParamsConfig, *maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig]] `mapstructure:"-"`
// The segments defines segments for the site. Used for partial/segmented builds.
Segments *config.ConfigNamespace[map[string]segments.SegmentConfig, segments.Segments] `mapstructure:"-"`
@@ -399,7 +398,6 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
hugo.DeprecateWithLogger("site config key paginate", "Use pagination.pagerSize instead.", "v0.128.0", logger.Logger())
c.Pagination.PagerSize = c.Paginate
}
if c.PaginatePath != "" {
hugo.DeprecateWithLogger("site config key paginatePath", "Use pagination.path instead.", "v0.128.0", logger.Logger())
c.Pagination.Path = c.PaginatePath
@@ -410,12 +408,10 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
hugo.DeprecateWithLogger("site 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("site 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("site config key privacy.twitter.simple", "Use privacy.x.simple instead.", "v0.141.0", logger.Logger())
c.Privacy.X.Simple = c.Privacy.Twitter.Simple
@@ -436,6 +432,45 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
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.",
gc.RenderHookUseEmbeddedNever,
gc.RenderHookUseEmbeddedFallback,
)
if c.Markup.Goldmark.RenderHooks.Image.EnableDefault != nil {
alternative := "Use markup.goldmark.renderHooks.image.useEmbedded instead." + " " + alternativeDetails
hugo.DeprecateWithLogger("site config key markup.goldmark.renderHooks.image.enableDefault", alternative, "0.148.0", logger.Logger())
if *c.Markup.Goldmark.RenderHooks.Image.EnableDefault {
c.Markup.Goldmark.RenderHooks.Image.UseEmbedded = gc.RenderHookUseEmbeddedFallback
} else {
c.Markup.Goldmark.RenderHooks.Image.UseEmbedded = gc.RenderHookUseEmbeddedNever
}
}
if c.Markup.Goldmark.RenderHooks.Link.EnableDefault != nil {
alternative := "Use markup.goldmark.renderHooks.link.useEmbedded instead." + " " + alternativeDetails
hugo.DeprecateWithLogger("site config key markup.goldmark.renderHooks.link.enableDefault", alternative, "0.148.0", logger.Logger())
if *c.Markup.Goldmark.RenderHooks.Link.EnableDefault {
c.Markup.Goldmark.RenderHooks.Link.UseEmbedded = gc.RenderHookUseEmbeddedFallback
} else {
c.Markup.Goldmark.RenderHooks.Link.UseEmbedded = gc.RenderHookUseEmbeddedNever
}
}
// Validate render hook configuration.
renderHookUseEmbeddedModes := []string{
gc.RenderHookUseEmbeddedAlways,
gc.RenderHookUseEmbeddedAuto,
gc.RenderHookUseEmbeddedFallback,
gc.RenderHookUseEmbeddedNever,
}
if !slices.Contains(renderHookUseEmbeddedModes, c.Markup.Goldmark.RenderHooks.Image.UseEmbedded) {
return fmt.Errorf("site config markup.goldmark.renderHooks.image must be one of %s", helpers.StringSliceToList(renderHookUseEmbeddedModes, "or"))
}
if !slices.Contains(renderHookUseEmbeddedModes, c.Markup.Goldmark.RenderHooks.Link.UseEmbedded) {
return fmt.Errorf("site config markup.goldmark.renderHooks.link must be one of %s", helpers.StringSliceToList(renderHookUseEmbeddedModes, "or"))
}
c.C = &ConfigCompiled{
Timeout: timeout,
BaseURL: baseURL,
@@ -776,7 +811,7 @@ type Configs struct {
}
func (c *Configs) Validate(logger loggers.Logger) error {
c.Base.Cascade.Config.Range(func(p page.PageMatcher, params maps.Params) bool {
c.Base.Cascade.Config.Range(func(p page.PageMatcher, cfg page.PageMatcherParamsConfig) bool {
page.CheckCascadePattern(logger, p)
return true
})
@@ -1017,6 +1052,7 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
mergedConfig := config.New()
var differentRootKeys []string
switch x := v.(type) {
case nil:
case maps.Params:
_, found := x["params"]
if !found {
@@ -1033,6 +1069,14 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
// baseURL configure don the language level is a multihost setup.
isMultihost = true
}
if p, ok := vv.(maps.Params); ok {
// With the introduction of YAML anchor and alias support, language config entries
// may be contain shared references.
// This also break potential cycles.
vv = maps.CloneParamsDeep(p)
}
mergedConfig.Set(kk, vv)
rootv := cfg.Get(kk)
if rootv != nil && cfg.IsSet(kk) {
@@ -1043,7 +1087,8 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
differentRootKeys = append(differentRootKeys, kk)
// Use the language value as base.
mergedConfigEntry := xmaps.Clone(vvv)
// Note that this is already cloned above.
mergedConfigEntry := vvv
// Merge in the root value.
maps.MergeParams(mergedConfigEntry, rootv.(maps.Params))
@@ -1082,18 +1127,17 @@ func fromLoadConfigResult(fs afero.Fs, logger loggers.Logger, res config.LoadCon
// Adjust Goldmark config defaults for multilingual, single-host sites.
if len(languagesConfig) > 1 && !isMultihost && !clone.Markup.Goldmark.DuplicateResourceFiles {
if !clone.Markup.Goldmark.DuplicateResourceFiles {
if clone.Markup.Goldmark.RenderHooks.Link.EnableDefault == nil {
clone.Markup.Goldmark.RenderHooks.Link.EnableDefault = types.NewBool(true)
}
if clone.Markup.Goldmark.RenderHooks.Image.EnableDefault == nil {
clone.Markup.Goldmark.RenderHooks.Image.EnableDefault = types.NewBool(true)
}
if clone.Markup.Goldmark.RenderHooks.Image.UseEmbedded == gc.RenderHookUseEmbeddedAuto {
clone.Markup.Goldmark.RenderHooks.Image.UseEmbedded = gc.RenderHookUseEmbeddedFallback
}
if clone.Markup.Goldmark.RenderHooks.Link.UseEmbedded == gc.RenderHookUseEmbeddedAuto {
clone.Markup.Goldmark.RenderHooks.Link.UseEmbedded = gc.RenderHookUseEmbeddedFallback
}
}
langConfigMap[k] = clone
case maps.ParamsMergeStrategy:
default:
panic(fmt.Sprintf("unknown type in languages config: %T", v))
@@ -2,12 +2,14 @@ package allconfig_test
import (
"path/filepath"
"strings"
"testing"
qt "github.com/frankban/quicktest"
"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"
)
@@ -357,3 +359,50 @@ All.
b.Assert(b.H.Conf.DefaultContentLanguage(), qt.Equals, "sv")
}
func TestDefaultConfigEnvDisableLanguagesIssue13707(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableLanguages = []
[languages]
[languages.en]
weight = 1
[languages.nn]
weight = 2
[languages.sv]
weight = 3
`
b := hugolib.Test(t, files, hugolib.TestOptWithConfig(func(conf *hugolib.IntegrationTestConfig) {
conf.Environ = []string{`HUGO_DISABLELANGUAGES=sv nn`}
}))
b.Assert(len(b.H.Sites), qt.Equals, 1)
}
// Issue 13535
// We changed enablement of the embedded link and image render hooks from
// booleans to enums in v0.148.0.
func TestLegacyEmbeddedRenderHookEnablement(t *testing.T) {
files := `
-- hugo.toml --
[markup.goldmark.renderHooks.image]
#KEY_VALUE
[markup.goldmark.renderHooks.link]
#KEY_VALUE
`
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)
}
+1 -1
View File
@@ -330,7 +330,7 @@ var allDecoderSetups = map[string]decodeWeight{
key: "cascade",
decode: func(d decodeWeight, p decodeConfig) error {
var err error
p.c.Cascade, err = page.DecodeCascadeConfig(nil, p.p.Get(d.key))
p.c.Cascade, err = page.DecodeCascadeConfig(nil, true, p.p.Get(d.key))
return err
},
},
+66 -35
View File
@@ -40,7 +40,13 @@ import (
//lint:ignore ST1005 end user message.
var ErrNoConfigFile = errors.New("Unable to locate config file or config directory. Perhaps you need to create a new site.\n Run `hugo help new` for details.\n")
func LoadConfig(d ConfigSourceDescriptor) (*Configs, error) {
func LoadConfig(d ConfigSourceDescriptor) (configs *Configs, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("failed to load config: %v", r)
}
}()
if len(d.Environ) == 0 && !hugo.IsRunningAsTest() {
d.Environ = os.Environ()
}
@@ -59,7 +65,7 @@ func LoadConfig(d ConfigSourceDescriptor) (*Configs, error) {
return nil, fmt.Errorf("failed to load config: %w", err)
}
configs, err := fromLoadConfigResult(d.Fs, d.Logger, res)
configs, err = fromLoadConfigResult(d.Fs, d.Logger, res)
if err != nil {
return nil, fmt.Errorf("failed to create config from result: %w", err)
}
@@ -93,7 +99,7 @@ func LoadConfig(d ConfigSourceDescriptor) (*Configs, error) {
loggers.SetGlobalLogger(d.Logger)
return configs, nil
return
}
// ConfigSourceDescriptor describes where to find the config (e.g. config.toml etc.).
@@ -170,10 +176,16 @@ func (l configLoader) applyDefaultConfig() error {
}
func (l configLoader) normalizeCfg(cfg config.Provider) error {
if b, ok := cfg.Get("minifyOutput").(bool); ok && b {
cfg.Set("minify.minifyOutput", true)
} else if b, ok := cfg.Get("minify").(bool); ok && b {
cfg.Set("minify", maps.Params{"minifyOutput": true})
if b, ok := cfg.Get("minifyOutput").(bool); ok {
hugo.Deprecate("site config minifyOutput", "Use minify.minifyOutput instead.", "v0.150.0")
if b {
cfg.Set("minify.minifyOutput", true)
}
} else if b, ok := cfg.Get("minify").(bool); ok {
hugo.Deprecate("site config minify", "Use minify.minifyOutput instead.", "v0.150.0")
if b {
cfg.Set("minify", maps.Params{"minifyOutput": true})
}
}
return nil
@@ -233,43 +245,61 @@ func (l configLoader) applyOsEnvOverrides(environ []string) error {
if existing != nil {
val, err := metadecoders.Default.UnmarshalStringTo(env.Value, existing)
if err != nil {
if err == nil {
val = l.envValToVal(env.Key, val)
if owner != nil {
owner[nestedKey] = val
} else {
l.cfg.Set(env.Key, val)
}
continue
}
if owner != nil {
owner[nestedKey] = val
} else {
l.cfg.Set(env.Key, val)
}
} else {
if nestedKey != "" {
owner[nestedKey] = env.Value
} else {
var val any
key := strings.ReplaceAll(env.Key, delim, ".")
_, ok := allDecoderSetups[key]
if ok {
// A map.
if v, err := metadecoders.Default.UnmarshalStringTo(env.Value, map[string]any{}); err == nil {
val = v
}
}
if val == nil {
// A string.
val = l.envStringToVal(key, env.Value)
}
l.cfg.Set(key, val)
}
}
if owner != nil && nestedKey != "" {
owner[nestedKey] = env.Value
} else {
var val any
key := strings.ReplaceAll(env.Key, delim, ".")
_, ok := allDecoderSetups[key]
if ok {
// A map.
if v, err := metadecoders.Default.UnmarshalStringTo(env.Value, map[string]any{}); err == nil {
val = v
}
}
if val == nil {
// A string.
val = l.envStringToVal(key, env.Value)
}
l.cfg.Set(key, val)
}
}
return nil
}
func (l *configLoader) envValToVal(k string, v any) any {
switch v := v.(type) {
case string:
return l.envStringToVal(k, v)
default:
return v
}
}
func (l *configLoader) envStringToVal(k, v string) any {
switch k {
case "disablekinds", "disablelanguages":
case "disablekinds", "disablelanguages", "ignorefiles", "ignorelogs":
v = strings.TrimSpace(v)
if strings.HasPrefix(v, "[") && strings.HasSuffix(v, "]") {
if parsed, err := metadecoders.Default.UnmarshalStringTo(v, []any{}); err == nil {
return parsed
}
}
if strings.Contains(v, ",") {
return strings.Split(v, ",")
} else {
@@ -514,11 +544,12 @@ func (l configLoader) loadConfig(configName string) (string, error) {
return filename, nil
}
func (l configLoader) deleteMergeStrategies() {
func (l configLoader) deleteMergeStrategies() (err error) {
l.cfg.WalkParams(func(params ...maps.KeyParams) bool {
params[len(params)-1].Params.DeleteMergeStrategy()
return false
})
return
}
func (l configLoader) wrapFileError(err error, filename string) error {
+11
View File
@@ -14,6 +14,7 @@
package config
import (
"regexp"
"strings"
"testing"
@@ -32,3 +33,13 @@ func TestIsValidConfigFileName(t *testing.T) {
c.Assert(IsValidConfigFilename(""), qt.Equals, false)
c.Assert(IsValidConfigFilename("config.toml.swp"), qt.Equals, false)
}
func TestFromTOMLConfigString(t *testing.T) {
c := qt.New(t)
c.Assert(
func() { FromTOMLConfigString("cfg") },
qt.PanicMatches,
regexp.MustCompile("_stream.toml:.*"),
)
}
+12 -6
View File
@@ -14,11 +14,13 @@
package config
import (
"errors"
"fmt"
"slices"
"strings"
"sync"
xmaps "golang.org/x/exp/maps"
xmaps "maps"
"github.com/spf13/cast"
@@ -237,12 +239,16 @@ func (c *defaultConfigProvider) Merge(k string, v any) {
func (c *defaultConfigProvider) Keys() []string {
c.mu.RLock()
defer c.mu.RUnlock()
return xmaps.Keys(c.root)
return slices.Collect(xmaps.Keys(c.root))
}
func (c *defaultConfigProvider) WalkParams(walkFn func(params ...maps.KeyParams) bool) {
var walk func(params ...maps.KeyParams)
walk = func(params ...maps.KeyParams) {
maxDepth := 1000
var walk func(depth int, params ...maps.KeyParams)
walk = func(depth int, params ...maps.KeyParams) {
if depth > maxDepth {
panic(errors.New("max depth exceeded"))
}
if walkFn(params...) {
return
}
@@ -253,11 +259,11 @@ func (c *defaultConfigProvider) WalkParams(walkFn func(params ...maps.KeyParams)
paramsplus1 := make([]maps.KeyParams, i+1)
copy(paramsplus1, params)
paramsplus1[i] = maps.KeyParams{Key: k, Params: p2}
walk(paramsplus1...)
walk(depth+1, paramsplus1...)
}
}
}
walk(maps.KeyParams{Key: "", Params: c.root})
walk(0, maps.KeyParams{Key: "", Params: c.root})
}
func (c *defaultConfigProvider) determineMergeStrategy(params ...maps.KeyParams) maps.ParamsMergeStrategy {
+85
View File
@@ -17,6 +17,7 @@ import (
"context"
"errors"
"fmt"
"slices"
"strconv"
"strings"
"testing"
@@ -353,6 +354,90 @@ func TestDefaultConfigProvider(t *testing.T) {
c.Assert(r.Wait(), qt.IsNil)
})
c.Run("GetBool", func(c *qt.C) {
cfg := New()
var k string
var v bool
k, v = "foo", true
cfg.Set(k, v)
c.Assert(cfg.Get(k), qt.Equals, v)
c.Assert(cfg.GetBool(k), qt.Equals, v)
})
c.Run("GetParams", func(c *qt.C) {
cfg := New()
k := "foo"
cfg.Set(k, maps.Params{k: true})
c.Assert(cfg.GetParams(k), qt.DeepEquals, maps.Params{
k: true,
})
c.Assert(cfg.GetParams("bar"), qt.IsNil)
})
c.Run("Keys", func(c *qt.C) {
cfg := New()
k := "foo"
k2 := "bar"
cfg.Set(k, maps.Params{k: struct{}{}})
cfg.Set(k2, maps.Params{k2: struct{}{}})
c.Assert(len(cfg.Keys()), qt.Equals, 2)
got := cfg.Keys()
slices.Sort(got)
want := []string{k, k2}
slices.Sort(want)
c.Assert(got, qt.DeepEquals, want)
})
c.Run("WalkParams", func(c *qt.C) {
cfg := New()
cfg.Set("x", maps.Params{})
cfg.Set("y", maps.Params{})
var got []string
cfg.WalkParams(func(params ...maps.KeyParams) bool {
got = append(got, params[len(params)-1].Key)
return false
})
want := []string{"", "x", "y"}
slices.Sort(got)
slices.Sort(want)
c.Assert(got, qt.DeepEquals, want)
cfg = New()
cfg.WalkParams(func(params ...maps.KeyParams) bool {
return true
})
got = []string{""}
want = []string{""}
c.Assert(got, qt.DeepEquals, want)
})
c.Run("SetDefaults", func(c *qt.C) {
cfg := New()
cfg.SetDefaults(maps.Params{
"foo": "bar",
"bar": "baz",
})
c.Assert(cfg.Get("foo"), qt.Equals, "bar")
c.Assert(cfg.Get("bar"), qt.Equals, "baz")
})
}
func BenchmarkDefaultConfigProvider(b *testing.B) {
+1 -1
View File
@@ -44,7 +44,7 @@ var DefaultConfig = Config{
),
// These have been tested to work with Hugo's external programs
// on Windows, Linux and MacOS.
OsEnv: MustNewWhitelist(`(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE)$`),
OsEnv: MustNewWhitelist(`(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE|PROGRAMDATA)$`),
},
Funcs: Funcs{
Getenv: MustNewWhitelist("^HUGO_", "^CI$"),
+1 -1
View File
@@ -135,7 +135,7 @@ func TestToTOML(t *testing.T) {
got := DefaultConfig.ToTOML()
c.Assert(got, qt.Equals,
"[security]\n enableInlineShortcodes = false\n\n [security.exec]\n allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^git$', '^npx$', '^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)$']\n\n [security.funcs]\n getenv = ['^HUGO_', '^CI$']\n\n [security.http]\n methods = ['(?i)GET|POST']\n urls = ['.*']",
"[security]\n enableInlineShortcodes = false\n\n [security.exec]\n allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^git$', '^npx$', '^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 = ['.*']",
)
}
+4 -2
View File
@@ -1,7 +1,9 @@
{{ define "main" }}
{{ .Content }}
{{ range site.RegularPages }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ .Summary }}
<section>
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ .Summary }}
</section>
{{ end }}
{{ end }}
+4 -2
View File
@@ -2,7 +2,9 @@
<h1>{{ .Title }}</h1>
{{ .Content }}
{{ range .Pages }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ .Summary }}
<section>
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ .Summary }}
</section>
{{ end }}
{{ end }}
+49 -34
View File
@@ -36,6 +36,7 @@ import (
"github.com/dustin/go-humanize"
"github.com/gobwas/glob"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/para"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/deploy/deployconfig"
"github.com/gohugoio/hugo/media"
@@ -487,7 +488,12 @@ func knownHiddenDirectory(name string) bool {
// walkLocal walks the source directory and returns a flat list of files,
// using localFile.SlashPath as the map keys.
func (d *Deployer) walkLocal(fs afero.Fs, matchers []*deployconfig.Matcher, include, exclude glob.Glob, mediaTypes media.Types, mappath func(string) string) (map[string]*localFile, error) {
retval := map[string]*localFile{}
retval := make(map[string]*localFile)
var mu sync.Mutex
workers := para.New(d.cfg.Workers)
g, _ := workers.Start(context.Background())
err := afero.Walk(fs, "", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
@@ -508,45 +514,54 @@ func (d *Deployer) walkLocal(fs afero.Fs, matchers []*deployconfig.Matcher, incl
return nil
}
// When a file system is HFS+, its filepath is in NFD form.
if runtime.GOOS == "darwin" {
path = norm.NFC.String(path)
}
// Check include/exclude matchers.
slashpath := filepath.ToSlash(path)
if include != nil && !include.Match(slashpath) {
d.logger.Infof(" dropping %q due to include\n", slashpath)
return nil
}
if exclude != nil && exclude.Match(slashpath) {
d.logger.Infof(" dropping %q due to exclude\n", slashpath)
return nil
}
// Find the first matching matcher (if any).
var m *deployconfig.Matcher
for _, cur := range matchers {
if cur.Matches(slashpath) {
m = cur
break
// Process each file in a worker
g.Run(func() error {
// When a file system is HFS+, its filepath is in NFD form.
if runtime.GOOS == "darwin" {
path = norm.NFC.String(path)
}
}
// Apply any additional modifications to the local path, to map it to
// the remote path.
if mappath != nil {
slashpath = mappath(slashpath)
}
lf, err := newLocalFile(fs, path, slashpath, m, mediaTypes)
if err != nil {
return err
}
retval[lf.SlashPath] = lf
// Check include/exclude matchers.
slashpath := filepath.ToSlash(path)
if include != nil && !include.Match(slashpath) {
d.logger.Infof(" dropping %q due to include\n", slashpath)
return nil
}
if exclude != nil && exclude.Match(slashpath) {
d.logger.Infof(" dropping %q due to exclude\n", slashpath)
return nil
}
// Find the first matching matcher (if any).
var m *deployconfig.Matcher
for _, cur := range matchers {
if cur.Matches(slashpath) {
m = cur
break
}
}
// Apply any additional modifications to the local path, to map it to
// the remote path.
if mappath != nil {
slashpath = mappath(slashpath)
}
lf, err := newLocalFile(fs, path, slashpath, m, mediaTypes)
if err != nil {
return err
}
mu.Lock()
retval[lf.SlashPath] = lf
mu.Unlock()
return nil
})
return nil
})
if err != nil {
return nil, err
}
if err := g.Wait(); err != nil {
return nil, err
}
return retval, nil
}
+7 -6
View File
@@ -623,7 +623,7 @@ func TestEndToEndSync(t *testing.T) {
localFs: test.fs,
bucket: test.bucket,
mediaTypes: media.DefaultTypes,
cfg: deployconfig.DeployConfig{MaxDeletes: -1},
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1},
}
// Initial deployment should sync remote with local.
@@ -706,7 +706,7 @@ func TestMaxDeletes(t *testing.T) {
localFs: test.fs,
bucket: test.bucket,
mediaTypes: media.DefaultTypes,
cfg: deployconfig.DeployConfig{MaxDeletes: -1},
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1},
}
// Sync remote with local.
@@ -836,7 +836,7 @@ func TestIncludeExclude(t *testing.T) {
}
deployer := &Deployer{
localFs: fsTest.fs,
cfg: deployconfig.DeployConfig{MaxDeletes: -1}, bucket: fsTest.bucket,
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1}, bucket: fsTest.bucket,
target: tgt,
mediaTypes: media.DefaultTypes,
}
@@ -893,7 +893,7 @@ func TestIncludeExcludeRemoteDelete(t *testing.T) {
}
deployer := &Deployer{
localFs: fsTest.fs,
cfg: deployconfig.DeployConfig{MaxDeletes: -1}, bucket: fsTest.bucket,
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1}, bucket: fsTest.bucket,
mediaTypes: media.DefaultTypes,
}
@@ -945,7 +945,7 @@ func TestCompression(t *testing.T) {
deployer := &Deployer{
localFs: test.fs,
bucket: test.bucket,
cfg: deployconfig.DeployConfig{MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: ".*", Gzip: true, Re: regexp.MustCompile(".*")}}},
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: ".*", Gzip: true, Re: regexp.MustCompile(".*")}}},
mediaTypes: media.DefaultTypes,
}
@@ -1000,7 +1000,7 @@ func TestMatching(t *testing.T) {
deployer := &Deployer{
localFs: test.fs,
bucket: test.bucket,
cfg: deployconfig.DeployConfig{MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: "^subdir/aaa$", Force: true, Re: regexp.MustCompile("^subdir/aaa$")}}},
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: "^subdir/aaa$", Force: true, Re: regexp.MustCompile("^subdir/aaa$")}}},
mediaTypes: media.DefaultTypes,
}
@@ -1097,5 +1097,6 @@ func verifyRemote(ctx context.Context, bucket *blob.Bucket, local []*fileData) (
func newDeployer() *Deployer {
return &Deployer{
logger: loggers.NewDefault(),
cfg: deployconfig.DeployConfig{Workers: 2},
}
}
+2 -2
View File
@@ -4,10 +4,10 @@
[codespell]
# Comma separated list of dirs to be skipped.
skip = _vendor,.cspell.json,chroma.css,chroma_dark.css
skip = *.ai,chroma.css,chroma_dark.css,.cspell.json
# Comma separated list of words to be ignored. Words must be lowercased.
ignore-words-list = abl,edn,te,ue,trys,januar,womens,crossreferences
ignore-words-list = abl,edn,januar,te,trys,ue,womens
# Check file names as well.
check-filenames = true
+14 -2
View File
@@ -1,8 +1,15 @@
{
"version": "0.2",
"allowCompoundWords": true,
"files": [
"**/*.md"
"overrides": [
{
"filename": "**/*",
"enabled": false
},
{
"filename": "**/*.md",
"enabled": true
}
],
"flagWords": [
"alot",
@@ -64,12 +71,14 @@
"templating",
"transpile",
"unmarshal",
"unmarshaled",
"unmarshaling",
"unmarshals",
"# ----------------------------------------------------------------------",
"# cspell: ignore hugo terminology",
"# ----------------------------------------------------------------------",
"alignx",
"aligny",
"attrlink",
"canonify",
"codeowners",
@@ -99,6 +108,8 @@
"descripción",
"dokumentation",
"erklärungen",
"español",
"français",
"libros",
"mercredi",
"miesiąc",
@@ -146,6 +157,7 @@
"dpkg",
"doas",
"eopkg",
"forgejo",
"gitee",
"goldmark",
"katex",
-22
View File
@@ -1,22 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 120
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 30
# Issues with these labels will never be considered stale
exemptLabels:
- Keep
- Security
- UndocumentedFeature
# Label to use when marking an issue as stale
staleLabel: Stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. The resources of the Hugo team are limited, and so we are asking for your help.
If you still think this is important, please tell us why.
This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
+1 -1
View File
@@ -15,7 +15,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v5
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
+15
View File
@@ -0,0 +1,15 @@
name: Lint markdown
on:
workflow_dispatch:
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v5
- name: Run Markdown linter
uses: DavidAnson/markdownlint-cli2-action@v20
with:
globs: # set to null to override default of *.{md,markdown}
continue-on-error: false
+5 -7
View File
@@ -12,16 +12,14 @@ jobs:
spellcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: streetsidesoftware/cspell-action@v5
- uses: actions/checkout@v5
- uses: streetsidesoftware/cspell-action@v7
with:
check_dot_files: false
files: content/**/*.md
incremental_files_only: true
inline: warning
strict: false
strict: true
# cspell uses the .cspell.json configuration file
- uses: codespell-project/actions-codespell@v2
with:
check_filenames: true
check_hidden: true
# by default, codespell uses configuration from the .codespellrc
# codespell uses the .codespellrc file
+32
View File
@@ -0,0 +1,32 @@
name: Close stale issues and pull requests
on:
workflow_dispatch:
schedule:
- cron: "30 1 * * *"
permissions:
contents: read
jobs:
stale:
permissions:
contents: read
issues: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
days-before-stale: 90 # default is 60
days-before-close: 14 # default is 7
exempt-all-assignees: true
exempt-draft-pr: true
exempt-issue-labels: Keep, InProgress, NeedsTriage
exempt-pr-labels: Keep
operations-per-run: 100
stale-issue-message: >
This issue has been marked as stale because there hasn't been any
recent activity. It will be closed soon if there are no further
updates.
stale-pr-message: >
This pull request has been marked as stale because there hasn't
been any recent activity. It will be closed soon if there are no
further updates.
-41
View File
@@ -1,41 +0,0 @@
name: Super Linter
on:
workflow_dispatch:
permissions:
contents: read # to fetch code (actions/checkout)
jobs:
build:
permissions:
contents: read # to fetch code (actions/checkout)
statuses: write # to mark status of each linter run (github/super-linter/slim)
name: Lint Code Base
runs-on: ubuntu-latest
if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Lint Code Base
uses: super-linter/super-linter/slim@v6
env:
DEFAULT_BRANCH: master
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
IGNORE_GITIGNORED_FILES: true
LINTER_RULES_PATH: /
LOG_LEVEL: NOTICE
MARKDOWN_CONFIG_FILE: .markdownlint.yaml
SUPPRESS_POSSUM: true
VALIDATE_CSS: false
VALIDATE_EDITORCONFIG: false
VALIDATE_GITLEAKS: false
VALIDATE_HTML: false
VALIDATE_JAVASCRIPT_STANDARD: false
VALIDATE_JSCPD: false
VALIDATE_NATURAL_LANGUAGE: false
VALIDATE_SHELL_SHFMT: false
VALIDATE_XML: false
+91
View File
@@ -0,0 +1,91 @@
# Glob patterns to include
globs:
- "content/**/*.md"
# Glob patterns to exclude
ignores:
- "content/**/commands/**"
- "content/en/about/license.md"
- "content/LICENSE.md"
# Markdownlint rules and configuration
# https://github.com/DavidAnson/markdownlint?tab=readme-ov-file#rules--aliases
config:
MD001: true
# MD002 deprecated
MD003:
style: atx
MD004:
style: dash
MD005: true
# MD006 deprecated
MD007: false # if enabled, throws errors when definition descriptions contain list items
# MD008 deprecated
MD009: true
MD010: true
MD011: true
MD012: true
MD013: false
MD014: true
# MD015 deprecated
# MD016 deprecated
# MD017 deprecated
MD018: true
MD019: true
MD020: true
MD021: true
MD022: true
MD023: true
MD024: true
MD025: true
MD026: true
MD027: true
MD028: false
MD029:
style: one
MD030: true
MD031: true
MD032: true
MD033: true
MD034: false
MD035:
style: ---
MD036: true
MD037: true
MD038: true
MD039: true
MD040: true
MD041: false
MD042: true
MD043: false
MD044: false
MD045: true
MD046: false
MD047: true
MD048:
style: backtick
MD049:
style: underscore
MD050:
style: asterisk
MD051: false
MD052: true
MD053: true
MD054:
autolink: true
collapsed: true
full: true
inline: true
shortcut: true
url_inline: true
MD055:
style: consistent
MD056: true
# MD057 deprecated
MD058: true
MD059:
prohibited_texts:
- click here
- here
- link
- more
-27
View File
@@ -1,27 +0,0 @@
# https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md
MD001: false
MD002: false
MD003: false
MD004: false
MD007: false
MD012:
maximum: 2
MD013: false
MD014: false
MD022: false
MD024: false
MD031: false
MD032: false
MD033: false
MD034: false
MD036: false
MD037: false
MD038: false
MD041: false
MD046: false
MD049: false
MD050: false
MD051: false
MD053: false
MD055: false
-6
View File
@@ -1,6 +0,0 @@
**/commands/**
**/functions/**
**/news/**
**/showcase/**
**/zh/**
**/license.md
+8 -8
View File
@@ -2,16 +2,16 @@
**/icons.html
# These are whitespace sensitive.
layouts/_default/_markup/render-code*
layouts/_default/_markup/render-table*
layouts/shortcodes/glossary-term.html
layouts/shortcodes/glossary.html
layouts/shortcodes/highlighting-styles.html
layouts/shortcodes/list-pages-in-section.html
layouts/shortcodes/quick-reference.html
layouts/_markup/render-code*
layouts/_markup/render-table*
layouts/_shortcodes/glossary-term.html
layouts/_shortcodes/glossary.html
layouts/_shortcodes/highlighting-styles.html
layouts/_shortcodes/list-pages-in-section.html
layouts/_shortcodes/quick-reference.html
# No root node.
layouts/partials/layouts/head/head.html
layouts/_partials/layouts/head/head.html
# Auto generated.
assets/css/components/chroma*.css
+100
View File
@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 299 118" height="100%" width="100%" style="enable-background:new 0 0 299 118;" xml:space="preserve">
<style type="text/css">
.st0{clip-path:url(#SVGID_2_);}
.st1{fill:#414141;}
.st2{fill:#3D4DF4;}
</style>
<g>
<defs>
<rect id="SVGID_1_" x="0.4" y="0" width="66.5" height="67.8"/>
</defs>
<clipPath id="SVGID_2_">
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
</clipPath>
<g class="st0">
<path class="st1" d="M34.2,28l31.4,18.3c0.9,0.5,1.1,1.6,0.6,2.4c-0.2,0.3-0.4,0.5-0.6,0.6L35.6,66.9c-1.4,0.8-3.1,0.8-4.5,0
L1.3,49.6c-0.9-0.5-1.1-1.6-0.6-2.4c0.2-0.3,0.4-0.5,0.6-0.6l23-13.4l7.9,13.6c0.5,0.8,1.5,1.1,2.4,0.7l0.1,0l0.1,0
c0.6-0.4,0.9-1.2,0.7-2l-5-15.7l2.5-1.5C33.3,27.8,33.8,27.8,34.2,28z M36,58.6c-1.4-0.8-3.9-0.7-5.5,0.3l-3,1.7l7,4.1l2-1.2
l-2-1.1l1-0.6C37.1,60.9,37.3,59.4,36,58.6z M32.1,59.9c0.6-0.3,1.4-0.4,1.8-0.1c0.5,0.3,0.4,0.7-0.2,1.1l-1,0.6l-1.7-1L32.1,59.9
z M36.2,55.6l-2,1.2l7,4.1l2-1.2L36.2,55.6z M42.6,51.9l-2,1.2l2.9,1.7l-4.5-0.8L37,55.1l7,4.1l2-1.2L43,56.3l4.5,0.8l2.1-1.2
L42.6,51.9z M56.3,43.8l-6,3.5l2.5,1.4l-3.7-0.7L47,49.3l2.9,1.7l-4.5-0.8l-2.1,1.2l7,4.1l2-1.2l-2.9-1.7l4.5,0.8l2.1-1.2
l-2.9-1.7l4,0.7l0.2,0.1l2-1.2l4-2.3l-1.7-1l-4,2.3l-1-0.6l4-2.3l-1.7-1l-4,2.3L54,47.1l4-2.3L56.3,43.8z"/>
<path class="st2" d="M41.7,0c0.1,0,0.2,0,0.3,0c1,0.2,1.6,1.1,1.5,2.1l-2.3,13.5c3.9,2.5,6.5,6.9,6.5,11.9v0.7l-10.3,0l-2,17.9
c-0.1,0.8-0.7,1.4-1.5,1.5l-0.1,0c-1,0.1-1.9-0.6-2-1.5l-2-17.9H19.6v-0.7c0-5,2.6-9.4,6.5-11.9L23.8,2.1c0-0.1,0-0.2,0-0.3
c0-1,0.8-1.8,1.8-1.8H41.7z"/>
</g>
</g>
<path class="st1" d="M277.4,61c-3.7,0-7.1-0.8-10-2.4c-2.8-1.6-5.1-3.9-6.7-6.8c-1.6-2.9-2.4-6.4-2.4-10.3v-0.9
c0-4,0.8-7.4,2.4-10.3c1.6-2.9,3.8-5.2,6.6-6.8c2.8-1.6,6.1-2.4,9.9-2.4c3.7,0,6.9,0.8,9.7,2.5c2.7,1.6,4.9,3.9,6.4,6.8
c1.5,2.9,2.3,6.3,2.3,10.1v3.3h-27.4c0.1,2.6,1.1,4.7,2.9,6.3c1.8,1.6,4.1,2.4,6.7,2.4c2.7,0,4.7-0.6,5.9-1.7
c1.3-1.2,2.2-2.5,2.9-3.9l7.8,4.1c-0.7,1.3-1.7,2.8-3.1,4.3c-1.3,1.5-3.1,2.8-5.3,4C283.6,60.5,280.8,61,277.4,61z M268.2,36.8h17.6
c-0.2-2.2-1.1-3.9-2.7-5.2c-1.5-1.3-3.5-2-6-2c-2.6,0-4.6,0.7-6.2,2C269.5,32.9,268.5,34.6,268.2,36.8z"/>
<path class="st1" d="M192.9,60V6.8h18.6l9.2,46.4h1.4l9.2-46.4h18.6V60h-9.7V14.1h-1.4L229.6,60h-16.6L204,14.1h-1.4V60H192.9z"/>
<path class="st1" d="M146.3,60V22.3h9.4v4.9h1.4c0.6-1.3,1.7-2.6,3.4-3.7c1.7-1.2,4.2-1.8,7.6-1.8c2.9,0,5.5,0.7,7.7,2.1
c2.2,1.3,4,3.2,5.2,5.5c1.2,2.3,1.8,5.1,1.8,8.2V60h-9.6V38.2c0-2.8-0.7-5-2.1-6.4c-1.4-1.4-3.3-2.1-5.9-2.1c-2.9,0-5.2,1-6.8,3
c-1.6,1.9-2.4,4.6-2.4,8.1V60H146.3z"/>
<path class="st1" d="M126.1,60V22.3h9.6V60H126.1z M130.9,17.9c-1.7,0-3.2-0.6-4.4-1.7c-1.2-1.1-1.7-2.6-1.7-4.4
c0-1.8,0.6-3.3,1.7-4.4c1.2-1.1,2.7-1.7,4.4-1.7c1.8,0,3.2,0.6,4.4,1.7c1.2,1.1,1.7,2.6,1.7,4.4c0,1.8-0.6,3.3-1.7,4.4
C134.2,17.3,132.7,17.9,130.9,17.9z"/>
<path class="st1" d="M79.9,60V6.8h21.9c3.3,0,6.3,0.7,8.8,2.1c2.6,1.3,4.6,3.2,6,5.6c1.5,2.4,2.2,5.3,2.2,8.7v1.1
c0,3.3-0.8,6.2-2.3,8.7c-1.5,2.4-3.5,4.3-6.1,5.7c-2.5,1.3-5.4,2-8.7,2H89.9V60H79.9z M89.9,31.4h10.9c2.4,0,4.3-0.7,5.8-2
c1.5-1.3,2.2-3.1,2.2-5.4v-0.8c0-2.3-0.7-4.1-2.2-5.4c-1.5-1.3-3.4-2-5.8-2H89.9V31.4z"/>
<path class="st2" d="M285.3,112V91h13.5v3.6h-9.5v5h8.7v3.6h-8.7v5.2h9.7v3.6H285.3z"/>
<path class="st2" d="M268.7,112V91h13.5v3.6h-9.5v5h8.7v3.6h-8.7v5.2h9.7v3.6H268.7z"/>
<path class="st2" d="M249.7,112V91h9.1c1.3,0,2.5,0.2,3.4,0.7c1,0.5,1.7,1.1,2.3,1.9c0.5,0.8,0.8,1.8,0.8,3v0.4
c0,1.3-0.3,2.3-0.9,3.1c-0.6,0.8-1.3,1.4-2.2,1.7v0.5c0.8,0,1.4,0.3,1.9,0.8c0.4,0.5,0.7,1.2,0.7,2v6.9h-4v-6.3
c0-0.5-0.1-0.9-0.4-1.2c-0.2-0.3-0.6-0.4-1.2-0.4h-5.5v7.9H249.7z M253.7,100.4h4.7c0.9,0,1.7-0.2,2.2-0.8c0.5-0.5,0.8-1.2,0.8-2
v-0.3c0-0.8-0.3-1.5-0.8-2c-0.5-0.5-1.3-0.8-2.2-0.8h-4.7V100.4z"/>
<path class="st2" d="M233.7,112V91h13.2v3.6h-9.2v5.1h8.5v3.6h-8.5v8.7H233.7z"/>
<path class="st1" d="M214.3,112V97.1h3.7v1.7h0.5c0.2-0.6,0.6-1,1.1-1.3c0.5-0.3,1.1-0.4,1.8-0.4h1.8v3.4h-1.9c-1,0-1.8,0.3-2.4,0.8
c-0.6,0.5-0.9,1.3-0.9,2.3v8.5H214.3z"/>
<path class="st1" d="M203,112.4c-1.5,0-2.8-0.3-4-0.9c-1.2-0.6-2.1-1.5-2.8-2.6c-0.7-1.1-1-2.5-1-4.1v-0.5c0-1.6,0.3-3,1-4.1
c0.7-1.1,1.6-2,2.8-2.6c1.2-0.6,2.5-0.9,4-0.9c1.5,0,2.8,0.3,4,0.9c1.2,0.6,2.1,1.5,2.8,2.6c0.7,1.1,1,2.5,1,4.1v0.5
c0,1.6-0.3,3-1,4.1c-0.7,1.1-1.6,2-2.8,2.6C205.8,112.1,204.5,112.4,203,112.4z M203,109c1.2,0,2.1-0.4,2.9-1.1
c0.8-0.8,1.1-1.8,1.1-3.2v-0.3c0-1.4-0.4-2.5-1.1-3.2c-0.7-0.8-1.7-1.1-2.9-1.1c-1.2,0-2.1,0.4-2.9,1.1c-0.8,0.7-1.1,1.8-1.1,3.2
v0.3c0,1.4,0.4,2.5,1.1,3.2C200.9,108.7,201.8,109,203,109z"/>
<path class="st1" d="M185.8,112v-11.8H182v-3.1h3.8v-2.8c0-1,0.3-1.8,0.9-2.4c0.6-0.6,1.4-0.9,2.4-0.9h3.9v3.1h-2.6
c-0.6,0-0.8,0.3-0.8,0.9v2.1h3.9v3.1h-3.9V112H185.8z"/>
<path class="st1" d="M155.9,104.6v-0.5c0-1.6,0.3-2.9,0.9-4c0.6-1.1,1.4-2,2.5-2.5c1-0.6,2.2-0.9,3.4-0.9c1.4,0,2.4,0.2,3.1,0.7
c0.7,0.5,1.2,1,1.5,1.5h0.5v-1.8h3.7v17.5c0,1-0.3,1.8-0.9,2.4c-0.6,0.6-1.4,0.9-2.4,0.9h-10v-3.3h8.6c0.6,0,0.8-0.3,0.8-0.9v-3.9
h-0.5c-0.2,0.3-0.5,0.7-0.8,1c-0.4,0.3-0.8,0.6-1.4,0.8c-0.6,0.2-1.4,0.3-2.3,0.3c-1.2,0-2.3-0.3-3.4-0.9c-1-0.6-1.8-1.4-2.5-2.6
C156.2,107.5,155.9,106.1,155.9,104.6z M163.7,108.7c1.2,0,2.1-0.4,2.9-1.1s1.2-1.8,1.2-3.1v-0.3c0-1.4-0.4-2.4-1.2-3.1
c-0.8-0.7-1.7-1.1-2.9-1.1c-1.2,0-2.1,0.4-2.9,1.1c-0.8,0.7-1.2,1.8-1.2,3.1v0.3c0,1.3,0.4,2.4,1.2,3.1S162.6,108.7,163.7,108.7z"/>
<path class="st1" d="M145.3,112.4c-1.5,0-2.8-0.3-4-0.9c-1.2-0.6-2.1-1.5-2.8-2.6s-1-2.5-1-4.1v-0.5c0-1.6,0.3-3,1-4.1
c0.7-1.1,1.6-2,2.8-2.6c1.2-0.6,2.5-0.9,4-0.9s2.8,0.3,4,0.9c1.2,0.6,2.1,1.5,2.8,2.6c0.7,1.1,1,2.5,1,4.1v0.5c0,1.6-0.3,3-1,4.1
c-0.7,1.1-1.6,2-2.8,2.6C148.1,112.1,146.8,112.4,145.3,112.4z M145.3,109c1.2,0,2.1-0.4,2.9-1.1c0.8-0.8,1.1-1.8,1.1-3.2v-0.3
c0-1.4-0.4-2.5-1.1-3.2c-0.7-0.8-1.7-1.1-2.9-1.1c-1.2,0-2.1,0.4-2.9,1.1c-0.8,0.7-1.1,1.8-1.1,3.2v0.3c0,1.4,0.4,2.5,1.1,3.2
C143.2,108.7,144.1,109,145.3,109z"/>
<path class="st1" d="M130.3,112V91h3.8v21H130.3z"/>
<path class="st1" d="M109.6,112v-3.5h2.8v-14h-2.8V91h10.8c1.3,0,2.4,0.2,3.3,0.7c1,0.4,1.7,1,2.2,1.8c0.5,0.8,0.8,1.7,0.8,2.8v0.3
c0,1-0.2,1.8-0.5,2.4c-0.4,0.6-0.8,1.1-1.3,1.4c-0.5,0.3-0.9,0.6-1.4,0.7v0.5c0.4,0.1,0.9,0.3,1.4,0.7c0.5,0.3,1,0.8,1.3,1.4
c0.4,0.6,0.6,1.4,0.6,2.4v0.3c0,1.2-0.3,2.2-0.8,3c-0.5,0.8-1.3,1.4-2.2,1.9c-0.9,0.4-2,0.7-3.3,0.7H109.6z M116.3,108.4h3.7
c0.9,0,1.6-0.2,2.1-0.6c0.5-0.4,0.8-1,0.8-1.8v-0.3c0-0.8-0.3-1.4-0.8-1.8c-0.5-0.4-1.2-0.6-2.1-0.6h-3.7V108.4z M116.3,99.6h3.7
c0.8,0,1.5-0.2,2-0.6c0.5-0.4,0.8-1,0.8-1.7v-0.3c0-0.8-0.3-1.3-0.8-1.7c-0.5-0.4-1.2-0.6-2-0.6h-3.7V99.6z"/>
<path class="st1" d="M85.9,118v-3.3H94c0.6,0,0.8-0.3,0.8-0.9V110h-0.5c-0.2,0.3-0.4,0.7-0.8,1c-0.3,0.3-0.8,0.6-1.4,0.8
c-0.6,0.2-1.3,0.3-2.2,0.3c-1.2,0-2.2-0.3-3.1-0.8c-0.9-0.5-1.5-1.3-2-2.2c-0.5-0.9-0.7-2-0.7-3.2v-8.9h3.8v8.6c0,1.1,0.3,2,0.8,2.5
c0.6,0.6,1.4,0.8,2.4,0.8c1.2,0,2.1-0.4,2.7-1.1c0.6-0.8,1-1.9,1-3.2v-7.6h3.8v17.5c0,1-0.3,1.8-0.9,2.4c-0.6,0.6-1.4,0.9-2.4,0.9
H85.9z"/>
<path class="st1" d="M72.9,112.4c-1.5,0-2.8-0.3-4-0.9s-2.1-1.5-2.8-2.6s-1-2.5-1-4.1v-0.5c0-1.6,0.3-3,1-4.1c0.7-1.1,1.6-2,2.8-2.6
s2.5-0.9,4-0.9c1.5,0,2.8,0.3,4,0.9s2.1,1.5,2.8,2.6c0.7,1.1,1,2.5,1,4.1v0.5c0,1.6-0.3,3-1,4.1s-1.6,2-2.8,2.6
S74.4,112.4,72.9,112.4z M72.9,109c1.2,0,2.1-0.4,2.9-1.1c0.8-0.8,1.1-1.8,1.1-3.2v-0.3c0-1.4-0.4-2.5-1.1-3.2
c-0.7-0.8-1.7-1.1-2.9-1.1c-1.2,0-2.1,0.4-2.9,1.1c-0.8,0.7-1.1,1.8-1.1,3.2v0.3c0,1.4,0.4,2.5,1.1,3.2
C70.8,108.7,71.8,109,72.9,109z"/>
<path class="st1" d="M57.9,112V91h3.8v21H57.9z"/>
<path class="st1" d="M38.8,118V97.1h3.7v1.8H43c0.3-0.6,0.9-1.1,1.6-1.5c0.7-0.5,1.8-0.7,3.1-0.7c1.2,0,2.3,0.3,3.3,0.9
c1,0.6,1.8,1.4,2.5,2.6c0.6,1.1,0.9,2.5,0.9,4.1v0.5c0,1.6-0.3,3-0.9,4.1c-0.6,1.1-1.4,2-2.5,2.6c-1,0.6-2.1,0.9-3.3,0.9
c-0.9,0-1.7-0.1-2.3-0.3c-0.6-0.2-1.1-0.5-1.5-0.8c-0.4-0.3-0.7-0.7-0.9-1h-0.5v7.7H38.8z M46.6,109.1c1.2,0,2.1-0.4,2.9-1.1
c0.8-0.8,1.2-1.9,1.2-3.3v-0.3c0-1.4-0.4-2.5-1.2-3.3c-0.8-0.8-1.8-1.1-2.9-1.1s-2.1,0.4-2.9,1.1c-0.8,0.7-1.2,1.8-1.2,3.3v0.3
c0,1.4,0.4,2.5,1.2,3.3C44.4,108.7,45.4,109.1,46.6,109.1z"/>
<path class="st1" d="M28.2,112.4c-1.5,0-2.8-0.3-3.9-0.9c-1.1-0.6-2-1.5-2.6-2.7c-0.6-1.2-0.9-2.5-0.9-4.1v-0.4
c0-1.6,0.3-2.9,0.9-4.1c0.6-1.2,1.5-2,2.6-2.7c1.1-0.6,2.4-1,3.9-1c1.5,0,2.7,0.3,3.8,1c1.1,0.6,1.9,1.5,2.5,2.7
c0.6,1.1,0.9,2.5,0.9,4v1.3H24.6c0,1,0.4,1.8,1.1,2.5c0.7,0.6,1.6,1,2.6,1c1.1,0,1.8-0.2,2.3-0.7s0.9-1,1.1-1.5l3.1,1.6
c-0.3,0.5-0.7,1.1-1.2,1.7c-0.5,0.6-1.2,1.1-2.1,1.6C30.7,112.2,29.6,112.4,28.2,112.4z M24.6,102.8h7c-0.1-0.9-0.4-1.6-1-2.1
c-0.6-0.5-1.4-0.8-2.4-0.8c-1,0-1.8,0.3-2.4,0.8C25.1,101.3,24.7,102,24.6,102.8z"/>
<path class="st1" d="M0.8,112v-3.5h2.8v-14H0.8V91h8.6c2.8,0,5,0.7,6.4,2.2c1.5,1.4,2.2,3.5,2.2,6.4v4c0,2.8-0.7,4.9-2.2,6.4
c-1.5,1.4-3.6,2.1-6.4,2.1H0.8z M7.5,108.4h2c1.6,0,2.8-0.4,3.5-1.3c0.7-0.8,1.1-2,1.1-3.5v-4.2c0-1.5-0.4-2.7-1.1-3.5
c-0.7-0.8-1.9-1.3-3.5-1.3h-2V108.4z"/>
</svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

@@ -8,6 +8,7 @@ params
```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
@@ -21,10 +22,10 @@ minify
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.
: (`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
: (`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.
: (`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
: (`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:
@@ -58,10 +59,10 @@ target
platform
: {{< new-in 0.140.0 />}}
: (`string`) One of `browser`, `node`, `neutral`. Default is `browser`. See https://esbuild.github.io/api/#platform.
: (`string`) One of `browser`, `node`, `neutral`. Default is `browser`. See <https://esbuild.github.io/api/#platform>.
externals
: (`slice`) External dependencies. Use this to trim dependencies you know will never be executed. See https://esbuild.github.io/api/#external.
: (`slice`) External dependencies. Use this to trim dependencies you know will never be executed. See <https://esbuild.github.io/api/#external>.
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.
@@ -73,7 +74,7 @@ defines
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
: See <https://esbuild.github.io/api/#drop>
sourceMap
: (`string`) Whether to generate `inline`, `linked`, or `external` source maps from esbuild. 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. By default, source maps are not created. Note that the `linked` option was added in Hugo 0.140.0.
@@ -84,11 +85,11 @@ sourcesContent
JSX
: {{< new-in 0.124.0 />}}
: (`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.
: (`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
: {{< new-in 0.124.0 />}}
: (`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.
: (`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.:
@@ -6,6 +6,7 @@ _comment: Do not remove front matter.
> 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.dev/wiki/Modules](https://go.dev/wiki/Modules)
> - [blog.golang.org/using-go-modules](https://go.dev/blog/using-go-modules)
@@ -15,9 +15,3 @@ Prebuilt binaries are available for a variety of operating systems and architect
Please consult your operating system documentation if you need help setting file permissions or modifying your PATH environment variable.
If you do not see a prebuilt binary for the desired edition, operating system, and architecture, install Hugo using one of the methods described below.
[commit information]: /methods/page/gitinfo/
[Git]: https://git-scm.com/
[Go]: https://go.dev/
[Hugo Modules]: /hugo-modules/
[latest release]: https://github.com/gohugoio/hugo/releases/latest
@@ -32,13 +32,13 @@ content/
And these templates:
```go-html-template {file="layouts/_default/list.html"}
```go-html-template {file="layouts/section.html"}
{{ range .Pages.ByWeight }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ end }}
```
```go-html-template {file="layouts/_default/single.html"}
```go-html-template {file="layouts/page.html"}
{{ with .Prev }}
<a href="{{ .RelPermalink }}">Previous</a>
{{ end }}
@@ -32,13 +32,13 @@ content/
And these templates:
```go-html-template {file="layouts/_default/list.html"}
```go-html-template {file="layouts/section.html"}
{{ range .Pages.ByWeight }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ end }}
```
```go-html-template {file="layouts/_default/single.html"}
```go-html-template {file="layouts/page.html"}
{{ with .PrevInSection }}
<a href="{{ .RelPermalink }}">Previous</a>
{{ end }}
@@ -32,13 +32,13 @@ content/
And these templates:
```go-html-template {file="layouts/_default/list.html"}
```go-html-template {file="layouts/section.html"}
{{ range .Pages.ByWeight }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ end }}
```
```go-html-template {file="layouts/_default/single.html"}
```go-html-template {file="layouts/page.html"}
{{ $pages := .CurrentSection.Pages.ByWeight }}
{{ with $pages.Prev . }}
@@ -57,7 +57,7 @@ When you visit page-2:
To reverse the meaning of _next_ and _previous_ you can chain the [`Reverse`] method to the page collection definition:
```go-html-template {file="layouts/_default/single.html"}
```go-html-template {file="layouts/page.html"}
{{ $pages := .CurrentSection.Pages.ByWeight.Reverse }}
{{ with $pages.Prev . }}
@@ -32,9 +32,9 @@ To capture the "genres" `Taxonomy` object from within any template, use the [`Ta
{{ $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/_default/taxonomy.html"}
```go-html-template {file="layouts/taxonomy.html"}
{{ $taxonomyObject := .Data.Terms }}
```
+6 -2
View File
@@ -26,9 +26,15 @@ _comment: Do not remove front matter.
`:section`
: The content's section.
`:sectionslug`
: The content's section using slugified section name. The slugified section name is the `slug` as defined in front matter, else the `title` as defined in front matter, else the automatic title.
`:sections`
: The content's sections hierarchy. You can use a selection of the sections using _slice syntax_: `:sections[1:]` includes all but the first, `:sections[:last]` includes all but the last, `:sections[last]` includes only the last, `:sections[1:2]` includes section 2 and 3. Note that this slice access will not throw any out-of-bounds errors, so you don't have to be exact.
`:sectionslugs`
: The content's sections hierarchy using slugified section names. The slugified section name is the `slug` as defined in front matter, else the `title` as defined in front matter, else the automatic title. You can use a selection of the sections using _slice syntax_: `:sectionslugs[1:]` includes all but the first, `:sectionslugs[:last]` includes all but the last, `:sectionslugs[last]` includes only the last, `:sectionslugs[1:2]` includes section 2 and 3. Note that this slice access will not throw any out-of-bounds errors, so you don't have to be exact.
`:title`
: The `title` as defined in front matter, else the automatic title. Hugo generates titles automatically for section, taxonomy, and term pages that are not backed by a file.
@@ -67,5 +73,3 @@ For time-related values, you can also use the layout string components defined i
permalinks:
posts: /:06/:1/:2/:title/
{{< /code-toggle >}}
[content base name]: /methods/page/file/#contentbasename
@@ -8,7 +8,7 @@ _comment: Do not remove front matter.
The primary use case for `PageInner` is to resolve links and [page resources](g) relative to an included `Page`. For example, create an "include" shortcode to compose a page from multiple content files, while preserving a global context for footnotes and the table of contents:
```go-html-template {file="layouts/shortcodes/include.html" copy=true}
```go-html-template {file="layouts/_shortcodes/include.html" copy=true}
{{ with .Get 0 }}
{{ with $.Page.GetPage . }}
{{- .RenderShortcodes }}
@@ -22,14 +22,14 @@ 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/p1.md"}
{{%/* include "/posts/p2" */%}}
```text {file="content/posts/post-1.md"}
{{%/* include "/posts/post-2" */%}}
```
Any render hook triggered while rendering `/posts/p2` will get:
Any render hook triggered while rendering `/posts/post-2` will get:
- `/posts/p1` when calling `Page`
- `/posts/p2` when calling `PageInner`
- `/posts/post-1` when calling `Page`
- `/posts/post-2` when calling `PageInner`
`PageInner` falls back to the value of `Page` if not relevant, and always returns a value.
+1 -1
View File
@@ -9,7 +9,7 @@ The method or function used to create a scratch pad determines its scope. For ex
Scope|Method or function
:--|:--
page|[`PAGE.Store`]
site|[`SITE.Store`]
site|[`SITE.Store`]
global|[`hugo.Store`]
local|[`collections.NewScratch`]
shortcode|[`SHORTCODE.Store`]
@@ -28,6 +28,7 @@ lineNoStart
lineNos
: (`any`) Controls line number display. Default is `false`.
- `true`: Enable line numbers, controlled by `lineNumbersInTable`.
- `false`: Disable line numbers.
- `inline`: Enable inline line numbers (sets `lineNumbersInTable` to `false`).
+1 -1
View File
@@ -92,7 +92,7 @@ weight: 20
## Performance
[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.
: 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]
: 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 site once a week.
+3 -4
View File
@@ -84,7 +84,7 @@ 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
: (`[]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.
: (`[]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
: (`bool`) Whether to disable automatic live reloading of the browser window. Default is `false`.
@@ -123,7 +123,7 @@ ignoreCache
: (`bool`) Whether to ignore the cache directory. Default is `false`.
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].
: (`[]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
: (`[]string`) A slice of message identifiers corresponding to warnings and errors you wish to suppress. See [`erroridf`] and [`warnidf`].
@@ -280,7 +280,7 @@ themesDir
: (`string`) The designated directory for themes. Default is `themes`.
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 `30s`.
: (`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.
@@ -339,7 +339,6 @@ Some configuration settings, such as menus and custom parameters, can be defined
[`MainSections`]: /methods/site/mainsections/
[`segments`]: /configuration/segments/
[`strings.Title`]: /functions/strings/title/
[`strings.Title`]: /functions/strings/title
[`Summary`]: /methods/page/summary/
[`time.AsTime`]: /functions/time/astime/
[`time.Format`]: /functions/time/format/
+2
View File
@@ -27,6 +27,7 @@ useResourceCacheWhen
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:
<!-- markdownlint-disable MD049 -->
{{< code-toggle file=hugo >}}
[build]
[build.buildStats]
@@ -44,6 +45,7 @@ The `build.cachebusters` configuration option was added to support development u
source = "assets/.*\\.(.*)$"
target = "$1"
{{< /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.
+1 -1
View File
@@ -44,7 +44,7 @@ environment
: (`string`) A [glob](g) pattern matching the build [environment](g). For example: `{staging,production}`.
kind
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: ` {taxonomy,term}`.
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: `{taxonomy,term}`.
lang
: (`string`) A [glob](g) pattern matching the [page language]. For example: `{en,de}`.
+24 -13
View File
@@ -60,25 +60,32 @@ The default front matter configuration includes these aliases.
## Tokens
Hugo provides several [tokens](g) to assist with front matter configuration.
Hugo provides the following [tokens](g) to help you configure your front matter:
Token|Description
:--|:--
`:default`|The default ordered sequence of date fields.
`:fileModTime`|The file's last modification timestamp.
`:filename`|The date from the file name, if present.
`:git`|The Git author date for the file's last revision.
`:default`
: The default ordered sequence of date fields.
When Hugo extracts a date from a file name, it uses the rest of the file name to generate the page's [`slug`], but only if a slug isn't already specified in the page's front matter. For example, given the name `2025-02-01-article.md`, Hugo will set the `date` to `2025-02-01` and the `slug` to `article`.
`:fileModTime`
: The file's last modification timestamp.
[`slug`]: /content-management/front-matter/#slug
`:filename`
: Extracts the date from the file name, provided the file name begins with a date in one of the following formats:
To enable access to the Git author date, set [`enableGitInfo`] to `true`, or use\
the `--enableGitInfo` flag when building your site.
- `YYYY-MM-DD`
- `YYYY-MM-DD-HH-MM-SS` {{< new-in 0.148.0 />}}
[`enableGitInfo`]: /configuration/all/#enablegitinfo
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`).
Consider this example:
Hugo resolves the extracted date to the [`timeZone`] defined in your site 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.
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`.
`:git`
: The Git author date for the file's last revision. To enable access to the Git author date, set [`enableGitInfo`] to `true`, or use the `--enableGitInfo` flag when building your site.
## Example
Consider this site configuration:
{{< code-toggle file=hugo >}}
[frontmatter]
@@ -89,3 +96,7 @@ lastmod = ['lastmod', ':fileModTime']
To determine `date`, Hugo tries to extract the date from the file name, falling back to the default ordered sequence of date fields.
To determine `lastmod`, Hugo looks for a `lastmod` field in front matter, falling back to the file's last modification timestamp.
[`enableGitInfo`]: /configuration/all/#enablegitinfo
[`slug`]: /content-management/front-matter/#slug
[`timeZone`]: /configuration/all/#timezone
@@ -79,6 +79,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.
[#12899]: https://github.com/gohugoio/hugo/issues/12899
### Omit the root key
When splitting the configuration by root key, omit the root key in the component file. For example, these are equivalent:
+84 -68
View File
@@ -47,10 +47,10 @@ Extension|Documentation|Enabled
:--|:--|:-:
`cjk`|[Goldmark Extensions: CJK]|:heavy_check_mark:
`definitionList`|[PHP Markdown Extra: Definition lists]|:heavy_check_mark:
`extras`|[Hugo Goldmark Extensions: Extras]||
`extras`|[Hugo Goldmark Extensions: Extras]|&nbsp;
`footnote`|[PHP Markdown Extra: Footnotes]|:heavy_check_mark:
`linkify`|[GitHub Flavored Markdown: Autolinks]|:heavy_check_mark:
`passthrough`|[Hugo Goldmark Extensions: Passthrough]||
`passthrough`|[Hugo Goldmark Extensions: Passthrough]|&nbsp;
`strikethrough`|[GitHub Flavored Markdown: Strikethrough]|:heavy_check_mark:
`table`|[GitHub Flavored Markdown: Tables]|:heavy_check_mark:
`taskList`|[GitHub Flavored Markdown: Task list items]|:heavy_check_mark:
@@ -70,12 +70,19 @@ Mark text|`==baz==`|`<mark>baz</mark>`
Subscript|`H~2~O`|`H<sub>2</sub>O`
Superscript|`1^st^`|`1<sup>st</sup>`
To avoid a conflict when enabling the "subscript" feature of the Extras extension, if you want to render subscript and strikethrough text concurrently you must:
To avoid a conflict[^1], if you enable the "subscript" feature of the Extras extension, you must disable the Strikethrough extension:
1. Disable the Strikethrough extension
1. Enable the "deleted text" feature of the Extras extension
[^1]: See [details](https://github.com/gohugoio/hugo-goldmark-extensions/commit/4d4fcd022fe45a9b51483df001c9e5f4e632d5a9).
For example:
{{< code-toggle file=hugo >}}
[markup.goldmark.extensions]
strikethrough = false
[markup.goldmark.extensions.extras.subscript]
enable = true
{{< /code-toggle >}}
If you still need to show deleted text after disabling the Strikethrough extension, enable the "deleted text" feature of the Extras extension:
{{< code-toggle file=hugo >}}
[markup.goldmark.extensions]
@@ -83,11 +90,10 @@ strikethrough = false
[markup.goldmark.extensions.extras.delete]
enable = true
[markup.goldmark.extensions.extras.subscript]
enable = true
{{< /code-toggle >}}
With this configuration, to format text as deleted, wrap it with double-tildes.
#### Passthrough
{{< new-in 0.122.0 />}}
@@ -111,7 +117,7 @@ Markdown|Replaced by|Description
`”`|`&rdquo;`|right double quote
``|`&rsquo;`|right single quote
### Settings explained
### Goldmark settings explained
Most of the Goldmark settings above are self-explanatory, but some require explanation.
@@ -133,13 +139,13 @@ parser.autoHeadingID
: (`bool`) Whether to automatically add `id` attributes to headings (i.e., `h1`, `h2`, `h3`, `h4`, `h5`, and `h6` elements).
parser.autoIDType
: (`string`) The strategy used to automatically generate `id` attributes, one of `github`, `github-ascii` or `blackfriday`.
: (`string`) The strategy used to automatically generate `id` attributes, one of `github`, `github-ascii` or `blackfriday`. Default is `github`.
- `github` produces GitHub-compatible `id` attributes
- `github-ascii` drops any non-ASCII characters after accent normalization
- `blackfriday` produces `id` attributes compatible with the Blackfriday Markdown renderer
- `github`: Generate GitHub-compatible `id` attributes
- `github-ascii`: Drop any non-ASCII characters after accent normalization
- `blackfriday`: Generate `id` attributes compatible with the Blackfriday Markdown renderer
This is also the strategy used by the [anchorize](/functions/urls/anchorize) template function. Default is `github`.
This is also the strategy used by the [anchorize] template function.
parser.attribute.block
: (`bool`) Whether to enable [Markdown attributes] for block elements. Default is `false`.
@@ -147,19 +153,33 @@ parser.attribute.block
parser.attribute.title
: (`bool`) Whether to enable [Markdown attributes] for headings. Default is `true`.
<!-- TODO: delete this on or after July 1, 2027. -->
renderHooks.image.enableDefault
: {{< new-in 0.123.0 />}}
: (`bool`) Whether to enable the [embedded image render hook]. Default is `false`.
: Deprecated in v0.148.0. Use `renderHooks.image.useEmbedded` instead.
> [!note]
> The embedded image render hook is automatically enabled for multilingual single-host sites if [duplication of shared page resources] is disabled. This is the default configuration for multilingual single-host sites.
renderHooks.image.useEmbedded
: {{< new-in 0.148.0 />}}
: (`string`) When to use the [embedded image render hook]. One of `auto`, `never`, `always`, or `fallback`. Default is `auto`.
- `auto`: Automatically use the embedded image render hook for multilingual single-host sites, specifically when the [duplication of shared page resources] feature is disabled. This is the default behavior for such sites. If custom image render hooks are defined by your project, modules, or themes, these will be used instead.
- `never`: Never use the embedded image render hook. If custom image render hooks are defined by your project, modules, or themes, these will be used instead.
- `always`: Always use the embedded image render hook, even if custom image render hooks are provided by your project, modules, or themes. In this case, the embedded hook takes precedence.
- `fallback`: Use the embedded image render hook only if custom image render hooks are not provided by your project, modules, or themes. If custom image render hooks exist, these will be used instead.
<!-- TODO: delete this on or after July 1, 2027. -->
renderHooks.link.enableDefault
: {{< new-in 0.123.0 />}}
: (`bool`) Whether to enable the [embedded link render hook]. Default is `false`.
: Deprecated in v0.148.0. Use `renderHooks.link.useEmbedded` instead.
> [!note]
> The embedded link render hook is automatically enabled for multilingual single-host sites if [duplication of shared page resources] is disabled. This is the default configuration for multilingual single-host sites.
renderHooks.link.useEmbedded
: {{< new-in 0.148.0 />}}
: (`string`) When to use the [embedded link render hook]. One of `auto`, `never`, `always`, or `fallback`. Default is `auto`.
- `auto`: Automatically use the embedded link render hook for multilingual single-host sites, specifically when the [duplication of shared page resources] feature is disabled. This is the default behavior for such sites. If custom link render hooks are defined by your project, modules, or themes, these will be used instead.
- `never`: Never use the embedded link render hook. If custom link render hooks are defined by your project, modules, or themes, these will be used instead.
- `always`: Always use the embedded link render hook, even if custom link render hooks are provided by your project, modules, or themes. In this case, the embedded hook takes precedence.
- `fallback`: Use the embedded link render hook only if custom link render hooks are not provided by your project, modules, or themes. If custom link render hooks exist, these will be used instead.
renderer.hardWraps
: (`bool`) Whether to replace newline characters within a paragraph with `br` elements. Default is `false`.
@@ -173,7 +193,7 @@ This is the default configuration for the AsciiDoc renderer:
{{< code-toggle config=markup.asciidocExt />}}
### Settings explained
### AsciiDoc settings explained
attributes
: (`map`) A map of key-value pairs, each a document attribute. See Asciidoctor's [attributes].
@@ -226,49 +246,47 @@ workingFolderCurrent
Follow the steps below to enable syntax highlighting.
#### Step 1
Step 1
: Set the `source-highlighter` attribute in your site configuration. For example:
Set the `source-highlighter` attribute in your site configuration. For example:
{{< code-toggle file=hugo >}}
[markup.asciidocExt.attributes]
source-highlighter = 'rouge'
{{< /code-toggle >}}
{{< code-toggle file=hugo >}}
[markup.asciidocExt.attributes]
source-highlighter = 'rouge'
{{< /code-toggle >}}
Step 2
: Generate the highlighter CSS. For example:
#### Step 2
```text
rougify style monokai.sublime > assets/css/syntax.css
```
Generate the highlighter CSS. For example:
Step 3
: In your base template add a link to the CSS file:
```text
rougify style monokai.sublime > assets/css/syntax.css
```
```go-html-template {file="layouts/baseof.html"}
<head>
...
{{ with resources.Get "css/syntax.css" }}
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
{{ end }}
...
</head>
```
#### Step 3
Step 4
: Add the code to be highlighted to your markup:
In your base template add a link to the CSS file:
```text
[#hello,ruby]
----
require 'sinatra'
```go-html-template {file="layouts/_default/baseof.html"}
<head>
...
{{ with resources.Get "css/syntax.css" }}
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
{{ end }}
...
</head>
```
Then add the code to be highlighted to your markup:
```text
[#hello,ruby]
----
require 'sinatra'
get '/hi' do
"Hello World!"
end
----
```
get '/hi' do
"Hello World!"
end
----
```
### Troubleshooting
@@ -303,24 +321,24 @@ ordered
[`Fragments.Identifiers`]: /methods/page/fragments/#identifiers
[`TableOfContents`]: /methods/page/tableofcontents/
[anchorize]: /functions/urls/anchorize
[AsciiDoc]: https://asciidoc.org/
[asciidoctor-diagram]: https://asciidoctor.org/docs/asciidoctor-diagram/
[attributes]: https://asciidoctor.org/docs/asciidoc-syntax-quick-reference/#attributes-and-substitutions
[CommonMark]: https://spec.commonmark.org/current/
[deleted text]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/del
[duplication of shared page resources]: /configuration/markup/#duplicateresourcefiles
[duplication of shared page resources]: /configuration/markup/#duplicateresourcefiles
[embedded image render hook]: /render-hooks/images/#default
[embedded image render hook]: /render-hooks/images/#default
[embedded link render hook]: /render-hooks/links/#default
[embedded link render hook]: /render-hooks/links/#default
[GitHub Flavored Markdown]: https://github.github.com/gfm/
[Emacs Org Mode]: https://orgmode.org/
[embedded image render hook]: /render-hooks/images/#embedded
[embedded link render hook]: /render-hooks/links/#embedded
[GitHub Flavored Markdown: Autolinks]: https://github.github.com/gfm/#autolinks-extension-
[GitHub Flavored Markdown: Strikethrough]: https://github.github.com/gfm/#strikethrough-extension-
[GitHub Flavored Markdown: Tables]: https://github.github.com/gfm/#tables-extension-
[GitHub Flavored Markdown: Task list items]: https://github.github.com/gfm/#task-list-items-extension-
[Goldmark]: https://github.com/yuin/goldmark/
[GitHub Flavored Markdown]: https://github.github.com/gfm/
[Goldmark Extensions: CJK]: https://github.com/yuin/goldmark?tab=readme-ov-file#cjk-extension
[Goldmark Extensions: Typographer]: https://github.com/yuin/goldmark?tab=readme-ov-file#typographer-extension
[Goldmark]: https://github.com/yuin/goldmark/
[Hugo Goldmark Extensions: Extras]: https://github.com/gohugoio/hugo-goldmark-extensions?tab=readme-ov-file#extras-extension
[Hugo Goldmark Extensions: Passthrough]: https://github.com/gohugoio/hugo-goldmark-extensions?tab=readme-ov-file#passthrough-extension
[image render hook]: /render-hooks/images/
@@ -330,12 +348,10 @@ ordered
[Markdown attributes]: /content-management/markdown-attributes/
[mathematics in Markdown]: content-management/mathematics/
[multilingual page resources]: /content-management/page-resources/#multilingual
[Pandoc]: https://pandoc.org/
[PHP Markdown Extra: Definition lists]: https://michelf.ca/projects/php-markdown/extra/#def-list
[PHP Markdown Extra: Footnotes]: https://michelf.ca/projects/php-markdown/extra/#footnotes
[reStructuredText]: https://docutils.sourceforge.io/rst.html
[security policy]: /configuration/security/
[subscript]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub
[superscript]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup
[AsciiDoc]: https://asciidoc.org/
[Emacs Org Mode]: https://orgmode.org/
[Pandoc]: https://www.pandoc.org/
[reStructuredText]: https://docutils.sourceforge.io/rst.html
+2
View File
@@ -96,6 +96,7 @@ url
This nested menu demonstrates some of the available properties:
<!-- markdownlint-disable MD033 -->
{{< code-toggle file=hugo >}}
[[menus.main]]
name = 'Products'
@@ -127,6 +128,7 @@ weight = 30
[menus.main.params]
rel = 'external'
{{< /code-toggle >}}
<!-- markdownlint-enable MD033 -->
[`Menus`]: /methods/site/menus/
[Automatically]: /content-management/menus/#define-automatically
+6 -6
View File
@@ -11,6 +11,7 @@ aliases: [/hugo-modules/configuration/]
This is the default configuration:
<!-- markdownlint-disable MD049 -->
{{< code-toggle file=hugo >}}
[module]
noProxy = 'none'
@@ -20,6 +21,7 @@ proxy = 'direct'
vendorClosest = false
workspace = 'off'
{{< /code-toggle >}}
<!-- markdownlint-enable MD049 -->
auth
: {{< new-in 0.144.0 />}}
@@ -75,12 +77,10 @@ extended
: (`bool`) Whether the extended edition of Hugo is required, satisfied by installing either the extended or extended/deploy edition.
max
: (`string`) The maximum Hugo version supported, for example `0.143.0`.
: (`string`) The maximum Hugo version supported, for example `0.148.0`.
min
: (`string`) The minimum Hugo version supported, for example `0.123.0`.
[`themesDir`]: /configuration/all/#themesdir
: (`string`) The minimum Hugo version supported, for example `0.102.0`.
## Imports
@@ -112,8 +112,6 @@ noVendor
path
: (`string`) The module path, either a valid Go module path (e.g., `github.com/gohugoio/myShortcodes`) or the directory name if stored in the [`themesDir`].
[`themesDir`]: /configuration/all#themesDir
{{% include "/_common/gomodules-info.md" %}}
## Mounts
@@ -177,3 +175,5 @@ excludeFiles
source="assets"
target="assets"
{{< /code-toggle >}}
[`themesDir`]: /configuration/all/#themesdir
+51 -54
View File
@@ -44,25 +44,25 @@ isHTML
: (`bool`) Whether to classify the output format as HTML. Hugo uses this value to determine when to create alias redirects and when to inject the LiveReload script. Default is `false`.
isPlainText
: (`bool`) Whether to parse templates for this output format with Go's [text/template] package instead of the [html/template] package. Default is `false`.
: (`bool`) Whether to parse templates for this output format with Go's [text/template][] package instead of the [html/template][] package. Default is `false`.
mediaType
: (`string`) The [media type](g) of the published file. This must match one of the [configured media types].
: (`string`) The [media type](g) of the published file. This must match one of the [configured media types][].
notAlternative
: (`bool`) Whether to exclude this output format from the values returned by the [`AlternativeOutputFormats`] method on a `Page` object. Default is `false`.
: (`bool`) Whether to exclude this output format from the values returned by the [`AlternativeOutputFormats`][] method on a `Page` object. Default is `false`.
noUgly
: (`bool`) Whether to disable ugly URLs for this output format when [`uglyURLs`] are enabled in your site configuration. Default is `false`.
: (`bool`) Whether to disable ugly URLs for this output format when [`uglyURLs`][] are enabled in your site configuration. Default is `false`.
path
: (`string`) The published file's directory path, relative to the root of the publish directory. If not specified, the file will be published using its content path.
: (`string`) The first segment of the publication path for this output format. This path segment is relative to the root of your [`publishDir`][]. If omitted, Hugo will use the file's original content path for publishing.
permalinkable
: (`bool`) Whether to return the rendering output format rather than main output format when invoking the [`Permalink`] and [`RelPermalink`] methods on a `Page` object. See&nbsp;[details](#link-to-output-formats). Enabled by default for the `html` and `amp` output formats. Default is `false`.
: (`bool`) Whether to return the rendering output format rather than main output format when invoking the [`Permalink`][] and [`RelPermalink`][] methods on a `Page` object. See&nbsp;[details](#link-to-output-formats). Enabled by default for the `html` and `amp` output formats. Default is `false`.
protocol
: (`string`) The protocol (scheme) of the URL for this output format. For example, `https://` or `webcal://`. Default is the scheme of the [`baseURL`] parameter in your site configuration, typically `https://`.
: (`string`) The protocol (scheme) of the URL for this output format. For example, `https://` or `webcal://`. Default is the scheme of the [`baseURL`][] parameter in your site configuration, typically `https://`.
rel
: (`string`) If provided, you can assign this value to `rel` attributes in `link` elements when iterating over output formats in your templates. Default is `alternate`.
@@ -93,56 +93,52 @@ The example above shows that when you modify a default content format, you only
You can create new output formats as needed. For example, you may wish to create an output format to support Atom feeds.
### Step 1
Step 1
: Output formats require a specified media type. Because Atom feeds use `application/atom+xml`, which is not one of the [default media types][], you must create it first.
Output formats require a specified media type. Because Atom feeds use `application/atom+xml`, which is not one of the [default media types], you must create it first.
{{< code-toggle file=hugo >}}
[mediaTypes.'application/atom+xml']
suffixes = ['atom']
{{< /code-toggle >}}
{{< code-toggle file=hugo >}}
[mediaTypes.'application/atom+xml']
suffixes = ['atom']
{{< /code-toggle >}}
See [configure media types][] for more information.
See [configure media types] for more information.
Step 2
: Create a new output format:
### Step 2
{{< code-toggle file=hugo >}}
[outputFormats.atom]
mediaType = 'application/atom+xml'
noUgly = true
{{< /code-toggle >}}
Create a new output format:
Note that we use the default settings for all other output format properties.
{{< code-toggle file=hugo >}}
[outputFormats.atom]
mediaType = 'application/atom+xml'
noUgly = true
{{< /code-toggle >}}
Step 3
: Specify the page [kinds](g) for which to render this output format:
Note that we use the default settings for all other output format properties.
{{< code-toggle file=hugo >}}
[outputs]
home = ['html', 'rss', 'atom']
section = ['html', 'rss', 'atom']
taxonomy = ['html', 'rss', 'atom']
term = ['html', 'rss', 'atom']
{{< /code-toggle >}}
### Step 3
See [configure outputs][] for more information.
Specify the page [kinds](g) for which to render this output format:
Step 4
: Create a template to render the output format. Since Atom feeds are lists, you need to create a list template. Consult the [template lookup order] to find the correct template path:
{{< code-toggle file=hugo >}}
[outputs]
home = ['html', 'rss', 'atom']
section = ['html', 'rss', 'atom']
taxonomy = ['html', 'rss', 'atom']
term = ['html', 'rss', 'atom']
{{< /code-toggle >}}
```text
layouts/list.atom.atom
```
See [configure outputs] for more information.
### Step 4
Create a template to render the output format. Since Atom feeds are lists, you need to create a list template. Consult the [template lookup order] to find the correct template path:
```text
layouts/_default/list.atom.atom
```
We leave writing the template code as an exercise for you. Aim for a result similar to the [embedded RSS template].
We leave writing the template code as an exercise for you. Aim for a result similar to the [embedded RSS template][].
## List output formats
To access output formats, each `Page` object provides two methods: [`OutputFormats`] (for all formats, including the current one) and [`AlternativeOutputFormats`]. Use `AlternativeOutputFormats` to create a link `rel` list within your site's `head` element, as shown below:
To access output formats, each `Page` object provides two methods: [`OutputFormats`][] (for all formats, including the current one) and [`AlternativeOutputFormats`][]. Use `AlternativeOutputFormats` to create a link `rel` list within your site's `head` element, as shown below:
```go-html-template
{{ range .AlternativeOutputFormats }}
@@ -152,9 +148,9 @@ To access output formats, each `Page` object provides two methods: [`OutputForma
## Link to output formats
By default, a `Page` object's [`Permalink`] and [`RelPermalink`] methods return the URL of the [primary output format](g), typically `html`. This behavior remains consistent regardless of the template used.
By default, a `Page` object's [`Permalink`][] and [`RelPermalink`][] methods return the URL of the [primary output format](g), typically `html`. This behavior remains consistent regardless of the template used.
For example, in `single.json.json`, you'll see:
For example, in `page.json.json`, you'll see:
```go-html-template
{{ .RelPermalink }} → /that-page/
@@ -163,9 +159,9 @@ For example, in `single.json.json`, you'll see:
{{ end }}
```
To make these methods return the URL of the _current_ template's output format, you must set the [`permalinkable`] setting to `true` for that format.
To make these methods return the URL of the _current_ template's output format, you must set the [`permalinkable`][] setting to `true` for that format.
With `permalinkable` set to true for `json` in the same `single.json.json` template:
With `permalinkable` set to true for `json` in the same `page.json.json` template:
```go-html-template
{{ .RelPermalink }} → /that-page/index.json
@@ -176,7 +172,7 @@ With `permalinkable` set to true for `json` in the same `single.json.json` templ
## Template lookup order
Each output format requires a template conforming to the [template lookup order].
Each output format requires a template conforming to the [template lookup order][].
For the highest specificity in the template lookup order, include the page kind, output format, and suffix in the file name:
@@ -188,22 +184,23 @@ For example, for section pages:
Output format|Template path
:--|:--
`html`|`layouts/_default/section.html.html`
`json`|`layouts/_default/section.json.json`
`rss`|`layouts/_default/section.rss.xml`
`html`|`layouts/section.html.html`
`json`|`layouts/section.json.json`
`rss`|`layouts/section.rss.xml`
[`AlternativeOutputFormats`]: /methods/page/alternativeoutputformats/
[`baseURL`]: /configuration/all/#baseurl
[`OutputFormats`]: /methods/page/outputformats/
[`Permalink`]: /methods/page/permalink/
[`RelPermalink`]: /methods/page/relpermalink/
[`baseURL`]: /configuration/all/#baseurl
[`permalinkable`]: #permalinkable
[`publishDir`]: /configuration/all/#publishdir
[`RelPermalink`]: /methods/page/relpermalink/
[`uglyURLs`]: /configuration/ugly-urls/
[configure media types]: /configuration/media-types/
[configure outputs]: /configuration/outputs/
[configured media types]: /configuration/media-types/
[default media types]: /configuration/media-types/
[embedded RSS template]: {{% eturl rss %}}
[embedded RSS template]: <{{% eturl rss %}}>
[html/template]: https://pkg.go.dev/html/template
[template lookup order]: /templates/lookup-order/
[text/template]: https://pkg.go.dev/text/template
@@ -95,9 +95,9 @@ weight = 1
We've configured the `authors` index with a weight of `2` and the `genres` index with a weight of `1`. This means Hugo prioritizes shared `authors` as twice as significant as shared `genres`.
Then render a list of 5 related reviews with a partial template like this:
Then render a list of 5 related reviews with a _partial_ template like this:
```go-html-template {file="layouts/partials/related.html" copy=true}
```go-html-template {file="layouts/_partials/related.html" copy=true}
{{ with site.RegularPages.Related . | first 5 }}
<p>Related content:</p>
<ul>
+2 -2
View File
@@ -6,7 +6,7 @@ categories: []
keywords: []
---
Hugo's built-in security policy, which restricts access to `os/exec`, remote communication, and similar operations, is configured via allow lists. By default, access is restricted. If a build attempts to use a feature not included in the allow list, it will fail, providing a detailed message.
Hugo's built-in security policy, which restricts access to `os/exec`, remote communication, and similar operations, is configured via allowlists. By default, access is restricted. If a build attempts to use a feature not included in the allowlist, it will fail, providing a detailed message.
This is the default security configuration:
@@ -34,7 +34,7 @@ http.urls
: (`[]string`) A slice of [regular expressions](g) matching the URLs that the `resources.GetRemote` function is allowed to access.
> [!note]
> Setting an allow list to the string `none` will completely disable the associated feature.
> Setting an allowlist to the string `none` will completely disable the associated feature.
You can also override the site configuration with environment variables. For example, to block `resources.GetRemote` from accessing any URL:
+1 -1
View File
@@ -31,7 +31,7 @@ Each segment is defined by include and exclude filters:
Available fields for filtering:
kind
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: ` {taxonomy,term}`.
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: `{taxonomy,term}`.
lang
: (`string`) A [glob](g) pattern matching the [page language]. For example: `{en,de}`.
+1 -1
View File
@@ -47,7 +47,7 @@ to
## Headers
Include headers in every server response to facilitate testing, particularly for features like Content Security Policies.
Include headers in every server response to facilitate testing, particularly for features like [Content Security Policies].
[Content Security Policies]: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
+5 -4
View File
@@ -17,8 +17,8 @@ When creating a taxonomy:
Then use the value as the key in front matter:
<!-- markdownlint-disable MD007 MD032 -->
{{< code-toggle file=content/example.md fm=true >}}
---
title: Example
categories:
- vegetarian
@@ -27,7 +27,7 @@ tags:
- appetizer
- main course
{{< /code-toggle >}}
<!-- markdownlint-enable MD007 MD032 -->
If you do not expect to assign more than one [term](g) from a given taxonomy to a content page, you may use the singular form for both key and value:
{{< code-toggle file=hugo >}}
@@ -37,12 +37,13 @@ taxonomies:
Then in front matter:
<!-- markdownlint-disable MD007 MD032 -->
{{< code-toggle file=content/example.md fm=true >}}
---
title: Example
author:
- Robert Smith
{{< /code-toggle >}}
<!-- markdownlint-enable MD007 MD032 -->
The example above illustrates that even with a single term, the value is still provided as an array.
@@ -58,7 +59,7 @@ taxonomies:
To disable the taxonomy system, use the [`disableKinds`] setting in the root of your site configuration to disable the `taxonomy` and `term` page [kinds](g).
{{< code-toggle file=hugo >}}
disableKinds = ['categories','tags']
disableKinds = ['taxonomy','term']
{{< /code-toggle >}}
[`disableKinds`]: /configuration/all/#disablekinds
@@ -13,6 +13,7 @@ https://example.org/section/article.html
```
In its default configuration, Hugo generates [pretty URLs](g). For example:
```text
https://example.org/section/article/
```
@@ -69,7 +69,7 @@ title = 'Headless page'
To include the content and images on the home page:
```go-html-template {file="layouts/_default/home.html"}
```go-html-template {file="layouts/home.html"}
{{ with .Site.GetPage "/headless" }}
{{ .Content }}
{{ range .Resources.ByType "image" }}
@@ -127,7 +127,7 @@ In the front matter above, note that we have set `list` to `local` to include th
To include the content and images on the home page:
```go-html-template {file="layouts/_default/home.html"}
```go-html-template {file="layouts/home.html"}
{{ with .Site.GetPage "/headless" }}
{{ range .Pages }}
{{ .Content }}
@@ -186,7 +186,7 @@ render = 'always'
To render the glossary:
```go-html-template {file="layouts/glossary/list.html"}
```go-html-template {file="layouts/glossary/section.html"}
<dl>
{{ range .Pages }}
<dt>{{ .Title }}</dt>
@@ -34,7 +34,7 @@ For many websites, this is enough configuration. However, you also have the opti
Disqus has its own [internal template](/templates/embedded/#disqus) available, to render it add the following code where you want comments to appear:
```go-html-template
{{ template "_internal/disqus.html" . }}
{{ partial "disqus.html" . }}
```
## Alternatives
@@ -64,9 +64,4 @@ Open-source commenting systems:
[configuration]: /configuration/
[disquspartial]: /templates/embedded/#disqus
[disqussetup]: https://disqus.com/profile/signup/
[forum]: https://discourse.gohugo.io
[front matter]: /content-management/front-matter/
[kaijuissue]: https://github.com/spf13/kaiju/issues/new
[issotutorial]: https://stiobhart.net/2017-02-24-isso-comments/
[partials]: /templates/partial/
[MongoDB]: https://www.mongodb.com/
@@ -27,7 +27,7 @@ content/
└── _index.md
```
Each content adapter is named _content.gotmpl and uses the same [syntax] as templates in the `layouts` directory. You can use any of the [template functions] within a content adapter, as well as the methods described below.
Each content adapter is named `_content.gotmpl` and uses the same [syntax] as templates in the `layouts` directory. You can use any of the [template functions] within a content adapter, as well as the methods described below.
## Methods
@@ -71,7 +71,7 @@ Adds a page resource to the site.
Then retrieve the new page resource with something like:
```go-html-template {file="layouts/_default/single.html"}
```go-html-template {file="layouts/page.html"}
{{ with .Resources.Get "cover.jpg" }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
{{ end }}
@@ -90,7 +90,7 @@ Returns the `Site` to which the pages will be added.
### Store
Returns a persistent scratch pad to store and manipulate data. The main use case for this is to transfer values between executions when [EnableAllLanguages](#enablealllanguages) is set. See [examples](/methods/page/store/).
Returns a persistent "scratch pad" to store and manipulate data. The main use case for this is to transfer values between executions when [EnableAllLanguages](#enablealllanguages) is set. See [examples](/methods/page/store/).
```go-html-template {file="content/books/_content.gotmpl"}
{{ .Store.Set "key" "value" }}
@@ -99,7 +99,7 @@ Returns a persistent “scratch pad” to store and manipulate data. The main us
### EnableAllLanguages
By default, Hugo executes the content adapter for the language defined by the _content.gotmpl file. Use this method to activate the content adapter for all languages.
By default, Hugo executes the content adapter for the language defined by the `_content.gotmpl` file. Use this method to activate the content adapter for all languages.
```go-html-template {file="content/books/_content.gotmpl"}
{{ .EnableAllLanguages }}
@@ -153,7 +153,7 @@ Key|Description|Required
`title`|The resource title.|&nbsp;
> [!note]
> If the `content.value` is a string Hugo creates a new resource. If the `content.value` is a resource, Hugo obtains the value from the existing resource.
> When `content.value` is a string, Hugo generates a new resource with a publication path relative to the page. However, if `content.value` is already a resource, Hugo directly uses its value and publishes it relative to the site root. This latter method is more efficient.
>
> When setting the `path`, Hugo transforms the given string to a logical path. For example, setting `path` to `A B C/cover.jpg` produces a logical path of `/section/a-b-c/cover.jpg`.
@@ -161,112 +161,109 @@ Key|Description|Required
Create pages from remote data, where each page represents a book review.
### Step 1
Step 1
: Create the content structure.
Create the content structure.
```text
content/
└── books/
├── _content.gotmpl <-- content adapter
└── _index.md
```
```text
content/
└── books/
├── _content.gotmpl <-- content adapter
└── _index.md
```
Step 2
: Inspect the remote data to determine how to map key-value pairs to front matter fields.\
<https://gohugo.io/shared/examples/data/books.json>
### Step 2
Inspect the remote data to determine how to map key-value pairs to front matter fields.\
<https://gohugo.io/shared/examples/data/books.json>
Step 3
: Create the content adapter.
### Step 3
Create the content adapter.
```go-html-template {file="content/books/_content.gotmpl" copy=true}
{{/* Get remote data. */}}
{{ $data := dict }}
{{ $url := "https://gohugo.io/shared/examples/data/books.json" }}
{{ with try (resources.GetRemote $url) }}
{{ with .Err }}
{{ errorf "Unable to get remote resource %s: %s" $url . }}
{{ else with .Value }}
{{ $data = . | transform.Unmarshal }}
{{ else }}
{{ errorf "Unable to get remote resource %s" $url }}
{{ end }}
{{ end }}
{{/* Add pages and page resources. */}}
{{ range $data }}
{{/* Add page. */}}
{{ $content := dict "mediaType" "text/markdown" "value" .summary }}
{{ $dates := dict "date" (time.AsTime .date) }}
{{ $params := dict "author" .author "isbn" .isbn "rating" .rating "tags" .tags }}
{{ $page := dict
"content" $content
"dates" $dates
"kind" "page"
"params" $params
"path" .title
"title" .title
}}
{{ $.AddPage $page }}
{{/* Add page resource. */}}
{{ $item := . }}
{{ with $url := $item.cover }}
{{ with try (resources.GetRemote $url) }}
{{ with .Err }}
{{ errorf "Unable to get remote resource %s: %s" $url . }}
{{ else with .Value }}
{{ $content := dict "mediaType" .MediaType.Type "value" .Content }}
{{ $params := dict "alt" $item.title }}
{{ $resource := dict
"content" $content
"params" $params
"path" (printf "%s/cover.%s" $item.title .MediaType.SubType)
}}
{{ $.AddResource $resource }}
{{ else }}
{{ errorf "Unable to get remote resource %s" $url }}
{{ end }}
```go-html-template {file="content/books/_content.gotmpl" copy=true}
{{/* Get remote data. */}}
{{ $data := dict }}
{{ $url := "https://gohugo.io/shared/examples/data/books.json" }}
{{ with try (resources.GetRemote $url) }}
{{ with .Err }}
{{ errorf "Unable to get remote resource %s: %s" $url . }}
{{ else with .Value }}
{{ $data = . | transform.Unmarshal }}
{{ else }}
{{ errorf "Unable to get remote resource %s" $url }}
{{ end }}
{{ end }}
{{ end }}
```
{{/* Add pages and page resources. */}}
{{ range $data }}
### Step 4
{{/* Add page. */}}
{{ $content := dict "mediaType" "text/markdown" "value" .summary }}
{{ $dates := dict "date" (time.AsTime .date) }}
{{ $params := dict "author" .author "isbn" .isbn "rating" .rating "tags" .tags }}
{{ $page := dict
"content" $content
"dates" $dates
"kind" "page"
"params" $params
"path" .title
"title" .title
}}
{{ $.AddPage $page }}
Create a single template to render each book review.
```go-html-template {file="layouts/books/single.html" copy=true}
{{ define "main" }}
<h1>{{ .Title }}</h1>
{{ with .Resources.GetMatch "cover.*" }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="{{ .Params.alt }}">
{{ end }}
<p>Author: {{ .Params.author }}</p>
<p>
ISBN: {{ .Params.isbn }}<br>
Rating: {{ .Params.rating }}<br>
Review date: {{ .Date | time.Format ":date_long" }}
</p>
{{ with .GetTerms "tags" }}
<p>Tags:</p>
<ul>
{{ range . }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{/* Add page resource. */}}
{{ $item := . }}
{{ with $url := $item.cover }}
{{ with try (resources.GetRemote $url) }}
{{ with .Err }}
{{ errorf "Unable to get remote resource %s: %s" $url . }}
{{ else with .Value }}
{{ $content := dict "mediaType" .MediaType.Type "value" .Content }}
{{ $params := dict "alt" $item.title }}
{{ $resource := dict
"content" $content
"params" $params
"path" (printf "%s/cover.%s" $item.title .MediaType.SubType)
}}
{{ $.AddResource $resource }}
{{ else }}
{{ errorf "Unable to get remote resource %s" $url }}
{{ end }}
{{ end }}
</ul>
{{ end }}
{{ end }}
{{ .Content }}
{{ end }}
```
{{ end }}
```
Step 4
: Create a _page_ template to render each book review.
```go-html-template {file="layouts/books/page.html" copy=true}
{{ define "main" }}
<h1>{{ .Title }}</h1>
{{ with .Resources.GetMatch "cover.*" }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="{{ .Params.alt }}">
{{ end }}
<p>Author: {{ .Params.author }}</p>
<p>
ISBN: {{ .Params.isbn }}<br>
Rating: {{ .Params.rating }}<br>
Review date: {{ .Date | time.Format ":date_long" }}
</p>
{{ with .GetTerms "tags" }}
<p>Tags:</p>
<ul>
{{ range . }}
<li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li>
{{ end }}
</ul>
{{ end }}
{{ .Content }}
{{ end }}
```
## Multilingual sites
@@ -338,7 +335,7 @@ content/
└── the-hunchback-of-notre-dame.md
```
If the content adapter also creates books/the-hunchback-of-notre-dame, the content of the published page is indeterminate. You can not define the processing order.
If the content adapter also creates `books/the-hunchback-of-notre-dame`, the content of the published page is indeterminate. You can not define the processing order.
To detect page collisions, use the `--printPathWarnings` flag when building your site.
@@ -65,7 +65,7 @@ Use data sources to augment existing content. For example, create a shortcode to
{{</* csv-to-table "pets.csv" */>}}
```
```go-html-template {file="layouts/shortcodes/csv-to-table.html"}
```go-html-template {file="layouts/_shortcodes/csv-to-table.html"}
{{ with $file := .Get 0 }}
{{ with resources.Get $file }}
{{ with . | transform.Unmarshal }}
@@ -39,7 +39,7 @@ Will be rendered as:
Hugo does not provide a built-in template for Mermaid diagrams. Create your own using a [code block render hook]:
```go-html-template {file="layouts/_default/_markup/render-codeblock-mermaid.html" copy=true}
```go-html-template {file="layouts/_markup/render-codeblock-mermaid.html" copy=true}
<pre class="mermaid">
{{ .Inner | htmlEscape | safeHTML }}
</pre>
@@ -48,7 +48,7 @@ Hugo does not provide a built-in template for Mermaid diagrams. Create your own
Then include this snippet at the _bottom_ of your base template, before the closing `body` tag:
```go-html-template {file="layouts/_default/baseof.html" copy=true}
```go-html-template {file="layouts/baseof.html" copy=true}
{{ if .Store.Get "hasMermaid" }}
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs';
@@ -75,7 +75,7 @@ Create your content in the [Emacs Org Mode] format preceded by front matter. You
### AsciiDoc
Create your content in the [AsciiDoc] format preceded by front matter. Hugo renders AsciiDoc content to HTML using the Asciidoctor executable. You must install Asciidoctor and its dependencies (Ruby) to use the AsciiDoc content format.
Create your content in the [AsciiDoc] format preceded by front matter. Hugo renders AsciiDoc content to HTML using the Asciidoctor executable. You must install Asciidoctor and its dependencies (Ruby) to render the AsciiDoc content format.
You can configure the AsciiDoc renderer in your [site configuration][configure asciidoc].
@@ -92,12 +92,13 @@ hugo --logLevel info
```
[AsciiDoc]: https://asciidoc.org/
[configure the AsciiDoc renderer]: /configuration/markup/#asciidoc
[configure asciidoc]: /configuration/markup/#asciidoc
### Pandoc
Create your content in the [Pandoc] format preceded by front matter. Hugo renders Pandoc content to HTML using the Pandoc executable. You must install Pandoc to use the Pandoc content format.
Create your content in the [Pandoc] format[^1] preceded by front matter. Hugo renders Pandoc content to HTML using the Pandoc executable. You must install Pandoc to render the Pandoc content format.
[^1]: This is a derivation of the Markdown format as described by the CommonMark specification.
Hugo passes these CLI flags when calling the Pandoc executable:
@@ -105,11 +106,11 @@ Hugo passes these CLI flags when calling the Pandoc executable:
--mathjax
```
[Pandoc]: https://pandoc.org/
[Pandoc]: https://pandoc.org/MANUAL.html#pandocs-markdown
### reStructuredText
Create your content in the [reStructuredText] format preceded by front matter. Hugo renders reStructuredText content to HTML using [Docutils], specifically rst2html. You must install Docutils and its dependencies (Python) to use the reStructuredText content format.
Create your content in the [reStructuredText] format preceded by front matter. Hugo renders reStructuredText content to HTML using [Docutils], specifically rst2html. You must install Docutils and its dependencies (Python) to render the reStructuredText content format.
Hugo passes these CLI flags when calling the rst2html executable:
@@ -18,10 +18,6 @@ The front matter at the top of each content file is metadata that:
Provide front matter using a serialization format, one of [JSON], [TOML], or [YAML]. Hugo determines the front matter format by examining the delimiters that separate the front matter from the page content.
[json]: https://www.json.org/
[toml]: https://toml.io/
[yaml]: https://yaml.org/
See examples of front matter delimiters by toggling between the serialization formats below.
{{< code-toggle file=content/example.md fm=true >}}
@@ -115,7 +111,7 @@ sitemap
: (`map`) A map of sitemap options. See the [sitemap templates] page for details. Access these values from a template using the [`Sitemap`] method on a `Page` object.
slug
: (`string`) Overrides the last segment of the URL path. Not applicable to section pages. See the [URL management] page for details. Access this value from a template using the [`Slug`] method on a `Page` object.
: (`string`) Overrides the last segment of the URL path. Not applicable to `home`, `section`, `taxonomy`, or `term` pages. See the [URL management] page for details. Access this value from a template using the [`Slug`] method on a `Page` object.
summary
: (`string`) Conceptually different than the page `description`, the summary either summarizes the content or serves as a teaser to encourage readers to visit the page. Access this value from a template using the [`Summary`] method on a `Page` object.
@@ -138,42 +134,6 @@ url
weight
: (`int`) The page [weight](g), used to order the page within a [page collection](g). Access this value from a template using the [`Weight`] method on a `Page` object.
[URL management]: /content-management/urls/#slug
[`Summary`]: /methods/page/summary/
[`aliases`]: /methods/page/aliases/
[`date`]: /methods/page/date/
[`description`]: /methods/page/description/
[`draft`]: /methods/page/draft/
[`expirydate`]: /methods/page/expirydate/
[`fuzzywordcount`]: /methods/page/wordcount/
[`keywords`]: /methods/page/keywords/
[`lastmod`]: /methods/page/date/
[`layout`]: /methods/page/layout/
[`linktitle`]: /methods/page/linktitle/
[`publishdate`]: /methods/page/publishdate/
[`readingtime`]: /methods/page/readingtime/
[`sitemap`]: /methods/page/sitemap/
[`slug`]: /methods/page/slug/
[`summary`]: /methods/page/summary/
[`title`]: /methods/page/title/
[`translationkey`]: /methods/page/translationkey/
[`type`]: /methods/page/type/
[`weight`]: /methods/page/weight/
[`wordcount`]: /methods/page/wordcount/
[aliases]: /content-management/urls/#aliases
[build options]: /content-management/build-options/
[cascade]: #cascade-1
[configure outputs]: /configuration/outputs/#outputs-per-page
[content formats]: /content-management/formats/#classification
[leaf bundles]: /content-management/page-bundles/#leaf-bundles
[menus]: /content-management/menus/#define-in-front-matter
[output formats]: /configuration/output-formats/
[page parameters]: #parameters
[page resources]: /content-management/page-resources/#metadata
[sitemap templates]: /templates/sitemap/
[target a specific template]: /templates/lookup-order/#target-a-template
[template lookup order]: /templates/lookup-order/
## Parameters
{{< new-in 0.123.0 />}}
@@ -191,9 +151,6 @@ author = 'John Smith'
Access these values from a template using the [`Params`] or [`Param`] method on a `Page` object.
[`param`]: /methods/page/param/
[`params`]: /methods/page/params/
Hugo provides [embedded templates] to optionally insert meta data within the `head` element of your rendered pages. These embedded templates expect the following front matter parameters:
Parameter|Data type|Used by these embedded templates
@@ -237,7 +194,7 @@ You can add taxonomy terms to the front matter of any these [page kinds](g):
Access taxonomy terms from a template using the [`Params`] or [`GetTerms`] method on a `Page` object. For example:
```go-html-template {file="layouts/_default/single.html"}
```go-html-template {file="layouts/page.html"}
{{ with .GetTerms "tags" }}
<p>Tags</p>
<ul>
@@ -248,7 +205,6 @@ Access taxonomy terms from a template using the [`Params`] or [`GetTerms`] metho
{{ end }}
```
[`Params`]: /methods/page/params/
[`GetTerms`]: /methods/page/getterms/
## Cascade
@@ -289,7 +245,7 @@ environment
: (`string`) A [glob](g) pattern matching the build [environment](g). For example: `{staging,production}`.
kind
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: ` {taxonomy,term}`.
: (`string`) A [glob](g) pattern matching the [page kind](g). For example: `{taxonomy,term}`.
path
: (`string`) A [glob](g) pattern matching the page's [logical path](g). For example: `{/books,/books/**}`.
@@ -356,7 +312,46 @@ To override the default time zone, set the [`timeZone`](/configuration/all/#time
1. The time zone specified in your site configuration
1. The `Etc/UTC` time zone
[`aliases`]: /methods/page/aliases/
[`date`]: /methods/page/date/
[`description`]: /methods/page/description/
[`draft`]: /methods/page/draft/
[`expirydate`]: /methods/page/expirydate/
[`fuzzywordcount`]: /methods/page/wordcount/
[`keywords`]: /methods/page/keywords/
[`lastmod`]: /methods/page/date/
[`layout`]: /methods/page/layout/
[`linktitle`]: /methods/page/linktitle/
[`opengraph.html`]: {{% eturl opengraph %}}
[`Param`]: /methods/page/param/
[`Params`]: /methods/page/params/
[`publishdate`]: /methods/page/publishdate/
[`readingtime`]: /methods/page/readingtime/
[`schema.html`]: {{% eturl schema %}}
[`sitemap`]: /methods/page/sitemap/
[`slug`]: /methods/page/slug/
[`Summary`]: /methods/page/summary/
[`title`]: /methods/page/title/
[`translationkey`]: /methods/page/translationkey/
[`twitter_cards.html`]: {{% eturl twitter_cards %}}
[`type`]: /methods/page/type/
[`weight`]: /methods/page/weight/
[`wordcount`]: /methods/page/wordcount/
[aliases]: /content-management/urls/#aliases
[build options]: /content-management/build-options/
[cascade]: #cascade-1
[configure outputs]: /configuration/outputs/#outputs-per-page
[content formats]: /content-management/formats/#classification
[embedded templates]: /templates/embedded/
[json]: https://www.json.org/
[leaf bundles]: /content-management/page-bundles/#leaf-bundles
[menus]: /content-management/menus/#define-in-front-matter
[output formats]: /configuration/output-formats/
[page parameters]: #parameters
[page resources]: /content-management/page-resources/#metadata
[sitemap templates]: /templates/sitemap/
[target a specific template]: /templates/lookup-order/#target-a-template
[template lookup order]: /templates/lookup-order/
[toml]: https://toml.io/
[URL management]: /content-management/urls/#slug
[yaml]: https://yaml.org/
@@ -45,126 +45,123 @@ Whether an equation or expression appears inline, or as a block, depends on the
Follow these instructions to include mathematical equations and expressions in your Markdown using LaTeX markup.
### Step 1
Step 1
: Enable and configure the Goldmark [passthrough extension] in your site configuration. The passthrough extension preserves raw Markdown within delimited snippets of text, including the delimiters themselves.
Enable and configure the Goldmark [passthrough extension] in your site configuration. The passthrough extension preserves raw Markdown within delimited snippets of text, including the delimiters themselves.
{{< code-toggle file=hugo copy=true >}}
[markup.goldmark.extensions.passthrough]
enable = true
{{< code-toggle file=hugo copy=true >}}
[markup.goldmark.extensions.passthrough]
enable = true
[markup.goldmark.extensions.passthrough.delimiters]
block = [['\[', '\]'], ['$$', '$$']]
inline = [['\(', '\)']]
[markup.goldmark.extensions.passthrough.delimiters]
block = [['\[', '\]'], ['$$', '$$']]
inline = [['\(', '\)']]
[params]
math = true
{{< /code-toggle >}}
[params]
math = true
{{< /code-toggle >}}
The configuration above enables mathematical rendering on every page unless you set the `math` parameter to `false` in front matter. To enable mathematical rendering as needed, set the `math` parameter to `false` in your site configuration, and set the `math` parameter to `true` in front matter. Use this parameter in your base template as shown in [Step 3](#step-3).
The configuration above enables mathematical rendering on every page unless you set the `math` parameter to `false` in front matter. To enable mathematical rendering as needed, set the `math` parameter to `false` in your site configuration, and set the `math` parameter to `true` in front matter. Use this parameter in your base template as shown in [Step 3].
> [!note]
> The configuration above precludes the use of the `$...$` delimiter pair for inline equations. Although you can add this delimiter pair to the configuration and JavaScript, you must double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting.
>
> See the [inline delimiters](#inline-delimiters) section for details.
> [!note]
> The configuration above precludes the use of the `$...$` delimiter pair for inline equations. Although you can add this delimiter pair to the configuration and JavaScript, you will need to double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting.
>
> See the [inline delimiters](#inline-delimiters) section for details.
To disable passthrough of inline snippets, omit the `inline` key from the configuration:
To disable passthrough of inline snippets, omit the `inline` key from the configuration:
{{< code-toggle file=hugo >}}
[markup.goldmark.extensions.passthrough.delimiters]
block = [['\[', '\]'], ['$$', '$$']]
{{< /code-toggle >}}
{{< code-toggle file=hugo >}}
[markup.goldmark.extensions.passthrough.delimiters]
block = [['\[', '\]'], ['$$', '$$']]
{{< /code-toggle >}}
You can define your own opening and closing delimiters, provided they match the delimiters that you set in [Step 2].
You can define your own opening and closing delimiters, provided they match the delimiters that you set in [Step 2].
{{< code-toggle file=hugo >}}
[markup.goldmark.extensions.passthrough.delimiters]
block = [['@@', '@@']]
inline = [['@', '@']]
{{< /code-toggle >}}
{{< code-toggle file=hugo >}}
[markup.goldmark.extensions.passthrough.delimiters]
block = [['@@', '@@']]
inline = [['@', '@']]
{{< /code-toggle >}}
Step 2
: Create a _partial_ template to load MathJax or KaTeX. The example below loads MathJax, or you can use KaTeX as described in the [engines](#engines) section.
### Step 2
```go-html-template {file="layouts/_partials/math.html" copy=true}
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
<script>
MathJax = {
tex: {
displayMath: [['\\[', '\\]'], ['$$', '$$']], // block
inlineMath: [['\\(', '\\)']] // inline
},
loader:{
load: ['ui/safe']
},
};
</script>
```
Create a partial template to load MathJax or KaTeX. The example below loads MathJax, or you can use KaTeX as described in the [engines](#engines) section.
The delimiters above must match the delimiters in your site configuration.
```go-html-template {file="layouts/partials/math.html" copy=true}
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
<script>
MathJax = {
tex: {
displayMath: [['\\[', '\\]'], ['$$', '$$']], // block
inlineMath: [['\\(', '\\)']] // inline
},
loader:{
load: ['ui/safe']
},
};
</script>
```
Step 3
: Conditionally call the _partial_ template from the base template.
The delimiters above must match the delimiters in your site configuration.
```go-html-template {file="layouts/baseof.html"}
<head>
...
{{ if .Param "math" }}
{{ partialCached "math.html" . }}
{{ end }}
...
</head>
```
### Step 3
The example above loads the _partial_ template if you have set the `math` parameter in front matter to `true`. If you have not set the `math` parameter in front matter, the conditional statement falls back to the `math` parameter in your site configuration.
Conditionally call the partial template from the base template.
Step 4
: If you set the `math` parameter to `false` in your site configuration, you must set the `math` parameter to `true` in front matter. For example:
```go-html-template {file="layouts/_default/baseof.html"}
<head>
...
{{ if .Param "math" }}
{{ partialCached "math.html" . }}
{{ end }}
...
</head>
```
{{< code-toggle file=content/math-examples.md fm=true >}}
title = 'Math examples'
date = 2024-01-24T18:09:49-08:00
[params]
math = true
{{< /code-toggle >}}
The example above loads the partial template if you have set the `math` parameter in front matter to `true`. If you have not set the `math` parameter in front matter, the conditional statement falls back to the `math` parameter in your site configuration.
Step 5
: Include mathematical equations and expressions in Markdown using LaTeX markup.
### Step 4
```text {file="content/math-examples.md" copy=true}
This is an inline \(a^*=x-b^*\) equation.
Include mathematical equations and expressions in Markdown using LaTeX markup.
These are block equations:
```text {file="content/math-examples.md" copy=true}
This is an inline \(a^*=x-b^*\) equation.
\[a^*=x-b^*\]
These are block equations:
\[ a^*=x-b^* \]
\[a^*=x-b^*\]
\[
a^*=x-b^*
\]
\[ a^*=x-b^* \]
These are also block equations:
\[
a^*=x-b^*
\]
$$a^*=x-b^*$$
These are also block equations:
$$ a^*=x-b^* $$
$$a^*=x-b^*$$
$$ a^*=x-b^* $$
$$
a^*=x-b^*
$$
```
If you set the `math` parameter to `false` in your site configuration, you must set the `math` parameter to `true` in front matter. For example:
{{< code-toggle file=content/math-examples.md fm=true >}}
title = 'Math examples'
date = 2024-01-24T18:09:49-08:00
[params]
math = true
{{< /code-toggle >}}
$$
a^*=x-b^*
$$
```
## Inline delimiters
The configuration, JavaScript, and examples above use the `\(...\)` delimiter pair for inline equations. The `$...$` delimiter pair is a common alternative, but using it may result in unintended formatting if you use the `$` symbol outside of math contexts.
If you add the `$...$` delimiter pair to your configuration and JavaScript, you must double-escape the `$` when outside of math contexts, regardless of whether mathematical rendering is enabled on the page. For example:
If you add the `$...$` delimiter pair to your configuration and JavaScript, you must double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting. For example:
```text
A \\$5 bill _saved_ is a \\$5 bill _earned_.
I will give you \\$2 if you can solve $y = x^2$.
```
> [!note]
@@ -179,9 +176,9 @@ MathJax and KaTeX are open-source JavaScript display engines. Both engines are f
>
>See the [inline delimiters](#inline-delimiters) section for details.
To use KaTeX instead of MathJax, replace the partial template from [Step 2] with this:
To use KaTeX instead of MathJax, replace the _partial_ template from [Step 2] with this:
```go-html-template {file="layouts/partials/math.html" copy=true}
```go-html-template {file="layouts/_partials/math.html" copy=true}
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css"
@@ -227,12 +224,10 @@ $$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$
$$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$
As shown in [Step 2] above, MathJax supports chemical equations without additional configuration. To add chemistry support to KaTeX, enable the mhchem extension as described in the KaTeX [documentation](https://katex.org/docs/libs).
As shown in [Step 2](#step-2) above, MathJax supports chemical equations without additional configuration. To add chemistry support to KaTeX, enable the mhchem extension as described in the KaTeX [documentation](https://katex.org/docs/libs).
[`transform.ToMath`]: /functions/transform/tomath/
[KaTeX]: https://katex.org/
[LaTeX]: https://www.latex-project.org/
[MathJax]: https://www.mathjax.org/
[passthrough extension]: /configuration/markup/#passthrough
[Step 2]: #step-2
[Step 3]: #step-3
@@ -68,6 +68,7 @@ Use these properties when defining menu entries in front matter:
This front matter menu entry demonstrates some of the available properties:
<!-- markdownlint-disable MD033 -->
{{< code-toggle file=content/products/software.md fm=true >}}
title = 'Software'
[menus.main]
@@ -77,6 +78,7 @@ pre = '<i class="fa-solid fa-code"></i>'
[menus.main.params]
class = 'center'
{{< /code-toggle >}}
<!-- markdownlint-enable MD033 -->
Access the entry with `site.Menus.main` in your templates. See [menu templates] for details.
@@ -25,9 +25,9 @@ Considering the following example:
The first file is assigned the English language and is linked to the second.
The second file is assigned the French language and is linked to the first.
Their language is __assigned__ according to the language code added as a __suffix to the file name__.
Their language is assigned according to the language code added as a suffix to the file name.
By having the same **path and base file name**, the content pieces are __linked__ together as translated pages.
By having the same path and base file name, the content pieces are linked together as translated pages.
> [!note]
> If a file has no language code, it will be assigned the default language.
@@ -58,9 +58,9 @@ Considering the following example in conjunction with the configuration above:
The first file is assigned the English language and is linked to the second.
The second file is assigned the French language and is linked to the first.
Their language is __assigned__ according to the `content` directory they are __placed__ in.
Their language is assigned according to the `content` directory they are placed in.
By having the same **path and basename** (relative to their language `content` directory), the content pieces are __linked__ together as translated pages.
By having the same path and basename (relative to their language `content` directory), the content pieces are linked together as translated pages.
### Bypassing default linking
@@ -76,7 +76,7 @@ Considering the following example:
translationKey: "about"
{{< /code-toggle >}}
By setting the `translationKey` front matter parameter to `about` in all three pages, they will be __linked__ as translated pages.
By setting the `translationKey` front matter parameter to `about` in all three pages, they will be linked as translated pages.
### Localizing permalinks
@@ -114,7 +114,7 @@ If, across the linked bundles, two or more files share the same basename, only o
To create a list of links to translated content, use a template similar to the following:
```go-html-template {file="layouts/partials/i18nlist.html"}
```go-html-template {file="layouts/_partials/i18nlist.html"}
{{ if .IsTranslated }}
<h4>{{ i18n "translations" }}</h4>
<ul>
@@ -127,7 +127,7 @@ To create a list of links to translated content, use a template similar to the f
{{ end }}
```
The above can be put in a `partial` (i.e., inside `layouts/partials/`) and included in any template. It will not print anything if there are no translations for a given page.
The above can be put in a _partial_ template then included in any template. It will not print anything if there are no translations for a given page.
The above also uses the [`i18n` function][i18func] described in the next section.
@@ -135,7 +135,7 @@ The above also uses the [`i18n` function][i18func] described in the next section
`.AllTranslations` on a `Page` can be used to list all translations, including the page itself. On the home page it can be used to build a language navigator:
```go-html-template {file="layouts/partials/allLanguages.html"}
```go-html-template {file="layouts/_partials/allLanguages.html"}
<ul>
{{ range $.Site.Home.AllTranslations }}
<li><a href="{{ .RelPermalink }}">{{ .Language.LanguageName }}</a></li>
@@ -99,7 +99,7 @@ The [sections] can be nested as deeply as you want. The important thing to under
### Single pages in sections
Single content files in each of your sections will be rendered by a [single template]. Here is an example of a single `post` within `posts`:
Single content files in each of your sections will be rendered by a [page template]. Here is an example of a single `post` within `posts`:
```txt
path ("posts/my-first-hugo-post.md")
@@ -128,7 +128,7 @@ The following concepts provide more insight into the relationship between your p
### `section`
A default content type is determined by the section in which a content item is stored. `section` is determined by the location within the project's `content` directory. `section` *cannot* be specified or overridden in front matter.
A default content type is determined by the section in which a content item is stored. `section` is determined by the location within the project's `content` directory. `section` cannot be specified or overridden in front matter.
### `slug`
@@ -148,4 +148,4 @@ The `url` is the entire URL path, defined by the file path and optionally overri
[config]: /configuration/
[pretty]: /content-management/urls/#appearance
[sections]: /content-management/sections/
[single template]: /templates/types/#single
[page template]: /templates/types/#page
@@ -38,10 +38,10 @@ Page bundle characteristics vary by bundle type.
| | Leaf bundle | Branch bundle |
|---------------------|---------------------------------------------------------|---------------------------------------------------------|
| Index file | `index.md` | `_index.md` |
| Example | `content/about/index.md` | `content/posts/_index.md ` |
| Index file | `index.md` | `_index.md` |
| Example | `content/about/index.md` | `content/posts/_index.md` |
| [Page kinds](g) | `page` | `home`, `section`, `taxonomy`, or `term` |
| Template types | [single] | [home], [section], [taxonomy], or [term] |
| Template types | [single] | [home], [section], [taxonomy], or [term] |
| Descendant pages | None | Zero or more |
| Resource location | Adjacent to the index file or in a nested subdirectory | Same as a leaf bundles, but excludes descendant bundles |
| [Resource types](g) | `page`, `image`, `video`, etc. | all but `page` |
@@ -35,10 +35,10 @@ content
Use any of these methods on a `Page` object to capture page resources:
- [`Resources.ByType`]
- [`Resources.Get`]
- [`Resources.GetMatch`]
- [`Resources.Match`]
- [`Resources.ByType`]
- [`Resources.Get`]
- [`Resources.GetMatch`]
- [`Resources.Match`]
Once you have captured a resource, use any of the applicable [`Resource`] methods to return a value or perform an action.
@@ -125,30 +125,32 @@ params
### Resources metadata example
<!-- markdownlint-disable MD007 MD032 -->
{{< code-toggle file=content/example.md fm=true >}}
title: Application
date : 2018-01-25
resources :
- src : "images/sunset.jpg"
name : "header"
- src : "documents/photo_specs.pdf"
title : "Photo Specifications"
params:
icon : "photo"
- src : "documents/guide.pdf"
title : "Instruction Guide"
- src : "documents/checklist.pdf"
title : "Document Checklist"
- src : "documents/payment.docx"
title : "Proof of Payment"
- src : "**.pdf"
name : "pdf-file-:counter"
params :
icon : "pdf"
- src : "**.docx"
params :
icon : "word"
date: 2018-01-25
resources:
- src: images/sunset.jpg
name: header
- src: documents/photo_specs.pdf
title: Photo Specifications
params:
icon: photo
- src: documents/guide.pdf
title: Instruction Guide
- src: documents/checklist.pdf
title: Document Checklist
- src: documents/payment.docx
title: Proof of Payment
- src: "**.pdf"
name: pdf-file-:counter
params:
icon: pdf
- src: "**.docx"
params:
icon: word
{{</ code-toggle >}}
<!-- markdownlint-enable MD007 MD032 -->
From the example above:
@@ -271,12 +273,12 @@ public/
This approach reduces build times, storage requirements, bandwidth consumption, and deployment times, ultimately reducing cost.
> [!note]
> [!important]
> To resolve Markdown link and image destinations to the correct location, you must use link and image render hooks that capture the page resource with the [`Resources.Get`] method, and then invoke its [`RelPermalink`] method.
>
> By default, with multilingual single-host sites, Hugo enables its [embedded link render hook] and [embedded image render hook] to resolve Markdown link and image destinations.
> In its default configuration, Hugo automatically uses the [embedded link render hook] and the [embedded image render hook] for multilingual single-host sites, specifically when the [duplication of shared page resources] feature is disabled. This is the default behavior for such sites. If custom link or image render hooks are defined by your project, modules, or themes, these will be used instead.
>
> You may override the embedded render hooks as needed, provided they capture the resource as described above.
> You can also configure Hugo to `always` use the embedded link or image render hook, use it only as a `fallback`, or `never` use it. See&nbsp;[details](/configuration/markup/#renderhookslinkuseembedded).
Although duplicating shared page resources is inefficient, you can enable this feature in your site configuration if desired:
@@ -288,10 +290,10 @@ duplicateResourceFiles = true
[`RelPermalink`]: /methods/resource/relpermalink/
[`Resource`]: /methods/resource
[`Resources.ByType`]: /methods/page/resources#bytype
[`Resources.Get`]: /methods/page/resources#get
[`Resources.Get`]: /methods/page/resources/#get
[`Resources.GetMatch`]: /methods/page/resources#getmatch
[`Resources.Match`]: /methods/page/resources#match
[content formats]: /content-management/formats/
[embedded image render hook]: /render-hooks/images/#default
[embedded link render hook]: /render-hooks/links/#default
[duplication of shared page resources]: /configuration/markup/#duplicateresourcefiles
[embedded image render hook]: /render-hooks/images/#embedded
[embedded link render hook]: /render-hooks/links/#embedded
@@ -12,7 +12,7 @@ Hugo uses a set of factors to identify a page's related content based on front m
To list up to 5 related pages (which share the same _date_ or _keyword_ parameters) is as simple as including something similar to this partial in your template:
```go-html-template {file="layouts/partials/related.html" copy=true}
```go-html-template {file="layouts/_partials/related.html" copy=true}
{{ with site.RegularPages.Related . | first 5 }}
<p>Related content:</p>
<ul>
+10 -10
View File
@@ -53,7 +53,7 @@ The example above has two top-level sections: articles and products. None of the
Sections and non-sections behave differently.
||Sections|Non-sections
&nbsp;|Sections|Non-sections
:--|:-:|:-:
Directory names become URL segments|:heavy_check_mark:|:heavy_check_mark:
Have logical ancestors and descendants|:heavy_check_mark:|:x:
@@ -63,7 +63,7 @@ With the file structure from the [example above](#overview):
1. The list page for the articles section includes all articles, regardless of directory structure; none of the subdirectories are sections.
1. The articles/2022 and articles/2023 directories do not have list pages; they are not sections.
1. The list page for the products section, by default, includes product-1 and product-2, but not their descendant pages. To include descendant pages, use the `RegularPagesRecursive` method instead of the `Pages` method in the list template.
1. The list page for the products section, by default, includes product-1 and product-2, but not their descendant pages. To include descendant pages, use the `RegularPagesRecursive` method instead of the `Pages` method in the _section_ template.
1. All directories in the products section have list pages; each directory is a section.
## Template selection
@@ -74,15 +74,15 @@ With the file structure from the [example above](#overview):
Content directory|Section template
:--|:--
`content/products`|`layouts/products/list.html`
`content/products/product-1`|`layouts/products/list.html`
`content/products/product-1/benefits`|`layouts/products/list.html`
`content/products`|`layouts/products/section.html`
`content/products/product-1`|`layouts/products/section.html`
`content/products/product-1/benefits`|`layouts/products/section.html`
Content directory|Single template
Content directory|Page template
:--|:--
`content/products`|`layouts/products/single.html`
`content/products/product-1`|`layouts/products/single.html`
`content/products/product-1/benefits`|`layouts/products/single.html`
`content/products`|`layouts/products/page.html`
`content/products/product-1`|`layouts/products/page.html`
`content/products/product-1/benefits`|`layouts/products/page.html`
If you need to use a different template for a subsection, specify `type` and/or `layout` in front matter.
@@ -98,7 +98,7 @@ The content file (benefit-1.md) has four ancestors: benefits, product-1, product
For example, use the `.Ancestors` method to render breadcrumb navigation.
```go-html-template {file="layouts/partials/breadcrumb.html"}
```go-html-template {file="layouts/_partials/breadcrumb.html"}
<nav aria-label="breadcrumb" class="breadcrumb">
<ol>
{{ range .Ancestors.Reverse }}
@@ -20,9 +20,9 @@ Hugo's embedded shortcodes are pre-defined templates within the application. Ref
## Custom
Create custom shortcodes to simplify and standardize content creation. For example, the following shortcode template generates an audio player using a [global resource](g):
Create custom shortcodes to simplify and standardize content creation. For example, the following _shortcode_ template generates an audio player using a [global resource](g):
```go-html-template {file="layouts/shortcodes/audio.html"}
```go-html-template {file="layouts/_shortcodes/audio.html"}
{{ with resources.Get (.Get "src") }}
<audio controls preload="auto" src="{{ .RelPermalink }}"></audio>
{{ end }}
@@ -38,11 +38,11 @@ Learn more about creating shortcodes in the [shortcode templates] section.
## Inline
An inline shortcode is a shortcode template defined within content.
An inline shortcode is a _shortcode_ template defined within content.
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.
To conform with this security model, creating shortcode templates within content is disabled by default. If you trust your content authors, you can enable this functionality in your site's configuration:
To conform with this security model, creating _shortcode_ templates within content is disabled by default. If you trust your content authors, you can enable this functionality in your site's configuration:
{{< code-toggle file=hugo >}}
[security]
@@ -69,7 +69,7 @@ In the example above, the inline shortcode is executed twice: once upon definiti
<p>Today is Thursday, January 30, 2025</p>
```
Inline shortcodes process their inner content within the same context as regular shortcode templates, allowing you to use any available [shortcode method].
Inline shortcodes process their inner content within the same context as regular _shortcode_ templates, allowing you to use any available [shortcode method].
> [!note]
> You cannot [nest](#nesting) inline shortcodes.
@@ -179,9 +179,9 @@ Hugo processes the shortcode before the page content is rendered by the Markdown
With standard notation, Hugo processes the shortcode separately, merging the output into the page content after Markdown rendering. This means, for instance, that Markdown headings inside a standard-notation shortcode will be excluded when invoking the `TableOfContents` method on the `Page` object.
By way of example, with this shortcode template:
By way of example, with this _shortcode_ template:
```go-html-template {file="layouts/shortcodes/foo.html"}
```go-html-template {file="layouts/_shortcodes/foo.html"}
{{ .Inner }}
```
@@ -32,7 +32,7 @@ Let's assume you are making a website about movies. You may want to include the
- Year
- Awards
Then, in each of the movies, you would specify terms for each of these taxonomies (i.e., in the [front matter] of each of your movie content files). From these terms, Hugo would automatically create pages for each Actor, Director, Studio, Genre, Year, and Award, with each listing all of the Movies that matched that specific Actor, Director, Studio, Genre, Year, and Award.
Then, in each of the movies, you would specify terms for each of these taxonomies (i.e., in the front matter of each of your movie content files). From these terms, Hugo would automatically create pages for each Actor, Director, Studio, Genre, Year, and Award, with each listing all of the Movies that matched that specific Actor, Director, Studio, Genre, Year, and Award.
### Movie taxonomy organization
@@ -71,10 +71,10 @@ Moonrise Kingdom <- Value
### Default destinations
When taxonomies are used---and [taxonomy templates] are provided---Hugo will automatically create both a page listing all the taxonomy's terms and individual pages with lists of content associated with each term. For example, a `categories` taxonomy declared in your configuration and used in your content front matter will create the following pages:
When taxonomies are used Hugo will automatically create both a page listing all the taxonomy's terms and individual pages with lists of content associated with each term. For example, a `categories` taxonomy declared in your configuration and used in your content front matter will create the following pages:
- A single page at `example.com/categories/` that lists all the terms within the taxonomy
- [Individual taxonomy list pages][taxonomy templates] (e.g., `/categories/development/`) for each of the terms that shows a listing of all pages marked as part of that taxonomy within any content file's [front matter]
- Individual taxonomy list pages (e.g., `/categories/development/`) for each of the terms that shows a listing of all pages marked as part of that taxonomy within any content file's front matter
## Configuration
@@ -92,7 +92,7 @@ categories = ['Category A','Category B']
## Order taxonomies
A content file can assign weight for each of its associate taxonomies. Taxonomic weight can be used for sorting or ordering content in [taxonomy templates] and is declared in a content file's [front matter]. The convention for declaring taxonomic weight is `taxonomyname_weight`.
A content file can assign weight for each of its associate taxonomies. Taxonomic weight can be used for sorting or ordering content in taxonomy templates and is declared in a content file's front matter. The convention for declaring taxonomic weight is `taxonomyname_weight`.
The following show a piece of content that has a weight of 22, which can be used for ordering purposes when rendering the pages assigned to the "a", "b" and "c" values of the `tags` taxonomy. It has also been assigned the weight of 44 when rendering the "d" category page.
@@ -108,18 +108,73 @@ categories_weight = 44
By using taxonomic weight, the same piece of content can appear in different positions in different taxonomies.
## Add custom metadata to a taxonomy or term
## Metadata
If you need to add custom metadata to your taxonomy terms, you will need to create a page for that term at `/content/<TAXONOMY>/<TERM>/_index.md` and add your metadata in its front matter. Continuing with our 'Actors' example, let's say you want to add a Wikipedia page link to each actor. Your terms pages would be something like this:
Display metadata about each term by creating a corresponding branch bundle in the `content` directory.
{{< code-toggle file=content/actors/bruce-willis/_index.md fm=true >}}
title: "Bruce Willis"
wikipedia: "https://en.wikipedia.org/wiki/Bruce_Willis"
For example, create an "authors" taxonomy:
{{< code-toggle file=hugo >}}
[taxonomies]
author = 'authors'
{{< /code-toggle >}}
[content section]: /content-management/sections/
[content type]: /content-management/types/
[documentation on archetypes]: /content-management/archetypes/
[front matter]: /content-management/front-matter/
[taxonomy templates]: /templates/types/#taxonomy
[site configuration]: /configuration/
Then create content with one [branch bundle](g) for each term:
```text
content/
└── authors/
├── jsmith/
│ ├── _index.md
│ └── portrait.jpg
└── rjones/
├── _index.md
└── portrait.jpg
```
Then add front matter to each term page:
{{< code-toggle file=content/authors/jsmith/_index.md fm=true >}}
title = "John Smith"
affiliation = "University of Chicago"
{{< /code-toggle >}}
Then create a _taxonomy_ template specific to the "authors" taxonomy:
```go-html-template {file="layouts/authors/taxonomy.html"}
{{ define "main" }}
<h1>{{ .Title }}</h1>
{{ .Content }}
{{ range .Data.Terms.Alphabetical }}
<h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a></h2>
<p>Affiliation: {{ .Page.Params.Affiliation }}</p>
{{ with .Page.Resources.Get "portrait.jpg" }}
{{ with .Fill "100x100" }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="portrait">
{{ end }}
{{ end }}
{{ end }}
{{ end }}
```
In the example above we list each author including their affiliation and portrait.
Or create a _term_ template specific to the "authors" taxonomy:
```go-html-template {file="layouts/authors/term.html"}
{{ define "main" }}
<h1>{{ .Title }}</h1>
<p>Affiliation: {{ .Params.affiliation }}</p>
{{ with .Resources.Get "portrait.jpg" }}
{{ with .Fill "100x100" }}
<img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="portrait">
{{ end }}
{{ end }}
{{ .Content }}
{{ range .Pages }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ end }}
{{ end }}
```
In the example above we display the author including their affiliation and portrait, then a list of associated content.
@@ -1,14 +0,0 @@
---
title: Content types
description: Hugo is built around content organized in sections.
categories: []
keywords: []
aliases: [/content/types]
---
A **content type** is a way to organize your content. Hugo resolves the content type from either the `type` in front matter or, if not set, the first directory in the file path. E.g. `content/blog/my-first-event.md` will be of type `blog` if no `type` is set.
A content type is used to
- Determine how the content is rendered. See [Template Lookup Order](/templates/lookup-order/) and [Content Views](/templates/content-view) for more.
- Determine which [archetype](/content-management/archetypes/) template to use for new content.

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