Merge commit 'bfa74537929f409fca841540b971125b7678963a'

This commit is contained in:
Bjørn Erik Pedersen
2025-08-23 12:39:28 +02:00
196 changed files with 2243 additions and 1951 deletions
+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
+13 -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,6 +71,7 @@
"templating",
"transpile",
"unmarshal",
"unmarshaled",
"unmarshaling",
"unmarshals",
"# ----------------------------------------------------------------------",
@@ -100,6 +108,8 @@
"descripción",
"dokumentation",
"erklärungen",
"español",
"français",
"libros",
"mercredi",
"miesiąc",
@@ -147,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,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,7 +32,7 @@ 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/taxonomy.html"}
{{ $taxonomyObject := .Data.Terms }}
@@ -73,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
@@ -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.
-1
View File
@@ -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
+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/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://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
+46 -49
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/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,7 +148,7 @@ 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 `page.json.json`, you'll see:
@@ -163,7 +159,7 @@ For example, in `page.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 `page.json.json` template:
@@ -176,7 +172,7 @@ With `permalinkable` set to true for `json` in the same `page.json.json` templat
## 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:
@@ -193,17 +189,18 @@ Output format|Template path
`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,7 +95,7 @@ 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}
{{ with site.RegularPages.Related . | first 5 }}
+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
+4 -3
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.
@@ -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/
```
@@ -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/
@@ -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 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>
{{/* 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
@@ -92,7 +92,6 @@ hugo --logLevel info
```
[AsciiDoc]: https://asciidoc.org/
[configure the AsciiDoc renderer]: /configuration/markup/#asciidoc
[configure asciidoc]: /configuration/markup/#asciidoc
### Pandoc
@@ -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
@@ -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,117 +45,114 @@ 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 must 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/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
@@ -179,7 +176,7 @@ 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}
<link
@@ -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
@@ -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 template then 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.
@@ -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`
@@ -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
@@ -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 section 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
@@ -20,7 +20,7 @@ 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"}
{{ with resources.Get (.Get "src") }}
@@ -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,7 +179,7 @@ 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"}
{{ .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.
@@ -139,7 +139,7 @@ title = "John Smith"
affiliation = "University of Chicago"
{{< /code-toggle >}}
Then create a taxonomy template specific to the "authors" taxonomy:
Then create a _taxonomy_ template specific to the "authors" taxonomy:
```go-html-template {file="layouts/authors/taxonomy.html"}
{{ define "main" }}
@@ -159,7 +159,7 @@ Then create a taxonomy template specific to the "authors" taxonomy:
In the example above we list each author including their affiliation and portrait.
Or create a term template specific to the "authors" taxonomy:
Or create a _term_ template specific to the "authors" taxonomy:
```go-html-template {file="layouts/authors/term.html"}
{{ define "main" }}
+2 -1
View File
@@ -20,7 +20,7 @@ You can change the structure and appearance of URLs with front matter values and
### `slug`
Set the `slug` in front matter to override the last segment of the path. The `slug` value does not affect section pages.
Set the `slug` in front matter to override the last segment of the path. This front matter field is not applicable to `home`, `section`, `taxonomy`, or `term` pages.
{{< code-toggle file=content/posts/post-1.md fm=true >}}
title = 'My First Post'
@@ -39,6 +39,7 @@ Set the `url` in front matter to override the entire path. Use this with either
> [!note]
> Hugo does not sanitize the `url` front matter field, allowing you to generate:
>
> - File paths that contain characters reserved by the operating system. For example, file paths on Windows may not contain any of these [reserved characters]. Hugo throws an error if a file path includes a character reserved by the current operating system.
> - URLs that contain disallowed characters. For example, the less than sign (`<`) is not allowed in a URL.
+60 -70
View File
@@ -46,99 +46,89 @@ To build the extended or extended/deploy edition from source you must:
Use this workflow to create and submit pull requests.
### Step 1
Step 1
: Fork the [project repository].
Fork the [project repository].
Step 2
: Clone your fork.
### Step 2
Step 3
: Create a new branch with a descriptive name that includes the corresponding issue number.
Clone your fork.
For a new feature:
### Step 3
```sh
git checkout -b feat/implement-some-feature-99999
```
Create a new branch with a descriptive name that includes the corresponding issue number.
For a bug fix:
For a new feature:
```sh
git checkout -b fix/fix-some-bug-99999
```
```sh
git checkout -b feat/implement-some-feature-99999
```
Step 4
: Make changes.
For a bug fix:
Step 5
: Compile and install.
```sh
git checkout -b fix/fix-some-bug-99999
```
To compile and install the standard edition:
### Step 4
```text
go install
```
Make changes.
To compile and install the extended edition:
### Step 5
```text
CGO_ENABLED=1 go install -tags extended
```
Compile and install.
To compile and install the extended/deploy edition:
To compile and install the standard edition:
```text
CGO_ENABLED=1 go install -tags extended,withdeploy
```
```text
go install
```
Step 6
: Test your changes:
To compile and install the extended edition:
```text
go test ./...
```
```text
CGO_ENABLED=1 go install -tags extended
```
Step 7
: Commit your changes with a descriptive commit message:
To compile and install the extended/deploy edition:
- Provide a summary on the first line, typically 50 characters or less, followed by a blank line.
- Begin the summary with one of content, theme, config, all, or misc, followed by a colon, a space, and a brief description of the change beginning with a capital letter
- Use imperative present tense
- See the [commit message guidelines] for requirements
- Optionally, provide a detailed description where each line is 72 characters or less, followed by a blank line.
- Add one or more "Fixes" or "Closes" keywords, each on its own line, referencing the [issues] addressed by this change.
```text
CGO_ENABLED=1 go install -tags extended,withdeploy
```
For example:
### Step 6
```sh
git commit -m "tpl/strings: Create wrap function
Test your changes:
The strings.Wrap function wraps a string into one or more lines,
splitting the string after the given number of characters, but not
splitting in the middle of a word.
```text
go test ./...
```
Fixes #99998
Closes #99999"
```
### Step 7
Step 8
: Push the new branch to your fork of the documentation repository.
Commit your changes with a descriptive commit message:
Step 9
: Visit the [project repository] and create a pull request (PR).
- Provide a summary on the first line, typically 50 characters or less, followed by a blank line.
- Begin the summary with one of content, theme, config, all, or misc, followed by a colon, a space, and a brief description of the change beginning with a capital letter
- Use imperative present tense
- See the [commit message guidelines] for requirements
- Optionally, provide a detailed description where each line is 72 characters or less, followed by a blank line.
- Add one or more "Fixes" or "Closes" keywords, each on its own line, referencing the [issues] addressed by this change.
For example:
```sh
git commit -m "tpl/strings: Create wrap function
The strings.Wrap function wraps a string into one or more lines,
splitting the string after the given number of characters, but not
splitting in the middle of a word.
Fixes #99998
Closes #99999"
```
### Step 8
Push the new branch to your fork of the documentation repository.
### Step 9
Visit the [project repository] and create a pull request (PR).
### Step 10
A project maintainer will review your PR and may request changes. You may delete your branch after the maintainer merges your PR.
Step 10
: A project maintainer will review your PR and may request changes. You may delete your branch after the maintainer merges your PR.
## Building from source
@@ -153,7 +143,7 @@ CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@latest
To build and install a specific release:
```sh
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@v0.147.1
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@v0.148.0
```
To build and install at the latest commit on the master branch:
@@ -165,7 +155,7 @@ CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@master
To build and install at a specific commit:
```sh
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@0851c17
CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@c0d9beb
```
[bugs]: https://github.com/gohugoio/hugo/issues?q=is%3Aopen+is%3Aissue+label%3ABug
+69 -65
View File
@@ -70,6 +70,22 @@ Link to the [glossary] as needed and use terms consistently. Pay particular atte
- "Markdown" (capitalized)
- "open-source" (hyphenated adjective)
### Template types
When you refer to a template type, italicize it:
```text
When creating a _taxonomy_ template, do this...
```
However, if the template type is also a link, do not italicize it to avoid distracting formatting:
```text
When creating a [taxonomy] template, do this...
```
Do not italicize the template type in a title, heading, or front matter description.
### Titles and headings
- Use sentence-style capitalization.
@@ -154,25 +170,25 @@ If quotation marks are required, prefer single quotes to double quotes when poss
Field|Description|Required
:--|:--|:--
`title`|The page title|:heavy_check_mark:|
`linkTitle`|A short version of the page title||
`description`|A complete sentence describing the page|:heavy_check_mark:|
`categories`|An array of terms in the categories taxonomy|:heavy_check_mark: [^1]|
`keywords`|An array of keywords used to identify related content|:heavy_check_mark: [^1]|
`publishDate`|Applicable to news items: the publication date||
`params.alt_title`|An alternate title: used in the "see also" panel if provided||
`params.functions_and_methods.aliases`|Applicable to function and method pages: an array of alias names||
`params.functions_and_methods.returnType`|Applicable to function and method pages: the data type returned||
`params.functions_and_methods.signatures`|Applicable to function and method pages: an array of signatures||
`params.hide_in_this_section`|Whether to hide the "in this section" panel||
`params.minversion`|Applicable to the quick start page: the minimum Hugo version required||
`params.permalink`|Reserved for use by the news content adapter||
`params.reference (used in glossary term)`|Applicable to glossary entries: a URL for additional information||
`params.searchable`|Whether to add the content of this page to the search index. The default value is cascaded down from the site configuration; `true` if the page kind is `page`, and `false` if the page kind is one of `home`, `section`, `taxonomy`, or `term`. Add this field to override the default value.||
`params.show_publish_date`|Whether to show the `publishDate` when rendering the page||
`weight`|The page weight||
`aliases`|Previous URLs used to access this page||
`expirydate`|The expiration date||
`title`|The page title|:heavy_check_mark:
`linkTitle`|A short version of the page title|&nbsp;
`description`|A complete sentence describing the page|:heavy_check_mark:
`categories`|An array of terms in the categories taxonomy|:heavy_check_mark: [^1]
`keywords`|An array of keywords used to identify related content|:heavy_check_mark: [^1]
`publishDate`|Applicable to news items: the publication date|&nbsp;
`params.alt_title`|An alternate title: used in the "see also" panel if provided|&nbsp;
`params.functions_and_methods.aliases`|Applicable to function and method pages: an array of alias names|&nbsp;
`params.functions_and_methods.returnType`|Applicable to function and method pages: the data type returned|&nbsp;
`params.functions_and_methods.signatures`|Applicable to function and method pages: an array of signatures|&nbsp;
`params.hide_in_this_section`|Whether to hide the "in this section" panel|&nbsp;
`params.minversion`|Applicable to the quick start page: the minimum Hugo version required|&nbsp;
`params.permalink`|Reserved for use by the news content adapter|&nbsp;
`params.reference (used in glossary term)`|Applicable to glossary entries: a URL for additional information|&nbsp;
`params.searchable`|Whether to add the content of this page to the search index. The default value is cascaded down from the site configuration; `true` if the page kind is `page`, and `false` if the page kind is one of `home`, `section`, `taxonomy`, or `term`. Add this field to override the default value.|&nbsp;
`params.show_publish_date`|Whether to show the `publishDate` when rendering the page|&nbsp;
`weight`|The page weight|&nbsp;
`aliases`|Previous URLs used to access this page|&nbsp;
`expirydate`|The expiration date|&nbsp;
[^1]: The field is required, but its data is not.
@@ -329,8 +345,6 @@ Limiting the number of callout types helps us to use them consistently.
> [!important]
> Key information users need to know to achieve their goal.
## Shortcodes
These shortcodes are commonly used throughout the documentation. Other shortcodes are available for specialized use.
@@ -457,67 +471,57 @@ Set the `expiryDate` to two years from the date of deprecation, and add a brief
Use this workflow to create and submit pull requests.
### Step 1
Step 1
: Fork the [documentation repository].
Fork the [documentation repository].
Step 2
: Clone your fork.
### Step 2
Step 3
: Create a new branch with a descriptive name that includes the corresponding issue number, if any:
Clone your fork.
```sh
git checkout -b restructure-foo-page-99999
```
### Step 3
Step 4
: Make changes.
Create a new branch with a descriptive name that includes the corresponding issue number, if any:
Step 5
: Build the site locally to preview your changes.
```sh
git checkout -b restructure-foo-page-99999
```
Step 6
: Commit your changes with a descriptive commit message:
### Step 4
- Provide a summary on the first line, typically 50 characters or less, followed by a blank line.
- Begin the summary with one of `content`, `theme`, `config`, `all`, or `misc`, followed by a colon, a space, and a brief description of the change beginning with a capital letter
- Use imperative present tense
- Optionally, provide a detailed description where each line is 72 characters or less, followed by a blank line.
- Optionally, add one or more "Fixes" or "Closes" keywords, each on its own line, referencing the [issues] addressed by this change.
Make changes.
For example:
### Step 5
```text
git commit -m "content: Restructure the taxonomy page
Build the site locally to preview your changes.
This restructures the taxonomy page by splitting topics into logical
sections, each with one or more examples.
### Step 6
Fixes #9999
Closes #9998"
```
Commit your changes with a descriptive commit message:
Step 7
: Push the new branch to your fork of the documentation repository.
- Provide a summary on the first line, typically 50 characters or less, followed by a blank line.
- Begin the summary with one of `content`, `theme`, `config`, `all`, or `misc`, followed by a colon, a space, and a brief description of the change beginning with a capital letter
- Use imperative present tense
- Optionally, provide a detailed description where each line is 72 characters or less, followed by a blank line.
- Optionally, add one or more "Fixes" or "Closes" keywords, each on its own line, referencing the [issues] addressed by this change.
Step 8
: Visit the [documentation repository] and create a pull request (PR).
For example:
```text
git commit -m "content: Restructure the taxonomy page
This restructures the taxonomy page by splitting topics into logical
sections, each with one or more examples.
Fixes #9999
Closes #9998"
```
### Step 7
Push the new branch to your fork of the documentation repository.
### Step 8
Visit the [documentation repository] and create a pull request (PR).
### Step 9
A project maintainer will review your PR and may request changes. You may delete your branch after the maintainer merges your PR.
Step 9
: A project maintainer will review your PR and may request changes. You may delete your branch after the maintainer merges your PR.
[ATX]: https://spec.commonmark.org/current/#atx-headings
[basic english]: https://simple.wikipedia.org/wiki/Basic_English
[basic english]: https://simple.wikipedia.org/wiki/Basic_English
[developer documentation style guide]: https://developers.google.com/style
[documentation repository]: https://github.com/gohugoio/hugoDocs/
[fenced code blocks]: https://spec.commonmark.org/current/#fenced-code-blocks
+27 -32
View File
@@ -22,46 +22,41 @@ params:
Follow the steps below to transform CSS using any of the available [PostCSS plugins].
### Step 1
Step 1
: Install [Node.js].
Install [Node.js].
Step 2
: Install the required Node.js packages in the root of your project. For example, to add vendor prefixes to your CSS rules:
### Step 2
```sh
npm i -D postcss postcss-cli autoprefixer
```
Install the required Node.js packages in the root of your project. For example, to add vendor prefixes to your CSS rules:
Step 3
: Create a PostCSS configuration file in the root of your project.
```sh
npm i -D postcss postcss-cli autoprefixer
```
```js {file="postcss.config.js"}
module.exports = {
plugins: [
require('autoprefixer')
]
};
```
### Step 3
> [!note]
> If you are a Windows user, and the path to your project contains a space, you must place the PostCSS configuration within the package.json file. See [this example] and issue [#7333].
Create a PostCSS configuration file in the root of your project.
Step 4
: Place your CSS file within the `assets/css` directory.
```js {file="postcss.config.js"}
module.exports = {
plugins: [
require('autoprefixer')
]
};
```
Step 5
: Process the resource with PostCSS:
> [!note]
> If you are a Windows user, and the path to your project contains a space, you must place the PostCSS configuration within the package.json file. See [this example] and issue [#7333].
### Step 4
Place your CSS file within the `assets/css` directory.
### Step 5
Process the resource with PostCSS:
```go-html-template
{{ with resources.Get "css/main.css" | postCSS }}
<link rel="stylesheet" href="{{ .RelPermalink }}">
{{ end }}
```
```go-html-template
{{ with resources.Get "css/main.css" | postCSS }}
<link rel="stylesheet" href="{{ .RelPermalink }}">
{{ end }}
```
## Options
+14 -66
View File
@@ -122,83 +122,31 @@ Run `hugo env` to list the active transpilers.
### Installing in a production environment
For [CI/CD](g) deployments (e.g., GitHub Pages, GitLab Pages, Netlify, etc.) you must edit the workflow to install Dart Sass before Hugo builds the site[^2]. Some providers allow you to use one of the package managers above, or you can download and extract one of the prebuilt binaries.
To use Dart Sass with Hugo on a CI/CD platform like GitHub Pages, GitLab Pages, or Netlify, you typically must modify your build workflow to install Dart Sass before the Hugo site build begins. This is because these platforms don't have Dart Sass pre-installed, and Hugo needs it to process your Sass files.
[^2]: You do not have to do this if (a) you have not modified the assets cache location, and (b) you have not set `useResourceCacheWhen` to `never` in your [site configuration], and (c) you add and commit your `resources` directory to your repository.
There's one key exception where you can skip this step: you have committed your `resources` directory to your repository. This is only possible if:
#### GitHub Pages
- You have not changed Hugo's default asset cache location.
- You have not set [`useResourceCacheWhen`] to never in your sites configuration.
To install Dart Sass for your builds on GitHub Pages, add this step to the GitHub Pages workflow file:
By committing the `resources` directory, you're providing the pre-built CSS files directly to your CI/CD service, so it doesn't need to run the Sass compilation itself.
```yaml
- name: Install Dart Sass
run: sudo snap install dart-sass
```
For examples of how to install Dart Sass in a production environment, see the following workflow files:
#### GitLab Pages
To install Dart Sass for your builds on GitLab Pages, the `.gitlab-ci.yml` file should look something like this:
```yaml
variables:
HUGO_VERSION: 0.147.9
DART_SASS_VERSION: 1.89.2
GIT_DEPTH: 0
GIT_STRATEGY: clone
GIT_SUBMODULE_STRATEGY: recursive
TZ: America/Los_Angeles
image:
name: golang:1.20-buster
pages:
script:
# Install Dart Sass
- curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
- tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
- cp -r dart-sass/* /usr/local/bin
- rm -rf dart-sass*
# Install Hugo
- curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb
- apt install -y ./hugo_extended_${HUGO_VERSION}_linux-amd64.deb
- rm hugo_extended_${HUGO_VERSION}_linux-amd64.deb
# Build
- hugo --gc --minify
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
#### Netlify
To install Dart Sass for your builds on Netlify, the `netlify.toml` file should look something like this:
```toml
[build.environment]
HUGO_VERSION = "0.147.9"
DART_SASS_VERSION = "1.89.2"
NODE_VERSION = "22"
TZ = "America/Los_Angeles"
[build]
publish = "public"
command = """\
curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
rm dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
export PATH=/opt/build/repo/dart-sass:$PATH && \
hugo --gc --minify \
"""
```
- [GitHub Pages]
- [GitLab Pages]
- [Netlify]
[`publishDir`]: /configuration/all/#publishdir
[`useResourceCacheWhen`]: /configuration/build/#useresourcecachewhen
[brew.sh]: https://brew.sh/
[chocolatey.org]: https://community.chocolatey.org/packages/sass
[dart sass]: https://sass-lang.com/dart-sass
[GitHub Pages]: /host-and-deploy/host-on-github-pages/#step-7
[GitLab Pages]: /host-and-deploy/host-on-gitlab-pages/#configure-gitlab-cicd
[libsass]: https://sass-lang.com/libsass
[Netlify]: /host-and-deploy/host-on-netlify/#configuration-file
[prebuilt binaries]: https://github.com/sass/dart-sass/releases/latest
[scoop.sh]: https://scoop.sh/#/apps?q=sass
[site configuration]: /configuration/build/
[snap package]: /installation/linux/#snap
[snapcraft.io]: https://snapcraft.io/dart-sass
[starter workflow]: https://github.com/actions/starter-workflows/blob/main/pages/hugo.yml
[`publishDir`]: /configuration/all/#publishdir
+59 -65
View File
@@ -25,86 +25,80 @@ Use the `css.TailwindCSS` function to process your Tailwind CSS files. This func
## Setup
### Step 1
Step 1
: Install the Tailwind CSS CLI v4.0 or later:
Install the Tailwind CSS CLI v4.0 or later:
```sh {copy=true}
npm install --save-dev tailwindcss @tailwindcss/cli
```
```sh {copy=true}
npm install --save-dev tailwindcss @tailwindcss/cli
```
The Tailwind CSS CLI is also available as a [standalone executable]. You must install it outside of your project directory and ensure its path is included in your system's `PATH` environment variable.
The Tailwind CSS CLI is also available as a [standalone executable]. You must install it outside of your project directory and ensure its path is included in your system's `PATH` environment variable.
[standalone executable]: https://github.com/tailwindlabs/tailwindcss/releases/latest
Step 2
: Add this to your site configuration:
[standalone executable]: https://github.com/tailwindlabs/tailwindcss/releases/latest
{{< code-toggle file=hugo copy=true >}}
[build]
[build.buildStats]
enable = true
[[build.cachebusters]]
source = 'assets/notwatching/hugo_stats\.json'
target = 'css'
[[build.cachebusters]]
source = '(postcss|tailwind)\.config\.js'
target = 'css'
[module]
[[module.mounts]]
source = 'assets'
target = 'assets'
[[module.mounts]]
disableWatch = true
source = 'hugo_stats.json'
target = 'assets/notwatching/hugo_stats.json'
{{< /code-toggle >}}
### Step 2
Step 3
: Create a CSS entry file:
Add this to your site configuration:
```css {file="assets/css/main.css" copy=true}
@import "tailwindcss";
@source "hugo_stats.json";
```
{{< code-toggle file=hugo copy=true >}}
[build]
[build.buildStats]
enable = true
[[build.cachebusters]]
source = 'assets/notwatching/hugo_stats\.json'
target = 'css'
[[build.cachebusters]]
source = '(postcss|tailwind)\.config\.js'
target = 'css'
[module]
[[module.mounts]]
source = 'assets'
target = 'assets'
[[module.mounts]]
disableWatch = true
source = 'hugo_stats.json'
target = 'assets/notwatching/hugo_stats.json'
{{< /code-toggle >}}
Tailwind CSS respects `.gitignore` files. This means that if `hugo_stats.json` is listed in your `.gitignore` file, Tailwind CSS will ignore it. To make `hugo_stats.json` available to Tailwind CSS you must explicitly source it as shown in the example above.
### Step 3
Step 4
: Create a _partial_ template to process the CSS with the Tailwind CSS CLI:
Create a CSS entry file:
```css {file="assets/css/main.css" copy=true}
@import "tailwindcss";
@source "hugo_stats.json";
```
Tailwind CSS respects `.gitignore` files. This means that if `hugo_stats.json` is listed in your `.gitignore` file, Tailwind CSS will ignore it. To make `hugo_stats.json` available to Tailwind CSS you must explicitly source it as shown in the example above.
### Step 4
Create a partial template to process the CSS with the Tailwind CSS CLI:
```go-html-template {file="layouts/_partials/css.html" copy=true}
{{ with resources.Get "css/main.css" }}
{{ $opts := dict "minify" (not hugo.IsDevelopment) }}
{{ with . | css.TailwindCSS $opts }}
{{ if hugo.IsDevelopment }}
<link rel="stylesheet" href="{{ .RelPermalink }}">
{{ else }}
{{ with . | fingerprint }}
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
```go-html-template {file="layouts/_partials/css.html" copy=true}
{{ with resources.Get "css/main.css" }}
{{ $opts := dict "minify" (not hugo.IsDevelopment) }}
{{ with . | css.TailwindCSS $opts }}
{{ if hugo.IsDevelopment }}
<link rel="stylesheet" href="{{ .RelPermalink }}">
{{ else }}
{{ with . | fingerprint }}
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
{{ end }}
{{ end }}
{{ end }}
{{ end }}
{{ end }}
```
```
### Step 5
Step 5
: Call the _partial_ template from your base template, deferring template execution until after all sites and output formats have been rendered:
Call the partial template from your base template, deferring template execution until after all sites and output formats have been rendered:
```go-html-template {file="layouts/baseof.html" copy=true}
<head>
...
{{ with (templates.Defer (dict "key" "global")) }}
{{ partial "css.html" . }}
{{ end }}
...
</head>
```
```go-html-template {file="layouts/baseof.html" copy=true}
<head>
...
{{ with (templates.Defer (dict "key" "global")) }}
{{ partial "css.html" . }}
{{ end }}
...
</head>
```
## Options
+4 -3
View File
@@ -97,7 +97,7 @@ my-project/
## Page resource alternative
Consider using the [`Resources.Get`] method with [`transform.Unmarshal`] when accessing a page resource.
Consider using the [`Resources.Get`][/methods/page/resources/] method with [`transform.Unmarshal`] when accessing a page resource.
```text
my-project/
@@ -138,7 +138,8 @@ Consider using the [`resources.GetRemote`] function with [`transform.Unmarshal`]
{{ end }}
```
[`Resources.Get`]: /methods/page/resources/
[`resources.GetRemote`]: /functions/resources/getremote/
[`resources.Get`]: /functions/resources/get/
<!-- markdownlint-disable MD053 -->
[`transform.Unmarshal`]: /functions/transform/unmarshal/
<!-- markdownlint-enable MD053 -->
+5 -4
View File
@@ -80,7 +80,7 @@ Add multiple headers using a slice:
## Global resource alternative
Consider using the [`resources.Get`] function with [`transform.Unmarshal`] when accessing a global resource.
Consider using the [`resources.Get`](/functions/resources/get/) function with [`transform.Unmarshal`] when accessing a global resource.
```text
my-project/
@@ -101,7 +101,7 @@ my-project/
## Page resource alternative
Consider using the [`Resources.Get`] method with [`transform.Unmarshal`] when accessing a page resource.
Consider using the [`Resources.Get`][/methods/page/resources/] method with [`transform.Unmarshal`] when accessing a page resource.
```text
my-project/
@@ -140,7 +140,8 @@ Consider using the [`resources.GetRemote`] function with [`transform.Unmarshal`]
{{ end }}
```
[`Resources.Get`]: /methods/page/resources/
[`resources.GetRemote`]: /functions/resources/getremote/
[`resources.Get`]: /functions/resources/get/
<!-- markdownlint-disable MD053 -->
[`transform.Unmarshal`]: /functions/transform/unmarshal/
<!-- markdownlint-enable MD053 -->
@@ -13,8 +13,8 @@ aliases: [/functions/jsonify]
To customize the printing of the JSON, pass an options map as the first
argument. Supported options are "prefix" and "indent". Each JSON element in
the output will begin on a new line beginning with *prefix* followed by one or
more copies of *indent* according to the indentation nesting.
the output will begin on a new line beginning with _prefix_ followed by one or
more copies of _indent_ according to the indentation nesting.
```go-html-template
{{ dict "title" .Title "content" .Plain | jsonify }}
+5 -5
View File
@@ -53,9 +53,9 @@ content/
└── _index.md <-- title is "My Home Page"
```
And this code in the home template:
And this code in the _home_ template:
```go-html-template
```go-html-template {file="layouts/home.html"}
{{ range site.Sections }}
{{ range .Pages }}
{{ page.Title }}
@@ -71,7 +71,7 @@ My Home Page
My Home Page
```
In the example above, the global `page` function accesses the `Page` object passed into the home template; it does not access the `Page` object of the iterated pages.
In the example above, the global `page` function accesses the `Page` object passed into the _home_ template; it does not access the `Page` object of the iterated pages.
### Be aware of caching
@@ -83,9 +83,9 @@ Do not use the global `page` function in:
Hugo caches rendered shortcodes. If you use the global `page` function within a shortcode, and the page content is rendered in two or more templates, the cached shortcode may be incorrect.
Consider this section template:
Consider this _section_ template:
```go-html-template
```go-html-template {file="layouts/section.html"}
{{ range .Pages }}
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
{{ .Summary }}
@@ -21,6 +21,7 @@ and then executing it in place:
```go-html-template
{{ template "name" pipeline }}
```
The typical use is to define a set of root templates that are then customized by redefining the block templates within.
```go-html-template {file="layouts/baseof.html"}
@@ -43,21 +43,8 @@ Use with the [`template`] function:
{{ end }}
```
> [!warning]
> Only [template comments] are allowed outside of the `define` and `end` statements. Avoid placing any other text, including HTML comments, outside of these boundaries. Doing so will cause rendering issues, potentially resulting in a blank page. See the example below.
```go-html-template {file="layouts/do-not-do-this.html"}
<div>This div element broke your template.</div>
{{ define "main" }}
<h2>{{ .Title }}</h2>
{{ .Content }}
{{ end }}
<!-- An HTML comment will break your template too. -->
```
{{% include "/_common/functions/go-template/text-template.md" %}}
[`block`]: /functions/go-template/block/
[`template`]: /functions/go-template/block/
[`partial`]: /functions/partials/include/
[template comments]: /templates/introduction/#comments
@@ -38,7 +38,9 @@ Within a range block:
## Understanding context
At the top of a page template, the [context](g) (the dot) is a `Page` object. Within the `range` block, the context is bound to each successive element.
See the [context] section in the introduction to templating.
For example, at the top of a _page_ template, the [context](g) (the dot) is a `Page` object. Within the `range` block, the context is bound to each successive element.
With this contrived example:
@@ -217,3 +219,4 @@ Ranging over a non-positive integer executes the block zero times.
[`break`]: /functions/go-template/break/
[`continue`]: /functions/go-template/continue/
[`else`]: /functions/go-template/else/
[context]: /templates/introduction/#context
@@ -10,7 +10,7 @@ params:
signatures: ['return [VALUE]']
---
The `return` statement is a non-standard extension to Go's [text/template package]. Used within partial templates, the `return` statement terminates template execution and returns the given value, if any.
The `return` statement is a non-standard extension to Go's [text/template package]. Used within _partial_ templates, the `return` statement terminates template execution and returns the given value, if any.
The returned value may be of any data type including, but not limited to, [`bool`](g), [`float`](g), [`int`](g), [`map`](g), [`resource`](g), [`slice`](g), or [`string`](g).
@@ -21,7 +21,7 @@ A `return` statement without a value returns an empty string of type `template.H
## Example
By way of example, let's create a partial template that _renders_ HTML, describing whether the given number is odd or even:
By way of example, let's create a _partial_ template that _renders_ HTML, describing whether the given number is odd or even:
```go-html-template {file="layouts/_partials/odd-or-even.html"}
{{ if math.ModBool . 2 }}
@@ -20,7 +20,7 @@ Use the `template` function to execute a defined template:
{{ end }}
```
The example above can be rewritten using an inline partial template:
The example above can be rewritten using an inline _partial_ template:
```go-html-template
{{ partial "inline/foo.html" (dict "answer" 42) }}
@@ -33,8 +33,8 @@ The example above can be rewritten using an inline partial template:
The key distinctions between the preceding two examples are:
1. Inline partials are globally scoped. That means that an inline partial defined in _one_ template may be called from _any_ template.
2. Leveraging the [`partialCached`] function when calling an inline partial allows for performance optimization through result caching.
3. An inline partial can [`return`] a value of any data type instead of rendering a string.
1. Leveraging the [`partialCached`] function when calling an inline partial allows for performance optimization through result caching.
1. An inline partial can [`return`] a value of any data type instead of rendering a string.
{{% include "/_common/functions/go-template/text-template.md" %}}
@@ -101,6 +101,7 @@ Instead of failing the build, we can catch the error and emit a warning:
{{ end }}
{{ end }}
```
In the above, note that the [context](g) within the last conditional block is the `TryValue` object returned by the `try` statement. At this point neither the `Err` nor `Value` methods returned anything, so the current context is not useful. Use the `$` to access the [template context] if needed.
> [!note]
@@ -57,7 +57,9 @@ Initialize a variable, scoped to the current block:
## Understanding context
At the top of a page template, the [context](g) (the dot) is a `Page` object. Inside of the `with` block, the context is bound to the value passed to the `with` statement.
See the [context] section in the introduction to templating.
For example, at the top of a _page_ template, the [context](g) (the dot) is a `Page` object. Inside of the `with` block, the context is bound to the value passed to the `with` statement.
With this contrived example:
@@ -90,3 +92,4 @@ This template will render the page title as desired:
{{% include "/_common/functions/go-template/text-template.md" %}}
[`else`]: /functions/go-template/else/
[context]: /templates/introduction/#context
+1 -1
View File
@@ -11,5 +11,5 @@ params:
---
```go-html-template
{{ hugo.Generator }} → <meta name="generator" content="Hugo 0.147.9">
{{ hugo.Generator }} → <meta name="generator" content="Hugo 0.148.0">
```
+1 -1
View File
@@ -100,7 +100,7 @@ Removes the given key.
## Determinate values
The `Store` method is often used to set scratch pad values within a shortcode, a partial template called by a shortcode, or by a Markdown render hook. In all three cases, the scratch pad values are indeterminate until Hugo renders the page content.
The `Store` method is often used to set scratch pad values within a _shortcode_ template, a _partial_ template called by a _shortcode_ template, or by a _render hook_ template. In all three cases, the scratch pad values are indeterminate until Hugo renders the page content.
If you need to access a scratch pad value from a parent template, and the parent template has not yet rendered the page content, you can trigger content rendering by assigning the returned value to a [noop](g) variable:
+1 -1
View File
@@ -11,5 +11,5 @@ params:
---
```go-html-template
{{ hugo.Version }} → 0.147.9
{{ hugo.Version }} → 0.148.0
```
+13 -16
View File
@@ -31,26 +31,23 @@ params:
## Setup
### Step 1
Step 1
: Install [Node.js](https://nodejs.org/en/download)
Install [Node.js](https://nodejs.org/en/download)
Step 2
: Install the required Node.js packages in the root of your project.
### Step 2
```sh
npm install --save-dev @babel/core @babel/cli
```
Install the required Node.js packages in the root of your project.
Step 3
: Add the babel executable to Hugo's `security.exec.allow` list in your site configuration:
```sh
npm install --save-dev @babel/core @babel/cli
```
### Step 3
Add the babel executable to Hugo's `security.exec.allow` list in your site configuration:
{{< code-toggle file=hugo >}}
[security.exec]
allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^npx$', '^postcss$', '^babel$']
{{< /code-toggle >}}
{{< code-toggle file=hugo >}}
[security.exec]
allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^npx$', '^postcss$', '^babel$']
{{< /code-toggle >}}
## Configuration
+3 -4
View File
@@ -158,7 +158,7 @@ import * as params from "@params";
import * as config from "@params/config";
```
Setting the `Config` for a batch can be done from any template (including shortcode templates), but will only be set once (the first will win):
Setting the `Config` for a batch can be done from any template (including _shortcode_ templates), but will only be set once (the first will win):
```go-html-template
{{ with js.Batch "js/mybatch" }}
@@ -270,8 +270,8 @@ In a template you would typically handle one group with a given `ID` (e.g. scrip
In the official documentation for ESBuild's [code splitting], there's a warning note in the header. The two issues are:
- `esm` is currently the only implemented output format. This means that it will not work for very old browsers. See [caniuse](https://caniuse.com/?search=ESM).
- There's a known import ordering issue.
- `esm` is currently the only implemented output format. This means that it will not work for very old browsers. See [caniuse](https://caniuse.com/?search=ESM).
- There's a known import ordering issue.
We have not seen the ordering issue as a problem during our [extensive testing](https://github.com/bep/hugojsbatchdemo) of this new feature with different libraries. There are two main cases:
@@ -291,7 +291,6 @@ console.log('entrypoints-workaround.js');
[`Resources.Mount`]: /methods/page/resources/#mount
[`Resources`]: /methods/page/resources/
[`templates.Defer`]: /functions/templates/defer/
[`templates.Defer`]: /functions/templates/defer/
[build options]: #build-options
[code splitting]: https://esbuild.github.io/api/#splitting
[config]: #config
+1
View File
@@ -82,6 +82,7 @@ Also note the new `params` option that can be passed from template to your JS fi
```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
@@ -55,7 +55,7 @@ To list the GET and POST operations for each of the API paths:
```
> [!warning]
> The unmarshaled data structure is created with [`kin-openapi`](https://github.com/getkin/kin-openapi). Many fields are structs or pointers (not maps), and therefore require accessors or other methods for indexing and iteration.
> The unmarshaled data structure is created with [`kin-openapi`](https://github.com/getkin/kin-openapi). Many fields are structs or pointers (not maps), and therefore require accessors or other methods for indexing and iteration.
> For example, prior to [`kin-openapi` v0.122.0](https://github.com/getkin/kin-openapi#v01220) / [Hugo v0.121.0](https://github.com/gohugoio/hugo/releases/tag/v0.121.0), `Paths` was a map (so `.Paths` was iterable) and it is now a pointer (and requires the `.Paths.Map` accessor, as in the example above).
> See the [`kin-openapi` godoc for OpenAPI 3](https://pkg.go.dev/github.com/getkin/kin-openapi/openapi3) for full type definitions.
@@ -1,6 +1,6 @@
---
title: partials.Include
description: Executes the given partial template, optionally passing context. If the partial template contains a return statement, returns the given value, else returns the rendered output.
description: Executes the given template, optionally passing context. If the partial template contains a return statement, returns the given value, else returns the rendered output.
categories: []
keywords: []
params:
@@ -13,9 +13,7 @@ aliases: [/functions/partial]
Without a [`return`] statement, the `partial` function returns a string of type `template.HTML`. With a `return` statement, the `partial` function can return any data type.
[`return`]: /functions/go-template/return/
In this example we have three partial templates:
In this example we have three _partial_ templates:
```text
layouts/
@@ -56,7 +54,7 @@ You can pass anything in context: a page, a page collection, a scalar value, a s
{{ partial "render-student-info.html" $ctx }}
```
Then, within the partial template:
Then, within the _partial_ template:
```go-html-template
<p>{{ .name }} is majoring in {{ .major }}.</p>
@@ -64,7 +62,7 @@ Then, within the partial template:
<p>See <a href="{{ .page.RelPermalink }}">details.</a></p>
```
To return a value from a partial template, it must contain only one `return` statement, placed at the end of the template:
To return a value from a _partial_ template, it must contain only one `return` statement, placed at the end of the template:
```go-html-template
{{ $result := "" }}
@@ -79,6 +77,4 @@ To return a value from a partial template, it must contain only one `return` sta
See&nbsp;[details][`return`].
[`return`]: /functions/go-template/return/
[breadcrumb navigation]: /content-management/sections/#ancestors-and-descendants
[details]: /functions/go-template/return/
@@ -38,9 +38,9 @@ Pass additional arguments, of any data type, as needed to create unique variants
{{ partialCached "footer.html" . .Params.country .Params.province }}
```
The variant arguments are not available to the underlying partial template; they are only used to create unique cache keys.
The variant arguments are not available to the underlying _partial_ template; they are only used to create unique cache keys.
To return a value from a partial template, it must contain only one `return` statement, placed at the end of the template:
To return a value from a _partial_ template, it must contain only one `return` statement, placed at the end of the template:
```go-html-template
{{ $result := "" }}
@@ -22,9 +22,9 @@ Let's say you need to publish a file named "site.json" in the root of your `publ
```json
{
"build_date": "2025-05-03T19:14:41-08:00",
"hugo_version": "0.147.9",
"last_modified": "2025-05-03T19:14:46-08:00"
"build_date": "2025-07-08T13:12:19-07:00",
"hugo_version": "0.148.0",
"last_modified": "2025-07-07T22:09:13-07:00"
}
```
@@ -15,8 +15,6 @@ The `Err` method on the returned resource was removed in v0.141.0.
Use the [`try`] statement instead, as shown in the [error handling] example below.
[`try`]: /functions/go-template/try
[error handling]: #error-handling
{{< /new-in >}}
```go-html-template
@@ -36,26 +34,21 @@ Use the [`try`] statement instead, as shown in the [error handling] example belo
The `resources.GetRemote` function takes an optional map of options.
###### body
body
: (`string`) The data you want to transmit to the server.
(`string`) The data you want to transmit to the server.
headers
: (`map[string][]string`) The collection of key-value pairs that provide additional information about the request.
###### headers
key
: (`string`) The cache key. Hugo derives the default value from the URL and options map. See [caching](#caching).
(`map[string][]string`) The collection of key-value pairs that provide additional information about the request.
method
: (`string`) The action to perform on the requested resource, typically one of `GET`, `POST`, or `HEAD`.
###### key
(`string`) The cache key. Hugo derives the default value from the URL and options map. See [caching](#caching).
###### method
(`string`) The action to perform on the requested resource, typically one of `GET`, `POST`, or `HEAD`.
###### responseHeaders
{{< new-in 0.143.0 />}}
(`[]string`) The headers to extract from the server's response, accessible through the resource's [`Data.Headers`] method. Header name matching is case-insensitive.
responseHeaders
: {{< new-in 0.143.0 />}}
: (`[]string`) The headers to extract from the server's response, accessible through the resource's [`Data.Headers`] method. Header name matching is case-insensitive.
[`Data.Headers`]: /methods/resource/data/#headers
@@ -64,8 +57,6 @@ The `resources.GetRemote` function takes an optional map of options.
> [!note]
> For brevity, the examples below do not include [error handling].
[error handling]: #error-handling
To include a header:
```go-html-template
@@ -150,8 +141,6 @@ When retrieving remote data, use the [`transform.Unmarshal`] function to [unmars
Use the [`try`] statement to capture HTTP request errors. If you do not handle the error yourself, Hugo will fail the build.
[`try`]: /functions/go-template/try
> [!note]
> Hugo does not classify an HTTP response with status code 404 as an error. In this case `resources.GetRemote` returns nil.
@@ -202,8 +191,6 @@ By default, Hugo derives the cache key from the arguments passed to the function
{{ $resource := resources.GetRemote $url $opts }}
```
[configure file caches]: /configuration/caches/
## Security
To protect against malicious intent, the `resources.GetRemote` function inspects the server response including:
@@ -234,3 +221,7 @@ Note that the entry above is:
[allowlist]: https://en.wikipedia.org/wiki/Whitelist
[Content-Type]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
[`try`]: /functions/go-template/try
[configure file caches]: /configuration/caches/
[error handling]: #error-handling
@@ -17,9 +17,9 @@ The `resources.PostProcess` function delays resource transformation steps until
In this example, after the build is complete, Hugo will:
1. Purge unused CSS using the [PurgeCSS] plugin for [PostCSS]
2. Add vendor prefixes to CSS rules using the [Autoprefixer] plugin for PostCSS
3. [Minify] the CSS
4. [Fingerprint] the CSS
1. Add vendor prefixes to CSS rules using the [Autoprefixer] plugin for PostCSS
1. [Minify] the CSS
1. [Fingerprint] the CSS
Step 1
: Install [Node.js].
@@ -27,51 +27,51 @@ Step 1
Step 2
: Install the required Node.js packages in the root of your project:
```sh
npm i -D postcss postcss-cli autoprefixer @fullhuman/postcss-purgecss
```
```sh {copy=true}
npm i -D postcss postcss-cli autoprefixer @fullhuman/postcss-purgecss
```
Step 3
: Enable creation of the `hugo_stats.json` file when building the site. If you are only using this for the production build, consider placing it below [`config/production`].
{{< code-toggle file=hugo >}}
[build.buildStats]
enable = true
{{< /code-toggle >}}
{{< code-toggle file=hugo copy=true >}}
[build.buildStats]
enable = true
{{< /code-toggle >}}
See the [configure build] documentation for details and options.
See the [configure build] documentation for details and options.
Step 4
: Create a PostCSS configuration file in the root of your project.
```js {file="postcss.config.js" copy=true}
const autoprefixer = require('autoprefixer');
const purgeCSSPlugin = require('@fullhuman/postcss-purgecss').default;
```js {file="postcss.config.js" copy=true}
const autoprefixer = require('autoprefixer');
const purgeCSSPlugin = require('@fullhuman/postcss-purgecss').default;
const purgecss = purgeCSSPlugin({
content: ['./hugo_stats.json'],
defaultExtractor: content => {
const els = JSON.parse(content).htmlElements;
return [
...(els.tags || []),
...(els.classes || []),
...(els.ids || []),
];
},
// https://purgecss.com/safelisting.html
safelist: []
});
const purgecss = purgeCSSPlugin({
content: ['./hugo_stats.json'],
defaultExtractor: content => {
const els = JSON.parse(content).htmlElements;
return [
...(els.tags || []),
...(els.classes || []),
...(els.ids || []),
];
},
// https://purgecss.com/safelisting.html
safelist: []
});
module.exports = {
plugins: [
process.env.HUGO_ENVIRONMENT !== 'development' ? purgecss : null,
autoprefixer,
]
};
```
module.exports = {
plugins: [
process.env.HUGO_ENVIRONMENT !== 'development' ? purgecss : null,
autoprefixer,
]
};
```
> [!note]
> If you are a Windows user, and the path to your project contains a space, you must place the PostCSS configuration within the package.json file. See [this example] and issue [#7333].
> [!note]
> If you are a Windows user, and the path to your project contains a space, you must place the PostCSS configuration within the package.json file. See [this example] and issue [#7333].
Step 5
: Place your CSS file within the `assets/css` directory.
@@ -79,17 +79,17 @@ Step 5
Step 6
: If the current environment is not `development`, process the resource with PostCSS:
```go-html-template
{{ with resources.Get "css/main.css" }}
{{ if hugo.IsDevelopment }}
<link rel="stylesheet" href="{{ .RelPermalink }}">
{{ else }}
{{ with . | postCSS | minify | fingerprint | resources.PostProcess }}
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
```go-html-template {copy=true}
{{ with resources.Get "css/main.css" }}
{{ if hugo.IsDevelopment }}
<link rel="stylesheet" href="{{ .RelPermalink }}">
{{ else }}
{{ with . | postCSS | minify | fingerprint | resources.PostProcess }}
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
{{ end }}
{{ end }}
{{ end }}
{{ end }}
```
```
## Environment variables
@@ -124,7 +124,7 @@ let tailwindConfig = process.env.HUGO_FILE_TAILWIND_CONFIG_JS || './tailwind.con
## Limitations
Do not use `resources.PostProcess` when running Hugo's built-in development server. The examples above specifically prevent this by verifying that the current environment is not "development".
Do not use `resources.PostProcess` when running Hugo's built-in development server. The examples above specifically prevent this by verifying that the current environment is not `development`.
The `resources.PostProcess` function only works within templates that produce HTML files.
@@ -64,7 +64,7 @@ To visually mark where a template begins and ends execution:
### Call stack
To display the chain of templates that led to the current one, create a partial template that iterates through its ancestors:
To display the chain of templates that led to the current one, create a _partial_ template that iterates through its ancestors:
```go-html-template {file="layouts/_partials/template-call-stack.html" copy=true}
{{ with templates.Current }}
@@ -113,7 +113,7 @@ To reverse the order of the entries, chain the `Reverse` method to the `Ancestor
### VS Code
To render links that, when clicked, will open the template in Microsoft Visual Studio Code, create a partial template with anchor elements that use the `vscode` URI scheme:
To render links that, when clicked, will open the template in Microsoft Visual Studio Code, create a _partial_ template with anchor elements that use the `vscode` URI scheme:
```go-html-template {file="layouts/_partials/template-open-in-vs-code.html" copy=true}
{{ with templates.Current.Parent }}
+1 -1
View File
@@ -14,7 +14,7 @@ aliases: [/functions/templates.defer]
{{< new-in 0.128.0 />}}
> [!note]
> This feature should only be used in the main page template, typically `layouts/baseof.html`. Using it in shortcodes, partials, or render hook templates may lead to unpredictable results. For further details, please refer to [this issue].
> This feature should only be used in the main template, typically `layouts/baseof.html`. Using it in _shortcode_, _partial_, or _render hook_ templates may lead to unpredictable results. For further details, please refer to [this issue].
[this issue]: https://github.com/gohugoio/hugo/issues/13492#issuecomment-2734700391
@@ -11,7 +11,7 @@ params:
aliases: [/functions/time.parseduration]
---
The `time.ParseDuration` function returns a time.Duration value that you can use with any of the `Duration` [methods].
The `time.ParseDuration` function returns a [`time.Duration`] value that you can use with any of the `Duration` [methods].
A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as `300ms`, `-1.5h` or `2h45m`. Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`.
@@ -194,6 +194,7 @@ export const schemaTypes = [postType]
Unfortunately, Sanity's API does not support [RFC 7234](https://tools.ietf.org/html/rfc7234) and their output changes even if the data has not. A recommended setup is therefore to use their cached `apicdn` endpoint (see above) and then set up a reasonable polling and file cache strategy in your Hugo configuration, e.g:
<!-- markdownlint-disable MD049 -->
{{< code-toggle file=hugo >}}
[HTTPCache]
[[HTTPCache.polls]]
@@ -207,6 +208,7 @@ Unfortunately, Sanity's API does not support [RFC 7234](https://tools.ietf.org/h
dir = ':cacheDir/:project'
maxAge = "5m"
{{< /code-toggle >}}
<!-- markdownlint-enable MD049 -->
The polling above will be used when running the server/watch mode and rebuild when you push new content in Sanity.
+58 -64
View File
@@ -45,14 +45,14 @@ fleqn
macros
: (`map`) A map of macros to be used in the math expression. Default is `{}`.
```go-html-template
{{ $macros := dict
"\\addBar" "\\bar{#1}"
"\\bold" "\\mathbf{#1}"
}}
{{ $opts := dict "macros" $macros }}
{{ transform.ToMath "\\addBar{y} + \\bold{H}" $opts }}
```
```go-html-template
{{ $macros := dict
"\\addBar" "\\bar{#1}"
"\\bold" "\\mathbf{#1}"
}}
{{ $opts := dict "macros" $macros }}
{{ transform.ToMath "\\addBar{y} + \\bold{H}" $opts }}
```
minRuleThickness
: (`float`) The minimum thickness of the fraction lines in `em`. Default is `0.04`.
@@ -60,10 +60,10 @@ minRuleThickness
output
: (`string`) Determines the markup language of the output, one of `html`, `mathml`, or `htmlAndMathml`. Default is `mathml`.
With `html` and `htmlAndMathml` you must include the KaTeX style sheet within the `head` element of your base template.
With `html` and `htmlAndMathml` you must include the KaTeX style sheet within the `head` element of your base template.
```html
<link href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css" rel="stylesheet">
```html
<link href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css" rel="stylesheet">
strict
: {{< new-in 0.147.6 />}}
@@ -73,10 +73,7 @@ strict
- `ignore`: Allows convenient, unsupported LaTeX features without any feedback.
- `warn`: {{< new-in 0.147.7 />}} Emits a warning when convenient, unsupported LaTeX features are encountered.
: The `newLineInDisplayMode` error code, which flags the use of `\\`
or `\newline` in display mode outside an array or tabular environment, is
intentionally designed not to throw an error, despite this behavior
being questionable.
The `newLineInDisplayMode` error code, which flags the use of `\\` or `\newline` in display mode outside an array or tabular environment, is intentionally designed not to throw an error, despite this behavior being questionable.
throwOnError
: (`bool`) Whether to throw a `ParseError` when KaTeX encounters an unsupported command or invalid LaTeX. Default is `true`.
@@ -95,66 +92,65 @@ The example below demonstrates error handing within a template.
Instead of client-side JavaScript rendering of mathematical markup using MathJax or KaTeX, create a passthrough render hook which calls the `transform.ToMath` function.
### 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.
[passthrough extension]: /configuration/markup/#passthrough
{{< 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 = [['\(', '\)']]
{{< /code-toggle >}}
[markup.goldmark.extensions.passthrough.delimiters]
block = [['\[', '\]'], ['$$', '$$']]
inline = [['\(', '\)']]
{{< /code-toggle >}}
> [!note]
> The configuration above precludes the use of the `$...$` delimiter pair for inline equations. Although you can add this delimiter pair to the configuration, you must double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting.
> [!note]
> The configuration above precludes the use of the `$...$` delimiter pair for inline equations. Although you can add this delimiter pair to the configuration, you must double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting.
Step 2
: Create a [passthrough render hook][] to capture and render the LaTeX markup.4
### Step 2
[passthrough render hook]: /render-hooks/passthrough/
Create a [passthrough render hook] to capture and render the LaTeX markup.
```go-html-template {file="layouts/_markup/render-passthrough.html" copy=true}
{{- $opts := dict "output" "htmlAndMathml" "displayMode" (eq .Type "block") }}
{{- with try (transform.ToMath .Inner $opts) }}
{{- with .Err }}
{{- errorf "Unable to render mathematical markup to HTML using the transform.ToMath function. The KaTeX display engine threw the following error: %s: see %s." . $.Position }}
{{- else }}
{{- .Value }}
{{- $.Page.Store.Set "hasMath" true }}
{{- end }}
{{- end -}}
```
Step 3
: In your base template, conditionally include the KaTeX CSS within the head element.
```go-html-template {file="layouts/_markup/render-passthrough.html" copy=true}
{{- $opts := dict "output" "htmlAndMathml" "displayMode" (eq .Type "block") }}
{{- with try (transform.ToMath .Inner $opts) }}
{{- with .Err }}
{{- errorf "Unable to render mathematical markup to HTML using the transform.ToMath function. The KaTeX display engine threw the following error: %s: see %s." . $.Position }}
{{- else }}
{{- .Value }}
{{- $.Page.Store.Set "hasMath" true }}
{{- end }}
{{- end -}}
```
```go-html-template {file="layouts/baseof.html" copy=true}
<head>
{{ $noop := .WordCount }}
{{ if .Page.Store.Get "hasMath" }}
<link href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css" rel="stylesheet">
{{ end }}
</head>
```
### Step 3
In the above, note the use of a [noop](g) statement to force content rendering before we check the value of `hasMath` with the `Store.Get` method.
In your base template, conditionally include the KaTeX CSS within the head element.
Step 4
: Add some mathematical markup to your content, then test.
```go-html-template {file="layouts/baseof.html" copy=true}
<head>
{{ $noop := .WordCount }}
{{ if .Page.Store.Get "hasMath" }}
<link href="https://cdn.jsdelivr.net/npm/katex@0.16.22/dist/katex.min.css" rel="stylesheet">
{{ end }}
</head>
```
```text {file="content/example.md"}
This is an inline \(a^*=x-b^*\) equation.
In the above, note the use of a [noop](g) statement to force content rendering before we check the value of `hasMath` with the `Store.Get` method.
These are block equations:
### Step 4
\[a^*=x-b^*\]
Add some mathematical markup to your content, then test.
```text {file="content/example.md"}
This is an inline \(a^*=x-b^*\) equation.
These are block equations:
\[a^*=x-b^*\]
$$a^*=x-b^*$$
```
$$a^*=x-b^*$$
```
## Chemistry
@@ -172,6 +168,4 @@ $$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$
[KaTeX]: https://katex.org/
[MathML]: https://developer.mozilla.org/en-US/docs/Web/MathML
[mhchem]: https://mhchem.github.io/MathJax-mhchem/
[passthrough extension]: /configuration/markup/#passthrough
[passthrough render hook]: /render-hooks/passthrough/
[rendering options]: https://katex.org/docs/options.html
@@ -196,10 +196,7 @@ my-theme/
├── i18n/
├── layouts/
├── static/
── LICENSE
├── README.md
├── hugo.toml
└── theme.toml
── hugo.toml
```
Using the union file system described above, Hugo mounts each of these directories to the corresponding location in the project. When two files have the same path, the file in the project directory takes precedence. This allows you, for example, to override a theme's template by placing a copy in the same location within the project directory.
@@ -7,6 +7,9 @@ keywords: []
weight: 40
---
> [!note]
> Many of the resources on this page, including older books and videos, may contain out-of-date information. The Hugo software has undergone significant changes since these resources were created. These changes include the introduction of a new template system, the deprecation of various functions and settings, and the addition of new features like Markdown render hooks, content adapters, and support for mathematical markup. While some concepts may still be relevant, it's recommended to consult the official Hugo documentation for the most current and accurate information.
## Books
### Hugo in Action
@@ -1,52 +0,0 @@
---
title: Host on 21YunBox
description: Host your site on 21YunBox.
categories: []
keywords: []
aliases: [/hosting-and-deployment/hosting-on-21yunbox/]
---
[21YunBox](https://www.21cloudbox.com/) is a fully-managed cloud platform dedicated to make web deployment easy within the Chinese Great Firewall where you can host static sites, backend APIs, databases, cron jobs, and all your other apps in one place. It provides blazing fast Chinese CDN, continuous deployment, one-click HTTPS and [other services like managed databases and backend web services](https://www.21cloudbox.com/docs/), providing an avenue to launch web projects in China.
21YunBox includes the following features:
- Continuous, automatic builds & deploys from GitHub and Gitee
- Automatic SSL certificates through [Let's Encrypt](https://letsencrypt.org)
- Instant cache invalidation with a blazing fast, Chinese CDN
- Unlimited [custom domains](https://www.21cloudbox.com/dns-configuration.html)
- Automatic [Brotli compression](https://en.wikipedia.org/wiki/Brotli) for faster sites
- Native HTTP/2 support
- Automatic HTTP → HTTPS redirects
- Custom URL redirects and rewrites
## Prerequisites
This guide assumes you already have a Hugo project to deploy. If you need a project, use the [Quick Start](/getting-started/quick-start/) to get started or fork 21YunBox's [Hugo Example](https://gitee.com/eryiyunbox-examples/hello-hugo) before continuing.
## Setup
You can set up a Hugo site on 21YunBox in two quick steps:
1. Create a new web service on 21YunBox, and give 21YunBox permission to access your GitHub or Gitee repo.
1. Use the following values during creation:<!-- do not insert blank line -->
| Field | Value |
| ----------------- | ------------------------------------------------ |
| Environment | `Static Site` |
| Build Command | `hugo --gc --minify` (or your own build command) |
| Publish Directory | `./public` (or your own output directory) |
That's it! Your site will be live on your 21YunBox URL (which looks like `yoursite.21yunbox.com`) as soon as the build is done.
## Continuous deploys
Now that 21YunBox is connected to your repo, it will automatically build and publish your site any time you push to GitHub.
Every deploy automatically and instantly invalidates the CDN cache, so your users can always access the latest content on your site.
## Custom domains
Add your own domains to your site easily using 21YunBox's [custom domains](https://www.21cloudbox.com/dns-configuration.html) guide.
## Support
Click [here](https://www.21cloudbox.com/contact.html) to contact with 21YunBox' experts if you need help.
@@ -6,155 +6,152 @@ keywords: []
aliases: [/hosting-and-deployment/hosting-on-aws-amplify/]
---
Use these instructions to enable continuous deployment from a GitHub repository. The same general steps apply if you are using GitLab for version control.
## Prerequisites
Please complete the following tasks before continuing:
1. [Create an AWS account]
1. [Install Git]
1. [Create a Hugo site] and test it locally with `hugo server`
1. Commit the changes to your local repository
1. Push the local repository to your [GitHub], [GitLab], or [Bitbucket] account
[Bitbucket]: https://bitbucket.org/product
[Create a Hugo site]: /getting-started/quick-start/
[Create an AWS account]: https://aws.amazon.com/resources/create-account/
[GitHub]: https://github.com
[GitLab]: https://about.gitlab.com/
[Install Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
1. [Create](https://aws.amazon.com/resources/create-account/) an AWS account
1. [Log in](https://console.aws.amazon.com/) to your AWS account
1. [Create](https://github.com/signup) a GitHub account
1. [Log in](https://github.com/login) to your GitHub account
1. [Create](https://github.com/new) a GitHub repository for your project
1. [Create](https://git-scm.com/docs/git-init) a local Git repository for your project with a [remote](https://git-scm.com/docs/git-remote) reference to your GitHub repository
1. Create a Hugo site within your local Git repository and test it with the `hugo server` command
1. Commit the changes to your local Git repository and push to your GitHub repository.
## Procedure
This procedure will enable continuous deployment from a GitHub repository. The procedure is essentially the same if you are using GitLab or Bitbucket.
### Step 1
Step 1
: Create a file named `amplify.yml` in the root of your project.
Create a file named `amplify.yml` in the root of your project.
```sh
touch amplify.yml
```
```sh
touch amplify.yml
```
Step 2
: Copy and paste the YAML below into the file you created. Change the application versions and time zone as needed.
### Step 2
```yaml {file="amplify.yml" copy=true}
version: 1
env:
variables:
# Application versions
DART_SASS_VERSION: 1.90.0
GO_VERSION: 1.24.5
HUGO_VERSION: 0.148.2
# Time zone
TZ: Europe/Oslo
# Cache
HUGO_CACHEDIR: ${PWD}/.hugo
NPM_CONFIG_CACHE: ${PWD}/.npm
frontend:
phases:
preBuild:
commands:
# Create directory for user-specific executable files
- echo "Creating directory for user-specific executable files..."
- mkdir -p "${HOME}/.local"
Copy and paste the YAML below into the file you created. Change the application versions and time zone as needed.
# Install Dart Sass
- echo "Installing Dart Sass ${DART_SASS_VERSION}..."
- curl -sLJO "https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz"
- tar -C "${HOME}/.local" -xf "dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz"
- rm "dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz"
- export PATH="${HOME}/.local/dart-sass:${PATH}"
```yaml {file="amplify.yml" copy=true}
version: 1
env:
variables:
# Application versions
DART_SASS_VERSION: 1.89.2
GO_VERSION: 1.24.2
HUGO_VERSION: 0.147.9
# Time zone
TZ: America/Los_Angeles
# Cache
HUGO_CACHEDIR: ${PWD}/.hugo
NPM_CONFIG_CACHE: ${PWD}/.npm
frontend:
phases:
preBuild:
commands:
# Install Dart Sass
- curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
- sudo tar -C /usr/local/bin -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
- rm dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
- export PATH=/usr/local/bin/dart-sass:$PATH
# Install Go
- echo "Installing Go ${GO_VERSION}..."
- curl -sLJO "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz"
- tar -C "${HOME}/.local" -xf "go${GO_VERSION}.linux-amd64.tar.gz"
- rm "go${GO_VERSION}.linux-amd64.tar.gz"
- export PATH="${HOME}/.local/go/bin:${PATH}"
# Install Go
- curl -LJO https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz
- sudo tar -C /usr/local -xf go${GO_VERSION}.linux-amd64.tar.gz
- rm go${GO_VERSION}.linux-amd64.tar.gz
- export PATH=/usr/local/go/bin:$PATH
# Install Hugo
- echo "Installing Hugo ${HUGO_VERSION}..."
- curl -sLJO "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz"
- mkdir "${HOME}/.local/hugo"
- tar -C "${HOME}/.local/hugo" -xf "hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz"
- rm "hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz"
- export PATH="${HOME}/.local/hugo:${PATH}"
# Install Hugo
- curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz
- sudo tar -C /usr/local/bin -xf hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz
- rm hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz
- export PATH=/usr/local/bin:$PATH
# Verify installations
- echo "Verifying installations..."
- "echo Dart Sass: $(sass --version)"
- "echo Go: $(go version)"
- "echo Hugo: $(hugo version)"
- "echo Node.js: $(node --version)"
# Check installed versions
- go version
- hugo version
- node -v
- npm -v
- sass --embedded --version
# Install Node.js dependencies
- echo "Installing Node.js dependencies..."
- "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci --prefer-offline || true"
# Install Node.JS dependencies
- "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci --prefer-offline || true"
# Configure Git
- echo "Configuring Git..."
- git config core.quotepath false
build:
commands:
- echo "Building site..."
- hugo --gc --minify
artifacts:
baseDirectory: public
files:
- '**/*'
cache:
paths:
- ${HUGO_CACHEDIR}/**/*
- ${NPM_CONFIG_CACHE}/**/*
```
# https://github.com/gohugoio/hugo/issues/9810
- git config --add core.quotepath false
build:
commands:
- hugo --gc --minify
artifacts:
baseDirectory: public
files:
- '**/*'
cache:
paths:
- ${HUGO_CACHEDIR}/**/*
- ${NPM_CONFIG_CACHE}/**/*
```
Step 3
: Commit and push the change to your GitHub repository.
### Step 3
```sh
git add -A
git commit -m "Create amplify.yml"
git push
```
Commit and push the change to your GitHub repository.
Step 4
: Log in to your AWS account, navigate to the [Amplify Console], then press the **Deploy an app** button.
```sh
git add -A
git commit -m "Create amplify.yml"
git push
```
### Step 4
Log in to your AWS account, navigate to the [Amplify Console], then press the **Deploy an app** button.
[Amplify Console]: https://console.aws.amazon.com/amplify/apps
### Step 5
Choose a source code provider, then press the **Next** button.
Step 5
: Choose a source code provider, then press the **Next** button.
![screen capture](amplify-step-05.png)
### Step 6
Authorize AWS Amplify to access your GitHub account.
Step 6
: Authorize AWS Amplify to access your GitHub account.
![screen capture](amplify-step-06.png)
### Step 7
Select your personal account or relevant organization.
Step 7
: Select your personal account or relevant organization.
![screen capture](amplify-step-07.png)
### Step 8
Authorize access to one or more repositories.
Step 8
: Authorize access to one or more repositories.
![screen capture](amplify-step-08.png)
### Step 9
Select a repository and branch, then press the **Next** button.
Step 9
: Select a repository and branch, then press the **Next** button.
![screen capture](amplify-step-09.png)
### Step 10
Step 10
: On the "App settings" page, scroll to the bottom then press the **Next** button. Amplify reads the `amplify.yml` file you created in Steps 1-3 instead of using the values on this page.
On the "App settings" page, scroll to the bottom then press the **Next** button. Amplify reads the `amplify.yml` file you created in Steps 1-3 instead of using the values on this page.
Step 11
: On the "Review" page, scroll to the bottom then press the **Save and deploy** button.
### Step 11
On the "Review" page, scroll to the bottom then press the **Save and deploy** button.
### Step 12
When your site has finished deploying, press the **Visit deployed URL** button to view your published site.
Step 12
: When your site has finished deploying, press the **Visit deployed URL** button to view your published site.
![screen capture](amplify-step-11.png)
[Amplify Console]: https://console.aws.amazon.com/amplify/apps
@@ -1,11 +0,0 @@
---
title: Host on Cloudflare Pages
description: Host your site on Cloudflare Pages.
categories: []
keywords: []
aliases: [/hosting-and-deployment/hosting-on-cloudflare-pages/]
---
[Cloudflare Pages](https://developers.cloudflare.com/pages/) are super fast, always up-to-date, and deployed directly from your [Git provider](https://developers.cloudflare.com/pages/get-started/#connect-your-git-provider-to-pages).
Cloudflare Pages docs have a detailed tutorial on [how to deploy a Hugo site](https://developers.cloudflare.com/pages/framework-guides/deploy-a-hugo-site/).
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

@@ -0,0 +1,166 @@
---
title: Host on Cloudflare
description: Host your site on Cloudflare.
categories: []
keywords: []
---
Use these instructions to enable continuous deployment from a GitHub repository. The same general steps apply if you are using GitLab for version control.
## Prerequisites
Please complete the following tasks before continuing:
1. [Create](https://dash.cloudflare.com/sign-up) a Cloudflare account
1. [Log in](https://dash.cloudflare.com/login) to your Cloudflare account
1. [Create](https://github.com/signup) a GitHub account
1. [Log in](https://github.com/login) to your GitHub account
1. [Create](https://github.com/new) a GitHub repository for your project
1. [Create](https://git-scm.com/docs/git-init) a local Git repository for your project with a [remote](https://git-scm.com/docs/git-remote) reference to your GitHub repository
1. Create a Hugo site within your local Git repository and test it with the `hugo server` command
## Procedure
Step 1
: Create a `wrangler.toml` file in the root of your project.
```toml {file="wrangler.toml" copy=true}
# Configure Cloudflare Worker
name = "hosting-cloudflare-worker"
compatibility_date = "2025-07-31"
[build]
command = "chmod a+x build.sh && ./build.sh"
[assets]
directory = "./public"
not_found_handling = "404"
```
Step 2
: Create a `build.sh` file in the root of your project.
```sh {file="build.sh" copy=true}
#!/usr/bin/env bash
#------------------------------------------------------------------------------
# @file
# Builds a Hugo site hosted on a Cloudflare Worker.
#
# The Cloudflare Worker automatically installs Node.js dependencies.
#------------------------------------------------------------------------------
main() {
DART_SASS_VERSION=1.90.0
GO_VERSION=1.24.5
HUGO_VERSION=0.148.2
NODE_VERSION=22.18.0
export TZ=Europe/Oslo
# Install Dart Sass
echo "Installing Dart Sass ${DART_SASS_VERSION}..."
curl -sLJO "https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz"
tar -C "${HOME}/.local" -xf "dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz"
rm "dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz"
export PATH="${HOME}/.local/dart-sass:${PATH}"
# Install Go
echo "Installing Go ${GO_VERSION}..."
curl -sLJO "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz"
tar -C "${HOME}/.local" -xf "go${GO_VERSION}.linux-amd64.tar.gz"
rm "go${GO_VERSION}.linux-amd64.tar.gz"
export PATH="${HOME}/.local/go/bin:${PATH}"
# Install Hugo
echo "Installing Hugo ${HUGO_VERSION}..."
curl -sLJO "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz"
mkdir "${HOME}/.local/hugo"
tar -C "${HOME}/.local/hugo" -xf "hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz"
rm "hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz"
export PATH="${HOME}/.local/hugo:${PATH}"
# Install Node.js
echo "Installing Node.js ${NODE_VERSION}..."
curl -sLJO "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz"
tar -C "${HOME}/.local" -xf "node-v${NODE_VERSION}-linux-x64.tar.xz"
rm "node-v${NODE_VERSION}-linux-x64.tar.xz"
export PATH="${HOME}/.local/node-v${NODE_VERSION}-linux-x64/bin:${PATH}"
# Verify installations
echo "Verifying installations..."
echo Dart Sass: "$(sass --version)"
echo Go: "$(go version)"
echo Hugo: "$(hugo version)"
echo Node.js: "$(node --version)"
# Configure Git
echo "Configuring Git..."
git config core.quotepath false
if [ "$(git rev-parse --is-shallow-repository)" = "true" ]; then
git fetch --unshallow
fi
# Build the site
echo "Building the site..."
hugo --gc --minify
}
set -euo pipefail
main "$@"
```
Step 3
: Commit the changes to your local Git repository and push to your GitHub repository.
Step 4
: In the upper right corner of the Cloudflare [dashboard](https://dash.cloudflare.com/), press the **Add** button and select "Workers" from the drop down menu.
![screen capture](cloudflare-01.png)
Step 5
: On the "Workers" tab, press the **Get started** button to the right of the "Import a repository" item.
![screen capture](cloudflare-02.png)
Step 6
: Connect to GitHub.
![screen capture](cloudflare-03.png)
Step 7
: Select the GitHub account where you want to install the Cloudflare Workers and Pages application.
![screen capture](cloudflare-04.png)
Step 8
: Authorize the Cloudflare Workers and Pages application to access all repositories or only select repositories, then press the **Install & Authorize** button.
![screen capture](cloudflare-05.png)
Your browser will be redirected to the Cloudflare dashboard.
Step 9
: On the "Workers" tab, press the **Get started** button to the right of the "Import a repository" item.
![screen capture](cloudflare-02.png)
Step 10
: Select the repository to import.
![screen capture](cloudflare-06.png)
Step 11
: On the "Set up your application" screen, provide a project name, leave the build command blank, then press the **Create and deploy** button.
![screen capture](cloudflare-07.png)
Step 12
: Wait for the site to build and deploy, then visit your site.
![screen capture](cloudflare-08.png)
In the future, whenever you push a change from your local Git repository, Cloudflare will rebuild and deploy your site.
@@ -51,9 +51,11 @@ git remote add origin https://codeberg.org/<YourUsername>/pages.git
git push -u origin main
```
## Automated deployment using Woodpecker CI
## Automated deployment
There are two methods you can use to deploy your Hugo website to Codeberg automatically. These are: Woodpecker CI and Forgejo Actions.
You can automatically deploy your Hugo website to Codeberg using one of two methods: Woodpecker CI or Forgejo Actions.
### Woodpecker CI
To use Codeberg's Woodpecker CI, you need to have or [request] access to it, as well as add a `.woodpecker.yaml` file in the root of your project. A template and additional instructions are available in the official [examples repository].
@@ -78,7 +80,7 @@ git push -u origin main
Your project will then be built and deployed by Codeberg's Woodpecker CI.
## Automated deployment using Forgejo Actions
### Forgejo Actions
The other way to deploy your website to Codeberg pages automatically is to make use of Forgejo Actions. Actions need a _runner_ to work, and Codeberg has [great documentation] on how to set one up yourself. However, Codeberg provides a [handful of humble runners] themselves (they say this feature is in "open alpha"), which actually seem powerful enough to build at least relatively simple websites.
@@ -109,7 +111,7 @@ jobs:
runs-on: codeberg-tiny-lazy
container:
# Specify "hugomods/hugo:exts" if you want to always use the latest version of Hugo for building.
image: "hugomods/hugo:exts-0.147.9"
image: "hugomods/hugo:exts-0.148.0"
steps:
- name: Clone the repository
uses: https://code.forgejo.org/actions/checkout@v4
@@ -160,21 +162,25 @@ jobs:
The second file implements a more complex scenario: having your website sources in one repository and the resulting static website in another repository (in this case, `pages`). If you want Codeberg to make your website available at the root of your pages subdomain (`https://<YourUsername>.codeberg.page/`), you have to push that website to the default branch of your repository named `pages`.
Since this action involves more than one repository, it will require a bit more preparation:
1. Create the target repository. Name it `pages`.
2. Generate a new SSH key. *Do not* use any of your own SSH keys for this, but generate one for this specific task only. On Linux, BSD, and, likely, other operating systems, you can open a terminal emulator and run the following command to generate the key:
1. Generate a new SSH key. Do not use any of your own SSH keys for this, but generate one for this specific task only. On Linux, BSD, and, likely, other operating systems, you can open a terminal emulator and run the following command to generate the key:
```shell
ssh-keygen -f pagesbuild -P ""
```
This will generate two files in your current directory: `pagesbuild` (private key) and `pagesbuild.pub` (public key).
3. Add the newly generated public key as a deploy key to your `pages` repository: navigate to its Settings, click on "Deploy keys" in the left menu, click the "Add deploy key" button, give it a name (e.g. "Actions deploy key"), paste the contents of the **public** key file (`pagesbuild.pub`) to the Content field, tick the "Enable write access" checkbox, then submit the form.
4. Navigate back to your source repository settings, expand the "Actions" menu and click on "Secrets". Then click "Add Secret", enter "DEPLOY_KEY" as the secret name and paste the contents of the newly generated **private** key file (`pagesbuild`) into the Value field.
5. Navigate to the "Variables" submenu of the "Actions" menu and add the following variables:
| Name | Value |
|---------------------|----------------------------------------------------------------------------------|
| `TARGET_REPOSITORY` | `<YourUsername>/pages` |
| `TARGET_BRANCH` | `main` (enter the default branch name of the `pages` repo here) |
| `SSH_KNOWN_HOSTS` | (paste the output you get by running `ssh-keyscan codeberg.org` in the terminal) |
This will generate two files in your current directory: `pagesbuild` (private key) and `pagesbuild.pub` (public key).
1. Add the newly generated public key as a deploy key to your `pages` repository: navigate to its Settings, click on "Deploy keys" in the left menu, click the "Add deploy key" button, give it a name (e.g. "Actions deploy key"), paste the contents of the **public** key file (`pagesbuild.pub`) to the Content field, tick the "Enable write access" checkbox, then submit the form.
1. Navigate back to your source repository settings, expand the "Actions" menu and click on "Secrets". Then click "Add Secret", enter "DEPLOY_KEY" as the secret name and paste the contents of the newly generated **private** key file (`pagesbuild`) into the Value field.
1. Navigate to the "Variables" submenu of the "Actions" menu and add the following variables:
Name|Value
:--|:--
`TARGET_REPOSITORY`|`<YourUsername>/pages`
`TARGET_BRANCH`|`main` (enter the default branch name of the `pages` repo here)
`SSH_KNOWN_HOSTS`|(paste the output you get by running `ssh-keyscan codeberg.org` in the terminal)
Once you've done all of the above, commit the following file to your repository as `.forgejo/workflows/hugo.yaml`. As you can see, the `deploy` job of this workflow is slightly different from the file above:
@@ -195,7 +201,7 @@ jobs:
runs-on: codeberg-tiny-lazy
container:
# Specify "hugomods/hugo:exts" if you want to always use the latest version of Hugo for building.
image: "hugomods/hugo:exts-0.147.9"
image: "hugomods/hugo:exts-0.148.0"
steps:
- name: Clone the repository
uses: https://code.forgejo.org/actions/checkout@v4
@@ -249,6 +255,27 @@ jobs:
Once you commit one of the two files to your website source repository, you should see your first automated build firing up pretty soon. You can also trigger it manually by navigating to the **Actions** section of your repository web page, choosing **hugo.yaml** on the left and clicking on **Run workflow**.
## Forgejo Actions custom domains
Codeberg Pages relies on a `.domains` file to identify allowed domains for a specific branch. It's important that this file is located in the root directory of your output repository or branch, rather than in the root directory of your source files. To achieve this, simply place your `.domains` file in the `static` directory of your project. When your site is built, it will be automatically copied to the `public` directory, which serves as the root of your output.
When looking at the example `.forgejo/workflows/hugo.yaml`, you'll notice that the `upload-artifact@v3` action is used to upload the public directory to the deployment branch.
By default, both `upload-artifact@v3` and `upload-artifact@v4` exclude all dot files from being uploaded unless you specifically tell them not to (you can find more details [here]).
By default, upload-artifact@v3 and upload-artifact@v4 exclude all dot files from being uploaded. You can find more details on [how to handle dot files and other file patterns in the documentation](https://github.com/actions/upload-artifact/issues/602). To make sure dot files are included, modify your workflow like this:
```yaml {file=".forgejo/workflows/hugo.yaml" copy=true}
- name: Upload generated files
uses: https://code.forgejo.org/actions/upload-artifact@v3
with:
name: Generated files
path: public/
include-hidden-files: true # Prevents excluding .domains from uploading
```
If you're using a custom domain, it's important to update your workflow file accordingly.
## Other resources
- [Codeberg Pages](https://codeberg.page/)
@@ -43,22 +43,22 @@ From here:
In new versions of Firebase, some other questions apply:
6. Set up automatic builds and deploys with GitHub?
1. Set up automatic builds and deploys with GitHub?
Here you will be redirected to login in your GitHub account to get permissions. Confirm.
Here you will be redirected to login in your GitHub account to get permissions. Confirm.
7. For which GitHub repository would you like to set up a GitHub workflow? (format: user/repository)
1. For which GitHub repository would you like to set up a GitHub workflow? (format: user/repository)
Include the repository you will use in the format above (Account/Repo)
Firebase script with retrieve credentials, create a service account you can later manage in your GitHub settings.
Include the repository you will use in the format above (Account/Repo)
Firebase script with retrieve credentials, create a service account you can later manage in your GitHub settings.
8. Set up the workflow to run a build script before every deploy?
1. Set up the workflow to run a build script before every deploy?
Here is your opportunity to include some commands before you run the deploy.
Here is your opportunity to include some commands before you run the deploy.
9. Set up automatic deployment to your site's live channel when a PR is merged?
1. Set up automatic deployment to your site's live channel when a PR is merged?
You can let in the default option (main)
You can let in the default option (main)
After that Firebase has been set in your project with [CI/CD](g). After that run:
@@ -66,7 +66,7 @@ After that Firebase has been set in your project with [CI/CD](g). After that run
hugo && firebase deploy
```
With this you will have the app initialized manually. After that you can manage and fix your GitHub workflow from: https://github.com/your-account/your-repo/actions
With this you will have the app initialized manually. After that you can manage and fix your GitHub workflow from <https://github.com/your-account/your-repo/actions>.
Don't forget to update your static pages before push!

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

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