From: Bjørn Erik Pedersen Date: Sat, 23 Aug 2025 10:39:28 +0000 (+0200) Subject: Merge commit 'bfa74537929f409fca841540b971125b7678963a' X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=ff3ae62933896c5892159566de1998e80973b5c8;p=brevno-suite%2Fhugo Merge commit 'bfa74537929f409fca841540b971125b7678963a' --- ff3ae62933896c5892159566de1998e80973b5c8 diff --cc docs/.codespellrc index 564fc77c0,000000000..f322b0123 mode 100644,000000..100644 --- a/docs/.codespellrc +++ b/docs/.codespellrc @@@ -1,13 -1,0 +1,13 @@@ +# Config file for codespell. +# https://github.com/codespell-project/codespell#using-a-config-file + +[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 diff --cc docs/.cspell.json index 16f9bd9f2,000000000..28dba57be mode 100644,000000..100644 --- a/docs/.cspell.json +++ b/docs/.cspell.json @@@ -1,186 -1,0 +1,197 @@@ +{ + "version": "0.2", + "allowCompoundWords": true, - "files": [ - "**/*.md" ++ "overrides": [ ++ { ++ "filename": "**/*", ++ "enabled": false ++ }, ++ { ++ "filename": "**/*.md", ++ "enabled": true ++ } + ], + "flagWords": [ + "alot", + "hte", + "langauge", + "reccommend", + "seperate", + "teh" + ], + "ignorePaths": [ + "**/emojis.md", + "**/commands/*", + "**/showcase/*", + "**/tools/*" + ], + "ignoreRegExpList": [ + "# cspell: ignore fenced code blocks", + "^(\\s*`{3,}).*[\\s\\S]*?^\\1$", + "# cspell: ignore words joined with dot", + "\\w+\\.\\w+", + "# cspell: ignore strings within backticks", + "`.+`", + "# cspell: ignore strings within double quotes", + "\".+\"", + "# cspell: ignore strings within brackets", + "\\[.+\\]", + "# cspell: ignore strings within parentheses", + "\\(.+\\)", + "# cspell: ignore words that begin with a slash", + "/\\w+", + "# cspell: ignore everything within action delimiters", + "\\{\\{.+\\}\\}", + "# cspell: ignore everything after a right arrow", + "\\s+→\\s+.+" + ], + "language": "en", + "words": [ + "composability", + "configurators", + "defang", + "deindent", + "downscale", + "downscaling", + "exif", + "geolocalized", + "grayscale", + "marshal", + "marshaling", + "multihost", + "multiplatfom", + "performantly", + "preconfigured", + "prerendering", + "redirection", + "redirections", + "subexpression", + "suppressible", + "synchronisation", + "templating", + "transpile", + "unmarshal", ++ "unmarshaled", + "unmarshaling", + "unmarshals", + "# ----------------------------------------------------------------------", + "# cspell: ignore hugo terminology", + "# ----------------------------------------------------------------------", + "alignx", + "aligny", + "attrlink", + "canonify", + "codeowners", + "dynacache", + "eturl", + "getenv", + "gohugo", + "gohugoio", + "keyvals", + "leftdelim", + "linkify", + "numworkermultiplier", + "rightdelim", + "shortcode", + "stringifier", + "struct", + "toclevels", + "unmarshal", + "unpublishdate", + "zgotmplz", + "# ----------------------------------------------------------------------", + "# cspell: ignore foreign language words", + "# ----------------------------------------------------------------------", + "bezpieczeństwo", + "blatt", + "buch", + "descripción", + "dokumentation", + "erklärungen", ++ "español", ++ "français", + "libros", + "mercredi", + "miesiąc", + "miesiąc", + "miesiąca", + "miesiące", + "miesięcy", + "misérables", + "mittwoch", + "muchos", + "novembre", + "otro", + "pocos", + "produkte", + "projekt", + "prywatność", + "referenz", + "régime", + "# ----------------------------------------------------------------------", + "# cspell: ignore names", + "# ----------------------------------------------------------------------", + "Atishay", + "Cosette", + "Eliott", + "Furet", + "Gregor", + "Jaco", + "Lanczos", + "Ninke", + "Noll", + "Pastorius", + "Samsa", + "Stucki", + "Thénardier", + "WASI", + "# ----------------------------------------------------------------------", + "# cspell: ignore operating systems and software packages", + "# ----------------------------------------------------------------------", + "asciidoctor", + "brotli", + "cifs", + "corejs", + "disqus", + "docutils", + "dpkg", + "doas", + "eopkg", ++ "forgejo", + "gitee", + "goldmark", + "katex", + "kubuntu", + "lubuntu", + "mathjax", + "nosql", + "pandoc", + "pkgin", + "rclone", + "xubuntu", + "# ----------------------------------------------------------------------", + "# cspell: ignore miscellaneous", + "# ----------------------------------------------------------------------", + "achristie", + "ccpa", + "cpra", + "ddmaurier", + "dring", + "fleqn", + "inor", + "jausten", + "jdoe", + "jsmith", + "leqno", + "milli", + "monokai", + "mysanityprojectid", + "rgba", + "rsmith", + "tdewolff", + "tjones", + "vcard", + "wcag", + "xfeff" + ] +} diff --cc docs/.github/workflows/codeql-analysis.yml index 86441b845,000000000..6f7038c9e mode 100644,000000..100644 --- a/docs/.github/workflows/codeql-analysis.yml +++ b/docs/.github/workflows/codeql-analysis.yml @@@ -1,26 -1,0 +1,26 @@@ +name: "CodeQL" + +on: + schedule: + - cron: "0 0 1 * *" + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + steps: + - name: Checkout repository - uses: actions/checkout@v4 ++ uses: actions/checkout@v5 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: "javascript" + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --cc docs/.github/workflows/markdownlint.yml index 000000000,000000000..0e2ac88fb new file mode 100644 --- /dev/null +++ b/docs/.github/workflows/markdownlint.yml @@@ -1,0 -1,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 diff --cc docs/.github/workflows/spellcheck.yml index e01ab1764,000000000..d9036f18a mode 100644,000000..100644 --- a/docs/.github/workflows/spellcheck.yml +++ b/docs/.github/workflows/spellcheck.yml @@@ -1,27 -1,0 +1,25 @@@ +name: "Check spelling" +on: + push: + pull_request: + branches-ignore: + - "dependabot/**" + +permissions: + contents: read + +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 diff --cc docs/.github/workflows/stale.yml index 000000000,000000000..c537f1642 new file mode 100644 --- /dev/null +++ b/docs/.github/workflows/stale.yml @@@ -1,0 -1,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. diff --cc docs/.markdownlint-cli2.yaml index 000000000,000000000..1ededafd0 new file mode 100644 --- /dev/null +++ b/docs/.markdownlint-cli2.yaml @@@ -1,0 -1,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 diff --cc docs/content/en/_common/functions/js/options.md index 475429d05,000000000..0c82fcae5 mode 100644,000000..100644 --- a/docs/content/en/_common/functions/js/options.md +++ b/docs/content/en/_common/functions/js/options.md @@@ -1,108 -1,0 +1,109 @@@ +--- +_comment: Do not remove front matter. +--- + +params +: (`map` or `slice`) Params that can be imported as JSON in your JS files, e.g. + + ```go-html-template + {{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }} + ``` ++ + And then in your JS file: + + ```js + import * as params from '@params'; + ``` + + Note that this is meant for small data sets, e.g., configuration settings. For larger data sets, please put/mount the files into `assets` and import them directly. + +minify +: (`bool`) Whether to let `js.Build` handle the minification. + +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 . + +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 . + +shims +: (`map`) This option allows swapping out a component with another. A common use case is to load dependencies like React from a CDN (with _shims_) when in production, but running with the full bundled `node_modules` dependency during development: + + ```go-html-template + {{ $shims := dict "react" "js/shims/react.js" "react-dom" "js/shims/react-dom.js" }} + {{ $js = $js | js.Build dict "shims" $shims }} + ``` + + The _shim_ files may look like these: + + ```js + // js/shims/react.js + module.exports = window.React; + ``` + + ```js + // js/shims/react-dom.js + module.exports = window.ReactDOM; + ``` + + With the above, these imports should work in both scenarios: + + ```js + import * as React from 'react'; + import * as ReactDOM from 'react-dom/client'; + ``` + +target +: (`string`) The language target. One of: `es5`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020`, `es2021`, `es2022`, `es2023`, `es2024`, or `esnext`. Default is `esnext`. + +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 . + +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 . + +defines +: (`map`) This option allows you to define a set of string replacements to be performed when building. It must be a map where each key will be replaced by its value. + + ```go-html-template + {{ $defines := dict "process.env.NODE_ENV" `"development"` }} + ``` + +drop +: {{< 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 + +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. + +sourcesContent +: {{< new-in 0.140.0 />}} +: (`bool`) Whether to include the content of the source files in the source map. By default, this is `true`. + +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 . + +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 . + + The combination of `JSX` and `JSXImportSource` is helpful if you want to use a non-React JSX library like Preact, e.g.: + + ```go-html-template + {{ $js := resources.Get "js/main.jsx" | js.Build (dict "JSX" "automatic" "JSXImportSource" "preact") }} + ``` + + With the above, you can use Preact components and JSX without having to manually import `h` and `Fragment` every time: + + ```jsx + import { render } from 'preact'; + + const App = () => <>Hello world!; + + const container = document.getElementById('app'); + if (container) render(, container); + ``` diff --cc docs/content/en/_common/gomodules-info.md index 5d88a6f9d,000000000..1eefff545 mode 100644,000000..100644 --- a/docs/content/en/_common/gomodules-info.md +++ b/docs/content/en/_common/gomodules-info.md @@@ -1,13 -1,0 +1,14 @@@ +--- +_comment: Do not remove front matter. +--- + +> [!note] Hugo Modules are Go Modules +> You need [Go] version 1.18 or later and [Git] to use Hugo Modules. For older sites hosted on Netlify, please ensure the `GO_VERSION` environment variable is set to `1.18` or higher. +> +> 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) + +[Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[Go]: https://go.dev/doc/install diff --cc docs/content/en/_common/installation/03-prebuilt-binaries.md index 34411cddd,000000000..c72a68bee mode 100644,000000..100644 --- a/docs/content/en/_common/installation/03-prebuilt-binaries.md +++ b/docs/content/en/_common/installation/03-prebuilt-binaries.md @@@ -1,23 -1,0 +1,17 @@@ +--- +_comment: Do not remove front matter. +--- + +## Prebuilt binaries + +Prebuilt binaries are available for a variety of operating systems and architectures. Visit the [latest release] page, and scroll down to the Assets section. + +1. Download the archive for the desired edition, operating system, and architecture +1. Extract the archive +1. Move the executable to the desired directory +1. Add this directory to the PATH environment variable +1. Verify that you have _execute_ permission on the file + +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 diff --cc docs/content/en/_common/methods/taxonomy/get-a-taxonomy-object.md index a6c46b8b7,000000000..c90224338 mode 100644,000000..100644 --- a/docs/content/en/_common/methods/taxonomy/get-a-taxonomy-object.md +++ b/docs/content/en/_common/methods/taxonomy/get-a-taxonomy-object.md @@@ -1,67 -1,0 +1,67 @@@ +--- +_comment: Do not remove front matter. +--- + +Before we can use a `Taxonomy` method, we need to capture a `Taxonomy` object. + +## Capture a Taxonomy object + +Consider this site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +genre = 'genres' +author = 'authors' +{{< /code-toggle >}} + +And this content structure: + +```text +content/ +├── books/ +│ ├── and-then-there-were-none.md --> genres: suspense +│ ├── death-on-the-nile.md --> genres: suspense +│ └── jamaica-inn.md --> genres: suspense, romance +│ └── pride-and-prejudice.md --> genres: romance +└── _index.md +``` + +To capture the "genres" `Taxonomy` object from within any template, use the [`Taxonomies`] method on a `Site` object. + +```go-html-template +{{ $taxonomyObject := .Site.Taxonomies.genres }} +``` + - To capture the "genres" `Taxonomy` object when rendering its page with a taxonomy template, use the [`Terms`] method on the page's [`Data`] object: ++To capture the "genres" `Taxonomy` object when rendering its page with a _taxonomy_ template, use the [`Terms`] method on the page's [`Data`] object: + +```go-html-template {file="layouts/taxonomy.html"} +{{ $taxonomyObject := .Data.Terms }} +``` + +To inspect the data structure: + +```go-html-template +
{{ debug.Dump $taxonomyObject }}
+``` + +Although the [`Alphabetical`] and [`ByCount`] methods provide a better data structure for ranging through the taxonomy, you can render the weighted pages by term directly from the `Taxonomy` object: + +```go-html-template +{{ range $term, $weightedPages := $taxonomyObject }} +

{{ .Page.LinkTitle }}

+ +{{ end }} +``` + +In the example above, the first anchor element is a link to the term page. + +[`Alphabetical`]: /methods/taxonomy/alphabetical/ +[`ByCount`]: /methods/taxonomy/bycount/ + +[`data`]: /methods/page/data/ +[`terms`]: /methods/page/data/#in-a-taxonomy-template +[`taxonomies`]: /methods/site/taxonomies/ diff --cc docs/content/en/_common/permalink-tokens.md index e8443101a,000000000..62b4b0d0c mode 100644,000000..100644 --- a/docs/content/en/_common/permalink-tokens.md +++ b/docs/content/en/_common/permalink-tokens.md @@@ -1,77 -1,0 +1,75 @@@ +--- +_comment: Do not remove front matter. +--- + +`:year` +: The 4-digit year as defined in the front matter `date` field. + +`:month` +: The 2-digit month as defined in the front matter `date` field. + +`:monthname` +: The name of the month as defined in the front matter `date` field. + +`:day` +: The 2-digit day as defined in the front matter `date` field. + +`:weekday` +: The 1-digit day of the week as defined in the front matter `date` field (Sunday = `0`). + +`:weekdayname` +: The name of the day of the week as defined in the front matter `date` field. + +`:yearday` +: The 1- to 3-digit day of the year as defined in the front matter `date` field. + +`:section` +: The content's section. + +`:sectionslug` +: The content's section using slugified section name. The slugified section name is the `slug` as defined in front matter, else the `title` as defined in front matter, else the automatic title. + +`:sections` +: The content's sections hierarchy. You can use a selection of the sections using _slice syntax_: `:sections[1:]` includes all but the first, `:sections[:last]` includes all but the last, `:sections[last]` includes only the last, `:sections[1:2]` includes section 2 and 3. Note that this slice access will not throw any out-of-bounds errors, so you don't have to be exact. + +`:sectionslugs` +: The content's sections hierarchy using slugified section names. The slugified section name is the `slug` as defined in front matter, else the `title` as defined in front matter, else the automatic title. You can use a selection of the sections using _slice syntax_: `:sectionslugs[1:]` includes all but the first, `:sectionslugs[:last]` includes all but the last, `:sectionslugs[last]` includes only the last, `:sectionslugs[1:2]` includes section 2 and 3. Note that this slice access will not throw any out-of-bounds errors, so you don't have to be exact. + +`:title` +: The `title` as defined in front matter, else the automatic title. Hugo generates titles automatically for section, taxonomy, and term pages that are not backed by a file. + +`:slug` +: The `slug` as defined in front matter, else the `title` as defined in front matter, else the automatic title. Hugo generates titles automatically for section, taxonomy, and term pages that are not backed by a file. + +`:filename` +: The content's file name without extension, applicable to the `page` page kind. + + {{< deprecated-in v0.144.0 >}} + The `:filename` token has been deprecated. Use `:contentbasename` instead. + {{< /deprecated-in >}} + +`:slugorfilename` +: The `slug` as defined in front matter, else the content's file name without extension, applicable to the `page` page kind. + + {{< deprecated-in v0.144.0 >}} + The `:slugorfilename` token has been deprecated. Use `:slugorcontentbasename` instead. + {{< /deprecated-in >}} + +`:contentbasename` +: {{< new-in 0.144.0 />}} +: The [content base name]. + +[content base name]: /methods/page/file/#contentbasename + +`:slugorcontentbasename` +: {{< new-in 0.144.0 />}} +: The `slug` as defined in front matter, else the [content base name]. + +For time-related values, you can also use the layout string components defined in Go's [time package]. For example: + +[time package]: https://pkg.go.dev/time#pkg-constants + +{{< code-toggle file=hugo >}} +permalinks: + posts: /:06/:1/:2/:title/ +{{< /code-toggle >}} - - [content base name]: /methods/page/file/#contentbasename diff --cc docs/content/en/_common/render-hooks/pageinner.md index e5c0afb79,000000000..3efbc9ce3 mode 100644,000000..100644 --- a/docs/content/en/_common/render-hooks/pageinner.md +++ b/docs/content/en/_common/render-hooks/pageinner.md @@@ -1,47 -1,0 +1,47 @@@ +--- +_comment: Do not remove front matter. +--- + +## PageInner details + +{{< new-in 0.125.0 />}} + +The primary use case for `PageInner` is to resolve links and [page resources](g) relative to an included `Page`. For example, create an "include" shortcode to compose a page from multiple content files, while preserving a global context for footnotes and the table of contents: + +```go-html-template {file="layouts/_shortcodes/include.html" copy=true} +{{ with .Get 0 }} + {{ with $.Page.GetPage . }} + {{- .RenderShortcodes }} + {{ else }} + {{ errorf "The %q shortcode was unable to find %q. See %s" $.Name . $.Position }} + {{ end }} +{{ else }} + {{ errorf "The %q shortcode requires a positional parameter indicating the logical path of the file to include. See %s" .Name .Position }} +{{ end }} +``` + +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. + +> [!note] +> The `PageInner` method is only relevant for shortcodes that invoke the [`RenderShortcodes`] method, and you must call the shortcode using [Markdown notation]. + +As a practical example, Hugo's embedded link and image render hooks use the `PageInner` method to resolve markdown link and image destinations. See the source code for each: + +- [Embedded link render hook] +- [Embedded image render hook] + +[`RenderShortcodes`]: /methods/page/rendershortcodes/ +[Markdown notation]: /content-management/shortcodes/#notation +[Embedded link render hook]: {{% eturl render-link %}} +[Embedded image render hook]: {{% eturl render-image %}} diff --cc docs/content/en/_common/scratch-pad-scope.md index b659497d8,000000000..789b943e6 mode 100644,000000..100644 --- a/docs/content/en/_common/scratch-pad-scope.md +++ b/docs/content/en/_common/scratch-pad-scope.md @@@ -1,21 -1,0 +1,21 @@@ +--- +_comment: Do not remove front matter. +--- + +## Scope + +The method or function used to create a scratch pad determines its scope. For example, use the `Store` method on a `Page` object to create a scratch pad scoped to the page. + +Scope|Method or function +:--|:-- +page|[`PAGE.Store`] - site|[`SITE.Store`] ++site|[`SITE.Store`] +global|[`hugo.Store`] +local|[`collections.NewScratch`] +shortcode|[`SHORTCODE.Store`] + +[`page.store`]: /methods/page/store +[`site.store`]: /methods/site/store +[`hugo.store`]: /functions/hugo/store +[`collections.newscratch`]: functions/collections/newscratch +[`shortcode.store`]: /methods/shortcode/store diff --cc docs/content/en/_common/syntax-highlighting-options.md index 36144e090,000000000..11348f661 mode 100644,000000..100644 --- a/docs/content/en/_common/syntax-highlighting-options.md +++ b/docs/content/en/_common/syntax-highlighting-options.md @@@ -1,56 -1,0 +1,57 @@@ +--- +_comment: Do not remove front matter. +--- + +anchorLineNos +: (`bool`) Whether to render each line number as an HTML anchor element, setting the `id` attribute of the surrounding `span` element to the line number. Irrelevant if `lineNos` is `false`. Default is `false`. + +codeFences +: (`bool`) Whether to highlight fenced code blocks. Default is `true`. + +guessSyntax +: (`bool`) Whether to automatically detect the language if the `LANG` argument is blank or set to a language for which there is no corresponding [lexer](g). Falls back to a plain text lexer if unable to automatically detect the language. Default is `false`. + + > [!note] + > The Chroma syntax highlighter includes lexers for approximately 250 languages, but only 5 of these have implemented automatic language detection. + +hl_Lines +: (`string`) A space-delimited list of lines to emphasize within the highlighted code. To emphasize lines 2, 3, 4, and 7, set this value to `2-4 7`. This option is independent of the `lineNoStart` option. + +hl_inline +: (`bool`) Whether to render the highlighted code without a wrapping container. Default is `false`. + +lineAnchors +: (`string`) When rendering a line number as an HTML anchor element, prepend this value to the `id` attribute of the surrounding `span` element. This provides unique `id` attributes when a page contains two or more code blocks. Irrelevant if `lineNos` or `anchorLineNos` is `false`. + +lineNoStart +: (`int`) The number to display at the beginning of the first line. Irrelevant if `lineNos` is `false`. Default is `1`. + +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`). + - `table`: Enable table-based line numbers (sets `lineNumbersInTable` to `true`). + +lineNumbersInTable +: (`bool`) Whether to render the highlighted code in an HTML table with two cells. The left table cell contains the line numbers, while the right table cell contains the code. Irrelevant if `lineNos` is `false`. Default is `true`. + +noClasses +: (`bool`) Whether to use inline CSS styles instead of an external CSS file. Default is `true`. To use an external CSS file, set this value to `false` and generate the CSS file from the command line: + + ```text + hugo gen chromastyles --style=monokai > syntax.css + ``` + +style +: (`string`) The CSS styles to apply to the highlighted code. Case-sensitive. Default is `monokai`. See [syntax highlighting styles]. + +tabWidth +: (`int`) Substitute this number of spaces for each tab character in your highlighted code. Irrelevant if `noClasses` is `false`. Default is `4`. + +wrapperClass +: {{< new-in 0.140.2 />}} +: (`string`) The class or classes to use for the outermost element of the highlighted code. Default is `highlight`. + +[syntax highlighting styles]: /quick-reference/syntax-highlighting-styles/ diff --cc docs/content/en/about/features.md index ff1a6b8eb,000000000..d9fd36f61 mode 100644,000000..100644 --- a/docs/content/en/about/features.md +++ b/docs/content/en/about/features.md @@@ -1,136 -1,0 +1,136 @@@ +--- +title: Features +description: Hugo's rich and powerful feature set provides the framework and tools to create static sites that build in seconds, often less. +categories: [] +keywords: [] +weight: 20 +--- + +## Framework + +[Multiplatform] +: Install Hugo's single executable on Linux, macOS, Windows, and more. + +[Multilingual] +: Localize your project for each language and region, including translations, images, dates, currencies, numbers, percentages, and collation sequence. Hugo's multilingual framework supports single-host and multihost configurations. + +[Output formats] +: Render each page of your site to one or more output formats, with granular control by page kind, section, and path. While HTML is the default output format, you can add JSON, RSS, CSV, and more. For example, create a REST API to access content. + +[Templates] +: Create templates using variables, functions, and methods to transform your content, resources, and data into a published page. While HTML templates are the most common, you can create templates for any output format. + +[Themes] +: Reduce development time and cost by using one of the hundreds of themes contributed by the Hugo community. Themes are available for corporate sites, documentation projects, image portfolios, landing pages, personal and professional blogs, resumes, CVs, and more. + +[Modules] +: Reduce development time and cost by creating or importing packaged combinations of archetypes, assets, content, data, templates, translation tables, static files, or configuration settings. A module may serve as the basis for a new site, or to augment an existing site. + +[Privacy] +: Configure your site to help comply with regional privacy regulations. + +[Security] +: Hugo's security model is based on the premise that template and configuration authors are trusted, but content authors are not. This model enables generation of HTML output safe against code injection. Other protections prevent "shelling out" to arbitrary applications, limit access to specific environment variables, prevent connections to arbitrary remote data sources, and more. + +## Content authoring + +[Content formats] +: Create your content using Markdown, HTML, AsciiDoc, Emacs Org Mode, Pandoc, or reStructuredText. Markdown is the default content format, conforming to the [CommonMark] and [GitHub Flavored Markdown] specifications. + +[Markdown attributes] +: Apply HTML attributes such as `class` and `id` to Markdown images and block elements including blockquotes, fenced code blocks, headings, horizontal rules, lists, paragraphs, and tables. + +[Markdown extensions] +: Leverage the embedded Markdown extensions to create tables, definition lists, footnotes, task lists, inserted text, mark text, subscripts, superscripts, and more. + +[Markdown render hooks] +: Override the conversion of Markdown to HTML when rendering blockquotes, fenced code blocks, headings, images, links, and tables. For example, render every standalone image as an HTML `figure` element. + +[Diagrams] +: Use fenced code blocks and Markdown render hooks to include diagrams in your content. + +[Mathematics] +: Include mathematical equations and expressions in Markdown using LaTeX markup. + +[Syntax highlighting] +: Syntactically highlight code examples using Hugo's embedded syntax highlighter, enabled by default for fenced code blocks in Markdown. The syntax highlighter supports hundreds of code languages and dozens of styles. + +[Shortcodes] +: Use Hugo's embedded shortcodes, or create your own, to insert complex content. For example, use shortcodes to include `audio` and `video` elements, render tables from local or remote data sources, insert snippets from other pages, and more. + +## Content management + +[Content adapters] +: Create content adapters to dynamically add content when building your site. For example, use a content adapter to create pages from a remote data source such as JSON, TOML, YAML, or XML. + +[Taxonomies] +: Classify content to establish simple or complex logical relationships between pages. For example, create an authors taxonomy, and assign one or more authors to each page. Among other uses, the taxonomy system provides an inverted, weighted index to render a list of related pages, ordered by relevance. + +[Data] +: Augment your content using local or remote data sources including CSV, JSON, TOML, YAML, and XML. For example, create a shortcode to render an HTML table from a remote CSV file. + +[Menus] +: Provide rapid access to content via Hugo's menu system, configured automatically, globally, or on a page-by-page basis. The menu system is a key component of Hugo's multilingual architecture. + +[URL management] +: Serve any page from any path via global configuration or on a page-by-page basis. + +## Asset pipelines + +[Image processing] +: Convert, resize, crop, rotate, adjust colors, apply filters, overlay text and images, and extract EXIF data. + +[JavaScript bundling] +: Transpile TypeScript and JSX to JavaScript, bundle, tree shake, minify, create source maps, and perform SRI hashing. + +[Sass processing] +: Transpile Sass to CSS, bundle, tree shake, minify, create source maps, perform SRI hashing, and integrate with PostCSS. + +[Tailwind CSS processing] +: Compile Tailwind CSS utility classes into standard CSS, bundle, tree shake, optimize, minify, perform SRI hashing, and integrate with PostCSS. + +## Performance + +[Caching] - : 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. + +[Minification] +: Minify HTML, CSS, and JavaScript to reduce file size, bandwidth consumption, and loading times. + +[Multilingual]: /content-management/multilingual/ +[Multiplatform]: /installation/ +[Output formats]: /configuration/output-formats/ +[Templates]: /templates/introduction/ +[Themes]: https://themes.gohugo.io/ +[Modules]: /hugo-modules/ +[Privacy]: /configuration/privacy/ +[Security]: /about/security/ + +[Content formats]: /content-management/formats/ +[CommonMark]: https://spec.commonmark.org/current/ +[GitHub Flavored Markdown]: https://github.github.com/gfm/ +[Markdown attributes]: /content-management/markdown-attributes/ +[Markdown extensions]: /configuration/markup/#extensions +[Markdown render hooks]: /render-hooks/introduction/ +[Diagrams]: /content-management/diagrams/ +[Mathematics]: /content-management/mathematics/ +[Syntax highlighting]: /content-management/syntax-highlighting/ +[Shortcodes]: /content-management/shortcodes/ + +[Content adapters]: /content-management/content-adapters/ +[Taxonomies]: /content-management/taxonomies/ +[Data]: /content-management/data-sources/ +[Menus]: /content-management/menus/ +[URL management]: /content-management/urls/ + +[Image processing]: /content-management/image-processing/ +[JavaScript bundling]: /functions/js/build/ +[Sass processing]: /functions/css/Sass/ +[Tailwind CSS processing]: /functions/css/tailwindcss/ + +[Caching]: /functions/partials/includecached/ +[Segmentation]: /configuration/segments/ +[Minification]: /configuration/minify/ diff --cc docs/content/en/configuration/all.md index c64638499,000000000..c733e0a99 mode 100644,000000..100644 --- a/docs/content/en/configuration/all.md +++ b/docs/content/en/configuration/all.md @@@ -1,362 -1,0 +1,361 @@@ +--- +title: All settings +description: The complete list of Hugo configuration settings. +categories: [] +keywords: [] +weight: 20 +aliases: [/getting-started/configuration/] +--- + +## Settings + +archetypeDir +: (`string`) The designated directory for [archetypes](g). Default is `archetypes`. {{% module-mounts-note %}} + +assetDir +: (`string`) The designated directory for [global resources](g). Default is `assets`. {{% module-mounts-note %}} + +baseURL +: (`string`) The absolute URL of your published site including the protocol, host, path, and a trailing slash. + +build +: See [configure build](/configuration/build/). + +buildDrafts +: (`bool`) Whether to include draft content when building a site. Default is `false`. + +buildExpired +: (`bool`) Whether to include expired content when building a site. Default is `false`. + +buildFuture +: (`bool`) Whether to include future content when building a site. Default is `false`. + +cacheDir +: (`string`) The designated cache directory. See [details](#cache-directory). + +caches +: See [configure file caches](/configuration/caches/). + +canonifyURLs +: (`bool`) See [details](/content-management/urls/#canonical-urls) before enabling this feature. Default is `false`. + +capitalizeListTitles +: {{< new-in 0.123.3 />}} +: (`bool`) Whether to capitalize automatic list titles. Applicable to section, taxonomy, and term pages. Default is `true`. Use the [`titleCaseStyle`](#titlecasestyle) setting to configure capitalization rules. + +cascade +: See [configure cascade](/configuration/cascade/). + +cleanDestinationDir +: (`bool`) Whether to remove files from the site's destination directory that do not have corresponding files in the `static` directory during the build. Default is `false`. + +contentDir +: (`string`) The designated directory for content files. Default is `content`. {{% module-mounts-note %}} + +copyright +: (`string`) The copyright notice for a site, typically displayed in the footer. + +dataDir +: (`string`) The designated directory for data files. Default is `data`. {{% module-mounts-note %}} + +defaultContentLanguage +: (`string`) The project's default language key, conforming to the syntax described in [RFC 5646]. This value must match one of the defined language keys. Default is `en`. + +defaultContentLanguageInSubdir +: (`bool`) Whether to publish the default language site to a subdirectory matching the `defaultContentLanguage`. Default is `false`. + +defaultOutputFormat +: (`string`) The default output format for the site. If unspecified, the first available format in the defined order (by weight, then alphabetically) will be used. + +deployment +: See [configure deployment](/configuration/deployment/). + +disableAliases +: (`bool`) Whether to disable generation of alias redirects. Even if this option is enabled, the defined aliases will still be present on the page. This allows you to manage redirects separately, for example, by generating 301 redirects in an `.htaccess` file or a Netlify `_redirects` file using a custom output format. Default is `false`. + +disableDefaultLanguageRedirect +: {{< new-in 0.140.0 />}} +: (`bool`) Whether to disable generation of the alias redirect to the default language when `DefaultContentLanguageInSubdir` is `true`. Default is `false`. + +disableHugoGeneratorInject +: (`bool`) Whether to disable injection of a `` tag into the home page. Default is `false`. + +disableKinds +: (`[]string`) A slice of page [kinds](g) to disable during the build process, any of `404`, `home`, `page`, `robotstxt`, `rss`, `section`, `sitemap`, `taxonomy`, or `term`. + +disableLanguages +: (`[]string`) A slice of language keys representing the languages to disable during the build process. Although this is functional, consider using the [`disabled`] key under each language instead. + +disableLiveReload +: (`bool`) Whether to disable automatic live reloading of the browser window. Default is `false`. + +disablePathToLower +: (`bool`) Whether to disable transformation of page URLs to lower case. + +enableEmoji +: (`bool`) Whether to allow emoji in Markdown. Default is `false`. + +enableGitInfo +: (`bool`) For sites under Git version control, whether to enable the [`GitInfo`] object for each page. With the [default front matter configuration], the `Lastmod` method on a `Page` object will return the Git author date. Default is `false`. + +enableMissingTranslationPlaceholders +: (`bool`) Whether to show a placeholder instead of the default value or an empty string if a translation is missing. Default is `false`. + +enableRobotsTXT +: (`bool`) Whether to enable generation of a `robots.txt` file. Default is `false`. + +environment +: (`string`) The build environment. Default is `production` when running `hugo` and `development` when running `hugo server`. + +frontmatter +: See [configure front matter](/configuration/front-matter/). + +hasCJKLanguage +: (`bool`) Whether to automatically detect [CJK](g) languages in content. Affects the values returned by the [`WordCount`] and [`FuzzyWordCount`] methods. Default is `false`. + +HTTPCache +: See [configure HTTP cache](/configuration/http-cache/). + +i18nDir +: (`string`) The designated directory for translation tables. Default is `i18n`. {{% module-mounts-note %}} + +ignoreCache +: (`bool`) Whether to ignore the cache directory. Default is `false`. + +ignoreFiles +: (`[]string`) A slice of [regular expressions](g) used to exclude specific files from a build. These expressions are matched against the absolute file path and apply to files within the `content`, `data`, and `i18n` directories. For more advanced file exclusion options, see the section on [module mounts]. + +ignoreLogs +: (`[]string`) A slice of message identifiers corresponding to warnings and errors you wish to suppress. See [`erroridf`] and [`warnidf`]. + +ignoreVendorPaths +: (`string`) A [glob](g) pattern matching the module paths to exclude from the `_vendor` directory. + +imaging +: See [configure imaging](/configuration/imaging/). + +languageCode +: (`string`) The site's language tag, conforming to the syntax described in [RFC 5646]. This value does not affect translations or localization. Hugo uses this value to populate: + + - The `language` element in the [embedded RSS template] + - The `lang` attribute of the `html` element in the [embedded alias template] + - The `og:locale` `meta` element in the [embedded Open Graph template] + + When present in the root of the configuration, this value is ignored if one or more language keys exists. Please specify this value independently for each language key. + +languages +: See [configure languages](/configuration/languages/). + +layoutDir +: (`string`) The designated directory for templates. Default is `layouts`. {{% module-mounts-note %}} + +mainSections +: (`string` or `[]string`) The main sections of a site. If set, the [`MainSections`] method on the `Site` object returns the given sections, otherwise it returns the section with the most pages. + +markup +: See [configure markup](/configuration/markup/). + +mediaTypes +: See [configure media types](/configuration/media-types/). + +menus +: See [configure menus](/configuration/menus/). + +minify +: See [configure minify](/configuration/minify/). + +module +: See [configure modules](/configuration/module/). + +newContentEditor +: (`string`) The editor to use when creating new content. + +noBuildLock +: (`bool`) Whether to disable creation of the `.hugo_build.lock` file. Default is `false`. + +noChmod +: (`bool`) Whether to disable synchronization of file permission modes. Default is `false`. + +noTimes +: (`bool`) Whether to disable synchronization of file modification times. Default is `false`. + +outputFormats +: See [configure output formats](/configuration/output-formats/). + +outputs +: See [configure outputs](/configuration/outputs/). + +page +: See [configure page](/configuration/page/). + +pagination +: See [configure pagination](/configuration/pagination/). + +panicOnWarning +: (`bool`) Whether to panic on the first WARNING. Default is `false`. + +params +: See [configure params](/configuration/params/). + +permalinks +: See [configure permalinks](/configuration/permalinks/). + +pluralizeListTitles +: (`bool`) Whether to pluralize automatic list titles. Applicable to section pages. Default is `true`. + +printI18nWarnings +: (`bool`) Whether to log WARNINGs for each missing translation. Default is `false`. + +printPathWarnings +: (`bool`) Whether to log WARNINGs when Hugo publishes two or more files to the same path. Default is `false`. + +printUnusedTemplates +: (`bool`) Whether to log WARNINGs for each unused template. Default is `false`. + +privacy +: See [configure privacy](/configuration/privacy/). + +publishDir +: (`string`) The designated directory for publishing the site. Default is `public`. + +refLinksErrorLevel +: (`string`) The logging error level to use when the `ref` and `relref` functions, methods, and shortcodes are unable to resolve a reference to a page. Either `ERROR` or `WARNING`. Any `ERROR` will fail the build. Default is `ERROR`. + +refLinksNotFoundURL +: (`string`) The URL to return when the `ref` and `relref` functions, methods, and shortcodes are unable to resolve a reference to a page. + +related +: See [configure related content](/configuration/related-content/). + +relativeURLs +: (`bool`) See [details](/content-management/urls/#relative-urls) before enabling this feature. Default is `false`. + +removePathAccents +: (`bool`) Whether to remove [non-spacing marks](https://www.compart.com/en/unicode/category/Mn) from [composite characters](https://en.wikipedia.org/wiki/Precomposed_character) in content paths. Default is `false`. + +renderSegments +: {{< new-in 0.124.0 />}} +: (`[]string`) A slice of [segments](g) to render. If omitted, all segments are rendered. This option is typically set via a command-line flag, such as `hugo --renderSegments segment1,segment2`. The provided segment names must correspond to those defined in the [`segments`] configuration. + +resourceDir +: (`string`) The designated directory for caching output from [asset pipelines](g). Default is `resources`. + +security +: See [configure security](/configuration/security/). + +sectionPagesMenu +: (`string`) When set, each top-level section will be added to the menu identified by the provided value. See [details](/content-management/menus/#define-automatically). + +segments +: See [configure segments](/configuration/segments/). + +server +: See [configure server](/configuration/server/). + +services +: See [configure services](/configuration/services/). + +sitemap +: See [configure sitemap](/configuration/sitemap/). + +staticDir +: (`string`) The designated directory for static files. Default is `static`. {{% module-mounts-note %}} + +summaryLength +: (`int`) Applicable to [automatic summaries], the minimum number of words returned by the [`Summary`] method on a `Page` object. The `Summary` method will return content truncated at the paragraph boundary closest to the specified `summaryLength`, but at least this minimum number of words. + +taxonomies +: See [configure taxonomies](/configuration/taxonomies/). + +templateMetrics +: (`bool`) Whether to print template execution metrics to the console. Default is `false`. See [details](/troubleshooting/performance/#template-metrics). + +templateMetricsHints +: (`bool`) Whether to print template execution improvement hints to the console. Applicable when `templateMetrics` is `true`. Default is `false`. See [details](/troubleshooting/performance/#template-metrics). + +theme +: (`string` or `[]string`) The [theme](g) to use. Multiple themes can be listed, with precedence given from left to right. See [details](/hugo-modules/theme-components/). + +themesDir +: (`string`) The designated directory for themes. Default is `themes`. + +timeout +: (`string`) The timeout for generating page content, either as a [duration] or in seconds. This timeout is used to prevent infinite recursion during content generation. You may need to increase this value if your pages take a long time to generate, for example, due to extensive image processing or reliance on remote content. Default is `60s`. + +timeZone +: (`string`) The time zone used to parse dates without time zone offsets, including front matter date fields and values passed to the [`time.AsTime`] and [`time.Format`] template functions. The list of valid values may be system dependent, but should include `UTC`, `Local`, and any location in the [IANA Time Zone Database]. For example, `America/Los_Angeles` and `Europe/Oslo` are valid time zones. + +title +: (`string`) The site title. + +titleCaseStyle +: (`string`) The capitalization rules to follow when Hugo automatically generates a section title, or when using the [`strings.Title`] function. One of `ap`, `chicago`, `go`, `firstupper`, or `none`. Default is `ap`. See [details](#title-case-style). + +uglyurls +: See [configure ugly URLs](/configuration/ugly-urls/). + +## Cache directory + +Hugo's file cache directory is configurable via the [`cacheDir`] configuration option or the `HUGO_CACHEDIR` environment variable. If neither is set, Hugo will use, in order of preference: + +1. If running on Netlify: `/opt/build/cache/hugo_cache/`. This means that if you run your builds on Netlify, all caches configured with `:cacheDir` will be saved and restored on the next build. For other [CI/CD](g) vendors, please read their documentation. For an CircleCI example, see [this configuration]. +1. In a `hugo_cache` directory below the OS user cache directory as defined by Go's [os.UserCacheDir] function. On Unix systems, per the [XDG base directory specification], this is `$XDG_CACHE_HOME` if non-empty, else `$HOME/.cache`. On MacOS, this is `$HOME/Library/Caches`. On Windows, this is`%LocalAppData%`. On Plan 9, this is `$home/lib/cache`. +1. In a `hugo_cache_$USER` directory below the OS temp dir. + +To determine the current `cacheDir`: + +```sh +hugo config | grep cachedir +``` + +## Title case style + +Hugo's [`titleCaseStyle`] setting governs capitalization for automatically generated section titles and the [`strings.Title`] function. By default, it follows the capitalization rules published in the Associated Press Stylebook. Change this setting to use other capitalization rules. + +ap +: Use the capitalization rules published in the [Associated Press Stylebook]. This is the default. + +chicago +: Use the capitalization rules published in the [Chicago Manual of Style]. + +go +: Capitalize the first letter of every word. + +firstupper +: Capitalize the first letter of the first word. + +none +: Disable transformation of automatic section titles, and disable the transformation performed by the `strings.Title` function. This is useful if you would prefer to manually capitalize section titles as needed, and to bypass opinionated theme usage of the `strings.Title` function. + +## Localized settings + +Some configuration settings, such as menus and custom parameters, can be defined separately for each language. See [configure languages](/configuration/languages/#localized-settings). + +[`cacheDir`]: #cachedir +[`disabled`]: /configuration/languages/#disabled +[`erroridf`]: /functions/fmt/erroridf/ +[`FuzzyWordCount`]: /methods/page/fuzzywordcount/ +[`GitInfo`]: /methods/page/gitinfo/ +[`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/ +[`titleCaseStyle`]: #titlecasestyle +[`warnidf`]: /functions/fmt/warnidf/ +[`WordCount`]: /methods/page/wordcount/ +[Associated Press Stylebook]: https://www.apstylebook.com/ +[automatic summaries]: /content-management/summaries/#automatic-summary +[Chicago Manual of Style]: https://www.chicagomanualofstyle.org/home.html +[default front matter configuration]: /configuration/front-matter/ +[duration]: https://pkg.go.dev/time#Duration +[embedded alias template]: {{% eturl alias %}} +[embedded Open Graph template]: {{% eturl opengraph %}} +[embedded RSS template]: {{% eturl rss %}} +[IANA Time Zone Database]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +[module mounts]: /configuration/module/#mounts +[os.UserCacheDir]: https://pkg.go.dev/os#UserCacheDir +[RFC 5646]: https://datatracker.ietf.org/doc/html/rfc5646#section-2.1 +[this configuration]: https://github.com/bep/hugo-sass-test/blob/6c3960a8f4b90e8938228688bc49bdcdd6b2d99e/.circleci/config.yml +[XDG base directory specification]: https://specifications.freedesktop.org/basedir-spec/latest/ diff --cc docs/content/en/configuration/build.md index 116294f05,000000000..1354f0860 mode 100644,000000..100644 --- a/docs/content/en/configuration/build.md +++ b/docs/content/en/configuration/build.md @@@ -1,81 -1,0 +1,83 @@@ +--- +title: Configure build +linkTitle: Build +description: Configure global build options. +categories: [] +keywords: [] +aliases: [/getting-started/configuration-build/] +--- + +The `build` configuration section contains global build-related configuration options. + +{{< code-toggle config=build />}} + +buildStats +: See the [build stats](#build-stats) section below. + +cachebusters +: See the [cache busters](#cache-busters) section below. + +noJSConfigInAssets +: (`bool`) Whether to disable writing a `jsconfig.json` in your `assets` directory with mapping of imports from running [js.Build](/hugo-pipes/js). This file is intended to help with intellisense/navigation inside code editors such as [VS Code](https://code.visualstudio.com/). Note that if you do not use `js.Build`, no file will be written. + +useResourceCacheWhen +: (`string`) When to use the resource file cache, one of `never`, `fallback`, or `always`. Applicable when transpiling Sass to CSS. Default is `fallback`. + +## Cache busters + +The `build.cachebusters` configuration option was added to support development using Tailwind 3.x's JIT compiler where a `build` configuration may look like this: + ++ +{{< code-toggle file=hugo >}} +[build] + [build.buildStats] + enable = true + [[build.cachebusters]] + source = "assets/watching/hugo_stats\\.json" + target = "styles\\.css" + [[build.cachebusters]] + source = "(postcss|tailwind)\\.config\\.js" + target = "css" + [[build.cachebusters]] + source = "assets/.*\\.(js|ts|jsx|tsx)" + target = "js" + [[build.cachebusters]] + source = "assets/.*\\.(.*)$" + target = "$1" +{{< /code-toggle >}} ++ + +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. + +source +: (`string`) A [regular expression](g) matching file(s) relative to one of the virtual component directories in Hugo, typically `assets/...`. + +target +: (`string`) A [regular expression](g) matching the keys in the resource cache that should be expired when `source` changes. You can use the matching regexp groups from `source` in the expression, e.g. `$1`. + +## Build stats + +{{< code-toggle config=build.buildStats />}} + +enable +: (`bool`) Whether to create a `hugo_stats.json` file in the root of your project. This file contains arrays of the `class` attributes, `id` attributes, and tags of every HTML element within your published site. Use this file as data source when [removing unused CSS] from your site. This process is also known as pruning, purging, or tree shaking. Default is `false`. + +[removing unused CSS]: /functions/resources/postprocess/ + +disableIDs +: (`bool`) Whether to exclude `id` attributes. Default is `false`. + +disableTags +: (`bool`) Whether to exclude element tags. Default is `false`. + +disableClasses +: (`bool`) Whether to exclude `class` attributes. Default is `false`. + +> [!note] +> Given that CSS purging is typically limited to production builds, place the `buildStats` object below [`config/production`]. +> +> Built for speed, there may be "false positive" detections (e.g., HTML elements that are not HTML elements) while parsing the published site. These "false positives" are infrequent and inconsequential. + +Due to the nature of partial server builds, new HTML entities are added while the server is running, but old values will not be removed until you restart the server or run a regular `hugo` build. + +[`config/production`]: /configuration/introduction/#configuration-directory diff --cc docs/content/en/configuration/cascade.md index d91996301,000000000..85b221df2 mode 100644,000000..100644 --- a/docs/content/en/configuration/cascade.md +++ b/docs/content/en/configuration/cascade.md @@@ -1,77 -1,0 +1,77 @@@ +--- +title: Configure cascade +linkTitle: Cascade +description: Configure cascade. +categories: [] +keywords: [] +--- + +You can configure your site to cascade front matter values to the home page and any of its descendants. However, this cascading will be prevented if the descendant already defines the field, or if a closer ancestor [node](g) has already cascaded a value for the same field through its front matter's `cascade` key. + +> [!note] +> You can also configure cascading behavior within a page's front matter. See [details]. + +For example, to cascade a "color" parameter to the home page and all its descendants: + +{{< code-toggle file=hugo >}} +title = 'Home' +[cascade.params] +color = 'red' +{{< /code-toggle >}} + +## Target + + + +The `target`[^1] keyword allows you to target specific pages or [environments](g). For example, to cascade a "color" parameter to pages within the "articles" section, including the "articles" section page itself: + +[^1]: The `_target` alias for `target` is deprecated and will be removed in a future release. + +{{< code-toggle file=hugo >}} +[cascade.params] +color = 'red' +[cascade.target] +path = '{/articles,/articles/**}' +{{< /code-toggle >}} + +Use any combination of these keywords to target pages and/or environments: + +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}`. + +path +: (`string`) A [glob](g) pattern matching the page's [logical path](g). For example: `{/books,/books/**}`. + +## Array + +Define an array of cascade parameters to apply different values to different targets. For example: + +{{< code-toggle file=hugo >}} +[[cascade]] +[cascade.params] +color = 'red' +[cascade.target] +path = '{/books/**}' +kind = 'page' +lang = '{en,de}' +[[cascade]] +[cascade.params] +color = 'blue' +[cascade.target] +path = '{/films/**}' +kind = 'page' +environment = 'production' +{{< /code-toggle >}} + +[details]: /content-management/front-matter/#cascade-1 +[page language]: /methods/page/language/ diff --cc docs/content/en/configuration/front-matter.md index 9f51b8a5a,000000000..a97648b61 mode 100644,000000..100644 --- a/docs/content/en/configuration/front-matter.md +++ b/docs/content/en/configuration/front-matter.md @@@ -1,91 -1,0 +1,102 @@@ +--- +title: Configure front matter +linkTitle: Front matter +description: Configure front matter. +categories: [] +keywords: [] +--- + +## Dates + +There are four methods on a `Page` object that return a date. + +Method|Description +:--|:-- +[`Date`]|Returns the date of the given page. +[`ExpiryDate`]|Returns the expiry date of the given page. +[`Lastmod`]|Returns the last modification date of the given page. +[`PublishDate`]|Returns the publish date of the given page. + +[`Date`]: /methods/page/date +[`ExpiryDate`]: /methods/page/expirydate +[`Lastmod`]: /methods/page/lastmod +[`PublishDate`]: /methods/page/publishdate + +Hugo determines the values to return based on this configuration: + +{{< code-toggle config=frontmatter />}} + +The `ExpiryDate` method, for example, returns the `expirydate` value if it exists, otherwise it returns `unpublishdate`. + +You can also use custom date parameters: + +{{< code-toggle file=hugo >}} +[frontmatter] +date = ["myDate", "date"] +{{< /code-toggle >}} + +In the example above, the `Date` method returns the `myDate` value if it exists, otherwise it returns `date`. + +To fall back to the default sequence of dates, use the `:default` token: + +{{< code-toggle file=hugo >}} +[frontmatter] +date = ["myDate", ":default"] +{{< /code-toggle >}} + +In the example above, the `Date` method returns the `myDate` value if it exists, otherwise it returns the first valid date from `date`, `publishdate`, `pubdate`, `published`, `lastmod`, and `modified`. + +## Aliases + +Some of the front matter fields have aliases. + +Front matter field|Aliases +:--|:-- +`expiryDate`|`unpublishdate` +`lastmod`|`modified` +`publishDate`|`pubdate`, `published` + +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`). ++ ++ 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`. + - Consider this example: ++`: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] +date = [':filename', ':default'] +lastmod = ['lastmod', ':fileModTime'] +{{< /code-toggle >}} + +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 diff --cc docs/content/en/configuration/markup.md index 4a2efb5e8,000000000..bf5aac374 mode 100644,000000..100644 --- a/docs/content/en/configuration/markup.md +++ b/docs/content/en/configuration/markup.md @@@ -1,341 -1,0 +1,357 @@@ +--- +title: Configure markup +linkTitle: Markup +description: Configure markup. +categories: [] +keywords: [] +aliases: [/getting-started/configuration-markup/] +--- + +## Default handler + +In its default configuration, Hugo uses [Goldmark] to render Markdown to HTML. + +{{< code-toggle file=hugo >}} +[markup] +defaultMarkdownHandler = 'goldmark' +{{< /code-toggle >}} + +Files with ending with `.md`, `.mdown`, or `.markdown` are processed as Markdown, unless you've explicitly set a different format using the `markup` field in your front matter. + +To use a different renderer for Markdown files, specify one of `asciidocext`, `org`, `pandoc`, or `rst` in your site configuration. + +`defaultMarkdownHandler`|Renderer +:--|:-- +`asciidocext`|[AsciiDoc] +`goldmark`|[Goldmark] +`org`|[Emacs Org Mode] +`pandoc`|[Pandoc] +`rst`|[reStructuredText] + +To use AsciiDoc, Pandoc, or reStructuredText you must install the relevant renderer and update your [security policy]. + +> [!note] +> Unless you need a unique capability provided by one of the alternative Markdown handlers, we strongly recommend that you use the default setting. Goldmark is fast, well maintained, conforms to the [CommonMark] specification, and is compatible with [GitHub Flavored Markdown] (GFM). + +## Goldmark + +This is the default configuration for the Goldmark Markdown renderer: + +{{< code-toggle config=markup.goldmark />}} + +### Extensions + +The extensions below, excluding Extras and Passthrough, are enabled by default. + +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]|  +`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]|  +`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: +`typographer`|[Goldmark Extensions: Typographer]|:heavy_check_mark: + +#### Extras + +{{< new-in 0.126.0 />}} + +Enable [deleted text], [inserted text], [mark text], [subscript], and [superscript] elements in Markdown. + +Element|Markdown|Rendered +:--|:--|:-- +Deleted text|`~~foo~~`|`foo` +Inserted text|`++bar++`|`bar` +Mark text|`==baz==`|`baz` +Subscript|`H~2~O`|`H2O` +Superscript|`1^st^`|`1st` + - 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 - - For example: ++[^1]: See [details](https://github.com/gohugoio/hugo-goldmark-extensions/commit/4d4fcd022fe45a9b51483df001c9e5f4e632d5a9). + +{{< code-toggle file=hugo >}} +[markup.goldmark.extensions] +strikethrough = false + - [markup.goldmark.extensions.extras.delete] ++[markup.goldmark.extensions.extras.subscript] +enable = true ++{{< /code-toggle >}} + - [markup.goldmark.extensions.extras.subscript] ++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] ++strikethrough = false ++ ++[markup.goldmark.extensions.extras.delete] +enable = true +{{< /code-toggle >}} + ++With this configuration, to format text as deleted, wrap it with double-tildes. ++ +#### Passthrough + +{{< new-in 0.122.0 />}} + +Enable the Passthrough extension to include mathematical equations and expressions in Markdown using LaTeX markup. See [mathematics in Markdown] for details. + +#### Typographer + +The Typographer extension replaces certain character combinations with HTML entities as specified below: + +Markdown|Replaced by|Description +:--|:--|:-- +`...`|`…`|horizontal ellipsis +`'`|`’`|apostrophe +`--`|`–`|en dash +`---`|`—`|em dash +`«`|`«`|left angle quote +`“`|`“`|left double quote +`‘`|`‘`|left single quote +`»`|`»`|right angle quote +`”`|`”`|right double quote +`’`|`’`|right single quote + - ### Settings explained ++### Goldmark settings explained + +Most of the Goldmark settings above are self-explanatory, but some require explanation. + +duplicateResourceFiles +: {{< new-in 0.123.0 />}} +: (`bool`) Whether to duplicate shared page resources for each language on multilingual single-host sites. See [multilingual page resources] for details. Default is `false`. + + > [!note] + > With multilingual single-host sites, setting this parameter to `false` will enable Hugo's [embedded link render hook] and [embedded image render hook]. This is the default configuration for multilingual single-host sites. + +parser.wrapStandAloneImageWithinParagraph +: (`bool`) Whether to wrap image elements without adjacent content within a `p` element when rendered. This is the default Markdown behavior. Set to `false` when using an [image render hook] to render standalone images as `figure` elements. Default is `true`. + +parser.autoDefinitionTermID +: {{< new-in 0.144.0 />}} +: (`bool`) Whether to automatically add `id` attributes to description list terms (i.e., `dt` elements). When `true`, the `id` attribute of each `dt` element is accessible through the [`Fragments.Identifiers`] method on a `Page` object. + +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`. + +parser.attribute.title +: (`bool`) Whether to enable [Markdown attributes] for headings. Default is `true`. + ++ +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. ++ ++ +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`. + +renderer.unsafe +: (`bool`) Whether to render raw HTML mixed within Markdown. This is unsafe unless the content is under your control. Default is `false`. + +## AsciiDoc + +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]. + +backend +: (`string`) The backend output file format. Default is `html5`. + +extensions +: (`string array`) An array of enabled extensions, one or more of `asciidoctor-html5s`, `asciidoctor-bibtex`, `asciidoctor-diagram`, `asciidoctor-interdoc-reftext`, `asciidoctor-katex`, `asciidoctor-latex`, `asciidoctor-mathematical`, or `asciidoctor-question`. + + > [!note] + > To mitigate security risks, entries in the extension array may not contain forward slashes (`/`), backslashes (`\`), or periods. Due to this restriction, extensions must be in Ruby's `$LOAD_PATH`. + +failureLevel +: (`string`) The minimum logging level that triggers a non-zero exit code (failure). Default is `fatal`. + +noHeaderOrFooter +: (`bool`) Whether to output an embeddable document, which excludes the header, the footer, and everything outside the body of the document. Default is `true`. + +preserveTOC +: (`bool`) Whether to preserve the table of contents (TOC) rendered by Asciidoctor. By default, to make the TOC compatible with existing themes, Hugo removes the TOC rendered by Asciidoctor. To render the TOC, use the [`TableOfContents`] method on a `Page` object in your templates. Default is `false`. + +safeMode +: (`string`) The safe mode level, one of `unsafe`, `safe`, `server`, or `secure`. Default is `unsafe`. + +sectionNumbers +: (`bool`) Whether to number each section title. Default is `false`. + +trace +: (`bool`) Whether to include backtrace information on errors. Default is `false`. + +verbose +: (`bool`) Whether to verbosely print processing information and configuration file checks to stderr. Default is `false`. + +workingFolderCurrent +: (`bool`) Whether to set the working directory to be the same as that of the AsciiDoc file being processed, allowing [includes] to work with relative paths. Set to `true` to render diagrams with the [asciidoctor-diagram] extension. Default is `false`. + +### Configuration example + +{{< code-toggle file=hugo >}} +[markup.asciidocExt] + extensions = ["asciidoctor-html5s", "asciidoctor-diagram"] + workingFolderCurrent = true + [markup.asciidocExt.attributes] + my-base-url = "https://example.com/" + my-attribute-name = "my value" +{{< /code-toggle >}} + +### Syntax highlighting + +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"} ++ ++ ... ++ {{ with resources.Get "css/syntax.css" }} ++ ++ {{ end }} ++ ... ++ ++ ``` + - #### 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"} - - ... - {{ with resources.Get "css/syntax.css" }} - - {{ end }} - ... - - ``` - - 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 + +Run `hugo --logLevel debug` to examine Hugo's call to the Asciidoctor executable: + +```txt +INFO 2019/12/22 09:08:48 Rendering book-as-pdf.adoc with C:\Ruby26-x64\bin\asciidoctor.bat using asciidoc args [--no-header-footer -r asciidoctor-html5s -b html5s -r asciidoctor-diagram --base-dir D:\prototypes\hugo_asciidoc_ddd\docs -a outdir=D:\prototypes\hugo_asciidoc_ddd\build -] ... +``` + +## Highlight + +This is the default configuration. + +{{< code-toggle config=markup.highlight />}} + +{{% include "/_common/syntax-highlighting-options.md" %}} + +## Table of contents + +This is the default configuration for the table of contents, applicable to Goldmark and Asciidoctor: + +{{< code-toggle config=markup.tableOfContents />}} + +startLevel +: (`int`) Heading levels less than this value will be excluded from the table of contents. For example, to exclude `h1` elements from the table of contents, set this value to `2`. Default is `2`. + +endLevel +: (`int`) Heading levels greater than this value will be excluded from the table of contents. For example, to exclude `h4`, `h5`, and `h6` elements from the table of contents, set this value to `3`. Default is `3`. + +ordered +: (`bool`) Whether to generates an ordered list instead of an unordered list. Default is `false`. + +[`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/ +[includes]: https://docs.asciidoctor.org/asciidoc/latest/syntax-quick-reference/#includes +[inserted text]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ins +[mark text]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark +[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 diff --cc docs/content/en/configuration/menus.md index 759f53ff3,000000000..6b27e966b mode 100644,000000..100644 --- a/docs/content/en/configuration/menus.md +++ b/docs/content/en/configuration/menus.md @@@ -1,135 -1,0 +1,137 @@@ +--- +title: Configure menus +linkTitle: Menus +description: Centrally define menu entries for one or more menus. +categories: [] +keywords: [] +--- + +> [!note] +> To understand Hugo's menu system, please refer to the [menus] page. + +There are three ways to define menu entries: + +1. [Automatically] +1. [In front matter] +1. In site configuration + +This page covers the site configuration method. + +## Example + +To define entries for a "main" menu: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Home' +pageRef = '/' +weight = 10 + +[[menus.main]] +name = 'Products' +pageRef = '/products' +weight = 20 + +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 30 +{{< /code-toggle >}} + +This creates a menu structure that you can access with [`Menus`] method on a `Site` object: + +```go-html-template +{{ range .Site.Menus.main }} + ... +{{ end }} +``` + +See [menu templates] for a detailed example. + +To define entries for a "footer" menu: + +{{< code-toggle file=hugo >}} +[[menus.footer]] +name = 'Terms' +pageRef = '/terms' +weight = 10 + +[[menus.footer]] +name = 'Privacy' +pageRef = '/privacy' +weight = 20 +{{< /code-toggle >}} + +Access this menu structure in the same way: + +```go-html-template +{{ range .Site.Menus.footer }} + ... +{{ end }} +``` + +## Properties + +Menu entries usually include at least three properties: `name`, `weight`, and either `pageRef` or `url`. Use `pageRef` for internal page destinations and `url` for external destinations. + +These are the available menu entry properties: + +{{% include "/_common/menu-entry-properties.md" %}} + +pageRef +: (`string`) The [logical path](g) of the target page. For example: + + page kind|pageRef + :--|:-- + home|`/` + page|`/books/book-1` + section|`/books` + taxonomy|`/tags` + term|`/tags/foo` + +url +: (`string`) The destination URL. Use this for external destinations only. + +## Nested menu + +This nested menu demonstrates some of the available properties: + ++ +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Products' +pageRef = '/products' +weight = 10 + +[[menus.main]] +name = 'Hardware' +pageRef = '/products/hardware' +parent = 'Products' +weight = 1 + +[[menus.main]] +name = 'Software' +pageRef = '/products/software' +parent = 'Products' +weight = 2 + +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 20 + +[[menus.main]] +name = 'Hugo' +pre = '' +url = 'https://gohugo.io/' +weight = 30 +[menus.main.params] +rel = 'external' +{{< /code-toggle >}} ++ + +[`Menus`]: /methods/site/menus/ +[Automatically]: /content-management/menus/#define-automatically +[In front matter]: /content-management/menus/#define-in-front-matter +[menu templates]: /templates/menu/ +[menus]: /content-management/menus/ diff --cc docs/content/en/configuration/module.md index d736b7c6f,000000000..4a7267bd6 mode 100644,000000..100644 --- a/docs/content/en/configuration/module.md +++ b/docs/content/en/configuration/module.md @@@ -1,179 -1,0 +1,179 @@@ +--- +title: Configure modules +linkTitle: Modules +description: Configure modules. +categories: [] +keywords: [] +aliases: [/hugo-modules/configuration/] +--- + +## Top-level options + +This is the default configuration: + ++ +{{< code-toggle file=hugo >}} +[module] +noProxy = 'none' +noVendor = '' +private = '*.*' +proxy = 'direct' +vendorClosest = false +workspace = 'off' +{{< /code-toggle >}} ++ + +auth +: {{< new-in 0.144.0 />}} +: (`string`) Configures `GOAUTH` when running the Go command for module operations. This is a semicolon-separated list of authentication commands for go-import and HTTPS module mirror interactions. This is useful for private repositories. See `go help goauth` for more information. + +noProxy +: (`string`) A comma-separated list of [glob](g) patterns matching paths that should not use the [configured proxy server](#proxy). + +noVendor +: (`string`) A [glob](g) pattern matching module paths to skip when vendoring. + +private +: (`string`) A comma-separated list of [glob](g) patterns matching paths that should be treated as private. + +proxy +: (`string`) The proxy server to use to download remote modules. Default is `direct`, which means `git clone` and similar. + +replacements +: (`string`) Primarily useful for local module development, a comma-separated list of mappings from module paths to directories. Paths may be absolute or relative to the [`themesDir`]. + + {{< code-toggle file=hugo >}} + [module] + replacements = 'github.com/bep/my-theme -> ../..,github.com/bep/shortcodes -> /some/path' + {{< /code-toggle >}} + +vendorClosest +: (`bool`) Whether to pick the vendored module closest to the module using it. The default behavior is to pick the first. Note that there can still be only one dependency of a given module path, so once it is in use it cannot be redefined. Default is `false`. + +workspace +: (`string`) The Go workspace file to use, either as an absolute path or a path relative to the current working directory. Enabling this activates Go workspace mode and requires Go 1.18 or later. The default is `off`. + +You may also use environment variables to set any of the above. For example: + +```sh +export HUGO_MODULE_PROXY="https://proxy.example.org" +export HUGO_MODULE_REPLACEMENTS="github.com/bep/my-theme -> ../.." +export HUGO_MODULE_WORKSPACE="/my/hugo.work" +``` + +{{% include "/_common/gomodules-info.md" %}} + +## Hugo version + +You can specify a required Hugo version for your module in the `module` section. Users will then receive a warning if their Hugo version is incompatible. + +This is the default configuration: + +{{< code-toggle config=module.hugoVersion />}} + +You can omit any of the settings above. + +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 + +{{< code-toggle file=hugo >}} +[[module.imports]] +disable = false +ignoreConfig = false +ignoreImports = false +path = "github.com/gohugoio/hugoTestModules1_linux/modh1_2_1v" +[[module.imports]] +path = "my-shortcodes" +{{< /code-toggle >}} + +disable +: (`bool`) Whether to disable the module but keep version information in the `go.*` files. Default is `false`. + +ignoreConfig +: (`bool`) Whether to ignore module configuration files, for example, `hugo.toml`. This will also prevent loading of any transitive module dependencies. Default is `false`. + +ignoreImports +: (`bool`) Whether to ignore module imports. Default is `false`. + +noMounts +: (`bool`) Whether to disable directory mounting for this import. Default is `false`. + +noVendor +: (`bool`) Whether to disable vendoring for this import. This setting is restricted to the main project. Default is `false`. + +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 + +Before Hugo v0.56.0, custom component paths could only be configured by setting [`archetypeDir`], [`assetDir`], [`contentDir`], [`dataDir`], [`i18nDir`], [`layoutDi`], or [`staticDir`] in the site configuration. Module mounts offer greater flexibility than these legacy settings, but +you cannot use both. + +[`archetypeDir`]: /configuration/all/ +[`assetDir`]: /configuration/all/ +[`contentDir`]: /configuration/all/ +[`dataDir`]: /configuration/all/ +[`i18nDir`]: /configuration/all/ +[`layoutDi`]: /configuration/all/ +[`staticDir`]: /configuration/all/ + +> [!note] +> If you use module mounts do not use the legacy settings. + +### Default mounts + +> [!note] +> Adding a new mount to a target root will cause the existing default mount for that root to be ignored. If you still need the default mount, you must explicitly add it along with the new mount. + +The are the default mounts: + +{{< code-toggle config=module.mounts />}} + +source +: (`string`) The source directory of the mount. For the main project, this can be either project-relative or absolute. For other modules it must be project-relative. + +target +: (`string`) Where the mount will reside within Hugo's virtual file system. It must begin with one of Hugo's component directories: `archetypes`, `assets`, `content`, `data`, `i18n`, `layouts`, or `static`. For example, `content/blog`. + +disableWatch +: {{< new-in 0.128.0 />}} +: (`bool`) Whether to disable watching in watch mode for this mount. Default is `false`. + +lang +: (`string`) The language code, e.g. "en". Relevant for `content` mounts, and `static` mounts when in multihost mode. + +includeFiles +: (`string` or `[]string`) One or more [glob](g) patterns matching files or directories to include. If `excludeFiles` is not set, the files matching `includeFiles` will be the files mounted. + + The glob patterns are matched against file names relative to the source root. Use Unix-style forward slashes (`/`), even on Windows. A single forward slash (`/`) matches the mount root, and double asterisks (`**`) act as a recursive wildcard, matching all directories and files beneath a given point (e.g., `/posts/**.jpg`). The search is case-insensitive. + +excludeFiles +: (`string` or `[]string`) One or more [glob](g) patterns matching files to exclude. + +### Example + +{{< code-toggle file=hugo >}} +[module] +[[module.mounts]] + source="content" + target="content" + excludeFiles="docs/*" +[[module.mounts]] + source="node_modules" + target="assets" +[[module.mounts]] + source="assets" + target="assets" +{{< /code-toggle >}} ++ ++[`themesDir`]: /configuration/all/#themesdir diff --cc docs/content/en/configuration/output-formats.md index f3dbceec5,000000000..7e80d30fb mode 100644,000000..100644 --- a/docs/content/en/configuration/output-formats.md +++ b/docs/content/en/configuration/output-formats.md @@@ -1,209 -1,0 +1,206 @@@ +--- +title: Configure output formats +linkTitle: Output formats +description: Configure output formats. +categories: [] +keywords: [] +--- + +{{% glossary-term "output format" %}} + +You can output a page in as many formats as you want. Define an infinite number of output formats, provided they each resolve to a unique file system path. + +This is the default output format configuration in tabular form: + +{{< datatable + "config" + "outputFormats" + "_key" + "mediaType" + "weight" + "baseName" + "isHTML" + "isPlainText" + "noUgly" + "notAlternative" + "path" + "permalinkable" + "protocol" + "rel" + "root" + "ugly" +>}} + +## Default configuration + +The following is the default configuration that matches the table above: + +{{< code-toggle config=outputFormats />}} + +baseName +: (`string`) The base name of the published file. Default is `index`. + +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 [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 [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`. + +root +: (`bool`) Whether to publish files to the root of the publish directory. Default is `false`. + +ugly +: (`bool`) Whether to enable uglyURLs for this output format when `uglyURLs` is `false` in your site configuration. Default is `false`. + +weight +: (`int`) When set to a non-zero value, Hugo uses the `weight` as the first criteria when sorting output formats, falling back to the name of the output format. Lighter items float to the top, while heavier items sink to the bottom. Hugo renders output formats sequentially based on the sort order. Default is `0`, except for the `html` output format, which has a default weight of `10`. + +## Modify an output format + +You can modify any of the default output formats. For example, to prioritize `json` rendering over `html` rendering, when both are generated, adjust the [`weight`](#weight): + +{{< code-toggle file=hugo >}} +[outputFormats.json] +weight = 1 +[outputFormats.html] +weight = 2 +{{< /code-toggle >}} + +The example above shows that when you modify a default content format, you only need to define the properties that differ from their default values. + +## Create an output format + +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. - - ### Step 2 - - Create a new output format: - - {{< code-toggle file=hugo >}} - [outputFormats.atom] - mediaType = 'application/atom+xml' - noUgly = true - {{< /code-toggle >}} ++ See [configure media types][] for more information. + - Note that we use the default settings for all other output format properties. ++Step 2 ++: Create a new output format: + - ### Step 3 ++ {{< code-toggle file=hugo >}} ++ [outputFormats.atom] ++ mediaType = 'application/atom+xml' ++ noUgly = true ++ {{< /code-toggle >}} + - 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 ++: Specify the page [kinds](g) for which to render this output format: + - See [configure outputs] for more information. ++ {{< code-toggle file=hugo >}} ++ [outputs] ++ home = ['html', 'rss', 'atom'] ++ section = ['html', 'rss', 'atom'] ++ taxonomy = ['html', 'rss', 'atom'] ++ term = ['html', 'rss', 'atom'] ++ {{< /code-toggle >}} + - ### Step 4 ++ See [configure outputs][] for more information. + - 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: ++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 - ``` ++ ```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 }} + +{{ end }} +``` + +## 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: + +```go-html-template +{{ .RelPermalink }} → /that-page/ +{{ with .OutputFormats.Get "json" }} + {{ .RelPermalink }} → /that-page/index.json +{{ 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: + +```go-html-template +{{ .RelPermalink }} → /that-page/index.json +{{ with .OutputFormats.Get "html" }} + {{ .RelPermalink }} → /that-page/ +{{ end }} +``` + +## 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: + +```text +[page kind].[output format].[suffix] +``` + +For example, for section pages: + +Output format|Template path +:--|:-- +`html`|`layouts/section.html.html` +`json`|`layouts/section.json.json` +`rss`|`layouts/section.rss.xml` + +[`AlternativeOutputFormats`]: /methods/page/alternativeoutputformats/ ++[`baseURL`]: /configuration/all/#baseurl +[`OutputFormats`]: /methods/page/outputformats/ +[`Permalink`]: /methods/page/permalink/ - [`RelPermalink`]: /methods/page/relpermalink/ - [`baseURL`]: /configuration/all/#baseurl +[`permalinkable`]: #permalinkable ++[`publishDir`]: /configuration/all/#publishdir ++[`RelPermalink`]: /methods/page/relpermalink/ +[`uglyURLs`]: /configuration/ugly-urls/ +[configure media types]: /configuration/media-types/ +[configure outputs]: /configuration/outputs/ +[configured media types]: /configuration/media-types/ +[default media types]: /configuration/media-types/ - [embedded RSS template]: {{% eturl rss %}} ++[embedded RSS template]: <{{% eturl rss %}}> +[html/template]: https://pkg.go.dev/html/template +[template lookup order]: /templates/lookup-order/ +[text/template]: https://pkg.go.dev/text/template diff --cc docs/content/en/configuration/related-content.md index 7f2aa9831,000000000..421a1ea77 mode 100644,000000..100644 --- a/docs/content/en/configuration/related-content.md +++ b/docs/content/en/configuration/related-content.md @@@ -1,111 -1,0 +1,111 @@@ +--- +title: Configure related content +linkTitle: Related content +description: Configure related content. +categories: [] +keywords: [] +--- + +> [!note] +> To understand Hugo's related content identification, please refer to the [related content] page. + +Hugo provides a sensible default configuration for identifying related content, but you can customize it in your site configuration, either globally or per language. + +## Default configuration + +This is the default configuration: + +{{< code-toggle config=related />}} + +> [!note] +> Adding a `related` section to your site configuration requires you to provide a full configuration. You cannot override individual default values without specifying all related settings. + +## Top-level options + +threshold +: (`int`) A value between 0-100, inclusive. A lower value will return more, but maybe not so relevant, matches. + +includeNewer +: (`bool`) Whether to include pages newer than the current page in the related content listing. This will mean that the output for older posts may change as new related content gets added. Default is `false`. + +toLower +: (`bool`) Whether to transform keywords in both the indexes and the queries to lower case. This may give more accurate results at a slight performance penalty. Default is `false`. + +## Per-index options + +name +: (`string`) The index name. This value maps directly to a page parameter. Hugo supports string values (`author` in the example) and lists (`tags`, `keywords` etc.) and time and date objects. + +type +: (`string`) One of `basic` or `fragments`. Default is `basic`. + +applyFilter +: (`string`) Apply a `type` specific filter to the result of a search. This is currently only used for the `fragments` type. + +weight +: (`int`) An integer weight that indicates how important this parameter is relative to the other parameters. It can be `0`, which has the effect of turning this index off, or even negative. Test with different values to see what fits your content best. Default is `0`. + +cardinalityThreshold +: (`int`) If between 1 and 100, this is a percentage. All keywords that are used in more than this percentage of documents are removed. For example, setting this to `60` will remove all keywords that are used in more than 60% of the documents in the index. If `0`, no keyword is removed from the index. Default is `0`. + +pattern +: (`string`) This is currently only relevant for dates. When listing related content, we may want to list content that is also close in time. Setting "2006" (default value for date indexes) as the pattern for a date index will add weight to pages published in the same year. For busier blogs, "200601" (year and month) may be a better default. + +toLower +: (`bool`) Whether to transform keywords in both the indexes and the queries to lower case. This may give more accurate results at a slight performance penalty. Default is `false`. + +## Example + +Imagine we're building a book review site. Our main content will be book reviews, and we'll use genres and authors as taxonomies. When someone views a book review, we want to show a short list of related reviews based on shared authors and genres. + +Create the content: + +```text +content/ +└── book-reviews/ + ├── book-review-1.md + ├── book-review-2.md + ├── book-review-3.md + ├── book-review-4.md + └── book-review-5.md +``` + +Configure the taxonomies: + +{{< code-toggle file=hugo >}} +[taxonomies] +author = 'authors' +genre = 'genres' +{{< /code-toggle >}} + +Configure the related content identification: + +{{< code-toggle file=hugo >}} +[related] +includeNewer = true +threshold = 80 +toLower = true +[[related.indices]] +name = 'authors' +weight = 2 +[[related.indices]] +name = 'genres' +weight = 1 +{{< /code-toggle >}} + +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 }} +

Related content:

+ +{{ end }} +``` + +[related content]: /content-management/related-content/ diff --cc docs/content/en/configuration/security.md index f950dd233,000000000..f9eb91bd9 mode 100644,000000..100644 --- a/docs/content/en/configuration/security.md +++ b/docs/content/en/configuration/security.md @@@ -1,50 -1,0 +1,50 @@@ +--- +title: Configure security +linkTitle: Security +description: Configure security. +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: + +{{< code-toggle config=security />}} + +enableInlineShortcodes +: (`bool`) Whether to enable [inline shortcodes]. Default is `false`. + +exec.allow +: (`[]string`) A slice of [regular expressions](g) matching the names of external executables that Hugo is allowed to run. + +exec.osEnv +: (`[]string`) A slice of [regular expressions](g) matching the names of operating system environment variables that Hugo is allowed to access. + +funcs.getenv +: (`[]string`) A slice of [regular expressions](g) matching the names of operating system environment variables that Hugo is allowed to access with the [`os.Getenv`] function. + +http.methods +: (`[]string`) A slice of [regular expressions](g) matching the HTTP methods that the [`resources.GetRemote`] function is allowed to use. + +http.mediaTypes +: (`[]string`) Applicable to the `resources.GetRemote` function, a slice of [regular expressions](g) matching the `Content-Type` in HTTP responses that Hugo trusts, bypassing file content analysis for media type detection. + +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: + +```txt +export HUGO_SECURITY_HTTP_URLS=none +``` + +Learn more about [using environment variables] to configure your site. + +[`os.Getenv`]: /functions/os/getenv +[`resources.GetRemote`]: /functions/resources/getremote +[inline shortcodes]: /content-management/shortcodes/#inline +[using environment variables]: /configuration/introduction/#environment-variables diff --cc docs/content/en/configuration/segments.md index 0c4098770,000000000..b87c870c4 mode 100644,000000..100644 --- a/docs/content/en/configuration/segments.md +++ b/docs/content/en/configuration/segments.md @@@ -1,77 -1,0 +1,77 @@@ +--- +title: Configure segments +linkTitle: Segments +description: Configure your site for segmented rendering. +categories: [] +keywords: [] +--- + +{{< new-in 0.124.0 />}} + +> [!note] +> The `segments` configuration applies only to segmented rendering. While it controls when content is rendered, it doesn't restrict access to Hugo's complete object graph (sites and pages), which remains fully available. + +Segmented rendering offers several advantages: + +- Faster builds: Process large sites more efficiently. +- Rapid development: Render only a subset of your site for quicker iteration. +- Scheduled rebuilds: Rebuild specific sections at different frequencies (e.g., home page and news hourly, full site weekly). +- Targeted output: Generate specific output formats (like JSON for search indexes). + +## Segment definition + +Each segment is defined by include and exclude filters: + +- Filters: Each segment has zero or more exclude filters and zero or more include filters. +- Matchers: Each filter contains one or more field [glob](g) matchers. +- Logic: Matchers within a filter use AND logic. Filters within a section (include or exclude) use OR logic. + +## Filter fields + +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}`. + +output +: (`string`) A [glob](g) pattern matching the [output format](g) of the page. For example: `{html,json}`. + +path +: (`string`) A [glob](g) pattern matching the page's [logical path](g). For example: `{/books,/books/**}`. + +## Example + +Place broad filters, such as those for language or output format, in the excludes section. For example: + +{{< code-toggle file=hugo >}} +[segments.segment1] + [[segments.segment1.excludes]] + lang = "n*" + [[segments.segment1.excludes]] + lang = "en" + output = "rss" + [[segments.segment1.includes]] + kind = "{home,term,taxonomy}" + [[segments.segment1.includes]] + path = "{/docs,/docs/**}" +{{< /code-toggle >}} + +## Rendering segments + +Render specific segments using the [`renderSegments`] configuration or the `--renderSegments` flag: + +```bash +hugo --renderSegments segment1 +``` + +You can configure multiple segments and use a comma-separated list with `--renderSegments` to render them all. + +```bash +hugo --renderSegments segment1,segment2 +``` + +[`renderSegments`]: /configuration/all/#rendersegments +[page language]: /methods/page/language/ diff --cc docs/content/en/configuration/server.md index 92f0f0cfa,000000000..f77e7f47f mode 100644,000000..100644 --- a/docs/content/en/configuration/server.md +++ b/docs/content/en/configuration/server.md @@@ -1,128 -1,0 +1,128 @@@ +--- +title: Configure server +linkTitle: Server +description: Configure the development server. +categories: [] +keywords: [] +--- + +These settings are exclusive to Hugo's development server, so a dedicated [configuration directory] for development, where the server is configured accordingly, is the recommended approach. + +[configuration directory]: /configuration/introduction/#configuration-directory + +```text +project/ +└── config/ + ├── _default/ + │ └── hugo.toml + └── development/ + └── server.toml +``` + +## Default settings + +The development server defaults to redirecting to `/404.html` for any requests to URLs that don't exist. See the [404 errors](#404-errors) section below for details. + +{{< code-toggle config=server />}} + +force +: (`bool`) Whether to force a redirect even if there is existing content in the path. + +from +: (`string`) A [glob](g) pattern matching the requested URL. Either `from` or `fromRE` must be set. If both `from` and `fromRe` are specified, the URL must match both patterns. + +fromHeaders +: {{< new-in 0.144.0 />}} +: (`map[string][string]`) Headers to match for the redirect. This maps the HTTP header name to a [glob](g) pattern with values to match. If the map is empty, the redirect will always be triggered. + +fromRe +: {{< new-in 0.144.0 />}} +: (`string`) A [regular expression](g) used to match the requested URL. Either `from` or `fromRE` must be set. If both `from` and `fromRe` are specified, the URL must match both patterns. Capture groups from the regular expression are accessible in the `to` field as `$1`, `$2`, and so on. + +status +: (`string`) The HTTP status code to use for the redirect. A status code of 200 will trigger a URL rewrite. + +to +: (`string`) The URL to forward the request 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 + +{{< code-toggle file=config/development/server >}} +[[headers]] +for = "/**" + +[headers.values] +X-Frame-Options = "DENY" +X-XSS-Protection = "1; mode=block" +X-Content-Type-Options = "nosniff" +Referrer-Policy = "strict-origin-when-cross-origin" +Content-Security-Policy = "script-src localhost:1313" +{{< /code-toggle >}} + +## Redirects + +You can define simple redirect rules. + +{{< code-toggle file=config/development/server >}} +[[redirects]] +from = "/myspa/**" +to = "/myspa/" +status = 200 +force = false +{{< /code-toggle >}} + +The `200` status code in this example triggers a URL rewrite, which is typically the desired behavior for [single-page applications]. + +[single-page applications]: https://en.wikipedia.org/wiki/Single-page_application + +## 404 errors + +The development server defaults to redirecting to /404.html for any requests to URLs that don't exist. + +{{< code-toggle config=server />}} + +If you've already defined other redirects, you must explicitly add the 404 redirect. + +{{< code-toggle file=config/development/server >}} +[[redirects]] +force = false +from = "/**" +to = "/404.html" +status = 404 +{{< /code-toggle >}} + +For multilingual sites, ensure the default language 404 redirect is defined last: + +{{< code-toggle file=config/development/server >}} +defaultContentLanguage = 'en' +defaultContentLanguageInSubdir = false +[[redirects]] +from = '/fr/**' +to = '/fr/404.html' +status = 404 + +[[redirects]] # Default language must be last. +from = '/**' +to = '/404.html' +status = 404 +{{< /code-toggle >}} + +When the default language is served from a subdirectory: + +{{< code-toggle file=config/development/server >}} +defaultContentLanguage = 'en' +defaultContentLanguageInSubdir = true +[[redirects]] +from = '/fr/**' +to = '/fr/404.html' +status = 404 + +[[redirects]] # Default language must be last. +from = '/**' +to = '/en/404.html' +status = 404 +{{< /code-toggle >}} diff --cc docs/content/en/configuration/taxonomies.md index 3cf6497bc,000000000..fed1d4c5e mode 100644,000000..100644 --- a/docs/content/en/configuration/taxonomies.md +++ b/docs/content/en/configuration/taxonomies.md @@@ -1,68 -1,0 +1,69 @@@ +--- +title: Configure taxonomies +linkTitle: Taxonomies +description: Configure taxonomies. +categories: [] +keywords: [] +--- + +The default configuration defines two [taxonomies](g), `categories` and `tags`. + +{{< code-toggle config=taxonomies />}} + +When creating a taxonomy: + +- Use the singular form for the key (e.g., `category`). +- Use the plural form for the value (e.g., `categories`). + +Then use the value as the key in front matter: + ++ +{{< code-toggle file=content/example.md fm=true >}} - --- +title: Example +categories: + - vegetarian + - gluten-free +tags: + - appetizer + - main course +{{< /code-toggle >}} - ++ +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 >}} +taxonomies: + author: author +{{< /code-toggle >}} + +Then in front matter: + ++ +{{< code-toggle file=content/example.md fm=true >}} - --- +title: Example +author: + - Robert Smith +{{< /code-toggle >}} ++ + +The example above illustrates that even with a single term, the value is still provided as an array. + +You must explicitly define the default taxonomies to maintain them when adding a new one: + +{{< code-toggle file=hugo >}} +taxonomies: + author: author + category: categories + tag: tags +{{< /code-toggle >}} + +To disable the taxonomy system, use the [`disableKinds`] setting in the root of your site configuration to disable the `taxonomy` and `term` page [kinds](g). + +{{< code-toggle file=hugo >}} +disableKinds = ['taxonomy','term'] +{{< /code-toggle >}} + +[`disableKinds`]: /configuration/all/#disablekinds + +See the [taxonomies] section for more information. + +[taxonomies]: /content-management/taxonomies/ diff --cc docs/content/en/configuration/ugly-urls.md index ec1dd8a49,000000000..17b110a9f mode 100644,000000..100644 --- a/docs/content/en/configuration/ugly-urls.md +++ b/docs/content/en/configuration/ugly-urls.md @@@ -1,36 -1,0 +1,37 @@@ +--- +title: Configure ugly URLs +linkTitle: Ugly URLs +description: Configure ugly URLs. +categories: [] +keywords: [] +--- + +{{% glossary-term "ugly url" %}} For example: + +```text +https://example.org/section/article.html +``` + +In its default configuration, Hugo generates [pretty URLs](g). For example: ++ +```text +https://example.org/section/article/ +``` + +This is the default configuration: + +{{< code-toggle config=uglyURLs />}} + +To generate ugly URLs for the entire site: + +{{< code-toggle file=hugo >}} +uglyURLs = true +{{< /code-toggle >}} + +To generate ugly URLs for specific sections of your site: + +{{< code-toggle file=hugo >}} +[uglyURLs] +books = true +films = false +{{< /code-toggle >}} diff --cc docs/content/en/content-management/comments.md index f0e4a9ae1,000000000..b843ddb99 mode 100644,000000..100644 --- a/docs/content/en/content-management/comments.md +++ b/docs/content/en/content-management/comments.md @@@ -1,72 -1,0 +1,67 @@@ +--- +title: Comments +description: Hugo ships with an internal Disqus template, but this isn't the only commenting system that will work with your new Hugo website. +categories: [] +keywords: [] +aliases: [/extras/comments/] +--- + +Hugo ships with support for [Disqus](https://disqus.com/), a third-party service that provides comment and community capabilities to websites via JavaScript. + +Your theme may already support Disqus, but if not, it is easy to add to your templates via [Hugo's built-in Disqus partial][disquspartial]. + +## Add Disqus + +Hugo comes with all the code you need to load Disqus into your templates. Before adding Disqus to your site, you'll need to [set up an account][disqussetup]. + +### Configure Disqus + +Disqus comments require you set a single value in your [site's configuration file][configuration] like so: + +{{< code-toggle file=hugo >}} +[services.disqus] +shortname = 'your-disqus-shortname' +{{}} + +For many websites, this is enough configuration. However, you also have the option to set the following in the [front matter] of a single content file: + +- `disqus_identifier` +- `disqus_title` +- `disqus_url` + +### Render Hugo's built-in Disqus partial template + +Disqus has its own [internal template](/templates/embedded/#disqus) available, to render it add the following code where you want comments to appear: + +```go-html-template +{{ partial "disqus.html" . }} +``` + +## Alternatives + +Commercial commenting systems: + +- [Emote](https://emote.com/) +- [Graph Comment](https://graphcomment.com/) +- [Hyvor Talk](https://talk.hyvor.com/) +- [IntenseDebate](https://intensedebate.com/) +- [ReplyBox](https://getreplybox.com/) + +Open-source commenting systems: + +- [Cactus Comments](https://cactus.chat/docs/integrations/hugo/) +- [Comentario](https://gitlab.com/comentario/comentario/) +- [Comma](https://github.com/Dieterbe/comma/) +- [Commento](https://commento.io/) +- [Discourse](https://meta.discourse.org/t/embed-discourse-comments-on-another-website-via-javascript/31963) +- [Giscus](https://giscus.app/) +- [Isso](https://isso-comments.de/) +- [Remark42](https://remark42.com/) +- [Staticman](https://staticman.net/) +- [Talkyard](https://blog-comments.talkyard.io/) +- [Utterances](https://utteranc.es/) + +[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/ diff --cc docs/content/en/content-management/content-adapters.md index e22962531,000000000..9eae86266 mode 100644,000000..100644 --- a/docs/content/en/content-management/content-adapters.md +++ b/docs/content/en/content-management/content-adapters.md @@@ -1,349 -1,0 +1,346 @@@ +--- +title: Content adapters +description: Create content adapters to dynamically add content when building your site. +categories: [] +keywords: [] +--- + +{{< new-in 0.126.0 />}} + +## Overview + +A content adapter is a template that dynamically creates pages when building a site. For example, use a content adapter to create pages from a remote data source such as JSON, TOML, YAML, or XML. + +Unlike templates that reside in the `layouts` directory, content adapters reside in the `content` directory, no more than one per directory per language. When a content adapter creates a page, the page's [logical path](g) will be relative to the content adapter. + +```text +content/ +├── articles/ +│ ├── _index.md +│ ├── article-1.md +│ └── article-2.md +├── books/ +│ ├── _content.gotmpl <-- content adapter +│ └── _index.md +└── films/ + ├── _content.gotmpl <-- content adapter + └── _index.md +``` + +Each content adapter is named `_content.gotmpl` and uses the same [syntax] as templates in the `layouts` directory. You can use any of the [template functions] within a content adapter, as well as the methods described below. + +## Methods + +Use these methods within a content adapter. + +### AddPage + +Adds a page to the site. + +```go-html-template {file="content/books/_content.gotmpl"} +{{ $content := dict + "mediaType" "text/markdown" + "value" "The _Hunchback of Notre Dame_ was written by Victor Hugo." +}} +{{ $page := dict + "content" $content + "kind" "page" + "path" "the-hunchback-of-notre-dame" + "title" "The Hunchback of Notre Dame" +}} +{{ .AddPage $page }} +``` + +### AddResource + +Adds a page resource to the site. + +```go-html-template {file="content/books/_content.gotmpl"} +{{ with resources.Get "images/a.jpg" }} + {{ $content := dict + "mediaType" .MediaType.Type + "value" . + }} + {{ $resource := dict + "content" $content + "path" "the-hunchback-of-notre-dame/cover.jpg" + }} + {{ $.AddResource $resource }} +{{ end }} +``` + +Then retrieve the new page resource with something like: + +```go-html-template {file="layouts/page.html"} +{{ with .Resources.Get "cover.jpg" }} + +{{ end }} +``` + +### Site + +Returns the `Site` to which the pages will be added. + +```go-html-template {file="content/books/_content.gotmpl"} +{{ .Site.Title }} +``` + +> [!note] +> Note that the `Site` returned isn't fully built when invoked from the content adapters; if you try to call methods that depends on pages, e.g. `.Site.Pages`, you will get an error saying "this method cannot be called before the site is fully initialized". + +### Store + +Returns a persistent "scratch pad" to store and manipulate data. The main use case for this is to transfer values between executions when [EnableAllLanguages](#enablealllanguages) is set. See [examples](/methods/page/store/). + +```go-html-template {file="content/books/_content.gotmpl"} +{{ .Store.Set "key" "value" }} +{{ .Store.Get "key" }} +``` + +### EnableAllLanguages + +By default, Hugo executes the content adapter for the language defined by the `_content.gotmpl` file. Use this method to activate the content adapter for all languages. + +```go-html-template {file="content/books/_content.gotmpl"} +{{ .EnableAllLanguages }} +{{ $content := dict + "mediaType" "text/markdown" + "value" "The _Hunchback of Notre Dame_ was written by Victor Hugo." +}} +{{ $page := dict + "content" $content + "kind" "page" + "path" "the-hunchback-of-notre-dame" + "title" "The Hunchback of Notre Dame" +}} +{{ .AddPage $page }} +``` + +## Page map + +Set any [front matter field] in the map passed to the [`AddPage`](#addpage) method, excluding `markup`. Instead of setting the `markup` field, specify the `content.mediaType` as described below. + +This table describes the fields most commonly passed to the `AddPage` method. + +Key|Description|Required +:--|:--|:-: +`content.mediaType`|The content [media type]. Default is `text/markdown`. See [content formats] for examples.|  +`content.value`|The content value as a string.|  +`dates.date`|The page creation date as a `time.Time` value.|  +`dates.expiryDate`|The page expiry date as a `time.Time` value.|  +`dates.lastmod`|The page last modification date as a `time.Time` value.|  +`dates.publishDate`|The page publication date as a `time.Time` value.|  +`params`|A map of page parameters.|  +`path`|The page's [logical path](g) relative to the content adapter. Do not include a leading slash or file extension.|:heavy_check_mark: +`title`|The page title.|  + +> [!note] +> While `path` is the only required field, we recommend setting `title` as well. +> +> When setting the `path`, Hugo transforms the given string to a logical path. For example, setting `path` to `A B C` produces a logical path of `/section/a-b-c`. + +## Resource map + +Construct the map passed to the [`AddResource`](#addresource) method using the fields below. + +Key|Description|Required +:--|:--|:-: +`content.mediaType`|The content [media type].|:heavy_check_mark: +`content.value`|The content value as a string or resource.|:heavy_check_mark: +`name`|The resource name.|  +`params`|A map of resource parameters.|  +`path`|The resources's [logical path](g) relative to the content adapter. Do not include a leading slash.|:heavy_check_mark: +`title`|The resource title.|  + +> [!note] +> When `content.value` is a string, Hugo generates a new resource with a publication path relative to the page. However, if `content.value` is already a resource, Hugo directly uses its value and publishes it relative to the site root. This latter method is more efficient. +> +> When setting the `path`, Hugo transforms the given string to a logical path. For example, setting `path` to `A B C/cover.jpg` produces a logical path of `/section/a-b-c/cover.jpg`. + +## Example + +Create pages from remote data, where each page represents a book review. + - ### Step 1 - - Create the content structure. - - ```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.\ - - - ### 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 }} ++Step 1 ++: Create the content structure. ++ ++ ```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.\ ++ ++ ++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 }} - {{ 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 }} ++ {{/* 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 }} + {{ end }} + {{ end }} - {{ end }} - - {{ end }} - ``` + - ### Step 4 - - Create a page template to render each book review. ++ {{ end }} ++ ``` + - ```go-html-template {file="layouts/books/page.html" copy=true} - {{ define "main" }} -

{{ .Title }}

++Step 4 ++: Create a _page_ template to render each book review. + - {{ with .Resources.GetMatch "cover.*" }} - {{ .Params.alt }} - {{ end }} ++ ```go-html-template {file="layouts/books/page.html" copy=true} ++ {{ define "main" }} ++

{{ .Title }}

+ -

Author: {{ .Params.author }}

++ {{ with .Resources.GetMatch "cover.*" }} ++ {{ .Params.alt }} ++ {{ end }} + -

- ISBN: {{ .Params.isbn }}
- Rating: {{ .Params.rating }}
- Review date: {{ .Date | time.Format ":date_long" }} -

++

Author: {{ .Params.author }}

++ ++

++ ISBN: {{ .Params.isbn }}
++ Rating: {{ .Params.rating }}
++ Review date: {{ .Date | time.Format ":date_long" }} ++

++ ++ {{ with .GetTerms "tags" }} ++

Tags:

++ ++ {{ end }} + - {{ with .GetTerms "tags" }} -

Tags:

- ++ {{ .Content }} + {{ end }} - - {{ .Content }} - {{ end }} - ``` ++ ``` + +## Multilingual sites + +With multilingual sites you can: + +1. Create one content adapter for all languages using the [`EnableAllLanguages`](#enablealllanguages) method as described above. +1. Create content adapters unique to each language. See the examples below. + +### Translations by file name + +With this site configuration: + +{{< code-toggle file=hugo >}} +[languages.en] +weight = 1 + +[languages.de] +weight = 2 +{{< /code-toggle >}} + +Include a language designator in the content adapter's file name. + +```text +content/ +└── books/ + ├── _content.de.gotmpl + ├── _content.en.gotmpl + ├── _index.de.md + └── _index.en.md +``` + +### Translations by content directory + +With this site configuration: + +{{< code-toggle file=hugo >}} +[languages.en] +contentDir = 'content/en' +weight = 1 + +[languages.de] +contentDir = 'content/de' +weight = 2 +{{< /code-toggle >}} + +Create a single content adapter in each directory: + +```text +content/ +├── de/ +│ └── books/ +│ ├── _content.gotmpl +│ └── _index.md +└── en/ + └── books/ + ├── _content.gotmpl + └── _index.md +``` + +## Page collisions + +Two or more pages collide when they have the same publication path. Due to concurrency, the content of the published page is indeterminate. Consider this example: + +```text +content/ +└── books/ + ├── _content.gotmpl <-- content adapter + ├── _index.md + └── the-hunchback-of-notre-dame.md +``` + +If the content adapter also creates `books/the-hunchback-of-notre-dame`, the content of the published page is indeterminate. You can not define the processing order. + +To detect page collisions, use the `--printPathWarnings` flag when building your site. + +[content formats]: /content-management/formats/#classification +[front matter field]: /content-management/front-matter/#fields +[media type]: https://en.wikipedia.org/wiki/Media_type +[syntax]: /templates/introduction/ +[template functions]: /functions/ diff --cc docs/content/en/content-management/formats.md index c82329ab2,000000000..65fb3d04d mode 100644,000000..100644 --- a/docs/content/en/content-management/formats.md +++ b/docs/content/en/content-management/formats.md @@@ -1,134 -1,0 +1,133 @@@ +--- +title: Content formats +description: Create your content using Markdown, HTML, Emacs Org Mode, AsciiDoc, Pandoc, or reStructuredText. +categories: [] +keywords: [] +aliases: [/content/markdown-extras/,/content/supported-formats/,/doc/supported-formats/] +--- + +## Introduction + +You may mix content formats throughout your site. For example: + +```text +content/ +└── posts/ + ├── post-1.md + ├── post-2.adoc + ├── post-3.org + ├── post-4.pandoc + ├── post-5.rst + └── post-6.html +``` + +Regardless of content format, all content must have [front matter], preferably including both `title` and `date`. + +Hugo selects the content renderer based on the `markup` identifier in front matter, falling back to the file extension. See the [classification] table below for a list of markup identifiers and recognized file extensions. + +[classification]: #classification +[front matter]: /content-management/front-matter/ + +## Formats + +### Markdown + +Create your content in [Markdown] preceded by front matter. + +Markdown is Hugo's default content format. Hugo natively renders Markdown to HTML using [Goldmark]. Goldmark is fast and conforms to the [CommonMark] and [GitHub Flavored Markdown] specifications. You can configure Goldmark in your [site configuration][configure goldmark]. + +Hugo provides custom Markdown features including: + +[Attributes] +: Apply HTML attributes such as `class` and `id` to Markdown images and block elements including blockquotes, fenced code blocks, headings, horizontal rules, lists, paragraphs, and tables. + +[Extensions] +: Leverage the embedded Markdown extensions to create tables, definition lists, footnotes, task lists, inserted text, mark text, subscripts, superscripts, and more. + +[Mathematics] +: Include mathematical equations and expressions in Markdown using LaTeX markup. + +[Render hooks] +: Override the conversion of Markdown to HTML when rendering fenced code blocks, headings, images, and links. For example, render every standalone image as an HTML `figure` element. + +[Attributes]: /content-management/markdown-attributes/ +[CommonMark]: https://spec.commonmark.org/current/ +[Extensions]: /configuration/markup/#extensions +[GitHub Flavored Markdown]: https://github.github.com/gfm/ +[Goldmark]: https://github.com/yuin/goldmark +[Markdown]: https://daringfireball.net/projects/markdown/ +[Mathematics]: /content-management/mathematics/ +[Render hooks]: /render-hooks/introduction/ +[configure goldmark]: /configuration/markup/#goldmark + +### HTML + +Create your content in [HTML] preceded by front matter. The content is typically what you would place within an HTML document's `body` or `main` element. + +[HTML]: https://developer.mozilla.org/en-US/docs/Learn_web_development/Getting_started/Your_first_website/Creating_the_content + +### Emacs Org Mode + +Create your content in the [Emacs Org Mode] format preceded by front matter. You can use Org Mode keywords for front matter. See [details]. + +[details]: /content-management/front-matter/#emacs-org-mode +[Emacs Org Mode]: https://orgmode.org/ + +### AsciiDoc + +Create your content in the [AsciiDoc] format preceded by front matter. Hugo renders AsciiDoc content to HTML using the Asciidoctor executable. You must install Asciidoctor and its dependencies (Ruby) to render the AsciiDoc content format. + +You can configure the AsciiDoc renderer in your [site configuration][configure asciidoc]. + +In its default configuration, Hugo passes these CLI flags when calling the Asciidoctor executable: + +```text +--no-header-footer +``` + +The CLI flags passed to the Asciidoctor executable depend on configuration. You may inspect the flags when building your site: + +```text +hugo --logLevel info +``` + +[AsciiDoc]: https://asciidoc.org/ - [configure the AsciiDoc renderer]: /configuration/markup/#asciidoc +[configure asciidoc]: /configuration/markup/#asciidoc + +### Pandoc + +Create your content in the [Pandoc] format[^1] preceded by front matter. Hugo renders Pandoc content to HTML using the Pandoc executable. You must install Pandoc to render the Pandoc content format. + +[^1]: This is a derivation of the Markdown format as described by the CommonMark specification. + +Hugo passes these CLI flags when calling the Pandoc executable: + +```text +--mathjax +``` + +[Pandoc]: https://pandoc.org/MANUAL.html#pandocs-markdown + +### reStructuredText + +Create your content in the [reStructuredText] format preceded by front matter. Hugo renders reStructuredText content to HTML using [Docutils], specifically rst2html. You must install Docutils and its dependencies (Python) to render the reStructuredText content format. + +Hugo passes these CLI flags when calling the rst2html executable: + +```text +--leave-comments --initial-header-level=2 +``` + +[Docutils]: https://docutils.sourceforge.io/ +[reStructuredText]: https://docutils.sourceforge.io/rst.html + +## Classification + +{{% include "/_common/content-format-table.md" %}} + +When converting content to HTML, Hugo uses: + +- Native renderers for Markdown, HTML, and Emacs Org mode +- External renderers for AsciiDoc, Pandoc, and reStructuredText + +Native renderers are faster than external renderers. diff --cc docs/content/en/content-management/front-matter.md index d99475f4c,000000000..2da6a2613 mode 100644,000000..100644 --- a/docs/content/en/content-management/front-matter.md +++ b/docs/content/en/content-management/front-matter.md @@@ -1,362 -1,0 +1,357 @@@ +--- +title: Front matter +description: Use front matter to add metadata to your content. +categories: [] +keywords: [] +aliases: [/content/front-matter/] +--- + +## Overview + +The front matter at the top of each content file is metadata that: + +- Describes the content +- Augments the content +- Establishes relationships with other content +- Controls the published structure of your site +- Determines template selection + +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 >}} +title = 'Example' +date = 2024-02-02T04:14:54-08:00 +draft = false +weight = 10 +[params] +author = 'John Smith' +{{< /code-toggle >}} + +Front matter fields may be [boolean](g), [integer](g), [float](g), [string](g), [arrays](g), or [maps](g). Note that the TOML format also supports unquoted date/time values. + +## Fields + +The most common front matter fields are `date`, `draft`, `title`, and `weight`, but you can specify metadata using any of fields below. + +> [!note] +> The field names below are reserved. For example, you cannot create a custom field named `type`. Create custom fields under the `params` key. See the [parameters] section for details. + +[parameters]: #parameters + +aliases +: (`string array`) An array of one or more aliases, where each alias is a relative URL that will redirect the browser to the current location. Access these values from a template using the [`Aliases`] method on a `Page` object. See the [aliases] section for details. + +build +: (`map`) A map of [build options]. + +cascade +: (`map`) A map of front matter keys whose values are passed down to the page's descendants unless overwritten by self or a closer ancestor's cascade. See the [cascade] section for details. + +date +: (`string`) The date associated with the page, typically the creation date. Note that the TOML format also supports unquoted date/time values. See the [dates](#dates) section for examples. Access this value from a template using the [`Date`] method on a `Page` object. + +description +: (`string`) Conceptually different than the page `summary`, the description is typically rendered within a `meta` element within the `head` element of the published HTML file. Access this value from a template using the [`Description`] method on a `Page` object. + +draft +: (`bool`) Whether to disable rendering unless you pass the `--buildDrafts` flag to the `hugo` command. Access this value from a template using the [`Draft`] method on a `Page` object. + +expiryDate +: (`string`) The page expiration date. On or after the expiration date, the page will not be rendered unless you pass the `--buildExpired` flag to the `hugo` command. Note that the TOML format also supports unquoted date/time values. See the [dates](#dates) section for examples. Access this value from a template using the [`ExpiryDate`] method on a `Page` object. + +headless +: (`bool`) Applicable to [leaf bundles], whether to set the `render` and `list` [build options] to `never`, creating a headless bundle of [page resources]. + +isCJKLanguage +: (`bool`) Whether the content language is in the [CJK](g) family. This value determines how Hugo calculates word count, and affects the values returned by the [`WordCount`], [`FuzzyWordCount`], [`ReadingTime`], and [`Summary`] methods on a `Page` object. + +keywords +: (`string array`) An array of keywords, typically rendered within a `meta` element within the `head` element of the published HTML file, or used as a [taxonomy](g) to classify content. Access these values from a template using the [`Keywords`] method on a `Page` object. + +lastmod +: (`string`) The date that the page was last modified. Note that the TOML format also supports unquoted date/time values. See the [dates](#dates) section for examples. Access this value from a template using the [`Lastmod`] method on a `Page` object. + +layout +: (`string`) Provide a template name to [target a specific template], overriding the default [template lookup order]. Set the value to the base file name of the template, excluding its extension. Access this value from a template using the [`Layout`] method on a `Page` object. + +linkTitle +: (`string`) Typically a shorter version of the `title`. Access this value from a template using the [`LinkTitle`] method on a `Page` object. + +markup +: (`string`) An identifier corresponding to one of the supported [content formats]. If not provided, Hugo determines the content renderer based on the file extension. + +menus +: (`string`, `string array`, or `map`) If set, Hugo adds the page to the given menu or menus. See the [menus] page for details. + +modified +: Alias to [lastmod](#lastmod). + +outputs +: (`string array`) The [output formats] to render. See [configure outputs] for more information. + +params +: {{< new-in 0.123.0 />}} +: (`map`) A map of custom [page parameters]. + +pubdate +: Alias to [publishDate](#publishdate). + +publishDate +: (`string`) The page publication date. Before the publication date, the page will not be rendered unless you pass the `--buildFuture` flag to the `hugo` command. Note that the TOML format also supports unquoted date/time values. See the [dates](#dates) section for examples. Access this value from a template using the [`PublishDate`] method on a `Page` object. + +published +: Alias to [publishDate](#publishdate). + +resources +: (`map array`) An array of maps to provide metadata for [page resources]. + +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. + +title +: (`string`) The page title. Access this value from a template using the [`Title`] method on a `Page` object. + +translationKey +: (`string`) An arbitrary value used to relate two or more translations of the same page, useful when the translated pages do not share a common path. Access this value from a template using the [`TranslationKey`] method on a `Page` object. + +type +: (`string`) The [content type](g), overriding the value derived from the top-level section in which the page resides. Access this value from a template using the [`Type`] method on a `Page` object. + +unpublishdate +: Alias to [expirydate](#expirydate). + +url +: (`string`) Overrides the entire URL path. Applicable to regular pages and section pages. See the [URL management] page for details. + +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 />}} + +Specify custom page parameters under the `params` key in front matter: + +{{< code-toggle file=content/example.md fm=true >}} +title = 'Example' +date = 2024-02-02T04:14:54-08:00 +draft = false +weight = 10 +[params] +author = 'John Smith' +{{< /code-toggle >}} + +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 +:--|:--|:-- +`audio`|`[]string`|[`opengraph.html`] +`images`|`[]string`|[`opengraph.html`], [`schema.html`], [`twitter_cards.html`] +`videos`|`[]string`|[`opengraph.html`] + +The embedded templates will skip a parameter if not provided in front matter, but will throw an error if the data type is unexpected. + +## Taxonomies + +Classify content by adding taxonomy terms to front matter. For example, with this site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +tag = 'tags' +genre = 'genres' +{{< /code-toggle >}} + +Add taxonomy terms as shown below: + +{{< code-toggle file=content/example.md fm=true >}} +title = 'Example' +date = 2024-02-02T04:14:54-08:00 +draft = false +weight = 10 +tags = ['red','blue'] +genres = ['mystery','romance'] +[params] +author = 'John Smith' +{{< /code-toggle >}} + +You can add taxonomy terms to the front matter of any these [page kinds](g): + +- `home` +- `page` +- `section` +- `taxonomy` +- `term` + +Access taxonomy terms from a template using the [`Params`] or [`GetTerms`] method on a `Page` object. For example: + +```go-html-template {file="layouts/page.html"} +{{ with .GetTerms "tags" }} +

Tags

+ +{{ end }} +``` + - [`Params`]: /methods/page/params/ +[`GetTerms`]: /methods/page/getterms/ + +## Cascade + +A [node](g) can cascade front matter values to its descendants. However, this cascading will be prevented if the descendant already defines the field, or if a closer ancestor node has already cascaded a value for that same field. + +For example, to cascade a "color" parameter from the home page to all its descendants: + +{{< code-toggle file=content/_index.md fm=true >}} +title = 'Home' +[cascade.params] +color = 'red' +{{< /code-toggle >}} + +### Target + + + +The `target`[^1] keyword allows you to target specific pages or [environments](g). For example, to cascade a "color" parameter from the home page only to pages within the "articles" section, including the "articles" section page itself: + +[^1]: The `_target` alias for `target` is deprecated and will be removed in a future release. + +{{< code-toggle file=content/_index.md fm=true >}} +title = 'Home' +[cascade.params] +color = 'red' +[cascade.target] +path = '{/articles,/articles/**}' +{{< /code-toggle >}} + +Use any combination of these keywords to target pages and/or environments: + +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/**}`. + +### Array + +Define an array of cascade parameters to apply different values to different targets. For example: + +{{< code-toggle file=content/_index.md fm=true >}} +title = 'Home' +[[cascade]] +[cascade.params] +color = 'red' +[cascade.target] +path = '{/books/**}' +kind = 'page' +[[cascade]] +[cascade.params] +color = 'blue' +[cascade.target] +path = '{/films/**}' +kind = 'page' +{{< /code-toggle >}} + +> [!note] +> For multilingual sites, defining cascade values in your site configuration is often more efficient. This avoids repeating the same cascade values on the home, section, taxonomy, or term page for each language. See [details](/configuration/cascade/). +> +> If you choose to define cascade values in front matter for a multilingual site, you must create a corresponding home, section, taxonomy, or term page for every language. + +## Emacs Org Mode + +If your [content format] is [Emacs Org Mode], you may provide front matter using Org Mode keywords. For example: + +```text {file="content/example.org"} +#+TITLE: Example +#+DATE: 2024-02-02T04:14:54-08:00 +#+DRAFT: false +#+AUTHOR: John Smith +#+GENRES: mystery +#+GENRES: romance +#+TAGS: red +#+TAGS: blue +#+WEIGHT: 10 +``` + +Note that you can also specify array elements on a single line: + +```text {file="content/example.org"} +#+TAGS[]: red blue +``` + +[content format]: /content-management/formats/ +[emacs org mode]: https://orgmode.org/ + +## Dates + +When populating a date field, whether a [custom page parameter](#parameters) or one of the four predefined fields ([`date`](#date), [`expiryDate`](#expirydate), [`lastmod`](#lastmod), [`publishDate`](#publishdate)), use one of these parsable formats: + +{{% include "/_common/parsable-date-time-strings.md" %}} + +To override the default time zone, set the [`timeZone`](/configuration/all/#timezone) in your site configuration. The order of precedence for determining the time zone is: + +1. The time zone offset in the date/time string +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/ diff --cc docs/content/en/content-management/mathematics.md index dc47cbde4,000000000..aaa8c2394 mode 100644,000000..100644 --- a/docs/content/en/content-management/mathematics.md +++ b/docs/content/en/content-management/mathematics.md @@@ -1,238 -1,0 +1,233 @@@ +--- +title: Mathematics in Markdown +linkTitle: Mathematics +description: Include mathematical equations and expressions in Markdown using LaTeX markup. +categories: [] +keywords: [] +--- + +{{< new-in 0.122.0 />}} + +## Overview + +Mathematical equations and expressions written in [LaTeX] are common in academic and scientific publications. Your browser typically renders this mathematical markup using an open-source JavaScript display engine such as [MathJax] or [KaTeX]. + +For example, with this LaTeX markup: + +```text +\[ +\begin{aligned} +KL(\hat{y} || y) &= \sum_{c=1}^{M}\hat{y}_c \log{\frac{\hat{y}_c}{y_c}} \\ +JS(\hat{y} || y) &= \frac{1}{2}(KL(y||\frac{y+\hat{y}}{2}) + KL(\hat{y}||\frac{y+\hat{y}}{2})) +\end{aligned} +\] +``` + +The MathJax display engine renders this: + +\[ +\begin{aligned} +KL(\hat{y} || y) &= \sum_{c=1}^{M}\hat{y}_c \log{\frac{\hat{y}_c}{y_c}} \\ +JS(\hat{y} || y) &= \frac{1}{2}(KL(y||\frac{y+\hat{y}}{2}) + KL(\hat{y}||\frac{y+\hat{y}}{2})) +\end{aligned} +\] + +Equations and expressions can be displayed inline with other text, or as standalone blocks. Block presentation is also known as "display" mode. + +Whether an equation or expression appears inline, or as a block, depends on the delimiters that surround the mathematical markup. Delimiters are defined in pairs, where each pair consists of an opening and closing delimiter. The opening and closing delimiters may be the same, or different. + +> [!note] +> You can configure Hugo to render mathematical markup on the client side using the MathJax or KaTeX display engine, or you can render the markup with the [`transform.ToMath`] function while building your site. +> +> The first approach is described below. + +## Setup + +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} ++ ++ ++ ``` + - 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} - - - ``` ++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"} ++ ++ ... ++ {{ if .Param "math" }} ++ {{ partialCached "math.html" . }} ++ {{ end }} ++ ... ++ ++ ``` + - ### 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"} - - ... - {{ if .Param "math" }} - {{ partialCached "math.html" . }} - {{ end }} - ... - - ``` ++ {{< 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^* - \] - - 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: ++ $$ a^*=x-b^* $$ + - {{< code-toggle file=content/math-examples.md fm=true >}} - title = 'Math examples' - date = 2024-01-24T18:09:49-08:00 - [params] - math = true - {{< /code-toggle >}} ++ $$ ++ a^*=x-b^* ++ $$ ++ ``` + +## Inline delimiters + +The configuration, JavaScript, and examples above use the `\(...\)` delimiter pair for inline equations. The `$...$` delimiter pair is a common alternative, but using it may result in unintended formatting if you use the `$` symbol outside of math contexts. + +If you add the `$...$` delimiter pair to your configuration and JavaScript, you must double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting. For example: + +```text +I will give you \\$2 if you can solve $y = x^2$. +``` + +> [!note] +> If you use the `$...$` delimiter pair for inline equations, and occasionally use the `$` symbol outside of math contexts, you must use MathJax instead of KaTeX to avoid unintended formatting caused by [this KaTeX limitation](https://github.com/KaTeX/KaTeX/issues/437). + +## Engines + +MathJax and KaTeX are open-source JavaScript display engines. Both engines are fast, but at the time of this writing MathJax v3.2.2 is slightly faster than KaTeX v0.16.11. + +> [!note] +> If you use the `$...$` delimiter pair for inline equations, and occasionally use the `$` symbol outside of math contexts, you must use MathJax instead of KaTeX to avoid unintended formatting caused by [this KaTeX limitation](https://github.com/KaTeX/KaTeX/issues/437). +> +>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} + + + + +``` + +The delimiters above must match the delimiters in your site configuration. + +## Chemistry + +Both MathJax and KaTeX provide support for chemical equations. For example: + +```text +$$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 diff --cc docs/content/en/content-management/menus.md index 6d01173dc,000000000..8ff0597b3 mode 100644,000000..100644 --- a/docs/content/en/content-management/menus.md +++ b/docs/content/en/content-management/menus.md @@@ -1,97 -1,0 +1,99 @@@ +--- +title: Menus +description: Create menus by defining entries, localizing each entry, and rendering the resulting data structure. +categories: [] +keywords: [] +aliases: [/extras/menus/] +--- + +## Overview + +To create a menu for your site: + +1. Define the menu entries +1. [Localize](multilingual/#menus) each entry +1. Render the menu with a [template] + +Create multiple menus, either flat or nested. For example, create a main menu for the header, and a separate menu for the footer. + +There are three ways to define menu entries: + +1. Automatically +1. In front matter +1. In site configuration + +> [!note] +> Although you can use these methods in combination when defining a menu, the menu will be easier to conceptualize and maintain if you use one method throughout the site. + +## Define automatically + +To automatically define a menu entry for each top-level [section](g) of your site, enable the section pages menu in your site configuration. + +{{< code-toggle file=hugo >}} +sectionPagesMenu = "main" +{{< /code-toggle >}} + +This creates a menu structure that you can access with `site.Menus.main` in your templates. See [menu templates] for details. + +## Define in front matter + +To add a page to the "main" menu: + +{{< code-toggle file=content/about.md fm=true >}} +title = 'About' +menus = 'main' +{{< /code-toggle >}} + +Access the entry with `site.Menus.main` in your templates. See [menu templates] for details. + +To add a page to the "main" and "footer" menus: + +{{< code-toggle file=content/contact.md fm=true >}} +title = 'Contact' +menus = ['main','footer'] +{{< /code-toggle >}} + +Access the entry with `site.Menus.main` and `site.Menus.footer` in your templates. See [menu templates] for details. + +> [!note] +> The configuration key in the examples above is `menus`. The `menu` (singular) configuration key is an alias for `menus`. + +### Properties + +Use these properties when defining menu entries in front matter: + +{{% include "/_common/menu-entry-properties.md" %}} + +### Example + +This front matter menu entry demonstrates some of the available properties: + ++ +{{< code-toggle file=content/products/software.md fm=true >}} +title = 'Software' +[menus.main] +parent = 'Products' +weight = 20 +pre = '' +[menus.main.params] +class = 'center' +{{< /code-toggle >}} ++ + +Access the entry with `site.Menus.main` in your templates. See [menu templates] for details. + +## Define in site configuration + +See [configure menus](/configuration/menus/). + +## Localize + +Hugo provides two methods to localize your menu entries. See [multilingual]. + +## Render + +See [menu templates]. + +[menu templates]: /templates/menu/ +[multilingual]: /content-management/multilingual/#menus +[template]: /templates/menu/ diff --cc docs/content/en/content-management/multilingual.md index a22f0b50e,000000000..5a5cd2307 mode 100644,000000..100644 --- a/docs/content/en/content-management/multilingual.md +++ b/docs/content/en/content-management/multilingual.md @@@ -1,429 -1,0 +1,429 @@@ +--- +title: Multilingual mode +linkTitle: Multilingual +description: Localize your project for each language and region, including translations, images, dates, currencies, numbers, percentages, and collation sequence. Hugo's multilingual framework supports single-host and multihost configurations. +categories: [] +keywords: [] +aliases: [/content/multilingual/,/tutorials/create-a-multilingual-site/] +--- + +## Configuration + +See [configure languages](/configuration/languages/). + +## Translate your content + +There are two ways to manage your content translations. Both ensure each page is assigned a language and is linked to its counterpart translations. + +### Translation by file name + +Considering the following example: + +1. `/content/about.en.md` +1. `/content/about.fr.md` + +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. + +### Translation by content directory + +This system uses different content directories for each of the languages. Each language's `content` directory is set using the `contentDir` parameter. + +{{< code-toggle file=hugo >}} +languages: + en: + weight: 10 + languageName: "English" + contentDir: "content/english" + fr: + weight: 20 + languageName: "Français" + contentDir: "content/french" +{{< /code-toggle >}} + +The value of `contentDir` can be any valid path -- even absolute path references. The only restriction is that the content directories cannot overlap. + +Considering the following example in conjunction with the configuration above: + +1. `/content/english/about.md` +1. `/content/french/about.md` + +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 + +Any pages sharing the same `translationKey` set in front matter will be linked as translated pages regardless of basename or location. + +Considering the following example: + +1. `/content/about-us.en.md` +1. `/content/om.nn.md` +1. `/content/presentation/a-propos.fr.md` + +{{< code-toggle file=hugo >}} +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 + +Because paths and file names are used to handle linking, all translated pages will share the same URL (apart from the language subdirectory). + +To localize URLs: + +- For a regular page, set either [`slug`] or [`url`] in front matter +- For a section page, set [`url`] in front matter + +For example, a French translation can have its own localized slug. + +{{< code-toggle file=content/about.fr.md fm=true >}} +title: A Propos +slug: "a-propos" +{{< /code-toggle >}} + +At render, Hugo will build both `/about/` and `/fr/a-propos/` without affecting the translation link. + +### Page bundles + +To avoid the burden of having to duplicate files, each Page Bundle inherits the resources of its linked translated pages' bundles except for the content files (Markdown files, HTML files etc.). + +Therefore, from within a template, the page will have access to the files from all linked pages' bundles. + +If, across the linked bundles, two or more files share the same basename, only one will be included and chosen as follows: + +- File from current language bundle, if present. +- First file found across bundles by order of language `Weight`. + +> [!note] +> Page Bundle resources follow the same language assignment logic as content files, both by file name (`image.jpg`, `image.fr.jpg`) and by directory (`english/about/header.jpg`, `french/about/header.jpg`). + +## Reference translated content + +To create a list of links to translated content, use a template similar to the following: + +```go-html-template {file="layouts/_partials/i18nlist.html"} +{{ if .IsTranslated }} +

{{ i18n "translations" }}

+ +{{ 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. + +### List all available languages + +`.AllTranslations` on a `Page` can be used to list all translations, including the page itself. On the home page it can be used to build a language navigator: + +```go-html-template {file="layouts/_partials/allLanguages.html"} + +``` + +## Translation of strings + +See the [`lang.Translate`] template function. + +## Localization + +The following localization examples assume your site's primary language is English, with translations to French and German. + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' + +[languages] +[languages.en] +contentDir = 'content/en' +languageName = 'English' +weight = 1 +[languages.fr] +contentDir = 'content/fr' +languageName = 'Français' +weight = 2 +[languages.de] +contentDir = 'content/de' +languageName = 'Deutsch' +weight = 3 + +{{< /code-toggle >}} + +### Dates + +With this front matter: + +{{< code-toggle file=hugo >}} +date = 2021-11-03T12:34:56+01:00 +{{< /code-toggle >}} + +And this template code: + +```go-html-template +{{ .Date | time.Format ":date_full" }} +``` + +The rendered page displays: + +Language|Value +:--|:-- +English|Wednesday, November 3, 2021 +Français|mercredi 3 novembre 2021 +Deutsch|Mittwoch, 3. November 2021 + +See [`time.Format`] for details. + +### Currency + +With this template code: + +```go-html-template +{{ 512.5032 | lang.FormatCurrency 2 "USD" }} +``` + +The rendered page displays: + +Language|Value +:--|:-- +English|$512.50 +Français|512,50 $US +Deutsch|512,50 $ + +See [lang.FormatCurrency] and [lang.FormatAccounting] for details. + +### Numbers + +With this template code: + +```go-html-template +{{ 512.5032 | lang.FormatNumber 2 }} +``` + +The rendered page displays: + +Language|Value +:--|:-- +English|512.50 +Français|512,50 +Deutsch|512,50 + +See [lang.FormatNumber] and [lang.FormatNumberCustom] for details. + +### Percentages + +With this template code: + +```go-html-template +{{ 512.5032 | lang.FormatPercent 2 }} +``` + +The rendered page displays: + +Language|Value +:--|:-- +English|512.50% +Français|512,50 % +Deutsch|512,50 % + +See [lang.FormatPercent] for details. + +## Menus + +Localization of menu entries depends on how you define them: + +- When you define menu entries [automatically] using the section pages menu, you must use translation tables to localize each entry. +- When you define menu entries [in front matter], they are already localized based on the front matter itself. If the front matter values are insufficient, use translation tables to localize each entry. +- When you define menu entries [in site configuration], you must create language-specific menu entries under each language key. If the names of the menu entries are insufficient, use translation tables to localize each entry. + +### Create language-specific menu entries + +#### Method 1 -- Use a single configuration file + +For a simple menu with a small number of entries, use a single configuration file. For example: + +{{< code-toggle file=hugo >}} +[languages.de] +languageCode = 'de-DE' +languageName = 'Deutsch' +weight = 1 + +[[languages.de.menus.main]] +name = 'Produkte' +pageRef = '/products' +weight = 10 + +[[languages.de.menus.main]] +name = 'Leistungen' +pageRef = '/services' +weight = 20 + +[languages.en] +languageCode = 'en-US' +languageName = 'English' +weight = 2 + +[[languages.en.menus.main]] +name = 'Products' +pageRef = '/products' +weight = 10 + +[[languages.en.menus.main]] +name = 'Services' +pageRef = '/services' +weight = 20 +{{< /code-toggle >}} + +#### Method 2 -- Use a configuration directory + +With a more complex menu structure, create a [configuration directory] and split the menu entries into multiple files, one file per language. For example: + +```text +config/ +└── _default/ + ├── menus.de.toml + ├── menus.en.toml + └── hugo.toml +``` + +{{< code-toggle file=config/_default/menus.de >}} +[[main]] +name = 'Produkte' +pageRef = '/products' +weight = 10 +[[main]] +name = 'Leistungen' +pageRef = '/services' +weight = 20 +{{< /code-toggle >}} + +{{< code-toggle file=config/_default/menus.en >}} +[[main]] +name = 'Products' +pageRef = '/products' +weight = 10 +[[main]] +name = 'Services' +pageRef = '/services' +weight = 20 +{{< /code-toggle >}} + +### Use translation tables + +When rendering the text that appears in menu each entry, the [example menu template] does this: + +```go-html-template +{{ or (T .Identifier) .Name | safeHTML }} +``` + +It queries the translation table for the current language using the menu entry's `identifier` and returns the translated string. If the translation table does not exist, or if the `identifier` key is not present in the translation table, it falls back to `name`. + +The `identifier` depends on how you define menu entries: + +- If you define the menu entry [automatically] using the section pages menu, the `identifier` is the page's `.Section`. +- If you define the menu entry [in site configuration] or [in front matter], set the `identifier` property to the desired value. + +For example, if you define menu entries in site configuration: + +{{< code-toggle file=hugo >}} +[[menus.main]] + identifier = 'products' + name = 'Products' + pageRef = '/products' + weight = 10 +[[menus.main]] + identifier = 'services' + name = 'Services' + pageRef = '/services' + weight = 20 +{{< / code-toggle >}} + +Create corresponding entries in the translation tables: + +{{< code-toggle file=i18n/de >}} +products = 'Produkte' +services = 'Leistungen' +{{< / code-toggle >}} + +## Missing translations + +If a string does not have a translation for the current language, Hugo will use the value from the default language. If no default value is set, an empty string will be shown. + +While translating a Hugo website, it can be handy to have a visual indicator of missing translations. The [`enableMissingTranslationPlaceholders` configuration option][config] will flag all untranslated strings with the placeholder `[i18n] identifier`, where `identifier` is the id of the missing translation. + +> [!note] +> Hugo will generate your website with these missing translation placeholders. It might not be suitable for production environments. + +For merging of content from other languages (i.e. missing content translations), see [lang.Merge]. + +To track down missing translation strings, run Hugo with the `--printI18nWarnings` flag: + +```sh +hugo --printI18nWarnings | grep i18n +i18n|MISSING_TRANSLATION|en|wordCount +``` + +## Multilingual themes support + +To support Multilingual mode in your themes, some considerations must be taken for the URLs in the templates. If there is more than one language, URLs must meet the following criteria: + +- Come from the built-in `.Permalink` or `.RelPermalink` +- Be constructed with the [`relLangURL`] or [`absLangURL`] template function, or be prefixed with `{{ .LanguagePrefix }}` + +If there is more than one language defined, the `LanguagePrefix` method will return `/en` (or whatever the current language is). If not enabled, it will be an empty string (and is therefore harmless for single-language Hugo websites). + +## Generate multilingual content with `hugo new content` + +If you organize content with translations in the same directory: + +```sh +hugo new content post/test.en.md +hugo new content post/test.de.md +``` + +If you organize content with translations in different directories: + +```sh +hugo new content content/en/post/test.md +hugo new content content/de/post/test.md +``` + +[`absLangURL`]: /functions/urls/abslangurl/ +[`lang.Translate`]: /functions/lang/translate +[`relLangURL`]: /functions/urls/rellangurl/ +[`slug`]: /content-management/urls/#slug +[`time.Format`]: /functions/time/format/ +[`url`]: /content-management/urls/#url +[automatically]: /content-management/menus/#define-automatically +[config]: /configuration/ +[configuration directory]: /configuration/introduction/#configuration-directory +[example menu template]: /templates/menu/#example +[i18func]: /functions/lang/translate/ +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/#define-in-site-configuration +[lang.FormatAccounting]: /functions/lang/formataccounting/ +[lang.FormatCurrency]: /functions/lang/formatcurrency/ +[lang.FormatNumber]: /functions/lang/formatnumber/ +[lang.FormatNumberCustom]: /functions/lang/formatnumbercustom/ +[lang.FormatPercent]: /functions/lang/formatpercent/ +[lang.Merge]: /functions/lang/merge/ diff --cc docs/content/en/content-management/organization/index.md index 4a8fcb6fc,000000000..4c6b94e3e mode 100644,000000..100644 --- a/docs/content/en/content-management/organization/index.md +++ b/docs/content/en/content-management/organization/index.md @@@ -1,151 -1,0 +1,151 @@@ +--- +title: Content organization +linkTitle: Organization +description: Hugo assumes that the same structure that works to organize your source content is used to organize the rendered site. +categories: [] +keywords: [] +aliases: [/content/sections/] +--- + +## Page bundles + +Hugo `0.32` announced page-relative images and other resources packaged into `Page Bundles`. + +These terms are connected, and you also need to read about [Page Resources](/content-management/page-resources) and [Image Processing](/content-management/image-processing) to get the full picture. + +```text +content/ +├── blog/ +│ ├── hugo-is-cool/ +│ │ ├── images/ +│ │ │ ├── funnier-cat.jpg +│ │ │ └── funny-cat.jpg +│ │ ├── cats-info.md +│ │ └── index.md +│ ├── posts/ +│ │ ├── post1.md +│ │ └── post2.md +│ ├── 1-landscape.jpg +│ ├── 2-sunset.jpg +│ ├── _index.md +│ ├── content-1.md +│ └── content-2.md +├── 1-logo.png +└── _index.md +``` + +The file tree above shows three bundles. Note that the home page bundle cannot contain other content pages, although other files (images etc.) are allowed. + +## Organization of content source + +In Hugo, your content should be organized in a manner that reflects the rendered website. + +While Hugo supports content nested at any level, the top levels (i.e. `content/`) are special in Hugo and are considered the content type used to determine layouts etc. To read more about sections, including how to nest them, see [sections]. + +Without any additional configuration, the following will automatically work: + +```txt +. +└── content + └── about + | └── index.md // <- https://example.org/about/ + ├── posts + | ├── firstpost.md // <- https://example.org/posts/firstpost/ + | ├── happy + | | └── ness.md // <- https://example.org/posts/happy/ness/ + | └── secondpost.md // <- https://example.org/posts/secondpost/ + └── quote + ├── first.md // <- https://example.org/quote/first/ + └── second.md // <- https://example.org/quote/second/ +``` + +## Path breakdown in Hugo + +The following demonstrates the relationships between your content organization and the output URL structure for your Hugo website when it renders. These examples assume you are [using pretty URLs][pretty], which is the default behavior for Hugo. The examples also assume a key-value of `baseURL = "https://example.org/"` in your [site's configuration file][config]. + +### Index pages: `_index.md` + +`_index.md` has a special role in Hugo. It allows you to add front matter and content to `home`, `section`, `taxonomy`, and `term` pages. + +> [!note] +> Access the content and metadata within an `_index.md` file by invoking the `GetPage` method on a `Site` or `Page` object. + +You can create one `_index.md` for your home page and one in each of your content sections, taxonomies, and terms. The following shows typical placement of an `_index.md` that would contain content and front matter for a `posts` section list page on a Hugo website: + +```txt +. url +. ⊢--^-⊣ +. path slug +. ⊢--^-⊣⊢---^---⊣ +. file path +. ⊢------^------⊣ +content/posts/_index.md +``` + +At build, this will output to the following destination with the associated values: + +```txt + + url ("/posts/") + ⊢-^-⊣ + baseurl section ("posts") +⊢--------^---------⊣⊢-^-⊣ + permalink +⊢----------^-------------⊣ +https://example.org/posts/index.html +``` + +The [sections] can be nested as deeply as you want. The important thing to understand is that to make the section tree fully navigational, at least the lower-most section must include a content file. (i.e. `_index.md`). + +### Single pages in sections + +Single content files in each of your sections will be rendered by a [page template]. Here is an example of a single `post` within `posts`: + +```txt + path ("posts/my-first-hugo-post.md") +. ⊢-----------^------------⊣ +. section slug +. ⊢-^-⊣⊢--------^----------⊣ +content/posts/my-first-hugo-post.md +``` + +When Hugo builds your site, the content will be output to the following destination: + +```txt + + url ("/posts/my-first-hugo-post/") + ⊢------------^----------⊣ + baseurl section slug +⊢--------^--------⊣⊢-^--⊣⊢-------^---------⊣ + permalink +⊢--------------------^---------------------⊣ +https://example.org/posts/my-first-hugo-post/index.html +``` + +## Paths explained + +The following concepts provide more insight into the relationship between your project's organization and the default Hugo behavior when building output for the website. + +### `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` + +The `slug` is the last segment of the URL path, defined by the file name and optionally overridden by a `slug` value in front matter. See [URL Management](/content-management/urls/#slug) for details. + +### `path` + +A content's `path` is determined by the section's path to the file. The file `path`: + +- Is based on the path to the content's location AND +- Does not include the slug + +### `url` + +The `url` is the entire URL path, defined by the file path and optionally overridden by a `url` value in front matter. See [URL Management](/content-management/urls/#slug) for details. + +[config]: /configuration/ +[pretty]: /content-management/urls/#appearance +[sections]: /content-management/sections/ +[page template]: /templates/types/#page diff --cc docs/content/en/content-management/page-bundles.md index f6a5cf771,000000000..a5bf9a3af mode 100644,000000..100644 --- a/docs/content/en/content-management/page-bundles.md +++ b/docs/content/en/content-management/page-bundles.md @@@ -1,145 -1,0 +1,145 @@@ +--- +title: Page bundles +description: Use page bundles to logically associate one or more resources with content. +categories: [] +keywords: [] +--- + +## Introduction + +A page bundle is a directory that encapsulates both content and associated resources. + +By way of example, this site has an "about" page and a "privacy" page: + +```text +content/ +├── about/ +│ ├── index.md +│ └── welcome.jpg +└── privacy.md +``` + +The "about" page is a page bundle. It logically associates a resource with content by bundling them together. Resources within a page bundle are [page resources], accessible with the [`Resources`] method on the `Page` object. + +Page bundles are either _leaf bundles_ or _branch bundles_. + +leaf bundle +: A _leaf bundle_ is a directory that contains an `index.md` file and zero or more resources. Analogous to a physical leaf, a leaf bundle is at the end of a branch. It has no descendants. + +branch bundle +: A _branch bundle_ is a directory that contains an `_index.md` file and zero or more resources. Analogous to a physical branch, a branch bundle may have descendants including leaf bundles and other branch bundles. Top-level directories with or without `_index.md` files are also branch bundles. This includes the home page. + +> [!note] +> In the definitions above and the examples below, the extension of the index file depends on the [content format](g). For example, use `index.md` for Markdown content, `index.html` for HTML content, `index.adoc` for AsciiDoc content, etc. + +## Comparison + +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` | + +Files with [resource type](g) `page` include content written in Markdown, HTML, AsciiDoc, Pandoc, reStructuredText, and Emacs Org Mode. In a leaf bundle, excluding the index file, these files are only accessible as page resources. In a branch bundle, these files are only accessible as content pages. + +## Leaf bundles + +A _leaf bundle_ is a directory that contains an `index.md` file and zero or more resources. Analogous to a physical leaf, a leaf bundle is at the end of a branch. It has no descendants. + +```text +content/ +├── about +│ └── index.md +├── posts +│ ├── my-post +│ │ ├── content-1.md +│ │ ├── content-2.md +│ │ ├── image-1.jpg +│ │ ├── image-2.png +│ │ └── index.md +│ └── my-other-post +│ └── index.md +└── another-section + ├── foo.md + └── not-a-leaf-bundle + ├── bar.md + └── another-leaf-bundle + └── index.md +``` + +There are four leaf bundles in the example above: + +about +: This leaf bundle does not contain any page resources. + +my-post +: This leaf bundle contains an index file, two resources of [resource type](g) `page`, and two resources of resource type `image`. + + - content-1, content-2 + + These are resources of resource type `page`, accessible via the [`Resources`] method on the `Page` object. Hugo will not render these as individual pages. + + - image-1, image-2 + + These are resources of resource type `image`, accessible via the `Resources` method on the `Page` object + +my-other-post +: This leaf bundle does not contain any page resources. + +another-leaf-bundle +: This leaf bundle does not contain any page resources. + +> [!note] +> Create leaf bundles at any depth within the `content` directory, but a leaf bundle may not contain another bundle. Leaf bundles do not have descendants. + +## Branch bundles + +A _branch bundle_ is a directory that contains an `_index.md` file and zero or more resources. Analogous to a physical branch, a branch bundle may have descendants including leaf bundles and other branch bundles. Top-level directories with or without `_index.md` files are also branch bundles. This includes the home page. + +```text +content/ +├── branch-bundle-1/ +│ ├── _index.md +│ ├── content-1.md +│ ├── content-2.md +│ ├── image-1.jpg +│ └── image-2.png +├── branch-bundle-2/ +│ ├── a-leaf-bundle/ +│ │ └── index.md +│ └── _index.md +└── _index.md +``` + +There are three branch bundles in the example above: + +home page +: This branch bundle contains an index file, two descendant branch bundles, and no resources. + +branch-bundle-1 +: This branch bundle contains an index file, two resources of [resource type](g) `page`, and two resources of resource type `image`. + +branch-bundle-2 +: This branch bundle contains an index file and a leaf bundle. + +> [!note] +> Create branch bundles at any depth within the `content` directory. Branch bundles may have descendants. + +## Headless bundles + +Use [build options] in front matter to create an unpublished leaf or branch bundle whose content and resources you can include in other pages. + +[`Resources`]: /methods/page/resources/ +[build options]: /content-management/build-options/ +[home]: /templates/types/#home +[page resources]: /content-management/page-resources/ +[section]: /templates/types/#section +[single]: /templates/types/#single +[taxonomy]: /templates/types/#taxonomy +[term]: /templates/types/#term diff --cc docs/content/en/content-management/page-resources.md index 204ca5301,000000000..e8991de6f mode 100644,000000..100644 --- a/docs/content/en/content-management/page-resources.md +++ b/docs/content/en/content-management/page-resources.md @@@ -1,297 -1,0 +1,299 @@@ +--- +title: Page resources +description: Use page resources to logically associate assets with a page. +categories: [] +keywords: [] +--- + +Page resources are only accessible from [page bundles](/content-management/page-bundles), those directories with `index.md` or +`_index.md` files at their root. Page resources are only available to the +page with which they are bundled. + +In this example, `first-post` is a page bundle with access to 10 page resources including audio, data, documents, images, and video. Although `second-post` is also a page bundle, it has no page resources and is unable to directly access the page resources associated with `first-post`. + +```text +content +└── post + ├── first-post + │ ├── images + │ │ ├── a.jpg + │ │ ├── b.jpg + │ │ └── c.jpg + │ ├── index.md (root of page bundle) + │ ├── latest.html + │ ├── manual.json + │ ├── notice.md + │ ├── office.mp3 + │ ├── pocket.mp4 + │ ├── rating.pdf + │ └── safety.txt + └── second-post + └── index.md (root of page bundle) +``` + +## Examples + +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. + +The following examples assume this content structure: + +```text +content/ +└── example/ + ├── data/ + │ └── books.json <-- page resource + ├── images/ + │ ├── a.jpg <-- page resource + │ └── b.jpg <-- page resource + ├── snippets/ + │ └── text.md <-- page resource + └── index.md +``` + +Render a single image, and throw an error if the file does not exist: + +```go-html-template +{{ $path := "images/a.jpg" }} +{{ with .Resources.Get $path }} + +{{ else }} + {{ errorf "Unable to get page resource %q" $path }} +{{ end }} +``` + +Render all images, resized to 300 px wide: + +```go-html-template +{{ range .Resources.ByType "image" }} + {{ with .Resize "300x" }} + + {{ end }} +{{ end }} +``` + +Render the markdown snippet: + +```go-html-template +{{ with .Resources.Get "snippets/text.md" }} + {{ .Content }} +{{ end }} +``` + +List the titles in the data file, and throw an error if the file does not exist. + +```go-html-template +{{ $path := "data/books.json" }} +{{ with .Resources.Get $path }} + {{ with . | transform.Unmarshal }} +

Books:

+
    + {{ range . }} +
  • {{ .title }}
  • + {{ end }} +
+ {{ end }} +{{ else }} + {{ errorf "Unable to get page resource %q" $path }} +{{ end }} +``` + +## Metadata + +The page resources' metadata is managed from the corresponding page's front matter with an array/table parameter named `resources`. You can batch assign values using [wildcards](https://tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm). + +> [!note] +> Resources of type `page` get `Title` etc. from their own front matter. + +name +: (`string`) Sets the value returned in `Name`. + +> [!note] +> The methods `Match`, `Get` and `GetMatch` use `Name` to match the resources. + +title +: (`string`) Sets the value returned in `Title` + +params +: (`map`) A map of custom key-value pairs. + +### Resources metadata example + ++ +{{< 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 +{{}} ++ + +From the example above: + +- `sunset.jpg` will receive a new `Name` and can now be found with `.GetMatch "header"`. +- `documents/photo_specs.pdf` will get the `photo` icon. +- `documents/checklist.pdf`, `documents/guide.pdf` and `documents/payment.docx` will get `Title` as set by `title`. +- Every `PDF` in the bundle except `documents/photo_specs.pdf` will get the `pdf` icon. +- All `PDF` files will get a new `Name`. The `name` parameter contains a special placeholder [`:counter`](#the-counter-placeholder-in-name-and-title), so the `Name` will be `pdf-file-1`, `pdf-file-2`, `pdf-file-3`. +- Every docx in the bundle will receive the `word` icon. + +> [!note] +> The order matters; only the first set values of the `title`, `name` and `params` keys will be used. Consecutive parameters will be set only for the ones not already set. In the above example, `.Params.icon` is first set to `"photo"` in `src = "documents/photo_specs.pdf"`. So that would not get overridden to `"pdf"` by the later set `src = "**.pdf"` rule. + +### The `:counter` placeholder in `name` and `title` + +The `:counter` is a special placeholder recognized in `name` and `title` parameters `resources`. + +The counter starts at 1 the first time they are used in either `name` or `title`. + +For example, if a bundle has the resources `photo_specs.pdf`, `other_specs.pdf`, `guide.pdf` and `checklist.pdf`, and the front matter has specified the `resources` as: + +{{< code-toggle file=content/inspections/engine/index.md fm=true >}} +title = 'Engine inspections' +[[resources]] + src = "*specs.pdf" + title = "Specification #:counter" +[[resources]] + src = "**.pdf" + name = "pdf-file-:counter" +{{}} + +the `Name` and `Title` will be assigned to the resource files as follows: + +| Resource file | `Name` | `Title` | +|-------------------|-------------------|-----------------------| +| checklist.pdf | `"pdf-file-1.pdf` | `"checklist.pdf"` | +| guide.pdf | `"pdf-file-2.pdf` | `"guide.pdf"` | +| other\_specs.pdf | `"pdf-file-3.pdf` | `"Specification #1"` | +| photo\_specs.pdf | `"pdf-file-4.pdf` | `"Specification #2"` | + +## Multilingual + +{{< new-in 0.123.0 />}} + +By default, with a multilingual single-host site, Hugo does not duplicate shared page resources when building the site. + +> [!note] +> This behavior is limited to Markdown content. Shared page resources for other [content formats] are copied into each language bundle. + +Consider this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = true + +[languages.de] +languageCode = 'de-DE' +languageName = 'Deutsch' +weight = 1 + +[languages.en] +languageCode = 'en-US' +languageName = 'English' +weight = 2 +{{< /code-toggle >}} + +And this content: + +```text +content/ +└── my-bundle/ + ├── a.jpg <-- shared page resource + ├── b.jpg <-- shared page resource + ├── c.de.jpg + ├── c.en.jpg + ├── index.de.md + └── index.en.md +``` + +With v0.122.0 and earlier, Hugo duplicated the shared page resources, creating copies for each language: + +```text +public/ +├── de/ +│ ├── my-bundle/ +│ │ ├── a.jpg <-- shared page resource +│ │ ├── b.jpg <-- shared page resource +│ │ ├── c.de.jpg +│ │ └── index.html +│ └── index.html +├── en/ +│ ├── my-bundle/ +│ │ ├── a.jpg <-- shared page resource (duplicate) +│ │ ├── b.jpg <-- shared page resource (duplicate) +│ │ ├── c.en.jpg +│ │ └── index.html +│ └── index.html +└── index.html + +``` + +With v0.123.0 and later, Hugo places the shared resources in the page bundle for the default content language: + +```text +public/ +├── de/ +│ ├── my-bundle/ +│ │ ├── a.jpg <-- shared page resource +│ │ ├── b.jpg <-- shared page resource +│ │ ├── c.de.jpg +│ │ └── index.html +│ └── index.html +├── en/ +│ ├── my-bundle/ +│ │ ├── c.en.jpg +│ │ └── index.html +│ └── index.html +└── index.html +``` + +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 [details](/configuration/markup/#renderhookslinkuseembedded). + +Although duplicating shared page resources is inefficient, you can enable this feature in your site configuration if desired: + +{{< code-toggle file=hugo >}} +[markup.goldmark] +duplicateResourceFiles = true +{{< /code-toggle >}} + +[`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 diff --cc docs/content/en/content-management/sections.md index d21aca71b,000000000..3dfad5bd4 mode 100644,000000..100644 --- a/docs/content/en/content-management/sections.md +++ b/docs/content/en/content-management/sections.md @@@ -1,139 -1,0 +1,139 @@@ +--- +title: Sections +description: Organize content into sections. + +categories: [] +keywords: [] +aliases: [/content/sections/] +--- + +## Overview + +{{% glossary-term "section" %}} + +```text +content/ +├── articles/ <-- section (top-level directory) +│ ├── 2022/ +│ │ ├── article-1/ +│ │ │ ├── cover.jpg +│ │ │ └── index.md +│ │ └── article-2.md +│ └── 2023/ +│ ├── article-3.md +│ └── article-4.md +├── products/ <-- section (top-level directory) +│ ├── product-1/ <-- section (has _index.md file) +│ │ ├── benefits/ <-- section (has _index.md file) +│ │ │ ├── _index.md +│ │ │ ├── benefit-1.md +│ │ │ └── benefit-2.md +│ │ ├── features/ <-- section (has _index.md file) +│ │ │ ├── _index.md +│ │ │ ├── feature-1.md +│ │ │ └── feature-2.md +│ │ └── _index.md +│ └── product-2/ <-- section (has _index.md file) +│ ├── benefits/ <-- section (has _index.md file) +│ │ ├── _index.md +│ │ ├── benefit-1.md +│ │ └── benefit-2.md +│ ├── features/ <-- section (has _index.md file) +│ │ ├── _index.md +│ │ ├── feature-1.md +│ │ └── feature-2.md +│ └── _index.md +├── _index.md +└── about.md +``` + +The example above has two top-level sections: articles and products. None of the directories under articles are sections, while all of the directories under products are sections. A section within a section is a known as a nested section or subsection. + +## Explanation + +Sections and non-sections behave differently. + - ||Sections|Non-sections ++ |Sections|Non-sections +:--|:-:|:-: +Directory names become URL segments|:heavy_check_mark:|:heavy_check_mark: +Have logical ancestors and descendants|:heavy_check_mark:|:x: +Have list pages|:heavy_check_mark:|:x: + +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 + +Hugo has a defined [lookup order] to determine which template to use when rendering a page. The [lookup rules] consider the top-level section name; subsection names are not considered when selecting a template. + +With the file structure from the [example above](#overview): + +Content directory|Section template +:--|:-- +`content/products`|`layouts/products/section.html` +`content/products/product-1`|`layouts/products/section.html` +`content/products/product-1/benefits`|`layouts/products/section.html` + +Content directory|Page template +:--|:-- +`content/products`|`layouts/products/page.html` +`content/products/product-1`|`layouts/products/page.html` +`content/products/product-1/benefits`|`layouts/products/page.html` + +If you need to use a different template for a subsection, specify `type` and/or `layout` in front matter. + +## Ancestors and descendants + +A section has one or more ancestors (including the home page), and zero or more descendants. With the file structure from the [example above](#overview): + +```text +content/products/product-1/benefits/benefit-1.md +``` + +The content file (benefit-1.md) has four ancestors: benefits, product-1, products, and the home page. This logical relationship allows us to use the `.Parent` and `.Ancestors` methods to traverse the site structure. + +For example, use the `.Ancestors` method to render breadcrumb navigation. + +```go-html-template {file="layouts/_partials/breadcrumb.html"} + +``` + +With this CSS: + +```css +.breadcrumb ol { + padding-left: 0; +} + +.breadcrumb li { + display: inline; +} + +.breadcrumb li:not(:last-child)::after { + content: "»"; +} +``` + +Hugo renders this, where each breadcrumb is a link to the corresponding page: + +```text +Home » Products » Product 1 » Benefits » Benefit 1 +``` + +[lookup order]: /templates/lookup-order/ +[lookup rules]: /templates/lookup-order/#lookup-rules diff --cc docs/content/en/content-management/shortcodes.md index 2c3f1e29f,000000000..07ad22568 mode 100644,000000..100644 --- a/docs/content/en/content-management/shortcodes.md +++ b/docs/content/en/content-management/shortcodes.md @@@ -1,230 -1,0 +1,230 @@@ +--- +title: Shortcodes +description: Use embedded, custom, or inline shortcodes to insert elements such as videos, images, and social media embeds into your content. +categories: [] +keywords: [] +aliases: [/extras/shortcodes/] +--- + +## Introduction + +{{% glossary-term shortcode %}} + +There are three types of shortcodes: embedded, custom, and inline. + +## Embedded + +Hugo's embedded shortcodes are pre-defined templates within the application. Refer to each shortcode's documentation for specific usage instructions and available arguments. + +{{% list-pages-in-section path=/shortcodes %}} + +## 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") }} + +{{ end }} +``` + +Then call the shortcode from within markup: + +```text {file="content/example.md"} +{{}} +``` + +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] +enableInlineShortcodes = true +{{< /code-toggle >}} + +For more information see [configure security](/configuration/security). + +The following example demonstrates an inline shortcode, `date.inline`, that accepts a single positional argument: a date/time [layout string]. + +```text {file="content/example.md"} +Today is +{{}} + {{- now | time.Format (.Get 0) -}} +{{}}. + +Today is {{}}. +``` + +In the example above, the inline shortcode is executed twice: once upon definition and again when subsequently called. Hugo renders this to: + +```html +

Today is Jan 30, 2025.

+

Today is Thursday, January 30, 2025

+``` + - 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. + +Learn more about creating shortcodes in the [shortcode templates] section. + +## Calling + +Shortcode calls involve three syntactical elements: tags, arguments, and notation. + +### Tags + +Some shortcodes expect content between opening and closing tags. For example, the embedded [`details`] shortcode requires an opening and closing tag: + +```text +{{}} +This is a **bold** word. +{{}} +``` + +Some shortcodes do not accept content. For example, the embedded [`instagram`] shortcode requires a single _positional_ argument: + +```text +{{}} +``` + +Some shortcodes optionally accept content. For example, you can call the embedded [`qr`] shortcode with content: + +```text +{{}} +https://gohugo.io +{{}} +``` + +Or use the self-closing syntax with a trailing slash to pass the text as an argument: + +```text +{{}} +``` + +Refer to each shortcode's documentation for specific usage instructions and available arguments. + +### Arguments + +Shortcode arguments can be either _named_ or _positional_. + +Named arguments are passed as case-sensitive key-value pairs, as seen in this example with the embedded [`figure`] shortcode. The `src` argument, for instance, is required. + +```text +{{}} +``` + +Positional arguments, on the other hand, are determined by their position. The embedded `instagram` shortcode, for example, expects the first argument to be the Instagram post ID. + +```text +{{}} +``` + +Shortcode arguments are space-delimited, and arguments with internal spaces must be quoted. + +```text +{{}} +``` + +Shortcodes accept [scalar](g) arguments, one of [string](g), [integer](g), [floating point](g), or [boolean](g). + +```text +{{}} +``` + +You can optionally use multiple lines when providing several arguments to a shortcode for better readability: + +```text +{{}} +``` + +Use a [raw string literal](g) if you need to pass a multiline string: + +```text +{{HTML, +and a new line with a "quoted string".` */>}} +``` + +Shortcodes can accept named arguments, positional arguments, or both, but you must use either named or positional arguments exclusively within a single shortcode call; mixing them is not allowed. + +Refer to each shortcode's documentation for specific usage instructions and available arguments. + +### Notation + +Shortcodes can be called using two different notations, distinguished by their tag delimiters. + +Notation|Example +:--|:-- +Markdown|`{{%/* foo */%}} ## Section 1 {{%/* /foo */%}}` +Standard|`{{}} ## Section 2 {{}}` + +#### Markdown notation + +Hugo processes the shortcode before the page content is rendered by the Markdown renderer. This means, for instance, that Markdown headings inside a Markdown-notation shortcode will be included when invoking the [`TableOfContents`] method on the `Page` object. + +#### Standard notation + +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 }} +``` + +And this markdown: + +```text {file="content/example.md"} +{{%/* foo */%}} ## Section 1 {{%/* /foo */%}} + +{{}} ## Section 2 {{}} +``` + +Hugo renders this HTML: + +```html +

Section 1

+ +## Section 2 +``` + +In the above, "Section 1" will be included when invoking the `TableOfContents` method, while "Section 2" will not. + +The shortcode author determines which notation to use. Consult each shortcode's documentation for specific usage instructions and available arguments. + +## Nesting + +Shortcodes (excluding [inline](#inline) shortcodes) can be nested, creating parent-child relationships. For example, a gallery shortcode might contain several image shortcodes: + +```text {file="content/example.md"} +{{}} + {{}} + {{}} + {{}} +{{}} +``` + +The [shortcode templates][nesting] section provides a detailed explanation and examples. + +[`details`]: /shortcodes/details +[`figure`]: /shortcodes/figure +[`instagram`]: /shortcodes/instagram +[`qr`]: /shortcodes/qr +[`TableOfContents`]: /methods/page/tableofcontents/ +[layout string]: /functions/time/format/#layout-string +[nesting]: /templates/shortcode/#nesting +[shortcode method]: /templates/shortcode/#methods +[shortcode templates]: /templates/shortcode/ diff --cc docs/content/en/content-management/taxonomies.md index 6caf70b0c,000000000..12d96170e mode 100644,000000..100644 --- a/docs/content/en/content-management/taxonomies.md +++ b/docs/content/en/content-management/taxonomies.md @@@ -1,180 -1,0 +1,180 @@@ +--- +title: Taxonomies +description: Hugo includes support for user-defined taxonomies. +categories: [] +keywords: [] +aliases: [/taxonomies/overview/,/taxonomies/usage/,/indexes/overview/,/doc/indexes/,/extras/indexes] +--- + +## What is a taxonomy? + +Hugo includes support for user-defined groupings of content called **taxonomies**. Taxonomies are classifications of logical relationships between content. + +### Definitions + +Taxonomy +: A categorization that can be used to classify content + +Term +: A key within the taxonomy + +Value +: A piece of content assigned to a term + +## Example taxonomy: movie website + +Let's assume you are making a website about movies. You may want to include the following taxonomies: + +- Actors +- Directors +- Studios +- Genre +- 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 + +To continue with the example of a movie site, the following demonstrates content relationships from the perspective of the taxonomy: + +```txt +Actor <- Taxonomy + Bruce Willis <- Term + The Sixth Sense <- Value + Unbreakable <- Value + Moonrise Kingdom <- Value + Samuel L. Jackson <- Term + Unbreakable <- Value + The Avengers <- Value + xXx <- Value +``` + +From the perspective of the content, the relationships would appear differently, although the data and labels used are the same: + +```txt +Unbreakable <- Value + Actors <- Taxonomy + Bruce Willis <- Term + Samuel L. Jackson <- Term + Director <- Taxonomy + M. Night Shyamalan <- Term + ... +Moonrise Kingdom <- Value + Actors <- Taxonomy + Bruce Willis <- Term + Bill Murray <- Term + Director <- Taxonomy + Wes Anderson <- Term + ... +``` + +### 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 + +See [configure taxonomies](/configuration/taxonomies/). + +## Assign terms to content + +To assign one or more terms to a page, create a front matter field using the plural name of the taxonomy, then add terms to the corresponding array. For example: + +{{< code-toggle file=content/example.md fm=true >}} +title = 'Example' +tags = ['Tag A','Tag B'] +categories = ['Category A','Category B'] +{{< /code-toggle >}} + +## 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. + +### Example: taxonomic `weight` + +{{< code-toggle file=hugo >}} +title = "foo" +tags = [ "a", "b", "c" ] +tags_weight = 22 +categories = ["d"] +categories_weight = 44 +{{}} + +By using taxonomic weight, the same piece of content can appear in different positions in different taxonomies. + +## Metadata + +Display metadata about each term by creating a corresponding branch bundle in the `content` directory. + +For example, create an "authors" taxonomy: + +{{< code-toggle file=hugo >}} +[taxonomies] +author = 'authors' +{{< /code-toggle >}} + +Then create content with one [branch bundle](g) for each term: + +```text +content/ +└── authors/ + ├── jsmith/ + │ ├── _index.md + │ └── portrait.jpg + └── rjones/ + ├── _index.md + └── portrait.jpg +``` + +Then add front matter to each term page: + +{{< code-toggle file=content/authors/jsmith/_index.md fm=true >}} +title = "John Smith" +affiliation = "University of Chicago" +{{< /code-toggle >}} + - Then create a taxonomy template specific to the "authors" taxonomy: ++Then create a _taxonomy_ template specific to the "authors" taxonomy: + +```go-html-template {file="layouts/authors/taxonomy.html"} +{{ define "main" }} +

{{ .Title }}

+ {{ .Content }} + {{ range .Data.Terms.Alphabetical }} +

{{ .Page.LinkTitle }}

+

Affiliation: {{ .Page.Params.Affiliation }}

+ {{ with .Page.Resources.Get "portrait.jpg" }} + {{ with .Fill "100x100" }} + portrait + {{ end }} + {{ end }} + {{ end }} +{{ end }} +``` + +In the example above we list each author including their affiliation and portrait. + - Or create a term template specific to the "authors" taxonomy: ++Or create a _term_ template specific to the "authors" taxonomy: + +```go-html-template {file="layouts/authors/term.html"} +{{ define "main" }} +

{{ .Title }}

+

Affiliation: {{ .Params.affiliation }}

+ {{ with .Resources.Get "portrait.jpg" }} + {{ with .Fill "100x100" }} + portrait + {{ end }} + {{ end }} + {{ .Content }} + {{ range .Pages }} +

{{ .LinkTitle }}

+ {{ end }} +{{ end }} +``` + +In the example above we display the author including their affiliation and portrait, then a list of associated content. diff --cc docs/content/en/content-management/urls.md index a39afa6ef,000000000..2513614ee mode 100644,000000..100644 --- a/docs/content/en/content-management/urls.md +++ b/docs/content/en/content-management/urls.md @@@ -1,265 -1,0 +1,266 @@@ +--- +title: URL management +description: Control the structure and appearance of URLs through front matter entries and settings in your site configuration. +categories: [] +keywords: [] +aliases: [/extras/permalinks/,/extras/aliases/,/extras/urls/,/doc/redirects/,/doc/alias/,/doc/aliases/] +--- + +## Overview + +By default, when Hugo renders a page, the resulting URL matches the file path within the `content` directory. For example: + +```text +content/posts/post-1.md → https://example.org/posts/post-1/ +``` + +You can change the structure and appearance of URLs with front matter values and site configuration options. + +## Front matter + +### `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' +slug = 'my-first-post' +{{< /code-toggle >}} + +The resulting URL will be: + +```text +https://example.org/posts/my-first-post/ +``` + +### `url` + +Set the `url` in front matter to override the entire path. Use this with either regular pages or section pages. + +> [!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. + +If you set both `slug` and `url` in front matter, the `url` value takes precedence. + +#### Include a colon + +{{< new-in 0.136.0 />}} + +If you need to include a colon in the `url` front matter field, escape it with backslash characters. Use one backslash if you wrap the string within single quotes, or use two backslashes if you wrap the string within double quotes. With YAML front matter, use a single backslash if you omit quotation marks. + +For example, with this front matter: + +{{< code-toggle file=content/example.md fm=true >}} +title: Example +url: "my\\:example" +{{< /code-toggle >}} + +The resulting URL will be: + +```text +https://example.org/my:example/ +``` + +As described above, this will fail on Windows because the colon (`:`) is a reserved character. + +#### File extensions + +With this front matter: + +{{< code-toggle file=content/posts/post-1.md fm=true >}} +title = 'My First Article' +url = 'articles/my-first-article' +{{< /code-toggle >}} + +The resulting URL will be: + +```text +https://example.org/articles/my-first-article/ +``` + +If you include a file extension: + +{{< code-toggle file=content/posts/post-1.md fm=true >}} +title = 'My First Article' +url = 'articles/my-first-article.html' +{{< /code-toggle >}} + +The resulting URL will be: + +```text +https://example.org/articles/my-first-article.html +``` + +#### Leading slashes + +With monolingual sites, `url` values with or without a leading slash are relative to the [`baseURL`]. With multilingual sites, `url` values with a leading slash are relative to the `baseURL`, and `url` values without a leading slash are relative to the `baseURL` plus the language prefix. + +Site type|Front matter `url`|Resulting URL +:--|:--|:-- +monolingual|`/about`|`https://example.org/about/` +monolingual|`about`|`https://example.org/about/` +multilingual|`/about`|`https://example.org/about/` +multilingual|`about`|`https://example.org/de/about/` + +#### Permalinks tokens in front matter + +{{< new-in 0.131.0 />}} + +You can also use tokens when setting the `url` value. This is typically used in `cascade` sections: + +{{< code-toggle file=content/foo/bar/_index.md fm=true >}} +title ="Bar" +[[cascade]] + url = "/:sections[last]/:slug" +{{< /code-toggle >}} + +Use any of these tokens: + +{{% include "/_common/permalink-tokens.md" %}} + +## Site configuration + +### Permalinks + +See [configure permalinks](/configuration/permalinks). + +### Appearance + +See [configure ugly URLs](/configuration/ugly-urls/). + +### Post-processing + +Hugo provides two mutually exclusive configuration options to alter URLs _after_ it renders a page. + +#### Canonical URLs + +> [!caution] +> This is a legacy configuration option, superseded by template functions and Markdown render hooks, and will likely be [removed in a future release]. +{class="!mt-6"} + +If enabled, Hugo performs a search and replace _after_ it renders the page. It searches for site-relative URLs (those with a leading slash) associated with `action`, `href`, `src`, `srcset`, and `url` attributes. It then prepends the `baseURL` to create absolute URLs. + +```html + → + → +``` + +This is an imperfect, brute force approach that can affect content as well as HTML attributes. As noted above, this is a legacy configuration option that will likely be removed in a future release. + +To enable: + +{{< code-toggle file=hugo >}} +canonifyURLs = true +{{< /code-toggle >}} + +#### Relative URLs + +> [!caution] +> Do not enable this option unless you are creating a serverless site, navigable via the file system. +{class="!mt-6"} + +If enabled, Hugo performs a search and replace _after_ it renders the page. It searches for site-relative URLs (those with a leading slash) associated with `action`, `href`, `src`, `srcset`, and `url` attributes. It then transforms the URL to be relative to the current page. + +For example, when rendering `content/posts/post-1`: + +```html + → + → +``` + +This is an imperfect, brute force approach that can affect content as well as HTML attributes. As noted above, do not enable this option unless you are creating a serverless site. + +To enable: + +{{< code-toggle file=hugo >}} +relativeURLs = true +{{< /code-toggle >}} + +## Aliases + +Create redirects from old URLs to new URLs with aliases: + +- An alias with a leading slash is relative to the `baseURL` +- An alias without a leading slash is relative to the current directory + +### Examples {#alias-examples} + +Change the file name of an existing page, and create an alias from the previous URL to the new URL: + +{{< code-toggle file=content/posts/new-file-name.md fm=true >}} +aliases = ['/posts/previous-file-name'] +{{< /code-toggle >}} + +Each of these directory-relative aliases is equivalent to the site-relative alias above: + +- `previous-file-name` +- `./previous-file-name` +- `../posts/previous-file-name` + +You can create more than one alias to the current page: + +{{< code-toggle file=content/posts/new-file-name.md fm=true >}} +aliases = ['previous-file-name','original-file-name'] +{{< /code-toggle >}} + +In a multilingual site, use a directory-relative alias, or include the language prefix with a site-relative alias: + +{{< code-toggle file=content/posts/new-file-name.de.md fm=true >}} +aliases = ['/de/posts/previous-file-name'] +{{< /code-toggle >}} + +### How aliases work + +Using the first example above, Hugo generates the following site structure: + +```text +public/ +├── posts/ +│ ├── new-file-name/ +│ │ └── index.html +│ ├── previous-file-name/ +│ │ └── index.html +│ └── index.html +└── index.html +``` + +The alias from the previous URL to the new URL is a client-side redirect: + +```html {file="posts/previous-file-name/index.html"} + + + + https://example.org/posts/new-file-name/ + + + + + + +``` + +Collectively, the elements in the `head` section: + +- Tell search engines that the new URL is canonical +- Tell search engines not to index the previous URL +- Tell the browser to redirect to the new URL + +Hugo renders alias files before rendering pages. A new page with the previous file name will overwrite the alias, as expected. + +### Customize + +To override Hugo's embedded `alias` template, copy the [source code] to a file with the same name in the `layouts` directory. The template receives the following context: + +Permalink +: The link to the page being aliased. + +Page +: The Page data for the page being aliased. + +[`baseURL`]: /configuration/all/#baseurl +[removed in a future release]: https://github.com/gohugoio/hugo/issues/4733 +[reserved characters]: https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#naming-conventions +[source code]: {{% eturl alias %}} diff --cc docs/content/en/contribute/development.md index e2cfee4ff,000000000..5930fbf52 mode 100644,000000..100644 --- a/docs/content/en/contribute/development.md +++ b/docs/content/en/contribute/development.md @@@ -1,186 -1,0 +1,176 @@@ +--- +title: Development +description: Contribute to the development of Hugo. +categories: [] +keywords: [] +--- + +## Introduction + +You can contribute to the Hugo project by: + +- Answering questions on the [forum] +- Improving the [documentation] +- Monitoring the [issue queue] +- Creating or improving [themes] +- Squashing [bugs] + +Please submit documentation issues and pull requests to the [documentation repository]. + +If you have an idea for an enhancement or new feature, create a new topic on the [forum] in the "Feature" category. This will help you to: + +- Determine if the capability already exists +- Measure interest +- Refine the concept + +If there is sufficient interest, [create a proposal]. Do not submit a pull request until the project lead accepts the proposal. + +For a complete guide to contributing to Hugo, see the [Contribution Guide]. + +## Prerequisites + +To build the extended or extended/deploy edition from source you must: + +1. Install [Git] +1. Install [Go] version 1.23.0 or later +1. Install a C compiler, either [GCC] or [Clang] +1. Update your `PATH` environment variable as described in the [Go documentation] + +> [!note] +> See these [detailed instructions](https://discourse.gohugo.io/t/41370) to install GCC on Windows. + +## GitHub workflow + +> [!note] +> This section assumes that you have a working knowledge of Go, Git and GitHub, and are comfortable working on the command line. + +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 - ``` - - For a bug fix: - - ```sh - git checkout -b fix/fix-some-bug-99999 - ``` - - ### Step 4 - - Make changes. - - ### Step 5 - - Compile and install. ++Step 4 ++: Make changes. + - To compile and install the standard edition: ++Step 5 ++: Compile and install. + - ```text - go install - ``` - - To compile and install the extended edition: - - ```text - CGO_ENABLED=1 go install -tags extended - ``` - - 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 ++ To compile and install the extended edition: + - Test your changes: ++ ```text ++ CGO_ENABLED=1 go install -tags extended ++ ``` + - ```text - go test ./... - ``` ++ To compile and install the extended/deploy edition: + - ### Step 7 ++ ```text ++ CGO_ENABLED=1 go install -tags extended,withdeploy ++ ``` + - Commit your changes with a descriptive commit message: ++Step 6 ++: Test your changes: + - - 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 ++ go test ./... ++ ``` + - For example: ++Step 7 ++: Commit your changes with a descriptive commit message: + - ```sh - git commit -m "tpl/strings: Create wrap function ++ - 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. + - 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" - ``` ++ For example: + - ### Step 8 ++ ```sh ++ git commit -m "tpl/strings: Create wrap function + - Push the new branch to your fork of the documentation repository. ++ 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. + - ### Step 9 ++ Fixes #99998 ++ Closes #99999" ++ ``` + - Visit the [project repository] and create a pull request (PR). ++Step 8 ++: Push the new branch to your fork of the documentation repository. + - ### Step 10 ++Step 9 ++: Visit the [project repository] and create a pull request (PR). + - 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 + +You can build, install, and test Hugo at any point in its development history. The examples below build and install the extended edition of Hugo. + +To build and install the latest release: + +```sh +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: + +```sh +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 +[Clang]: https://clang.llvm.org/ +[commit message guidelines]: https://github.com/gohugoio/hugo/blob/master/CONTRIBUTING.md#git-commit-message-guidelines +[Contribution Guide]: https://github.com/gohugoio/hugo/blob/master/CONTRIBUTING.md +[create a proposal]: https://github.com/gohugoio/hugo/issues/new?labels=Proposal%2C+NeedsTriage&template=feature_request.md +[documentation]: /documentation +[documentation repository]: https://github.com/gohugoio/hugoDocs +[forum]: https://discourse.gohugo.io +[GCC]: https://gcc.gnu.org/ +[Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[Go]: https://go.dev/doc/install +[Go documentation]: https://go.dev/doc/code#Command +[issue queue]: https://github.com/gohugoio/hugo/issues +[issues]: https://github.com/gohugoio/hugo/issues +[project repository]: https://github.com/gohugoio/hugo/ +[themes]: https://themes.gohugo.io/ diff --cc docs/content/en/contribute/documentation.md index c72ddd03f,000000000..2ce2db169 mode 100644,000000..100644 --- a/docs/content/en/contribute/documentation.md +++ b/docs/content/en/contribute/documentation.md @@@ -1,531 -1,0 +1,535 @@@ +--- +title: Documentation +description: Help us to improve the documentation by identifying issues and suggesting changes. +categories: [] +keywords: [] +aliases: [/contribute/docs/] +--- + +## Introduction + +We welcome corrections and improvements to the documentation. The documentation lives in a separate repository from the main project. To contribute: + +- For corrections and improvements to existing documentation, submit issues and pull requests to the [documentation repository]. +- For documentation of new features, include the documentation changes in your pull request to the [project repository]. + +## Guidelines + +### Style + +Follow Google's [developer documentation style guide]. + +### Markdown + +Adhere to these Markdown conventions: + +- Use [ATX] headings (levels 2-4), not [setext] headings. +- Use [fenced code blocks], not [indented code blocks]. +- Use hyphens, not asterisks, for unordered [list items]. +- Use [callouts](#callouts) instead of bold text for emphasis. +- Do not mix [raw HTML] within Markdown. +- Do not use bold text in place of a heading or description term (`dt`). +- Remove consecutive blank lines. +- Remove trailing spaces. + +### Glossary + +[Glossary] terms are defined on individual pages, providing a central repository for definitions, though these pages are not directly linked from the site. + +Definitions must be complete sentences, with the first sentence defining the term. Italicize the first occurrence of the term and any referenced glossary terms for consistency. + +Link to glossary terms using this syntax: `[term](g)` + +Term lookups are case-insensitive, ignore formatting, and support singular and plural forms. For example, all of these variations will link to the same glossary term: + +```text +[global resource](g) +[Global Resource](g) +[Global Resources](g) +[`Global Resources`](g) +``` + +Use the [glossary-term shortcode](#glossary-term) to insert a term definition: + +```text +{{%/* glossary-term "global resource" */%}} +``` + +### Terminology + +Link to the [glossary] as needed and use terms consistently. Pay particular attention to: + +- "front matter" (two words, except when referring to the configuration key) +- "home page" (two words) +- "website" (one word) +- "standalone" (one word, no hyphen) +- "map" (instead of "dictionary") +- "flag" (instead of "option" for command-line flags) +- "client side" (noun), "client-side" (adjective) +- "server side" (noun), "server-side" (adjective) +- "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. +- Avoid formatted strings. +- Keep them concise. + +### Page descriptions + +When writing the page `description` use imperative present tense when possible. For example: + +{{< code-toggle file=content/en/functions/data/_index.md" fm=true >}} +title: Data functions +linkTitle: data +description: Use these functions to read local or remote data files. +{{< /code-toggle >}} + +### Writing style + +Use active voice and present tense wherever possible. + +No → With Hugo you can build a static site.\ +Yes → Build a static site with Hugo. + +No → This will cause Hugo to generate HTML files in the `public` directory.\ +Yes → Hugo generates HTML files in the `public` directory. + +Use second person instead of third person. + +No → Users should exercise caution when deleting files.\ +Better → You must be cautious when deleting files.\ +Best → Be cautious when deleting files. + +Minimize adverbs. + +No → Hugo is extremely fast.\ +Yes → Hugo is fast. + +> [!note] +> "It's an adverb, Sam. It's a lazy tool of a weak mind." (Outbreak, 1995). + +### Function and method descriptions + +Start descriptions in the functions and methods sections with "Returns", or for boolean values, "Reports whether". + +### File paths and names + +Enclose directory names, file names, and file paths in backticks, except when used in: + +- Page titles +- Section headings (h1-h6) +- Definition list terms +- The `description` field in front matter + +### Miscellaneous + +Other best practices: + +- Introduce lists with a sentence or phrase, not directly under a heading. +- Avoid bold text; use [callouts](#callouts) for emphasis. +- Do not put description terms (`dt`) in backticks unless syntactically necessary. +- Do not use Hugo's `ref` or `relref` shortcodes. +- Prioritize current best practices over multiple options or historical information. +- Use short, focused code examples. +- Use [basic english] where possible for a global audience. + +## Front matter fields + +This site uses the front matter fields listed in the table below. + +Of the four required fields, only `title` and `description` require data. + +```text +title: The title +description: The description +categories: [] +keywords: [] +``` + +This example demonstrates the minimum required front matter fields. + +If quotation marks are required, prefer single quotes to double quotes when possible. + +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|  ++`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|  + +[^1]: The field is required, but its data is not. + +## Related content + +When available, the "See also" sidebar displays related pages using Hugo's [related content] feature, based on front matter keywords. We ensure consistent keyword usage by validating them against `data/keywords.yaml` during the build process. If a keyword is not found, you'll be alerted and must either modify the keyword or update the data file. This validation process helps to refine the related content for better results. + +If the title in the "See also" sidebar is ambiguous or the same as another page, you can define an alternate title in the front matter: + +{{< code-toggle file=hugo >}} +title = "Long descriptive title" +linkTitle = "Short title" +[params] +alt_title = "Whatever you want" +{{< /code-toggle >}} + +Use of the alternate title is limited to the "See also" sidebar. + +> [!note] +> Think carefully before setting the `alt_title`. Use it only when absolutely necessary. + +## Code examples + +With examples of template code: + +- Indent with two spaces. +- Insert a space after an opening action delimiter. +- Insert a space before a closing action delimiter. +- Do not add white space removal syntax to action delimiters unless required. For example, inline elements like `img` and `a` require whitespace removal on both sides. + +```go-html-template +{{ if eq $foo $bar }} + {{ fmt.Printf "%s is %s" $foo $bar }} +{{ end }} +``` + +### Fenced code blocks + +Always specify the language. + +When providing a Mardown example, set the code language to "text" to prevent +erroneous lexing/highlighting of shortcode calls. + +````text +```go-html-template +{{ if eq $foo "bar" }} + {{ print "foo is bar" }} +{{ end }} +``` +```` + +To include a file name header and copy-to-clipboard button: + +````text +```go-html-template {file="layouts/_partials/foo.html" copy=true} +{{ if eq $foo "bar" }} + {{ print "foo is bar" }} +{{ end }} +``` +```` + +To wrap the code block within an initially-opened `details` element using a non-default summary: + +````text +```go-html-template {details=true open=true summary="layouts/_partials/foo.html" copy=true} +{{ if eq $foo "bar" }} + {{ print "foo is bar" }} +{{ end }} +``` +```` + +### Shortcode calls + +Use this syntax : + +````text +```text +{{}} +{{%/*/* foo */*/%}} +``` +```` + +### Site configuration + +Use the [code-toggle shortcode](#code-toggle) to include site configuration examples: + +```text +{{}} +baseURL = 'https://example.org/' +languageCode = 'en-US' +title = 'My Site' +{{}} +``` + +### Front matter + +Use the [code-toggle shortcode](#code-toggle) to include front matter examples: + +```text +{{}} +title = 'My first post' +date = 2023-11-09T12:56:07-08:00 +draft = false +{{}} +``` + +## Callouts + +To visually emphasize important information, use callouts (admonitions). Callout types are case-insensitive. Effective March 8, 2025, we utilize only three of the five available types. + +- note (272 instances) +- warning (2 instances) +- caution (1 instance) + +Limiting the number of callout types helps us to use them consistently. + +```text +> [!note] +> Useful information that users should know, even when skimming content. +``` + +> [!note] +> Useful information that users should know, even when skimming content. + +```text +> [!warning] +> Urgent info that needs immediate user attention to avoid problems. +``` + +> [!warning] +> Urgent info that needs immediate user attention to avoid problems. + +```text +> [!caution] +> Advises about risks or negative outcomes of certain actions. +``` + +> [!caution] +> Advises about risks or negative outcomes of certain actions. + +```text +> [!tip] +> Helpful advice for doing things better or more easily. +``` + +> [!tip] +> Helpful advice for doing things better or more easily. + +```text +> [!important] +> Key information users need to know to achieve their goal. +``` + +> [!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. + +### code-toggle + +Use the `code-toggle` shortcode to display examples of site configuration, front matter, or data files. This shortcode takes these arguments: + +config +: (`string`) The section of `site.Data.docs.config` to render. + +copy +: (`bool`) Whether to display a copy-to-clipboard button. Default is `false`. + +datakey: +: (`string`) The section of `site.Data.docs` to render. + +file +: (`string`) The file name to display above the rendered code. Omit the file extension for site configuration examples. + +fm +: (`bool`) Whether to render the code as front matter. Default is `false`. + +skipHeader +: (`bool`) Whether to omit top-level key(s) when rendering a section of `site.Data.docs.config`. + +```text +{{}} +baseURL = 'https://example.org/' +languageCode = 'en-US' +title = 'My Site' +{{}} +``` + +### deprecated-in + +Use the `deprecated-in` shortcode to indicate that a feature is deprecated: + +```text +{{}} + +Use [`hugo.IsServer`] instead. + +[`hugo.IsServer`]: /functions/hugo/isserver/ +{{}} +``` + +### eturl + +Use the embedded template URL (`eturl`) shortcode to insert an absolute URL to the source code for an embedded template. The shortcode takes a single argument, the base file name of the template (omit the file extension). + +```text +This is a link to the [embedded alias template]. + +[embedded alias template]: {{%/* eturl alias */%}} +``` + +### glossary-term + +Use the `glossary-term` shortcode to insert the definition of the given glossary term. + +```text +{{%/* glossary-term scalar */%}} +``` + +### include + +Use the `include` shortcode to include content from another page. + +```text +{{%/* include "_common/glob-patterns.md" */%}} +``` + +### new-in + +Use the `new-in` shortcode to indicate a new feature: + +```text +{{}} +``` + +You can also include details: + +```text +{{}} +This is a new feature. +{{}} +``` + +## New features + +Use the [new-in shortcode](#new-in) to indicate a new feature: + +```text +{{}} +``` + +The "new in" label will be hidden if the specified version is older than a predefined threshold, based on differences in major and minor versions. See [details](https://github.com/gohugoio/hugoDocs/blob/master/_vendor/github.com/gohugoio/gohugoioTheme/layouts/_shortcodes/new-in.html). + +## Deprecated features + +Use the [deprecated-in shorcode](#deprecated-in) shortcode to indicate that a feature is deprecated: + +```text +{{}} +Use [`hugo.IsServer`] instead. + +[`hugo.IsServer`]: /functions/hugo/isserver/ +{{}} +``` + +When deprecating a function or method, add something like this to front matter: + +{{< code-toggle file=content/something/foo.md fm=true >}} +expiryDate: 2027-02-17 # deprecated 2025-02-17 in v0.144.0 +{{< /code-toggle >}} + +Set the `expiryDate` to two years from the date of deprecation, and add a brief front matter comment to explain the setting. + +## GitHub workflow + +> [!note] +> This section assumes that you have a working knowledge of Git and GitHub, and are comfortable working on the command line. + +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 +[glossary]: /quick-reference/glossary/ +[indented code blocks]: https://spec.commonmark.org/current/#indented-code-blocks +[issues]: https://github.com/gohugoio/hugoDocs/issues +[list items]: https://spec.commonmark.org/current/#list-items +[project repository]: https://github.com/gohugoio/hugo +[raw HTML]: https://spec.commonmark.org/current/#raw-html +[related content]: /content-management/related-content/ +[setext]: https://spec.commonmark.org/current/#setext-heading diff --cc docs/content/en/functions/css/PostCSS.md index 9cc698248,000000000..4dce705be mode 100644,000000..100644 --- a/docs/content/en/functions/css/PostCSS.md +++ b/docs/content/en/functions/css/PostCSS.md @@@ -1,128 -1,0 +1,123 @@@ +--- +title: css.PostCSS +description: Processes the given resource with PostCSS using any PostCSS plugin. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [postCSS] + returnType: resource.Resource + signatures: ['css.PostCSS [OPTIONS] RESOURCE'] +--- + +{{< new-in 0.128.0 />}} + +```go-html-template +{{ with resources.Get "css/main.css" | postCSS }} + +{{ end }} +``` + +## Setup + +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 - ``` - - ### Step 3 - - Create a PostCSS configuration file in the root of your project. - - ```js {file="postcss.config.js"} - module.exports = { - plugins: [ - require('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]. ++ ```js {file="postcss.config.js"} ++ module.exports = { ++ plugins: [ ++ require('autoprefixer') ++ ] ++ }; ++ ``` + - ### Step 4 ++ > [!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]. + - Place your CSS file within the `assets/css` directory. ++Step 4 ++: Place your CSS file within the `assets/css` directory. + - ### Step 5 ++Step 5 ++: Process the resource with PostCSS: + - Process the resource with PostCSS: - - ```go-html-template - {{ with resources.Get "css/main.css" | postCSS }} - - {{ end }} - ``` ++ ```go-html-template ++ {{ with resources.Get "css/main.css" | postCSS }} ++ ++ {{ end }} ++ ``` + +## Options + +The `css.PostCSS` method takes an optional map of options. + +config +: (`string`) The directory that contains the PostCSS configuration file. Default is the root of the project directory. + +noMap +: (`bool`) Whether to disable inline source maps. Default is `false`. + +inlineImports +: (`bool`) Whether to enable inlining of import statements. It does so recursively, but will only import a file once. URL imports (e.g. `@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');`) and imports with media queries will be ignored. Note that this import routine does not care about the CSS spec, so you can have @import anywhere in the file. Hugo will look for imports relative to the module mount and will respect theme overrides. Default is `false`. + +skipInlineImportsNotFound +: (`bool`) Whether to allow the build process to continue despite unresolved import statements, preserving the original import declarations. If you have regular CSS imports in your CSS that you want to preserve, you can either use imports with URL or media queries (Hugo does not try to resolve those) or set this option to `true`. Default is `false`." + +```go-html-template +{{ $opts := dict "config" "config-directory" "noMap" true }} +{{ with resources.Get "css/main.css" | postCSS $opts }} + +{{ end }} +``` + +## No configuration file + +To avoid using a PostCSS configuration file, you can specify a minimal configuration using the options map. + +use +: (`string`) A space-delimited list of PostCSS plugins to use. + +parser +: (`string`) A custom PostCSS parser. + +stringifier +: (`string`) A custom PostCSS stringifier. + +syntax +: (`string`) Custom postcss syntax. + +```go-html-template +{{ $opts := dict "use" "autoprefixer postcss-color-alpha" }} +{{ with resources.Get "css/main.css" | postCSS $opts }} + +{{ end }} +``` + +## Check environment + +The current Hugo environment name (set by `--environment` or in configuration or OS environment) is available in the Node context, which allows constructs like this: + +```js +const autoprefixer = require('autoprefixer'); +module.exports = { + plugins: [ + process.env.HUGO_ENVIRONMENT !== 'development' ? autoprefixer : null + ] +} +``` + +[#7333]: https://github.com/gohugoio/hugo/issues/7333 +[Node.js]: https://nodejs.org/en +[PostCSS plugins]: https://postcss.org/docs/postcss-plugins +[this example]: https://github.com/postcss/postcss-load-config#packagejson diff --cc docs/content/en/functions/css/Sass.md index ae628a15f,000000000..4bce2fd06 mode 100644,000000..100644 --- a/docs/content/en/functions/css/Sass.md +++ b/docs/content/en/functions/css/Sass.md @@@ -1,204 -1,0 +1,152 @@@ +--- +title: css.Sass +description: Transpiles Sass to CSS. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [toCSS] + returnType: resource.Resource + signatures: ['css.Sass [OPTIONS] RESOURCE'] +--- + +{{< new-in 0.128.0 />}} + +Transpile Sass to CSS using the LibSass transpiler included in Hugo's extended and extended/deploy editions, or [install Dart Sass](#dart-sass) to use the latest features of the Sass language. + +Sass has two forms of syntax: [SCSS] and [indented]. Hugo supports both. + +[scss]: https://sass-lang.com/documentation/syntax#scss +[indented]: https://sass-lang.com/documentation/syntax#the-indented-syntax + +## Options + +enableSourceMap +: (`bool`) Whether to generate a source map. Default is `false`. + +includePaths +: (`slice`) A slice of paths, relative to the project root, that the transpiler will use when resolving `@use` and `@import` statements. + +outputStyle +: (`string`) The output style of the resulting CSS. With LibSass, one of `nested` (default), `expanded`, `compact`, or `compressed`. With Dart Sass, either `expanded` (default) or `compressed`. + +precision +: (`int`) The precision of floating point math. Applicable to LibSass. Default is `8`. + +silenceDeprecations +: {{< new-in 0.139.0 />}} +: (`slice`) A slice of deprecation IDs to silence. IDs are enclosed in brackets within Dart Sass warning messages (e.g., `import` in `WARN Dart Sass: DEPRECATED [import]`). Applicable to Dart Sass. Default is `false`. + +silenceDependencyDeprecations +: {{< new-in 0.146.0 />}} +: (`bool`) Whether to silence deprecation warnings from dependencies, where a dependency is considered any file transitively imported through a load path. This does not apply to `@warn` or `@debug` rules.Default is `false`. + +sourceMapIncludeSources +: (`bool`) Whether to embed sources in the generated source map. Applicable to Dart Sass. Default is `false`. + +targetPath +: (`string`) The publish path for the transformed resource, relative to the[`publishDir`]. If unset, the target path defaults to the asset's original path with a `.css` extension. + +transpiler +: (`string`) The transpiler to use, either `libsass` or `dartsass`. Hugo's extended and extended/deploy editions include the LibSass transpiler. To use the Dart Sass transpiler, see the [installation instructions](#dart-sass). Default is `libsass`. + +vars +: (`map`) A map of key-value pairs that will be available in the `hugo:vars` namespace. Useful for [initializing Sass variables from Hugo templates](https://discourse.gohugo.io/t/42053/). + + ```scss + // LibSass + @import "hugo:vars"; + + // Dart Sass + @use "hugo:vars" as v; + ``` + +## Example + +```go-html-template {copy=true} +{{ with resources.Get "sass/main.scss" }} + {{ $opts := dict + "enableSourceMap" hugo.IsDevelopment + "outputStyle" (cond hugo.IsDevelopment "expanded" "compressed") + "targetPath" "css/main.css" + "transpiler" "dartsass" + "vars" site.Params.styles + "includePaths" (slice "node_modules/bootstrap/scss") + }} + {{ with . | toCSS $opts }} + {{ if hugo.IsDevelopment }} + + {{ else }} + {{ with . | fingerprint }} + + {{ end }} + {{ end }} + {{ end }} +{{ end }} +``` + +## Dart Sass + +Hugo's extended and extended/deploy editions include [LibSass] to transpile Sass to CSS. In 2020, the Sass team deprecated LibSass in favor of [Dart Sass]. + +Use the latest features of the Sass language by installing Dart Sass in your development and production environments. + +### Installation overview + +Dart Sass is compatible with Hugo v0.114.0 and later. + +If you have been using Embedded Dart Sass[^1] with Hugo v0.113.0 and earlier, uninstall Embedded Dart Sass, then install Dart Sass. If you have installed both, Hugo will use Dart Sass. + +If you install Hugo as a [Snap package] there is no need to install Dart Sass. The Hugo Snap package includes Dart Sass. + +[^1]: In 2023, the Sass team deprecated Embedded Dart Sass in favor of Dart Sass. + +### Installing in a development environment + +When you install Dart Sass somewhere in your PATH, Hugo will find it. + +OS|Package manager|Site|Installation +:--|:--|:--|:-- +Linux|Homebrew|[brew.sh]|`brew install sass/sass/sass` +Linux|Snap|[snapcraft.io]|`sudo snap install dart-sass` +macOS|Homebrew|[brew.sh]|`brew install sass/sass/sass` +Windows|Chocolatey|[chocolatey.org]|`choco install sass` +Windows|Scoop|[scoop.sh]|`scoop install sass` + +You may also install [prebuilt binaries] for Linux, macOS, and Windows. You must install the prebuilt binary outside of your project directory and ensure its path is included in your system's PATH environment variable. + +Run `hugo env` to list the active transpilers. + +> [!note] +> If you build Hugo from source and run `mage test -v`, the test will fail if you install Dart Sass as a Snap package. This is due to the Snap package's strict confinement model. + +### 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 - ``` - - #### 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 - ``` ++For examples of how to install Dart Sass in a production environment, see the following workflow files: + - #### 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 diff --cc docs/content/en/functions/css/TailwindCSS.md index 9d40ad0aa,000000000..e8514679b mode 100644,000000..100644 --- a/docs/content/en/functions/css/TailwindCSS.md +++ b/docs/content/en/functions/css/TailwindCSS.md @@@ -1,122 -1,0 +1,116 @@@ +--- +title: css.TailwindCSS +description: Processes the given resource with the Tailwind CSS CLI. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: ['css.TailwindCSS [OPTIONS] RESOURCE'] +--- + +{{< new-in 0.128.0 />}} + +Use the `css.TailwindCSS` function to process your Tailwind CSS files. This function uses the Tailwind CSS CLI to: + +1. Scan your templates for Tailwind CSS utility class usage. +1. Compile those utility classes into standard CSS. +1. Generate an optimized CSS output file. + +> [!note] +> Use this function with Tailwind CSS v4.0 and later, which require a relatively [modern browser] to render correctly. + +[modern browser]: https://tailwindcss.com/docs/compatibility#browser-support + +## Setup + - ### Step 1 - - Install the Tailwind CSS CLI v4.0 or later: - - ```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. - - - [standalone executable]: https://github.com/tailwindlabs/tailwindcss/releases/latest - - ### Step 2 - - Add this to your site configuration: - - {{< 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 3 - - 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 }} - - {{ else }} - {{ with . | fingerprint }} - ++Step 1 ++: Install the Tailwind CSS CLI v4.0 or later: ++ ++ ```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. ++ ++ [standalone executable]: https://github.com/tailwindlabs/tailwindcss/releases/latest ++ ++Step 2 ++: Add this to your site configuration: ++ ++ {{< 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 3 ++: 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 }} ++ ++ {{ else }} ++ {{ with . | fingerprint }} ++ ++ {{ end }} + {{ end }} + {{ end }} + {{ end }} - {{ end }} - ``` - - ### Step 5 ++ ``` + - Call the partial template from your base template, deferring template execution until after all sites and output formats have been rendered: ++Step 5 ++: 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} - - ... - {{ with (templates.Defer (dict "key" "global")) }} - {{ partial "css.html" . }} - {{ end }} - ... - - ``` ++ ```go-html-template {file="layouts/baseof.html" copy=true} ++ ++ ... ++ {{ with (templates.Defer (dict "key" "global")) }} ++ {{ partial "css.html" . }} ++ {{ end }} ++ ... ++ ++ ``` + +## Options + +minify +: (`bool`) Whether to optimize and minify the output. Default is `false`. + +optimize +: (`bool`) Whether to optimize the output without minifying. Default is `false`. + +disableInlineImports +: {{< new-in 0.147.4 />}} +: (`bool`) Whether to disable inlining of `@import` statements. Inlining is performed recursively, but currently once only per file. It is not possible to import the same file in different scopes (root, media query, etc.). Note that this import routine does not care about the CSS specification, so you can have `@import` statements anywhere in the file. Default is `false`. + +skipInlineImportsNotFound +: (`bool`) Whether to allow the build process to continue despite unresolved import statements, preserving the original import declarations. It is important to note that the inline importer does not process URL-based imports or those with media queries, and these will remain unaltered even when this option is disabled. Default is `false`. diff --cc docs/content/en/functions/data/GetCSV.md index 39c71b06c,000000000..8d3f8a7d9 mode 100644,000000..100644 --- a/docs/content/en/functions/data/GetCSV.md +++ b/docs/content/en/functions/data/GetCSV.md @@@ -1,144 -1,0 +1,145 @@@ +--- +title: data.GetCSV +description: Returns an array of arrays from a local or remote CSV file, or an error if the file does not exist. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [getCSV] + returnType: '[][]string' + signatures: ['data.GetCSV SEPARATOR INPUT... [OPTIONS]'] +expiryDate: 2026-02-19 # deprecated 2024-02-19 in v0.123.0 +--- + +{{< deprecated-in 0.123.0 >}} +Instead, use [`transform.Unmarshal`] with a [global resource](g), [page resource](g), or [remote resource](g). + +See the [remote data example]. + +[`transform.Unmarshal`]: /functions/transform/unmarshal/ +[remote data example]: /functions/resources/getremote/#remote-data +{{< /deprecated-in >}} + +Given the following directory structure: + +```text +my-project/ +└── other-files/ + └── pets.csv +``` + +Access the data with either of the following: + +```go-html-template +{{ $data := getCSV "," "other-files/pets.csv" }} +{{ $data := getCSV "," "other-files/" "pets.csv" }} +``` + +> [!note] +> When working with local data, the file path is relative to the working directory. +> +> You must not place CSV files in the project's `data` directory. + +Access remote data with either of the following: + +```go-html-template +{{ $data := getCSV "," "https://example.org/pets.csv" }} +{{ $data := getCSV "," "https://example.org/" "pets.csv" }} +``` + +The resulting data structure is an array of arrays: + +```json +[ + ["name","type","breed","age"], + ["Spot","dog","Collie","3"], + ["Felix","cat","Malicious","7"] +] +``` + +## Options + +Add headers to the request by providing an options map: + +```go-html-template +{{ $opts := dict "Authorization" "Bearer abcd" }} +{{ $data := getCSV "," "https://example.org/pets.csv" $opts }} +``` + +Add multiple headers using a slice: + +```go-html-template +{{ $opts := dict "X-List" (slice "a" "b" "c") }} +{{ $data := getCSV "," "https://example.org/pets.csv" $opts }} +``` + +## Global resource alternative + +Consider using the [`resources.Get`] function with [`transform.Unmarshal`] when accessing a global resource. + +```text +my-project/ +└── assets/ + └── data/ + └── pets.csv +``` + +```go-html-template +{{ $data := dict }} +{{ $p := "data/pets.csv" }} +{{ with resources.Get $p }} + {{ $opts := dict "delimiter" "," }} + {{ $data = . | transform.Unmarshal $opts }} +{{ else }} + {{ errorf "Unable to get resource %q" $p }} +{{ end }} +``` + +## 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/ +└── content/ + └── posts/ + └── my-pets/ + ├── index.md + └── pets.csv +``` + +```go-html-template +{{ $data := dict }} +{{ $p := "pets.csv" }} +{{ with .Resources.Get $p }} + {{ $opts := dict "delimiter" "," }} + {{ $data = . | transform.Unmarshal $opts }} +{{ else }} + {{ errorf "Unable to get resource %q" $p }} +{{ end }} +``` + +## Remote resource alternative + +Consider using the [`resources.GetRemote`] function with [`transform.Unmarshal`] when accessing a remote resource to improve error handling and cache control. + +```go-html-template +{{ $data := dict }} +{{ $url := "https://example.org/pets.csv" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else with .Value }} + {{ $opts := dict "delimiter" "," }} + {{ $data = . | transform.Unmarshal $opts }} + {{ else }} + {{ errorf "Unable to get remote resource %q" $url }} + {{ end }} +{{ end }} +``` + - [`Resources.Get`]: /methods/page/resources/ +[`resources.GetRemote`]: /functions/resources/getremote/ - [`resources.Get`]: /functions/resources/get/ ++ ++ +[`transform.Unmarshal`]: /functions/transform/unmarshal/ ++ diff --cc docs/content/en/functions/data/GetJSON.md index 9cdea9287,000000000..d3aafe94d mode 100644,000000..100644 --- a/docs/content/en/functions/data/GetJSON.md +++ b/docs/content/en/functions/data/GetJSON.md @@@ -1,146 -1,0 +1,147 @@@ +--- +title: data.GetJSON +description: Returns a JSON object from a local or remote JSON file, or an error if the file does not exist. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [getJSON] + returnType: any + signatures: ['data.GetJSON INPUT... [OPTIONS]'] +expiryDate: 2026-02-19 # deprecated 2024-02-19 in v0.123.0 +--- + +{{< deprecated-in 0.123.0 >}} +Instead, use [`transform.Unmarshal`] with a [global resource](g), [page resource](g), or [remote resource](g). + +See the [remote data example]. + +[`transform.Unmarshal`]: /functions/transform/unmarshal/ +[remote data example]: /functions/resources/getremote/#remote-data +{{< /deprecated-in >}} + +Given the following directory structure: + +```text +my-project/ +└── other-files/ + └── books.json +``` + +Access the data with either of the following: + +```go-html-template +{{ $data := getJSON "other-files/books.json" }} +{{ $data := getJSON "other-files/" "books.json" }} +``` + +> [!note] +> When working with local data, the file path is relative to the working directory. + +Access remote data with either of the following: + +```go-html-template +{{ $data := getJSON "https://example.org/books.json" }} +{{ $data := getJSON "https://example.org/" "books.json" }} +``` + +The resulting data structure is a JSON object: + +```json +[ + { + "author": "Victor Hugo", + "rating": 5, + "title": "Les Misérables" + }, + { + "author": "Victor Hugo", + "rating": 4, + "title": "The Hunchback of Notre Dame" + } +] +``` + +## Options + +Add headers to the request by providing an options map: + +```go-html-template +{{ $opts := dict "Authorization" "Bearer abcd" }} +{{ $data := getJSON "https://example.org/books.json" $opts }} +``` + +Add multiple headers using a slice: + +```go-html-template +{{ $opts := dict "X-List" (slice "a" "b" "c") }} +{{ $data := getJSON "https://example.org/books.json" $opts }} +``` + +## 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/ +└── assets/ + └── data/ + └── books.json +``` + +```go-html-template +{{ $data := dict }} +{{ $p := "data/books.json" }} +{{ with resources.Get $p }} + {{ $data = . | transform.Unmarshal }} +{{ else }} + {{ errorf "Unable to get resource %q" $p }} +{{ end }} +``` + +## 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/ +└── content/ + └── posts/ + └── reading-list/ + ├── books.json + └── index.md +``` + +```go-html-template +{{ $data := dict }} +{{ $p := "books.json" }} +{{ with .Resources.Get $p }} + {{ $data = . | transform.Unmarshal }} +{{ else }} + {{ errorf "Unable to get resource %q" $p }} +{{ end }} +``` + +## Remote resource alternative + +Consider using the [`resources.GetRemote`] function with [`transform.Unmarshal`] when accessing a remote resource to improve error handling and cache control. + +```go-html-template +{{ $data := dict }} +{{ $url := "https://example.org/books.json" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else with .Value }} + {{ $data = . | transform.Unmarshal }} + {{ else }} + {{ errorf "Unable to get remote resource %q" $url }} + {{ end }} +{{ end }} +``` + - [`Resources.Get`]: /methods/page/resources/ +[`resources.GetRemote`]: /functions/resources/getremote/ - [`resources.Get`]: /functions/resources/get/ ++ ++ +[`transform.Unmarshal`]: /functions/transform/unmarshal/ ++ diff --cc docs/content/en/functions/encoding/Jsonify.md index 1d60dd68d,000000000..5bbbf1446 mode 100644,000000..100644 --- a/docs/content/en/functions/encoding/Jsonify.md +++ b/docs/content/en/functions/encoding/Jsonify.md @@@ -1,34 -1,0 +1,34 @@@ +--- +title: encoding.Jsonify +description: Encodes the given object to JSON. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [jsonify] + returnType: template.HTML + signatures: ['encoding.Jsonify [OPTIONS] INPUT'] +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 }} +{{ dict "title" .Title "content" .Plain | jsonify (dict "indent" " ") }} +{{ dict "title" .Title "content" .Plain | jsonify (dict "prefix" " " "indent" " ") }} +``` + +## Options + +indent +: (`string`) Indentation to use. Default is "". + +prefix +: (`string`) Indentation prefix. Default is "". + +noHTMLEscape +: (`bool`) Whether to disable escaping of problematic HTML characters inside JSON quoted strings. The default behavior is to escape `&`, `<`, and `>` to `\u0026`, `\u003c`, and `\u003e` to avoid certain safety problems that can arise when embedding JSON in HTML. Default is `false`. diff --cc docs/content/en/functions/global/page.md index 40f6aba8f,000000000..a7672d947 mode 100644,000000..100644 --- a/docs/content/en/functions/global/page.md +++ b/docs/content/en/functions/global/page.md @@@ -1,100 -1,0 +1,100 @@@ +--- +title: page +description: Provides global access to a Page object. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [page] +aliases: [/functions/page] +--- + +At the top level of a template that receives a `Page` object in context, these are equivalent: + +```go-html-template +{{ .Params.foo }} +{{ .Page.Params.foo }} +{{ page.Params.foo }} +``` + +When a `Page` object is not in context, you can use the global `page` function: + +```go-html-template +{{ page.Params.foo }} +``` + +> [!note] +> Do not use the global `page` function in shortcodes, partials called by shortcodes, or cached partials. See [warnings](#warnings) below. + +## Explanation + +Hugo almost always passes a `Page` as the data context into the top-level template (e.g., `baseof.html`). The one exception is the multihost sitemap template. This means that you can access the current page with the `.` in the template. + +But when you are deeply nested inside of a [content view](g), [partial](g), or [render hook](g), it is not always practical or possible to access the `Page` object. + +Use the global `page` function to access the `Page` object from anywhere in any template. + +## Warnings + +### Be aware of top-level context + +The global `page` function accesses the `Page` object passed into the top-level template. + +With this content structure: + +```text +content/ +├── posts/ +│ ├── post-1.md +│ ├── post-2.md +│ └── post-3.md +└── _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 }} + {{ end }} +{{ end }} +``` + +The rendered output will be: + +```text +My Home Page +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 + +Do not use the global `page` function in: + +- Shortcodes +- Partials called by shortcodes +- Partials cached by the [`partialCached`] function + +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 }} +

{{ .LinkTitle }}

+ {{ .Summary }} +{{ end }} +``` + +When you call the [`Summary`] method, Hugo renders the page content including shortcodes. In this case, within a shortcode, the global `page` function accesses the `Page` object of the section page, not the content page. + +If Hugo renders the section page before a content page, the cached rendered shortcode will be incorrect. You cannot control the rendering sequence due to concurrency. + +[`partialCached`]: /functions/partials/includecached/ +[`Summary`]: /methods/page/summary/ diff --cc docs/content/en/functions/go-template/block.md index 383a3d72e,000000000..d603a1f89 mode 100644,000000..100644 --- a/docs/content/en/functions/go-template/block.md +++ b/docs/content/en/functions/go-template/block.md @@@ -1,53 -1,0 +1,54 @@@ +--- +title: block +description: Defines a template and executes it in place. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [block NAME CONTEXT] +--- + +A block is shorthand for defining a template: + +```go-html-template +{{ define "name" }} T1 {{ end }} +``` + +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"} + +
+ {{ block "main" . }} + {{ print "default value if 'main' template is empty" }} + {{ end }} +
+ +``` + +```go-html-template {file="layouts/page.html"} +{{ define "main" }} +

{{ .Title }}

+ {{ .Content }} +{{ end }} +``` + +```go-html-template {file="layouts/section.html"} +{{ define "main" }} +

{{ .Title }}

+ {{ .Content }} + {{ range .Pages }} +

{{ .LinkTitle }}

+ {{ end }} +{{ end }} +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} diff --cc docs/content/en/functions/go-template/define.md index 40d495bd9,000000000..e4939057f mode 100644,000000..100644 --- a/docs/content/en/functions/go-template/define.md +++ b/docs/content/en/functions/go-template/define.md @@@ -1,63 -1,0 +1,50 @@@ +--- +title: define +description: Defines a template. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [define NAME] +--- + +Use with the [`block`] statement: + +```go-html-template +{{ block "main" . }} + {{ print "default value if 'main' template is empty" }} +{{ end }} + +{{ define "main" }} +

{{ .Title }}

+ {{ .Content }} +{{ end }} +``` + +Use with the [`partial`] function: + +```go-html-template +{{ partial "inline/foo.html" (dict "answer" 42) }} + +{{ define "_partials/inline/foo.html" }} + {{ printf "The answer is %v." .answer }} +{{ end }} +``` + +Use with the [`template`] function: + +```go-html-template +{{ template "foo" (dict "answer" 42) }} + +{{ define "foo" }} + {{ printf "The answer is %v." .answer }} +{{ 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"} -
This div element broke your template.
- {{ define "main" }} -

{{ .Title }}

- {{ .Content }} - {{ end }} - - ``` - +{{% 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 diff --cc docs/content/en/functions/go-template/range.md index 50f714140,000000000..3c50068f1 mode 100644,000000..100644 --- a/docs/content/en/functions/go-template/range.md +++ b/docs/content/en/functions/go-template/range.md @@@ -1,219 -1,0 +1,222 @@@ +--- +title: range +description: Iterates over a non-empty collection, binds context (the dot) to successive elements, and executes the block. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [range COLLECTION] +aliases: [/functions/range] +--- + +The collection may be a slice, a map, or an integer. + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + {{ . }} → foo bar baz +{{ end }} +``` + +Use with the [`else`] statement: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} +

{{ . }}

+{{ else }} +

The collection is empty

+{{ end }} +``` + +Within a range block: + +- Use the [`continue`] statement to stop the innermost iteration and continue to the next iteration +- Use the [`break`] statement to stop the innermost iteration and bypass all remaining iterations + +## 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: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + {{ .Title }} +{{ end }} +``` + +Hugo will throw an error: + +```text +can't evaluate field Title in type int +``` + +The error occurs because we are trying to use the `.Title` method on a string instead of a `Page` object. Within the `range` block, if we want to render the page title, we need to get the context passed into the template. + +> [!note] +> Use the `$` to get the context passed into the template. + +This template will render the page title three times: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + {{ $.Title }} +{{ end }} +``` + +> [!note] +> Gaining a thorough understanding of context is critical for anyone writing template code. + +## Examples + +### Slice of scalars + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} +

{{ . }}

+{{ end }} +``` + +Is rendered to: + +```html +

foo

+

bar

+

baz

+``` + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $v := $s }} +

{{ $v }}

+{{ end }} +``` + +Is rendered to: + +```html +

foo

+

bar

+

baz

+``` + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $k, $v := $s }} +

{{ $k }}: {{ $v }}

+{{ end }} +``` + +Is rendered to: + +```html +

0: foo

+

1: bar

+

2: baz

+``` + +### Slice of maps + +This template code: + +```go-html-template +{{ $m := slice + (dict "name" "John" "age" 30) + (dict "name" "Will" "age" 28) + (dict "name" "Joey" "age" 24) +}} +{{ range $m }} +

{{ .name }} is {{ .age }}

+{{ end }} +``` + +Is rendered to: + +```html +

John is 30

+

Will is 28

+

Joey is 24

+``` + +### Slice of pages + +This template code: + +```go-html-template +{{ range where site.RegularPages "Type" "articles" }} +

{{ .LinkTitle }}

+{{ end }} +``` + +Is rendered to: + +```html +

Article 3

+

Article 2

+

Article 1

+``` + +### Maps + +This template code: + +```go-html-template +{{ $m := dict "name" "John" "age" 30 }} +{{ range $k, $v := $m }} +

key = {{ $k }} value = {{ $v }}

+{{ end }} +``` + +Is rendered to: + +```go-html-template +

key = age value = 30

+

key = name value = John

+``` + +Unlike ranging over an array or slice, Hugo sorts by key when ranging over a map. + +### Integers + +{{< new-in 0.123.0 />}} + +Ranging over a positive integer `n` executes the block `n` times, with the context starting at zero and incrementing by one in each iteration. + +```go-html-template +{{ $s := slice }} +{{ range 1 }} + {{ $s = $s | append . }} +{{ end }} +{{ $s }} → [0] +``` + +```go-html-template +{{ $s := slice }} +{{ range 3 }} + {{ $s = $s | append . }} +{{ end }} +{{ $s }} → [0 1 2] +``` + +Ranging over a non-positive integer executes the block zero times. + +{{% include "/_common/functions/go-template/text-template.md" %}} + +[`break`]: /functions/go-template/break/ +[`continue`]: /functions/go-template/continue/ +[`else`]: /functions/go-template/else/ ++[context]: /templates/introduction/#context diff --cc docs/content/en/functions/go-template/return.md index 911c0925c,000000000..e96908565 mode 100644,000000..100644 --- a/docs/content/en/functions/go-template/return.md +++ b/docs/content/en/functions/go-template/return.md @@@ -1,93 -1,0 +1,93 @@@ +--- +title: return +description: Used within partial templates, terminates template execution and returns the given value, if any. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: any + 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). + +A `return` statement without a value returns an empty string of type `template.HTML`. + +> [!note] +> Unlike `return` statements in other languages, Hugo executes the first occurrence of the `return` statement regardless of its position within logical blocks. See [usage](#usage) notes below. + +## 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 }} +

{{ . }} is even

+{{ else }} +

{{ . }} is odd

+{{ end }} +``` + +When called, the partial renders HTML: + +```go-html-template +{{ partial "odd-or-even.html" 42 }} →

42 is even

+``` + +Instead of rendering HTML, let's create a partial that _returns_ a boolean value, reporting whether the given number is even: + +```go-html-template {file="layouts/_partials/is-even.html"} +{{ return math.ModBool . 2 }} +``` + +With this template: + +```go-html-template +{{ $number := 42 }} +{{ if partial "is-even.html" $number }} +

{{ $number }} is even

+{{ else }} +

{{ $number }} is odd

+{{ end }} +``` + +Hugo renders: + +```html +

42 is even

+``` + +## Usage + +> [!note] +> Unlike `return` statements in other languages, Hugo executes the first occurrence of the `return` statement regardless of its position within logical blocks. + +A partial that returns a value must contain only one `return` statement, placed at the end of the template. + +For example: + +```go-html-template {file="layouts/_partials/is-even.html"} +{{ $result := false }} +{{ if math.ModBool . 2 }} + {{ $result = "even" }} +{{ else }} + {{ $result = "odd" }} +{{ end }} +{{ return $result }} +``` + +> [!note] +> The construct below is incorrect; it contains more than one `return` statement. + +```go-html-template {file="layouts/_partials/do-not-do-this.html"} +{{ if math.ModBool . 2 }} + {{ return "even" }} +{{ else }} + {{ return "odd" }} +{{ end }} +``` + +[text/template package]: https://pkg.go.dev/text/template diff --cc docs/content/en/functions/go-template/template.md index 903f1490a,000000000..671f95e15 mode 100644,000000..100644 --- a/docs/content/en/functions/go-template/template.md +++ b/docs/content/en/functions/go-template/template.md @@@ -1,42 -1,0 +1,42 @@@ +--- +title: template +description: Executes the given template, optionally passing context. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: ['template NAME [CONTEXT]'] +--- + +Use the `template` function to execute a defined template: + +```go-html-template +{{ template "foo" (dict "answer" 42) }} + +{{ define "foo" }} + {{ printf "The answer is %v." .answer }} +{{ 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) }} + +{{ define "_partials/inline/foo.html" }} + {{ printf "The answer is %v." .answer }} +{{ end }} +``` + +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" %}} + +[`partialCached`]: /functions/partials/includecached/ +[`return`]: /functions/go-template/return/ diff --cc docs/content/en/functions/go-template/try.md index 6aef4da36,000000000..143810654 mode 100644,000000..100644 --- a/docs/content/en/functions/go-template/try.md +++ b/docs/content/en/functions/go-template/try.md @@@ -1,111 -1,0 +1,112 @@@ +--- +title: try +description: Returns a TryValue object after evaluating the given expression. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: TryValue + signatures: ['try EXPRESSION'] +--- + +{{< new-in 0.141.0 />}} + +The `try` statement is a non-standard extension to Go's [text/template] package. It introduces a mechanism for handling errors within templates, mimicking the `try-catch` constructs found in other programming languages. + +## Methods + +The `TryValue` object encapsulates the result of evaluating the expression, and provides two methods: + +### Err + +(`string`) Returns a string representation of the error thrown by the expression, if an error occurred, or returns `nil` if the expression evaluated without errors. + +### Value + +(`any`) Returns the result of the expression if the evaluation was successful, or returns `nil` if an error occurred while evaluating the expression. + +## Explanation + +By way of example, let's divide a number by zero: + +```go-html-template +{{ $x := 1 }} +{{ $y := 0 }} +{{ $result := div $x $y }} +{{ printf "%v divided by %v equals %v" $x $y .Value }} +``` + +As expected, the example above throws an error and fails the build: + +```terminfo +Error: error calling div: can't divide the value by 0 +``` + +Instead of failing the build, we can catch the error and emit a warning: + +```go-html-template +{{ $x := 1 }} +{{ $y := 0 }} +{{ with try (div $x $y) }} + {{ with .Err }} + {{ warnf "%s" . }} + {{ else }} + {{ printf "%v divided by %v equals %v" $x $y .Value }} + {{ end }} +{{ end }} +``` + +The error thrown by the expression is logged to the console as a warning: + +```terminfo +WARN error calling div: can't divide the value by 0 +``` + +Now let's change the arguments to avoid dividing by zero: + +```go-html-template +{{ $x := 42 }} +{{ $y := 6 }} +{{ with try (div $x $y) }} + {{ with .Err }} + {{ warnf "%s" . }} + {{ else }} + {{ printf "%v divided by %v equals %v" $x $y .Value }} + {{ end }} +{{ end }} +``` + +Hugo renders the above to: + +```html +42 divided by 6 equals 7 +``` + +## Example + +Error handling is essential when using the [`resources.GetRemote`] function to capture remote resources such as data or images. When calling this function, if the HTTP request fails, Hugo will fail the build. + +Instead of failing the build, we can catch the error and emit a warning: + +```go-html-template +{{ $url := "https://broken-example.org/images/a.jpg" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ warnf "%s" . }} + {{ else with .Value }} + + {{ else }} + {{ warnf "Unable to get remote resource %q" $url }} + {{ 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] +> Hugo does not classify an HTTP response with status code 404 as an error. In this case `resources.GetRemote` returns nil. + +[`resources.GetRemote`]: /functions/resources/getremote/ +[template context]: /templates/introduction/#template-context +[text/template]: https://pkg.go.dev/text/template diff --cc docs/content/en/functions/go-template/with.md index c25ce3fba,000000000..7354f1608 mode 100644,000000..100644 --- a/docs/content/en/functions/go-template/with.md +++ b/docs/content/en/functions/go-template/with.md @@@ -1,92 -1,0 +1,95 @@@ +--- +title: with +description: Binds context (the dot) to the expression and executes the block if expression is truthy. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [with EXPR] +aliases: [/functions/with] +--- + +{{% include "/_common/functions/truthy-falsy.md" %}} + +```go-html-template +{{ $var := "foo" }} +{{ with $var }} + {{ . }} → foo +{{ end }} +``` + +Use with the [`else`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ with $var }} + {{ . }} → foo +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +Use `else with` to check multiple conditions: + +```go-html-template +{{ $v1 := 0 }} +{{ $v2 := 42 }} +{{ with $v1 }} + {{ . }} +{{ else with $v2 }} + {{ . }} → 42 +{{ else }} + {{ print "v1 and v2 are falsy" }} +{{ end }} +``` + +Initialize a variable, scoped to the current block: + +```go-html-template +{{ with $var := 42 }} + {{ . }} → 42 + {{ $var }} → 42 +{{ end }} +{{ $var }} → undefined +``` + +## 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: + +```go-html-template +{{ with 42 }} + {{ .Title }} +{{ end }} +``` + +Hugo will throw an error: + + can't evaluate field Title in type int + +The error occurs because we are trying to use the `.Title` method on an integer instead of a `Page` object. Inside of the `with` block, if we want to render the page title, we need to get the context passed into the template. + +> [!note] +> Use the `$` to get the context passed into the template. + +This template will render the page title as desired: + +```go-html-template +{{ with 42 }} + {{ $.Title }} +{{ end }} +``` + +> [!note] +> Gaining a thorough understanding of context is critical for anyone writing template code. + +{{% include "/_common/functions/go-template/text-template.md" %}} + +[`else`]: /functions/go-template/else/ ++[context]: /templates/introduction/#context diff --cc docs/content/en/functions/hugo/Generator.md index c044a210c,000000000..176d8e6bf mode 100644,000000..100644 --- a/docs/content/en/functions/hugo/Generator.md +++ b/docs/content/en/functions/hugo/Generator.md @@@ -1,15 -1,0 +1,15 @@@ +--- +title: hugo.Generator +description: Renders an HTML meta element identifying the software that generated the site. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: template.HTML + signatures: [hugo.Generator] +--- + +```go-html-template - {{ hugo.Generator }} → ++{{ hugo.Generator }} → +``` diff --cc docs/content/en/functions/hugo/Store.md index 08c684146,000000000..c0d5c5933 mode 100644,000000..100644 --- a/docs/content/en/functions/hugo/Store.md +++ b/docs/content/en/functions/hugo/Store.md @@@ -1,117 -1,0 +1,117 @@@ +--- +title: hugo.Store +description: Returns a globally scoped "scratch pad" to store and manipulate data. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: maps.Scratch + signatures: [hugo.Store] +--- + +{{< new-in 0.139.0 />}} + +Use the `hugo.Store` function to create a globally scoped [scratch pad](g) to store and manipulate data. To create a scratch pad with a different [scope](g), refer to the [scope](#scope) section below. + +## Methods + +### Set + +Sets the value of the given key. + +```go-html-template +{{ hugo.Store.Set "greeting" "Hello" }} +``` + +### Get + +Gets the value of the given key. + +```go-html-template +{{ hugo.Store.Set "greeting" "Hello" }} +{{ hugo.Store.Get "greeting" }} → Hello +``` + +### Add + +Adds the given value to the existing value(s) of the given key. + +For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be appended to that list. + +```go-html-template +{{ hugo.Store.Set "greeting" "Hello" }} +{{ hugo.Store.Add "greeting" "Welcome" }} +{{ hugo.Store.Get "greeting" }} → HelloWelcome +``` + +```go-html-template +{{ hugo.Store.Set "total" 3 }} +{{ hugo.Store.Add "total" 7 }} +{{ hugo.Store.Get "total" }} → 10 +``` + +```go-html-template +{{ hugo.Store.Set "greetings" (slice "Hello") }} +{{ hugo.Store.Add "greetings" (slice "Welcome" "Cheers") }} +{{ hugo.Store.Get "greetings" }} → [Hello Welcome Cheers] +``` + +### SetInMap + +Takes a `key`, `mapKey` and `value` and adds a map of `mapKey` and `value` to the given `key`. + +```go-html-template +{{ hugo.Store.SetInMap "greetings" "english" "Hello" }} +{{ hugo.Store.SetInMap "greetings" "french" "Bonjour" }} +{{ hugo.Store.Get "greetings" }} → map[english:Hello french:Bonjour] +``` + +### DeleteInMap + +Takes a `key` and `mapKey` and removes the map of `mapKey` from the given `key`. + +```go-html-template +{{ hugo.Store.SetInMap "greetings" "english" "Hello" }} +{{ hugo.Store.SetInMap "greetings" "french" "Bonjour" }} +{{ hugo.Store.DeleteInMap "greetings" "english" }} +{{ hugo.Store.Get "greetings" }} → map[french:Bonjour] + ``` + +### GetSortedMapValues + +Returns an array of values from `key` sorted by `mapKey`. + +```go-html-template +{{ hugo.Store.SetInMap "greetings" "english" "Hello" }} +{{ hugo.Store.SetInMap "greetings" "french" "Bonjour" }} +{{ hugo.Store.GetSortedMapValues "greetings" }} → [Hello Bonjour] +``` + +### Delete + +Removes the given key. + +```go-html-template +{{ hugo.Store.Set "greeting" "Hello" }} +{{ hugo.Store.Delete "greeting" }} +``` + +{{% include "_common/scratch-pad-scope.md" %}} + +## 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: + +```go-html-template +{{ $noop := .Content }} +{{ hugo.Store.Get "mykey" }} +``` + +You can also trigger content rendering with the `ContentWithoutSummary`, `FuzzyWordCount`, `Len`, `Plain`, `PlainWords`, `ReadingTime`, `Summary`, `Truncated`, and `WordCount` methods. For example: + +```go-html-template +{{ $noop := .WordCount }} +{{ hugo.Store.Get "mykey" }} +``` diff --cc docs/content/en/functions/hugo/Version.md index a23bd75cd,000000000..33827737a mode 100644,000000..100644 --- a/docs/content/en/functions/hugo/Version.md +++ b/docs/content/en/functions/hugo/Version.md @@@ -1,15 -1,0 +1,15 @@@ +--- +title: hugo.Version +description: Returns the current version of the Hugo binary. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: hugo.VersionString + signatures: [hugo.Version] +--- + +```go-html-template - {{ hugo.Version }} → 0.147.9 ++{{ hugo.Version }} → 0.148.0 +``` diff --cc docs/content/en/functions/js/Babel.md index d0007aaa0,000000000..488c80503 mode 100644,000000..100644 --- a/docs/content/en/functions/js/Babel.md +++ b/docs/content/en/functions/js/Babel.md @@@ -1,99 -1,0 +1,96 @@@ +--- +title: js.Babel +description: Compile the given JavaScript resource with Babel. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [babel] + returnType: resource.Resource + signatures: ['js.Babel [OPTIONS] RESOURCE'] +--- + +```go-html-template +{{ with resources.Get "js/main.js" }} + {{ $opts := dict + "minified" hugo.IsProduction + "noComments" hugo.IsProduction + "sourceMap" (cond hugo.IsProduction "none" "external") + }} + {{ with . | js.Babel $opts }} + {{ if hugo.IsProduction }} + {{ with . | fingerprint }} + + {{ end }} + {{ else }} + + {{ end }} + {{ end }} +{{ end }} +``` + +## 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 + +We add the main project's `node_modules` to `NODE_PATH` when running Babel and similar tools. There are some known [issues](https://github.com/babel/babel/issues/5618) with Babel in this area, so if you have a `babel.config.js` living in a Hugo Module (and not in the project itself), we recommend using `require` to load the presets/plugins, e.g.: + +```js +module.exports = { + presets: [ + [ + require("@babel/preset-env"), + { + useBuiltIns: "entry", + corejs: 3, + }, + ], + ], +}; +``` + +## Options + +compact +: (`bool`) Whether to remove optional newlines and whitespace. Enabled when `minified` is `true`. Default is `false` + +config +: (`string`) Path to the Babel configuration file. Hugo will, by default, look for a `babel.config.js` file in the root of your project. See [details](https://babeljs.io/docs/en/configuration). + +minified +: (`bool`) Whether to minify the compiled code. Enables the `compact` option. Default is `false`. + +noBabelrc +: (`string`) Whether to ignore `.babelrc` and `.babelignore` files. Default is `false`. + +noComments +: (`bool`) Whether to remove comments. Default is `false`. + +sourceMap +: (`string`) Whether to generate source maps, one of `external`, `inline`, or `none`. Default is `none`. + +verbose +: (`bool`) Whether to enable verbose logging. Default is `false` + + diff --cc docs/content/en/functions/js/Batch.md index a2c8bb893,000000000..360f98656 mode 100644,000000..100644 --- a/docs/content/en/functions/js/Batch.md +++ b/docs/content/en/functions/js/Batch.md @@@ -1,307 -1,0 +1,306 @@@ +--- +title: js.Batch +description: Build JavaScript bundle groups with global code splitting and flexible hooks/runners setup. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: js.Batcher + signatures: ['js.Batch [ID]'] +--- + +> [!note] +> For a runnable example of this feature, see [this test and demo repo](https://github.com/bep/hugojsbatchdemo/). + +The Batch `ID` is used to create the base directory for this batch. Forward slashes are allowed. `js.Batch` returns an object with an API with this structure: + +- [Group] + - [Script] + - [SetOptions] + - [Instance] + - [SetOptions] + - [Runner] + - [SetOptions] + - [Config] + - [SetOptions] + +## Group + +The `Group` method take an `ID` (`string`) as argument. No slashes. It returns an object with these methods: + +### Script + +The `Script` method takes an `ID` (`string`) as argument. No slashes. It returns an [OptionsSetter] that can be used to set [script options] for this script. + +```go-html-template +{{ with js.Batch "js/mybatch" }} + {{ with .Group "mygroup" }} + {{ with .Script "myscript" }} + {{ .SetOptions (dict "resource" (resources.Get "myscript.js")) }} + {{ end }} + {{ end }} +{{ end }} +``` + +`SetOptions` takes a [script options] map. Note that if you want the script to be handled by a [runner], you need to set the `export` option to match what you want to pass on to the runner (default is `*`). + +### Instance + +The `Instance` method takes two `string` arguments `SCRIPT_ID` and `INSTANCE_ID`. No slashes. It returns an [OptionsSetter] that can be used to set [params options] for this instance. + +```go-html-template +{{ with js.Batch "js/mybatch" }} + {{ with .Group "mygroup" }} + {{ with .Instance "myscript" "myinstance" }} + {{ .SetOptions (dict "params" (dict "param1" "value1")) }} + {{ end }} + {{ end }} +{{ end }} +``` + +`SetOptions` takes a [params options] map. The instance options will be passed to any [runner] script in the same group, as JSON. + +### Runner + +The `Runner` method takes an `ID` (`string`) as argument. No slashes. It returns an [OptionsSetter] that can be used to set [script options] for this runner. + +```go-html-template +{{ with js.Batch "js/mybatch" }} + {{ with .Group "mygroup" }} + {{ with .Runner "myrunner" }} + {{ .SetOptions (dict "resource" (resources.Get "myrunner.js")) }} + {{ end }} + {{ end }} +{{ end }} +``` + +`SetOptions` takes a [script options] map. + +The runner will receive a data structure with all instances for that group with a live binding of the [JavaScript import] of the defined `export`. + +The runner script's export must be a function that takes one argument, the group data structure. An example of a group data structure as JSON is: + +```json +{ + "id": "leaflet", + "scripts": [ + { + "id": "mapjsx", + "binding": JAVASCRIPT_BINDING, + "instances": [ + { + "id": "0", + "params": { + "c": "h-64", + "lat": 48.8533173846729, + "lon": 2.3497416090232535, + "r": "map.jsx", + "title": "Cathédrale Notre-Dame de Paris", + "zoom": 23 + } + }, + { + "id": "1", + "params": { + "c": "h-64", + "lat": 59.96300872062237, + "lon": 10.663529183196863, + "r": "map.jsx", + "title": "Holmenkollen", + "zoom": 3 + } + } + ] + } + ] +} +``` + +Below is an example of a runner script that uses React to render elements. Note that the export (`default`) must match the `export` option in the [script options] (`default` is the default value for runner scripts) (runnable versions of examples on this page can be found at [js.Batch Demo Repo]): + +```js +import * as ReactDOM from 'react-dom/client'; +import * as React from 'react'; + +export default function Run(group) { + console.log('Running react-create-elements.js', group); + const scripts = group.scripts; + for (const script of scripts) { + for (const instance of script.instances) { + /* This is a convention in this project. */ + let elId = `${script.id}-${instance.id}`; + let el = document.getElementById(elId); + if (!el) { + console.warn(`Element with id ${elId} not found`); + continue; + } + const root = ReactDOM.createRoot(el); + const reactEl = React.createElement(script.binding, instance.params); + root.render(reactEl); + } + } +} +``` + +### Config + +Returns an [OptionsSetter] that can be used to set [build options] for the batch. + +These are mostly the same as for `js.Build`, but note that: + +- `targetPath` is set automatically (there may be multiple outputs). +- ``format` must be `esm`, currently the only format supporting [code splitting]. +- ``params` will be available in the `@params/config` namespace in the scripts. This way you can import both the [script] or [runner] params and the [config] params with: + +```js +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" }} + {{ with .Config }} + {{ .SetOptions (dict + "target" "es2023" + "format" "esm" + "jsx" "automatic" + "loaders" (dict ".png" "dataurl") + "minify" true + "params" (dict "param1" "value1") + ) + }} + {{ end }} +{{ end }} +``` + +## Options + +### Build options + +format +: (`string`) Currently only `esm` is supported in ESBuild's [code splitting]. + +{{% include "/_common/functions/js/options.md" %}} + +### Script options + +resource +: The resource to build. This can be a file resource or a virtual resource. + +export +: The export to bind the runner to. Set it to `*` to export the [entire namespace](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#namespace_import). Default is `default` for [runner] scripts and `*` for other [scripts](#script). + +importContext +: An additional context for resolving imports. Hugo will always check this one first before falling back to `assets` and `node_modules`. A common use of this is to resolve imports inside a page bundle. See [import context](#import-context). + +params +: A map of parameters that will be passed to the script as JSON. These gets bound to the `@params` namespace: + + ```js + import * as params from '@params'; + ``` + +### Params options + +params +: A map of parameters that will be passed to the script as JSON. + +### Import context + +Hugo will, by default, first try to resolve any import in [assets](/hugo-pipes/introduction/#asset-directory) and, if not found, let [ESBuild] resolve it (e.g. from `node_modules`). The `importContext` option can be used to set the first context for resolving imports. A common use of this is to resolve imports inside a [page bundle](/content-management/page-bundles/). + +```go-html-template +{{ $common := resources.Match "/js/headlessui/*.*" }} +{{ $importContext := (slice $.Page ($common.Mount "/js/headlessui" ".")) }} +``` + +You can pass any object that implements [Resource.Get](/methods/page/resources/#get). Pass a slice to set multiple contexts. + +The example above uses [`Resources.Mount`] to resolve a directory inside `assets` relative to the page bundle. + +### OptionsSetter + +An `OptionsSetter` is a special object that is returned once only. This means that you should wrap it with [with]: + +```go-html-template +{{ with .Script "myscript" }} + {{ .SetOptions (dict "resource" (resources.Get "myscript.js"))}} +{{ end }} +``` + +## Build + +The `Build` method returns an object with the following structure: + +- Groups (map) + - [`Resources`] + +Each [`Resource`] will be of media type `application/javascript` or `text/css`. + +In a template you would typically handle one group with a given `ID` (e.g. scripts for the current section). Because of the concurrent build, this needs to be done in a [`templates.Defer`] block: + +> [!note] +> The [`templates.Defer`] acts as a synchronisation point to handle scripts added concurrently by different templates. If you have a setup with where the batch is created in one go (in one template), you don't need it. +> +> See [this discussion](https://discourse.gohugo.io/t/js-batch-with-simple-global-script/53002/5?u=bep) for more. + +```go-html-template +{{ $group := .group }} +{{ with (templates.Defer (dict "key" $group "data" $group )) }} + {{ with (js.Batch "js/mybatch") }} + {{ with .Build }} + {{ with index .Groups $ }} + {{ range . }} + {{ $s := . }} + {{ if eq $s.MediaType.SubType "css" }} + + {{ else }} + + {{ end }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} +``` + +## Known Issues + +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: + +1. Undefined execution order of imports, see [this comment](https://github.com/evanw/esbuild/issues/399#issuecomment-1458680887) +1. Only one execution order of imports, see [this comment](https://github.com/evanw/esbuild/issues/399#issuecomment-735355932) + +Many would say that both of the above are [code smells](https://en.wikipedia.org/wiki/Code_smell). The first one has a simple workaround in Hugo. Define the import order in its own script and make sure it gets passed early to ESBuild, e.g. by putting it in a script group with a name that comes early in the alphabet. + +```js +import './lib2.js'; +import './lib1.js'; + +console.log('entrypoints-workaround.js'); +``` + +[`Resource`]: /methods/resource/ +[`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 +[ESBuild]: https://github.com/evanw/esbuild +[JavaScript import]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import +[js.Batch Demo Repo]: https://github.com/bep/hugojsbatchdemo/ +[OptionsSetter]: #optionssetter +[params options]: #params-options +[runner]: #runner +[script]: #script +[script options]: #script-options +[SetOptions]: #optionssetter +[with]: /functions/go-template/with/ diff --cc docs/content/en/functions/js/Build.md index d55220a52,000000000..79c52087d mode 100644,000000..100644 --- a/docs/content/en/functions/js/Build.md +++ b/docs/content/en/functions/js/Build.md @@@ -1,121 -1,0 +1,122 @@@ +--- +title: js.Build +description: Bundle, transpile, tree shake, and minify JavaScript resources. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: ['js.Build [OPTIONS] RESOURCE'] +--- + +The `js.Build` function uses the [evanw/esbuild] package to: + +- Bundle +- Transpile (TypeScript and JSX) +- Tree shake +- Minify +- Create source maps + +```go-html-template +{{ with resources.Get "js/main.js" }} + {{$opts := dict + "minify" (not hugo.IsDevelopment) + "sourceMap" (cond hugo.IsDevelopment "external" "") + "targetPath" "js/main.js" + }} + {{ with . | js.Build $opts }} + {{ if hugo.IsDevelopment }} + + {{ else }} + {{ with . | fingerprint }} + + {{ end }} + {{ end }} + {{ end }} +{{ end }} +``` + +## Options + +targetPath +: (`string`) If not set, the source path will be used as the base target path. Note that the target path's extension may change if the target MIME type is different, e.g. when the source is TypeScript. + +format +: (`string`) The output format. One of: `iife`, `cjs`, `esm`. Default is `iife`, a self-executing function, suitable for inclusion as a ` +``` + +[evanw/esbuild]: https://github.com/evanw/esbuild diff --cc docs/content/en/functions/openapi3/Unmarshal.md index ca2ee93e3,000000000..ed15d4d6a mode 100644,000000..100644 --- a/docs/content/en/functions/openapi3/Unmarshal.md +++ b/docs/content/en/functions/openapi3/Unmarshal.md @@@ -1,77 -1,0 +1,77 @@@ +--- +title: openapi3.Unmarshal +description: Unmarshals the given resource into an OpenAPI 3 document. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: openapi3.OpenAPIDocument + signatures: ['openapi3.Unmarshal RESOURCE'] +--- + +Use the `openapi3.Unmarshal` function with [global resources](g), [page resources](g), or [remote resources](g). + +[OpenAPI]: https://www.openapis.org/ + +For example, to work with a remote [OpenAPI] definition: + +```go-html-template +{{ $url := "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json" }} +{{ $api := "" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else with .Value }} + {{ $api = . | openapi3.Unmarshal }} + {{ else }} + {{ errorf "Unable to get remote resource %q" $url }} + {{ end }} +{{ end }} +``` + +To inspect the data structure: + +```go-html-template +
{{ debug.Dump $api }}
+``` + +To list the GET and POST operations for each of the API paths: + +```go-html-template +{{ range $path, $details := $api.Paths.Map }} +

{{ $path }}

+
+ {{ with $details.Get }} +
GET
+
{{ .Summary }}
+ {{ end }} + {{ with $details.Post }} +
POST
+
{{ .Summary }}
+ {{ end }} +
+{{ end }} +``` + +> [!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. + +Hugo renders this to: + +```html +

/pets

+
+
GET
+
List all pets
+
POST
+
Create a pet
+
+

/pets/{petId}

+
+
GET
+
Info for a specific pet
+
+``` diff --cc docs/content/en/functions/partials/Include.md index 0474bf77f,000000000..dfb8873b4 mode 100644,000000..100644 --- a/docs/content/en/functions/partials/Include.md +++ b/docs/content/en/functions/partials/Include.md @@@ -1,84 -1,0 +1,80 @@@ +--- +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: + functions_and_methods: + aliases: [partial] + returnType: any + signatures: ['partials.Include NAME [CONTEXT]'] +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/ +└── _partials/ + ├── average.html + ├── breadcrumbs.html + └── footer.html +``` + +The "average" partial returns the average of one or more numbers. We pass the numbers in context: + +```go-html-template +{{ $numbers := slice 1 6 7 42 }} +{{ $average := partial "average.html" $numbers }} +``` + +The "breadcrumbs" partial renders [breadcrumb navigation], and needs to receive the current page in context: + +```go-html-template +{{ partial "breadcrumbs.html" . }} +``` + +The "footer" partial renders the site footer. In this contrived example, the footer does not need access to the current page, so we can omit context: + +```go-html-template +{{ partial "footer.html" }} +``` + +You can pass anything in context: a page, a page collection, a scalar value, a slice, or a map. In this example we pass the current page and three scalar values: + +```go-html-template +{{ $ctx := dict + "page" . + "name" "John Doe" + "major" "Finance" + "gpa" 4.0 +}} +{{ partial "render-student-info.html" $ctx }} +``` + - Then, within the partial template: ++Then, within the _partial_ template: + +```go-html-template +

{{ .name }} is majoring in {{ .major }}.

+

Their grade point average is {{ .gpa }}.

+

See details.

+``` + - 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 := "" }} +{{ if math.ModBool . 2 }} + {{ $result = "even" }} +{{ else }} + {{ $result = "odd" }} +{{ end }} +{{ return $result }} +``` + +See [details][`return`]. + +[`return`]: /functions/go-template/return/ - +[breadcrumb navigation]: /content-management/sections/#ancestors-and-descendants - [details]: /functions/go-template/return/ diff --cc docs/content/en/functions/partials/IncludeCached.md index 9bf1d5384,000000000..b80aaf8a1 mode 100644,000000..100644 --- a/docs/content/en/functions/partials/IncludeCached.md +++ b/docs/content/en/functions/partials/IncludeCached.md @@@ -1,57 -1,0 +1,57 @@@ +--- +title: partials.IncludeCached +description: Executes the given template and caches the result, optionally passing context. If the partial template contains a return statement, returns the given value, else returns the rendered output. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [partialCached] + returnType: any + signatures: ['partials.IncludeCached LAYOUT CONTEXT [VARIANT...]'] +aliases: [/functions/partialcached] +--- + +Without a [`return`] statement, the `partialCached` function returns a string of type `template.HTML`. With a `return` statement, the `partialCached` function can return any data type. + +The `partialCached` function can offer significant performance gains for complex templates that don't need to be re-rendered on every invocation. + +> [!note] +> Each site (or language) has its own `partialCached` cache, so each site will execute a partial once. +> +> Hugo renders pages in parallel, and will render the partial more than once with concurrent calls to the `partialCached` function. After Hugo caches the rendered partial, new pages entering the build pipeline will use the cached result. + +Here is the simplest usage: + +```go-html-template +{{ partialCached "footer.html" . }} +``` + +Pass additional arguments to `partialCached` to create variants of the cached partial. For example, if you have a complex partial that should be identical when rendered for pages within the same section, use a variant based on section so that the partial is only rendered once per section: + +```go-html-template {file="layouts/baseof.html"} +{{ partialCached "footer.html" . .Section }} +``` + +Pass additional arguments, of any data type, as needed to create unique variants: + +```go-html-template +{{ 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 := "" }} +{{ if math.ModBool . 2 }} + {{ $result = "even" }} +{{ else }} + {{ $result = "odd" }} +{{ end }} +{{ return $result }} +``` + +See [details][`return`]. + +[`return`]: /functions/go-template/return/ diff --cc docs/content/en/functions/resources/FromString.md index bd2d894b1,000000000..c86f90cbb mode 100644,000000..100644 --- a/docs/content/en/functions/resources/FromString.md +++ b/docs/content/en/functions/resources/FromString.md @@@ -1,76 -1,0 +1,76 @@@ +--- +title: resources.FromString +description: Returns a resource created from a string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: [resources.FromString TARGETPATH STRING] +--- + +The `resources.FromString` function returns a resource created from a string, caching the result using the target path as its cache key. + +Hugo publishes the resource to the target path when you call its [`Publish`], [`Permalink`], or [`RelPermalink`] methods. + +[`publish`]: /methods/resource/publish/ +[`permalink`]: /methods/resource/permalink/ +[`relpermalink`]: /methods/resource/relpermalink/ + +Let's say you need to publish a file named "site.json" in the root of your `public` directory, containing the build date, the Hugo version used to build the site, and the date that the content was last modified. For example: + +```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" +} +``` + +Place this in your baseof.html template: + +```go-html-template +{{ if .IsHome }} + {{ $rfc3339 := "2006-01-02T15:04:05Z07:00" }} + {{ $m := dict + "hugo_version" hugo.Version + "build_date" (now.Format $rfc3339) + "last_modified" (site.Lastmod.Format $rfc3339) + }} + {{ $json := jsonify $m }} + {{ $r := resources.FromString "site.json" $json }} + {{ $r.Publish }} +{{ end }} +``` + +The example above: + +1. Creates a map with the relevant key-value pairs using the [`dict`] function +1. Encodes the map as a JSON string using the [`jsonify`] function +1. Creates a resource from the JSON string using the `resources.FromString` function +1. Publishes the file to the root of the `public` directory using the resource's `.Publish` method + +Combine `resources.FromString` with [`resources.ExecuteAsTemplate`] if your string contains template actions. Rewriting the example above: + +```go-html-template +{{ if .IsHome }} + {{ $string := ` + {{ $rfc3339 := "2006-01-02T15:04:05Z07:00" }} + {{ $m := dict + "hugo_version" hugo.Version + "build_date" (now.Format $rfc3339) + "last_modified" (site.Lastmod.Format $rfc3339) + }} + {{ $json := jsonify $m }} + ` + }} + {{ $r := resources.FromString "" $string }} + {{ $r = $r | resources.ExecuteAsTemplate "site.json" . }} + {{ $r.Publish }} +{{ end }} +``` + +[`dict`]: /functions/collections/dictionary/ +[`jsonify`]: /functions/encoding/jsonify/ +[`resources.ExecuteAsTemplate`]: /functions/resources/executeastemplate/ diff --cc docs/content/en/functions/resources/GetRemote.md index c6f6742b3,000000000..29768eedf mode 100644,000000..100644 --- a/docs/content/en/functions/resources/GetRemote.md +++ b/docs/content/en/functions/resources/GetRemote.md @@@ -1,236 -1,0 +1,227 @@@ +--- +title: resources.GetRemote +description: Returns a remote resource from the given URL, or nil if none found. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: ['resources.GetRemote URL [OPTIONS]'] +--- + +{{< new-in 0.141.0 >}} +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 +{{ $url := "https://example.org/images/a.jpg" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else with .Value }} + + {{ else }} + {{ errorf "Unable to get remote resource %q" $url }} + {{ end }} +{{ end }} +``` + +## Options + +The `resources.GetRemote` function takes an optional map of options. + - ###### body - - (`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. ++body ++: (`string`) The data you want to transmit to the server. + - ###### key ++headers ++: (`map[string][]string`) The collection of key-value pairs that provide additional information about the request. + - (`string`) The cache key. Hugo derives the default value from the URL and options map. See [caching](#caching). ++key ++: (`string`) The cache key. Hugo derives the default value from the URL and options map. See [caching](#caching). + - ###### method ++method ++: (`string`) The action to perform on the requested resource, typically one of `GET`, `POST`, or `HEAD`. + - (`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 + +## Options examples + +> [!note] +> For brevity, the examples below do not include [error handling]. + - [error handling]: #error-handling - +To include a header: + +```go-html-template +{{ $url := "https://example.org/api" }} +{{ $opts := dict + "headers" (dict "Authorization" "Bearer abcd") +}} +{{ $resource := resources.GetRemote $url $opts }} +``` + +To specify more than one value for the same header key, use a slice: + +```go-html-template +{{ $url := "https://example.org/api" }} +{{ $opts := dict + "headers" (dict "X-List" (slice "a" "b" "c")) +}} +{{ $resource := resources.GetRemote $url $opts }} +``` + +To post data: + +```go-html-template +{{ $url := "https://example.org/api" }} +{{ $opts := dict + "method" "post" + "body" `{"complete": true}` + "headers" (dict "Content-Type" "application/json") +}} +{{ $resource := resources.GetRemote $url $opts }} +``` + +To override the default cache key: + +```go-html-template +{{ $url := "https://example.org/images/a.jpg" }} +{{ $opts := dict + "key" (print $url (now.Format "2006-01-02")) +}} +{{ $resource := resources.GetRemote $url $opts }} +``` + +To extract specific headers from the server's response: + +```go-html-template +{{ $url := "https://example.org/images/a.jpg" }} +{{ $opts := dict + "method" "HEAD" + "responseHeaders" (slice "X-Frame-Options" "Server") +}} +{{ $resource := resources.GetRemote $url $opts }} +``` + +## Remote data + +When retrieving remote data, use the [`transform.Unmarshal`] function to [unmarshal](g) the response. + +[`transform.Unmarshal`]: /functions/transform/unmarshal/ + +```go-html-template +{{ $data := dict }} +{{ $url := "https://example.org/books.json" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else with .Value }} + {{ $data = . | transform.Unmarshal }} + {{ else }} + {{ errorf "Unable to get remote resource %q" $url }} + {{ end }} +{{ end }} +``` + +> [!note] +> When retrieving remote data, a misconfigured server may send a response header with an incorrect [Content-Type]. For example, the server may set the Content-Type header to `application/octet-stream` instead of `application/json`. +> +> In these cases, pass the resource `Content` through the `transform.Unmarshal` function instead of passing the resource itself. For example, in the above, do this instead: +> +> `{{ $data = .Content | transform.Unmarshal }}` + +## Error handling + +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. + +```go-html-template +{{ $url := "https://broken-example.org/images/a.jpg" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else with .Value }} + + {{ else }} + {{ errorf "Unable to get remote resource %q" $url }} + {{ end }} +{{ end }} +``` + +To log an error as a warning instead of an error: + +```go-html-template +{{ $url := "https://broken-example.org/images/a.jpg" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ warnf "%s" . }} + {{ else with .Value }} + + {{ else }} + {{ warnf "Unable to get remote resource %q" $url }} + {{ end }} +{{ end }} +``` + +## HTTP response + +The [`Data`] method on a resource returned by the `resources.GetRemote` function returns information from the HTTP response. + +[`Data`]: /methods/resource/data/ + +## Caching + +Resources returned from `resources.GetRemote` are cached to disk. See [configure file caches] for details. + +By default, Hugo derives the cache key from the arguments passed to the function. Override the cache key by setting a `key` in the options map. Use this approach to have more control over how often Hugo fetches a remote resource. + +```go-html-template +{{ $url := "https://example.org/images/a.jpg" }} +{{ $cacheKey := print $url (now.Format "2006-01-02") }} +{{ $opts := dict "key" $cacheKey }} +{{ $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: + +- The [Content-Type] in the response header +- The file extension, if any +- The content itself + +If Hugo is unable to resolve the media type to an entry in its [allowlist], the function throws an error: + +```text +ERROR error calling resources.GetRemote: failed to resolve media type... +``` + +For example, you will see the error above if you attempt to download an executable. + +Although the allowlist contains entries for common media types, you may encounter situations where Hugo is unable to resolve the media type of a file that you know to be safe. In these situations, edit your site configuration to add the media type to the allowlist. For example: + +{{< code-toggle file=hugo >}} +[security.http] +mediaTypes = ['^image/avif$','^application/vnd\.api\+json$'] +{{< /code-toggle >}} + +Note that the entry above is: + +- An _addition_ to the allowlist; it does not _replace_ the allowlist +- An array of [regular expressions](g) + +[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 diff --cc docs/content/en/functions/resources/PostProcess.md index d70437694,000000000..766817ff5 mode 100644,000000..100644 --- a/docs/content/en/functions/resources/PostProcess.md +++ b/docs/content/en/functions/resources/PostProcess.md @@@ -1,148 -1,0 +1,148 @@@ +--- +title: resources.PostProcess +description: Processes the given resource after the build. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: postpub.PostPublishedResource + signatures: [resources.PostProcess RESOURCE] +--- + +The `resources.PostProcess` function delays resource transformation steps until the build is complete, primarily for tasks like removing unused CSS rules. + +## Example + +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]. + +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; - - 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, - ] - }; - ``` - - > [!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]. ++ ```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: [] ++ }); ++ ++ 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]. + +Step 5 +: Place your CSS file within the `assets/css` directory. + +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 }} - - {{ else }} - {{ with . | postCSS | minify | fingerprint | resources.PostProcess }} - ++ ```go-html-template {copy=true} ++ {{ with resources.Get "css/main.css" }} ++ {{ if hugo.IsDevelopment }} ++ ++ {{ else }} ++ {{ with . | postCSS | minify | fingerprint | resources.PostProcess }} ++ ++ {{ end }} + {{ end }} + {{ end }} - {{ end }} - ``` ++ ``` + +## Environment variables + +Hugo passes the environment variables below to PostCSS, allowing you to do something like: + +```js +process.env.HUGO_ENVIRONMENT !== 'development' ? purgecss : null, +``` + +PWD +: The absolute path to the project working directory. + +HUGO_ENVIRONMENT +: The current Hugo environment, set with the `--environment` command line flag. +Default is `production` for `hugo` and `development` for `hugo server`. + +HUGO_PUBLISHDIR +: The absolute path to the publish directory, typically `public`. This value points to a directory on disk, even when rendering to memory with the `--renderToMemory` command line flag. + +HUGO_FILE_X +: Hugo automatically mounts the following files from your project's root directory under `assets/_jsconfig`: + +- `babel.config.js` +- `postcss.config.js` +- `tailwind.config.js` + +For each file, Hugo creates a corresponding environment variable named `HUGO_FILE_:filename:`, where `:filename:` is the uppercase version of the filename with periods replaced by underscores. This allows you to access these files within your JavaScript, for example: + +```js +let tailwindConfig = process.env.HUGO_FILE_TAILWIND_CONFIG_JS || './tailwind.config.js'; +``` + +## 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. + +You cannot manipulate the values returned from the resource's methods. For example, the `strings.ToUpper` function in this example will not work as expected: + +```go-html-template +{{ $css := resources.Get "css/main.css" }} +{{ $css = $css | css.PostCSS | minify | fingerprint | resources.PostProcess }} +{{ $css.RelPermalink | strings.ToUpper }} +``` + +[#7333]: https://github.com/gohugoio/hugo/issues/7333 +[`config/production`]: /configuration/introduction/#configuration-directory +[Autoprefixer]: https://github.com/postcss/autoprefixer +[configure build]: /configuration/build/ +[Fingerprint]: /functions/resources/fingerprint/ +[Minify]: /functions/resources/minify/ +[Node.js]: https://nodejs.org/en +[PostCSS]: https://postcss.org/ +[PurgeCSS]: https://github.com/FullHuman/purgecss +[this example]: https://github.com/postcss/postcss-load-config#packagejson diff --cc docs/content/en/functions/templates/Current.md index d2c2c9609,000000000..b82818c47 mode 100644,000000..100644 --- a/docs/content/en/functions/templates/Current.md +++ b/docs/content/en/functions/templates/Current.md @@@ -1,155 -1,0 +1,155 @@@ +--- +title: templates.Current +description: Returns information about the currently executing template. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: tpl.CurrentTemplateInfo + signatures: [templates.Current] +--- + +> [!note] +> This function is experimental and subject to change. + +{{< new-in 0.146.0 />}} + +The `templates.Current` function provides introspection capabilities, allowing you to access details about the currently executing templates. This is useful for debugging complex template hierarchies and understanding the flow of execution during rendering. + +## Methods + +Ancestors +: (`tpl.CurrentTemplateInfos`) Returns a slice containing information about each template in the current execution chain, starting from the parent of the current template and going up towards the initial template called. It excludes any base template applied via `define` and `block`. You can chain the `Reverse` method to this result to get the slice in chronological execution order. + +Base +: (`tpl.CurrentTemplateInfoCommonOps`) Returns an object representing the base template that was applied to the current template, if any. This may be `nil`. + +Filename +: (`string`) Returns the absolute path of the current template. This will be empty for embedded templates. + +Name +: (`string`) Returns the name of the current template. This is usually the path relative to the layouts directory. + +Parent +: (`tpl.CurrentTemplateInfo`) Returns an object representing the parent of the current template, if any. This may be `nil`. + +## Examples + +The examples below help visualize template execution and require a `debug` parameter set to `true` in your site configuration: + +{{< code-toggle file=hugo >}} +[params] +debug = true +{{< /code-toggle >}} + +### Boundaries + +To visually mark where a template begins and ends execution: + +```go-html-template {file="layouts/page.html"} +{{ define "main" }} + {{ if site.Params.debug }} +
[entering {{ templates.Current.Filename }}]
+ {{ end }} + +

{{ .Title }}

+ {{ .Content }} + + {{ if site.Params.debug }} +
[leaving {{ templates.Current.Filename }}]
+ {{ end }} +{{ end }} +``` + +### 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 }} +
+ {{ range .Ancestors }} + {{ .Filename }}
+ {{ with .Base }} + {{ .Filename }}
+ {{ end }} + {{ end }} +
+{{ end }} +``` + +Then call the partial from any template: + +```go-html-template {file="layouts/_partials/footer/copyright.html" copy=true} +{{ if site.Params.debug }} + {{ partial "template-call-stack.html" . }} +{{ end }} +``` + +The rendered template stack would look something like this: + +```text +/home/user/project/layouts/_partials/footer/copyright.html +/home/user/project/themes/foo/layouts/_partials/footer.html +/home/user/project/layouts/page.html +/home/user/project/themes/foo/layouts/baseof.html +``` + +To reverse the order of the entries, chain the `Reverse` method to the `Ancestors` method: + +```go-html-template {file="layouts/_partials/template-call-stack.html" copy=true} +{{ with templates.Current }} +
+ {{ range .Ancestors.Reverse }} + {{ with .Base }} + {{ .Filename }}
+ {{ end }} + {{ .Filename }}
+ {{ end }} +
+{{ end }} +``` + +### 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 }} +
+ {{ .Name }} + {{ with .Base }} + {{ .Name }} + {{ end }} +
+{{ end }} +``` + +Then call the partial from any template: + +```go-html-template {file="layouts/page.html" copy=true} +{{ define "main" }} +

{{ .Title }}

+ {{ .Content }} + + {{ if site.Params.debug }} + {{ partial "template-open-in-vs-code.html" . }} + {{ end }} +{{ end }} +``` + +Use the same approach to render the entire call stack as links: + +```go-html-template {file="layouts/_partials/template-call-stack.html" copy=true} +{{ with templates.Current }} +
+ {{ range .Ancestors }} + {{ .Filename }}
+ {{ with .Base }} + {{ .Filename }}
+ {{ end }} + {{ end }} +
+{{ end }} +``` diff --cc docs/content/en/functions/templates/Defer.md index 16c32724e,000000000..9acb91405 mode 100644,000000..100644 --- a/docs/content/en/functions/templates/Defer.md +++ b/docs/content/en/functions/templates/Defer.md @@@ -1,97 -1,0 +1,97 @@@ +--- +title: templates.Defer +description: Defer execution of a template until after all sites and output formats have been rendered. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [templates.Defer OPTIONS] +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 + +In some rare use cases, you may need to defer the execution of a template until after all sites and output formats have been rendered. One such example could be [TailwindCSS](/functions/css/tailwindcss/) using the output of [hugo_stats.json](/configuration/build/) to determine which classes and other HTML identifiers are being used in the final output: + +```go-html-template {file="layouts/baseof.html" copy=true} + + ... + {{ with (templates.Defer (dict "key" "global")) }} + {{ partial "css.html" . }} + {{ end }} + ... + +``` + +```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 }} + + {{ else }} + {{ with . | fingerprint }} + + {{ end }} + {{ end }} + {{ end }} +{{ end }} +``` + +> [!note] +> This function only works in combination with the `with` keyword. +> +> Variables defined on the outside are not visible on the inside and vice versa. To pass in data, use the `data` [option](#options). + +For the above to work well when running the server (or `hugo -w`), you want to have a configuration similar to this: + +{{< code-toggle file=hugo >}} +[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 >}} + +## Options + +The `templates.Defer` function takes a single argument, a map with the following optional keys: + +key (`string`) +: The key to use for the deferred template. This will, combined with a hash of the template content, be used as a cache key. If this is not set, Hugo will execute the deferred template on every render. This is not what you want for shared resources like CSS and JavaScript. + +data (`map`) +: Optional map to pass as data to the deferred template. This will be available in the deferred template as `.` or `$`. + +```go-html-template +Language Outside: {{ site.Language.Lang }} +Page Outside: {{ .RelPermalink }} +I18n Outside: {{ i18n "hello" }} +{{ $data := (dict "page" . )}} +{{ with (templates.Defer (dict "data" $data )) }} + Language Inside: {{ site.Language.Lang }} + Page Inside: {{ .page.RelPermalink }} + I18n Inside: {{ i18n "hello" }} +{{ end }} +``` + +The [output format](/configuration/output-formats/), [site](/methods/page/site/), and [language](/methods/site/language) will be the same, even if the execution is deferred. In the example above, this means that the `site.Language.Lang` and `.RelPermalink` will be the same on the inside and the outside of the deferred template. diff --cc docs/content/en/functions/time/ParseDuration.md index af5d73ad5,000000000..418632fc8 mode 100644,000000..100644 --- a/docs/content/en/functions/time/ParseDuration.md +++ b/docs/content/en/functions/time/ParseDuration.md @@@ -1,32 -1,0 +1,32 @@@ +--- +title: time.ParseDuration +description: Returns a time.Duration value by parsing the given duration string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: time.Duration + signatures: [time.ParseDuration DURATION] +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`. + +This template: + +```go-html-template +{{ $duration := time.ParseDuration "24h" }} +{{ printf "There are %.0f seconds in one day." $duration.Seconds }} +``` + +Is rendered to: + +```text +There are 86400 seconds in one day. +``` + +[`time.Duration`]: https://pkg.go.dev/time#Duration +[methods]: /methods/duration/ diff --cc docs/content/en/functions/transform/PortableText.md index 7baba99d4,000000000..fa9a91e33 mode 100644,000000..100644 --- a/docs/content/en/functions/transform/PortableText.md +++ b/docs/content/en/functions/transform/PortableText.md @@@ -1,213 -1,0 +1,215 @@@ +--- +title: transform.PortableText +description: Converts Portable Text to Markdown. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [transform.PortableText MAP] +--- + +{{< new-in "0.145.0" />}} + +[Portable Text](https://www.portabletext.org/) is a JSON structure that represent rich text content in the [Sanity](https://www.sanity.io/) CMS. In Hugo, this function is typically used in a [Content Adapter](https://gohugo.io/content-management/content-adapters/) that creates pages from Sanity data. + +## Types supported + +- `block` and `span` +- `image`. Note that the image handling is currently very simple; we link to the `asset.url` using `asset.altText` as the image alt text and `asset.title` as the title. For more fine grained control you may want to process the images in a [image render hook](/render-hooks/images/). +- `code` (see the [code-input](https://www.sanity.io/plugins/code-input) plugin). Code will be rendered as [fenced code blocks](/contribute/documentation/#fenced-code-blocks) with any file name provided passed on as a markdown attribute. + +> [!note] +> Since the Portable Text gets converted to Markdown before it gets passed to Hugo, rendering of links, headings, images and code blocks can be controlled with [Render Hooks](https://gohugo.io/render-hooks/). + +## Example + +### Content Adapter + +```go-html-template {file="content/_content.gotmpl" copy=true} +{{ $projectID := "mysanityprojectid" }} +{{ $useCached := true }} +{{ $api := "api" }} +{{ if $useCached }} + {{/* See https://www.sanity.io/docs/api-cdn */}} + {{ $api = "apicdn" }} +{{ end }} +{{ $url := printf "https://%s.%s.sanity.io/v2021-06-07/data/query/production" $projectID $api }} + +{{/* prettier-ignore-start */ -}} +{{ $q := `*[_type == 'post']{ + title, publishedAt, summary, slug, body[]{ + ..., + _type == "image" => { + ..., + asset->{ + _id, + path, + url, + altText, + title, + description, + metadata { + dimensions { + aspectRatio, + width, + height + } + } + } + } + }, + }` +}} +{{/* prettier-ignore-end */ -}} +{{ $body := dict "query" $q | jsonify }} +{{ $opts := dict "method" "post" "body" $body }} +{{ $r := resources.GetRemote $url $opts }} +{{ $m := $r | transform.Unmarshal }} +{{ $result := $m.result }} +{{ range $result }} + {{ if not .slug }} + {{ continue }} + {{ end }} + {{ $markdown := transform.PortableText .body }} + {{ $content := dict + "mediaType" "text/markdown" + "value" $markdown + }} + {{ $params := dict + "portabletext" (.body | jsonify (dict "indent" " ")) + }} + {{ $page := dict + "content" $content + "kind" "page" + "path" .slug.current + "title" .title + "date" (.publishedAt | time ) + "summary" .summary + "params" $params + }} + {{ $.AddPage $page }} +{{ end }} +``` + +### Sanity setup + +Below outlines a suitable Sanity studio setup for the above example. + +```ts {file="sanity.config.ts" copy=true} +import {defineConfig} from 'sanity' +import {structureTool} from 'sanity/structure' +import {visionTool} from '@sanity/vision' +import {schemaTypes} from './schemaTypes' +import {media} from 'sanity-plugin-media' +import {codeInput} from '@sanity/code-input' + +export default defineConfig({ + name: 'default', + title: 'my-sanity-project', + + projectId: 'mysanityprojectid', + dataset: 'production', + + plugins: [structureTool(), visionTool(), media(),codeInput()], + + schema: { + types: schemaTypes, + }, +}) +``` + +Type/schema definition: + +```ts {file="schemaTypes/postType.ts" copy=true} +import {defineField, defineType} from 'sanity' + +export const postType = defineType({ + name: 'post', + title: 'Post', + type: 'document', + fields: [ + defineField({ + name: 'title', + type: 'string', + validation: (rule) => rule.required(), + }), + defineField({ + name: 'summary', + type: 'string', + validation: (rule) => rule.required(), + }), + defineField({ + name: 'slug', + type: 'slug', + options: {source: 'title'}, + validation: (rule) => rule.required(), + }), + defineField({ + name: 'publishedAt', + type: 'datetime', + initialValue: () => new Date().toISOString(), + validation: (rule) => rule.required(), + }), + defineField({ + name: 'body', + type: 'array', + of: [ + { + type: 'block', + }, + { + type: 'image' + }, + { + type: 'code', + options: { + language: 'css', + languageAlternatives: [ + {title: 'HTML', value: 'html'}, + {title: 'CSS', value: 'css'}, + ], + withFilename: true, + }, + }, + ], + }), + ], +}) +``` + +Note that the above requires some additional plugins to be installed: + +```bash +npm i sanity-plugin-media @sanity/code-input +``` + +```ts {file="schemaTypes/index.ts" copy=true} +import {postType} from './postType' + +export const schemaTypes = [postType] +``` + +## Server setup + +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: + ++ +{{< code-toggle file=hugo >}} +[HTTPCache] + [[HTTPCache.polls]] + disable = false + low = '30s' + high = '3m' + [HTTPCache.polls.for] + includes = ['https://*.*.sanity.io/**'] + +[caches.getresource] + dir = ':cacheDir/:project' + maxAge = "5m" +{{< /code-toggle >}} ++ + +The polling above will be used when running the server/watch mode and rebuild when you push new content in Sanity. + +See [Caching in resources.GetRemote](/functions/resources/getremote/#caching) for more fine grained control. diff --cc docs/content/en/functions/transform/ToMath.md index 0beb8f56a,000000000..be62e8bce mode 100644,000000..100644 --- a/docs/content/en/functions/transform/ToMath.md +++ b/docs/content/en/functions/transform/ToMath.md @@@ -1,177 -1,0 +1,171 @@@ +--- +title: transform.ToMath +description: Renders mathematical equations and expressions written in the LaTeX markup language. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: template.HTML + signatures: ['transform.ToMath INPUT [OPTIONS]'] +aliases: [/functions/tomath] +--- + +{{< new-in 0.132.0 />}} + +Hugo uses an embedded instance of the [KaTeX] display engine to render mathematical markup to HTML. You do not need to install the KaTeX display engine. + +```go-html-template +{{ transform.ToMath "c = \\pm\\sqrt{a^2 + b^2}" }} +``` + +> [!note] +> By default, Hugo renders mathematical markup to [MathML], and does not require any CSS to display the result. +> +> To optimize rendering quality and accessibility, use the `htmlAndMathml` output option as described below. This approach requires an external stylesheet. + +```go-html-template +{{ $opts := dict "output" "htmlAndMathml" }} +{{ transform.ToMath "c = \\pm\\sqrt{a^2 + b^2}" $opts }} +``` + +## Options + +Pass a map of options as the second argument to the `transform.ToMath` function. The options below are a subset of the KaTeX [rendering options]. + +displayMode +: (`bool`) Whether to render in display mode instead of inline mode. Default is `false`. + +errorColor +: (`string`) The color of the error messages expressed as an RGB [hexadecimal color]. Default is `#cc0000`. + +fleqn +: (`bool`) Whether to render flush left with a 2em left margin. Default is `false`. + +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`. + +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 - ++ ```html ++ + +strict +: {{< new-in 0.147.6 />}} +: (`string`) Controls how KaTeX handles LaTeX features that offer convenience but aren't officially supported, one of `error`, `ignore`, or `warn`. Default is `error`. + + - `error`: Throws an error when convenient, unsupported LaTeX features are encountered. + - `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`. + +## Error handling + +There are three ways to handle errors: + +1. Let KaTeX throw an error and fail the build. This is the default behavior. +1. Set the `throwOnError` option to `false` to make KaTeX render the expression as an error instead of throwing an error. See [options](#options). +1. Handle the error in your template. + +The example below demonstrates error handing within a template. + +## Example + +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. - - {{< code-toggle file=hugo copy=true >}} - [markup.goldmark.extensions.passthrough] - enable = true - - [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. - - ### Step 2 - - 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/baseof.html" copy=true} - - {{ $noop := .WordCount }} - {{ if .Page.Store.Get "hasMath" }} - - {{ end }} - - ``` - - 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. - - ### Step 4 ++[passthrough extension]: /configuration/markup/#passthrough + - Add some mathematical markup to your content, then test. ++ {{< code-toggle file=hugo copy=true >}} ++ [markup.goldmark.extensions.passthrough] ++ enable = true ++ [markup.goldmark.extensions.passthrough.delimiters] ++ block = [['\[', '\]'], ['$$', '$$']] ++ inline = [['\(', '\)']] ++ {{< /code-toggle >}} + - ```text {file="content/example.md"} - This is an inline \(a^*=x-b^*\) equation. ++ > [!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. + - These are block equations: ++Step 2 ++: Create a [passthrough render hook][] to capture and render the LaTeX markup.4 + - \[a^*=x-b^*\] ++[passthrough render hook]: /render-hooks/passthrough/ + - $$a^*=x-b^*$$ - ``` ++ ```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/baseof.html" copy=true} ++ ++ {{ $noop := .WordCount }} ++ {{ if .Page.Store.Get "hasMath" }} ++ ++ {{ end }} ++ ++ ``` ++ ++ 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. ++ ++Step 4 ++: 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^*$$ ++ ``` + +## Chemistry + +{{< new-in 0.144.0 />}} + +You can also use the `transform.ToMath` function to render chemical equations, leveraging the `\ce` and `\pu` functions from the [mhchem] package. + +```text +$$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$ +``` + +$$C_p[\ce{H2O(l)}] = \pu{75.3 J // mol K}$$ + +[hexadecimal color]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color +[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 diff --cc docs/content/en/getting-started/directory-structure.md index 3feecd135,000000000..d01822c96 mode 100644,000000..100644 --- a/docs/content/en/getting-started/directory-structure.md +++ b/docs/content/en/getting-started/directory-structure.md @@@ -1,207 -1,0 +1,204 @@@ +--- +title: Directory structure +description: An overview of Hugo's directory structure. +categories: [] +keywords: [] +weight: 30 +aliases: [/overview/source-directory/] +--- + +Each Hugo project is a directory, with subdirectories that contribute to the content, structure, behavior, and presentation of your site. + +## Site skeleton + +Hugo generates a project skeleton when you create a new site. For example, this command: + +```sh +hugo new site my-site +``` + +Creates this directory structure: + +```txt +my-site/ +├── archetypes/ +│ └── default.md +├── assets/ +├── content/ +├── data/ +├── i18n/ +├── layouts/ +├── static/ +├── themes/ +└── hugo.toml <-- site configuration +``` + +Depending on requirements, you may wish to organize your site configuration into subdirectories: + +```txt +my-site/ +├── archetypes/ +│ └── default.md +├── assets/ +├── config/ <-- site configuration +│ └── _default/ +│ └── hugo.toml +├── content/ +├── data/ +├── i18n/ +├── layouts/ +├── static/ +└── themes/ +``` + +When you build your site, Hugo creates a `public` directory, and typically a `resources` directory as well: + +```txt +my-site/ +├── archetypes/ +│ └── default.md +├── assets/ +├── config/ +│ └── _default/ +│ └── hugo.toml +├── content/ +├── data/ +├── i18n/ +├── layouts/ +├── public/ <-- created when you build your site +├── resources/ <-- created when you build your site +├── static/ +└── themes/ +``` + +## Directories + +Each of the subdirectories contributes to the content, structure, behavior, or presentation of your site. + +archetypes +: The `archetypes` directory contains templates for new content. See [details](/content-management/archetypes/). + +assets +: The `assets` directory contains global resources typically passed through an asset pipeline. This includes resources such as images, CSS, Sass, JavaScript, and TypeScript. See [details](/hugo-pipes/introduction/). + +config +: The `config` directory contains your site configuration, possibly split into multiple subdirectories and files. For projects with minimal configuration or projects that do not need to behave differently in different environments, a single configuration file named `hugo.toml` in the root of the project is sufficient. See [details](/configuration/introduction/#configuration-directory). + +content +: The `content` directory contains the markup files (typically Markdown) and page resources that comprise the content of your site. See [details](/content-management/organization/). + +data +: The `data` directory contains data files (JSON, TOML, YAML, or XML) that augment content, configuration, localization, and navigation. See [details](/content-management/data-sources/). + +i18n +: The `i18n` directory contains translation tables for multilingual sites. See [details](/content-management/multilingual/). + +layouts +: The `layouts` directory contains templates to transform content, data, and resources into a complete website. See [details](/templates/). + +public +: The `public` directory contains the published website, generated when you run the `hugo` or `hugo server` commands. Hugo recreates this directory and its content as needed. See [details](/getting-started/usage/#build-your-site). + +resources +: The `resources` directory contains cached output from Hugo's asset pipelines, generated when you run the `hugo` or `hugo server` commands. By default this cache directory includes CSS and images. Hugo recreates this directory and its content as needed. + +static +: The `static` directory contains files that will be copied to the `public` directory when you build your site. For example: `favicon.ico`, `robots.txt`, and files that verify site ownership. Before the introduction of [page bundles](g) and [asset pipelines](/hugo-pipes/introduction/), the `static` directory was also used for images, CSS, and JavaScript. + +themes +: The `themes` directory contains one or more [themes](g), each in its own subdirectory. + +## Union file system + +Hugo creates a union file system, allowing you to mount two or more directories to the same location. For example, let's say your home directory contains a Hugo project in one directory, and shared content in another: + +```text +home/ +└── user/ + ├── my-site/ + │ ├── content/ + │ │ ├── books/ + │ │ │ ├── _index.md + │ │ │ ├── book-1.md + │ │ │ └── book-2.md + │ │ └── _index.md + │ ├── themes/ + │ │ └── my-theme/ + │ └── hugo.toml + └── shared-content/ + └── films/ + ├── _index.md + ├── film-1.md + └── film-2.md +``` + +You can include the shared content when you build your site using mounts. In your site configuration: + +{{< code-toggle file=hugo >}} +[[module.mounts]] +source = 'content' +target = 'content' + +[[module.mounts]] +source = '/home/user/shared-content' +target = 'content' +{{< /code-toggle >}} + +> [!note] +> When you overlay one directory on top of another, you must mount both directories. +> +> Hugo does not follow symbolic links. If you need the functionality provided by symbolic links, use Hugo's union file system instead. + +After mounting, the union file system has this structure: + +```text +home/ +└── user/ + └── my-site/ + ├── content/ + │ ├── books/ + │ │ ├── _index.md + │ │ ├── book-1.md + │ │ └── book-2.md + │ ├── films/ + │ │ ├── _index.md + │ │ ├── film-1.md + │ │ └── film-2.md + │ └── _index.md + ├── themes/ + │ └── my-theme/ + └── hugo.toml +``` + +> [!note] +> When two or more files have the same path, the order of precedence follows the order of the mounts. For example, if the shared content directory contains `books/book-1.md`, it will be ignored because the project's `content` directory was mounted first. + +You can mount directories to `archetypes`, `assets`, `content`, `data`, `i18n`, `layouts`, and `static`. See [details](/configuration/module/#mounts). + +You can also mount directories from Git repositories using Hugo Modules. See [details](/hugo-modules/). + +## Theme skeleton + +Hugo generates a functional theme skeleton when you create a new theme. For example, this command: + +```text +hugo new theme my-theme +``` + +Creates this directory structure (subdirectories not shown): + +```text +my-theme/ +├── archetypes/ +├── assets/ +├── content/ +├── data/ +├── 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. + +If you are simultaneously using components from two or more themes or modules, and there's a path collision, the first mount takes precedence. diff --cc docs/content/en/getting-started/external-learning-resources/index.md index f36544c02,000000000..d3101be18 mode 100644,000000..100644 --- a/docs/content/en/getting-started/external-learning-resources/index.md +++ b/docs/content/en/getting-started/external-learning-resources/index.md @@@ -1,83 -1,0 +1,86 @@@ +--- +title: External learning resources +linkTitle: External resources +description: Use these third-party resources to learn Hugo. +categories: [] +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 + +Hugo in Action is a step-by-step guide to using Hugo to create static websites. Working with a complete example website and source code samples, you'll learn how to build and host a low-maintenance, high-performance site that will wow your users and stay stable without relying on a third-party server. + +[{{< img src="hugo-in-action.png" alt="Book cover: Hugo in Action" filter="process" filterArgs="resize x350 webp">}}](https://www.manning.com/books/hugo-in-action/) + +Author: Atishay Jain\ +Publisher: [Manning Publications](https://www.manning.com/books/hugo-in-action/)\ +Publication date: March 2022\ +Length: 488 pages\ +ISBN: 9781617297007 + +### Build Websites with Hugo + +In this book, you'll use Hugo to build a personal portfolio site that you can use to showcase your skills and thoughts to the world. You'll build the basic skeleton, develop a custom theme, and use content templates to generate new pages quickly. You'll use internal and external data sources to embed content into your site and render some of your content in JSON and RSS. You'll add a blog section with posts and integrate Disqus with your site, and then make your site searchable. + +[{{< img src="build-websites-with-hugo.png" alt="Book cover: Build Websites with Hugo" filter="process" filterArgs="resize x350 webp">}}](https://pragprog.com/titles/bhhugo/build-websites-with-hugo/) + +Author: Brian P. Hogan\ +Publisher: [Pragmatic Bookshelf](https://pragprog.com/titles/bhhugo/build-websites-with-hugo/)\ +Publication date: May 2020\ +Length: 154 pages\ +ISBN: 9781680507263 + +## Videos + +### Hugo Beginner Tutorial Series + +Welcome to this introduction to Hugo tutorial. This series aims to take you from a lion cub with basic web design knowledge to creating your first Hugo website. In this series, you'll learn how to set up a Hugo site, the basics of using Hugo layouts, partials, and templating, set up a blog, and finally, use data files. By the end of this series, you'll have the foundational knowledge to build your own Hugo sites. + +1. [Getting set up in Hugo](https://cloudcannon.com/tutorials/hugo-beginner-tutorial/) +1. [Layouts in Hugo](https://cloudcannon.com/tutorials/hugo-beginner-tutorial/layouts-in-hugo/) +1. [Hugo Partials](https://cloudcannon.com/tutorials/hugo-beginner-tutorial/hugo-partials/) +1. [Hugo templating basics](https://cloudcannon.com/tutorials/hugo-beginner-tutorial/hugo-templating-basics/) +1. [Blogging in Hugo](https://cloudcannon.com/tutorials/hugo-beginner-tutorial/blogging-in-hugo/) +1. [Using Data in Hugo](https://cloudcannon.com/tutorials/hugo-beginner-tutorial/using-data-in-hugo/) + +Creator: Mike Neumegen\ +Affiliation: [CloudCannon](https://cloudcannon.com/)\ +Creation date: April 2022 + +### Hugo Static Site Generator + +This course covers the basics of using the Hugo static site generator. Work your way through the articles, and we'll teach you everything you need to know to create a professional and scalable website or blog! + +1. [Introduction](https://www.giraffeacademy.com/static-site-generators/hugo/) +1. [Windows Installation](https://www.giraffeacademy.com/static-site-generators/hugo/installing-hugo-on-windows/) +1. [Mac Installation](https://www.giraffeacademy.com/static-site-generators/hugo/installing-hugo-on-mac/) +1. [Creating A New Site](https://www.giraffeacademy.com/static-site-generators/hugo/hugo-directory-structure/) +1. [Installing & Using Themes](https://www.giraffeacademy.com/static-site-generators/hugo/installing-using-themes/) +1. [Content Organization](https://www.giraffeacademy.com/static-site-generators/hugo/content-organization/) +1. [Front Matter](https://www.giraffeacademy.com/static-site-generators/hugo/front-matter/) +1. [Archetypes](https://www.giraffeacademy.com/static-site-generators/hugo/archetypes/) +1. [Shortcodes](https://www.giraffeacademy.com/static-site-generators/hugo/shortcodes/) +1. [Taxonomies](https://www.giraffeacademy.com/static-site-generators/hugo/taxonomies/) +1. [Template Basics](https://www.giraffeacademy.com/static-site-generators/hugo/introduction-to-templates/) +1. [List Page Templates](https://www.giraffeacademy.com/static-site-generators/hugo/list-page-templates/) +1. [Single Page Templates](https://www.giraffeacademy.com/static-site-generators/hugo/single-page-templates/) +1. [Home Page Templates](https://www.giraffeacademy.com/static-site-generators/hugo/home-page-templates/) +1. [Section Templates](https://www.giraffeacademy.com/static-site-generators/hugo/section-templates/) +1. [Block Templates](https://www.giraffeacademy.com/static-site-generators/hugo/block-templates/) +1. [Variables](https://www.giraffeacademy.com/static-site-generators/hugo/variables/) +1. [Functions](https://www.giraffeacademy.com/static-site-generators/hugo/functions/) +1. [Conditionals](https://www.giraffeacademy.com/static-site-generators/hugo/conditionals/) +1. [Data Templates](https://www.giraffeacademy.com/static-site-generators/hugo/data-templates/) +1. [Partial Templates](https://www.giraffeacademy.com/static-site-generators/hugo/partial-templates/) +1. [Shortcode Templates](https://www.giraffeacademy.com/static-site-generators/hugo/shortcode-templates/) +1. [Building & Hosting](https://www.giraffeacademy.com/static-site-generators/hugo/building-&-hosting/) + +Creator: Mike Dane\ +Affiliation: [Giraffe Academy](https://www.giraffeacademy.com/)\ +Creation date: September 2017 diff --cc docs/content/en/host-and-deploy/host-on-aws-amplify/index.md index e2b35dbbe,000000000..4fd71f3f9 mode 100644,000000..100644 --- a/docs/content/en/host-and-deploy/host-on-aws-amplify/index.md +++ b/docs/content/en/host-and-deploy/host-on-aws-amplify/index.md @@@ -1,160 -1,0 +1,157 @@@ +--- +title: Host on AWS Amplify +description: Host your site on AWS Amplify. +categories: [] +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 - - Create a file named `amplify.yml` in the root of your project. - - ```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. - - ```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 - - 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 - - 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 - - # Check installed versions - - go version - - hugo version - - node -v - - npm -v - - sass --embedded --version - - # Install Node.JS dependencies - - "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci --prefer-offline || true" - - # 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. - - ```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 1 ++: Create a file named `amplify.yml` in the root of your project. ++ ++ ```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. ++ ++ ```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" ++ ++ # 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}" ++ ++ # Verify installations ++ - echo "Verifying installations..." ++ - "echo Dart Sass: $(sass --version)" ++ - "echo Go: $(go version)" ++ - "echo Hugo: $(hugo version)" ++ - "echo Node.js: $(node --version)" ++ ++ # Install Node.js dependencies ++ - echo "Installing 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}/**/* ++ ``` ++ ++Step 3 ++: Commit and push the change to your GitHub repository. ++ ++ ```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. ++ ++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 - - 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 ++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 "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 diff --cc docs/content/en/host-and-deploy/host-on-cloudflare/cloudflare-01.png index 000000000,000000000..9c7a4380d new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-cloudflare/cloudflare-02.png index 000000000,000000000..595a164ea new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-cloudflare/cloudflare-03.png index 000000000,000000000..6d4228b4a new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-cloudflare/cloudflare-04.png index 000000000,000000000..12fa0cbd8 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-cloudflare/cloudflare-05.png index 000000000,000000000..d907844d1 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-cloudflare/cloudflare-06.png index 000000000,000000000..33010b11d new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-cloudflare/cloudflare-07.png index 000000000,000000000..10ed1c7c6 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-cloudflare/cloudflare-08.png index 000000000,000000000..396387314 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-cloudflare/index.md index 000000000,000000000..018c50f0a new file mode 100644 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-cloudflare/index.md @@@ -1,0 -1,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. diff --cc docs/content/en/host-and-deploy/host-on-codeberg-pages.md index 2a881f718,000000000..3c7e7a847 mode 100644,000000..100644 --- a/docs/content/en/host-and-deploy/host-on-codeberg-pages.md +++ b/docs/content/en/host-and-deploy/host-on-codeberg-pages.md @@@ -1,255 -1,0 +1,282 @@@ +--- +title: Host on Codeberg Pages +description: Host your site on Codeberg Pages. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-codeberg/] +--- + +## Assumptions + +- Working familiarity with [Git] for version control +- Completion of the Hugo [Quick Start] +- A [Codeberg account] +- A Hugo website on your local machine that you are ready to publish + +[Codeberg account]: https://codeberg.org/user/login/ +[Git]: https://git-scm.com/ +[Quick Start]: /getting-started/quick-start/ + +Any and all mentions of `` refer to your actual Codeberg username and must be substituted accordingly. Likewise, `` represents your actual website name. + +## BaseURL + +The [`baseURL`] in your site configuration must reflect the full URL provided by Codeberg Pages if using the default address (e.g. `https://.codeberg.page/`). If you want to use another domain, follow the instructions in the [custom domain section] of the official documentation. + +[`baseURL`]: /configuration/all/#baseurl +[custom domain section]: https://docs.codeberg.org/codeberg-pages/using-custom-domain/ + +For more details regarding the URL of your deployed website, refer to Codeberg Pages' [quickstart instructions]. + +[quickstart instructions]: https://codeberg.page/ + +## Manual deployment + +Create a public repository on your Codeberg account titled `pages` or create a branch of the same name in an existing public repository. Finally, push the contents of Hugo's output directory (by default, `public`) to it. Here's an example: + +```sh +# build the website +hugo + +# access the output directory +cd public + +# initialize new git repository +git init + +# commit and push code to main branch +git add . +git commit -m "Initial commit" +git remote add origin https://codeberg.org//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]. + +[request]: https://codeberg.org/Codeberg-e.V./requests/issues/new?template=ISSUE_TEMPLATE%2fWoodpecker-CI.yaml +[examples repository]: https://codeberg.org/Codeberg-CI/examples/src/branch/main/Hugo/.woodpecker.yaml + +In this case, you must create a public repository on Codeberg (e.g. ``) and push your local project to it. Here's an example: + +```sh +# initialize new git repository +git init + +# add /public directory to our .gitignore file +echo "/public" >> .gitignore + +# commit and push code to main branch +git add . +git commit -m "Initial commit" +git remote add origin https://codeberg.org//.git +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. + +[great documentation]: https://docs.codeberg.org/ci/actions/ +[handful of humble runners]: https://codeberg.org/actions/meta + +To deploy your website this way, you don't need to request any access. All you need to do is enable actions in your repository settings (see the documentation link above) and add a workflow configuration file, for example, `hugo.yaml`, to the `.forgejo/workflows/` directory in your website's source repository. + +Two examples of such a file are provided below. + +The first file should work for automatically building your website from the source branch (`main` in this case) and committing the result to the target branch (`pages`). Without changes, this file should make your built website accessible under `https://.codeberg.page//`: + +```yaml {file=".forgejo/workflows/hugo.yaml" copy=true} +name: Deploy Hugo site to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: + # If you want to build from a different branch, change it here. + - main + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + build: + # You can find the list of available runners on https://codeberg.org/actions/meta, or run one yourself. + 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 + with: + submodules: recursive + fetch-depth: 0 + - name: Generate static files with Hugo + env: + # For maximum backward compatibility with Hugo modules + HUGO_ENVIRONMENT: production + HUGO_ENV: production + run: | + hugo \ + --gc \ + --minify + - name: Upload generated files + uses: https://code.forgejo.org/actions/upload-artifact@v3 + with: + name: Generated files + path: public/ + deploy: + needs: [ build ] + runs-on: codeberg-tiny-lazy + steps: + - name: Clone the repository + uses: https://code.forgejo.org/actions/checkout@v4 + with: + submodules: recursive + fetch-depth: 0 + - name: Checkout the target branch and clean it up + # If you want to commit to a branch other than "pages", change the two references below, as well as the reference in the last step. + run: | + git checkout pages || git switch --orphan pages && \ + rm -Rfv $(ls -A | egrep -v '^(\.git|LICENSE)$') + - name: Download generated files + uses: https://code.forgejo.org/actions/download-artifact@v3 + with: + name: Generated files + - name: Publish the website + run: | + git config user.email codeberg-ci && \ + git config user.name "Codeberg CI" && \ + git add . && \ + git commit --allow-empty --message "Codeberg build for ${GITHUB_SHA}" && \ + git push origin pages +``` + +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://.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` | `/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) | ++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`|`/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: + +```yaml {file=".forgejo/workflows/hugo.yaml" copy=true} +name: Deploy Hugo site to Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: + # If you want to build from a different branch, change it here. + - main + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + build: + 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 + with: + submodules: recursive + fetch-depth: 0 + - name: Generate static files with Hugo + env: + # For maximum backward compatibility with Hugo modules + HUGO_ENVIRONMENT: production + HUGO_ENV: production + run: | + hugo \ + --gc \ + --minify \ + --source ${PWD} \ + --destination ${PWD}/public/ + - name: Upload generated files + uses: https://code.forgejo.org/actions/upload-artifact@v3 + with: + name: Generated files + path: public/ + deploy: + needs: [ build ] + runs-on: codeberg-tiny-lazy + steps: + - name: Clone the repository + uses: https://code.forgejo.org/actions/checkout@v4 + with: + repository: ${{ vars.TARGET_REPOSITORY }} + ref: ${{ vars.TARGET_BRANCH }} + submodules: recursive + fetch-depth: 0 + ssh-key: ${{ secrets.DEPLOY_KEY }} + ssh-known-hosts: ${{ vars.SSH_KNOWN_HOSTS }} + - name: Remove all files + run: | + rm -Rfv $(ls -A | egrep -v '^(\.git|LICENSE)$') + - name: Download generated files + uses: https://code.forgejo.org/actions/download-artifact@v3 + with: + name: Generated files + - name: Commit and push the website + run: | + git config user.email codeberg-ci && \ + git config user.name "Codeberg CI" && \ + git add -v . && \ + git commit -v --allow-empty --message "Codeberg build for ${GITHUB_SHA}" && \ + git push -v origin ${{ vars.TARGET_BRANCH }} +``` + +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/) +- [Codeberg Pages official documentation](https://docs.codeberg.org/codeberg-pages/) diff --cc docs/content/en/host-and-deploy/host-on-firebase.md index 267c8d127,000000000..064ecadad mode 100644,000000..100644 --- a/docs/content/en/host-and-deploy/host-on-firebase.md +++ b/docs/content/en/host-and-deploy/host-on-firebase.md @@@ -1,106 -1,0 +1,106 @@@ +--- +title: Host on Firebase +description: Host your site on Firebase. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-firebase/] +--- + +## Assumptions + +1. You have an account with [Firebase][signup]. (If you don't, you can sign up for free using your Google account.) +1. You have completed the [Quick Start] or have a completed Hugo website ready for deployment. + +## Initial setup + +Go to the [Firebase console][console] and create a new project (unless you already have a project). You will need to globally install `firebase-tools` (node.js): + +```sh +npm install -g firebase-tools +``` + +Log in to Firebase (setup on your local machine) using `firebase login`, which opens a browser where you can select your account. Use `firebase logout` in case you are already logged in but to the wrong account. + +```sh +firebase login +``` + +In the root of your Hugo project, initialize the Firebase project with the `firebase init` command: + +```sh +firebase init +``` + +From here: + +1. Choose Hosting in the feature question +1. Choose the project you just set up +1. Accept the default for your database rules file +1. Accept the default for the publish directory, which is `public` +1. Choose "No" in the question if you are deploying a single-page app + +## Using Firebase & GitHub CI/CD + +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: + +```sh +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 . + +Don't forget to update your static pages before push! + +## Manual deploy + +To deploy your Hugo site, execute the `firebase deploy` command, and your site will be up in no time: + +```sh +hugo && firebase deploy +``` + +## CI setup (other tools) + +You can generate a deploy token using + +```sh +firebase login:ci +``` + +You can also set up your CI and add the token to a private variable like `$FIREBASE_DEPLOY_TOKEN`. + +> [!note] +> This is a private secret and it should not appear in a public repository. Make sure you understand your chosen CI and that it's not visible to others. + +You can then add a step in your build to do the deployment using the token: + +```sh +firebase deploy --token $FIREBASE_DEPLOY_TOKEN +``` + +## Reference links + +- [Firebase CLI Reference](https://firebase.google.com/docs/cli/#administrative_commands) + +[console]: https://console.firebase.google.com/ +[Quick Start]: /getting-started/quick-start/ +[signup]: https://console.firebase.google.com/ diff --cc docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-01.png index 000000000,000000000..29912f25c new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-02.png index 000000000,000000000..0050d33e2 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-03.png index 000000000,000000000..d2904cae1 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-04.png index 000000000,000000000..75774462b new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-05.png index 000000000,000000000..efe26129a new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-github-pages/index.md index 165c9934c,000000000..dd4039dd8 mode 100644,000000..100644 --- a/docs/content/en/host-and-deploy/host-on-github-pages/index.md +++ b/docs/content/en/host-and-deploy/host-on-github-pages/index.md @@@ -1,237 -1,0 +1,208 @@@ +--- +title: Host on GitHub Pages +description: Host your site on GitHub Pages. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-github/] +--- + - ## Prerequisites - - Please complete the following tasks before continuing: - - 1. [Create a GitHub account] - 1. [Install Git] - 1. [Create a Hugo site] and test it locally with `hugo server`. - +## Types of sites + +There are three types of GitHub Pages sites: project, user, and organization. Project sites are connected to a specific project hosted on GitHub. User and organization sites are connected to a specific account on GitHub.com. + +> [!note] +> See the [GitHub Pages documentation] to understand the requirements for repository ownership and naming. + - ## Procedure - - ### Step 1 - - Create a GitHub repository. - - ### Step 2 - - Push your local repository to GitHub. - - ### Step 3 - - Visit your GitHub repository. From the main menu choose **Settings** > **Pages**. In the center of your screen you will see this: - - ![screen capture](gh-pages-1.png) - {style="max-width: 280px"} - - ### Step 4 - - Change the **Source** to `GitHub Actions`. The change is immediate; you do not have to press a Save button. - - ![screen capture](gh-pages-2.png) - {style="max-width: 280px"} - - ### Step 5 - - In your site configuration, change the location of the image cache to the [`cacheDir`] as shown below: - - {{< code-toggle file=hugo >}} - [caches.images] - dir = ":cacheDir/images" - {{< /code-toggle >}} - - See [configure file caches] for more information. - - ### Step 6 - - Create a file named `hugo.yaml` in a directory named `.github/workflows`. - - ```text - mkdir -p .github/workflows - touch .github/workflows/hugo.yaml - ``` - - ### Step 7 - - > [!note] - > The workflow below ensures Hugo's `cacheDir` is persistent, preserving modules, processed images, and [`resources.GetRemote`] data between builds. - - Copy and paste the YAML below into the file you created. Change the branch name and Hugo version as needed. - - ```yaml {file=".github/workflows/hugo.yaml" copy=true} - # Sample workflow for building and deploying a Hugo site to GitHub Pages - name: Deploy Hugo site to Pages - - on: - # Runs on pushes targeting the default branch - push: - branches: - - main - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - - # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages - permissions: - contents: read - pages: write - id-token: write - - # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. - # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. - concurrency: - group: "pages" - cancel-in-progress: false - - # Default to bash - defaults: - run: - shell: bash - - jobs: - # Build job - build: - runs-on: ubuntu-latest - env: - DART_SASS_VERSION: 1.89.2 - HUGO_VERSION: 0.147.9 - HUGO_ENVIRONMENT: production - TZ: America/Los_Angeles - steps: - - name: Install Hugo CLI - run: | - wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \ - && sudo dpkg -i ${{ runner.temp }}/hugo.deb - - name: Install Dart Sass - run: | - wget -O ${{ runner.temp }}/dart-sass.tar.gz https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz \ - && tar -xf ${{ runner.temp }}/dart-sass.tar.gz --directory ${{ runner.temp }} \ - && mv ${{ runner.temp }}/dart-sass/ /usr/local/bin \ - && echo "/usr/local/bin/dart-sass" >> $GITHUB_PATH - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - fetch-depth: 0 - - name: Setup Pages - id: pages - uses: actions/configure-pages@v5 - - name: Install Node.js dependencies - run: "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true" - - name: Cache Restore - id: cache-restore - uses: actions/cache/restore@v4 - with: - path: | - ${{ runner.temp }}/hugo_cache - key: hugo-${{ github.run_id }} - restore-keys: - hugo- - - name: Configure Git - run: git config core.quotepath false - - name: Build with Hugo - run: | - hugo \ - --gc \ - --minify \ - --baseURL "${{ steps.pages.outputs.base_url }}/" \ - --cacheDir "${{ runner.temp }}/hugo_cache" - - name: Cache Save - id: cache-save - uses: actions/cache/save@v4 - with: - path: | - ${{ runner.temp }}/hugo_cache - key: ${{ steps.cache-restore.outputs.cache-primary-key }} - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - path: ./public - - # Deployment job - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - needs: build - steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v4 - ``` - - ### Step 8 - - Commit and push the change to your GitHub repository. - - ```sh - git add -A - git commit -m "Create hugo.yaml" - git push - ``` - - ### Step 9 - - From GitHub's main menu, choose **Actions**. You will see something like this: - - ![screen capture](gh-pages-3.png) - {style="max-width: 350px"} - - ### Step 10 - - When GitHub has finished building and deploying your site, the color of the status indicator will change to green. - - ![screen capture](gh-pages-4.png) - {style="max-width: 350px"} - - ### Step 11 ++## Prerequisites + - Click on the commit message as shown above. You will see this: ++Please complete the following tasks before continuing: + - ![screen capture](gh-pages-5.png) - {style="max-width: 611px"} ++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 + - Under the deploy step, you will see a link to your live site. ++## Procedure + - In the future, whenever you push a change from your local repository, GitHub will rebuild your site and deploy the changes. ++Step 1 ++: Visit your GitHub repository. From the main menu choose **Settings** > **Pages**. In the center of your screen you will see this: ++ ++ ![screen capture](gh-pages-01.png) ++ ++ Change the **Source** to `GitHub Actions`. The change is immediate; you do not have to press a Save button. ++ ++ ![screen capture](gh-pages-02.png) ++ ++Step 2 ++: In your site configuration, change the location of the image cache to the [`cacheDir`] as shown below: ++ ++ {{< code-toggle file=hugo copy=true >}} ++ [caches.images] ++ dir = ":cacheDir/images" ++ {{< /code-toggle >}} ++ ++ See [configure file caches] for more information. ++ ++Step 3 ++: Create a file named `hugo.yaml` in a directory named `.github/workflows`. ++ ++ ```text ++ mkdir -p .github/workflows ++ touch .github/workflows/hugo.yaml ++ ``` ++ ++Step 4 ++: Copy and paste the YAML below into the file you created. ++ ++ ```yaml {file=".github/workflows/hugo.yaml" copy=true} ++ name: Build and deploy ++ on: ++ push: ++ branches: ++ - main ++ workflow_dispatch: ++ permissions: ++ contents: read ++ pages: write ++ id-token: write ++ concurrency: ++ group: pages ++ cancel-in-progress: false ++ defaults: ++ run: ++ shell: bash ++ jobs: ++ build: ++ runs-on: ubuntu-latest ++ env: ++ DART_SASS_VERSION: 1.90.0 ++ GO_VERSION: 1.24.5 ++ HUGO_VERSION: 0.148.2 ++ NODE_VERSION: 22.18.0 ++ TZ: Europe/Oslo ++ steps: ++ - name: Checkout ++ uses: actions/checkout@v5 ++ with: ++ submodules: recursive ++ fetch-depth: 0 ++ - name: Setup Go ++ uses: actions/setup-go@v5 ++ with: ++ go-version: ${{ env.GO_VERSION }} ++ cache: false ++ - name: Setup Node.js ++ uses: actions/setup-node@v4 ++ with: ++ node-version: ${{ env.NODE_VERSION }} ++ - name: Setup Pages ++ id: pages ++ uses: actions/configure-pages@v5 ++ - name: Create directory for user-specific executable files ++ run: | ++ mkdir -p "${HOME}/.local" ++ - name: Install Dart Sass ++ run: | ++ 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" ++ echo "${HOME}/.local/dart-sass" >> "${GITHUB_PATH}" ++ - name: Install Hugo ++ run: | ++ 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" ++ echo "${HOME}/.local/hugo" >> "${GITHUB_PATH}" ++ - name: Verify installations ++ run: | ++ echo "Dart Sass: $(sass --version)" ++ echo "Go: $(go version)" ++ echo "Hugo: $(hugo version)" ++ echo "Node.js: $(node --version)" ++ - name: Install Node.js dependencies ++ run: | ++ [[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true ++ - name: Configure Git ++ run: | ++ git config core.quotepath false ++ - name: Cache restore ++ id: cache-restore ++ uses: actions/cache/restore@v4 ++ with: ++ path: ${{ runner.temp }}/hugo_cache ++ key: hugo-${{ github.run_id }} ++ restore-keys: ++ hugo- ++ - name: Build the site ++ run: | ++ hugo \ ++ --gc \ ++ --minify \ ++ --baseURL "${{ steps.pages.outputs.base_url }}/" \ ++ --cacheDir "${{ runner.temp }}/hugo_cache" ++ - name: Cache save ++ id: cache-save ++ uses: actions/cache/save@v4 ++ with: ++ path: ${{ runner.temp }}/hugo_cache ++ key: ${{ steps.cache-restore.outputs.cache-primary-key }} ++ - name: Upload artifact ++ uses: actions/upload-pages-artifact@v3 ++ with: ++ path: ./public ++ deploy: ++ environment: ++ name: github-pages ++ url: ${{ steps.deployment.outputs.page_url }} ++ runs-on: ubuntu-latest ++ needs: build ++ steps: ++ - name: Deploy to GitHub Pages ++ id: deployment ++ uses: actions/deploy-pages@v4 ++ ``` ++ ++Step 5 ++: Commit the changes to your local Git repository and push to your GitHub repository. ++ ++Step 6 ++: From GitHub's main menu, choose **Actions**. You will see something like this: ++ ++ ![screen capture](gh-pages-03.png) ++ ++Step 7 ++: When GitHub has finished building and deploying your site, the color of the status indicator will change to green. ++ ++ ![screen capture](gh-pages-04.png) ++ ++Step 8 ++: Click on the commit message as shown above. Under the deploy step, you will see a link to your live site. ++ ++ ![screen capture](gh-pages-05.png) ++ ++In the future, whenever you push a change from your local Git repository, GitHub Pages will rebuild and deploy your site. + +## Customize the workflow + +The example workflow above includes this step, which typically takes 10‑15 seconds: + +```yaml +- name: Install Dart Sass + run: sudo snap install dart-sass +``` + +You may remove this step if your site, themes, and modules do not transpile Sass to CSS using the [Dart Sass] transpiler. + +## Other resources + +- [Learn more about GitHub Actions](https://docs.github.com/en/actions) +- [Caching dependencies to speed up workflows](https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows) +- [Manage a custom domain for your GitHub Pages site](https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/about-custom-domains-and-github-pages) + - [Create a GitHub account]: https://github.com/signup - [Create a Hugo site]: /getting-started/quick-start/ - [Dart Sass]: /functions/css/sass/#dart-sass - [GitHub Pages documentation]: https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages#types-of-github-pages-sites - [Install Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[`cacheDir`]: /configuration/all/#cachedir - [`resources.GetRemote`]: /functions/resources/getremote/ +[configure file caches]: /configuration/caches/ ++[Dart Sass]: /functions/css/sass/#dart-sass ++[GitHub Pages documentation]: https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages#types-of-github-pages-sites diff --cc docs/content/en/host-and-deploy/host-on-gitlab-pages.md index cf4220888,000000000..c43303804 mode 100644,000000..100644 --- a/docs/content/en/host-and-deploy/host-on-gitlab-pages.md +++ b/docs/content/en/host-and-deploy/host-on-gitlab-pages.md @@@ -1,99 -1,0 +1,136 @@@ +--- +title: Host on GitLab Pages +description: Host your site on GitLab Pages. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-gitlab/] +--- + +## Assumptions + +- Working familiarity with Git for version control +- Completion of the Hugo [Quick Start] +- A [GitLab account](https://gitlab.com/users/sign_in) +- A Hugo website on your local machine that you are ready to publish + +## BaseURL + +The `baseURL` in your [site configuration](/configuration/) must reflect the full URL of your GitLab pages repository if you are using the default GitLab Pages URL (e.g., `https://.gitlab.io//`) and not a custom domain. + +## Configure GitLab CI/CD + +Define your [CI/CD](g) jobs by creating a `.gitlab-ci.yml` file in the root of your project. + +```yaml {file=".gitlab-ci.yml" copy=true} +variables: - DART_SASS_VERSION: 1.89.2 ++ # Application versions ++ DART_SASS_VERSION: 1.90.0 ++ HUGO_VERSION: 0.148.2 ++ NODE_VERSION: 22.18.0 ++ # Git + GIT_DEPTH: 0 + GIT_STRATEGY: clone + GIT_SUBMODULE_STRATEGY: recursive - HUGO_VERSION: 0.147.9 - NODE_VERSION: 22.x - TZ: America/Los_Angeles ++ # Time zone ++ TZ: Europe/Oslo ++ +image: - name: golang:1.24.2-bookworm ++ name: golang:1.24.5-bookworm + +pages: + stage: deploy + script: - # Install brotli ++ # Create directory for user-specific executable files ++ - echo "Creating directory for user-specific executable files..." ++ - mkdir -p "${HOME}/.local" ++ ++ # Install utilities ++ - echo "Installing utilities..." + - apt-get update - - apt-get install -y brotli ++ - apt-get install -y brotli xz-utils zstd ++ + # 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* - - export PATH=/usr/local/bin/dart-sass:$PATH ++ - 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 Hugo - - curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb - - apt-get install -y ./hugo_extended_${HUGO_VERSION}_linux-amd64.deb - - rm hugo_extended_${HUGO_VERSION}_linux-amd64.deb ++ - 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 - - curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION} | bash - - - apt-get install -y nodejs ++ - 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)" ++ - "echo brotli: $(brotli --version)" ++ - "echo xz: $(xz --version)" ++ - "echo zstd: $(zstd --version)" ++ + # Install Node.js dependencies - - "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true" ++ - echo "Installing 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 - - hugo --gc --minify --baseURL ${CI_PAGES_URL} - # Compress - - find public -type f -regex '.*\.\(css\|html\|js\|txt\|xml\)$' -exec gzip -f -k {} \; - - find public -type f -regex '.*\.\(css\|html\|js\|txt\|xml\)$' -exec brotli -f -k {} \; ++ ++ # Build site ++ - echo "Building site..." ++ - hugo --gc --minify --baseURL "${CI_PAGES_URL}" ++ ++ # Compress published files ++ - echo "Compressing published files..." ++ - find public/ -type f -regextype posix-extended -regex '.+\.(css|html|js|json|mjs|svg|txt|xml)$' -print0 > files.txt ++ - time xargs --null --max-procs=0 --max-args=1 brotli --quality=10 --force --keep < files.txt ++ - time xargs --null --max-procs=0 --max-args=1 gzip -9 --force --keep < files.txt + artifacts: + paths: + - public + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH +``` + +## Push your Hugo website to GitLab + - Next, create a new repository on GitLab. It is *not* necessary to make the repository public. In addition, you might want to add `/public` to your .gitignore file, as there is no need to push compiled assets to GitLab or keep your output website in version control. ++Next, create a new repository on GitLab. It is not necessary to make the repository public. In addition, you might want to add `/public` to your .gitignore file, as there is no need to push compiled assets to GitLab or keep your output website in version control. + +```sh +# initialize new git repository +git init + +# add /public directory to our .gitignore file +echo "/public" >> .gitignore + +# commit and push code to master branch +git add . +git commit -m "Initial commit" +git remote add origin https://gitlab.com/YourUsername/your-hugo-site.git +git push -u origin master +``` + +## Wait for your page to build + +That's it! You can now follow the CI agent building your page at `https://gitlab.com///pipelines`. + +After the build has passed, your new website is available at `https://.gitlab.io//`. + +## Next steps + +GitLab supports using custom CNAME's and TLS certificates. For more details on GitLab Pages, see the [GitLab Pages setup documentation](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/). + +[Quick Start]: /getting-started/quick-start/ diff --cc docs/content/en/host-and-deploy/host-on-netlify/index.md index 61ac15da8,000000000..cc0bf6b2b mode 100644,000000..100644 --- a/docs/content/en/host-and-deploy/host-on-netlify/index.md +++ b/docs/content/en/host-and-deploy/host-on-netlify/index.md @@@ -1,146 -1,0 +1,130 @@@ +--- +title: Host on Netlify +description: Host your site on Netlify. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-netlify/] +--- + ++Use these instructions to enable continuous deployment from a GitHub repository. The same general steps apply if you are using Azure DevOps, Bitbucket, or GitLab for version control. ++ +## Prerequisites + +Please complete the following tasks before continuing: + - 1. [Create a Netlify 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 a Netlify account]: https://app.netlify.com/signup - [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://app.netlify.com/signup) a Netlify account ++1. [Log in](https://app.netlify.com/login) to your Netlify 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 - - Log in to your Netlify account, navigate to the Sites page, press the **Add new site** button, and choose "Import an existing project" from the dropdown menu. - - ### Step 2 ++Step 1 ++: Log in to your Netlify account, navigate to the Sites page, press the **Add new site** button, and choose "Import an existing project" from the dropdown menu. + - Select your deployment method. ++Step 2 ++: Select your deployment method. + + ![screen capture](netlify-step-02.png) + - ### Step 3 - - Authorize Netlify to connect with your GitHub account by pressing the **Authorize Netlify** button. - - ![screen capture](netlify-step-03.png) - - ### Step 4 - - Press the **Configure Netlify on GitHub** button. - - ![screen capture](netlify-step-04.png) ++Step 3 ++: Authorize Netlify to connect with your GitHub account by pressing the **Authorize Netlify** button. + - ### Step 5 ++ ![screen capture](netlify-step-03.png) + - Install the Netlify app by selecting your GitHub account. ++Step 4 ++: Press the **Configure Netlify on GitHub** button. + - ![screen capture](netlify-step-05.png) ++ ![screen capture](netlify-step-04.png) + - ### Step 6 ++Step 5 ++: Install the Netlify app by selecting your GitHub account. + - Press the **Install** button. ++ ![screen capture](netlify-step-05.png) + - ![screen capture](netlify-step-06.png) ++Step 6 ++: Press the **Install** button. + - ### Step 7 ++ ![screen capture](netlify-step-06.png) + - Click on the site's repository from the list. ++Step 7 ++: Click on the site's repository from the list. + - ![screen capture](netlify-step-07.png) ++ ![screen capture](netlify-step-07.png) + - ### Step 8 ++Step 8 ++: Set the site name and branch from which to deploy. + - Set the site name and branch from which to deploy. ++ ![screen capture](netlify-step-08.png) + - ![screen capture](netlify-step-08.png) ++Step 9 ++: Define the build settings, press the **Add environment variables** button, then press the **New variable** button. + - ### Step 9 ++ ![screen capture](netlify-step-09.png) + - Define the build settings, press the **Add environment variables** button, then press the **New variable** button. ++Step 10 ++: Create a new environment variable named `HUGO_VERSION` and set the value to the [latest version](https://github.com/gohugoio/hugo/releases/latest). + - ![screen capture](netlify-step-09.png) ++ ![screen capture](netlify-step-10.png) + - ### Step 10 ++Step 11 ++: Press the "Deploy my new site" button at the bottom of the page. + - Create a new environment variable named `HUGO_VERSION` and set the value to the [latest version]. ++ ![screen capture](netlify-step-11.png) + - [latest version]: https://github.com/gohugoio/hugo/releases/latest ++Step 12 ++: At the bottom of the screen, wait for the deploy to complete, then click on the deploy log entry. + - ![screen capture](netlify-step-10.png) ++ ![screen capture](netlify-step-12.png) + - ### Step 11 ++Step 13 ++: Press the **Open production deploy** button to view the live site. + - Press the "Deploy my new site" button at the bottom of the page. - - ![screen capture](netlify-step-11.png) - - ### Step 12 - - At the bottom of the screen, wait for the deploy to complete, then click on the deploy log entry. - - ![screen capture](netlify-step-12.png) - - ### Step 13 - - Press the **Open production deploy** button to view the live site. - - ![screen capture](netlify-step-13.png) ++ ![screen capture](netlify-step-13.png) + +## Configuration file + +In the procedure above we configured our site using the Netlify user interface. Most site owners find it easier to use a configuration file checked into source control. + - Create a new file named netlify.toml in the root of your project directory. In its simplest form, the configuration file might look like this: ++Create a new file named `netlify.toml` in the root of your project directory. In its simplest form, the configuration file might look like this: + +```toml {file="netlify.toml"} +[build.environment] - GO_VERSION = "1.24.2" - HUGO_VERSION = "0.147.9" - NODE_VERSION = "22" - TZ = "America/Los_Angeles" ++GO_VERSION = "1.24.5" ++HUGO_VERSION = "0.148.2" ++NODE_VERSION = "22.18.0" ++TZ = "Europe/Oslo" + +[build] +publish = "public" - command = "git config core.quotepath false && hugo --gc --minify" ++command = """\ ++ git config core.quotepath false && \ ++ hugo --gc --minify --baseURL "${URL}" ++ """ +``` + +If your site requires Dart Sass to transpile Sass to CSS, the configuration file should look something like this: + +```toml {file="netlify.toml"} +[build.environment] - DART_SASS_VERSION = "1.89.2" - GO_VERSION = "1.24.2" - HUGO_VERSION = "0.147.9" - NODE_VERSION = "22" - TZ = "America/Los_Angeles" ++DART_SASS_VERSION = "1.90.0" ++GO_VERSION = "1.24.5" ++HUGO_VERSION = "0.148.2" ++NODE_VERSION = "22.18.0" ++TZ = "Europe/Oslo" + +[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 && \ ++ 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}" && \ + git config core.quotepath false && \ - hugo --gc --minify \ ++ hugo --gc --minify --baseURL "${URL}" + """ +``` diff --cc docs/content/en/host-and-deploy/host-on-render/index.md index 000000000,000000000..f52e09280 new file mode 100644 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-render/index.md @@@ -1,0 -1,0 +1,170 @@@ ++--- ++title: Host on Render ++description: Host your site on Render. ++categories: [] ++keywords: [] ++aliases: [/hosting-and-deployment/hosting-on-render/] ++--- ++ ++Use these instructions to enable continuous deployment from a GitHub repository. The same general steps apply if you are using Bitbucket or GitLab for version control. ++ ++## Prerequisites ++ ++Please complete the following tasks before continuing: ++ ++1. [Create](https://dashboard.render.com/register) a Render account ++1. [Log in](https://dashboard.render.com/login) to your Render 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 [Render Blueprint][] in the root of your project. ++ ++ ``` {file="render.yaml" copy=true} ++ services: ++ - type: web ++ name: hosting-render ++ repo: https://github.com/jmooring/hosting-render ++ runtime: static ++ buildCommand: chmod a+x build.sh && ./build.sh ++ staticPublishPath: public ++ envVars: ++ - key: DART_SASS_VERSION ++ value: 1.90.0 ++ - key: GO_VERSION ++ value: 1.24.5 ++ - key: HUGO_VERSION ++ value: 0.148.2 ++ - key: NODE_VERSION ++ value: 22.18.0 ++ - key: TZ ++ value: Europe/Oslo ++ ``` ++ ++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 Render. ++ # ++ # Render automatically installs Node.js dependencies. ++ #------------------------------------------------------------------------------ ++ ++ main() { ++ ++ # Create directory for user-specific executable files ++ echo "Creating directory for user-specific executable files..." ++ mkdir -p "${HOME}/.local" ++ ++ # 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 -p "${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}" ++ ++ # 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 --baseURL "${RENDER_EXTERNAL_URL}" ++ ++ } ++ ++ set -euo pipefail ++ main "$@" ++ ``` ++ ++Step 3 ++: Commit the changes to your local Git repository and push to your GitHub repository. ++ ++Step 4 ++: On the Render [dashboard][], press the **Add new** button and select "Blueprint" from the drop-down menu. ++ ++ ![screen capture](render-01.png) ++ ++Step 5 ++: Press the **GitHub** button to connect to your GitHub account. ++ ++ ![screen capture](render-02.png) ++ ++Step 6 ++: Press the **Authorize Render** button to allow the Render application to access your GitHub account. ++ ++ ![screen capture](render-03.png) ++ ++Step 7 ++: Select the GitHub account where you want to install the Render application. ++ ++ ![screen capture](render-04.png) ++ ++Step 8 ++: Authorize the Render application to access all repositories or only select repositories, then press the **Install** button. ++ ++![screen capture](render-05.png) ++ ++Step 9 ++: On the "Create a new Blueprint Instance in My Workspacee" page, press the **Connect** button to the right of the name of your GitHub repository. ++ ++ ![screen capture](render-06.png) ++ ++Step 10 ++: Enter a unique name for your Blueprint, then press the **Deploy Blueprint** button at the bottom of the page. ++ ++ ![screen capture](render-07.png) ++ ++Step 11 ++: Wait for the site to build and deploy, then click on the "Resources" link on the left side of the page. ++ ++ ![screen capture](render-08.png) ++ ++Step 12 ++: Click on the link to the static site resource. ++ ++ ![screen capture](render-09.png) ++ ++Step 13 ++: Click on the link to your published site. ++ ++ ![screen capture](render-10.png) ++ ++In the future, whenever you push a change from your local Git repository, Render will rebuild and deploy your site. ++ ++[Render Blueprint]: https://render.com/docs/blueprint-spec ++[dashboard]: https://dashboard.render.com/ diff --cc docs/content/en/host-and-deploy/host-on-render/render-01.png index 000000000,000000000..b325a679c new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-render/render-02.png index 000000000,000000000..aa8753536 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-render/render-03.png index 000000000,000000000..731d8ff26 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-render/render-04.png index 000000000,000000000..94e5ea87b new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-render/render-05.png index 000000000,000000000..05707092c new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-render/render-06.png index 000000000,000000000..7b0076139 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-render/render-07.png index 000000000,000000000..2a645d13a new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-render/render-08.png index 000000000,000000000..1dc75ae6c new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-render/render-09.png index 000000000,000000000..48e9404a9 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-render/render-10.png index 000000000,000000000..4df0dcffd new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-vercel/index.md index 000000000,000000000..8d402cb87 new file mode 100644 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-vercel/index.md @@@ -1,0 -1,0 +1,165 @@@ ++--- ++title: Host on Vercel ++description: Host your site on Vercel. ++categories: [] ++keywords: [] ++--- ++ ++Use these instructions to enable continuous deployment from a GitHub repository. The same general steps apply if you are using Bitbucket or GitLab for version control. ++ ++## Prerequisites ++ ++Please complete the following tasks before continuing: ++ ++1. [Create](https://vercel.com/signup) a Vercel account ++1. [Log in](https://vercel.com/login) to your Vercel 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 `vercel.json` file in the root of your project. ++ ++ ```json {file="vercel.json" copy=true} ++ { ++ "$schema": "https://openapi.vercel.sh/vercel.json", ++ "buildCommand": "chmod a+x build.sh && ./build.sh", ++ "outputDirectory": "public" ++ } ++ ``` ++ ++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 Vercel. ++ # ++ # The Vercel build image 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 --baseURL "https://${VERCEL_PROJECT_PRODUCTION_URL}" ++ ++ } ++ ++ 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 Vercel dashboard, press the **Add New** button and select "Project" from the drop down menu. ++ ++ ![screen capture](vercel-01.png) ++ ++Step 5 ++: Press the "Continue with GitHub" button. ++ ++ ![screen capture](vercel-02.png) ++ ++Step 6 ++: Press the **Authorize Vercel** button to allow the Vercel application to access your GitHub account. ++ ++ ![screen capture](vercel-03.png) ++ ++Step 7 ++: Press the **Install** button to install the Vercel application. ++ ++ ![screen capture](vercel-04.png) ++ ++Step 8 ++: Select the GitHub account where you want to install the Vercel application. ++ ++ ![screen capture](vercel-05.png) ++ ++Step 9 ++: Authorize the Vercel application to access all repositories or only select repositories, then press the **Install** button. ++ ++ ![screen capture](vercel-06.png) ++ ++ Your browser will be redirected to the Cloudflare dashboard. ++ ++Step 10 ++: Press the **Import** button to the right of the name of your GitHub repository. ++ ++ ![screen capture](vercel-07.png) ++ ++Step 11 ++: On the "New Project" page, leave the settings at their default values and press the **Deploy** button. ++ ++ ![screen capture](vercel-08.png) ++ ++Step 12 ++: When the deployment completes, press the **Continue to Dashboard" button at the bottom of the page. ++ ++ ![screen capture](vercel-09.png) ++ ++Step 13 ++: On the "Production Deployment" page, click on the link to your published site. ++ ++ ![screen capture](vercel-10.png) ++ ++In the future, whenever you push a change from your local Git repository, Vercel will rebuild and deploy your site. diff --cc docs/content/en/host-and-deploy/host-on-vercel/vercel-01.png index 000000000,000000000..dd0215d0c new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-vercel/vercel-02.png index 000000000,000000000..ef3a788ae new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-vercel/vercel-03.png index 000000000,000000000..a86ba36d4 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-vercel/vercel-04.png index 000000000,000000000..cbd0388d5 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-vercel/vercel-05.png index 000000000,000000000..4ae341aa5 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-vercel/vercel-06.png index 000000000,000000000..3b34cd44c new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-vercel/vercel-07.png index 000000000,000000000..ec4355b85 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-vercel/vercel-08.png index 000000000,000000000..c7fa13d0d new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-vercel/vercel-09.png index 000000000,000000000..35ae55748 new file mode 100644 Binary files differ diff --cc docs/content/en/host-and-deploy/host-on-vercel/vercel-10.png index 000000000,000000000..5fdd0aab6 new file mode 100644 Binary files differ diff --cc docs/content/en/hugo-pipes/introduction.md index d1b93094f,000000000..fa9493f20 mode 100755,000000..100755 --- a/docs/content/en/hugo-pipes/introduction.md +++ b/docs/content/en/hugo-pipes/introduction.md @@@ -1,74 -1,0 +1,74 @@@ +--- +title: Hugo Pipes +linkTitle: Introduction +description: Hugo Pipes is Hugo's asset processing set of functions. +categories: [] +keywords: [] +weight: 10 +aliases: [/assets/] +--- + +## Find resources in assets + +This is about global and remote resources. + +global resource +: A file within the `assets` directory, or within any directory [mounted] to the `assets` directory. + +remote resource +: A file on a remote server, accessible via HTTP or HTTPS. + +For `.Page` scoped resources, see the [page resources] section. + +[mounted]: /configuration/module/#mounts +[page resources]: /content-management/page-resources/ + +## Get a resource + +In order to process an asset with Hugo Pipes, it must be retrieved as a resource. + +For global resources, use: + +- [`resources.ByType`](/functions/resources/bytype/) +- [`resources.Get`](/functions/resources/get/) +- [`resources.GetMatch`](/functions/resources/getmatch/) +- [`resources.Match`](/functions/resources/match/) + +For remote resources, use: + +- [`resources.GetRemote`](/functions/resources/getremote/) + +See the [GoDoc Page](https://pkg.go.dev/github.com/gohugoio/hugo/tpl/resources) for the `resources` package for an up to date overview of all template functions in this namespace. + +## Copy a resource + +See the [`resources.Copy`](/functions/resources/copy/) function. + +## Asset directory + +Asset files must be stored in the asset directory. This is `assets` by default, but can be configured via the configuration file's `assetDir` key. + +## Asset publishing + +Hugo publishes assets to the `publishDir` (typically `public`) when you invoke `.Permalink`, `.RelPermalink`, or `.Publish`. You can use `.Content` to inline the asset. + +## Go Pipes + +For improved readability, the Hugo Pipes examples of this documentation will be written using [Go Pipes](/templates/introduction/#pipes): + +```go-html-template +{{ $style := resources.Get "sass/main.scss" | css.Sass | resources.Minify | resources.Fingerprint }} + +``` + +## Caching + - Hugo Pipes invocations are cached based on the entire *pipe chain*. ++Hugo Pipes invocations are cached based on the entire _pipe chain_. + +An example of a pipe chain is: + +```go-html-template +{{ $mainJs := resources.Get "js/main.js" | js.Build "main.js" | minify | fingerprint }} +``` + +The pipe chain is only invoked the first time it is encountered in a site build, and results are otherwise loaded from cache. As such, Hugo Pipes can be used in templates which are executed thousands or millions of times without negatively impacting the build performance. diff --cc docs/content/en/installation/bsd.md index 2f6519e6d,000000000..a4f31bd5f mode 100644,000000..100644 --- a/docs/content/en/installation/bsd.md +++ b/docs/content/en/installation/bsd.md @@@ -1,75 -1,0 +1,75 @@@ +--- +title: BSD +description: Install Hugo on BSD derivatives. +categories: [] +keywords: [] +weight: 40 +--- + +## Editions + +{{% include "/_common/installation/01-editions.md" %}} + +Unless your specific deployment needs require the extended/deploy edition, we recommend the extended edition. + +{{% include "/_common/installation/02-prerequisites.md" %}} + +{{% include "/_common/installation/03-prebuilt-binaries.md" %}} + +## Repository packages + +Most BSD derivatives maintain a repository for commonly installed applications. Please note that these repositories may not contain the [latest release]. + +[latest release]: https://github.com/gohugoio/hugo/releases/latest + +### DragonFly BSD + +[DragonFly BSD] includes Hugo in its package repository. To install the extended edition of Hugo: + +```sh +sudo pkg install gohugo +``` + +[DragonFly BSD]: https://www.dragonflybsd.org/ + +### FreeBSD + +[FreeBSD] includes Hugo in its package repository. To install the extended edition of Hugo: + +```sh +sudo pkg install gohugo +``` + +[FreeBSD]: https://www.freebsd.org/ + +### NetBSD + +[NetBSD] includes Hugo in its package repository. To install the extended edition of Hugo: + +```sh +sudo pkgin install go-hugo +``` + +[NetBSD]: https://www.netbsd.org/ + +### OpenBSD + +[OpenBSD] includes Hugo in its package repository. This will prompt you to select which edition of Hugo to install: + +```sh +doas pkg_add hugo +``` + +[OpenBSD]: https://www.openbsd.org/ + +{{% include "/_common/installation/04-build-from-source.md" %}} + +## Comparison + - ||Prebuilt binaries|Repository packages|Build from source ++ |Prebuilt binaries|Repository packages|Build from source +:--|:--:|:--:|:--: +Easy to install?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Easy to upgrade?|:heavy_check_mark:|varies|:heavy_check_mark: +Easy to downgrade?|:heavy_check_mark:|varies|:heavy_check_mark: +Automatic updates?|:x:|varies|:x: +Latest version available?|:heavy_check_mark:|varies|:heavy_check_mark: diff --cc docs/content/en/installation/linux.md index 591bf0818,000000000..babb759ea mode 100644,000000..100644 --- a/docs/content/en/installation/linux.md +++ b/docs/content/en/installation/linux.md @@@ -1,218 -1,0 +1,218 @@@ +--- +title: Linux +description: Install Hugo on Linux. +categories: [] +keywords: [] +weight: 20 +--- + +## Editions + +{{% include "/_common/installation/01-editions.md" %}} + +Unless your specific deployment needs require the extended/deploy edition, we recommend the extended edition. + +{{% include "/_common/installation/02-prerequisites.md" %}} + +{{% include "/_common/installation/03-prebuilt-binaries.md" %}} + +## Package managers + +### Snap + +[Snap] is a free and open-source package manager for Linux. Available for [most distributions], snap packages are simple to install and are automatically updated. + +The Hugo snap package is [strictly confined]. Strictly confined snaps run in complete isolation, up to a minimal access level that's deemed always safe. The sites you create and build must be located within your home directory, or on removable media. + +To install the extended edition of Hugo: + +```sh +sudo snap install hugo +``` + +To control automatic updates: + +```sh +# disable automatic updates +sudo snap refresh --hold hugo + +# enable automatic updates +sudo snap refresh --unhold hugo +``` + +To control access to removable media: + +```sh +# allow access +sudo snap connect hugo:removable-media + +# revoke access +sudo snap disconnect hugo:removable-media +``` + +To control access to SSH keys: + +```sh +# allow access +sudo snap connect hugo:ssh-keys + +# revoke access +sudo snap disconnect hugo:ssh-keys +``` + +{{% include "/_common/installation/homebrew.md" %}} + +## Repository packages + +Most Linux distributions maintain a repository for commonly installed applications. + +> [!note] +> The Hugo version available in package repositories varies based on Linux distribution and release, and in some cases will not be the [latest version]. +> +> Use one of the other installation methods if your package repository does not provide the desired version. + +### Alpine Linux + +To install the extended edition of Hugo on [Alpine Linux]: + +```sh +doas apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community hugo +``` + +### Arch Linux + +Derivatives of the [Arch Linux] distribution of Linux include [EndeavourOS], [Garuda Linux], [Manjaro], and others. To install the extended edition of Hugo: + +```sh +sudo pacman -S hugo +``` + +### Debian + +Derivatives of the [Debian] distribution of Linux include [elementary OS], [KDE neon], [Linux Lite], [Linux Mint], [MX Linux], [Pop!_OS], [Ubuntu], [Zorin OS], and others. To install the extended edition of Hugo: + +```sh +sudo apt install hugo +``` + +You can also download Debian packages from the [latest release] page. + +### Exherbo + +To install the extended edition of Hugo on [Exherbo]: + +1. Add this line to /etc/paludis/options.conf: + + ```text + www-apps/hugo extended + ``` + +1. Install using the Paludis package manager: + + ```sh + cave resolve -x repository/heirecka + cave resolve -x hugo + ``` + +### Fedora + +Derivatives of the [Fedora] distribution of Linux include [CentOS], [Red Hat Enterprise Linux], and others. To install the extended edition of Hugo: + +```sh +sudo dnf install hugo +``` + +### Gentoo + +Derivatives of the [Gentoo] distribution of Linux include [Calculate Linux], [Funtoo], and others. To install the extended edition of Hugo: + +1. Specify the `extended` [USE] flag in /etc/portage/package.use/hugo: + + ```text + www-apps/hugo extended + ``` + +1. Build using the Portage package manager: + + ```sh + sudo emerge www-apps/hugo + ``` + +### NixOS + +The NixOS distribution of Linux includes Hugo in its package repository. To install the extended edition of Hugo: + +```sh +nix-env -iA nixos.hugo +``` + +### openSUSE + +Derivatives of the [openSUSE] distribution of Linux include [GeckoLinux], [Linux Karmada], and others. To install the extended edition of Hugo: + +```sh +sudo zypper install hugo +``` + +### Solus + +The [Solus] distribution of Linux includes Hugo in its package repository. To install the extended edition of Hugo: + +```sh +sudo eopkg install hugo +``` + +### Void Linux + +To install the extended edition of Hugo on [Void Linux]: + +```sh +sudo xbps-install -S hugo +``` + +{{% include "/_common/installation/04-build-from-source.md" %}} + +## Comparison + - ||Prebuilt binaries|Package managers|Repository packages|Build from source ++ |Prebuilt binaries|Package managers|Repository packages|Build from source +:--|:--:|:--:|:--:|:--: +Easy to install?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Easy to upgrade?|:heavy_check_mark:|:heavy_check_mark:|varies|:heavy_check_mark: +Easy to downgrade?|:heavy_check_mark:|:heavy_check_mark: [^1]|varies|:heavy_check_mark: +Automatic updates?|:x:|varies [^2]|:x:|:x: +Latest version available?|:heavy_check_mark:|:heavy_check_mark:|varies|:heavy_check_mark: + +[^1]: Easy if a previous version is still installed. +[^2]: Snap packages are automatically updated. Homebrew requires advanced configuration. + +[Alpine Linux]: https://alpinelinux.org/ +[Arch Linux]: https://archlinux.org/ +[Calculate Linux]: https://www.calculate-linux.org/ +[CentOS]: https://www.centos.org/ +[Debian]: https://www.debian.org/ +[elementary OS]: https://elementary.io/ +[EndeavourOS]: https://endeavouros.com/ +[Exherbo]: https://www.exherbolinux.org/ +[Fedora]: https://getfedora.org/ +[Funtoo]: https://www.funtoo.org/ +[Garuda Linux]: https://garudalinux.org/ +[GeckoLinux]: https://geckolinux.github.io/ +[Gentoo]: https://www.gentoo.org/ +[KDE neon]: https://neon.kde.org/ +[latest version]: https://github.com/gohugoio/hugo/releases/latest +[Linux Karmada]: https://linuxkamarada.com/ +[Linux Lite]: https://www.linuxliteos.com/ +[Linux Mint]: https://linuxmint.com/ +[Manjaro]: https://manjaro.org/ +[most distributions]: https://snapcraft.io/docs/installing-snapd +[MX Linux]: https://mxlinux.org/ +[openSUSE]: https://www.opensuse.org/ +[Pop!_OS]: https://pop.system76.com/ +[Red Hat Enterprise Linux]: https://www.redhat.com/ +[Snap]: https://snapcraft.io/ +[Solus]: https://getsol.us/ +[strictly confined]: https://snapcraft.io/docs/snap-confinement +[Ubuntu]: https://ubuntu.com/ +[USE]: https://packages.gentoo.org/packages/www-apps/hugo +[Void Linux]: https://voidlinux.org/ +[Zorin OS]: https://zorin.com/os/ diff --cc docs/content/en/installation/macos.md index a873b512a,000000000..0f1fc0d27 mode 100644,000000..100644 --- a/docs/content/en/installation/macos.md +++ b/docs/content/en/installation/macos.md @@@ -1,46 -1,0 +1,46 @@@ +--- +title: macOS +description: Install Hugo on macOS. +categories: [] +keywords: [] +weight: 10 +--- + +## Editions + +{{% include "/_common/installation/01-editions.md" %}} + +Unless your specific deployment needs require the extended/deploy edition, we recommend the extended edition. + +{{% include "/_common/installation/02-prerequisites.md" %}} + +{{% include "/_common/installation/03-prebuilt-binaries.md" %}} + +## Package managers + +{{% include "/_common/installation/homebrew.md" %}} + +### MacPorts + +[MacPorts] is a free and open-source package manager for macOS. To install the extended edition of Hugo: + +```sh +sudo port install hugo +``` + +[MacPorts]: https://www.macports.org/ + +{{% include "/_common/installation/04-build-from-source.md" %}} + +## Comparison + - ||Prebuilt binaries|Package managers|Build from source ++ |Prebuilt binaries|Package managers|Build from source +:--|:--:|:--:|:--: - Easy to install?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:| ++Easy to install?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Easy to upgrade?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Easy to downgrade?|:heavy_check_mark:|:heavy_check_mark: [^1]|:heavy_check_mark: +Automatic updates?|:x:|:x: [^2]|:x: +Latest version available?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: + +[^1]: Easy if a previous version is still installed. +[^2]: Possible but requires advanced configuration. diff --cc docs/content/en/installation/windows.md index a5920d45f,000000000..0b7d89f6e mode 100644,000000..100644 --- a/docs/content/en/installation/windows.md +++ b/docs/content/en/installation/windows.md @@@ -1,74 -1,0 +1,74 @@@ +--- +title: Windows +description: Install Hugo on Windows. +categories: [] +keywords: [] +weight: 30 +--- + +> [!note] +> Hugo v0.121.1 and later require at least Windows 10 or Windows Server 2016. + +## Editions + +{{% include "/_common/installation/01-editions.md" %}} + +Unless your specific deployment needs require the extended/deploy edition, we recommend the extended edition. + +{{% include "/_common/installation/02-prerequisites.md" %}} + +{{% include "/_common/installation/03-prebuilt-binaries.md" %}} + +## Package managers + +### Chocolatey + +[Chocolatey] is a free and open-source package manager for Windows. To install the extended edition of Hugo: + +```sh +choco install hugo-extended +``` + +### Scoop + +[Scoop] is a free and open-source package manager for Windows. To install the extended edition of Hugo: + +```sh +scoop install hugo-extended +``` + +### Winget + +[Winget] is Microsoft's official free and open-source package manager for Windows. To install the extended edition of Hugo: + +```sh +winget install Hugo.Hugo.Extended +``` + +To uninstall the extended edition of Hugo: + +```sh +winget uninstall --name "Hugo (Extended)" +``` + +{{% include "/_common/installation/04-build-from-source.md" %}} + +> [!note] +> See these [detailed instructions](https://discourse.gohugo.io/t/41370) to install GCC on Windows. + +## Comparison + - ||Prebuilt binaries|Package managers|Build from source ++ |Prebuilt binaries|Package managers|Build from source +:--|:--:|:--:|:--: - Easy to install?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:| ++Easy to install?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Easy to upgrade?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Easy to downgrade?|:heavy_check_mark:|:heavy_check_mark: [^2]|:heavy_check_mark: +Automatic updates?|:x:|:x: [^1]|:x: +Latest version available?|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: + +[^1]: Possible but requires advanced configuration. +[^2]: Easy if a previous version is still installed. + +[Chocolatey]: https://chocolatey.org/ +[Scoop]: https://scoop.sh/ +[Winget]: https://learn.microsoft.com/en-us/windows/package-manager/ diff --cc docs/content/en/methods/page/AllTranslations.md index 62117b429,000000000..ed92cd482 mode 100644,000000..100644 --- a/docs/content/en/methods/page/AllTranslations.md +++ b/docs/content/en/methods/page/AllTranslations.md @@@ -1,88 -1,0 +1,88 @@@ +--- +title: AllTranslations - description: Returns all translations of the given page, including the current language. ++description: Returns all translations of the given page, including the current language, sorted by language weight. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGE.AllTranslations] +--- + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' + +[languages.en] +contentDir = 'content/en' +languageCode = 'en-US' +languageName = 'English' +weight = 1 + +[languages.de] +contentDir = 'content/de' +languageCode = 'de-DE' +languageName = 'Deutsch' +weight = 2 + +[languages.fr] +contentDir = 'content/fr' +languageCode = 'fr-FR' +languageName = 'Français' +weight = 3 +{{< /code-toggle >}} + +And this content: + +```text +content/ +├── de/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +├── en/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +├── fr/ +│ ├── books/ +│ │ └── book-1.md +│ └── _index.md +└── _index.md +``` + +And this template: + +```go-html-template +{{ with .AllTranslations }} + +{{ end }} +``` + +Hugo will render this list on the "Book 1" page of each site: + +```html + +``` + +On the "Book 2" page of the English and German sites, Hugo will render this: + +```html + +``` diff --cc docs/content/en/methods/page/Data.md index bb88dbde6,000000000..387422901 mode 100644,000000..100644 --- a/docs/content/en/methods/page/Data.md +++ b/docs/content/en/methods/page/Data.md @@@ -1,101 -1,0 +1,101 @@@ +--- +title: Data +description: Returns a unique data object for each page kind. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Data + signatures: [PAGE.Data] +--- + +The `Data` method on a `Page` object returns a unique data object for each [page kind](g). + +> [!note] +> The `Data` method is only useful within [taxonomy](g) and [term](g) templates. +> +> Themes that are not actively maintained may still use `.Data.Pages` in their templates. Although that syntax remains functional, use one of these methods instead: [`Pages`], [`RegularPages`], or [`RegularPagesRecursive`] + +The examples that follow are based on this site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +genre = 'genres' +author = 'authors' +{{< /code-toggle >}} + +And this content structure: + +```text +content/ +├── books/ +│ ├── and-then-there-were-none.md --> genres: suspense +│ ├── death-on-the-nile.md --> genres: suspense +│ └── jamaica-inn.md --> genres: suspense, romance +│ └── pride-and-prejudice.md --> genres: romance +└── _index.md +``` + +## In a taxonomy template + - Use these methods on the `Data` object within a taxonomy template. ++Use these methods on the `Data` object within a _taxonomy_ template. + +Singular +: (`string`) Returns the singular name of the taxonomy. + +```go-html-template +{{ .Data.Singular }} → genre +``` + +Plural +: (`string`) Returns the plural name of the taxonomy. + +```go-html-template +{{ .Data.Plural }} → genres +``` + +Terms +: (`page.Taxonomy`) Returns the `Taxonomy` object, consisting of a map of terms and the [weighted pages](g) associated with each term. + +```go-html-template +{{ $taxonomyObject := .Data.Terms }} +``` + +> [!note] +> Once you have captured the `Taxonomy` object, use any of the [taxonomy methods] to sort, count, or capture a subset of its weighted pages. + +Learn more about [taxonomy templates]. + +## In a term template + - Use these methods on the `Data` object within a term template. ++Use these methods on the `Data` object within a _term_ template. + +Singular +: (`string`) Returns the singular name of the taxonomy. + +```go-html-template +{{ .Data.Singular }} → genre +``` + +Plural +: (`string`) Returns the plural name of the taxonomy. + +```go-html-template +{{ .Data.Plural }} → genres +``` + +Term +: (`string`) Returns the name of the term. + +```go-html-template +{{ .Data.Term }} → suspense +``` + +Learn more about [term templates]. + +[`Pages`]: /methods/page/pages/ +[`RegularPages`]: /methods/page/regularpages/ +[`RegularPagesRecursive`]: /methods/page/regularpagesrecursive/ +[taxonomy methods]: /methods/taxonomy/ +[taxonomy templates]: /templates/types/#taxonomy +[term templates]: /templates/types/#term diff --cc docs/content/en/methods/page/Date.md index b6c2042c2,000000000..21bf03445 mode 100644,000000..100644 --- a/docs/content/en/methods/page/Date.md +++ b/docs/content/en/methods/page/Date.md @@@ -1,34 -1,0 +1,33 @@@ +--- +title: Date +description: Returns the date of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [PAGE.Date] +--- + +Set the date in front matter: + +{{< code-toggle file=content/news/article-1.md fm=true >}} +title = 'Article 1' +date = 2023-10-19T00:40:04-07:00 +{{< /code-toggle >}} + +> [!note] +> The date field in front matter is often considered to be the creation date, You can change its meaning, and its effect on your site, in the site configuration. See [details]. + +The date is a [time.Time] value. Format and localize the value with the [`time.Format`] function, or use it with any of the [time methods]. + +```go-html-template +{{ .Date | time.Format ":date_medium" }} → Oct 19, 2023 +``` + +In the example above we explicitly set the date in front matter. With Hugo's default configuration, the `Date` method returns the front matter value. This behavior is configurable, allowing you to set fallback values if the date is not defined in front matter. See [details]. + +[`time.Format`]: /functions/time/format/ +[details]: /configuration/front-matter/#dates - [details]: /configuration/front-matter/#dates +[time methods]: /methods/time/ +[time.Time]: https://pkg.go.dev/time#Time diff --cc docs/content/en/methods/page/GitInfo.md index 90dc3870a,000000000..2b620103e mode 100644,000000..100644 --- a/docs/content/en/methods/page/GitInfo.md +++ b/docs/content/en/methods/page/GitInfo.md @@@ -1,167 -1,0 +1,185 @@@ +--- +title: GitInfo +description: Returns Git information related to the last commit of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: - returnType: source.GitInfo ++ returnType: '*gitmap.GitInfo' + signatures: [PAGE.GitInfo] +--- + +The `GitInfo` method on a `Page` object returns an object with additional methods. + +> [!note] +> Hugo's Git integration is performant, but may increase build times on large sites. + +## Prerequisites + - Install [Git], create a repository, and commit your project files. ++Install Git, create a repository, and commit your project files. + +You must also allow Hugo to access your repository. In your site configuration: + +{{< code-toggle file=hugo >}} +enableGitInfo = true +{{< /code-toggle >}} + +Alternatively, use the command line flag when building your site: + +```sh +hugo --enableGitInfo +``` + +> [!note] +> When you set `enableGitInfo` to `true`, or enable the feature with the command line flag, the last modification date for each content page will be the Author Date of the last commit for that file. +> +> This is configurable. See [details]. + +## Methods + +### AbbreviatedHash + +(`string`) The abbreviated commit hash. + +```go-html-template +{{ with .GitInfo }} + {{ .AbbreviatedHash }} → aab9ec0b3 +{{ end }} +``` + +### AuthorDate + +(`time.Time`) The author date. + +```go-html-template +{{ with .GitInfo }} + {{ .AuthorDate.Format "2006-01-02" }} → 2023-10-09 +{{ end }} +``` + +### AuthorEmail + +(`string`) The author's email address, respecting [gitmailmap]. + +```go-html-template +{{ with .GitInfo }} + {{ .AuthorEmail }} → jsmith@example.org +{{ end }} +``` + +### AuthorName + +(`string`) The author's name, respecting [gitmailmap]. + +```go-html-template +{{ with .GitInfo }} + {{ .AuthorName }} → John Smith +{{ end }} +``` + +### CommitDate + +(`time.Time`) The commit date. + +```go-html-template +{{ with .GitInfo }} + {{ .CommitDate.Format "2006-01-02" }} → 2023-10-09 +{{ end }} +``` + +### Hash + +(`string`) The commit hash. + +```go-html-template +{{ with .GitInfo }} + {{ .Hash }} → aab9ec0b31ebac916a1468c4c9c305f2bebf78d4 +{{ end }} +``` + +### Subject + +(`string`) The commit message subject. + +```go-html-template +{{ with .GitInfo }} + {{ .Subject }} → Add tutorials +{{ end }} +``` + +### Body + +(`string`) The commit message body. + +```go-html-template +{{ with .GitInfo }} + {{ .Body }} → - Two new pages added. +{{ end }} +``` + +### Ancestors + - (`*source.GitInfo`) The file-filtered ancestor commits, if any. ++(`gitmap.GitInfos`) A slice of file-filtered ancestor commits, if any, ordered from most recent to least recent. ++ ++For example, to list the last 5 commits: + +```go-html-template +{{ with .GitInfo }} + {{ range .Ancestors | first 5 }} + {{ .CommitDate.Format "2006-01-02" }}: {{ .Subject }} + {{ end }} +{{ end }} +``` + ++To reverse the order: ++ ++```go-html-template ++{{ with .GitInfo }} ++ {{ range .Ancestors.Reverse | first 5 }} ++ {{ .CommitDate.Format "2006-01-02" }}: {{ .Subject }} ++ {{ end }} ++{{ end }} ++``` ++ +### Parent + - (`*source.GitInfo`) The first file-filtered ancestor commit, if any. ++(`*gitmap.GitInfo`) The first file-filtered ancestor commit, if any. + +## Last modified date + +By default, when `enableGitInfo` is `true`, the `Lastmod` method on a `Page` object returns the Git AuthorDate of the last commit that included the file. + +You can change this behavior in your [site configuration]. + +## Hosting considerations + - When hosting your site in a [CI/CD](g) environment, the step that clones your project repository must perform a deep clone. If the clone is shallow, the Git information for a given file may not be accurate---it may reflect the most recent repository commit, not the commit that last modified the file. ++In a [CI/CD](g) environment, the step that clones your project repository must perform a deep clone. If the clone is shallow, the Git information for a given file may be inaccurate. It might incorrectly reflect the most recent repository commit, rather than the commit that actually modified the file. ++ ++While some providers perform a deep clone by default, others require you to configure the depth yourself. + - Some providers perform deep clones by default, others allow you to configure the clone depth, and some only perform shallow clones. ++Hosting service|Default clone depth|Configurable ++:--|:--|:-- ++AWS Amplify|Deep|N/A ++Cloudflare|Shallow|Yes [^1] ++DigitalOcean App Platform|Deep|N/A ++GitHub Pages|Shallow|Yes [^2] ++GitLab Pages|Shallow|Yes [^3] ++Netlify|Deep|N/A ++Render|Shallow|Yes [^1] ++Vercel|Shallow|Yes [^1] + - Hosting service | Default clone depth | Configurable - :-- | :-- | :-- - AWS Amplify | Deep | N/A - Cloudflare Pages | Shallow | Yes [^1] - DigitalOcean App Platform | Deep | N/A - GitHub Pages | Shallow | Yes [^2] - GitLab Pages | Shallow | Yes [^3] - Netlify | Deep | N/A - Render | Shallow | No - Vercel | Shallow | No ++[^1]: To perform a deep clone when hosting on Cloudflare, Render, or Vercel, include this code in the build script after the repository has been cloned: + - [^1]: To configure a Cloudflare Pages site for deep cloning, run `git fetch --unshallow` before building the site. ++ ```text ++ if [ "$(git rev-parse --is-shallow-repository)" = "true" ]; then ++ git fetch --unshallow ++ fi ++ ``` + - [^2]: You can configure the GitHub Action to do a deep clone by specifying `fetch-depth: 0` in the applicable "checkout" step of your workflow file, as shown in the Hugo documentation's [example workflow file](/host-and-deploy/host-on-github-pages/#procedure). ++[^2]: To perform a deep clone when hosting on GitHub Pages, set `fetch-depth: 0` in the `checkout` step of the GitHub Action. See [example](/host-and-deploy/host-on-github-pages/#step-7). + - [^3]: You can configure the GitLab Runner's clone depth [as explained in the GitLab documentation](https://docs.gitlab.com/ee/ci/large_repositories/#shallow-cloning); see also the Hugo documentation's [example workflow file](/host-and-deploy/host-on-gitlab-pages/#configure-gitlab-cicd). ++[^3]: To perform a deep clone when hosting on GitLab Pages, set the `GIT_DEPTH` environment variable to `0` in the workflow file. See [example](/host-and-deploy/host-on-gitlab-pages/#configure-gitlab-cicd). + +[details]: /configuration/front-matter/#dates +[gitmailmap]: https://git-scm.com/docs/gitmailmap +[site configuration]: /configuration/front-matter/ diff --cc docs/content/en/methods/page/Page.md index 01abb3103,000000000..b7bdf3558 mode 100644,000000..100644 --- a/docs/content/en/methods/page/Page.md +++ b/docs/content/en/methods/page/Page.md @@@ -1,35 -1,0 +1,35 @@@ +--- +title: Page +description: Returns the Page object of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [PAGE.Page] +--- + - This is a convenience method, useful within partial templates that are called from both [shortcodes](g) and page templates. ++This is a convenience method, useful within _partial_ templates that are called from both _shortcode_ and other template types. + +```go-html-template {file="layouts/_shortcodes/foo.html"} +{{ partial "my-partial.html" . }} +``` + - When the shortcode calls the partial, it passes the current [context](g) (the dot). The context includes identifiers such as `Page`, `Params`, `Inner`, and `Name`. ++When the _shortcode_ template calls the _partial_ template, it passes the current [context](g) (the dot). The context includes identifiers such as `Page`, `Params`, `Inner`, and `Name`. + +```go-html-template {file="layouts/page.html"} +{{ partial "my-partial.html" . }} +``` + - When the page template calls the partial, it also passes the current context (the dot). But in this case, the dot _is_ the `Page` object. ++When the _page_ template calls the _partial_ template, it also passes the current context (the dot). But in this case, the dot _is_ the `Page` object. + +```go-html-template {file="layouts/_partials/my-partial.html"} +The page title is: {{ .Page.Title }} +``` + - To handle both scenarios, the partial template must be able to access the `Page` object with `Page.Page`. ++To handle both scenarios, the _partial_ template must be able to access the `Page` object with `Page.Page`. + +> [!note] +> And yes, that means you can do `.Page.Page.Page.Page.Title` too. +> +> But don't. diff --cc docs/content/en/methods/page/Paginate.md index 7792980e6,000000000..337811240 mode 100644,000000..100644 --- a/docs/content/en/methods/page/Paginate.md +++ b/docs/content/en/methods/page/Paginate.md @@@ -1,47 -1,0 +1,47 @@@ +--- +title: Paginate +description: Paginates a collection of pages. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pager + signatures: ['PAGE.Paginate COLLECTION [N]'] +--- + +Pagination is the process of splitting a list page into two or more pagers, where each pager contains a subset of the page collection and navigation links to other pagers. + +By default, the number of elements on each pager is determined by your [site configuration]. The default is `10`. Override that value by providing a second argument, an integer, when calling the `Paginate` method. + +> [!note] +> There is also a `Paginator` method on `Page` objects, but it can neither filter nor sort the page collection. +> +> The `Paginate` method is more flexible. + - You can invoke pagination on the [home template], [section templates], [taxonomy templates], and [term templates]. ++You can invoke pagination in [home], [section], [taxonomy], and [term] templates. + +```go-html-template {file="layouts/section.html"} +{{ $pages := where .Site.RegularPages "Section" "articles" }} +{{ $pages = $pages.ByTitle }} +{{ range (.Paginate $pages 7).Pages }} +

{{ .Title }}

+{{ end }} +{{ partial "pagination.html" . }} +``` + +In the example above, we: + +1. Build a page collection +1. Sort the collection by title +1. Paginate the collection, with 7 elements per pager +1. Range over the paginated page collection, rendering a link to each page +1. Call the embedded pagination template to create navigation links between pagers + +> [!note] +> Please note that the results of pagination are cached. Once you have invoked either the `Paginator` or `Paginate` method, the paginated collection is immutable. Additional invocations of these methods will have no effect. + - [home template]: /templates/types/#home - [section templates]: /templates/types/#section ++[home]: /templates/types/#home ++[section]: /templates/types/#section +[site configuration]: /configuration/pagination/ - [taxonomy templates]: /templates/types/#taxonomy - [term templates]: /templates/types/#term ++[taxonomy]: /templates/types/#taxonomy ++[term]: /templates/types/#term diff --cc docs/content/en/methods/page/Paginator.md index 1518ac95d,000000000..02b5d5719 mode 100644,000000..100644 --- a/docs/content/en/methods/page/Paginator.md +++ b/docs/content/en/methods/page/Paginator.md @@@ -1,40 -1,0 +1,40 @@@ +--- +title: Paginator +description: Paginates the collection of regular pages received in context. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pager + signatures: [PAGE.Paginator] +--- + +Pagination is the process of splitting a list page into two or more pagers, where each pager contains a subset of the page collection and navigation links to other pagers. + +The number of elements on each pager is determined by your [site configuration]. The default is `10`. + - You can invoke pagination on the [home template], [section templates], [taxonomy templates], and [term templates]. Each of these receives a collection of regular pages in [context](g). When you invoke the `Paginator` method, it paginates the page collection received in context. ++You can invoke pagination in [home], [section], [taxonomy], and [term] templates. Each of these receives a collection of regular pages in [context](g). When you invoke the `Paginator` method, it paginates the page collection received in context. + +```go-html-template {file="layouts/section.html"} +{{ range .Paginator.Pages }} +

{{ .LinkTitle }}

+{{ end }} +{{ partial "pagination.html" . }} +``` + +In the example above, the embedded pagination template creates navigation links between pagers. + +> [!note] +> Although simple to invoke, with the `Paginator` method you can neither filter nor sort the page collection. It acts upon the page collection received in context. +> +> The [`Paginate`] method is more flexible, and strongly recommended. + +> [!note] +> Please note that the results of pagination are cached. Once you have invoked either the `Paginator` or `Paginate` method, the paginated collection is immutable. Additional invocations of these methods will have no effect. + - [home template]: /templates/types/#home - [section templates]: /templates/types/#section ++[home]: /templates/types/#home ++[section]: /templates/types/#section +[site configuration]: /configuration/pagination/ - [taxonomy templates]: /templates/types/#taxonomy - [term templates]: /templates/types/#term ++[taxonomy]: /templates/types/#taxonomy ++[term]: /templates/types/#term +[`Paginate`]: /methods/page/paginate/ diff --cc docs/content/en/methods/page/Path.md index db4e7d629,000000000..df565f716 mode 100644,000000..100644 --- a/docs/content/en/methods/page/Path.md +++ b/docs/content/en/methods/page/Path.md @@@ -1,140 -1,0 +1,140 @@@ +--- +title: Path +description: Returns the logical path of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Path] +--- + +{{< new-in 0.123.0 />}} + +The `Path` method on a `Page` object returns the logical path of the given page, regardless of whether the page is backed by a file. + +{{% glossary-term "logical path" %}} + +```go-html-template +{{ .Path }} → /posts/post-1 +``` + +> [!note] +> Beginning with the release of [v0.92.0] in January 2022, Hugo emitted a warning whenever calling the `Path` method. The warning indicated that this method would change in a future release. +> +> The meaning of, and value returned by, the `Path` method on a `Page` object changed with the release of [v0.123.0] in February 2024. + +The value returned by the `Path` method on a `Page` object is independent of content format, language, and URL modifiers such as the `slug` and `url` front matter fields. + +## Examples + +### Monolingual site + +Note that the logical path is independent of content format and URL modifiers. + +File path|Front matter slug|Logical path +:--|:--|:-- +`content/_index.md`||`/` +`content/posts/_index.md`||`/posts` +`content/posts/post-1.md`|`foo`|`/posts/post-1` +`content/posts/post-2.html`|`bar`|`/posts/post-2` + +### Multilingual site + +Note that the logical path is independent of content format, language identifiers, and URL modifiers. + +File path|Front matter slug|Logical path +:--|:--|:-- +`content/_index.en.md`||`/` +`content/_index.de.md`||`/` +`content/posts/_index.en.md`||`/posts` +`content/posts/_index.de.md`||`/posts` +`content/posts/posts-1.en.md`|`foo`|`/posts/post-1` +`content/posts/posts-1.de.md`|`foo`|`/posts/post-1` +`content/posts/posts-2.en.html`|`bar`|`/posts/post-2` +`content/posts/posts-2.de.html`|`bar`|`/posts/post-2` + +### Pages not backed by a file + +The `Path` method on a `Page` object returns a value regardless of whether the page is backed by a file. + +```text +content/ +└── posts/ + └── post-1.md <-- front matter: tags = ['hugo'] +``` + +When you build the site: + +```text +public/ +├── posts/ +│ ├── post-1/ +│ │ └── index.html .Page.Path = /posts/post-1 +│ └── index.html .Page.Path = /posts +├── tags/ +│ ├── hugo/ +│ │ └── index.html .Page.Path = /tags/hugo +│ └── index.html .Page.Path = /tags +└── index.html .Page.Path = / +``` + +## Finding pages + +These methods, functions, and shortcodes use the logical path to find the given page: + +Methods|Functions|Shortcodes +:--|:--|:-- +[`Site.GetPage`]|[`urls.Ref`]|[`ref`] +[`Page.GetPage`]|[`urls.RelRef`]|[`relref`] - [`Page.Ref`]||| - [`Page.RelRef`]||| - [`Shortcode.Ref`]||| - [`Shortcode.RelRef`]||| ++[`Page.Ref`]| |  ++[`Page.RelRef`]| |  ++[`Shortcode.Ref`]| |  ++[`Shortcode.RelRef`]| |  + +> [!note] +> Specify the logical path when using any of these methods, functions, or shortcodes. If you include a file extension or language identifier, Hugo will strip these values before finding the page in the logical tree. + +## Logical tree + +Just as file paths form a file tree, logical paths form a logical tree. + +A file tree: + +```text +content/ +└── s1/ + ├── p1/ + │ └── index.md + └── p2.md +``` + +The same content represented as a logical tree: + +```text +content/ +└── s1/ + ├── p1 + └── p2 +``` + +A key difference between these trees is the relative path from p1 to p2: + +- In the file tree, the relative path from p1 to p2 is `../p2.md` +- In the logical tree, the relative path is `p2` + +> [!note] +> Remember to use the logical path when using any of the methods, functions, or shortcodes listed in the previous section. If you include a file extension or language identifier, Hugo will strip these values before finding the page in the logical tree. + +[`Page.GetPage`]: /methods/page/getpage/ +[`Page.Ref`]: /methods/page/ref/ +[`Page.RelRef`]: /methods/page/relref/ +[`ref`]: /shortcodes/ref/ +[`relref`]: /shortcodes/relref/ +[`Shortcode.Ref`]: /methods/shortcode/ref +[`Shortcode.RelRef`]: /methods/shortcode/relref +[`Site.GetPage`]: /methods/site/getpage/ +[`urls.Ref`]: /functions/urls/ref/ +[`urls.RelRef`]: /functions/urls/relref/ +[v0.123.0]: https://github.com/gohugoio/hugo/releases/tag/v0.123.0 +[v0.92.0]: https://github.com/gohugoio/hugo/releases/tag/v0.92.0 diff --cc docs/content/en/methods/page/Render.md index 4ee09fb6e,000000000..cd24419c2 mode 100644,000000..100644 --- a/docs/content/en/methods/page/Render.md +++ b/docs/content/en/methods/page/Render.md @@@ -1,71 -1,0 +1,71 @@@ +--- +title: Render +description: Renders the given template with the given page as context. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: [PAGE.Render NAME] +aliases: [/functions/render] +--- + +Typically used when ranging over a page collection, the `Render` method on a `Page` object renders the given template, passing the given page as context. + +```go-html-template +{{ range site.RegularPages }} +

{{ .LinkTitle }}

+ {{ .Render "summary" }} +{{ end }} +``` + +In the example above, note that the template ("summary") is identified by its file name without directory or extension. + +Although similar to the [`partial`] function, there are key differences. + - `Render` method|`partial` function| ++`Render` method|`partial` function +:--|:-- - The `Page` object is automatically passed to the given template. You cannot pass additional context.| You must specify the context, allowing you to pass a combination of objects, slices, maps, and scalars. ++The `Page` object is automatically passed to the given template. You cannot pass additional context.|You must specify the context, allowing you to pass a combination of objects, slices, maps, and scalars. +The path to the template is determined by the [content type](g).|You must specify the path to the template, relative to the `layouts/_partials` directory. + +Consider this layout structure: + +```text +layouts/ +├── books/ +│ └── li.html <-- used when content type is "books" +├── baseof.html +├── home.html +├── li.html <-- used for other content types +├── page.html +├── section.html +├── taxonomy.html +└── term.html +``` + +And this template: + +```go-html-template +
    + {{ range site.RegularPages.ByDate }} + {{ .Render "li" }} + {{ end }} +
+``` + +When rendering content of type "books" the `Render` method calls: + +```text +layouts/books/li.html +``` + +For all other content types the `Render` methods calls: + +```text +layouts/li.html +``` + +See [content views] for more examples. + +[content views]: /templates/types/#content-view +[`partial`]: /functions/partials/include/ diff --cc docs/content/en/methods/page/RenderShortcodes.md index 81a78b04b,000000000..e440302dc mode 100644,000000..100644 --- a/docs/content/en/methods/page/RenderShortcodes.md +++ b/docs/content/en/methods/page/RenderShortcodes.md @@@ -1,87 -1,0 +1,87 @@@ +--- +title: RenderShortcodes +description: Renders all shortcodes in the content of the given page, preserving the surrounding markup. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: [PAGE.RenderShortcodes] +--- + - Use this method in shortcode templates to compose a page from multiple content files, while preserving a global context for footnotes and the table of contents. ++Use this method in _shortcode_ templates to compose a page from multiple content files, while preserving a global context for footnotes and the table of contents. + +For example: + +```go-html-template {file="layouts/_shortcodes/include.html" copy=true} +{{ with .Get 0 }} + {{ with $.Page.GetPage . }} + {{- .RenderShortcodes }} + {{ else }} + {{ errorf "The %q shortcode was unable to find %q. See %s" $.Name . $.Position }} + {{ end }} +{{ else }} + {{ errorf "The %q shortcode requires a positional parameter indicating the logical path of the file to include. See %s" .Name .Position }} +{{ end }} +``` + +Then call the shortcode in your Markdown: + +```text {file="content/about.md"} +{{%/* include "/snippets/services" */%}} +{{%/* include "/snippets/values" */%}} +{{%/* include "/snippets/leadership" */%}} +``` + +Each of the included Markdown files can contain calls to other shortcodes. + +## Shortcode notation + +In the example above it's important to understand the difference between the two delimiters used when calling a shortcode: + +- `{{}}` tells Hugo that the rendered shortcode does not need further processing. For example, the shortcode content is HTML. +- `{{%/* myshortcode */%}}` tells Hugo that the rendered shortcode needs further processing. For example, the shortcode content is Markdown. + +Use the latter for the "include" shortcode described above. + +## Further explanation + +To understand what is returned by the `RenderShortcodes` method, consider this content file + +```text {file="content/about.md"} ++++ +title = 'About' +date = 2023-10-07T12:28:33-07:00 ++++ + +{{}} + +An *emphasized* word. +``` + +With this template code: + +```go-html-template +{{ $p := site.GetPage "/about" }} +{{ $p.RenderShortcodes }} +``` + +Hugo renders this:; + +```html +https://example.org/privacy/ + +An *emphasized* word. +``` + +Note that the shortcode within the content file was rendered, but the surrounding Markdown was preserved. + +## Limitations + +The primary use case for `.RenderShortcodes` is inclusion of Markdown content. If you try to use `.RenderShortcodes` inside `HTML` blocks when inside Markdown, you will get a warning similar to this: + +```text +WARN .RenderShortcodes detected inside HTML block in "/content/mypost.md"; this may not be what you intended ... +``` + +The above warning can be turned off is this is what you really want. diff --cc docs/content/en/methods/page/Store.md index 0b1049b0a,000000000..c5ad6b316 mode 100644,000000..100644 --- a/docs/content/en/methods/page/Store.md +++ b/docs/content/en/methods/page/Store.md @@@ -1,35 -1,0 +1,35 @@@ +--- +title: Store +description: Returns a "scratch pad" to store and manipulate data, scoped to the current page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: maps.Scratch + signatures: [PAGE.Store] +aliases: [/functions/store/,/extras/scratch/,/doc/scratch/,/functions/scratch] +--- + +Use the `Store` method on a `Page` object to create a [scratch pad](g) to store and manipulate data, scoped to the current page. To create a scratch pad with a different [scope](g), refer to the [scope](#scope) section below. + +{{% include "_common/store-methods.md" %}} + +{{% include "_common/scratch-pad-scope.md" %}} + +## 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: + +```go-html-template +{{ $noop := .Content }} +{{ .Store.Get "mykey" }} +``` + +You can also trigger content rendering with the `ContentWithoutSummary`, `FuzzyWordCount`, `Len`, `Plain`, `PlainWords`, `ReadingTime`, `Summary`, `Truncated`, and `WordCount` methods. For example: + +```go-html-template +{{ $noop := .WordCount }} +{{ .Store.Get "mykey" }} +``` diff --cc docs/content/en/methods/page/Translations.md index 4bab9fe11,000000000..c342a8618 mode 100644,000000..100644 --- a/docs/content/en/methods/page/Translations.md +++ b/docs/content/en/methods/page/Translations.md @@@ -1,86 -1,0 +1,86 @@@ +--- +title: Translations - description: Returns all translations of the given page, excluding the current language. ++description: Returns all translations of the given page, excluding the current language, sorted by language weight. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGE.Translations] +--- + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' + +[languages.en] +contentDir = 'content/en' +languageCode = 'en-US' +languageName = 'English' +weight = 1 + +[languages.de] +contentDir = 'content/de' +languageCode = 'de-DE' +languageName = 'Deutsch' +weight = 2 + +[languages.fr] +contentDir = 'content/fr' +languageCode = 'fr-FR' +languageName = 'Français' +weight = 3 +{{< /code-toggle >}} + +And this content: + +```text +content/ +├── de/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +├── en/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +├── fr/ +│ ├── books/ +│ │ └── book-1.md +│ └── _index.md +└── _index.md +``` + +And this template: + +```go-html-template +{{ with .Translations }} + +{{ end }} +``` + +Hugo will render this list on the "Book 1" page of the English site: + +```html + +``` + +Hugo will render this list on the "Book 2" page of the English site: + +```html + +``` diff --cc docs/content/en/methods/resource/Content.md index 2c2c12d3a,000000000..ff2ad6de8 mode 100644,000000..100644 --- a/docs/content/en/methods/resource/Content.md +++ b/docs/content/en/methods/resource/Content.md @@@ -1,60 -1,0 +1,60 @@@ +--- +title: Content +description: Returns the content of the given resource. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: any + signatures: [RESOURCE.Content] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + - The `Content` method on a `Resource` object returns `template.HTML` when the resource type is `page`, otherwise it returns a `string`. ++The `Content` method on a `Resource` object returns `template.HTML` when the [resource type] is `page`, otherwise it returns a `string`. + +[resource type]: /methods/resource/resourcetype/ + +```text {file="assets/quotations/kipling.txt"} +He travels the fastest who travels alone. +``` + +To get the content: + +```go-html-template +{{ with resources.Get "quotations/kipling.txt" }} + {{ .Content }} → He travels the fastest who travels alone. +{{ end }} +``` + +To get the size in bytes: + +```go-html-template +{{ with resources.Get "quotations/kipling.txt" }} + {{ .Content | len }} → 42 +{{ end }} +``` + +To create an inline image: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + +{{ end }} +``` + +To create inline CSS: + +```go-html-template +{{ with resources.Get "css/style.css" }} + +{{ end }} +``` + +To create inline JavaScript: + +```go-html-template +{{ with resources.Get "js/script.js" }} + +{{ end }} +``` diff --cc docs/content/en/methods/resource/Data.md index 0709ca50a,000000000..01b22823d mode 100644,000000..100644 --- a/docs/content/en/methods/resource/Data.md +++ b/docs/content/en/methods/resource/Data.md @@@ -1,66 -1,0 +1,64 @@@ +--- +title: Data +description: Applicable to resources returned by the resources.GetRemote function, returns information from the HTTP response. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: map + signatures: [RESOURCE.Data] +--- + +The `Data` method on a resource returned by the [`resources.GetRemote`] function returns information from the HTTP response. + - [`resources.GetRemote`]: /functions/resources/getremote/ - +## Example + +```go-html-template +{{ $url := "https://example.org/images/a.jpg" }} +{{ $opts := dict "responseHeaders" (slice "Server") }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else with .Value }} + {{ with .Data }} + {{ .ContentLength }} → 42764 + {{ .ContentType }} → image/jpeg + {{ .Headers }} → map[Server:[Netlify]] + {{ .Status }} → 200 OK + {{ .StatusCode }} → 200 + {{ .TransferEncoding }} → [] + {{ end }} + {{ else }} + {{ errorf "Unable to get remote resource %q" $url }} + {{ end }} +{{ end }} +``` + +## Methods + +### ContentLength + +(`int`) The content length in bytes. + +### ContentType + +(`string`) The content type. + +### Headers + +(`map[string][]string`) A map of response headers matching those requested in the [`responseHeaders`] option passed to the `resources.GetRemote` function. The header name matching is case-insensitive. In most cases there will be one value per header key. + +### Status + +(`string`) The HTTP status text. + +### StatusCode + +(`int`) The HTTP status code. + +### TransferEncoding + +(`string`) The transfer encoding. + +[`resources.GetRemote`]: /functions/resources/getremote/ +[`responseHeaders`]: /functions/resources/getremote/#responseheaders diff --cc docs/content/en/methods/resource/Name.md index c678c96c9,000000000..3331bb50d mode 100644,000000..100644 --- a/docs/content/en/methods/resource/Name.md +++ b/docs/content/en/methods/resource/Name.md @@@ -1,88 -1,0 +1,89 @@@ +--- +title: Name +description: Returns the name of the given resource as optionally defined in front matter, falling back to its file path. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [RESOURCE.Name] +--- + +The value returned by the `Name` method on a `Resource` object depends on the resource type. + +## Global resource + +With a [global resource](g), the `Name` method returns the path to the resource, relative to the `assets` directory. + +```text +assets/ +└── images/ + └── Sunrise in Bryce Canyon.jpg +``` + +```go-html-template +{{ with resources.Get "images/Sunrise in Bryce Canyon.jpg" }} + {{ .Name }} → /images/Sunrise in Bryce Canyon.jpg +{{ end }} +``` + +## Page resource + +With a [page resource](g), if you create an element in the `resources` array in front matter, the `Name` method returns the value of the `name` parameter. + +```text +content/ +├── example/ +│ ├── images/ +│ │ └── a.jpg +│ └── index.md +└── _index.md +``` + +{{< code-toggle file=content/example/index.md fm=true >}} +title = 'Example' +[[resources]] +src = 'images/a.jpg' +name = 'Sunrise in Bryce Canyon' +{{< /code-toggle >}} + +```go-html-template +{{ with .Resources.Get "images/a.jpg" }} + {{ .Name }} → Sunrise in Bryce Canyon +{{ end }} +``` + +You can also capture the image by specifying its `name` instead of its path: + +```go-html-template +{{ with .Resources.Get "Sunrise in Bryce Canyon" }} + {{ .Name }} → Sunrise in Bryce Canyon +{{ end }} +``` + +If you do not create an element in the `resources` array in front matter, the `Name` method returns the file path, relative to the page bundle. + +```text +content/ +├── example/ +│ ├── images/ +│ │ └── Sunrise in Bryce Canyon.jpg +│ └── index.md +└── _index.md +``` + +```go-html-template +{{ with .Resources.Get "images/Sunrise in Bryce Canyon.jpg" }} + {{ .Name }} → images/Sunrise in Bryce Canyon.jpg +{{ end }} +``` ++ +## Remote resource + +With a [remote resource](g), the `Name` method returns a hashed file name. + +```go-html-template +{{ with resources.GetRemote "https://example.org/images/a.jpg" }} + {{ .Name }} → /a_18432433023265451104.jpg +{{ end }} +``` diff --cc docs/content/en/methods/shortcode/IsNamedParams.md index c95398313,000000000..0574128ec mode 100644,000000..100644 --- a/docs/content/en/methods/shortcode/IsNamedParams.md +++ b/docs/content/en/methods/shortcode/IsNamedParams.md @@@ -1,29 -1,0 +1,29 @@@ +--- +title: IsNamedParams +description: Reports whether the shortcode call uses named arguments. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [SHORTCODE.IsNamedParams] +--- + +To support both positional and named arguments when calling a shortcode, use the `IsNamedParams` method to determine how the shortcode was called. + - With this shortcode template: ++With this _shortcode_ template: + +```go-html-template {file="layouts/_shortcodes/myshortcode.html"} +{{ if .IsNamedParams }} + {{ printf "%s %s." (.Get "greeting") (.Get "firstName") }} +{{ else }} + {{ printf "%s %s." (.Get 0) (.Get 1) }} +{{ end }} +``` + +Both of these calls return the same value: + +```text {file="content/about.md"} +{{}} +{{}} +``` diff --cc docs/content/en/methods/shortcode/Ordinal.md index 4c32705c1,000000000..b16758952 mode 100644,000000..100644 --- a/docs/content/en/methods/shortcode/Ordinal.md +++ b/docs/content/en/methods/shortcode/Ordinal.md @@@ -1,52 -1,0 +1,52 @@@ +--- +title: Ordinal +description: Returns the zero-based ordinal of the shortcode in relation to its parent. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [SHORTCODE.Ordinal] +--- + +The `Ordinal` method returns the zero-based ordinal of the shortcode in relation to its parent. If the parent is the page itself, the ordinal represents the position of this shortcode in the page content. + +> [!note] +> Hugo increments the ordinal with each shortcode call, regardless of the specific shortcode type. This means that the ordinal value is tracked sequentially across all shortcodes within a given page. + +This method is useful for, among other things, assigning unique element IDs when a shortcode is called two or more times from the same page. For example: + +```text {file="content/about.md"} +{{}} + +{{}} +``` + +This shortcode performs error checking, then renders an HTML `img` element with a unique `id` attribute: + +```go-html-template {file="layouts/_shortcodes/img.html"} +{{ $src := "" }} +{{ with .Get "src" }} + {{ $src = . }} + {{ with resources.Get $src }} + {{ $id := printf "img-%03d" $.Ordinal }} + + {{ else }} + {{ errorf "The %q shortcode was unable to find %s. See %s" $.Name $src $.Position }} + {{ end }} +{{ else }} + {{ errorf "The %q shortcode requires a 'src' argument. See %s" .Name .Position }} +{{ end }} +``` + +Hugo renders the page to: + +```html + + +``` + +> [!note] - > In the shortcode template above, the [`with`] statement is used to create conditional blocks. Remember that the `with` statement binds context (the dot) to its expression. Inside of a `with` block, preface shortcode method calls with a `$` to access the top-level context passed into the template. ++> In the _shortcode_ template above, the [`with`] statement is used to create conditional blocks. Remember that the `with` statement binds context (the dot) to its expression. Inside of a `with` block, preface shortcode method calls with a `$` to access the top-level context passed into the template. + +[`with`]: /functions/go-template/with/ diff --cc docs/content/en/methods/site/GetPage.md index 2a3bd7d59,000000000..34f531720 mode 100644,000000..100644 --- a/docs/content/en/methods/site/GetPage.md +++ b/docs/content/en/methods/site/GetPage.md @@@ -1,105 -1,0 +1,105 @@@ +--- +title: GetPage +description: Returns a Page object from the given path. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [SITE.GetPage PATH] +--- + +The `GetPage` method is also available on `Page` objects, allowing you to specify a path relative to the current page. See [details]. + +[details]: /methods/page/getpage/ + +When using the `GetPage` method on a `Site` object, specify a path relative to the `content` directory. + +If Hugo cannot resolve the path to a page, the method returns nil. + +Consider this content structure: + +```text +content/ +├── works/ +│ ├── paintings/ +│ │ ├── _index.md +│ │ ├── starry-night.md +│ │ └── the-mona-lisa.md +│ ├── sculptures/ +│ │ ├── _index.md +│ │ ├── david.md +│ │ └── the-thinker.md +│ └── _index.md +└── _index.md +``` + - This home template: ++This _home_ template: + - ```go-html-template ++```go-html-template {file="layouts/home.html"} +{{ with .Site.GetPage "/works/paintings" }} +
    + {{ range .Pages }} +
  • {{ .Title }} by {{ .Params.artist }}
  • + {{ end }} +
+{{ end }} +``` + +Is rendered to: + +```html +
    +
  • Starry Night by Vincent van Gogh
  • +
  • The Mona Lisa by Leonardo da Vinci
  • +
+``` + +To get a regular page instead of a section page: + - ```go-html-template ++```go-html-template {file="layouts/home.html"} +{{ with .Site.GetPage "/works/paintings/starry-night" }} + {{ .Title }} → Starry Night + {{ .Params.artist }} → Vincent van Gogh +{{ end }} +``` + +## Multilingual projects + +With multilingual projects, the `GetPage` method on a `Site` object resolves the given path to a page in the current language. + +To get a page from a different language, query the `Sites` object: + +```go-html-template +{{ with where .Site.Sites "Language.Lang" "eq" "de" }} + {{ with index . 0 }} + {{ with .GetPage "/works/paintings/starry-night" }} + {{ .Title }} → Sternenklare Nacht + {{ end }} + {{ end }} +{{ end }} +``` + +## Page bundles + +Consider this content structure: + +```text +content/ +├── headless/ +│ ├── a.jpg +│ ├── b.jpg +│ ├── c.jpg +│ └── index.md <-- front matter: headless = true +└── _index.md +``` + - In the home template, use the `GetPage` method on a `Site` object to render all the images in the headless [page bundle](g): ++In the _home_ template, use the `GetPage` method on a `Site` object to render all the images in the headless [page bundle](g): + - ```go-html-template ++```go-html-template {file="layouts/home.html"} +{{ with .Site.GetPage "/headless" }} + {{ range .Resources.ByType "image" }} + + {{ end }} +{{ end }} +``` diff --cc docs/content/en/methods/site/MainSections.md index bee4f2d57,000000000..6a0dbdc74 mode 100644,000000..100644 --- a/docs/content/en/methods/site/MainSections.md +++ b/docs/content/en/methods/site/MainSections.md @@@ -1,54 -1,0 +1,54 @@@ +--- +title: MainSections +description: Returns a slice of the main section names as defined in the site configuration, falling back to the top-level section with the most pages. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: '[]string' + signatures: [SITE.MainSections] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +mainSections = ['books','films'] +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.MainSections }} → [books films] +``` + +If `mainSections` is not defined in the site configuration, this method returns a slice with one element---the top-level section with the most pages. + +With this content structure, the "films" section has the most pages: + +```text +content/ +├── books/ +│ ├── book-1.md +│ └── book-2.md +├── films/ +│ ├── film-1.md +│ ├── film-2.md +│ └── film-3.md +└── _index.md +``` + +Template: + +```go-html-template +{{ .Site.MainSections }} → [films] +``` + +When creating a theme, instead of hardcoding section names when listing the most relevant pages on the front page, instruct site authors to set `mainSections` in their site configuration. + - Then your home template can do something like this: ++Then your _home_ template can do something like this: + - ```go-html-template ++```go-html-template {file="layouts/home.html"} +{{ range where .Site.RegularPages "Section" "in" .Site.MainSections }} +

{{ .LinkTitle }}

+{{ end }} +``` diff --cc docs/content/en/methods/site/Menus.md index 398a9b022,000000000..0c8509e92 mode 100644,000000..100644 --- a/docs/content/en/methods/site/Menus.md +++ b/docs/content/en/methods/site/Menus.md @@@ -1,89 -1,0 +1,89 @@@ +--- +title: Menus +description: Returns a collection of menu objects for the given site. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: navigation.Menus + signatures: [SITE.Menus] +--- + +The `Menus` method on a `Site` object returns a collection of menus, where each menu contains one or more entries, either flat or nested. Each entry points to a page within the site, or to an external resource. + +> [!note] +> Menus can be defined and localized in several ways. Please see the [menus] section for a complete explanation and examples. + +A site can have multiple menus. For example, a main menu and a footer menu: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Home' +pageRef = '/' +weight = 10 + +[[menus.main]] +name = 'Books' +pageRef = '/books' +weight = 20 + +[[menus.main]] +name = 'Films' +pageRef = '/films' +weight = 30 + +[[menus.footer]] +name = 'Legal' +pageRef = '/legal' +weight = 10 + +[[menus.footer]] +name = 'Privacy' +pageRef = '/privacy' +weight = 20 +{{< /code-toggle >}} + +This template renders the main menu: + +```go-html-template +{{ with site.Menus.main }} + +{{ end }} +``` + +When viewing the home page, the result is: + +```html + +``` + +When viewing the "books" page, the result is: + +```html + +``` + - You will typically render a menu using a partial template. As the active menu entry will be different on each page, use the [`partial`] function to call the template. Do not use the [`partialCached`] function. ++You will typically render a menu using a _partial_ template. As the active menu entry will be different on each page, use the [`partial`] function to call the template. Do not use the [`partialCached`] function. + +The example above is simplistic. Please see the [menu templates] section for more information. + +[`partial`]: /functions/partials/include/ +[`partialCached`]: /functions/partials/includecached/ +[menu templates]: /templates/menu/ +[menus]: /content-management/menus/ diff --cc docs/content/en/methods/site/Store.md index 7dcf7d095,000000000..6c6d57a90 mode 100644,000000..100644 --- a/docs/content/en/methods/site/Store.md +++ b/docs/content/en/methods/site/Store.md @@@ -1,117 -1,0 +1,117 @@@ +--- +title: Store +description: Returns a "scratch pad" to store and manipulate data, scoped to the current site. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: maps.Scratch + signatures: [site.Store] +--- + +{{< new-in 0.139.0 />}} + +Use the `Store` method on a `Site` object to create a [scratch pad](g) to store and manipulate data, scoped to the current site. To create a scratch pad with a different [scope](g), refer to the [scope](#scope) section below. + +## Methods + +### Set + +Sets the value of a given key. + +```go-html-template +{{ site.Store.Set "greeting" "Hello" }} +``` + +### Get + +Gets the value of a given key. + +```go-html-template +{{ site.Store.Set "greeting" "Hello" }} +{{ site.Store.Get "greeting" }} → Hello +``` + +### Add + +Adds a given value to existing value(s) of the given key. + +For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be appended to that list. + +```go-html-template +{{ site.Store.Set "greeting" "Hello" }} +{{ site.Store.Add "greeting" "Welcome" }} +{{ site.Store.Get "greeting" }} → HelloWelcome +``` + +```go-html-template +{{ site.Store.Set "total" 3 }} +{{ site.Store.Add "total" 7 }} +{{ site.Store.Get "total" }} → 10 +``` + +```go-html-template +{{ site.Store.Set "greetings" (slice "Hello") }} +{{ site.Store.Add "greetings" (slice "Welcome" "Cheers") }} +{{ site.Store.Get "greetings" }} → [Hello Welcome Cheers] + ``` + +### SetInMap + +Takes a `key`, `mapKey` and `value` and adds a map of `mapKey` and `value` to the given `key`. + +```go-html-template +{{ site.Store.SetInMap "greetings" "english" "Hello" }} +{{ site.Store.SetInMap "greetings" "french" "Bonjour" }} +{{ site.Store.Get "greetings" }} → map[english:Hello french:Bonjour] +``` + +### DeleteInMap + +Takes a `key` and `mapKey` and removes the map of `mapKey` from the given `key`. + +```go-html-template +{{ site.Store.SetInMap "greetings" "english" "Hello" }} +{{ site.Store.SetInMap "greetings" "french" "Bonjour" }} +{{ site.Store.DeleteInMap "greetings" "english" }} +{{ site.Store.Get "greetings" }} → map[french:Bonjour] +``` + +### GetSortedMapValues + +Returns an array of values from `key` sorted by `mapKey`. + +```go-html-template +{{ site.Store.SetInMap "greetings" "english" "Hello" }} +{{ site.Store.SetInMap "greetings" "french" "Bonjour" }} +{{ site.Store.GetSortedMapValues "greetings" }} → [Hello Bonjour] +``` + +### Delete + +Removes the given key. + +```go-html-template +{{ site.Store.Set "greeting" "Hello" }} +{{ site.Store.Delete "greeting" }} +``` + +{{% include "_common/scratch-pad-scope.md" %}} + +## 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: + +```go-html-template +{{ $noop := .Content }} +{{ site.Store.Get "mykey" }} +``` + +You can also trigger content rendering with the `ContentWithoutSummary`, `FuzzyWordCount`, `Len`, `Plain`, `PlainWords`, `ReadingTime`, `Summary`, `Truncated`, and `WordCount` methods. For example: + +```go-html-template +{{ $noop := .WordCount }} +{{ site.Store.Get "mykey" }} +``` diff --cc docs/content/en/methods/site/Taxonomies.md index 857bfd01d,000000000..ab28aff1d mode 100644,000000..100644 --- a/docs/content/en/methods/site/Taxonomies.md +++ b/docs/content/en/methods/site/Taxonomies.md @@@ -1,176 -1,0 +1,181 @@@ +--- +title: Taxonomies +description: Returns a data structure containing the site's Taxonomy objects, the terms within each Taxonomy object, and the pages to which the terms are assigned. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.TaxonomyList + signatures: [SITE.Taxonomies] +--- + +Conceptually, the `Taxonomies` method on a `Site` object returns a data structure such as: + ++ +{{< code-toggle file=hugo >}} +taxonomy a: + - term 1: + - page 1 + - page 2 + - term 2: + - page 1 +taxonomy b: + - term 1: + - page 2 + - term 2: + - page 1 + - page 2 +{{< /code-toggle >}} ++ + +For example, on a book review site you might create two taxonomies; one for genres and another for authors. + +With this site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +genre = 'genres' +author = 'authors' +{{< /code-toggle >}} + +And this content structure: + +```text +content/ +├── books/ +│ ├── and-then-there-were-none.md --> genres: suspense +│ ├── death-on-the-nile.md --> genres: suspense +│ └── jamaica-inn.md --> genres: suspense, romance +│ └── pride-and-prejudice.md --> genres: romance +└── _index.md +``` + +Conceptually, the taxonomies data structure looks like: + ++ +{{< code-toggle file=hugo >}} +genres: + - suspense: + - And Then There Were None + - Death on the Nile + - Jamaica Inn + - romance: + - Jamaica Inn + - Pride and Prejudice +authors: + - achristie: + - And Then There Were None + - Death on the Nile + - ddmaurier: + - Jamaica Inn + - jausten: + - Pride and Prejudice +{{< /code-toggle >}} ++ + +To list the "suspense" books: + +```go-html-template +
    + {{ range .Site.Taxonomies.genres.suspense }} +
  • {{ .LinkTitle }}
  • + {{ end }} +
+``` + +Hugo renders this to: + +```html + +``` + +> [!note] +> Hugo's taxonomy system is powerful, allowing you to classify content and create relationships between pages. +> +> Please see the [taxonomies] section for a complete explanation and examples. + +## Examples + +### List content with the same taxonomy term + +If you are using a taxonomy for something like a series of posts, you can list individual pages associated with the same term. For example: + +```go-html-template + +``` + +### List all content in a given taxonomy + +This would be very useful in a sidebar as “featured content”. You could even have different sections of “featured content” by assigning different terms to the content. + +```go-html-template + +``` + +### Render a site's taxonomies + +The following example displays all terms in a site's tags taxonomy: + +```go-html-template + +``` ++ +This example will list all taxonomies and their terms, as well as all the content assigned to each of the terms. + +```go-html-template {file="layouts/_partials/all-taxonomies.html"} +{{ with .Site.Taxonomies }} + {{ $numberOfTerms := 0 }} + {{ range $taxonomy, $terms := . }} + {{ $numberOfTerms = len . | add $numberOfTerms }} + {{ end }} + + {{ if gt $numberOfTerms 0 }} + + {{ end }} +{{ end }} +``` + +[taxonomies]: /content-management/taxonomies/ diff --cc docs/content/en/methods/time/Round.md index 816d41b44,000000000..afda0e294 mode 100644,000000..100644 --- a/docs/content/en/methods/time/Round.md +++ b/docs/content/en/methods/time/Round.md @@@ -1,21 -1,0 +1,21 @@@ +--- +title: Round +description: Returns the result of rounding TIME to the nearest multiple of DURATION since January 1, 0001, 00:00:00 UTC. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [TIME.Round DURATION] +--- + +The rounding behavior for halfway values is to round up. + +The `Round` method operates on TIME as an absolute duration since the [zero time](g); it does not operate on the presentation form of the time. If DURATION is a multiple of one hour, `Round` may return a time with a non-zero minute, depending on the time zone. + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} - {{ $d := time.ParseDuration "1h"}} ++{{ $d := time.ParseDuration "1h" }} + +{{ ($t.Round $d).Format "2006-01-02T15:04:05-00:00" }} → 2023-01-28T00:00:00-00:00 +``` diff --cc docs/content/en/methods/time/Truncate.md index b797afec0,000000000..b90c3847f mode 100644,000000..100644 --- a/docs/content/en/methods/time/Truncate.md +++ b/docs/content/en/methods/time/Truncate.md @@@ -1,19 -1,0 +1,19 @@@ +--- +title: Truncate +description: Returns the result of rounding TIME down to a multiple of DURATION since January 1, 0001, 00:00:00 UTC. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [TIME.Truncate DURATION] +--- + +The `Truncate` method operates on TIME as an absolute duration since the [zero time](g); it does not operate on the presentation form of the time. If DURATION is a multiple of one hour, `Truncate` may return a time with a non-zero minute, depending on the time zone. + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} - {{ $d := time.ParseDuration "1h"}} ++{{ $d := time.ParseDuration "1h" }} + +{{ ($t.Truncate $d).Format "2006-01-02T15:04:05-00:00" }} → 2023-01-27T23:00:00-00:00 +``` diff --cc docs/content/en/quick-reference/glossary/raw-string-literal.md index 7465c6837,000000000..a3ceabe10 mode 100644,000000..100644 --- a/docs/content/en/quick-reference/glossary/raw-string-literal.md +++ b/docs/content/en/quick-reference/glossary/raw-string-literal.md @@@ -1,6 -1,0 +1,6 @@@ +--- +title: raw string literal +reference: https://go.dev/ref/spec#String_literals +--- + - A _raw string literal_ is a character sequences between backticks, as in \`bar\`. Within the backticks, any character may appear except a backtick. Backslashes have no special meaning and the string may contain newlines. Carriage return characters (`\r`) inside raw string literals are discarded from the raw string value. ++A _raw string literal_ is a character sequence between backticks, as in \`bar\`. Within the backticks, any character may appear except a backtick. Backslashes have no special meaning and the string may contain newlines. Carriage return characters (`\r`) inside raw string literals are discarded from the raw string value. diff --cc docs/content/en/quick-reference/syntax-highlighting-styles.md index 14b313cbc,000000000..76aa77bf4 mode 100644,000000..100644 --- a/docs/content/en/quick-reference/syntax-highlighting-styles.md +++ b/docs/content/en/quick-reference/syntax-highlighting-styles.md @@@ -1,35 -1,0 +1,35 @@@ +--- +title: Syntax highlighting styles +description: Highlight code examples using one of these styles. +categories: [] +keywords: [highlight] +--- + +## Overview + +Hugo provides several methods to add syntax highlighting to code examples: + +- Use the [`transform.Highlight`] function within your templates +- Use the [`highlight`] shortcode with any [content format](g) - - Use fenced code blocks with the Markdown content format ++- Use [fenced code blocks] with the Markdown content format + +Regardless of method, use any of the syntax highlighting styles below. + +Set the default syntax highlighting style in your site configuration: + +{{< code-toggle file=hugo >}} +[markup.highlight] +style = 'monokai' +{{< /code-toggle >}} + +See [configure Markup](/configuration/markup/#highlight). + +[`transform.Highlight`]: /functions/transform/highlight/ +[`highlight`]: /shortcodes/highlight/ +[fenced code blocks]: /content-management/syntax-highlighting/#fenced-code-blocks + +## Styles + +This gallery demonstrates the application of each syntax highlighting style with code examples written in different programming languages. + +{{% syntax-highlighting-styles %}} diff --cc docs/content/en/render-hooks/_index.md index a5e6203ff,000000000..a957cb4cf mode 100644,000000..100644 --- a/docs/content/en/render-hooks/_index.md +++ b/docs/content/en/render-hooks/_index.md @@@ -1,8 -1,0 +1,8 @@@ +--- +title: Render hooks - description: Create render hooks to override the rendering of Markdown to HTML. ++description: Create render hook templates to override the rendering of Markdown to HTML. +categories: [] +keywords: [] +weight: 10 +aliases: [/templates/render-hooks/] +--- diff --cc docs/content/en/render-hooks/blockquotes.md index 411c6c796,000000000..77e7059c7 mode 100755,000000..100755 --- a/docs/content/en/render-hooks/blockquotes.md +++ b/docs/content/en/render-hooks/blockquotes.md @@@ -1,183 -1,0 +1,183 @@@ +--- +title: Blockquote render hooks +linkTitle: Blockquotes - description: Create a blockquote render hook to override the rendering of Markdown blockquotes to HTML. ++description: Create blockquote render hook templates to override the rendering of Markdown blockquotes to HTML. +categories: [] +keywords: [] +--- + +{{< new-in 0.132.0 />}} + +## Context + - Blockquote render hook templates receive the following [context](g): ++Blockquote _render hook_ templates receive the following [context](g): + +AlertType +: (`string`) Applicable when [`Type`](#type) is `alert`, this is the alert type converted to lowercase. See the [alerts](#alerts) section below. + +AlertTitle +: {{< new-in 0.134.0 />}} +: (`template.HTML`) Applicable when [`Type`](#type) is `alert`, this is the alert title. See the [alerts](#alerts) section below. + +AlertSign +: {{< new-in 0.134.0 />}} +: (`string`) Applicable when [`Type`](#type) is `alert`, this is the alert sign. Typically used to indicate whether an alert is graphically foldable, this is one of `+`, `-`, or an empty string. See the [alerts](#alerts) section below. + +Attributes +: (`map`) The [Markdown attributes], available if you configure your site as follows: + + {{< code-toggle file=hugo >}} + [markup.goldmark.parser.attribute] + block = true + {{< /code-toggle >}} + +Ordinal +: (`int`) The zero-based ordinal of the blockquote on the page. + +Page +: (`page`) A reference to the current page. + +PageInner +: (`page`) A reference to a page nested via the [`RenderShortcodes`] method. [See details](#pageinner-details). + +Position +: (`string`) The position of the blockquote within the page content. + +Text +: (`template.HTML`) The blockquote text, excluding the first line if [`Type`](#type) is `alert`. See the [alerts](#alerts) section below. + +Type +: (`string`) The blockquote type. Returns `alert` if the blockquote has an alert designator, else `regular`. See the [alerts](#alerts) section below. + +## Examples + +In its default configuration, Hugo renders Markdown blockquotes according to the [CommonMark specification]. To create a render hook that does the same thing: + +```go-html-template {file="layouts/_markup/render-blockquote.html" copy=true} +
+ {{ .Text }} +
+``` + +To render a blockquote as an HTML `figure` element with an optional citation and caption: + +```go-html-template {file="layouts/_markup/render-blockquote.html" copy=true} +
+
+ {{ .Text }} +
+ {{ with .Attributes.caption }} +
+ {{ . | safeHTML }} +
+ {{ end }} +
+``` + +Then in your markdown: + +```text +> Some text +{cite="https://gohugo.io" caption="Some caption"} +``` + +## Alerts + +Also known as _callouts_ or _admonitions_, alerts are blockquotes used to emphasize critical information. + +### Basic syntax + +With the basic Markdown syntax, the first line of each alert is an alert designator consisting of an exclamation point followed by the alert type, wrapped within brackets. For example: + +```text {file="content/example.md"} +> [!NOTE] +> Useful information that users should know, even when skimming content. + +> [!TIP] +> Helpful advice for doing things better or more easily. + +> [!IMPORTANT] +> Key information users need to know to achieve their goal. + +> [!WARNING] +> Urgent info that needs immediate user attention to avoid problems. + +> [!CAUTION] +> Advises about risks or negative outcomes of certain actions. +``` + +The basic syntax is compatible with [GitHub], [Obsidian], and [Typora]. + +### Extended syntax + +With the extended Markdown syntax, you may optionally include an alert sign and/or an alert title. The alert sign is one of `+` or `-`, typically used to indicate whether an alert is graphically foldable. For example: + +```text {file="content/example.md"} +> [!WARNING]+ Radiation hazard +> Do not approach or handle without protective gear. +``` + +The extended syntax is compatible with [Obsidian]. + +> [!note] +> The extended syntax is not compatible with GitHub or Typora. If you include an alert sign or an alert title, these applications render the Markdown as a blockquote. + +### Example + +This blockquote render hook renders a multilingual alert if an alert designator is present, otherwise it renders a blockquote according to the CommonMark specification. + +```go-html-template {file="layouts/_markup/render-blockquote.html" copy=true} +{{ $emojis := dict + "caution" ":exclamation:" + "important" ":information_source:" + "note" ":information_source:" + "tip" ":bulb:" + "warning" ":information_source:" +}} + +{{ if eq .Type "alert" }} +
+

+ {{ transform.Emojify (index $emojis .AlertType) }} + {{ with .AlertTitle }} + {{ . }} + {{ else }} + {{ or (i18n .AlertType) (title .AlertType) }} + {{ end }} +

+ {{ .Text }} +
+{{ else }} +
+ {{ .Text }} +
+{{ end }} +``` + +To override the label, create these entries in your i18n files: + +{{< code-toggle file=i18n/en.toml >}} +caution = 'Caution' +important = 'Important' +note = 'Note' +tip = 'Tip' +warning = 'Warning' +{{< /code-toggle >}} + +Although you can use one template with conditional logic as shown above, you can also create separate templates for each [`Type`](#type) of blockquote: + +```text +layouts/ + └── _markup/ + ├── render-blockquote-alert.html + └── render-blockquote-regular.html +``` + +{{% include "/_common/render-hooks/pageinner.md" %}} + +[`RenderShortcodes`]: /methods/page/rendershortcodes +[CommonMark specification]: https://spec.commonmark.org/current/ +[GitHub]: https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts +[Markdown attributes]: /content-management/markdown-attributes/ +[Obsidian]: https://help.obsidian.md/Editing+and+formatting/Callouts +[Typora]: https://support.typora.io/Markdown-Reference/#callouts--github-style-alerts diff --cc docs/content/en/render-hooks/code-blocks.md index 6e0ea011f,000000000..526a1232f mode 100755,000000..100755 --- a/docs/content/en/render-hooks/code-blocks.md +++ b/docs/content/en/render-hooks/code-blocks.md @@@ -1,126 -1,0 +1,126 @@@ +--- +title: Code block render hooks +linkTitle: Code blocks - description: Create a code block render hook to override the rendering of Markdown code blocks to HTML. ++description: Create code block render hook templates to override the rendering of Markdown code blocks to HTML. +categories: [] +keywords: [] +--- + +## Markdown + +This Markdown example contains a fenced code block: + +````text {file="content/example.md"} +```bash {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2} +declare a=1 +echo "$a" +exit +``` +```` + +A fenced code block consists of: + +- A leading [code fence] +- An optional [info string] +- A code sample +- A trailing code fence + +In the previous example, the info string contains: + +- The language of the code sample (the first word) +- An optional space-delimited or comma-delimited list of attributes (everything within braces) + +The attributes in the info string can be generic attributes or highlighting options. + +In the example above, the _generic attributes_ are `class` and `id`. In the absence of special handling within a code block render hook, Hugo adds each generic attribute to the HTML element surrounding the rendered code block. Consistent with its content security model, Hugo removes HTML event attributes such as `onclick` and `onmouseover`. Generic attributes are typically global HTML attributes, but you may include custom attributes as well. + +In the example above, the _highlighting options_ are `lineNos` and `tabWidth`. Hugo uses the [Chroma] syntax highlighter to render the code sample. You can control the appearance of the rendered code by specifying one or more [highlighting options]. + +> [!note] +> Although `style` is a global HTML attribute, when used in an info string it is a highlighting option. + +## Context + - Code block render hook templates receive the following [context](g): ++Code block _render hook_ templates receive the following [context](g): + +Attributes +: (`map`) The generic attributes from the info string. + +Inner +: (`string`) The content between the leading and trailing code fences, excluding the info string. + +Options - : (`map`) The highlighting options from the info string. ++: (`map`) The highlighting options from the info string. This map is empty if [`Type`](#type) is an empty string or a code language that is not supported by the Chroma syntax highlighter. However, in this case, the highlighting options are available in the [`Attributes`](#attributes) map. + +Ordinal +: (`int`) The zero-based ordinal of the code block on the page. + +Page +: (`page`) A reference to the current page. + +PageInner +: {{< new-in 0.125.0 />}} +: (`page`) A reference to a page nested via the [`RenderShortcodes`] method. [See details](#pageinner-details). + +Position +: (`text.Position`) The position of the code block within the page content. + +Type +: (`string`) The first word of the info string, typically the code language. + +## Examples + +In its default configuration, Hugo renders fenced code blocks by passing the code sample through the Chroma syntax highlighter and wrapping the result. To create a render hook that does the same thing: + +```go-html-template {file="layouts/_markup/render-codeblock.html" copy=true} +{{ $result := transform.HighlightCodeBlock . }} +{{ $result.Wrapped }} +``` + +Although you can use one template with conditional logic to control the behavior on a per-language basis, you can also create language-specific templates. + +```text +layouts/ + └── _markup/ + ├── render-codeblock-mermaid.html + ├── render-codeblock-python.html + └── render-codeblock.html +``` + +For example, to create a code block render hook to render [Mermaid] diagrams: + +```go-html-template {file="layouts/_markup/render-codeblock-mermaid.html" copy=true} +
 +  {{ .Inner | htmlEscape | safeHTML }}
 +
+{{ .Page.Store.Set "hasMermaid" true }} +``` + +Then include this snippet at the _bottom_ of your base template, before the closing `body` tag: + +```go-html-template {file="layouts/baseof.html" copy=true} +{{ if .Store.Get "hasMermaid" }} + +{{ end }} +``` + +See the [diagrams] page for details. + +## Embedded + +Hugo includes an [embedded code block render hook] to render [GoAT diagrams]. + +{{% include "/_common/render-hooks/pageinner.md" %}} + +[`RenderShortcodes`]: /methods/page/rendershortcodes +[Chroma]: https://github.com/alecthomas/chroma/ +[code fence]: https://spec.commonmark.org/current/#code-fence +[diagrams]: /content-management/diagrams/#mermaid-diagrams +[embedded code block render hook]: {{% eturl render-codeblock-goat %}} +[GoAT diagrams]: /content-management/diagrams/#goat-diagrams-ascii +[highlighting options]: /functions/transform/highlight/#options +[info string]: https://spec.commonmark.org/current/#info-string +[Mermaid]: https://mermaid.js.org/ diff --cc docs/content/en/render-hooks/headings.md index 5279dff78,000000000..44281bb3d mode 100755,000000..100755 --- a/docs/content/en/render-hooks/headings.md +++ b/docs/content/en/render-hooks/headings.md @@@ -1,64 -1,0 +1,64 @@@ +--- +title: Heading render hooks +linkTitle: Headings - description: Create a heading render hook to override the rendering of Markdown headings to HTML. ++description: Create heading render hook templates to override the rendering of Markdown headings to HTML. +categories: [] +keywords: [] +--- + +## Context + - Heading render hook templates receive the following [context](g): ++Heading _render hook_ templates receive the following [context](g): + +Anchor +: (`string`) The `id` attribute of the heading element. + +Attributes +: (`map`) The [Markdown attributes], available if you configure your site as follows: + + {{< code-toggle file=hugo >}} + [markup.goldmark.parser.attribute] + title = true + {{< /code-toggle >}} + +Level +: (`int`) The heading level, 1 through 6. + +Page +: (`page`) A reference to the current page. + +PageInner +: {{< new-in 0.125.0 />}} +: (`page`) A reference to a page nested via the [`RenderShortcodes`] method. [See details](#pageinner-details). + +PlainText +: (`string`) The heading text as plain text. + +Text +: (`template.HTML`) The heading text. + +[Markdown attributes]: /content-management/markdown-attributes/ +[`RenderShortcodes`]: /methods/page/rendershortcodes + +## Examples + +In its default configuration, Hugo renders Markdown headings according to the [CommonMark specification] with the addition of automatic `id` attributes. To create a render hook that does the same thing: + +[CommonMark specification]: https://spec.commonmark.org/current/ + +```go-html-template {file="layouts/_markup/render-heading.html" copy=true} + + {{- .Text -}} + +``` + +To add an anchor link to the right of each heading: + +```go-html-template {file="layouts/_markup/render-heading.html" copy=true} + + {{ .Text }} + # + +``` + +{{% include "/_common/render-hooks/pageinner.md" %}} diff --cc docs/content/en/render-hooks/images.md index 9f8ef1efb,000000000..bee068a0d mode 100755,000000..100755 --- a/docs/content/en/render-hooks/images.md +++ b/docs/content/en/render-hooks/images.md @@@ -1,138 -1,0 +1,137 @@@ +--- +title: Image render hooks +linkTitle: Images - description: Create an image render to hook override the rendering of Markdown images to HTML. ++description: Create image render hook templates to override the rendering of Markdown images to HTML. +categories: [] +keywords: [] +--- + +## Markdown + +A Markdown image has three components: the image description, the image destination, and optionally the image title. + +```text +![white kitten](/images/kitten.jpg "A kitten!") + ------------ ------------------ --------- + description destination title +``` + +These components are passed into the render hook [context](g) as shown below. + +## Context + - Image render hook templates receive the following context: ++Image _render hook_ templates receive the following context: + +Attributes +: (`map`) The [Markdown attributes], available if you configure your site as follows: + + {{< code-toggle file=hugo >}} + [markup.goldmark.parser] + wrapStandAloneImageWithinParagraph = false + [markup.goldmark.parser.attribute] + block = true + {{< /code-toggle >}} + +Destination +: (`string`) The image destination. + +IsBlock +: (`bool`) Reports whether a standalone image is not wrapped within a paragraph element. + +Ordinal +: (`int`) The zero-based ordinal of the image on the page. + +Page +: (`page`) A reference to the current page. + +PageInner +: {{< new-in 0.125.0 />}} +: (`page`) A reference to a page nested via the [`RenderShortcodes`] method. [See details](#pageinner-details). + +PlainText +: (`string`) The image description as plain text. + +Text +: (`template.HTML`) The image description. + +Title +: (`string`) The image title. + +## Examples + +> [!note] +> With inline elements such as images and links, remove leading and trailing whitespace using the `{{‑ ‑}}` delimiter notation to prevent whitespace between adjacent inline elements and text. + +In its default configuration, Hugo renders Markdown images according to the [CommonMark specification]. To create a render hook that does the same thing: + +```go-html-template {file="layouts/_markup/render-image.html" copy=true} +{{ . }} +{{- /* chomp trailing newline */ -}} +``` + +To render standalone images within `figure` elements: + +```go-html-template {file="layouts/_markup/render-image.html" copy=true} +{{- if .IsBlock -}} +
+ {{ . }} + {{- with .Title }}
{{ . }}
{{ end -}} +
+{{- else -}} + {{ . }} +{{- end -}} +``` + +Note that the above requires the following site configuration: + +{{< code-toggle file=hugo >}} +[markup.goldmark.parser] +wrapStandAloneImageWithinParagraph = false +{{< /code-toggle >}} + - ## Default ++## Embedded + +{{< new-in 0.123.0 />}} + - Hugo includes an [embedded image render hook] to resolve Markdown image destinations. Disabled by default, you can enable it in your site configuration: ++Hugo includes an [embedded image render hook] to resolve Markdown image destinations. You can adjust its behavior in your site configuration. This is the default setting: + +{{< code-toggle file=hugo >}} +[markup.goldmark.renderHooks.image] - enableDefault = true ++useEmbedded = 'auto' +{{< /code-toggle >}} + - A custom render hook, even when provided by a theme or module, will override the embedded render hook regardless of the configuration setting above. ++When set to `auto` as shown above, Hugo automatically uses 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. + - > [!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. ++You can also configure Hugo to `always` use the embedded image render hook, use it only as a `fallback`, or `never` use it. See [details](/configuration/markup/#renderhooksimageuseembedded). + +The embedded image render hook resolves internal Markdown destinations by looking for a matching [page resource](g), falling back to a matching [global resource](g). Remote destinations are passed through, and the render hook will not throw an error or warning if unable to resolve a destination. + +You must place global resources in the `assets` directory. If you have placed your resources in the `static` directory, and you are unable or unwilling to move them, you must mount the `static` directory to the `assets` directory by including both of these entries in your site configuration: + +{{< code-toggle file=hugo >}} +[[module.mounts]] +source = 'assets' +target = 'assets' + +[[module.mounts]] +source = 'static' +target = 'assets' +{{< /code-toggle >}} + +Note that the embedded image render hook does not perform image processing. Its sole purpose is to resolve Markdown image destinations. + +{{% include "/_common/render-hooks/pageinner.md" %}} + +[`RenderShortcodes`]: /methods/page/rendershortcodes +[CommonMark specification]: https://spec.commonmark.org/current/ +[duplication of shared page resources]: /configuration/markup/#duplicateresourcefiles +[embedded image render hook]: {{% eturl render-image %}} +[Markdown attributes]: /content-management/markdown-attributes/ diff --cc docs/content/en/render-hooks/links.md index af0a8f0dd,000000000..0e6519e2e mode 100755,000000..100755 --- a/docs/content/en/render-hooks/links.md +++ b/docs/content/en/render-hooks/links.md @@@ -1,108 -1,0 +1,107 @@@ +--- +title: Link render hooks +linkTitle: Links +description: Create a link render hook to override the rendering of Markdown links to HTML. +categories: [] +keywords: [] +--- + +## Markdown + +A Markdown link has three components: the link text, the link destination, and optionally the link title. + +```text +[Post 1](/posts/post-1 "My first post") + ------ ------------- ------------- + text destination title +``` + +These components are passed into the render hook [context](g) as shown below. + +## Context + - Link render hook templates receive the following context: ++Link _render hook_ templates receive the following context: + +Destination +: (`string`) The link destination. + +Page +: (`page`) A reference to the current page. + +PageInner +: {{< new-in 0.125.0 />}} +: (`page`) A reference to a page nested via the [`RenderShortcodes`] method. [See details](#pageinner-details). + +PlainText +: (`string`) The link description as plain text. + +Text +: (`template.HTML`) The link description. + +Title +: (`string`) The link title. + +## Examples + +> [!note] +> With inline elements such as images and links, remove leading and trailing whitespace using the `{{‑ ‑}}` delimiter notation to prevent whitespace between adjacent inline elements and text. + +In its default configuration, Hugo renders Markdown links according to the [CommonMark specification]. To create a render hook that does the same thing: + +```go-html-template {file="layouts/_markup/render-link.html" copy=true} + + {{- with .Text }}{{ . }}{{ end -}} + +{{- /* chomp trailing newline */ -}} +``` + +To include a `rel` attribute set to `external` for external links: + +```go-html-template {file="layouts/_markup/render-link.html" copy=true} +{{- $u := urls.Parse .Destination -}} + + {{- with .Text }}{{ . }}{{ end -}} + +{{- /* chomp trailing newline */ -}} +``` + - ## Default ++## Embedded + +{{< new-in 0.123.0 />}} + - Hugo includes an [embedded link render hook] to resolve Markdown link destinations. Disabled by default, you can enable it in your site configuration: ++Hugo includes an [embedded link render hook] to resolve Markdown link destinations. You can adjust its behavior in your site configuration. This is the default setting: + +{{< code-toggle file=hugo >}} +[markup.goldmark.renderHooks.link] - enableDefault = true ++useEmbedded = 'auto' +{{< /code-toggle >}} + - A custom render hook, even when provided by a theme or module, will override the embedded render hook regardless of the configuration setting above. ++When set to `auto` as shown above, Hugo automatically uses 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. + - > [!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. ++You can also configure Hugo to `always` use the embedded link render hook, use it only as a `fallback`, or `never` use it. See [details](/configuration/markup/#renderhookslinkuseembedded). + +The embedded link render hook resolves internal Markdown destinations by looking for a matching page, falling back to a matching [page resource](g), then falling back to a matching [global resource](g). Remote destinations are passed through, and the render hook will not throw an error or warning if unable to resolve a destination. + +You must place global resources in the `assets` directory. If you have placed your resources in the `static` directory, and you are unable or unwilling to move them, you must mount the `static` directory to the `assets` directory by including both of these entries in your site configuration: + +{{< code-toggle file=hugo >}} +[[module.mounts]] +source = 'assets' +target = 'assets' + +[[module.mounts]] +source = 'static' +target = 'assets' +{{< /code-toggle >}} + +{{% include "/_common/render-hooks/pageinner.md" %}} + +[`RenderShortcodes`]: /methods/page/rendershortcodes +[CommonMark specification]: https://spec.commonmark.org/current/ +[duplication of shared page resources]: /configuration/markup/#duplicateresourcefiles +[embedded link render hook]: {{% eturl render-link %}} diff --cc docs/content/en/render-hooks/passthrough.md index ea0df8824,000000000..253039316 mode 100755,000000..100755 --- a/docs/content/en/render-hooks/passthrough.md +++ b/docs/content/en/render-hooks/passthrough.md @@@ -1,123 -1,0 +1,123 @@@ +--- +title: Passthrough render hooks +linkTitle: Passthrough - description: Create a passthrough render hook to override the rendering of text snippets captured by the Goldmark Passthrough extension. ++description: Create passthrough render hook templates to override the rendering of text snippets captured by the Goldmark Passthrough extension. +categories: [] +keywords: [] +--- + +{{< new-in 0.132.0 />}} + +## Overview + +Hugo uses [Goldmark] to render Markdown to HTML. Goldmark supports custom extensions to extend its core functionality. The [Passthrough] extension captures and preserves raw Markdown within delimited snippets of text, including the delimiters themselves. These are known as _passthrough elements_. + +[Goldmark]: https://github.com/yuin/goldmark +[Passthrough]: /configuration/markup/#passthrough + +Depending on your choice of delimiters, Hugo will classify a passthrough element as either _block_ or _inline_. Consider this contrived example: + +```text {file="content/example.md"} +This is a + +\[block\] + +passthrough element with opening and closing block delimiters. + +This is an \(inline\) passthrough element with opening and closing inline delimiters. +``` + +Update your site configuration to enable the Passthrough extension and define opening and closing delimiters for each passthrough element type, either `block` or `inline`. For example: + +{{< code-toggle file=hugo >}} +[markup.goldmark.extensions.passthrough] +enable = true +[markup.goldmark.extensions.passthrough.delimiters] +block = [['\[', '\]'], ['$$', '$$']] +inline = [['\(', '\)']] +{{< /code-toggle >}} + +In the example above there are two sets of `block` delimiters. You may use either one in your Markdown. + +The Passthrough extension is often used in conjunction with the MathJax or KaTeX display engine to render [mathematical expressions] written in the LaTeX markup language. + +[mathematical expressions]: /content-management/mathematics/ + +To enable custom rendering of passthrough elements, create a passthrough render hook. + +## Context + - Passthrough render hook templates receive the following [context](g): ++Passthrough _render hook_ templates receive the following [context](g): + +Attributes +: (`map`) The [Markdown attributes], available if you configure your site as follows: + + {{< code-toggle file=hugo >}} + [markup.goldmark.parser.attribute] + block = true + {{< /code-toggle >}} + + Hugo populates the `Attributes` map for _block_ passthrough elements. Markdown attributes are not applicable to _inline_ elements. + +Inner +: (`string`) The inner content of the passthrough element, excluding the delimiters. + +Ordinal +: (`int`) The zero-based ordinal of the passthrough element on the page. + +Page +: (`page`) A reference to the current page. + +PageInner +: (`page`) A reference to a page nested via the [`RenderShortcodes`] method. [See details](#pageinner-details). + +Position +: (`string`) The position of the passthrough element within the page content. + +Type +: (`string`) The passthrough element type, either `block` or `inline`. + +[Markdown attributes]: /content-management/markdown-attributes/ +[`RenderShortcodes`]: /methods/page/rendershortcodes + +## Example + +Instead of client-side JavaScript rendering of mathematical markup using MathJax or KaTeX, create a passthrough render hook which calls the [`transform.ToMath`] function. + +[`transform.ToMath`]: /functions/transform/tomath/ + +```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 -}} +``` + +Then, in your base template, conditionally include the KaTeX CSS within the head element: + +```go-html-template {file="layouts/baseof.html" copy=true} + + {{ $noop := .WordCount }} + {{ if .Page.Store.Get "hasMath" }} + + {{ end }} + +``` + +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. + +Although you can use one template with conditional logic as shown above, you can also create separate templates for each [`Type`](#type) of passthrough element: + +```text +layouts/ + └── _markup/ + ├── render-passthrough-block.html + └── render-passthrough-inline.html +``` + +{{% include "/_common/render-hooks/pageinner.md" %}} diff --cc docs/content/en/render-hooks/tables.md index 619090797,000000000..852f67e11 mode 100755,000000..100755 --- a/docs/content/en/render-hooks/tables.md +++ b/docs/content/en/render-hooks/tables.md @@@ -1,100 -1,0 +1,100 @@@ +--- +title: Table render hooks +linkTitle: Tables - description: Create a table render hook to override the rendering of Markdown tables to HTML. ++description: Create table render hook templates to override the rendering of Markdown tables to HTML. +categories: [] +keywords: [] +--- + +{{< new-in 0.134.0 />}} + +## Context + - Table render hook templates receive the following [context](g): ++Table _render hook_ templates receive the following [context](g): + +Attributes +: (`map`) The [Markdown attributes], available if you configure your site as follows: + + {{< code-toggle file=hugo >}} + [markup.goldmark.parser.attribute] + block = true + {{< /code-toggle >}} + +Ordinal +: (`int`) The zero-based ordinal of the table on the page. + +Page +: (`page`) A reference to the current page. + +PageInner +: (`page`) A reference to a page nested via the [`RenderShortcodes`] method. [See details](#pageinner-details). + +Position +: (`string`) The position of the table within the page content. + +THead +: (`slice`) A slice of table header rows, where each element is a slice of table cells. + +TBody +: (`slice`) A slice of table body rows, where each element is a slice of table cells. + +[Markdown attributes]: /content-management/markdown-attributes/ +[`RenderShortcodes`]: /methods/page/rendershortcodes + +## Table cells + +Each table cell within the slice of slices returned by the `THead` and `TBody` methods has the following fields: + +Alignment +: (`string`) The alignment of the text within the table cell, one of `left`, `center`, or `right`. + +Text +: (`template.HTML`) The text within the table cell. + +## Example + +In its default configuration, Hugo renders Markdown tables according to the [GitHub Flavored Markdown specification]. To create a render hook that does the same thing: + +[GitHub Flavored Markdown specification]: https://github.github.com/gfm/#tables-extension- + +```go-html-template {file="layouts/_markup/render-table.html" copy=true} + + + {{- range .THead }} + + {{- range . }} + + {{- end }} + + {{- end }} + + + {{- range .TBody }} + + {{- range . }} + + {{- end }} + + {{- end }} + +
+ {{- .Text -}} +
+ {{- .Text -}} +
+``` + +{{% include "/_common/render-hooks/pageinner.md" %}} diff --cc docs/content/en/shortcodes/qr.md index 27d9ae02f,000000000..3cbc5d3fd mode 100755,000000..100755 --- a/docs/content/en/shortcodes/qr.md +++ b/docs/content/en/shortcodes/qr.md @@@ -1,107 -1,0 +1,107 @@@ +--- +title: QR shortcode +linkTitle: QR +description: Insert a QR code into your content using the qr shortcode. +categories: [] +keywords: [] +--- + +{{< new-in 0.141.0 />}} + +> [!note] +> To override Hugo's embedded `qr` shortcode, copy the [source code] to a file with the same name in the `layouts/_shortcodes` directory. + +The `qr` shortcode encodes the given text into a [QR code] using the specified options and renders the resulting image. + +Internally this shortcode calls the `images.QR` function. Please read the [related documentation] for implementation details and guidance. + +## Examples + +Use the self-closing syntax to pass the text as an argument: + +```text +{{}} +``` + +Or insert the text between the opening and closing tags: + +```text +{{}} +https://gohugo.io +{{}} +``` + +Both of the above produce this image: + +{{< qr text="https://gohugo.io" class="qrcode" targetDir="images/qr" />}} + +To create a QR code for a phone number: + +```text +{{}} +``` + +{{< qr text="tel:+12065550101" class="qrcode" targetDir="images/qr" />}} + +To create a QR code containing contact information in the [vCard] format: + +```text +{{}} +BEGIN:VCARD +VERSION:2.1 +N;CHARSET=UTF-8:Smith;John;R.;Dr.;PhD +FN;CHARSET=UTF-8:Dr. John R. Smith, PhD. +ORG;CHARSET=UTF-8:ABC Widgets +TITLE;CHARSET=UTF-8:Vice President Engineering +TEL;TYPE=WORK:+12065550101 +EMAIL;TYPE=WORK:jsmith@example.org +END:VCARD +{{}} +``` + +{{< qr level="low" scale=2 alt="QR code of vCard for John Smith" class="qrcode" targetDir="images/qr" >}} +BEGIN:VCARD +VERSION:2.1 +N;CHARSET=UTF-8:Smith;John;R.;Dr.;PhD +FN;CHARSET=UTF-8:Dr. John R. Smith, PhD. +ORG;CHARSET=UTF-8:ABC Widgets +TITLE;CHARSET=UTF-8:Vice President Engineering +TEL;TYPE=WORK:+12065550101 +EMAIL;TYPE=WORK:jsmith@example.org +END:VCARD +{{< /qr >}} + +## Arguments + +text +: (`string`) The text to encode, falling back to the text between the opening and closing shortcode tags. + +level +: (`string`) The error correction level to use when encoding the text, one of `low`, `medium`, `quartile`, or `high`. Default is `medium`. + +scale +: (`int`) The number of image pixels per QR code module. Must be greater than or equal to 2. Default is `4`. + +targetDir +: (`string`) The subdirectory within the [`publishDir`] where Hugo will place the generated image. + +alt +: (`string`) The `alt` attribute of the `img` element. + +class +: (`string`) The `class` attribute of the `img` element. + +id +: (`string`) The `id` attribute of the `img` element. + +loading +: (`string`) The `loading` attribute of the `img` element, either `eager` or `lazy`. + +title +: (`string`) The `title` attribute of the `img` element. + +[`publishDir`]: /configuration/all/#publishdir +[QR code]: https://en.wikipedia.org/wiki/QR_code +[related documentation]: /functions/images/qr/ +[source code]: {{% eturl qr %}} - [vCard]: https://en.wikipedia.org/wiki/VCard ++[vCard]: diff --cc docs/content/en/shortcodes/ref.md index b38413c63,000000000..0cd5b52dc mode 100755,000000..100755 --- a/docs/content/en/shortcodes/ref.md +++ b/docs/content/en/shortcodes/ref.md @@@ -1,62 -1,0 +1,65 @@@ +--- +title: Ref shortcode +linkTitle: Ref +description: Insert a permalink to the given page reference using the ref shortcode. +categories: [] +keywords: [] +--- + +> [!note] +> To override Hugo's embedded `ref` shortcode, copy the [source code] to a file with the same name in the `layouts/_shortcodes` directory. + +> [!note] - > When working with Markdown, this shortcode is obsolete. Instead, use a [link render hook] that resolves the link destination using the `GetPage` method on the `Page` object. You can either create your own, or simply enable the [embedded link render hook]. The embedded link render hook is automatically enabled for multilingual single-host projects. ++> When working with Markdown this shortcode is obsolete. Instead, to properly resolve Markdown link destinations, use the [embedded link render hook] or create your own. ++> ++> In its default configuration, Hugo automatically uses 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. ++> ++> You can also configure Hugo to `always` use the embedded link render hook, use it only as a `fallback`, or `never` use it. See [details](/configuration/markup/#renderhookslinkuseembedded). + +## Usage + +The `ref` shortcode accepts either a single positional argument (the path) or one or more named arguments, as listed below. + +## Arguments + +{{% include "_common/ref-and-relref-options.md" %}} + +## Examples + +The `ref` shortcode typically provides the destination for a Markdown link. + +> [!note] +> Always use [Markdown notation] notation when calling this shortcode. + +The following examples show the rendered output for a page on the English version of the site: + +```md +[Link A]({{%/* ref "/books/book-1" */%}}) + +[Link B]({{%/* ref path="/books/book-1" */%}}) + +[Link C]({{%/* ref path="/books/book-1" lang="de" */%}}) + +[Link D]({{%/* ref path="/books/book-1" lang="de" outputFormat="json" */%}}) +``` + +Rendered: + +```html +Link A + +Link B + +Link C + +Link D +``` + +## Error handling + +{{% include "_common/ref-and-relref-error-handling.md" %}} + - [content format]: /content-management/formats/ - [embedded link render hook]: /render-hooks/links/#default - [link render hook]: /render-hooks/links/ ++[duplication of shared page resources]: /configuration/markup/#duplicateresourcefiles ++[embedded link render hook]: /render-hooks/links/#embedded +[Markdown notation]: /content-management/shortcodes/#notation +[source code]: {{% eturl relref %}} diff --cc docs/content/en/shortcodes/relref.md index d4f4c2425,000000000..22cdb9f2f mode 100755,000000..100755 --- a/docs/content/en/shortcodes/relref.md +++ b/docs/content/en/shortcodes/relref.md @@@ -1,62 -1,0 +1,65 @@@ +--- +title: Relref shortcode +linkTitle: Relref +description: Insert a relative permalink to the given page reference using the relref shortcode. +categories: [] +keywords: [] +--- + +> [!note] +> To override Hugo's embedded `relref` shortcode, copy the [source code] to a file with the same name in the `layouts/_shortcodes` directory. + +> [!note] - > When working with Markdown, this shortcode is obsolete. Instead, use a [link render hook] that resolves the link destination using the `GetPage` method on the `Page` object. You can either create your own, or simply enable the [embedded link render hook]. The embedded link render hook is automatically enabled for multilingual single-host projects. ++> When working with Markdown this shortcode is obsolete. Instead, to properly resolve Markdown link destinations, use the [embedded link render hook] or create your own. ++> ++> In its default configuration, Hugo automatically uses 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. ++> ++> You can also configure Hugo to `always` use the embedded link render hook, use it only as a `fallback`, or `never` use it. See [details](/configuration/markup/#renderhookslinkuseembedded). + +## Usage + +The `relref` shortcode accepts either a single positional argument (the path) or one or more named arguments, as listed below. + +## Arguments + +{{% include "_common/ref-and-relref-options.md" %}} + +## Examples + +The `relref` shortcode typically provides the destination for a Markdown link. + +> [!note] +> Always use [Markdown notation] notation when calling this shortcode. + +The following examples show the rendered output for a page on the English version of the site: + +```md +[Link A]({{%/* relref "/books/book-1" */%}}) + +[Link B]({{%/* relref path="/books/book-1" */%}}) + +[Link C]({{%/* relref path="/books/book-1" lang="de" */%}}) + +[Link D]({{%/* relref path="/books/book-1" lang="de" outputFormat="json" */%}}) +``` + +Rendered: + +```html +Link A + +Link B + +Link C + +Link D +``` + +## Error handling + +{{% include "_common/ref-and-relref-error-handling.md" %}} + - [content format]: /content-management/formats/ - [embedded link render hook]: /render-hooks/links/#default - [link render hook]: /render-hooks/links/ ++[duplication of shared page resources]: /configuration/markup/#duplicateresourcefiles ++[embedded link render hook]: /render-hooks/links/#embedded +[Markdown notation]: /content-management/shortcodes/#notation +[source code]: {{% eturl relref %}} diff --cc docs/content/en/showcase/_template/index.md index 3103903e1,000000000..6a115961b mode 100644,000000..100644 --- a/docs/content/en/showcase/_template/index.md +++ b/docs/content/en/showcase/_template/index.md @@@ -1,31 -1,0 +1,31 @@@ +--- +title: Myshowcase +date: +draft: true +description: A short description of this page. +# The URL to the site on the internet. +siteURL: https://gohugo.io/ +# Link to the site's Hugo source code if public and you can/want to share. +# Remove or leave blank if not needed/wanted. +siteSource: https://github.com/gohugoio/hugoDocs +# Add credit to the article author. Leave blank or remove if not needed/wanted. +byline: '[bep](https://github.com/bep), Hugo Lead' +--- + +To complete this showcase: + +1. Write the story about your site in this file. +1. Add a summary to the `bio.md` file in this directory. +1. Replace the `featured-template.png` with a screenshot of your site. You can rename it, but it must contain the word `featured`. - 1. Create a new pull request in https://github.com/gohugoio/hugoDocs/pulls ++1. Create a new pull request in + +The content of this bundle explained: + +index.md +: The main content file. Fill in required front matter metadata and write your story. I does not have to be a novel. It can even be self-promotional, but it should include Hugo in some form. + +bio.md +: A short summary of the website. Site credits (who built it) fits nicely here. + +featured.png +: A reasonably sized screenshot of your website. It can be named anything, but the name must start with "featured". The sample image is `1500x750` (2:1 aspect ratio). diff --cc docs/content/en/showcase/ampio-help/bio.md index a08b26be7,000000000..bc0a9a937 mode 100644,000000..100644 --- a/docs/content/en/showcase/ampio-help/bio.md +++ b/docs/content/en/showcase/ampio-help/bio.md @@@ -1,10 -1,0 +1,10 @@@ - __We are Ampio.__ We design and manufacture a building automation system that provides control, comfort, safety and reliability. Visit [our page](http://ampio.com/) to learn more about our solution! ++We are Ampio. We design and manufacture a building automation system that provides control, comfort, safety and reliability. Visit [our page](http://ampio.com/) to learn more about our solution! + - __Ampio Knowledge Base__ is a service built and maintained with Hugo. It is a self-service support platform for our customers and certified installers. It also contains a complete portfolio of our modules---building blocks of the Ampio building automation system. ++Ampio Knowledge Base is a service built and maintained with Hugo. It is a self-service support platform for our customers and certified installers. It also contains a complete portfolio of our modules---building blocks of the Ampio building automation system. + +The site is built by: + +- [@mgetka](https://github.com/mgetka), developer +- [@SteynAnna](https://github.com/SteynAnna), maintainer + +and other members of the Ampio team responsible for content creation. diff --cc docs/content/en/showcase/ampio-help/index.md index 462452cb1,000000000..20e767289 mode 100644,000000..100644 --- a/docs/content/en/showcase/ampio-help/index.md +++ b/docs/content/en/showcase/ampio-help/index.md @@@ -1,76 -1,0 +1,76 @@@ +--- +title: Ampio Knowledge Base +date: 2022-10-30 +description: "Knowledge base for the Ampio building automation system." +siteURL: https://help.ampio.com/ +--- + +As a company that specializes in highly customizable smart solutions for various industries, Ampio has accumulated a vast amount of knowledge throughout the years. We were on the lookout for a user-friendly platform to impart this knowledge to our clients and installers. Delivering a service that caters to both audiences, scattered around the globe with vastly divergent needs and expectations, was a challenge. + +On the one hand, we needed something that would let us educate a client with no technical knowledge about our system in a visually appealing way. + +On the other hand, our installers required technical drawings, offline manuals, and a deep dive into highly specialized subjects. + +Over and above that, we could not overlook the fact that our internal team of editors and maintainers of the Knowledge Base included non-programmers who had to be able to create content and navigate the architecture of the site just as well as those adept at coding. + +We started our journey with the following requirements: + - - Ease of contribution - - Efficient search capabilities - - The possibility of deployment to simple shared hosting - - Proper support for multilingualism ++- Ease of contribution ++- Efficient search capabilities ++- The possibility of deployment to simple shared hosting ++- Proper support for multilingualism + +## Dark ages of WordPress + +With the above-mentioned in mind, we built our first revision of the service in WordPress with a commercial knowledge base plugin. The initial requirements seemed not to be exorbitant, and yet we were surprised to see that only a few of the available solutions covered them. Especially, the case of multilingualism appeared to be particularly neglected across the available products. + +The WordPress-based products made big promises: pay some bucks, bootstrap the service in minutes, and forget about all the development troubles. And although those promises could possibly be deliverable on WordPress' end, it was definitely not true for anything more than the most generic deployments. In our case, we were dealing with more and more trade-offs. Plus, the solution was just slow on the simple shared hosting environment that we dedicated to the job. + +## Turning point + +The turning point was the introduction of a new key requirement---each document was to be downloadable in the PDF format. Such functionality was not available in the plugins we owned, nor did it look like any of the other existing WordPress plugins could fulfill our needs to a satisfactory degree. Nobody in our team was brave enough to add such a functionality to the current stack, so we decided to start from scratch. + +On top of that new development, we had to remember another one of our key requirements, namely, that mostly non-programmers were to be responsible for the service maintenance and content creation. Initially, we were leaning towards headless CMS-based solutions, but finally we made a bold move and decided to create a Git-managed Jamstack service and see what happens. + +## Hugo to the rescue + +Hugo was our first choice of SSG. The multilingualism support was the primary feature that convinced us. Later on, going through the documentation, we continued to discover new exciting features that we didn't even know we needed when we started. + +The rich functionalities of WordPress WYSIWYG editors soon turned out to be a curse. It became burdensome to maintain formatting consistency across documents prepared by multiple contributors. When we considered Markdown, we knew that it would give us a lot less flexibility. In our case, it proved to be a blessing in disguise---the constraints imposed by the notation ensured that each document was prepared in the same way. And in the cases where Markdown was not enough, Hugo shortcodes gave us all that we needed to get the results we anticipated. + +In terms of PDF generation, we utilized [custom output formats](/configuration/output-formats/) to produce intermediary document representations, which are consumed by our custom tool transforming them to TeX documents, which are finally used to produce PDF files. + +Custom output formats were also used to create search indexes. The search functionality is built on the brilliant [TNTSearch](https://github.com/teamtnt/tntsearch) library. The search queries and results are handled by PHP snippets embedded into static documents handled by Hugo. + +We even implemented a simple REST API generated by Hugo! We have yet to find something that cannot be achieved with this stack, while in WordPress-based solutions we were struggling with things as simple as defining custom document ordering in one of the categories list views. + +When talking about Hugo, we cannot forget about the speed. At the beginning we were not considering it a killer feature, but as our document base grew bigger, we appreciated it more and more. Dry-runs are not so common---most of the time we are working on one of the documents with cache already built during one of the previous Hugo runs. In such a scenario, Hugo rebuilds the site in about a second and we consider it a very good result. + +```text + | EN | PL +-------------------+-----+------ + Pages | 483 | 486 + Paginator pages | 56 | 55 + Non-page files | 745 | 749 + Static files | 917 | 917 + Processed images | 487 | 490 + Aliases | 80 | 79 + Sitemaps | 2 | 1 + Cleaned | 0 | 0 + +Total in 1096 ms +``` + +## Adaptation among the contributors + +Very quickly it became apparent that our initial concerns about the adaptation of the workflow among contributors were grossly exaggerated. Markdown is fairly straightforward and did not cause any trouble for the contributors. + +We recommended that our colleagues use Visual Studio Code as a tool for content creation. The project's repository tracks project-scoped configuration of the editor, which includes a set of _tasks_ allowing to run a live server from the GUI level. This is very useful for those who are easily frightened when faced with the mighty terminal. + +The basic skills of the Git workflow were also easily acquired. At the end of the day, builds and deployments are fully managed by [CI/CD](g) processes, so the administration of the service drills down to reviewing and accepting merge requests in the Git frontend. As a side effect, we receive a full and clear history of contributions, which is well appreciated by our quality assurance auditors. + +We could even say that our experiment spread the love for Git among non-programmers in our organization! + +## Summary + +Hugo is the best! Definitely give it a try if you are ever faced with a challenge similar to ours. And do not give it a second thought if your service contributors are not too technically inclined---it might still turn out great! diff --cc docs/content/en/showcase/hartwell-insurance/index.md index 07ee6182c,000000000..1e15510a8 mode 100644,000000..100644 --- a/docs/content/en/showcase/hartwell-insurance/index.md +++ b/docs/content/en/showcase/hartwell-insurance/index.md @@@ -1,63 -1,0 +1,63 @@@ +--- +title: Hartwell Insurance +date: 2018-02-09 +description: 'Showcase: "Hugo + Netlify + PWA makes for a rapid website."' +siteURL: https://www.hartwell-insurance.com/ +byline: "[Trys Mudford](http://www.trysmudford.com), Lead Developer, Tomango" +--- + +We've just launched a shiny new website for [Hartwell Insurance](https://www.hartwell-insurance.com/). I'm really proud of it. It was tackled in a different way to most previous Tomango site builds, using some fancy new tools and some vintage web standards. + - It's a multi-page, single-page (!) website written in Hugo, a static site generator built with performance as a first-class feature. _I've outlined a load of benefits to Hugo & static sites [here](https://why-static.netlify.com/), in case you're interested._ ++It's a multi-page, single-page (!) website written in Hugo, a static site generator built with performance as a first-class feature. I've outlined a load of benefits to Hugo and static sites [on a page explaining the benefits of static sites](https://why-static.netlify.com/), in case you're interested. + +> **In essence, a static site generator pre-renders the whole site into HTML files and serves them like it's 1995.** + +There's no Apache or Node backend that does compilation at runtime, it's all done at the build step. This means the server; Netlify in this case, only has to do one thing: serve files. Unsurprisingly, serving simple files is VERY quick. + +The starter point was the [Victor Hugo](https://github.com/netlify/victor-hugo) repository that Netlify have created. It let me dive in with Hugo, PostCSS, Browsersync and ES6 without setting up any tooling myself---always a win! + +I then took all the content from the design file and moved it into Markdown, putting shortcodes in where necessary. This site did need a number of custom shortcodes for the presentational elements like the expanding circles and full width backgrounds. But mostly it was just clean, semantic HTML with some CSS and JS enhancement thrown in. + +For example, this two column layout shown below. I used CSS Columns with a `break-after: always;` on the `

`. No multi-wrapper or difficult-to-clear shortcodes, just clean HTML. + +![The multi-column setup on Hartwell Insurance](hartwell-columns.png) + +For the ripple effects on the section headings, I used JS to prepend a `` element then animated it with `RequestAnimationFrame`. It adds a nice bit of movement on the page. + +On the Hartwell Profitmaker section, I toyed with the idea of using Vue.js for the calculator, but after giving it some thought, I decided to code in Vanilla. The result, all of the site JS comes in at 3.2KB! + +The plan was to host with Netlify and therefore get access to Netlify Forms. It meant spending 0 minutes on getting a backend set up so I could focus fully on the frontend. + +Cache invalidation isn't normally something I spend all that much time thinking about when building a site. But as this site was going to be a Progressive Web App, invalidating files would be important to ensure the site didn't appear broken when we made changes. As I was using Victor-Hugo, I wasn't really sure how to best tackle this and sadly spent far too many hours wrangling with Webpack and Gulp files to try and get hashed file names working nicely. + +Then; while I was waiting for a haircut, I read a [Netlify blog post](https://www.netlify.com/blog/2017/02/23/better-living-through-caching/) on how they do cache invalidation with HTTP2 and it promptly blew my mind. + +When you request an asset, they send an ETag in the headers which is a hash of the file. There's also a header to tell the browser not to trust it's own cache (which sounds a little bit bonkers). + +So when you request the page, it opens a persistent HTTP2 connection up (so no new connections for file requests). When it gets to requesting that asset, the browser sends the ETag back to Netlify and they either return nothing if the ETag matches, or the new file with the new ETag. No `app.klfjlkdsfjdslkfjdslkfdsj.js` or `app.js?v=20180112`. Just a clean `app.js` with instant cache invalidation. Amazing. + +Finally, the [Service Worker](https://www.hartwell-insurance.com/sw.js) could be added. This turned out to be straightforward as the Netlify cache invalidation system solved most of the pain points. I went for a network-first, cache-fallback setup for both assets and HTML. This does mean flaky speeds are reliant on the page connection time, but given we're on HTTP2, I'm hoping the persistent connection and tiny ETag size will keep it quick. For online connections, every request is up to date and instantly live after any update. Offline connections fall back to every assets' last cached state. It seems to work really nicely, and there's no need for an update prompt if assets have changed. + +--- + +## The results + +The WebPageTest results are looking good. The speed index is 456, 10x smaller than the average Alexa top 300,000 score. + +![WebPageTest results](hartwell-webpagetest.png) + +[TestMySite.io](https://testmysite.io/5a7e1bb2df99531a23c9ad2f/hartwell-insurance.com) is return ~2ms time to first byte from the CDN edge nodes. Lighthouse audits are also very promising. There's still some improvement to be gained lazy-loading the images and inlining the CSS. I'm less excited about the [second suggestion](http://www.trysmudford.com/css-in-2017/), but I'll certainly look at some lazy-loading, especially as I'm already using `IntersectionObserver` for some animations. + +![Lighthouse results](hartwell-lighthouse.png) + +The most encouraging result is how quick the site is around the world. Most Tomango clients (and their customers) are pretty local and almost exclusively UK-based. We have a dedicated server in Surrey that serves our market pretty well. It did take me by surprise just how much slower a connection from the USA, Australia and Japan to our server was. They're waiting ~500ms just for the first byte, let alone downloading each asset. + +[Hartwell Insurance](https://www.hartwell-insurance.com/) are a US company so by putting them on our server, we'd be instantly hampering their local response times by literally seconds. This was one of the main reasons for going with Netlify. They provide global CDN hosting that's quick from anywhere in the world. + +--- + +This project was such a blast to develop, it's a real pleasure to put new technologies to good use in production, and to see real performance and usability benefits from them. Even using classic web methods of serving directories with files is fun when you've been using dynamic systems for a while---there's something really pure about it. + +--- + +_This was originally posted on [my website](http://www.trysmudford.com/perfomance-wins-with-hugo-and-netlify/)_ diff --cc docs/content/en/showcase/pharmaseal/index.md index 3a8da2377,000000000..fa8c8a8ab mode 100644,000000..100644 --- a/docs/content/en/showcase/pharmaseal/index.md +++ b/docs/content/en/showcase/pharmaseal/index.md @@@ -1,25 -1,0 +1,25 @@@ +--- +title: PHARMASEAL +date: 2019-04-29 +description: "Pharmaseal website developed using Hugo, Forestry, hosted and deployed by Netlify." +siteURL: https://pharmaseal.co/ +byline: "[Roboto Studio](https://roboto.studio), Jonathan Alford" +--- + +We wanted to shake the status quo with PHARMASEAL, opting for a fast and scalable website built with Hugo instead of slower monolithic systems the competitors were using. + +We had two goals: + - **Make it fast** ++## Make it fast + +We wanted to optimize the site as much as possible, so we opted for using Cloudinary, enabling us to take advantage of on-the-fly image manipulation, and thanks to the sheer speed of static sites, we achieved a perfect optimization score with Google audits. + +Because we're hosting the site through Netlify and our target audience is in America, we are taking advantage of Netlify edge (Their alternative to a CDN). We're talking blazing fast. + - **Make it easy** ++## Make it easy + +We're big fans of simplicity, and that's what we delivered with the Forestry building blocks. Every element on the site is built with building blocks in mind, allowing PHARMASEAL to generate multiple pages in the blink of an eye. + +PHARMASEAL have found Forestry CMS combined with HUGO to be so effective at producing fast, purpose driven pages, that we have worked with them to add even more blocks in a scalable, modular fashion. + +**TLDR:** We're blown away with HUGO, the sheer speed, scalability and deployment possibilities with Netlify is the 💣 diff --cc docs/content/en/templates/introduction.md index 7ee4f6cdf,000000000..9d94032c9 mode 100644,000000..100644 --- a/docs/content/en/templates/introduction.md +++ b/docs/content/en/templates/introduction.md @@@ -1,537 -1,0 +1,531 @@@ +--- +title: Introduction to templating +linkTitle: Introduction +description: An introduction to Hugo's templating syntax. +categories: [] +keywords: [] +weight: 10 +--- + +{{< newtemplatesystem >}} + - +{{% glossary-term template %}} + +Templates use [variables], [functions], and [methods] to transform your content, resources, and data into a published page. + +> [!note] +> Hugo uses Go's [text/template] and [html/template] packages. +> +> The text/template package implements data-driven templates for generating textual output, while the html/template package implements data-driven templates for generating HTML output safe against code injection. +> +> By default, Hugo uses the html/template package when rendering HTML files. + +For example, this HTML template initializes the `$v1` and `$v2` variables, then displays them and their product within an HTML paragraph. + +```go-html-template +{{ $v1 := 6 }} +{{ $v2 := 7 }} +

The product of {{ $v1 }} and {{ $v2 }} is {{ mul $v1 $v2 }}.

+``` + +While HTML templates are the most common, you can create templates for any [output format](g) including CSV, JSON, RSS, and plain text. + +## Context + +The most important concept to understand before creating a template is _context_, the data passed into each template. The data may be a simple value, or more commonly [objects](g) and associated [methods](g). + - For example, a template for a single page receives a `Page` object, and the `Page` object provides methods to return values or perform actions. ++For example, a _page_ template receives a `Page` object, and the `Page` object provides methods to return values or perform actions. + +### Current context + +Within a template, the dot (`.`) represents the current context. + +```go-html-template {file="layouts/page.html"} +

{{ .Title }}

+``` + +In the example above the dot represents the `Page` object, and we call its [`Title`] method to return the title as defined in [front matter]. + +The current context may change within a template. For example, at the top of a template the context might be a `Page` object, but we rebind the context to another value or object within [`range`] or [`with`] blocks. + +```go-html-template {file="layouts/page.html"} +

{{ .Title }}

+ +{{ range slice "foo" "bar" }} +

{{ . }}

+{{ end }} + +{{ with "baz" }} +

{{ . }}

+{{ end }} +``` + +In the example above, the context changes as we `range` through the [slice](g) of values. In the first iteration the context is "foo", and in the second iteration the context is "bar". Inside of the `with` block the context is "baz". Hugo renders the above to: + +```html +

My Page Title

+

foo

+

bar

+

baz

+``` + +### Template context + +Within a `range` or `with` block you can access the context passed into the template by prepending a dollar sign (`$`) to the dot: + +```go-html-template {file="layouts/page.html"} +{{ with "foo" }} +

{{ $.Title }} - {{ . }}

+{{ end }} +``` + +Hugo renders this to: + +```html +

My Page Title - foo

+``` + +> [!note] +> Make sure that you thoroughly understand the concept of _context_ before you continue reading. The most common templating errors made by new users relate to context. + +## Actions + +In the examples above the paired opening and closing braces represent the beginning and end of a template action, a data evaluation or control structure within a template. + +A template action may contain literal values ([boolean](g), [string](g), [integer](g), and [float](g)), variables, functions, and methods. + +```go-html-template {file="layouts/page.html"} +{{ $convertToLower := true }} +{{ if $convertToLower }} +

{{ strings.ToLower .Title }}

+{{ end }} +``` + +In the example above: + +- `$convertToLower` is a variable +- `true` is a literal boolean value +- `strings.ToLower` is a function that converts all characters to lowercase +- `Title` is a method on a the `Page` object + +Hugo renders the above to: + +```html + + +

my page title

+ +``` + +### Whitespace + +Notice the blank lines and indentation in the previous example? Although irrelevant in production when you typically minify the output, you can remove the adjacent whitespace by using template action delimiters with hyphens: + +```go-html-template {file="layouts/page.html"} +{{- $convertToLower := true -}} +{{- if $convertToLower -}} +

{{ strings.ToLower .Title }}

+{{- end -}} +``` + +Hugo renders this to: + +```html +

my page title

+``` + +Whitespace includes spaces, horizontal tabs, carriage returns, and newlines. + +### Pipes + +Within a template action you may [pipe](g) a value to a function or method. The piped value becomes the final argument to the function or method. For example, these are equivalent: + +```go-html-template +{{ strings.ToLower "Hugo" }} → hugo +{{ "Hugo" | strings.ToLower }} → hugo +``` + +You can pipe the result of one function or method into another. For example, these are equivalent: + +```go-html-template +{{ strings.TrimSuffix "o" (strings.ToLower "Hugo") }} → hug +{{ "Hugo" | strings.ToLower | strings.TrimSuffix "o" }} → hug +``` + +These are also equivalent: + +```go-html-template +{{ mul 6 (add 2 5) }} → 42 +{{ 5 | add 2 | mul 6 }} → 42 +``` + +> [!note] +> Remember that the piped value becomes the final argument to the function or method to which you are piping. + +### Line splitting + +You can split a template action over two or more lines. For example, these are equivalent: + +```go-html-template +{{ $v := or $arg1 $arg2 }} + +{{ $v := or + $arg1 + $arg2 +}} +``` + +You can also split [raw string literals](g) over two or more lines. For example, these are equivalent: + +```go-html-template +{{ $msg := "This is line one.\nThis is line two." }} + +{{ $msg := `This is line one. +This is line two.` +}} +``` + +## Variables + +A variable is a user-defined [identifier](g) prepended with a dollar sign (`$`), representing a value of any data type, initialized or assigned within a template action. For example, `$foo` and `$bar` are variables. + +Variables may contain [scalars](g), [slices](g), [maps](g), or [objects](g). + +Use `:=` to initialize a variable, and use `=` to assign a value to a variable that has been previously initialized. For example: + +```go-html-template +{{ $total := 3 }} +{{ range slice 7 11 21 }} + {{ $total = add $total . }} +{{ end }} +{{ $total }} → 42 +``` + +Variables initialized inside of an `if`, `range`, or `with` block are scoped to the block. Variables initialized outside of these blocks are scoped to the template. + +With variables that represent a slice or map, use the [`index`] function to return the desired value. + +```go-html-template +{{ $slice := slice "foo" "bar" "baz" }} +{{ index $slice 2 }} → baz + +{{ $map := dict "a" "foo" "b" "bar" "c" "baz" }} +{{ index $map "c" }} → baz +``` + +> [!note] +> Slices and arrays are zero-based; element 0 is the first element. + +With variables that represent a map or object, [chain](g) identifiers to return the desired value or to access the desired method. + +```go-html-template +{{ $map := dict "a" "foo" "b" "bar" "c" "baz" }} +{{ $map.c }} → baz + +{{ $homePage := .Site.Home }} +{{ $homePage.Title }} → My Homepage +``` + +> [!note] +> As seen above, object and method names are capitalized. Although not required, to avoid confusion we recommend beginning variable and map key names with a lowercase letter or underscore. + +## Functions + +Used within a template action, a function takes one or more arguments and returns a value. Unlike methods, functions are not associated with an object. + +Go's text/template and html/template packages provide a small set of functions, operators, and statements for general use. See the [go-templates] section of the function documentation for details. + +Hugo provides hundreds of custom [functions] categorized by namespace. For example, the `strings` namespace includes these and other functions: + +Function|Alias +:--|:-- +[`strings.ToLower`](/functions/strings/tolower)|`lower` +[`strings.ToUpper`](/functions/strings/toupper)|`upper` +[`strings.Replace`](/functions/strings/replace)|`replace` + +As shown above, frequently used functions have an alias. Use aliases in your templates to reduce code length. + +When calling a function, separate the arguments from the function, and from each other, with a space. For example: + +```go-html-template +{{ $total := add 1 2 3 4 }} +``` + +## Methods + +Used within a template action and associated with an object, a method takes zero or more arguments and either returns a value or performs an action. + +The most commonly accessed objects are the [`Page`] and [`Site`] objects. This is a small sampling of the [methods] available to each object. + +Object|Method|Description +:--|:--|:-- +`Page`|[`Date`](methods/page/date/)|Returns the date of the given page. +`Page`|[`Params`](methods/page/params/)|Returns a map of custom parameters as defined in the front matter of the given page. +`Page`|[`Title`](methods/page/title/)|Returns the title of the given page. +`Site`|[`Data`](methods/site/data/)|Returns a data structure composed from the files in the `data` directory. +`Site`|[`Params`](methods/site/params/)|Returns a map of custom parameters as defined in the site configuration. +`Site`|[`Title`](methods/site/title/)|Returns the title as defined in the site configuration. + +Chain the method to its object with a dot (`.`) as shown below, remembering that the leading dot represents the [current context]. + +```go-html-template {file="layouts/page.html"} +{{ .Site.Title }} → My Site Title +{{ .Page.Title }} → My Page Title +``` + +The context passed into most templates is a `Page` object, so this is equivalent to the previous example: + +```go-html-template {file="layouts/page.html"} +{{ .Site.Title }} → My Site Title +{{ .Title }} → My Page Title +``` + +Some methods take an argument. Separate the argument from the method with a space. For example: + +```go-html-template {file="layouts/page.html"} +{{ $page := .Page.GetPage "/books/les-miserables" }} +{{ $page.Title }} → Les Misérables +``` + +## Comments + +> [!note] +> Do not attempt to use HTML comment delimiters to comment out template code. +> +> Hugo strips HTML comments when rendering a page, but first evaluates any template code within the HTML comment delimiters. Depending on the template code within the HTML comment delimiters, this could cause unexpected results or fail the build. + +Template comments are similar to template actions. Paired opening and closing braces represent the beginning and end of a comment. For example: + +```text +{{/* This is an inline comment. */}} +{{- /* This is an inline comment with adjacent whitespace removed. */ -}} +``` + +Code within a comment is not parsed, executed, or displayed. Comments may be inline, as shown above, or in block form: + +```text +{{/* +This is a block comment. +*/}} + +{{- /* +This is a block comment with +adjacent whitespace removed. +*/ -}} +``` + +You may not nest one comment inside of another. + +To render an HTML comment, pass a string through the [`safeHTML`] template function. For example: + +```go-html-template +{{ "" | safeHTML }} +{{ printf "" .Site.Title | safeHTML }} +``` + +## Include + +Use the [`template`] function to include one or more of Hugo's [embedded templates]: + +```go-html-template +{{ partial "google_analytics.html" . }} +{{ partial "opengraph" . }} +{{ partial "pagination.html" . }} +{{ partial "schema.html" . }} +{{ partial "twitter_cards.html" . }} +``` + +Use the [`partial`] or [`partialCached`] function to include one or more [partial templates]: + +```go-html-template +{{ partial "breadcrumbs.html" . }} +{{ partialCached "css.html" . }} +``` + - Create your partial templates in the layouts/_partials directory. ++Create your _partial_ templates in the `layouts/_partials` directory. + +> [!note] +> In the examples above, note that we are passing the current context (the dot) to each of the templates. + +## Examples + +This limited set of contrived examples demonstrates some of concepts described above. Please see the [functions], [methods], and [templates] documentation for specific examples. + +### Conditional blocks + +See documentation for [`if`], [`else`], and [`end`]. + +```go-html-template +{{ $var := 42 }} +{{ if eq $var 6 }} + {{ print "var is 6" }} +{{ else if eq $var 7 }} + {{ print "var is 7" }} +{{ else if eq $var 42 }} + {{ print "var is 42" }} +{{ else }} + {{ print "var is something else" }} +{{ end }} +``` + +### Logical operators + +See documentation for [`and`] and [`or`]. + +```go-html-template +{{ $v1 := true }} +{{ $v2 := false }} +{{ $v3 := false }} +{{ $result := false }} + +{{ if and $v1 $v2 $v3 }} + {{ $result = true }} +{{ end }} +{{ $result }} → false + +{{ if or $v1 $v2 $v3 }} + {{ $result = true }} +{{ end }} +{{ $result }} → true +``` + +### Loops + +See documentation for [`range`], [`else`], and [`end`]. + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} +

{{ . }}

+{{ else }} +

The collection is empty

+{{ end }} +``` + +To loop a specified number of times: + +```go-html-template +{{ $s := slice }} +{{ range 3 }} + {{ $s = $s | append . }} +{{ end }} +{{ $s }} → [0 1 2] +``` + +### Rebind context + +See documentation for [`with`], [`else`], and [`end`]. + +```go-html-template +{{ $var := "foo" }} +{{ with $var }} + {{ . }} → foo +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +To test multiple conditions: + +```go-html-template +{{ $v1 := 0 }} +{{ $v2 := 42 }} +{{ with $v1 }} + {{ . }} +{{ else with $v2 }} + {{ . }} → 42 +{{ else }} + {{ print "v1 and v2 are falsy" }} +{{ end }} +``` + +### Access site parameters + +See documentation for the [`Params`](/methods/site/params/) method on a `Site` object. + +With this site configuration: + +{{< code-toggle file=hugo >}} +title = 'ABC Widgets' +baseURL = 'https://example.org' +[params] + subtitle = 'The Best Widgets on Earth' + copyright-year = '2023' + [params.author] + email = 'jsmith@example.org' + name = 'John Smith' + [params.layouts] + rfc_1123 = 'Mon, 02 Jan 2006 15:04:05 MST' + rfc_3339 = '2006-01-02T15:04:05-07:00' +{{< /code-toggle >}} + +Access the custom site parameters by chaining the identifiers: + +```go-html-template +{{ .Site.Params.subtitle }} → The Best Widgets on Earth +{{ .Site.Params.author.name }} → John Smith + +{{ $layout := .Site.Params.layouts.rfc_1123 }} +{{ .Site.Lastmod.Format $layout }} → Tue, 17 Oct 2023 13:21:02 PDT +``` + +### Access page parameters + +See documentation for the [`Params`](/methods/page/params/) method on a `Page` object. + +By way of example, consider this front matter: + +{{< code-toggle file=content/annual-conference.md fm=true >}} +title = 'Annual conference' +date = 2023-10-17T15:11:37-07:00 +[params] +display_related = true +key-with-hyphens = 'must use index function' +[params.author] + email = 'jsmith@example.org' + name = 'John Smith' +{{< /code-toggle >}} + +The `title` and `date` fields are standard [front matter fields], while the other fields are user-defined. + +Access the custom fields by [chaining](g) the [identifiers](g) when needed: + +```go-html-template +{{ .Params.display_related }} → true +{{ .Params.author.email }} → jsmith@example.org +{{ .Params.author.name }} → John Smith +``` + +In the template example above, each of the keys is a valid identifier. For example, none of the keys contains a hyphen. To access a key that is not a valid identifier, use the [`index`] function: + +```go-html-template +{{ index .Params "key-with-hyphens" }} → must use index function +``` + +[`and`]: /functions/go-template/and +[`else`]: /functions/go-template/else/ +[`end`]: /functions/go-template/end/ +[`if`]: /functions/go-template/if/ +[`index`]: /functions/collections/indexfunction/ - [`index`]: /functions/collections/indexfunction/ +[`or`]: /functions/go-template/or +[`Page`]: /methods/page/ +[`partial`]: /functions/partials/include/ +[`partialCached`]: /functions/partials/includecached/ +[`range`]: /functions/go-template/range/ - [`range`]: /functions/go-template/range/ +[`safeHTML`]: /functions/safe/html +[`Site`]: /methods/site/ +[`template`]: /functions/go-template/template/ +[`Title`]: /methods/page/title +[`with`]: /functions/go-template/with/ - [`with`]: /functions/go-template/with/ +[current context]: #current-context +[embedded templates]: /templates/embedded/ +[front matter]: /content-management/front-matter/ +[front matter fields]: /content-management/front-matter/#fields +[functions]: /functions/ - [functions]: /functions +[go-templates]: /functions/go-template/ +[html/template]: https://pkg.go.dev/html/template +[methods]: /methods/ - [methods]: /methods/ +[partial templates]: /templates/types/#partial +[templates]: /templates/ +[text/template]: https://pkg.go.dev/text/template +[variables]: #variables diff --cc docs/content/en/templates/menu.md index e1eaa07b9,000000000..aa0e7c673 mode 100644,000000..100644 --- a/docs/content/en/templates/menu.md +++ b/docs/content/en/templates/menu.md @@@ -1,127 -1,0 +1,127 @@@ +--- +title: Menu templates +description: Create templates to render one or more menus. +categories: [] +keywords: [] +weight: 150 +aliases: [/templates/menus/,/templates/menu-templates/] +--- + +## Overview + +After [defining menu entries], use [menu methods] to render a menu. + +Three factors determine how to render a menu: + +1. The method used to define the menu entries: [automatic], [in front matter], or [in site configuration] +1. The menu structure: flat or nested +1. The method used to [localize the menu entries]: site configuration or translation tables + +The example below handles every combination. + +## Example + - This partial template recursively "walks" a menu structure, rendering a localized, accessible nested list. ++This _partial_ template recursively "walks" a menu structure, rendering a localized, accessible nested list. + +```go-html-template {file="layouts/_partials/menu.html" copy=true} +{{- $page := .page }} +{{- $menuID := .menuID }} + +{{- with index site.Menus $menuID }} + +{{- end }} + +{{- define "_partials/inline/menu/walk.html" }} + {{- $page := .page }} + {{- range .menuEntries }} + {{- $attrs := dict "href" .URL }} + {{- if $page.IsMenuCurrent .Menu . }} + {{- $attrs = merge $attrs (dict "class" "active" "aria-current" "page") }} + {{- else if $page.HasMenuCurrent .Menu .}} + {{- $attrs = merge $attrs (dict "class" "ancestor" "aria-current" "true") }} + {{- end }} + {{- $name := .Name }} + {{- with .Identifier }} + {{- with T . }} + {{- $name = . }} + {{- end }} + {{- end }} +
  • + {{ $name }} + {{- with .Children }} +
      + {{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }} +
    + {{- end }} +
  • + {{- end }} +{{- end }} +``` + +Call the partial above, passing a menu ID and the current page in context. + +```go-html-template {file="layouts/page.html"} +{{ partial "menu.html" (dict "menuID" "main" "page" .) }} +{{ partial "menu.html" (dict "menuID" "footer" "page" .) }} +``` + +## Page references + +Regardless of how you [define menu entries], an entry associated with a page has access to page context. + +This simplistic example renders a page parameter named `version` next to each entry's `name`. Code defensively using `with` or `if` to handle entries where (a) the entry points to an external resource, or (b) the `version` parameter is not defined. + +```go-html-template {file="layouts/page.html"} +{{- range site.Menus.main }} + + {{ .Name }} + {{- with .Page }} + {{- with .Params.version -}} + ({{ . }}) + {{- end }} + {{- end }} + +{{- end }} +``` + +## Menu entry parameters + +When you define menu entries [in site configuration] or [in front matter], you can include a `params` key as shown in these examples: + +- [Menu entry defined in site configuration] +- [Menu entry defined in front matter] + +This simplistic example renders a `class` attribute for each anchor element. Code defensively using `with` or `if` to handle entries where `params.class` is not defined. + +```go-html-template {file="layouts/_partials/menu.html"} +{{- range site.Menus.main }} + + {{ .Name }} + +{{- end }} +``` + +## Localize + +Hugo provides two methods to localize your menu entries. See [multilingual]. + +[automatic]: /content-management/menus/#define-automatically +[define menu entries]: /content-management/menus/ +[defining menu entries]: /content-management/menus/ +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/#define-in-site-configuration +[localize the menu entries]: /content-management/multilingual/#menus +[menu entry defined in front matter]: /content-management/menus/#example +[menu entry defined in site configuration]: /configuration/menus +[menu methods]: /methods/menu/ +[multilingual]: /content-management/multilingual/#menus diff --cc docs/content/en/templates/new-templatesystem-overview.md index 93be94bcc,000000000..a3b53197b mode 100644,000000..100644 --- a/docs/content/en/templates/new-templatesystem-overview.md +++ b/docs/content/en/templates/new-templatesystem-overview.md @@@ -1,99 -1,0 +1,99 @@@ - +--- +title: New template system in Hugo v0.146.0 +linktitle: New template system +description: Overview of the new template system in Hugo v0.146.0. +categories: [] +keywords: [] +weight: 1 +--- + +In [Hugo v0.146.0], we performed a full re-implementation of how Go templates are handled in Hugo. This includes structural changes to the `layouts` folder and a new, more powerful template lookup system. + +We have aimed to maintain as much backward compatibility as possible by mapping "old to new," but some reported breakages have occurred. We're working on a full overhaul of the documentation on this topic – until then, this is a one-pager with the most important changes. + +## Changes to the `layouts` folder + +| Description | Action required | +| ------------- | ------------- | +| The `_default` folder is removed. | Move all files in `layouts/_default` up to the `layouts/` root.| +| The `layouts/partials` folder is renamed to `layouts/_partials`. | Rename the folder. | +| The `layouts/shortcodes` folder is renamed to `layouts/_shortcodes`. | Rename the folder. | +| Any folder in `layouts` that does not start with `_` represents the root of a [Page path]. In [Hugo v0.146.0], this can be nested as deeply as needed, and `_shortcodes` and `_markup` folders can be placed at any level in the tree.| No action required.| +| The above also means that there's no top-level `layouts/taxonomy` or `layouts/section` folders anymore, unless it represents a [Page path].|Move them up to `layouts/` with one of the [Page kinds] `section`, `taxonomy` or `term` as the base name, or place the layouts into the taxonomy [Page path]. | +|A template named `taxonomy.html` used to be a candidate for both Page kind `term` and `taxonomy`, now it's only considered for `taxonomy`.|Create both `taxonomy.html` and `term.html` or create a more general layout, e.g. `list.html`.| +| For base templates (e.g., `baseof.html`), in previous Hugo versions, you could prepend one identifier (layout, type, or kind) with a hyphen in front of the baseof keyword.|Move that identifier after the first "dot," e.g., rename`list-baseof.html` to `baseof.list.html`.| +| We have added a new `all` "catch-all" layout. This means that if you have, e.g., `layouts/all.html` and that is the only template, that layout will be used for all HTML page rendering.|| +| We have removed the concept of `_internal` Hugo templates.[^internal]|Replace constructs similar to `{{ template "_internal/opengraph.html" . }}` with `{{ partial "opengraph.html" . }}`.| +| The identifiers that can be used in a template filename are one of the [Page kinds] (`home`, `page`, `section`, `taxonomy`, or `term`), one of the standard layouts (`list`, `single`, or `all`), a custom layout (as defined in the `layout` front matter field), a language (e.g., `en`), an output format (e.g., `html`, `rss`), and a suffix representing the media type. E.g., `all.en.html` and `home.rss.xml`.|| +| The above means that there's no such thing as an `index.html` template for the home page anymore. | Rename `index.html` to `home.html`.| + +Also, see the [Example folder structure] below for a more concrete example of the new layout system. + +## Changes to template lookup order + - We have consolidated the template lookup so it works the same across all shortcodes, render hooks, partials, and page templates. The previous setup was very hard to understand and had a massive number of variants. The new setup aims to feel natural with few surprises. ++We have consolidated the template lookup so it works the same across all [template types]. The previous setup was very hard to understand and had a massive number of variants. The new setup aims to feel natural with few surprises. + +The identifiers used in the template weighting, in order of importance, are: + +| Identifier | Description | +| ---------- | ----------- | +| Layout custom | The custom `layout` set in front matter. | +| [Page kinds] | One of `home`, `section`, `taxonomy`, `term`, `page`. | +| Layouts standard 1 | `list` or `single`. | +| Output format | The output format (e.g., `html`, `rss`). | +| Layouts standard 2 | `all`. | +| Language | The language (e.g., `en`). | +| Media type | The media type (e.g., `text/html`). | +| [Page path] | The page path (e.g., `/blog/mypost`). | +| Type | `type` set in front matter.[^type]| + +For templates placed in a `layouts` folder partly or completely matching a [Page path], a closer match upwards will be considered _better_. In the [Example folder structure] below, this means that: + - * `layouts/docs/api/_markup/render-link.html` will be used to render links from the Page path `/docs/api` and below. - * `layouts/docs/baseof.html` will be used as the base template for the Page path `/docs` and below. - * `layouts/tags/term.html` will be used for all `term` rendering in the `tags` taxonomy, except for the `blue` term, which will use `layouts/tags/blue/list.html`. ++- `layouts/docs/api/_markup/render-link.html` will be used to render links from the Page path `/docs/api` and below. ++- `layouts/docs/baseof.html` will be used as the base template for the Page path `/docs` and below. ++- `layouts/tags/term.html` will be used for all `term` rendering in the `tags` taxonomy, except for the `blue` term, which will use `layouts/tags/blue/list.html`. + +## Example folder structure + +```text +layouts +├── baseof.html +├── baseof.term.html +├── home.html +├── page.html +├── section.html +├── taxonomy.html +├── term.html +├── term.mylayout.en.rss.xml +├── _markup +│ ├── render-codeblock-go.term.mylayout.no.rss.xml +│ └── render-link.html +├── _partials +│ └── mypartial.html +├── _shortcodes +│ ├── myshortcode.html +│ └── myshortcode.section.mylayout.en.rss.xml +├── docs +│ ├── baseof.html +│ ├── _shortcodes +│ │ └── myshortcode.html +│ └── api +│ ├── mylayout.html +│ ├── page.html +│ └── _markup +│ └── render-link.html +└── tags + ├── taxonomy.html + ├── term.html + └── blue + └── list.html +``` + - [Hugo v0.146.0]: https://github.com/gohugoio/hugo/releases/tag/v0.146.0 - [Page path]: https://gohugo.io/methods/page/path/ - [Page kinds]: https://gohugo.io/methods/page/kind/ - [Example folder structure]: #example-folder-structure - +[^type]: The `type` set in front matter will effectively replace the `section` folder in [Page path] when doing lookups. +[^internal]: The old way of doing it made it very hard/impossible to, e.g., override `_internal/disqus.html` in a theme. Now you can just create a partial with the same name. ++ ++[Example folder structure]: #example-folder-structure ++[Hugo v0.146.0]: https://github.com/gohugoio/hugo/releases/tag/v0.146.0 ++[Page kinds]: https://gohugo.io/methods/page/kind/ ++[Page path]: https://gohugo.io/methods/page/path/ ++[template types]: /templates/types/ diff --cc docs/content/en/templates/pagination.md index 76b9d1fdc,000000000..6d4203949 mode 100644,000000..100644 --- a/docs/content/en/templates/pagination.md +++ b/docs/content/en/templates/pagination.md @@@ -1,241 -1,0 +1,240 @@@ +--- +title: Pagination +description: Split a list page into two or more subsets. +categories: [] +keywords: [] +weight: 160 +aliases: [/extras/pagination,/doc/pagination/] +--- + +Displaying a large page collection on a list page is not user-friendly: + +- A massive list can be intimidating and difficult to navigate. Users may get lost in the sheer volume of information. +- Large pages take longer to load, which can frustrate users and lead to them abandoning the site. +- Without any filtering or organization, finding a specific item becomes a tedious scrolling exercise. + +Improve usability by paginating `home`, `section`, `taxonomy`, and `term` pages. + +> [!note] +> The most common templating mistake related to pagination is invoking pagination more than once for a given list page. See the [caching](#caching) section below. + +## Terminology + +paginate +: To split a [list page](g) into two or more subsets. + +pagination +: The process of paginating a list page. + +pager +: Created during pagination, a pager contains a subset of a list page and navigation links to other pagers. + +paginator +: A collection of pagers. + +## Configuration + +See [configure pagination](/configuration/pagination). + +## Methods + +To paginate a `home`, `section`, `taxonomy`, or `term` page, invoke either of these methods on the `Page` object in the corresponding template: + +- [`Paginate`] +- [`Paginator`] + +The `Paginate` method is more flexible, allowing you to: + +- Paginate any page collection +- Filter, sort, and group the page collection +- Override the number of pages per pager as defined in your site configuration + +By comparison, the `Paginator` method paginates the page collection passed into the template, and you cannot override the number of pages per pager. + +## Examples + +To paginate a list page using the `Paginate` method: + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages.ByTitle 7 }} + +{{ range $paginator.Pages }} +

    {{ .LinkTitle }}

    +{{ end }} + +{{ partial "pagination.html" . }} +``` + +In the example above, we: + +1. Build a page collection +1. Sort the page collection by title +1. Paginate the page collection, with 7 pages per pager +1. Range over the paginated page collection, rendering a link to each page +1. Call the embedded pagination template to create navigation links between pagers + +To paginate a list page using the `Paginator` method: + +```go-html-template +{{ range .Paginator.Pages }} +

    {{ .LinkTitle }}

    +{{ end }} + +{{ partial "pagination.html" . }} +``` + +In the example above, we: + +1. Paginate the page collection passed into the template, with the default number of pages per pager +1. Range over the paginated page collection, rendering a link to each page +1. Call the embedded pagination template to create navigation links between pagers + +## Caching + +> [!note] +> The most common templating mistake related to pagination is invoking pagination more than once for a given list page. + +Regardless of pagination method, the initial invocation is cached and cannot be changed. If you invoke pagination more than once for a given list page, subsequent invocations use the cached result. This means that subsequent invocations will not behave as written. + +When paginating conditionally, do not use the `compare.Conditional` function due to its eager evaluation of arguments. Use an `if-else` construct instead. + +## Grouping + +Use pagination with any of the [grouping methods]. For example: + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate ($pages.GroupByDate "Jan 2006") }} + +{{ range $paginator.PageGroups }} +

    {{ .Key }}

    + {{ range .Pages }} +

    {{ .LinkTitle }}

    + {{ end }} +{{ end }} + +{{ partial "pagination.html" . }} +``` + +## Navigation + +As shown in the examples above, the easiest way to add navigation between pagers is with Hugo's embedded pagination template: + +```go-html-template +{{ partial "pagination.html" . }} +``` + +The embedded pagination template has two formats: `default` and `terse`. The above is equivalent to: + +```go-html-template +{{ partial "pagination.html" (dict "page" . "format" "default") }} +``` + +The `terse` format has fewer controls and page slots, consuming less space when styled as a horizontal list. To use the `terse` format: + +```go-html-template +{{ partial "pagination.html" (dict "page" . "format" "terse") }} +``` + +> [!note] +> To override Hugo's embedded pagination template, copy the [source code] to a file with the same name in the `layouts/_partials` directory, then call it from your templates using the [`partial`] function: +> +> `{{ partial "pagination.html" . }}` + +Create custom navigation components using any of the `Pager` methods: + +{{% list-pages-in-section path=/methods/pager %}} + +## Structure + +The example below depicts the published site structure when paginating a list page. + +With this content: + +```text +content/ +├── posts/ +│ ├── _index.md +│ ├── post-1.md +│ ├── post-2.md +│ ├── post-3.md +│ └── post-4.md +└── _index.md +``` + +And this site configuration: + +{{< code-toggle file=hugo >}} +[pagination] + disableAliases = false + pagerSize = 2 + path = 'page' +{{< /code-toggle >}} + - And this section template: ++And this _section_ template: + - ```go-html-template ++```go-html-template {file="layouts/section.html"} +{{ range (.Paginate .Pages).Pages }} +

    {{ .LinkTitle }}

    +{{ end }} + +{{ partial "pagination.html" . }} +``` + +The published site has this structure: + +```text +public/ +├── posts/ +│ ├── page/ +│ │ ├── 1/ +│ │ │ └── index.html <-- alias to public/posts/index.html +│ │ └── 2/ +│ │ └── index.html +│ ├── post-1/ +│ │ └── index.html +│ ├── post-2/ +│ │ └── index.html +│ ├── post-3/ +│ │ └── index.html +│ ├── post-4/ +│ │ └── index.html +│ └── index.html +└── index.html +``` + +To disable alias generation for the first pager, change your site configuration: + +{{< code-toggle file=hugo >}} +[pagination] + disableAliases = true + pagerSize = 2 + path = 'page' +{{< /code-toggle >}} + +Now the published site will have this structure: + +```text +public/ +├── posts/ +│ ├── page/ +│ │ └── 2/ +│ │ └── index.html +│ ├── post-1/ +│ │ └── index.html +│ ├── post-2/ +│ │ └── index.html +│ ├── post-3/ +│ │ └── index.html +│ ├── post-4/ +│ │ └── index.html +│ └── index.html +└── index.html +``` + +[`Paginate`]: /methods/page/paginate/ +[`Paginator`]: /methods/page/paginator/ +[`partial`]: /functions/partials/include/ +[grouping methods]: /quick-reference/page-collections/#group - [grouping methods]: /quick-reference/page-collections/#group +[source code]: {{% eturl pagination %}} diff --cc docs/content/en/templates/robots.md index 2d412d775,000000000..807a6027a mode 100644,000000..100644 --- a/docs/content/en/templates/robots.md +++ b/docs/content/en/templates/robots.md @@@ -1,53 -1,0 +1,52 @@@ +--- +title: robots.txt template +linkTitle: robots.txt templates +description: Hugo can generate a customized robots.txt in the same way as any other template. +categories: [] +keywords: [] +weight: 180 +aliases: [/extras/robots-txt/] +--- + +To generate a robots.txt file from a template, change the [site configuration]: + +{{< code-toggle file=hugo >}} +enableRobotsTXT = true +{{< /code-toggle >}} + +By default, Hugo generates robots.txt using an [embedded template]. + +```text +User-agent: * +``` + +Search engines that honor the Robots Exclusion Protocol will interpret this as permission to crawl everything on the site. + +## robots.txt template lookup order + +You may overwrite the internal template with a custom template. Hugo selects the template using this lookup order: + +1. `/layouts/robots.txt` +1. `/themes//layouts/robots.txt` + +## robots.txt template example + +```text {file="layouts/robots.txt"} +User-agent: * +{{ range .Pages }} +Disallow: {{ .RelPermalink }} +{{ end }} +``` + +This template creates a robots.txt file with a `Disallow` directive for each page on the site. Search engines that honor the Robots Exclusion Protocol will not crawl any page on the site. + +> [!note] +> To create a robots.txt file without using a template: +> +> 1. Set `enableRobotsTXT` to `false` in the site configuration. +> 1. Create a robots.txt file in the `static` directory. +> - > Remember that Hugo copies everything in the [`static` directory][static] to the root of `publishDir` (typically `public`) when you build your site. ++> Remember that Hugo copies everything in the static director to the root of `publishDir` (typically `public`) when you build your site. + +[embedded template]: {{% eturl robots %}} +[site configuration]: /configuration/ - [static]: /getting-started/directory-structure/ diff --cc docs/content/en/templates/shortcode.md index 5e6ad3429,000000000..f07206f6a mode 100644,000000..100644 --- a/docs/content/en/templates/shortcode.md +++ b/docs/content/en/templates/shortcode.md @@@ -1,341 -1,0 +1,340 @@@ +--- +title: Shortcode templates +description: Create custom shortcodes to simplify and standardize content creation. +categories: [] +keywords: [] +weight: 120 +aliases: [/templates/shortcode-templates/] +--- + +{{< newtemplatesystem >}} + - +> [!note] +> Before creating custom shortcodes, please review the [shortcodes] page in the [content management] section. Understanding the usage details will help you design and create better templates. + +## Introduction + +Hugo provides [embedded shortcodes] for many common tasks, but you'll likely need to create your own for more specific needs. Some examples of custom shortcodes you might develop include: + +- Audio players +- Video players +- Image galleries +- Diagrams +- Maps +- Tables +- And many other custom elements + +## Directory structure + - Create shortcode templates within the `layouts/_shortcodes` directory, either at its root or organized into subdirectories. ++Create _shortcode_ templates within the `layouts/_shortcodes` directory, either at its root or organized into subdirectories. + +```text +layouts/ +└── _shortcodes/ + ├── diagrams/ + │ ├── kroki.html + │ └── plotly.html + ├── media/ + │ ├── audio.html + │ ├── gallery.html + │ └── video.html + ├── capture.html + ├── column.html + ├── include.html + └── row.html +``` + +When calling a shortcode in a subdirectory, specify its path relative to the `_shortcode` directory, excluding the file extension. + +```text +{{}} +``` + +## Lookup order + - Hugo selects shortcode templates based on the shortcode name, the current output format, and the current language. The examples below are sorted by specificity in descending order. The least specific path is at the bottom of the list. ++Hugo selects _shortcode_ templates based on the shortcode name, the current output format, and the current language. The examples below are sorted by specificity in descending order. The least specific path is at the bottom of the list. + +Shortcode name|Output format|Language|Template path +:--|:--|:--|:-- +foo|html|en|`layouts/_shortcodes/foo.en.html` +foo|html|en|`layouts/_shortcodes/foo.html.html` +foo|html|en|`layouts/_shortcodes/foo.html` +foo|html|en|`layouts/_shortcodes/foo.html.en.html` + +Shortcode name|Output format|Language|Template path +:--|:--|:--|:-- +foo|json|en|`layouts/_shortcodes/foo.en.json` +foo|json|en|`layouts/_shortcodes/foo.json` +foo|json|en|`layouts/_shortcodes/foo.json.json` +foo|json|en|`layouts/_shortcodes/foo.json.en.json` + +## Methods + - Use these methods in your shortcode templates. Refer to each methods's documentation for details and examples. ++Use these methods in your _shortcode_ templates. Refer to each methods's documentation for details and examples. + +{{% list-pages-in-section path=/methods/shortcode %}} + +## Examples + +These examples range in complexity from simple to moderately advanced, with some simplified for clarity. + +### Insert year + +Create a shortcode to insert the current year: + +```go-html-template {file="layouts/_shortcodes/year.html"} +{{- now.Format "2006" -}} +``` + +Then call the shortcode from within your markup: + +```text {file="content/example.md"} +This is {{}}, and look at how far we've come. +``` + +This shortcode can be used inline or as a block on its own line. If a shortcode might be used inline, remove the surrounding [whitespace] by using [template action](g) delimiters with hyphens. + +### Insert image + +This example assumes the following content structure, where `content/example/index.md` is a [page bundle](g) containing one or more [page resources](g). + +```text +content/ +├── example/ +│ ├── a.jpg +│ └── index.md +└── _index.md +``` + +Create a shortcode to capture an image as a page resource, resize it to the given width, convert it to the WebP format, and add an `alt` attribute: + +```go-html-template {file="layouts/_shortcodes/image.html"} +{{- with .Page.Resources.Get (.Get "path") }} + {{- with .Process (printf "resize %dx wepb" ($.Get "width")) -}} + {{ $.Get + {{- end }} +{{- end -}} +``` + +Then call the shortcode from within your markup: + +```text {file="content/example/index.md"} +{{}} +``` + +The example above uses: + +- The [`with`] statement to rebind the [context](g) after each successful operation +- The [`Get`] method to retrieve arguments by name +- The `$` to access the template context + +> [!note] +> Make sure that you thoroughly understand the concept of context. The most common templating errors made by new users relate to context. +> +> Read more about context in the [introduction to templating]. + +### Insert image with error handling + +The previous example, while functional, silently fails if the image is missing, and does not gracefully exit if a required argument is missing. We'll add error handling to address these issues: + +```go-html-template {file="layouts/_shortcodes/image.html"} +{{- with .Get "path" }} + {{- with $r := $.Page.Resources.Get ($.Get "path") }} + {{- with $.Get "width" }} + {{- with $r.Process (printf "resize %dx wepb" ($.Get "width" )) }} + {{- $alt := or ($.Get "alt") "" -}} + {{ $alt }} + {{- end }} + {{- else }} + {{- errorf "The %q shortcode requires a 'width' argument: see %s" $.Name $.Position }} + {{- end }} + {{- else }} + {{- warnf "The %q shortcode was unable to find %s: see %s" $.Name ($.Get "path") $.Position }} + {{- end }} +{{- else }} + {{- errorf "The %q shortcode requires a 'path' argument: see %s" .Name .Position }} +{{- end -}} +``` + +This template throws an error and gracefully fails the build if the author neglected to provide a `path` or `width` argument, and it emits a warning if it cannot find the image at the specified path. If the author does not provide an `alt` argument, the `alt` attribute is set to an empty string. + +The [`Name`] and [`Position`] methods provide helpful context for errors and warnings. For example, a missing `width` argument causes the shortcode to throw this error: + +```text +ERROR The "image" shortcode requires a 'width' argument: see "/home/user/project/content/example/index.md:7:1" +``` + +### Positional arguments + +Shortcode arguments can be [named or positional]. We used named arguments previously; let's explore positional arguments. Here's the named argument version of our example: + +```text {file="content/example/index.md"} +{{}} +``` + +Here's how to call it with positional arguments: + +```text {file="content/example/index.md"} +{{}} +``` + +Using the `Get` method with zero-indexed keys, we'll initialize variables with descriptive names in our template: + +```go-html-template {file="layouts/_shortcodes/image.html"} +{{ $path := .Get 0 }} +{{ $width := .Get 1 }} +{{ $alt := .Get 2 }} +``` + +> [!note] +> Positional arguments work well for frequently used shortcodes with one or two arguments. Since you'll use them often, the argument order will be easy to remember. For less frequently used shortcodes, or those with more than two arguments, named arguments improve readability and reduce the chance of errors. + +### Named and positional arguments + +You can create a shortcode that will accept both named and positional arguments, but not at the same time. Use the [`IsNamedParams`] method to determine whether the shortcode call used named or positional arguments: + +```go-html-template {file="layouts/_shortcodes/image.html"} +{{ $path := cond (.IsNamedParams) (.Get "path") (.Get 0) }} +{{ $width := cond (.IsNamedParams) (.Get "width") (.Get 1) }} +{{ $alt := cond (.IsNamedParams) (.Get "alt") (.Get 2) }} +``` + +This example uses the `cond` alias for the [`compare.Conditional`] function to get the argument by name if `IsNamedParams` returns `true`, otherwise get the argument by position. + +### Argument collection + +Use the [`Params`] method to access the arguments as a collection. + +When using named arguments, the `Params` method returns a map: + +```text {file="content/example/index.md"} +{{}} +``` + +```go-html-template {file="layouts/_shortcodes/image.html"} +{{ .Params.path }} → a.jpg +{{ .Params.width }} → 300 +{{ .Params.alt }} → A white kitten +``` + + When using positional arguments, the `Params` method returns a slice: + +```text {file="content/example/index.md"} +{{}} +``` + +```go-html-template {file="layouts/_shortcodes/image.html"} +{{ index .Params 0 }} → a.jpg +{{ index .Params 1 }} → 300 +{{ index .Params 1 }} → A white kitten +``` + +Combine the `Params` method with the [`collections.IsSet`] function to determine if a parameter is set, even if its value is falsy. + +### Inner content + +Extract the content enclosed within shortcode tags using the [`Inner`] method. This example demonstrates how to pass both content and a title to a shortcode. The shortcode then generates a `div` element containing an `h2` element (displaying the title) and the provided content. + +```text {file="content/example.md"} +{{}} +This is a **bold** word, and this is an _emphasized_ word. +{{}} +``` + +```go-html-template {file="layouts/_shortcodes/contrived.html"} +
    +

    {{ .Get "title" }}

    + {{ .Inner | .Page.RenderString }} +
    +``` + +The preceding example called the shortcode using [standard notation], requiring us to process the inner content with the [`RenderString`] method to convert the Markdown to HTML. This conversion is unnecessary when calling a shortcode using [Markdown notation]. + +### Nesting + +The [`Parent`] method provides access to the parent shortcode context when the shortcode in question is called within the context of a parent shortcode. This provides an inheritance model. + +The following example is contrived but demonstrates the concept. Assume you have a `gallery` shortcode that expects one named `class` argument: + +```go-html-template {file="layouts/_shortcodes/gallery.html"} +
    + {{ .Inner }} +
    +``` + +You also have an `img` shortcode with a single named `src` argument that you want to call inside of `gallery` and other shortcodes, so that the parent defines the context of each `img`: + +```go-html-template {file="layouts/_shortcodes/img.html"} +{{ $src := .Get "src" }} +{{ with .Parent }} + +{{ else }} + +{{ end }} +``` + +You can then call your shortcode in your content as follows: + +```text {file="content/example.md"} +{{}} + {{}} + {{}} +{{}} +{{}} +``` + +This will output the following HTML. Note how the first two `img` shortcodes inherit the `class` value of `content-gallery` set with the call to the parent `gallery`, whereas the third `img` only uses `src`: + +```html + + +``` + +### Other examples + +For guidance, consider examining Hugo's embedded shortcodes. The source code, available on [GitHub], can provide a useful model. + +## Detection + +The [`HasShortcode`] method allows you to check if a specific shortcode has been called on a page. For example, consider a custom audio shortcode: + +```text {file="content/example.md"} +{{}} +``` + +You can use the `HasShortcode` method in your base template to conditionally load CSS if the audio shortcode was used on the page: + +```go-html-template {file="layouts/baseof.html"} + + ... + {{ if .HasShortcode "audio" }} + + {{ end }} + ... + +``` + +[`collections.IsSet`]: /functions/collections/isset/ +[`compare.Conditional`]: /functions/compare/conditional/ +[`Get`]: /methods/shortcode/get/ +[`HasShortcode`]: /methods/page/hasshortcode/ +[`Inner`]: /methods/shortcode/inner/ +[`IsNamedParams`]: /methods/shortcode/isnamedparams/ +[`Name`]: /methods/shortcode/name/ +[`Params`]: /methods/shortcode/params/ +[`Parent`]: /methods/shortcode/parent/ +[`Position`]: /methods/shortcode/position/ +[`RenderString`]: /methods/page/renderstring/ +[`with`]: /functions/go-template/with/ +[content management]: /content-management/shortcodes/ +[embedded shortcodes]: /shortcodes/ +[GitHub]: https://github.com/gohugoio/hugo/tree/master/tpl/tplimpl/embedded/templates/_shortcodes +[introduction to templating]: /templates/introduction/ +[Markdown notation]: /content-management/shortcodes/#markdown-notation +[named or positional]: /content-management/shortcodes/#arguments +[shortcodes]: /content-management/shortcodes/ +[standard notation]: /content-management/shortcodes/#standard-notation +[whitespace]: /templates/introduction/#whitespace diff --cc docs/content/en/templates/sitemap.md index 2691ae471,000000000..8eb358d87 mode 100644,000000..100644 --- a/docs/content/en/templates/sitemap.md +++ b/docs/content/en/templates/sitemap.md @@@ -1,62 -1,0 +1,54 @@@ +--- +title: Sitemap templates +description: Hugo provides built-in sitemap templates. +categories: [] +keywords: [] +weight: 130 +aliases: [/layout/sitemap/,/templates/sitemap-template/] +--- + +## Overview + +Hugo's embedded sitemap templates conform to v0.9 of the [sitemap protocol]. + +With a monolingual project, Hugo generates a sitemap.xml file in the root of the [`publishDir`] using the [embedded sitemap template]. + +With a multilingual project, Hugo generates: + +- A sitemap.xml file in the root of each site (language) using the [embedded sitemap template] +- A sitemap.xml file in the root of the [`publishDir`] using the [embedded sitemapindex template] + +## Configuration + +See [configure sitemap](/configuration/sitemap). + +## Override default values + +Override the default values for a given page in front matter. + +{{< code-toggle file=news.md fm=true >}} +title = 'News' +[sitemap] + changefreq = 'weekly' + disable = true + priority = 0.8 +{{}} + +## Override built-in templates + - To override the built-in sitemap.xml template, create a new file in either of these locations: ++To override the built-in sitemap.xml template, create a new `layouts/sitemap.xml` file. When ranging through the page collection, access the _change frequency_ and _priority_ with `.Sitemap.ChangeFreq` and `.Sitemap.Priority` respectively. + - - `layouts/sitemap.xml` - - `layouts/sitemap.xml` - - When ranging through the page collection, access the _change frequency_ and _priority_ with `.Sitemap.ChangeFreq` and `.Sitemap.Priority` respectively. - - To override the built-in sitemapindex.xml template, create a new file in either of these locations: - - - `layouts/sitemapindex.xml` - - `layouts/sitemapindex.xml` ++To override the built-in sitemapindex.xml template, create a new `layouts/sitemapindex.xml` file. + +## Disable sitemap generation + +You may disable sitemap generation in your site configuration: + +{{< code-toggle file=hugo >}} +disableKinds = ['sitemap'] +{{}} + +[`publishDir`]: /configuration/all/#publishdir +[embedded sitemap template]: {{% eturl sitemap %}} +[embedded sitemapindex template]: {{% eturl sitemapindex %}} +[sitemap protocol]: https://www.sitemaps.org/protocol.html diff --cc docs/content/en/templates/types.md index 8c533a56f,000000000..19e0e32dd mode 100644,000000..100644 --- a/docs/content/en/templates/types.md +++ b/docs/content/en/templates/types.md @@@ -1,381 -1,0 +1,403 @@@ +--- +title: Template types +description: Create templates of different types to render your content, resources, and data. +categories: [] +keywords: [] +weight: 30 +aliases: [ + '/templates/base/', + '/templates/content-view/', + '/templates/home/', + '/templates/lists/', + '/templates/partial/', + '/templates/section/', + '/templates/single/', + '/templates/taxonomy/', + '/templates/term/', +] +--- + +## Structure + +Create templates in the `layouts` directory in the root of your project. + +Although your site may not require each of these templates, the example below is typical for a site of medium complexity. + +```text +layouts/ +├── _markup/ +│ ├── render-image.html <-- render hook +│ └── render-link.html <-- render hook +├── _partials/ +│ ├── footer.html +│ └── header.html +├── _shortcodes/ +│ ├── audio.html +│ └── video.html +├── books/ +│ ├── page.html +│ └── section.html +├── films/ - │ ├── card.html <-- content view ++│ ├── view_card.html <-- content view ++│ ├── view_li.html <-- content view +│ ├── page.html +│ └── section.html +├── baseof.html +├── home.html +├── page.html +├── section.html +├── taxonomy.html +└── term.html +``` + +Hugo's [template lookup order] determines the template path, allowing you to create unique templates for any page. + +> [!note] +> You must have thorough understanding of the template lookup order when creating templates. Template selection is based on template type, page kind, content type, section, language, and output format. + +The purpose of each template type is described below. + +## Base + - A base template reduces duplicate code by wrapping other templates within a shell. ++A _base_ template serves as a foundational layout that other templates can build upon. It typically defines the common structural components of your HTML, such as the `html`, `head`, and `body` elements. It also often includes recurring features like headers, footers, navigation, and script inclusions that appear across multiple pages of your site. By defining these common aspects once in a _base_ template, you avoid redundancy, ensure consistency, and simplify the maintenance of your website. + - For example, the base template below calls the [`partial`] function to include partial templates for the `head`, `header`, and `footer` elements of each page, and it calls the [`block`] function to include `home`, `page`, `section`, `taxonomy`, and `term` templates within the `main` element of each page. ++Hugo can apply a _base_ template to the following template types: [home](#home), [page](#page), [section](#section), [taxonomy](#taxonomy), [term](#term), [single](#single), [list](#list), and [all](#all). When Hugo parses any of these template types, it will apply a _base_ template only if the template being parsed meets these specific conditions: ++ ++- It must include at least one [`define`] [action](g). ++- It can only contain `define` actions, whitespace, and [template comments]. No other content is allowed. ++ ++> [!note] ++> If a template doesn't meet all these criteria, Hugo executes it exactly as provided, without applying a _base_ template. ++ ++When Hugo applies a _base_ template, it replaces its [`block`] actions with content from the corresponding `define` actions found in the template to which the base template is applied. ++ ++For example, the _base_ template below calls the [`partial`] function to include `head`, `header`, and `footer` elements. The `block` action acts as a placeholder, and its content will be replaced by a matching `define` action from the template to which it is applied. + +```go-html-template {file="layouts/baseof.html"} + - ++ + + {{ partial "head.html" . }} + + +
    + {{ partial "header.html" . }} +
    +
    - {{ block "main" . }}{{ end }} ++ {{ block "main" . }} ++ This will be replaced with content from the ++ corresponding "define" action found in the template ++ to which this base template is applied. ++ {{ end }} +
    +
    + {{ partial "footer.html" . }} +
    + + +``` + - The `block` construct above is used to define a set of root templates that are then customized by redefining the block templates within. See [details](/functions/go-template/block/) ++```go-html-template {file="layouts/home.html"} ++{{ define "main" }} ++ This will replace the content of the "block" action ++ found in the base template. ++{{ end }} ++``` + +## Home + - A home template renders your site's home page. For example, the home template below inherits the site's shell from the [base template] and renders the home page content, such as a list of other pages. ++A _home_ template renders your site's home page. ++ ++For example, Hugo applies a _base_ template to the _home_ template below, then renders the page content and a list of the site's regular pages. + +```go-html-template {file="layouts/home.html"} +{{ define "main" }} + {{ .Content }} + {{ range .Site.RegularPages }} +

    {{ .LinkTitle }}

    + {{ end }} +{{ end }} +``` + +{{% include "/_common/filter-sort-group.md" %}} + +## Page + - A page template renders a regular page. ++A _page_ template renders a regular page. + - For example, the page template below inherits the site's shell from the [base template] and renders the page title and page content. ++For example, Hugo applies a _base_ template to the _page_ template below, then renders the page title and page content. + +```go-html-template {file="layouts/page.html"} +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} +{{ end }} +``` + +## Section + - A section template renders a list of pages within a section. ++A _section_ template renders a list of pages within a [section](g). + - For example, the section template below inherits the site's shell from the [base template] and renders a list of pages in the current section. ++For example, Hugo applies a _base_ template to the _section_ template below, then renders the page title, page content, and a list of pages in the current section. + +```go-html-template {file="layouts/section.html"} +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +

    {{ .LinkTitle }}

    + {{ end }} +{{ end }} +``` + +{{% include "/_common/filter-sort-group.md" %}} + +## Taxonomy + - A taxonomy template renders a list of terms in a [taxonomy](g). ++A _taxonomy_ template renders a list of terms in a [taxonomy](g). + - For example, the taxonomy template below inherits the site's shell from the [base template] and renders a list of terms in the current taxonomy. ++For example, Hugo applies a _base_ template to the _taxonomy_ template below, then renders the page title, page content, and a list of [terms](g) in the current taxonomy. + +```go-html-template {file="layouts/taxonomy.html"} +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +

    {{ .LinkTitle }}

    + {{ end }} +{{ end }} +``` + +{{% include "/_common/filter-sort-group.md" %}} + - Within a taxonomy template, the [`Data`] object provides these taxonomy-specific methods: ++Within a _taxonomy_ template, the [`Data`] object provides these taxonomy-specific methods: + +- [`Singular`][taxonomy-singular] +- [`Plural`][taxonomy-plural] - - [`Terms`]. ++- [`Terms`] + +The `Terms` method returns a [taxonomy object](g), allowing you to call any of its methods including [`Alphabetical`] and [`ByCount`]. For example, use the `ByCount` method to render a list of terms sorted by the number of pages associated with each term: + +```go-html-template {file="layouts/taxonomy.html"} +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Data.Terms.ByCount }} +

    {{ .Page.LinkTitle }} ({{ .Count }})

    + {{ end }} +{{ end }} +``` + +## Term + - A term template renders a list of pages associated with a [term](g). ++A _term_ template renders a list of pages associated with a [term](g). + - For example, the term template below inherits the site's shell from the [base template] and renders a list of pages associated with the current term. ++For example, Hugo applies a _base_ template to the _term_ template below, then renders the page title, page content, and a list of pages associated with the current term. + +```go-html-template {file="layouts/term.html"} +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +

    {{ .LinkTitle }}

    + {{ end }} +{{ end }} +``` + +{{% include "/_common/filter-sort-group.md" %}} + - Within a term template, the [`Data`] object provides these term-specific methods: ++Within a _term_ template, the [`Data`] object provides these term-specific methods: + +- [`Singular`][term-singular] +- [`Plural`][term-plural] - - [`Term`]. ++- [`Term`] + +## Single + - A single template is a fallback for [page templates](#page). If a page template does not exist, Hugo will look for a single template instead. - - Like a page template, a single template renders a regular page. ++A _single_ template is a fallback for a _page_ template. If a _page_ template does not exist, Hugo will look for a _single_ template instead. + - For example, the single template below inherits the site's shell from the [base template] and renders the page title and page content. ++For example, Hugo applies a _base_ template to the _single_ template below, then renders the page title and page content. + +```go-html-template {file="layouts/single.html"} +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} +{{ end }} +``` + +## List + - A list template is a fallback for these template types: [home](#home), [section](#section), [taxonomy](#taxonomy), and [term](#term). If one of these template types does not exist, Hugo will look for a list template instead. ++A _list_ template is a fallback for [home](#home), [section](#section), [taxonomy](#taxonomy), and [term](#term) templates. If one of these template types does not exist, Hugo will look for a _list_ template instead. + - For example, the list template below inherits the site's shell from the [base template] and renders a list of pages: ++For example, Hugo applies a _base_ template to the _list_ template below, then renders the page title, page content, and a list of pages. + +```go-html-template {file="layouts/list.html"} +{{ define "main" }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +

    {{ .LinkTitle }}

    + {{ end }} +{{ end }} +``` + +## All + - An "all" template is a fallback for these template types: [home](#home), [page](#page), [section](#section), [taxonomy](#taxonomy), [term](#term), [single](#single), and [list](#list). If one of these template types does not exist, Hugo will look for an "all" template instead. ++An _all_ template is a fallback for [home](#home), [page](#page), [section](#section), [taxonomy](#taxonomy), [term](#term), [single](#single), and [list](#list) templates. If one of these template types does not exist, Hugo will look for an _all_ template instead. + - For example, the contrived "all" template below inherits the site's shell from the [base template] and conditionally renders a page based on its page kind: ++For example, Hugo applies a _base_ template to the _all_ template below, then conditionally renders a page based on its page kind. + +```go-html-template {file="layouts/all.html"} +{{ define "main" }} + {{ if eq .Kind "home" }} + {{ .Content }} + {{ range .Site.RegularPages }} +

    {{ .LinkTitle }}

    + {{ end }} + {{ else if eq .Kind "page" }} +

    {{ .Title }}

    + {{ .Content }} + {{ else if in (slice "section" "taxonomy" "term") .Kind }} +

    {{ .Title }}

    + {{ .Content }} + {{ range .Pages }} +

    {{ .LinkTitle }}

    + {{ end }} + {{ else }} + {{ errorf "Unsupported page kind: %s" .Kind }} + {{ end }} +{{ end }} +``` + +## Partial + - A partial template is typically used to render a component of your site, though you may also create partial templates that return values. ++A _partial_ template is typically used to render a component of your site, though you may also create _partial_ templates that return values. + - - For example, the partial template below renders copyright information: ++For example, the _partial_ template below renders copyright information: + +```go-html-template {file="layouts/_partials/footer.html"} +

    Copyright {{ now.Year }}. All rights reserved.

    +``` + - Execute the partial template by calling the [`partial`] or [`partialCached`] function, optionally passing context as the second argument: ++Execute the _partial_ template by calling the [`partial`] or [`partialCached`] function, optionally passing context as the second argument: + +```go-html-template {file="layouts/baseof.html"} +{{ partial "footer.html" . }} +``` + - Unlike other template types, partial template selection is based on the file name passed in the partial call. Hugo does not consider the current page kind, content type, logical path, language, or output format when searching for a matching partial template. However, Hugo _does_ apply the same name matching logic it uses for other templates. This means it tries to find the most specific match first, then progressively looks for more general versions if the specific one isn't found. ++ ++Unlike other template types, Hugo does not consider the current page kind, content type, logical path, language, or output format when searching for a matching _partial_ template. However, it _does_ apply the same name matching logic it uses for other template types. This means it tries to find the most specific match first, then progressively looks for more general versions if the specific one isn't found. + - For example, with this partial call: ++For example, with this call: + +```go-html-template {file="layouts/baseof.html"} +{{ partial "footer.section.de.html" . }} +``` + +Hugo uses this lookup order to find a matching template: + +1. `layouts/_partials/footer.section.de.html` +1. `layouts/_partials/footer.section.html` +1. `layouts/_partials/footer.de.html` +1. `layouts/_partials/footer.html` + - Partials can also be defined inline within a template. However, it's important to note that the template namespace is global; ensuring unique names for these partials is necessary to prevent conflicts. ++A _partial_ template can also be defined inline within another template. However, it's important to note that the template namespace is global; ensuring unique names for these _partial_ templates is necessary to prevent conflicts. + +```go-html-template +Value: {{ partial "my-inline-partial.html" . }} + +{{ define "_partials/my-inline-partial.html" }} + {{ $value := 32 }} + {{ return $value }} +{{ end }} +``` + +## Content view + - A content view template is similar to a partial template, invoked by calling the [`Render`] method on a `Page` object. Unlike partial templates, content view templates: ++A _content view_ template is similar to a _partial_ template, invoked by calling the [`Render`] method on a `Page` object. Unlike _partial_ templates, _content view_ templates: + +- Inherit the context of the current page +- Can target any page kind, content type, logical path, language, or output format + - For example, the home template below inherits the site's shell from the [base template], and renders a card component for each page within the "films" section of your site. ++For example, Hugo applies a _base_ template to the _home_ template below, then renders the page content and a card component for each page within the "films" section of your site. + +```go-html-template {file="layouts/home.html"} +{{ define "main" }} + {{ .Content }} +
      + {{ range where site.RegularPages "Section" "films" }} - {{ .Render "card" }} ++ {{ .Render "view_card" }} + {{ end }} +
    +{{ end }} +``` + - ```go-html-template {file="layouts/films/card.html"} ++```go-html-template {file="layouts/films/view_card.html"} +
    +

    {{ .LinkTitle }}

    + {{ .Summary }} +
    +``` + ++In the example above, the content view template's name starts with `view_`. While not strictly required, this naming convention helps distinguish content view templates from other templates within the same directory, improving organization and clarity. ++ +## Render hook + - A render hook template overrides the conversion of Markdown to HTML. ++A _render hook_ template overrides the conversion of Markdown to HTML. + - For example, the render hook template below adds an anchor link to the right of each heading. ++For example, the _render hook_ template below adds an anchor link to the right of each heading. + - ```go-html-template {file="layouts/_markup/heading.html"} ++```go-html-template {file="layouts/_markup/render-heading.html"} + + {{ .Text }} + # + +``` + +Learn more about [render hook templates](/render-hooks/). + +## Shortcode + - A shortcode template is used to render a component of your site. Unlike [partial templates](#partial) or [content view templates](#content-view), shortcode templates are called from content pages. ++A _shortcode_ template is used to render a component of your site. Unlike _partial_ or _content view_ templates, _shortcode_ templates are called from content pages. + - For example, the shortcode template below renders an audio element from a [global resource](g). ++For example, the _shortcode_ template below renders an audio element from a [global resource](g). + +```go-html-template {file="layouts/_shortcodes/audio.html"} +{{ with resources.Get (.Get "src") }} + +{{ end }} +``` + +Then call the shortcode from within markup: + +```text {file="content/example.md"} +{{}} +``` + +Learn more about [shortcode templates](/templates/shortcode/). + +## Other + +Use other specialized templates to create: + +- [Sitemaps](/templates/sitemap) +- [RSS feeds](/templates/rss/) +- [404 error pages](/templates/404/) +- [robots.txt files](/templates/robots/) + +[`Alphabetical`]: /methods/taxonomy/alphabetical/ +[`block`]: /functions/go-template/block/ +[`ByCount`]: /methods/taxonomy/bycount/ +[`Data`]: /methods/page/data/ ++[`define`]: /functions/go-template/define/ +[`partial`]: /functions/partials/include/ +[`partialCached`]: /functions/partials/includeCached/ +[`Render`]: /methods/page/render/ - [`Taxonomy`]: /methods/taxonomy/ - [`Terms`]: /methods/page/data/#terms +[`Term`]: /methods/page/data/#term ++[`Terms`]: /methods/page/data/#terms +[taxonomy-plural]: /methods/page/data/#plural +[taxonomy-singular]: /methods/page/data/#singular ++[template comments]: /templates/introduction/#comments +[template lookup order]: /templates/lookup-order/ +[term-plural]: /methods/page/data/#plural-1 +[term-singular]: /methods/page/data/#singular-1 - [base template]: #base diff --cc docs/content/en/tools/editors.md index c375fcba8,000000000..612e06987 mode 100644,000000..100644 --- a/docs/content/en/tools/editors.md +++ b/docs/content/en/tools/editors.md @@@ -1,58 -1,0 +1,58 @@@ +--- +title: Editor plugins +description: The Hugo community uses a wide range of tools and has developed plugins for some of the most popular text editors to help automate parts of your workflow. +categories: [] +keywords: [] +weight: 10 +--- + +## Visual Studio Code + +[Front Matter](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-front-matter) +: Once you go for a static site, you need to think about how you are going to manage your articles. Front matter is a tool that helps you maintain the metadata/front matter of your articles like: creation date, modified date, slug, tile, SEO check, and more. + +[Hugo Helper](https://marketplace.visualstudio.com/items?itemName=rusnasonov.vscode-hugo) - : Hugo Helper is a plugin for Visual Studio Code that has some useful commands for Hugo. The source code can be found [here](https://github.com/rusnasonov/vscode-hugo). ++: Hugo Helper is a plugin for Visual Studio Code that has some useful commands for Hugo. The source code can be found on its [GitHub repository](https://github.com/rusnasonov/vscode-hugo). + +[Hugo Language and Syntax Support](https://marketplace.visualstudio.com/items?itemName=budparr.language-hugo-vscode) - : Hugo Language and Syntax Support is a Visual Studio Code plugin for Hugo syntax highlighting and snippets. The source code can be found [here](https://github.com/budparr/language-hugo-vscode). ++: Hugo Language and Syntax Support is a Visual Studio Code plugin for Hugo syntax highlighting and snippets. The source code can be found on its [GitHub repository](https://github.com/budparr/language-hugo-vscode). + +[Hugo Themer](https://marketplace.visualstudio.com/items?itemName=eliostruyf.vscode-hugo-themer) +: Hugo Themer is an extension to help you while developing themes. It allows you to easily navigate through your theme files. + +[Hugofy](https://marketplace.visualstudio.com/items?itemName=akmittal.hugofy) - : Hugofy is a plugin for Visual Studio Code to "make life easier" when developing with Hugo. The source code can be found [here](https://github.com/akmittal/hugofy-vscode). ++: Hugofy is a plugin for Visual Studio Code to "make life easier" when developing with Hugo. The source code can be found on its [GitHub repository](https://github.com/akmittal/hugofy-vscode). + +[Prettier Plugin for Go Templates](https://github.com/NiklasPor/prettier-plugin-go-template) +: Format Hugo templates using this [Prettier](https://prettier.io/) plugin. See [installation instructions](https://discourse.gohugo.io/t/38403). + +[Syntax Highlighting for Hugo Shortcodes](https://marketplace.visualstudio.com/items?itemName=kaellarkin.hugo-shortcode-syntax) +: This extension adds some syntax highlighting for Shortcodes, making visual identification of individual pieces easier. + +## Emacs + +[emacs-easy-hugo](https://github.com/masasam/emacs-easy-hugo) +: Emacs major mode for managing hugo blogs. Note that Hugo also supports [Org-mode][formats]. + +[ox-hugo.el](https://ox-hugo.scripter.co) - : Native Org-mode exporter that exports to Blackfriday Markdown with Hugo front-matter. `ox-hugo` supports two common Org blogging flows --- exporting multiple Org subtrees in a single file to multiple Hugo posts, and exporting a single Org file to a single Hugo post. It also leverages the Org tag and property inheritance features. See [*Why ox-hugo?*](https://ox-hugo.scripter.co/doc/why-ox-hugo/) for more. ++: Native Org-mode exporter that exports to Blackfriday Markdown with Hugo front-matter. `ox-hugo` supports two common Org blogging flows --- exporting multiple Org subtrees in a single file to multiple Hugo posts, and exporting a single Org file to a single Hugo post. It also leverages the Org tag and property inheritance features. See [Why ox-hugo?](https://ox-hugo.scripter.co/doc/why-ox-hugo/) for more. + +## Sublime Text + +[Hugofy](https://github.com/akmittal/Hugofy) +: Hugofy is a plugin for Sublime Text 3 to make life easier to use Hugo static site generator. + +[Hugo Snippets](https://packagecontrol.io/packages/Hugo%20Snippets) +: Hugo Snippets is a useful plugin for adding automatic snippets to Sublime Text 3. + +## Vim + +[Vim Hugo Helper]: https://github.com/robertbasic/vim-hugo-helper + +[Vim Hugo Helper] +: A small Vim plugin that facilitates authoring pages and blog posts with Hugo. + +[vim-hugo](https://github.com/phelipetls/vim-hugo) +: A Vim plugin with syntax highlighting for templates and a few other features. + +[formats]: /content-management/formats/ diff --cc docs/content/en/tools/front-ends.md index 0c52a4687,000000000..90fc8f57c mode 100644,000000..100644 --- a/docs/content/en/tools/front-ends.md +++ b/docs/content/en/tools/front-ends.md @@@ -1,31 -1,0 +1,34 @@@ +--- +title: Front-end interfaces +linkTitle: Front-ends +description: Do you prefer a graphical user interface over a text editor? Give these front-ends a try. +categories: [] +keywords: [] +weight: 20 +aliases: [/tools/frontends/] +--- + +## Commercial + +[CloudCannon](https://cloudcannon.com/hugo-cms/) +: The intuitive Git-based CMS for your Hugo website. CloudCannon syncs changes from your Git repository and pushes content changes back, so your development and content teams are always in sync. Edit all of your content on the page with visual editing, build entire pages with reusable custom components and then publish confidently. + +[DatoCMS](https://www.datocms.com) +: DatoCMS is a fully customizable administrative area for your static websites. Use your favorite website generator, let your clients publish new content independently, and the host the site anywhere you like. + +[PubCrank](https://www.pubcrank.com/) +: PubCrank is a static site editor which lets you define templates for different front matter layouts in your site. This gives writers an easy-to-use visual interface to create and edit content while maintaining the guardrails that the developer has created. PubCrank is free for local editing. + ++[Sitepins](https://sitepins.com) ++: Sitepins is a Git-based CMS built for static site generators like Hugo. It offers a clean visual editor, media management, role-based permissions, shortcode support, and more. To get started, simply connect your GitHub repository, configure your content folders, and start visually editing your Hugo site with Sitepins. ++ +## Open-source + +[Decap CMS](https://decapcms.org/) +: Decap CMS is an open-source, serverless solution for managing Git based content in static sites, and it works on any platform that can host static sites. A [Hugo/Decap CMS starter](https://github.com/decaporg/one-click-hugo-cms) is available to get new projects running quickly. + +[Quiqr Desktop](https://quiqr.org/) +: Quiqr Desktop is a open-source, cross-platform, offline desktop CMS for Hugo with built-in Git functionality for deploying static sites to any hosting server. + +[Sveltia CMS](https://github.com/sveltia/sveltia-cms/) +: Sveltia CMS is a drop-in replacement for Decap CMS which is built from the ground up with powerful and performant modern UI library Svelte. Sveltia CMS incorporates i18n into every corner of the product, while striving to radically improve UX, performance and productivity. diff --cc docs/content/en/tools/migrations.md index 103e28b9e,000000000..f1c10e6fa mode 100644,000000..100644 --- a/docs/content/en/tools/migrations.md +++ b/docs/content/en/tools/migrations.md @@@ -1,100 -1,0 +1,100 @@@ +--- +title: Migrate to Hugo +linkTitle: Migrations +description: A list of community-developed tools for migrating from your existing static site generator or content management system to Hugo. +categories: [] +keywords: [] +weight: 40 +aliases: [/developer-tools/migrations/, /developer-tools/migrated/] +--- + +This section highlights some independently developed projects related to Hugo. These tools extend functionality or help you to get started. + +Take a look at this list of migration tools if you currently use other blogging tools like Jekyll or WordPress but intend to switch to Hugo instead. They'll help you export your content into Hugo-friendly formats. + +## Jekyll + +Alternatively, you can use the [Jekyll import command](/commands/hugo_import_jekyll/). + +[JekyllToHugo](https://github.com/fredrikloch/JekyllToHugo) +: A Small script for converting Jekyll blog posts to a Hugo site. + +[ConvertToHugo](https://github.com/coderzh/ConvertToHugo) +: Convert your blog from Jekyll to Hugo. + +## Octopress + +[octohug](https://github.com/codebrane/octohug) +: Octopress to Hugo migrator. + +## DokuWiki + +[dokuwiki-to-hugo](https://github.com/wgroeneveld/dokuwiki-to-hugo) +: Migrates your DokuWiki source pages from [DokuWiki syntax](https://www.dokuwiki.org/wiki:syntax) to Hugo Markdown syntax. Includes extras like the TODO plugin. Written with extensibility in mind using Python 3. Also generates a TOML header for each page. Designed to copy-paste the wiki directory into your `content` directory. + +## WordPress + +[wordpress-to-hugo-exporter](https://github.com/SchumacherFM/wordpress-to-hugo-exporter) +: A one-click WordPress plugin that converts all posts, pages, taxonomies, metadata, and settings to Markdown and YAML which can be dropped into Hugo. (Note: If you have trouble using this plugin, you can [export your site for Jekyll](https://wordpress.org/plugins/jekyll-exporter/) and use Hugo's built-in Jekyll converter listed above.) + +[blog2md](https://github.com/palaniraja/blog2md) +: Works with [exported xml](https://en.support.wordpress.com/export/) file of your free YOUR-TLD.wordpress.com website. It also saves approved comments to `YOUR-POST-NAME-comments.md` file along with posts. + +[wordhugopress](https://github.com/nantipov/wordhugopress) +: A small utility written in Java that exports the entire WordPress site from the database and resource (e.g., images) files stored locally or remotely. Therefore, migration from the backup files is possible. Supports merging multiple WordPress sites into a single Hugo site. + +[wp2hugo](https://github.com/ashishb/wp2hugo) - : A Go-based CLI tool to migrate WordPress website to Hugo while preserving original URLs, GUIDs (for feeds), image URLs, code highlights, table of contents, YouTube embeds, Google Maps embeds, and original WordPress navigation categories. ++: A Go-based CLI tool to migrate WordPress websites to Hugo. It preserves original URLs, GUIDs, image URLs, code highlights, tables of contents, and WordPress navigation categories. It migrates WordPress custom post types, custom taxonomies, custom fields, and page hierarchy. It supports translated WordPress blogs via Polylang or WPML. It imports a WordPress media library database with original titles and dates. The tool can download all media or only media inserted into pages from the original server. It converts WordPress shortcodes and Gutenberg blocks to Hugo shortcodes including galleries, images, audio, YouTube embeds, Gists, and Google Maps. + +## Medium + +[medium2md](https://github.com/gautamdhameja/medium-2-md) +: A simple Medium to Hugo exporter able to import stories in one command, including front matter. + +[medium-to-hugo](https://github.com/bgadrian/medium-to-hugo) +: A CLI tool written in Go to export medium posts into a Hugo-compatible Markdown format. Tags and images are included. All images will be downloaded locally and linked appropriately. + +## Tumblr + +[tumblr-importr](https://github.com/carlmjohnson/tumblr-importr) +: An importer that uses the Tumblr API to create a Hugo static site. + +[tumblr2hugomarkdown](https://github.com/Wysie/tumblr2hugomarkdown) +: Export all your Tumblr content to Hugo Markdown files with preserved original formatting. + +[Tumblr to Hugo](https://github.com/jipiboily/tumblr-to-hugo) +: A migration tool that converts each of your Tumblr posts to a content file with a proper title and path. It also generates a CSV file to help you set up URL redirects. + +## Drupal + +[drupal2hugo](https://github.com/danapsimer/drupal2hugo) +: Convert a Drupal site to Hugo. + +## Joomla + +[hugojoomla](https://github.com/davetcc/hugojoomla) +: This utility written in Java takes a Joomla database and converts all the content into Markdown files. It changes any URLs that are in Joomla's internal format and converts them to a suitable form. + +## Blogger + +[blogimport](https://github.com/natefinch/blogimport) +: A tool to import from Blogger posts to Hugo. + +[blogger-to-hugo](https://pypi.org/project/blogger-to-hugo/) +: Another tool to import Blogger posts to Hugo. It also downloads embedded images so they will be stored locally. + +[blog2md](https://github.com/palaniraja/blog2md) +: Works with [exported xml](https://support.google.com/blogger/answer/41387?hl=en) file of your YOUR-TLD.blogspot.com website. It also saves comments to `YOUR-POST-NAME-comments.md` file along with posts. + +[BloggerToHugo](https://github.com/huanlin/blogger-to-hugo) +: Yet another tool to import Blogger posts to Hugo. For Windows platform only, and .NET Framework 4.5 is required. See README.md before using this tool. + +## Contentful + +[contentful-hugo](https://github.com/ModiiMedia/contentful-hugo) +: A tool to create content-files for Hugo from content on [Contentful](https://www.contentful.com/). + +## BlogML + +[BlogML2Hugo](https://github.com/jijiechen/BlogML2Hugo) +: A tool that helps you convert BlogML xml file to Hugo Markdown files. Users need to take care of links to attachments and images by themselves. This helps the blogs that export BlogML files (e.g. BlogEngine.NET) transform to hugo sites easily. diff --cc docs/content/en/troubleshooting/faq.md index e1a23610c,000000000..3e519b0e0 mode 100644,000000..100644 --- a/docs/content/en/troubleshooting/faq.md +++ b/docs/content/en/troubleshooting/faq.md @@@ -1,112 -1,0 +1,110 @@@ +--- +title: Frequently asked questions +linkTitle: FAQs +description: These questions are frequently asked by new users. +categories: [] +keywords: [] +--- + +Hugo's [forum] is an active community of users and developers who answer questions, share knowledge, and provide examples. A quick search of over 20,000 topics will often answer your question. Please be sure to read about [requesting help] before asking your first question. + +These are just a few of the questions most frequently asked by new users. + +An error message indicates that a feature is not available. Why? +: + {{% include "/_common/installation/01-editions.md" %}} + + When you attempt to use a feature that is not available in the edition that you installed, Hugo throws this error: + + ```go-html-template + this feature is not available in this edition of Hugo + ``` + + To resolve, install a different edition based on the feature table above. See the [installation] section for details. + +Why do I see "Page Not Found" when visiting the home page? +: In the `content/_index.md` file: + + - Is `draft` set to `true`? + - Is the `date` in the future? + - Is the `publishDate` in the future? + - Is the `expiryDate` in the past? + + If the answer to any of these questions is yes, either change the field values, or use one of these command line flags: `--buildDrafts`, `--buildFuture`, or `--buildExpired`. + +Why is a given page not published? +: In the `content/section/page.md` file, or in the `content/section/page/index.md` file: + + - Is `draft` set to `true`? + - Is the `date` in the future? + - Is the `publishDate` in the future? + - Is the `expiryDate` in the past? + + If the answer to any of these questions is yes, either change the field values, or use one of these command line flags: `--buildDrafts`, `--buildFuture`, or `--buildExpired`. + +Why can't I see any of a page's descendants? +: You may have an `index.md` file instead of an `_index.md` file. See [details](/content-management/page-bundles/). + +What is the difference between an `index.md` file and an `_index.md` file? +: A directory with an `index.md file` is a [leaf bundle](g). A directory with an `_index.md` file is a [branch bundle](g). See [details](/content-management/page-bundles/). + - Why is my partial template not rendered as expected? ++Why is my _partial_ template not rendered as expected? +: You may have neglected to pass the required [context](g) when calling the partial. For example: + + ```go-html-template + {{/* incorrect */}} + {{ partial "pagination.html" }} + + {{/* correct */}} + {{ partial "pagination.html" . }} + ``` + +In a template, what's the difference between `:=` and `=` when assigning values to variables? +: Use `:=` to initialize a variable, and use `=` to assign a value to a variable that has been previously initialized. See [details](https://pkg.go.dev/text/template#hdr-Variables). + +When I paginate a list page, why is the page collection not filtered as specified? +: You are probably invoking the [`Paginate`] or [`Paginator`] method more than once on the same page. See [details](/templates/pagination/). + +Why are there two ways to call a shortcode? - : Use the `{{%/* shortcode */%}}` notation if the shortcode template, or the content between the opening and closing shortcode tags, contains Markdown. Otherwise use the\ ++: Use the `{{%/* shortcode */%}}` notation if the _shortcode_ template, or the content between the opening and closing shortcode tags, contains Markdown. Otherwise use the\ +`{{}}` notation. See [details](/content-management/shortcodes/#notation). + +Can I use environment variables to control configuration? +: Yes. See [details](/configuration/introduction/#environment-variables). + +Why am I seeing inconsistent output from one build to the next? +: The most common causes are page collisions (publishing two pages to the same path) and the effects of concurrency. Use the `--printPathWarnings` command line flag to check for page collisions, and create a topic on the [forum] if you suspect concurrency problems. + +Why isn't Hugo's development server detecting file changes? +: In its default configuration, Hugo's file watcher may not be able detect file changes when: + + - Running Hugo within Windows Subsystem for Linux (WSL/WSL2) with project files on a Windows partition + - Running Hugo locally with project files on a removable drive + - Running Hugo locally with project files on a storage server accessed via the NFS, SMB, or CIFS protocols + + In these cases, instead of monitoring native file system events, use the `--poll` command line flag. For example, to poll the project files every 700 milliseconds, use `--poll 700ms`. + +Why is my page Store missing a value? - : The [`Store`] method on a `Page` object allows you to create a [scratch pad](g) on the given page to store and manipulate data. Values are often set 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 not determinate until Hugo renders the page content. ++: The [`Store`] method on a `Page` object allows you to create a [scratch pad](g) on the given page to store and manipulate data. Values are often set 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 not determinate 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: + + ```go-html-template + {{ $noop := .Content }} + {{ .Store.Get "mykey" }} + ``` + + You can trigger content rendering with other methods as well. See next FAQ. + +Which page methods trigger content rendering? +: The following methods on a `Page` object trigger content rendering: `Content`, `ContentWithoutSummary`, `FuzzyWordCount`, `Len`, `Plain`, `PlainWords`, `ReadingTime`, `Summary`, `Truncated`, and `WordCount`. + +> [!note] +> For other questions please visit the [forum]. A quick search of over 20,000 topics will often answer your question. Please be sure to read about [requesting help] before asking your first question. + +[`Paginate`]: /methods/page/paginate/ +[`Paginator`]: /methods/page/paginator/ +[`Store`]: /methods/page/store +[forum]: https://discourse.gohugo.io - [forum]: https://discourse.gohugo.io +[installation]: /installation/ +[requesting help]: https://discourse.gohugo.io/t/requesting-help/9132 - [requesting help]: https://discourse.gohugo.io/t/requesting-help/9132 diff --cc docs/content/en/troubleshooting/performance.md index f22758646,000000000..c52dc6966 mode 100644,000000..100644 --- a/docs/content/en/troubleshooting/performance.md +++ b/docs/content/en/troubleshooting/performance.md @@@ -1,102 -1,0 +1,102 @@@ +--- +title: Performance +description: Tools and suggestions for evaluating and improving performance. +categories: [] +keywords: [] +aliases: [/troubleshooting/build-performance/] +--- + +## Virus scanning + +Virus scanners are an essential component of system protection, but the performance impact can be severe for applications like Hugo that frequently read and write to disk. For example, with Microsoft Defender Antivirus, build times for some sites may increase by 400% or more. + +Before building a site, your virus scanner has already evaluated the files in your project directory. Scanning them again while building the site is superfluous. To improve performance, add Hugo's executable to your virus scanner's process exclusion list. + +For example, with Microsoft Defender Antivirus: + +**Start** > **Settings** > **Privacy & security** > **Windows Security** > **Open Windows Security** > **Virus & threat protection** > **Manage settings** > **Add or remove exclusions** > **Add an exclusion** > **Process** + +Then type `hugo.exe` add press the **Add** button. + +> [!note] +> Virus scanning exclusions are common, but use caution when changing these settings. See the [Microsoft Defender Antivirus documentation] for details. + +Other virus scanners have similar exclusion mechanisms. See their respective documentation. + +## Template metrics + +Hugo is fast, but inefficient templates impede performance. Enable template metrics to determine which templates take the most time, and to identify caching opportunities: + +```sh +hugo --templateMetrics --templateMetricsHints +``` + +The result will look something like this: + +```text +Template Metrics: + + cumulative average maximum cache percent cached total + duration duration duration potential cached count count template + ---------- -------- -------- --------- ------- ------ ----- -------- + 36.037476822s 135.990478ms 225.765245ms 11 0 0 265 _partials/head.html + 35.920040902s 164.018451ms 233.475072ms 0 0 0 219 articles/page.html + 34.163268129s 128.917992ms 224.816751ms 23 0 0 265 _partials/head/meta/opengraph.html + 1.041227437s 3.92916ms 186.303376ms 47 0 0 265 _partials/head/meta/schema.html + 805.628827ms 27.780304ms 114.678523ms 0 0 0 29 section.html + 624.08354ms 15.221549ms 108.420729ms 8 0 0 41 _partials/utilities/render-page-collection.html + 545.968801ms 775.523µs 105.045775ms 0 0 0 704 summary.html + 334.680981ms 1.262947ms 127.412027ms 100 0 0 265 _partials/head/js.html + 272.763205ms 2.050851ms 24.371757ms 0 0 0 133 _markup/render-codeblock.html + 163.951469ms 14.904679ms 70.267953ms 0 0 0 11 articles/section.html + 153.07021ms 577.623µs 73.593597ms 100 0 0 265 _partials/head/init.html + 150.910984ms 150.910984ms 150.910984ms 0 0 0 1 page.html + 146.785804ms 146.785804ms 146.785804ms 0 0 0 1 contact.html + 115.364617ms 115.364617ms 115.364617ms 0 0 0 1 authors/term.html + 87.392071ms 329.781µs 10.687132ms 100 0 0 265 _partials/head/css.html + 86.803122ms 86.803122ms 86.803122ms 0 0 0 1 home.html +``` + +From left to right, the columns represent: + +cumulative duration +: The cumulative time spent executing the template. + +average duration +: The average time spent executing the template. + +maximum duration +: The maximum time spent executing the template. + +cache potential - : Displayed as a percentage, any partial template with a 100% cache potential should be called with the [`partialCached`] function instead of the [`partial`] function. See the [caching](#caching) section below. ++: Displayed as a percentage, any _partial_ template with a 100% cache potential should be called with the [`partialCached`] function instead of the [`partial`] function. See the [caching](#caching) section below. + +percent cached +: The number of times the rendered templated was cached divided by the number of times the template was executed. + +cached count +: The number of times the rendered templated was cached. + +total count +: The number of times the template was executed. + +template +: The path to the template, relative to the `layouts` directory. + +> [!note] +> Hugo builds pages in parallel where multiple pages are generated simultaneously. Because of this parallelism, the sum of "cumulative duration" values is usually greater than the actual time it takes to build a site. + +## Caching + - Some partial templates such as sidebars or menus are executed many times during a site build. Depending on the content within the partial template and the desired output, the template may benefit from caching to reduce the number of executions. The [`partialCached`] template function provides caching capabilities for partial templates. ++Some _partial_ templates such as sidebars or menus are executed many times during a site build. Depending on the content within the _partial_ template and the desired output, the template may benefit from caching to reduce the number of executions. The [`partialCached`] template function provides caching capabilities for _partial_ templates. + +> [!note] +> Note that you can create cached variants of each partial by passing additional arguments to `partialCached` beyond the initial context. See the `partialCached` documentation for more details. + +## Timers + +Use the `debug.Timer` function to determine execution time for a block of code, useful for finding performance bottlenecks in templates. See [details](/functions/debug/timer/). + +[`partial`]: /functions/partials/include/ +[`partialCached`]: /functions/partials/includecached/ +[Microsoft Defender Antivirus documentation]: https://support.microsoft.com/en-us/topic/how-to-add-a-file-type-or-process-exclusion-to-windows-security-e524cbc2-3975-63c2-f9d1-7c2eb5331e53 diff --cc docs/data/docs.yaml index 62c8919a0,000000000..f6d2a96ae mode 100644,000000..100644 --- a/docs/data/docs.yaml +++ b/docs/data/docs.yaml @@@ -1,4486 -1,0 +1,4495 @@@ +chroma: + lexers: + - Aliases: + - abap + Name: ABAP + - Aliases: + - abnf + Name: ABNF + - Aliases: + - as + - actionscript + Name: ActionScript + - Aliases: + - as3 + - actionscript3 + Name: ActionScript 3 + - Aliases: + - ada + - ada95 + - ada2005 + Name: Ada + - Aliases: + - agda + Name: Agda + - Aliases: + - al + Name: AL + - Aliases: + - alloy + Name: Alloy + - Aliases: + - ng2 + Name: Angular2 + - Aliases: + - antlr + Name: ANTLR + - Aliases: + - apacheconf + - aconf + - apache + Name: ApacheConf + - Aliases: + - apl + Name: APL + - Aliases: + - applescript + Name: AppleScript + - Aliases: + - aql + Name: ArangoDB AQL + - Aliases: + - arduino + Name: Arduino + - Aliases: + - armasm + Name: ArmAsm + - Aliases: + - atl + Name: ATL + - Aliases: + - autohotkey + - ahk + Name: AutoHotkey + - Aliases: + - autoit + Name: AutoIt + - Aliases: + - awk + - gawk + - mawk + - nawk + Name: Awk + - Aliases: + - ballerina + Name: Ballerina + - Aliases: + - bash + - sh + - ksh + - zsh + - shell + Name: Bash + - Aliases: + - bash-session + - console + - shell-session + Name: Bash Session + - Aliases: + - bat + - batch + - dosbatch + - winbatch + Name: Batchfile + - Aliases: + - beef + Name: Beef + - Aliases: + - bib + - bibtex + Name: BibTeX + - Aliases: + - bicep + Name: Bicep + - Aliases: + - blitzbasic + - b3d + - bplus + Name: BlitzBasic + - Aliases: + - bnf + Name: BNF + - Aliases: + - bqn + Name: BQN + - Aliases: + - brainfuck + - bf + Name: Brainfuck + - Aliases: + - c + Name: C + - Aliases: + - csharp + - c# + Name: C# + - Aliases: + - cpp + - c++ + Name: C++ + - Aliases: + - caddyfile + - caddy + Name: Caddyfile + - Aliases: + - caddyfile-directives + - caddyfile-d + - caddy-d + Name: Caddyfile Directives + - Aliases: + - capnp + Name: Cap'n Proto + - Aliases: + - cassandra + - cql + Name: Cassandra CQL + - Aliases: + - ceylon + Name: Ceylon + - Aliases: + - cfengine3 + - cf3 + Name: CFEngine3 + - Aliases: + - cfs + Name: cfstatement + - Aliases: + - chai + - chaiscript + Name: ChaiScript + - Aliases: + - chapel + - chpl + Name: Chapel + - Aliases: + - cheetah + - spitfire + Name: Cheetah + - Aliases: + - clojure + - clj + - edn + Name: Clojure + - Aliases: + - cmake + Name: CMake + - Aliases: + - cobol + Name: COBOL + - Aliases: + - coffee-script + - coffeescript + - coffee + Name: CoffeeScript + - Aliases: + - common-lisp + - cl + - lisp + Name: Common Lisp + - Aliases: + - coq + Name: Coq ++ - Aliases: ++ - core ++ Name: Core + - Aliases: + - cr + - crystal + Name: Crystal + - Aliases: + - css + Name: CSS + - Aliases: + - csv + Name: CSV + - Aliases: + - cue + Name: CUE + - Aliases: + - cython + - pyx + - pyrex + Name: Cython + - Aliases: + - d + Name: D + - Aliases: + - dart + Name: Dart + - Aliases: + - dax + Name: Dax + - Aliases: + - desktop + - desktop_entry + Name: Desktop file + - Aliases: + - diff + - udiff + Name: Diff + - Aliases: + - django + - jinja + Name: Django/Jinja + - Aliases: + - zone + - bind + Name: dns + - Aliases: + - docker + - dockerfile + Name: Docker + - Aliases: + - dtd + Name: DTD + - Aliases: + - dylan + Name: Dylan + - Aliases: + - ebnf + Name: EBNF + - Aliases: + - elixir + - ex + - exs + Name: Elixir + - Aliases: + - elm + Name: Elm + - Aliases: + - emacs + - elisp + - emacs-lisp + Name: EmacsLisp + - Aliases: + - erlang + Name: Erlang + - Aliases: + - factor + Name: Factor + - Aliases: + - fennel + - fnl + Name: Fennel + - Aliases: + - fish + - fishshell + Name: Fish + - Aliases: + - forth + Name: Forth + - Aliases: + - fortran + - f90 + Name: Fortran + - Aliases: + - fortranfixed + Name: FortranFixed + - Aliases: + - fsharp + Name: FSharp + - Aliases: + - gas + - asm + Name: GAS + - Aliases: + - gdscript + - gd + Name: GDScript + - Aliases: + - gdscript3 + - gd3 + Name: GDScript3 + - Aliases: + - genshi + - kid + - xml+genshi + - xml+kid + Name: Genshi + - Aliases: + - html+genshi + - html+kid + Name: Genshi HTML + - Aliases: + - genshitext + Name: Genshi Text + - Aliases: + - cucumber + - Cucumber + - gherkin + - Gherkin + Name: Gherkin + - Aliases: + - gleam + Name: Gleam + - Aliases: + - glsl + Name: GLSL + - Aliases: + - gnuplot + Name: Gnuplot + - Aliases: + - go + - golang + Name: Go + - Aliases: + - go-html-template + Name: Go HTML Template + - Aliases: + - go-template + Name: Go Template + - Aliases: + - go-text-template + Name: Go Text Template + - Aliases: + - graphql + - graphqls + - gql + Name: GraphQL + - Aliases: + - groff + - nroff + - man + Name: Groff + - Aliases: + - groovy + Name: Groovy + - Aliases: + - handlebars + - hbs + Name: Handlebars + - Aliases: + - hare + Name: Hare + - Aliases: + - haskell + - hs + Name: Haskell + - Aliases: + - hx + - haxe + - hxsl + Name: Haxe + - Aliases: + - hcl + Name: HCL + - Aliases: + - hexdump + Name: Hexdump + - Aliases: + - hlb + Name: HLB + - Aliases: + - hlsl + Name: HLSL + - Aliases: + - holyc + Name: HolyC + - Aliases: + - html + Name: HTML + - Aliases: + - http + Name: HTTP + - Aliases: + - hylang + Name: Hy + - Aliases: + - idris + - idr + Name: Idris + - Aliases: + - igor + - igorpro + Name: Igor + - Aliases: + - ini + - cfg + - dosini + Name: INI + - Aliases: + - io + Name: Io + - Aliases: + - iscdhcpd + Name: ISCdhcpd + - Aliases: + - j + Name: J + - Aliases: + - janet + Name: Janet + - Aliases: + - java + Name: Java + - Aliases: + - js + - javascript + Name: JavaScript + - Aliases: + - json + Name: JSON + - Aliases: + - jsonata + Name: JSONata + - Aliases: + - jsonnet + Name: Jsonnet + - Aliases: + - julia + - jl + Name: Julia + - Aliases: + - jungle + Name: Jungle + - Aliases: + - kotlin + Name: Kotlin + - Aliases: + - lean4 + - lean + Name: Lean4 + - Aliases: + - lighty + - lighttpd + Name: Lighttpd configuration file + - Aliases: + - llvm + Name: LLVM + - Aliases: + - lua + - luau + Name: Lua + - Aliases: + - make + - makefile + - mf + - bsdmake + Name: Makefile + - Aliases: + - mako + Name: Mako + - Aliases: + - md + - mkd + Name: markdown + - Aliases: + - mason + Name: Mason + - Aliases: + - materialize + - mzsql + Name: Materialize SQL dialect + - Aliases: + - mathematica + - mma + - nb + Name: Mathematica + - Aliases: + - matlab + Name: Matlab + - Aliases: + - mcfunction + - mcf + Name: MCFunction + - Aliases: + - meson + - meson.build + Name: Meson + - Aliases: + - metal + Name: Metal + - Aliases: + - minizinc + - MZN + - mzn + Name: MiniZinc + - Aliases: + - mlir + Name: MLIR + - Aliases: + - modula2 + - m2 + Name: Modula-2 + - Aliases: + - mojo + - "\U0001F525" + Name: Mojo + - Aliases: + - monkeyc + Name: MonkeyC ++ - Aliases: ++ - moonscript ++ - moon ++ Name: MoonScript + - Aliases: + - morrowind + - mwscript + Name: MorrowindScript + - Aliases: + - myghty + Name: Myghty + - Aliases: + - mysql + - mariadb + Name: MySQL + - Aliases: + - nasm + Name: NASM + - Aliases: + - natural + Name: Natural + - Aliases: + - ndisasm + Name: NDISASM + - Aliases: + - newspeak + Name: Newspeak + - Aliases: + - nginx + Name: Nginx configuration file + - Aliases: + - nim + - nimrod + Name: Nim + - Aliases: + - nixos + - nix + Name: Nix + - Aliases: + - nsis + - nsi + - nsh + Name: NSIS + - Aliases: + - objective-c + - objectivec + - obj-c + - objc + Name: Objective-C + - Aliases: + - objectpascal + Name: ObjectPascal + - Aliases: + - ocaml + Name: OCaml + - Aliases: + - octave + Name: Octave + - Aliases: + - odin + Name: Odin + - Aliases: + - ones + - onesenterprise + - 1S + - 1S:Enterprise + Name: OnesEnterprise + - Aliases: + - openedge + - abl + - progress + - openedgeabl + Name: OpenEdge ABL + - Aliases: + - openscad + Name: OpenSCAD + - Aliases: + - org + - orgmode + Name: Org Mode + - Aliases: + - pacmanconf + Name: PacmanConf + - Aliases: + - perl + - pl + Name: Perl + - Aliases: + - php + - php3 + - php4 + - php5 + Name: PHP + - Aliases: + - phtml + Name: PHTML + - Aliases: + - pig + Name: Pig + - Aliases: + - pkgconfig + Name: PkgConfig + - Aliases: + - plpgsql + Name: PL/pgSQL + - Aliases: + - text + - plain + - no-highlight + Name: plaintext + - Aliases: + - plutus-core + - plc + Name: Plutus Core + - Aliases: + - pony + Name: Pony + - Aliases: + - postgresql + - postgres + Name: PostgreSQL SQL dialect + - Aliases: + - postscript + - postscr + Name: PostScript + - Aliases: + - pov + Name: POVRay + - Aliases: + - powerquery + - pq + Name: PowerQuery + - Aliases: + - powershell + - posh + - ps1 + - psm1 + - psd1 + - pwsh + Name: PowerShell + - Aliases: + - prolog + Name: Prolog + - Aliases: + - promela + Name: Promela + - Aliases: + - promql + Name: PromQL + - Aliases: + - java-properties + Name: properties + - Aliases: + - protobuf + - proto + Name: Protocol Buffer + - Aliases: + - prql + Name: PRQL + - Aliases: + - psl + Name: PSL + - Aliases: + - puppet + Name: Puppet + - Aliases: + - python + - py + - sage + - python3 + - py3 + Name: Python + - Aliases: + - python2 + - py2 + Name: Python 2 + - Aliases: + - qbasic + - basic + Name: QBasic + - Aliases: + - qml + - qbs + Name: QML + - Aliases: + - splus + - s + - r + Name: R + - Aliases: + - racket + - rkt + Name: Racket + - Aliases: + - ragel + Name: Ragel + - Aliases: + - perl6 + - pl6 + - raku + Name: Raku + - Aliases: + - jsx + - react + Name: react + - Aliases: + - reason + - reasonml + Name: ReasonML + - Aliases: + - registry + Name: reg + - Aliases: + - rego + Name: Rego + - Aliases: + - rst + - rest + - restructuredtext + Name: reStructuredText + - Aliases: + - rexx + - arexx + Name: Rexx + - Aliases: + - SQLRPGLE + - RPG IV + Name: RPGLE + - Aliases: + - spec + Name: RPMSpec + - Aliases: + - rb + - ruby + - duby + Name: Ruby + - Aliases: + - rust + - rs + Name: Rust + - Aliases: + - sas + Name: SAS + - Aliases: + - sass + Name: Sass + - Aliases: + - scala + Name: Scala + - Aliases: + - scheme + - scm + Name: Scheme + - Aliases: + - scilab + Name: Scilab + - Aliases: + - scss + Name: SCSS + - Aliases: + - sed + - gsed + - ssed + Name: Sed + - Aliases: + - sieve + Name: Sieve + - Aliases: + - smali + Name: Smali + - Aliases: + - smalltalk + - squeak + - st + Name: Smalltalk + - Aliases: + - smarty + Name: Smarty + - Aliases: + - snbt + Name: SNBT + - Aliases: + - snobol + Name: Snobol + - Aliases: + - sol + - solidity + Name: Solidity + - Aliases: + - sp + Name: SourcePawn + - Aliases: + - sparql + Name: SPARQL + - Aliases: + - sql + Name: SQL + - Aliases: + - squidconf + - squid.conf + - squid + Name: SquidConf + - Aliases: + - sml + Name: Standard ML + - Aliases: null + Name: stas + - Aliases: + - stylus + Name: Stylus + - Aliases: + - svelte + Name: Svelte + - Aliases: + - swift + Name: Swift + - Aliases: + - systemd + Name: SYSTEMD + - Aliases: + - systemverilog + - sv + Name: systemverilog + - Aliases: + - tablegen + Name: TableGen + - Aliases: + - tal + - uxntal + Name: Tal + - Aliases: + - tasm + Name: TASM + - Aliases: + - tcl + Name: Tcl + - Aliases: + - tcsh + - csh + Name: Tcsh + - Aliases: + - termcap + Name: Termcap + - Aliases: + - terminfo + Name: Terminfo + - Aliases: + - terraform + - tf + - hcl + Name: Terraform + - Aliases: + - tex + - latex + Name: TeX + - Aliases: + - thrift + Name: Thrift + - Aliases: + - toml + Name: TOML + - Aliases: + - tradingview + - tv + Name: TradingView + - Aliases: + - tsql + - t-sql + Name: Transact-SQL + - Aliases: + - turing + Name: Turing + - Aliases: + - turtle + Name: Turtle + - Aliases: + - twig + Name: Twig + - Aliases: + - ts + - tsx + - typescript + Name: TypeScript + - Aliases: + - typoscript + Name: TypoScript + - Aliases: + - typoscriptcssdata + Name: TypoScriptCssData + - Aliases: + - typoscripthtmldata + Name: TypoScriptHtmlData + - Aliases: + - typst + Name: Typst + - Aliases: null + Name: ucode + - Aliases: + - v + - vlang + Name: V + - Aliases: + - vsh + - vshell + Name: V shell + - Aliases: + - vala + - vapi + Name: Vala + - Aliases: + - vb.net + - vbnet + Name: VB.net + - Aliases: + - verilog + - v + Name: verilog + - Aliases: + - vhdl + Name: VHDL + - Aliases: + - vhs + - tape + - cassette + Name: VHS + - Aliases: + - vim + Name: VimL + - Aliases: + - vue + - vuejs + Name: vue + - Aliases: null + Name: WDTE + - Aliases: + - wgsl + Name: WebGPU Shading Language + - Aliases: + - vtt + Name: WebVTT + - Aliases: + - whiley + Name: Whiley + - Aliases: + - xml + Name: XML + - Aliases: + - xorg.conf + Name: Xorg + - Aliases: + - yaml + Name: YAML + - Aliases: + - yang + Name: YANG + - Aliases: + - z80 + Name: Z80 Assembly + - Aliases: + - zed + Name: Zed + - Aliases: + - zig + Name: Zig + styles: + - RPGLE + - abap + - algol + - algol_nu + - arduino + - autumn + - average + - base16-snazzy + - borland + - bw + - catppuccin-frappe + - catppuccin-latte + - catppuccin-macchiato + - catppuccin-mocha + - colorful + - doom-one + - doom-one2 + - dracula + - emacs + - evergarden + - friendly + - fruity + - github + - github-dark + - gruvbox + - gruvbox-light + - hr_high_contrast + - hrdark + - igor + - lovelace + - manni + - modus-operandi + - modus-vivendi + - monokai + - monokailight + - murphy + - native + - nord + - nordic + - onedark + - onesenterprise + - paraiso-dark + - paraiso-light + - pastie + - perldoc + - pygments + - rainbow_dash + - rose-pine + - rose-pine-dawn + - rose-pine-moon + - rrt + - solarized-dark + - solarized-dark256 + - solarized-light + - swapoff + - tango + - tokyonight-day + - tokyonight-moon + - tokyonight-night + - tokyonight-storm + - trac + - vim + - vs + - vulcan + - witchhazel + - xcode + - xcode-dark +config: + HTTPCache: + cache: + for: + excludes: + - '**' + includes: null + polls: + - disable: true + for: + excludes: null + includes: + - '**' + high: 0s + low: 0s + archeTypeDir: archetypes + assetDir: assets + author: null + baseURL: "" + build: + buildStats: + disableClasses: false + disableIDs: false + disableTags: false + enable: false + cacheBusters: + - source: (postcss|tailwind)\.config\.js + target: (css|styles|scss|sass) + noJSConfigInAssets: false + useResourceCacheWhen: fallback + buildDrafts: false + buildExpired: false + buildFuture: false + cacheDir: "" + caches: + assets: + dir: :resourceDir/_gen + maxAge: -1 + getcsv: + dir: :cacheDir/:project + maxAge: -1 + getjson: + dir: :cacheDir/:project + maxAge: -1 + getresource: + dir: :cacheDir/:project + maxAge: -1 + images: + dir: :resourceDir/_gen + maxAge: -1 + misc: + dir: :cacheDir/:project + maxAge: -1 + modules: + dir: :cacheDir/modules + maxAge: -1 + canonifyURLs: false + capitalizeListTitles: true + cascade: [] + cleanDestinationDir: false + contentDir: content + contentTypes: + text/asciidoc: {} + text/html: {} + text/markdown: {} + text/org: {} + text/pandoc: {} + text/rst: {} + copyright: "" + dataDir: data + defaultContentLanguage: en + defaultContentLanguageInSubdir: false + defaultOutputFormat: html + deployment: + confirm: false + dryRun: false + force: false + invalidateCDN: true + matchers: null + maxDeletes: 256 + order: null + target: "" + targets: null + workers: 10 + disableAliases: false + disableDefaultLanguageRedirect: false + disableHugoGeneratorInject: false + disableKinds: null + disableLanguages: null + disableLiveReload: false + disablePathToLower: false + enableEmoji: false + enableGitInfo: false + enableMissingTranslationPlaceholders: false + enableRobotsTXT: false + environment: production + frontmatter: + date: + - date + - publishdate + - pubdate + - published + - lastmod + - modified + expiryDate: + - expirydate + - unpublishdate + lastmod: + - :git + - lastmod + - modified + - date + - publishdate + - pubdate + - published + publishDate: + - publishdate + - pubdate + - published + - date + hasCJKLanguage: false + i18nDir: i18n + ignoreCache: false + ignoreFiles: null + ignoreLogs: null + ignoreVendorPaths: "" + imaging: + bgColor: '#ffffff' + hint: photo + quality: 75 + resampleFilter: box + languageCode: "" + languages: + en: + disabled: false + languageCode: "" + languageDirection: "" + languageName: "" + title: "" + weight: 0 + layoutDir: layouts + mainSections: null + markup: + asciidocExt: + attributes: {} + backend: html5 + extensions: [] + failureLevel: fatal + noHeaderOrFooter: true + preserveTOC: false + safeMode: unsafe + sectionNumbers: false + trace: false + verbose: false + workingFolderCurrent: false + defaultMarkdownHandler: goldmark + goldmark: + duplicateResourceFiles: false + extensions: + cjk: + eastAsianLineBreaks: false + eastAsianLineBreaksStyle: simple + enable: false + escapedSpace: false + definitionList: true + extras: + delete: + enable: false + insert: + enable: false + mark: + enable: false + subscript: + enable: false + superscript: + enable: false + footnote: true + linkify: true + linkifyProtocol: https + passthrough: + delimiters: + block: [] + inline: [] + enable: false + strikethrough: true + table: true + taskList: true + typographer: + apostrophe: '’' + disable: false + ellipsis: '…' + emDash: '—' + enDash: '–' + leftAngleQuote: '«' + leftDoubleQuote: '“' + leftSingleQuote: '‘' + rightAngleQuote: '»' + rightDoubleQuote: '”' + rightSingleQuote: '’' + parser: + attribute: + block: false + title: true + autoDefinitionTermID: false + autoHeadingID: true + autoIDType: github + wrapStandAloneImageWithinParagraph: true + renderHooks: + image: + enableDefault: false ++ useEmbedded: auto + link: + enableDefault: false ++ useEmbedded: auto + renderer: + hardWraps: false + unsafe: false + xhtml: false + highlight: + anchorLineNos: false + codeFences: true + guessSyntax: false + hl_Lines: "" + hl_inline: false + lineAnchors: "" + lineNoStart: 1 + lineNos: false + lineNumbersInTable: true + noClasses: true + style: monokai + tabWidth: 4 + wrapperClass: highlight + tableOfContents: + endLevel: 3 + ordered: false + startLevel: 2 + mediaTypes: + application/json: + delimiter: . + suffixes: + - json + application/manifest+json: + delimiter: . + suffixes: + - webmanifest + application/octet-stream: + delimiter: . + application/pdf: + delimiter: . + suffixes: + - pdf + application/rss+xml: + delimiter: . + suffixes: + - xml + - rss + application/toml: + delimiter: . + suffixes: + - toml + application/wasm: + delimiter: . + suffixes: + - wasm + application/xml: + delimiter: . + suffixes: + - xml + application/yaml: + delimiter: . + suffixes: + - yaml + - yml + font/otf: + delimiter: . + suffixes: + - otf + font/ttf: + delimiter: . + suffixes: + - ttf + image/bmp: + delimiter: . + suffixes: + - bmp + image/gif: + delimiter: . + suffixes: + - gif + image/jpeg: + delimiter: . + suffixes: + - jpg + - jpeg + - jpe + - jif + - jfif + image/png: + delimiter: . + suffixes: + - png + image/svg+xml: + delimiter: . + suffixes: + - svg + image/tiff: + delimiter: . + suffixes: + - tif + - tiff + image/webp: + delimiter: . + suffixes: + - webp + text/asciidoc: + delimiter: . + suffixes: + - adoc + - asciidoc + - ad + text/calendar: + delimiter: . + suffixes: + - ics + text/css: + delimiter: . + suffixes: + - css + text/csv: + delimiter: . + suffixes: + - csv + text/html: + delimiter: . + suffixes: + - html + - htm + text/javascript: + delimiter: . + suffixes: + - js + - jsm + - mjs + text/jsx: + delimiter: . + suffixes: + - jsx + text/markdown: + delimiter: . + suffixes: + - md + - mdown + - markdown + text/org: + delimiter: . + suffixes: + - org + text/pandoc: + delimiter: . + suffixes: + - pandoc + - pdc + text/plain: + delimiter: . + suffixes: + - txt + text/rst: + delimiter: . + suffixes: + - rst + text/tsx: + delimiter: . + suffixes: + - tsx + text/typescript: + delimiter: . + suffixes: + - ts + text/x-gotmpl: + delimiter: . + suffixes: + - gotmpl + text/x-sass: + delimiter: . + suffixes: + - sass + text/x-scss: + delimiter: . + suffixes: + - scss + video/3gpp: + delimiter: . + suffixes: + - 3gpp + - 3gp + video/mp4: + delimiter: . + suffixes: + - mp4 + video/mpeg: + delimiter: . + suffixes: + - mpg + - mpeg + video/ogg: + delimiter: . + suffixes: + - ogv + video/webm: + delimiter: . + suffixes: + - webm + video/x-msvideo: + delimiter: . + suffixes: + - avi + menus: {} + minify: + disableCSS: false + disableHTML: false + disableJS: false + disableJSON: false + disableSVG: false + disableXML: false + minifyOutput: false + tdewolff: + css: + inline: false + keepCSS2: true + precision: 0 + html: + keepComments: false + keepConditionalComments: false + keepDefaultAttrVals: true + keepDocumentTags: true + keepEndTags: true + keepQuotes: false + keepSpecialComments: true + keepWhitespace: false + templateDelims: + - "" + - "" + js: + keepVarNames: false + precision: 0 + version: 2022 + json: + keepNumbers: false + precision: 0 + svg: + inline: false + keepComments: false + precision: 0 + xml: + keepWhitespace: false + module: + auth: "" + hugoVersion: + extended: false + max: "" + min: "" + imports: null + mounts: + - disableWatch: false + excludeFiles: null + includeFiles: null + lang: "" + source: content + target: content + - disableWatch: false + excludeFiles: null + includeFiles: null + lang: "" + source: data + target: data + - disableWatch: false + excludeFiles: null + includeFiles: null + lang: "" + source: layouts + target: layouts + - disableWatch: false + excludeFiles: null + includeFiles: null + lang: "" + source: i18n + target: i18n + - disableWatch: false + excludeFiles: null + includeFiles: null + lang: "" + source: archetypes + target: archetypes + - disableWatch: false + excludeFiles: null + includeFiles: null + lang: "" + source: assets + target: assets + - disableWatch: false + excludeFiles: null + includeFiles: null + lang: "" + source: static + target: static + noProxy: none + noVendor: "" + params: null + private: '*.*' + proxy: direct + replacements: null + vendorClosest: false + workspace: "off" + newContentEditor: "" + noBuildLock: false + noChmod: false + noTimes: false + outputFormats: + "404": + baseName: "" + isHTML: true + isPlainText: false + mediaType: text/html + noUgly: false + notAlternative: true + path: "" + permalinkable: true + protocol: "" + rel: "" + root: false + ugly: true + weight: 0 + alias: + baseName: "" + isHTML: true + isPlainText: false + mediaType: text/html + noUgly: false + notAlternative: false + path: "" + permalinkable: false + protocol: "" + rel: "" + root: false + ugly: true + weight: 0 + amp: + baseName: index + isHTML: true + isPlainText: false + mediaType: text/html + noUgly: false + notAlternative: false + path: amp + permalinkable: true + protocol: "" + rel: amphtml + root: false + ugly: false + weight: 0 + calendar: + baseName: index + isHTML: false + isPlainText: true + mediaType: text/calendar + noUgly: false + notAlternative: false + path: "" + permalinkable: false + protocol: webcal:// + rel: alternate + root: false + ugly: false + weight: 0 + css: + baseName: styles + isHTML: false + isPlainText: true + mediaType: text/css + noUgly: false + notAlternative: true + path: "" + permalinkable: false + protocol: "" + rel: stylesheet + root: false + ugly: false + weight: 0 + csv: + baseName: index + isHTML: false + isPlainText: true + mediaType: text/csv + noUgly: false + notAlternative: false + path: "" + permalinkable: false + protocol: "" + rel: alternate + root: false + ugly: false + weight: 0 + gotmpl: + baseName: "" + isHTML: false + isPlainText: true + mediaType: text/x-gotmpl + noUgly: false + notAlternative: true + path: "" + permalinkable: false + protocol: "" + rel: "" + root: false + ugly: false + weight: 0 + html: + baseName: index + isHTML: true + isPlainText: false + mediaType: text/html + noUgly: false + notAlternative: false + path: "" + permalinkable: true + protocol: "" + rel: canonical + root: false + ugly: false + weight: 10 + json: + baseName: index + isHTML: false + isPlainText: true + mediaType: application/json + noUgly: false + notAlternative: false + path: "" + permalinkable: false + protocol: "" + rel: alternate + root: false + ugly: false + weight: 0 + markdown: + baseName: index + isHTML: false + isPlainText: true + mediaType: text/markdown + noUgly: false + notAlternative: false + path: "" + permalinkable: false + protocol: "" + rel: alternate + root: false + ugly: false + weight: 0 + robots: + baseName: robots + isHTML: false + isPlainText: true + mediaType: text/plain + noUgly: false + notAlternative: false + path: "" + permalinkable: false + protocol: "" + rel: alternate + root: true + ugly: false + weight: 0 + rss: + baseName: index + isHTML: false + isPlainText: false + mediaType: application/rss+xml + noUgly: true + notAlternative: false + path: "" + permalinkable: false + protocol: "" + rel: alternate + root: false + ugly: false + weight: 0 + sitemap: + baseName: sitemap + isHTML: false + isPlainText: false + mediaType: application/xml + noUgly: false + notAlternative: false + path: "" + permalinkable: false + protocol: "" + rel: sitemap + root: false + ugly: true + weight: 0 + sitemapindex: + baseName: sitemap + isHTML: false + isPlainText: false + mediaType: application/xml + noUgly: false + notAlternative: false + path: "" + permalinkable: false + protocol: "" + rel: sitemap + root: true + ugly: true + weight: 0 + webappmanifest: + baseName: manifest + isHTML: false + isPlainText: true + mediaType: application/manifest+json + noUgly: false + notAlternative: true + path: "" + permalinkable: false + protocol: "" + rel: manifest + root: false + ugly: false + weight: 0 + outputs: + home: + - html + - rss + page: + - html + rss: + - rss + section: + - html + - rss + taxonomy: + - html + - rss + term: + - html + - rss + page: + nextPrevInSectionSortOrder: desc + nextPrevSortOrder: desc + paginate: 0 + paginatePath: "" + pagination: + disableAliases: false + pagerSize: 10 + path: page + panicOnWarning: false + params: {} + permalinks: + page: {} + section: {} + taxonomy: {} + term: {} + pluralizeListTitles: true + printI18nWarnings: false + printPathWarnings: false + printUnusedTemplates: false + privacy: + disqus: + disable: false + googleAnalytics: + disable: false + respectDoNotTrack: false + instagram: + disable: false + simple: false + twitter: + disable: false + enableDNT: false + simple: false + vimeo: + disable: false + enableDNT: false + simple: false + x: + disable: false + enableDNT: false + simple: false + youTube: + disable: false + privacyEnhanced: false + publishDir: public + refLinksErrorLevel: "" + refLinksNotFoundURL: "" + related: + includeNewer: false + indices: + - applyFilter: false + cardinalityThreshold: 0 + name: keywords + pattern: "" + toLower: false + type: basic + weight: 100 + - applyFilter: false + cardinalityThreshold: 0 + name: date + pattern: "" + toLower: false + type: basic + weight: 10 + - applyFilter: false + cardinalityThreshold: 0 + name: tags + pattern: "" + toLower: false + type: basic + weight: 80 + threshold: 80 + toLower: false + relativeURLs: false + removePathAccents: false + renderSegments: null + resourceDir: resources + sectionPagesMenu: "" + security: + enableInlineShortcodes: false + exec: + allow: + - ^(dart-)?sass(-embedded)?$ + - ^go$ + - ^git$ + - ^npx$ + - ^postcss$ + - ^tailwindcss$ + osEnv: + - (?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+|(XDG_CONFIG_)?HOME|USERPROFILE|SSH_AUTH_SOCK|DISPLAY|LANG|SYSTEMDRIVE)$ + funcs: + getenv: + - ^HUGO_ + - ^CI$ + http: + mediaTypes: null + methods: + - (?i)GET|POST + urls: + - .* + segments: null + server: + headers: null + redirects: + - force: false + from: /** + fromHeaders: null + fromRe: "" + status: 404 + to: /404.html + services: + disqus: + shortname: "" + googleAnalytics: + id: "" + instagram: + accessToken: "" + disableInlineCSS: false + rss: + limit: -1 + twitter: + disableInlineCSS: false + x: + disableInlineCSS: false + sitemap: + changeFreq: "" + disable: false + filename: sitemap.xml + priority: -1 + social: null + staticDir: + - static + staticDir0: null + staticDir1: null + staticDir2: null + staticDir3: null + staticDir4: null + staticDir5: null + staticDir6: null + staticDir7: null + staticDir8: null + staticDir9: null + staticDir10: null + summaryLength: 70 + taxonomies: + category: categories + tag: tags + templateMetrics: false + templateMetricsHints: false + theme: null + themesDir: themes + timeZone: "" + timeout: 60s + title: "" + titleCaseStyle: AP + uglyURLs: null + workingDir: "" +config_helpers: + mergeStrategy: + build: + _merge: none + caches: + _merge: none + cascade: + _merge: none + contenttypes: + _merge: none + deployment: + _merge: none + frontmatter: + _merge: none + httpcache: + _merge: none + imaging: + _merge: none + languages: + _merge: none + en: + _merge: none + menus: + _merge: shallow + params: + _merge: deep + markup: + _merge: none + mediatypes: + _merge: shallow + menus: + _merge: shallow + minify: + _merge: none + module: + _merge: none + outputformats: + _merge: shallow + outputs: + _merge: none + page: + _merge: none + pagination: + _merge: none + params: + _merge: deep + permalinks: + _merge: none + privacy: + _merge: none + related: + _merge: none + security: + _merge: none + segments: + _merge: none + server: + _merge: none + services: + _merge: none + sitemap: + _merge: none + taxonomies: + _merge: none +output: + layouts: {} +tpl: + funcs: + cast: + ToFloat: + Aliases: + - float + Args: + - v + Description: ToFloat converts v to a float. + Examples: + - - '{{ "1234" | float | printf "%T" }}' + - float64 + ToInt: + Aliases: + - int + Args: + - v + Description: ToInt converts v to an int. + Examples: + - - '{{ "1234" | int | printf "%T" }}' + - int + ToString: + Aliases: + - string + Args: + - v + Description: ToString converts v to a string. + Examples: + - - '{{ 1234 | string | printf "%T" }}' + - string + collections: + After: + Aliases: + - after + Args: + - "n" + - l + Description: After returns all the items after the first n items in list l. + Examples: [] + Append: + Aliases: + - append + Args: + - args + Description: "Append appends args up to the last one to the slice in the last + argument.\nThis construct allows template constructs like this:\n\n\t{{ + $pages = $pages | append $p2 $p1 }}\n\nNote that with 2 arguments where + both are slices of the same type,\nthe first slice will be appended to the + second:\n\n\t{{ $pages = $pages | append .Site.RegularPages }}" + Examples: [] + Apply: + Aliases: + - apply + Args: + - ctx + - c + - fname + - args + Description: Apply takes an array or slice c and returns a new slice with + the function fname applied over it. + Examples: [] + Complement: + Aliases: + - complement + Args: + - ls + Description: "Complement gives the elements in the last element of ls that + are not in\nany of the others.\n\nAll elements of ls must be slices or arrays + of comparable types.\n\nThe reasoning behind this rather clumsy API is so + we can do this in the templates:\n\n\t{{ $c := .Pages | complement $last4 + }}" + Examples: + - - '{{ slice "a" "b" "c" "d" "e" "f" | complement (slice "b" "c") (slice + "d" "e") }}' + - '[a f]' + Delimit: + Aliases: + - delimit + Args: + - ctx + - l + - sep + - last + Description: |- + Delimit takes a given list l and returns a string delimited by sep. + If last is passed to the function, it will be used as the final delimiter. + Examples: + - - '{{ delimit (slice "A" "B" "C") ", " " and " }}' + - A, B and C + Dictionary: + Aliases: + - dict + Args: + - values + Description: |- + Dictionary creates a new map from the given parameters by + treating values as key-value pairs. The number of values must be even. + The keys can be string slices, which will create the needed nested structure. + Examples: [] + First: + Aliases: + - first + Args: + - limit + - l + Description: First returns the first limit items in list l. + Examples: [] + Group: + Aliases: + - group + Args: + - key + - items + Description: |- + Group groups a set of items by the given key. + This is currently only supported for Pages. + Examples: [] + In: + Aliases: + - in + Args: + - l + - v + Description: In returns whether v is in the list l. l may be an array or + slice. + Examples: + - - '{{ if in "this string contains a substring" "substring" }}Substring found!{{ + end }}' + - Substring found! + Index: + Aliases: + - index + Args: + - item + - args + Description: |- + Index returns the result of indexing its first argument by the following + arguments. Thus "index x 1 2 3" is, in Go syntax, x[1][2][3]. Each + indexed item must be a map, slice, or array. + + Adapted from Go stdlib src/text/template/funcs.go. + + We deviate from the stdlib mostly because of https://github.com/golang/go/issues/14751. + Examples: [] + Intersect: + Aliases: + - intersect + Args: + - l1 + - l2 + Description: |- + Intersect returns the common elements in the given sets, l1 and l2. l1 and + l2 must be of the same type and may be either arrays or slices. + Examples: [] + IsSet: + Aliases: + - isSet + - isset + Args: + - c + - key + Description: |- + IsSet returns whether a given array, channel, slice, or map in c has the given key + defined. + Examples: [] + KeyVals: + Aliases: + - keyVals + Args: + - key + - values + Description: KeyVals creates a key and values wrapper. + Examples: + - - '{{ keyVals "key" "a" "b" }}' + - 'key: [a b]' + Last: + Aliases: + - last + Args: + - limit + - l + Description: Last returns the last limit items in the list l. + Examples: [] + Merge: + Aliases: + - merge + Args: + - params + Description: |- + Merge creates a copy of the final parameter in params and merges the preceding + parameters into it in reverse order. + + Currently only maps are supported. Key handling is case insensitive. + Examples: + - - '{{ dict "title" "Hugo Rocks!" | collections.Merge (dict "title" "Default + Title" "description" "Yes, Hugo Rocks!") | sort }}' + - '[Yes, Hugo Rocks! Hugo Rocks!]' + - - '{{ merge (dict "title" "Default Title" "description" "Yes, Hugo Rocks!") + (dict "title" "Hugo Rocks!") | sort }}' + - '[Yes, Hugo Rocks! Hugo Rocks!]' + - - '{{ merge (dict "title" "Default Title" "description" "Yes, Hugo Rocks!") + (dict "title" "Hugo Rocks!") (dict "extra" "For reals!") | sort }}' + - '[Yes, Hugo Rocks! For reals! Hugo Rocks!]' + NewScratch: + Aliases: + - newScratch + Args: null + Description: |- + NewScratch creates a new Scratch which can be used to store values in a + thread safe way. + Examples: + - - '{{ $scratch := newScratch }}{{ $scratch.Add "b" 2 }}{{ $scratch.Add "b" + 2 }}{{ $scratch.Get "b" }}' + - "4" + Querify: + Aliases: + - querify + Args: + - params + Description: |- + Querify returns a URL query string composed of the given key-value pairs, + encoded and sorted by key. + Examples: + - - '{{ (querify "foo" 1 "bar" 2 "baz" "with spaces" "qux" "this&that=those") + | safeHTML }}' + - bar=2&baz=with+spaces&foo=1&qux=this%26that%3Dthose + - - Search + - Search + - - '{{ slice "foo" 1 "bar" 2 | querify | safeHTML }}' + - bar=2&foo=1 + Reverse: + Aliases: null + Args: null + Description: "" + Examples: null + Seq: + Aliases: + - seq + Args: + - args + Description: "Seq creates a sequence of integers from args. It's named and + used as GNU's seq.\n\nExamples:\n\n\t3 => 1, 2, 3\n\t1 2 4 => 1, 3\n\t-3 + => -1, -2, -3\n\t1 4 => 1, 2, 3, 4\n\t1 -2 => 1, 0, -1, -2" + Examples: + - - '{{ seq 3 }}' + - '[1 2 3]' + Shuffle: + Aliases: + - shuffle + Args: + - l + Description: Shuffle returns list l in a randomized order. + Examples: [] + Slice: + Aliases: + - slice + Args: + - args + Description: Slice returns a slice of all passed arguments. + Examples: + - - '{{ slice "B" "C" "A" | sort }}' + - '[A B C]' + Sort: + Aliases: + - sort + Args: + - ctx + - l + - args + Description: Sort returns a sorted copy of the list l. + Examples: [] + SymDiff: + Aliases: + - symdiff + Args: + - s2 + - s1 + Description: |- + SymDiff returns the symmetric difference of s1 and s2. + Arguments must be either a slice or an array of comparable types. + Examples: + - - '{{ slice 1 2 3 | symdiff (slice 3 4) }}' + - '[1 2 4]' + Union: + Aliases: + - union + Args: + - l1 + - l2 + Description: |- + Union returns the union of the given sets, l1 and l2. l1 and + l2 must be of the same type and may be either arrays or slices. + If l1 and l2 aren't of the same type then l1 will be returned. + If either l1 or l2 is nil then the non-nil list will be returned. + Examples: + - - '{{ union (slice 1 2 3) (slice 3 4 5) }}' + - '[1 2 3 4 5]' + Uniq: + Aliases: + - uniq + Args: + - l + Description: Uniq returns a new list with duplicate elements in the list l + removed. + Examples: + - - '{{ slice 1 2 3 2 | uniq }}' + - '[1 2 3]' + Where: + Aliases: + - where + Args: + - ctx + - c + - key + - args + Description: Where returns a filtered subset of collection c. + Examples: [] + compare: + Conditional: + Aliases: + - cond + Args: + - cond + - v1 + - v2 + Description: |- + Conditional can be used as a ternary operator. + + It returns v1 if cond is true, else v2. + Examples: + - - '{{ cond (eq (add 2 2) 4) "2+2 is 4" "what?" | safeHTML }}' + - 2+2 is 4 + Default: + Aliases: + - default + Args: + - defaultv + - givenv + Description: |- + Default checks whether a givenv is set and returns the default value defaultv if it + is not. "Set" in this context means non-zero for numeric types and times; + non-zero length for strings, arrays, slices, and maps; + any boolean or struct value; or non-nil for any other types. + Examples: + - - '{{ "Hugo Rocks!" | default "Hugo Rules!" }}' + - Hugo Rocks! + - - '{{ "" | default "Hugo Rules!" }}' + - Hugo Rules! + Eq: + Aliases: + - eq + Args: + - first + - others + Description: Eq returns the boolean truth of arg1 == arg2 || arg1 == arg3 + || arg1 == arg4. + Examples: + - - '{{ if eq .Section "blog" }}current-section{{ end }}' + - current-section + Ge: + Aliases: + - ge + Args: + - first + - others + Description: Ge returns the boolean truth of arg1 >= arg2 && arg1 >= arg3 + && arg1 >= arg4. + Examples: + - - '{{ if ge hugo.Version "0.80" }}Reasonable new Hugo version!{{ end }}' + - Reasonable new Hugo version! + Gt: + Aliases: + - gt + Args: + - first + - others + Description: Gt returns the boolean truth of arg1 > arg2 && arg1 > arg3 && + arg1 > arg4. + Examples: [] + Le: + Aliases: + - le + Args: + - first + - others + Description: Le returns the boolean truth of arg1 <= arg2 && arg1 <= arg3 + && arg1 <= arg4. + Examples: [] + Lt: + Aliases: + - lt + Args: + - first + - others + Description: Lt returns the boolean truth of arg1 < arg2 && arg1 < arg3 && + arg1 < arg4. + Examples: [] + LtCollate: + Aliases: null + Args: null + Description: "" + Examples: null + Ne: + Aliases: + - ne + Args: + - first + - others + Description: Ne returns the boolean truth of arg1 != arg2 && arg1 != arg3 + && arg1 != arg4. + Examples: [] + crypto: + FNV32a: + Aliases: null + Args: null + Description: "" + Examples: null + HMAC: + Aliases: + - hmac + Args: + - h + - k + - m + - e + Description: HMAC returns a cryptographic hash that uses a key to sign a message. + Examples: + - - '{{ hmac "sha256" "Secret key" "Hello world, gophers!" }}' + - b6d11b6c53830b9d87036272ca9fe9d19306b8f9d8aa07b15da27d89e6e34f40 + MD5: + Aliases: + - md5 + Args: + - v + Description: MD5 hashes the v and returns its MD5 checksum. + Examples: + - - '{{ md5 "Hello world, gophers!" }}' + - b3029f756f98f79e7f1b7f1d1f0dd53b + - - '{{ crypto.MD5 "Hello world, gophers!" }}' + - b3029f756f98f79e7f1b7f1d1f0dd53b + SHA1: + Aliases: + - sha1 + Args: + - v + Description: SHA1 hashes v and returns its SHA1 checksum. + Examples: + - - '{{ sha1 "Hello world, gophers!" }}' + - c8b5b0e33d408246e30f53e32b8f7627a7a649d4 + SHA256: + Aliases: + - sha256 + Args: + - v + Description: SHA256 hashes v and returns its SHA256 checksum. + Examples: + - - '{{ sha256 "Hello world, gophers!" }}' + - 6ec43b78da9669f50e4e422575c54bf87536954ccd58280219c393f2ce352b46 + css: + PostCSS: + Aliases: + - postCSS + Args: + - args + Description: PostCSS processes the given Resource with PostCSS. + Examples: [] + Quoted: + Aliases: null + Args: null + Description: "" + Examples: null + Sass: + Aliases: + - toCSS + Args: + - args + Description: Sass processes the given Resource with SASS. + Examples: [] + TailwindCSS: + Aliases: null + Args: null + Description: "" + Examples: null + Unquoted: + Aliases: null + Args: null + Description: "" + Examples: null + data: + GetCSV: + Aliases: + - getCSV + Args: + - sep + - args + Description: |- + GetCSV expects the separator sep and one or n-parts of a URL to a resource which + can either be a local or a remote one. + The data separator can be a comma, semi-colon, pipe, etc, but only one character. + If you provide multiple parts for the URL they will be joined together to the final URL. + GetCSV returns nil or a slice slice to use in a short code. + Examples: [] + GetJSON: + Aliases: + - getJSON + Args: + - args + Description: |- + GetJSON expects one or n-parts of a URL in args to a resource which can either be a local or a remote one. + If you provide multiple parts they will be joined together to the final URL. + GetJSON returns nil or parsed JSON to use in a short code. + Examples: [] + debug: + Dump: + Aliases: null + Args: + - val + Description: |- + Dump returns a object dump of val as a string. + Note that not every value passed to Dump will print so nicely, but + we'll improve on that. + + We recommend using the "go" Chroma lexer to format the output + nicely. + + Also note that the output from Dump may change from Hugo version to the next, + so don't depend on a specific output. + Examples: + - - |- + {{ $m := newScratch }} + {{ $m.Set "Hugo" "Rocks!" }} + {{ $m.Values | debug.Dump | safeHTML }} + - |- + { + "Hugo": "Rocks!" + } + TestDeprecationErr: + Aliases: null + Args: null + Description: "" + Examples: null + TestDeprecationInfo: + Aliases: null + Args: null + Description: "" + Examples: null + TestDeprecationWarn: + Aliases: null + Args: null + Description: "" + Examples: null + Timer: + Aliases: null + Args: null + Description: "" + Examples: null + VisualizeSpaces: + Aliases: null + Args: null + Description: "" + Examples: null + diagrams: + Goat: + Aliases: null + Args: null + Description: "" + Examples: null + encoding: + Base64Decode: + Aliases: + - base64Decode + Args: + - content + Description: Base64Decode returns the base64 decoding of the given content. + Examples: + - - '{{ "SGVsbG8gd29ybGQ=" | base64Decode }}' + - Hello world + - - '{{ 42 | base64Encode | base64Decode }}' + - "42" + Base64Encode: + Aliases: + - base64Encode + Args: + - content + Description: Base64Encode returns the base64 encoding of the given content. + Examples: + - - '{{ "Hello world" | base64Encode }}' + - SGVsbG8gd29ybGQ= + Jsonify: + Aliases: + - jsonify + Args: + - args + Description: |- + Jsonify encodes a given object to JSON. To pretty print the JSON, pass a map + or dictionary of options as the first value in args. 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. + Examples: + - - '{{ (slice "A" "B" "C") | jsonify }}' + - '["A","B","C"]' + - - '{{ (slice "A" "B" "C") | jsonify (dict "indent" " ") }}' + - |- + [ + "A", + "B", + "C" + ] + fmt: + Errorf: + Aliases: + - errorf + Args: + - format + - args + Description: |- + Errorf formats args according to a format specifier and logs an ERROR. + It returns an empty string. + Examples: + - - '{{ errorf "%s." "failed" }}' + - "" + Erroridf: + Aliases: + - erroridf + Args: + - id + - format + - args + Description: |- + Erroridf formats args according to a format specifier and logs an ERROR and + an information text that the error with the given id can be suppressed in config. + It returns an empty string. + Examples: + - - '{{ erroridf "my-err-id" "%s." "failed" }}' + - "" + Errormf: + Aliases: null + Args: null + Description: "" + Examples: null + Print: + Aliases: + - print + Args: + - args + Description: Print returns a string representation of args. + Examples: + - - '{{ print "works!" }}' + - works! + Printf: + Aliases: + - printf + Args: + - format + - args + Description: Printf returns string representation of args formatted with the + layout in format. + Examples: + - - '{{ printf "%s!" "works" }}' + - works! + Println: + Aliases: + - println + Args: + - args + Description: Println returns string representation of args ending with a + newline. + Examples: + - - '{{ println "works!" }}' + - | + works! + Warnf: + Aliases: + - warnf + Args: + - format + - args + Description: |- + Warnf formats args according to a format specifier and logs a WARNING. + It returns an empty string. + Examples: + - - '{{ warnf "%s." "warning" }}' + - "" + Warnidf: + Aliases: + - warnidf + Args: + - id + - format + - args + Description: |- + Warnidf formats args according to a format specifier and logs an WARNING and + an information text that the warning with the given id can be suppressed in config. + It returns an empty string. + Examples: + - - '{{ warnidf "my-warn-id" "%s." "warning" }}' + - "" + Warnmf: + Aliases: null + Args: null + Description: "" + Examples: null + hash: + FNV32a: + Aliases: null + Args: + - v + Description: FNV32a hashes v using fnv32a algorithm. + Examples: + - - '{{ hash.FNV32a "Hugo Rocks!!" }}' + - "1515779328" + XxHash: + Aliases: + - xxhash + Args: + - v + Description: XxHash returns the xxHash of the input string. + Examples: + - - '{{ hash.XxHash "The quick brown fox jumps over the lazy dog" }}' + - 0b242d361fda71bc + hugo: + Deps: + Aliases: null + Args: null + Description: "" + Examples: null + Generator: + Aliases: null + Args: null + Description: "" + Examples: null + IsDevelopment: + Aliases: null + Args: null + Description: "" + Examples: null + IsExtended: + Aliases: null + Args: null + Description: "" + Examples: null + IsMultiHost: + Aliases: null + Args: null + Description: "" + Examples: null + IsMultihost: + Aliases: null + Args: null + Description: "" + Examples: null + IsMultilingual: + Aliases: null + Args: null + Description: "" + Examples: null + IsProduction: + Aliases: null + Args: null + Description: "" + Examples: null + IsServer: + Aliases: null + Args: null + Description: "" + Examples: null + Store: + Aliases: null + Args: null + Description: "" + Examples: null + Version: + Aliases: null + Args: null + Description: "" + Examples: null + WorkingDir: + Aliases: null + Args: null + Description: "" + Examples: null + images: + AutoOrient: + Aliases: null + Args: null + Description: "" + Examples: null + Brightness: + Aliases: null + Args: null + Description: "" + Examples: null + ColorBalance: + Aliases: null + Args: null + Description: "" + Examples: null + Colorize: + Aliases: null + Args: null + Description: "" + Examples: null + Config: + Aliases: + - imageConfig + Args: + - path + Description: |- + Config returns the image.Config for the specified path relative to the + working directory. + Examples: [] + Contrast: + Aliases: null + Args: null + Description: "" + Examples: null + Dither: + Aliases: null + Args: null + Description: "" + Examples: null + Filter: + Aliases: null + Args: null + Description: "" + Examples: null + Gamma: + Aliases: null + Args: null + Description: "" + Examples: null + GaussianBlur: + Aliases: null + Args: null + Description: "" + Examples: null + Grayscale: + Aliases: null + Args: null + Description: "" + Examples: null + Hue: + Aliases: null + Args: null + Description: "" + Examples: null + Invert: + Aliases: null + Args: null + Description: "" + Examples: null + Mask: + Aliases: null + Args: null + Description: "" + Examples: null + Opacity: + Aliases: null + Args: null + Description: "" + Examples: null + Overlay: + Aliases: null + Args: null + Description: "" + Examples: null + Padding: + Aliases: null + Args: null + Description: "" + Examples: null + Pixelate: + Aliases: null + Args: null + Description: "" + Examples: null + Process: + Aliases: null + Args: null + Description: "" + Examples: null + QR: + Aliases: null + Args: null + Description: "" + Examples: null + Saturation: + Aliases: null + Args: null + Description: "" + Examples: null + Sepia: + Aliases: null + Args: null + Description: "" + Examples: null + Sigmoid: + Aliases: null + Args: null + Description: "" + Examples: null + Text: + Aliases: null + Args: null + Description: "" + Examples: null + UnsharpMask: + Aliases: null + Args: null + Description: "" + Examples: null + inflect: + Humanize: + Aliases: + - humanize + Args: + - v + Description: |- + Humanize returns the humanized form of v. + + If v is either an integer or a string containing an integer + value, the behavior is to add the appropriate ordinal. + Examples: + - - '{{ humanize "my-first-post" }}' + - My first post + - - '{{ humanize "myCamelPost" }}' + - My camel post + - - '{{ humanize "52" }}' + - 52nd + - - '{{ humanize 103 }}' + - 103rd + Pluralize: + Aliases: + - pluralize + Args: + - v + Description: Pluralize returns the plural form of the single word in v. + Examples: + - - '{{ "cat" | pluralize }}' + - cats + Singularize: + Aliases: + - singularize + Args: + - v + Description: Singularize returns the singular form of a single word in v. + Examples: + - - '{{ "cats" | singularize }}' + - cat + js: + Babel: + Aliases: + - babel + Args: + - args + Description: Babel processes the given Resource with Babel. + Examples: [] + Batch: + Aliases: null + Args: null + Description: "" + Examples: null + Build: + Aliases: null + Args: null + Description: "" + Examples: null + lang: + FormatAccounting: + Aliases: null + Args: + - precision + - currency + - number + Description: |- + FormatAccounting returns the currency representation of number for the given currency and precision + for the current language in accounting notation. + + The return value is formatted with at least two decimal places. + Examples: + - - '{{ 512.5032 | lang.FormatAccounting 2 "NOK" }}' + - NOK512.50 + FormatCurrency: + Aliases: null + Args: + - precision + - currency + - number + Description: |- + FormatCurrency returns the currency representation of number for the given currency and precision + for the current language. + + The return value is formatted with at least two decimal places. + Examples: + - - '{{ 512.5032 | lang.FormatCurrency 2 "USD" }}' + - $512.50 + FormatNumber: + Aliases: null + Args: + - precision + - number + Description: FormatNumber formats number with the given precision for the + current language. + Examples: + - - '{{ 512.5032 | lang.FormatNumber 2 }}' + - "512.50" + FormatNumberCustom: + Aliases: null + Args: + - precision + - number + - options + Description: |- + FormatNumberCustom formats a number with the given precision. The first + options parameter is a space-delimited string of characters to represent + negativity, the decimal point, and grouping. The default value is `- . ,`. + The second options parameter defines an alternate delimiting character. + + Note that numbers are rounded up at 5 or greater. + So, with precision set to 0, 1.5 becomes `2`, and 1.4 becomes `1`. + + For a simpler function that adapts to the current language, see FormatNumber. + Examples: + - - '{{ lang.FormatNumberCustom 2 12345.6789 }}' + - 12,345.68 + - - '{{ lang.FormatNumberCustom 2 12345.6789 "- , ." }}' + - 12.345,68 + - - '{{ lang.FormatNumberCustom 6 -12345.6789 "- ." }}' + - "-12345.678900" + - - '{{ lang.FormatNumberCustom 0 -12345.6789 "- . ," }}' + - -12,346 + - - '{{ lang.FormatNumberCustom 0 -12345.6789 "-|.| " "|" }}' + - -12 346 + - - '{{ -98765.4321 | lang.FormatNumberCustom 2 }}' + - -98,765.43 + FormatPercent: + Aliases: null + Args: + - precision + - number + Description: |- + FormatPercent formats number with the given precision for the current language. + Note that the number is assumed to be a percentage. + Examples: + - - '{{ 512.5032 | lang.FormatPercent 2 }}' + - 512.50% + Merge: + Aliases: null + Args: null + Description: "" + Examples: null + Translate: + Aliases: + - i18n + - T + Args: + - ctx + - id + - args + Description: Translate returns a translated string for id. + Examples: [] + math: + Abs: + Aliases: null + Args: + - "n" + Description: Abs returns the absolute value of n. + Examples: + - - '{{ math.Abs -2.1 }}' + - "2.1" + Acos: + Aliases: null + Args: + - "n" + Description: Acos returns the arccosine, in radians, of n. + Examples: + - - '{{ math.Acos 1 }}' + - "0" + Add: + Aliases: + - add + Args: + - inputs + Description: Add adds the multivalued addends n1 and n2 or more values. + Examples: + - - '{{ add 1 2 }}' + - "3" + Asin: + Aliases: null + Args: + - "n" + Description: Asin returns the arcsine, in radians, of n. + Examples: + - - '{{ math.Asin 1 }}' + - "1.5707963267948966" + Atan: + Aliases: null + Args: + - "n" + Description: Atan returns the arctangent, in radians, of n. + Examples: + - - '{{ math.Atan 1 }}' + - "0.7853981633974483" + Atan2: + Aliases: null + Args: + - "n" + - m + Description: Atan2 returns the arc tangent of n/m, using the signs of the + two to determine the quadrant of the return value. + Examples: + - - '{{ math.Atan2 1 2 }}' + - "0.4636476090008061" + Ceil: + Aliases: null + Args: + - "n" + Description: Ceil returns the least integer value greater than or equal to + n. + Examples: + - - '{{ math.Ceil 2.1 }}' + - "3" + Cos: + Aliases: null + Args: + - "n" + Description: Cos returns the cosine of the radian argument n. + Examples: + - - '{{ math.Cos 1 }}' + - "0.5403023058681398" + Counter: + Aliases: null + Args: null + Description: "" + Examples: null + Div: + Aliases: + - div + Args: + - inputs + Description: Div divides n1 by n2. + Examples: + - - '{{ div 6 3 }}' + - "2" + Floor: + Aliases: null + Args: + - "n" + Description: Floor returns the greatest integer value less than or equal to + n. + Examples: + - - '{{ math.Floor 1.9 }}' + - "1" + Log: + Aliases: null + Args: + - "n" + Description: Log returns the natural logarithm of the number n. + Examples: + - - '{{ math.Log 1 }}' + - "0" + Max: + Aliases: null + Args: + - inputs + Description: Max returns the greater of all numbers in inputs. Any slices + in inputs are flattened. + Examples: + - - '{{ math.Max 1 2 }}' + - "2" + MaxInt64: + Aliases: null + Args: null + Description: MaxInt64 returns the maximum value for a signed 64-bit integer. + Examples: + - - '{{ math.MaxInt64 }}' + - "9223372036854775807" + Min: + Aliases: null + Args: + - inputs + Description: Min returns the smaller of all numbers in inputs. Any slices + in inputs are flattened. + Examples: + - - '{{ math.Min 1 2 }}' + - "1" + Mod: + Aliases: + - mod + Args: + - n1 + - n2 + Description: Mod returns n1 % n2. + Examples: + - - '{{ mod 15 3 }}' + - "0" + ModBool: + Aliases: + - modBool + Args: + - n1 + - n2 + Description: ModBool returns the boolean of n1 % n2. If n1 % n2 == 0, return + true. + Examples: + - - '{{ modBool 15 3 }}' + - "true" + Mul: + Aliases: + - mul + Args: + - inputs + Description: Mul multiplies the multivalued numbers n1 and n2 or more values. + Examples: + - - '{{ mul 2 3 }}' + - "6" + Pi: + Aliases: null + Args: null + Description: Pi returns the mathematical constant pi. + Examples: + - - '{{ math.Pi }}' + - "3.141592653589793" + Pow: + Aliases: + - pow + Args: + - n1 + - n2 + Description: Pow returns n1 raised to the power of n2. + Examples: + - - '{{ math.Pow 2 3 }}' + - "8" + Product: + Aliases: null + Args: null + Description: "" + Examples: null + Rand: + Aliases: null + Args: null + Description: Rand returns, as a float64, a pseudo-random number in the half-open + interval [0.0,1.0). + Examples: + - - '{{ math.Rand }}' + - "0.6312770459590062" + Round: + Aliases: null + Args: + - "n" + Description: Round returns the integer nearest to n, rounding half away from + zero. + Examples: + - - '{{ math.Round 1.5 }}' + - "2" + Sin: + Aliases: null + Args: + - "n" + Description: Sin returns the sine of the radian argument n. + Examples: + - - '{{ math.Sin 1 }}' + - "0.8414709848078965" + Sqrt: + Aliases: null + Args: + - "n" + Description: Sqrt returns the square root of the number n. + Examples: + - - '{{ math.Sqrt 81 }}' + - "9" + Sub: + Aliases: + - sub + Args: + - inputs + Description: Sub subtracts multivalued. + Examples: + - - '{{ sub 3 2 }}' + - "1" + Sum: + Aliases: null + Args: null + Description: "" + Examples: null + Tan: + Aliases: null + Args: + - "n" + Description: Tan returns the tangent of the radian argument n. + Examples: + - - '{{ math.Tan 1 }}' + - "1.557407724654902" + ToDegrees: + Aliases: null + Args: + - "n" + Description: ToDegrees converts radians into degrees. + Examples: + - - '{{ math.ToDegrees 1.5707963267948966 }}' + - "90" + ToRadians: + Aliases: null + Args: + - "n" + Description: ToRadians converts degrees into radians. + Examples: + - - '{{ math.ToRadians 90 }}' + - "1.5707963267948966" + openapi3: + Unmarshal: + Aliases: null + Args: null + Description: "" + Examples: [] + os: + FileExists: + Aliases: + - fileExists + Args: + - i + Description: FileExists checks whether a file exists under the given path. + Examples: + - - '{{ fileExists "foo.txt" }}' + - "false" + Getenv: + Aliases: + - getenv + Args: + - key + Description: |- + Getenv retrieves the value of the environment variable named by the key. + It returns the value, which will be empty if the variable is not present. + Examples: [] + ReadDir: + Aliases: + - readDir + Args: + - i + Description: ReadDir lists the directory contents relative to the configured + WorkingDir. + Examples: + - - '{{ range (readDir "files") }}{{ .Name }}{{ end }}' + - README.txt + ReadFile: + Aliases: + - readFile + Args: + - i + Description: |- + ReadFile reads the file named by filename relative to the configured WorkingDir. + It returns the contents as a string. + There is an upper size limit set at 1 megabytes. + Examples: + - - '{{ readFile "files/README.txt" }}' + - Hugo Rocks! + Stat: + Aliases: null + Args: null + Description: "" + Examples: null + partials: + Include: + Aliases: + - partial + Args: + - ctx + - name + - contextList + Description: |- + Include executes the named partial. + If the partial contains a return statement, that value will be returned. + Else, the rendered output will be returned: + A string if the partial is a text/template, or template.HTML when html/template. + Note that ctx is provided by Hugo, not the end user. + Examples: + - - '{{ partial "header.html" . }}' + - Hugo Rocks! + IncludeCached: + Aliases: + - partialCached + Args: + - ctx + - name + - context + - variants + Description: |- + IncludeCached executes and caches partial templates. The cache is created with name+variants as the key. + Note that ctx is provided by Hugo, not the end user. + Examples: [] + path: + Base: + Aliases: null + Args: null + Description: "" + Examples: null + BaseName: + Aliases: null + Args: null + Description: "" + Examples: null + Clean: + Aliases: null + Args: null + Description: "" + Examples: null + Dir: + Aliases: null + Args: null + Description: "" + Examples: null + Ext: + Aliases: null + Args: null + Description: "" + Examples: null + Join: + Aliases: null + Args: + - elements + Description: |- + Join joins any number of path elements into a single path, adding a + separating slash if necessary. All the input + path elements are passed into filepath.ToSlash converting any Windows slashes + to forward slashes. + The result is Cleaned; in particular, + all empty strings are ignored. + Examples: + - - '{{ slice "my/path" "filename.txt" | path.Join }}' + - my/path/filename.txt + - - '{{ path.Join "my" "path" "filename.txt" }}' + - my/path/filename.txt + - - '{{ "my/path/filename.txt" | path.Ext }}' + - .txt + - - '{{ "my/path/filename.txt" | path.Base }}' + - filename.txt + - - '{{ "my/path/filename.txt" | path.Dir }}' + - my/path + Split: + Aliases: null + Args: + - path + Description: |- + Split splits path immediately following the final slash, + separating it into a directory and file name component. + If there is no slash in path, Split returns an empty dir and + file set to path. + The input path is passed into filepath.ToSlash converting any Windows slashes + to forward slashes. + The returned values have the property that path = dir+file. + Examples: + - - '{{ "/my/path/filename.txt" | path.Split }}' + - /my/path/|filename.txt + - - '{{ "/my/path/filename.txt" | path.Split }}' + - /my/path/|filename.txt + reflect: + IsMap: + Aliases: null + Args: + - v + Description: IsMap reports whether v is a map. + Examples: + - - '{{ if reflect.IsMap (dict "a" 1) }}Map{{ end }}' + - Map + IsSlice: + Aliases: null + Args: + - v + Description: IsSlice reports whether v is a slice. + Examples: + - - '{{ if reflect.IsSlice (slice 1 2 3) }}Slice{{ end }}' + - Slice + resources: + Babel: + Aliases: null + Args: null + Description: "" + Examples: null + ByType: + Aliases: null + Args: null + Description: "" + Examples: null + Concat: + Aliases: null + Args: null + Description: "" + Examples: null + Copy: + Aliases: null + Args: null + Description: "" + Examples: null + ExecuteAsTemplate: + Aliases: null + Args: null + Description: "" + Examples: null + Fingerprint: + Aliases: + - fingerprint + Args: + - args + Description: |- + Fingerprint transforms the given Resource with a MD5 hash of the content in + the RelPermalink and Permalink. + Examples: [] + FromString: + Aliases: null + Args: null + Description: "" + Examples: null + Get: + Aliases: null + Args: + - filename + Description: |- + Get locates the filename given in Hugo's assets filesystem + and creates a Resource object that can be used for further transformations. + Examples: [] + GetMatch: + Aliases: null + Args: null + Description: "" + Examples: null + GetRemote: + Aliases: null + Args: + - args + Description: |- + GetRemote gets the URL (via HTTP(s)) in the first argument in args and creates Resource object that can be used for + further transformations. + + A second argument may be provided with an option map. + + Note: This method does not return any error as a second return value, + for any error situations the error can be checked in .Err. + Examples: [] + Match: + Aliases: null + Args: null + Description: "" + Examples: null + Minify: + Aliases: + - minify + Args: + - r + Description: |- + Minify minifies the given Resource using the MediaType to pick the correct + minifier. + Examples: [] + PostCSS: + Aliases: null + Args: null + Description: "" + Examples: null + PostProcess: + Aliases: null + Args: null + Description: "" + Examples: null + ToCSS: + Aliases: null + Args: null + Description: "" + Examples: null + safe: + CSS: + Aliases: + - safeCSS + Args: + - s + Description: CSS returns the string s as html/template CSS content. + Examples: + - - '{{ "Bat&Man" | safeCSS | safeCSS }}' + - Bat&Man + HTML: + Aliases: + - safeHTML + Args: + - s + Description: HTML returns the string s as html/template HTML content. + Examples: + - - '{{ "Bat&Man" | safeHTML | safeHTML }}' + - Bat&Man + - - '{{ "Bat&Man" | safeHTML }}' + - Bat&Man + HTMLAttr: + Aliases: + - safeHTMLAttr + Args: + - s + Description: HTMLAttr returns the string s as html/template HTMLAttr content. + Examples: [] + JS: + Aliases: + - safeJS + Args: + - s + Description: JS returns the given string as a html/template JS content. + Examples: + - - '{{ "(1*2)" | safeJS | safeJS }}' + - (1*2) + JSStr: + Aliases: + - safeJSStr + Args: + - s + Description: JSStr returns the given string as a html/template JSStr content. + Examples: [] + URL: + Aliases: + - safeURL + Args: + - s + Description: URL returns the string s as html/template URL content. + Examples: + - - '{{ "http://gohugo.io" | safeURL | safeURL }}' + - http://gohugo.io + site: + AllPages: + Aliases: null + Args: null + Description: "" + Examples: null + Author: + Aliases: null + Args: null + Description: "" + Examples: null + Authors: + Aliases: null + Args: null + Description: "" + Examples: null + BaseURL: + Aliases: null + Args: null + Description: "" + Examples: null + BuildDrafts: + Aliases: null + Args: null + Description: "" + Examples: null + CheckReady: + Aliases: null + Args: null + Description: "" + Examples: null + Config: + Aliases: null + Args: null + Description: "" + Examples: null + Copyright: + Aliases: null + Args: null + Description: "" + Examples: null + Current: + Aliases: null + Args: null + Description: "" + Examples: null + Data: + Aliases: null + Args: null + Description: "" + Examples: null + ForEeachIdentityByName: + Aliases: null + Args: null + Description: "" + Examples: null + GetPage: + Aliases: null + Args: null + Description: "" + Examples: null + Home: + Aliases: null + Args: null + Description: "" + Examples: null + Hugo: + Aliases: null + Args: null + Description: "" + Examples: null + IsMultiLingual: + Aliases: null + Args: null + Description: "" + Examples: null + Key: + Aliases: null + Args: null + Description: "" + Examples: null + Language: + Aliases: null + Args: null + Description: "" + Examples: null + LanguageCode: + Aliases: null + Args: null + Description: "" + Examples: null + LanguagePrefix: + Aliases: null + Args: null + Description: "" + Examples: null + Languages: + Aliases: null + Args: null + Description: "" + Examples: null + LastChange: + Aliases: null + Args: null + Description: "" + Examples: null + Lastmod: + Aliases: null + Args: null + Description: "" + Examples: null + MainSections: + Aliases: null + Args: null + Description: "" + Examples: null + Menus: + Aliases: null + Args: null + Description: "" + Examples: null + Pages: + Aliases: null + Args: null + Description: "" + Examples: null + Param: + Aliases: null + Args: null + Description: "" + Examples: null + Params: + Aliases: null + Args: null + Description: "" + Examples: null + RegularPages: + Aliases: null + Args: null + Description: "" + Examples: null + Sections: + Aliases: null + Args: null + Description: "" + Examples: null + ServerPort: + Aliases: null + Args: null + Description: "" + Examples: null + Sites: + Aliases: null + Args: null + Description: "" + Examples: null + Social: + Aliases: null + Args: null + Description: "" + Examples: null + Store: + Aliases: null + Args: null + Description: "" + Examples: null + Taxonomies: + Aliases: null + Args: null + Description: "" + Examples: null + Title: + Aliases: null + Args: null + Description: "" + Examples: null + strings: + Chomp: + Aliases: + - chomp + Args: + - s + Description: Chomp returns a copy of s with all trailing newline characters + removed. + Examples: + - - '{{ chomp "

    Blockhead

    \n" | safeHTML }}' + -

    Blockhead

    + Contains: + Aliases: null + Args: + - s + - substr + Description: Contains reports whether substr is in s. + Examples: + - - '{{ strings.Contains "abc" "b" }}' + - "true" + - - '{{ strings.Contains "abc" "d" }}' + - "false" + ContainsAny: + Aliases: null + Args: + - s + - chars + Description: ContainsAny reports whether any Unicode code points in chars + are within s. + Examples: + - - '{{ strings.ContainsAny "abc" "bcd" }}' + - "true" + - - '{{ strings.ContainsAny "abc" "def" }}' + - "false" + ContainsNonSpace: + Aliases: null + Args: null + Description: "" + Examples: null + Count: + Aliases: null + Args: + - substr + - s + Description: |- + Count counts the number of non-overlapping instances of substr in s. + If substr is an empty string, Count returns 1 + the number of Unicode code points in s. + Examples: + - - '{{ "aabab" | strings.Count "a" }}' + - "3" + CountRunes: + Aliases: + - countrunes + Args: + - s + Description: CountRunes returns the number of runes in s, excluding whitespace. + Examples: [] + CountWords: + Aliases: + - countwords + Args: + - s + Description: CountWords returns the approximate word count in s. + Examples: [] + Diff: + Aliases: null + Args: null + Description: "" + Examples: null + FindRE: + Aliases: + - findRE + Args: + - expr + - content + - limit + Description: |- + FindRE returns a list of strings that match the regular expression. By default all matches + will be included. The number of matches can be limited with an optional third parameter. + Examples: + - - '{{ findRE "[G|g]o" "Hugo is a static side generator written in Go." 1 + }}' + - '[go]' + FindRESubmatch: + Aliases: + - findRESubmatch + Args: + - expr + - content + - limit + Description: |- + FindRESubmatch returns a slice of all successive matches of the regular + expression in content. Each element is a slice of strings holding the text + of the leftmost match of the regular expression and the matches, if any, of + its subexpressions. + + By default all matches will be included. The number of matches can be + limited with the optional limit parameter. A return value of nil indicates + no match. + Examples: + - - '{{ findRESubmatch `(.+?)` `
  • Foo
  • +
  • Bar
  • ` | print | safeHTML }}' + - '[[Foo #foo Foo] [Bar #bar Bar]]' + FirstUpper: + Aliases: null + Args: + - s + Description: FirstUpper converts s making the first character upper case. + Examples: + - - '{{ "hugo rocks!" | strings.FirstUpper }}' + - Hugo rocks! + HasPrefix: + Aliases: + - hasPrefix + Args: + - s + - prefix + Description: HasPrefix tests whether the input s begins with prefix. + Examples: + - - '{{ hasPrefix "Hugo" "Hu" }}' + - "true" + - - '{{ hasPrefix "Hugo" "Fu" }}' + - "false" + HasSuffix: + Aliases: + - hasSuffix + Args: + - s + - suffix + Description: HasSuffix tests whether the input s begins with suffix. + Examples: + - - '{{ hasSuffix "Hugo" "go" }}' + - "true" + - - '{{ hasSuffix "Hugo" "du" }}' + - "false" + Repeat: + Aliases: null + Args: + - "n" + - s + Description: Repeat returns a new string consisting of n copies of the string + s. + Examples: + - - '{{ "yo" | strings.Repeat 4 }}' + - yoyoyoyo + Replace: + Aliases: + - replace + Args: + - s + - old + - new + - limit + Description: |- + Replace returns a copy of the string s with all occurrences of old replaced + with new. The number of replacements can be limited with an optional fourth + parameter. + Examples: + - - '{{ replace "Batman and Robin" "Robin" "Catwoman" }}' + - Batman and Catwoman + - - '{{ replace "aabbaabb" "a" "z" 2 }}' + - zzbbaabb + ReplaceRE: + Aliases: + - replaceRE + Args: + - pattern + - repl + - s + - "n" + Description: |- + ReplaceRE returns a copy of s, replacing all matches of the regular + expression pattern with the replacement text repl. The number of replacements + can be limited with an optional fourth parameter. + Examples: + - - '{{ replaceRE "a+b" "X" "aabbaabbab" }}' + - XbXbX + - - '{{ replaceRE "a+b" "X" "aabbaabbab" 1 }}' + - Xbaabbab + RuneCount: + Aliases: null + Args: + - s + Description: RuneCount returns the number of runes in s. + Examples: [] + SliceString: + Aliases: + - slicestr + Args: + - a + - startEnd + Description: |- + SliceString slices a string by specifying a half-open range with + two indices, start and end. 1 and 4 creates a slice including elements 1 through 3. + The end index can be omitted, it defaults to the string's length. + Examples: + - - '{{ slicestr "BatMan" 0 3 }}' + - Bat + - - '{{ slicestr "BatMan" 3 }}' + - Man + Split: + Aliases: + - split + Args: + - a + - delimiter + Description: Split slices an input string into all substrings separated by + delimiter. + Examples: [] + Substr: + Aliases: + - substr + Args: + - a + - nums + Description: |- + Substr extracts parts of a string, beginning at the character at the specified + position, and returns the specified number of characters. + + It normally takes two parameters: start and length. + It can also take one parameter: start, i.e. length is omitted, in which case + the substring starting from start until the end of the string will be returned. + + To extract characters from the end of the string, use a negative start number. + + In addition, borrowing from the extended behavior described at http://php.net/substr, + if length is given and is negative, then that many characters will be omitted from + the end of string. + Examples: + - - '{{ substr "BatMan" 0 -3 }}' + - Bat + - - '{{ substr "BatMan" 3 3 }}' + - Man + Title: + Aliases: + - title + Args: + - s + Description: |- + Title returns a copy of the input s with all Unicode letters that begin words + mapped to their title case. + Examples: + - - '{{ title "Bat man" }}' + - Bat Man + - - '{{ title "somewhere over the rainbow" }}' + - Somewhere Over the Rainbow + ToLower: + Aliases: + - lower + Args: + - s + Description: |- + ToLower returns a copy of the input s with all Unicode letters mapped to their + lower case. + Examples: + - - '{{ lower "BatMan" }}' + - batman + ToUpper: + Aliases: + - upper + Args: + - s + Description: |- + ToUpper returns a copy of the input s with all Unicode letters mapped to their + upper case. + Examples: + - - '{{ upper "BatMan" }}' + - BATMAN + Trim: + Aliases: + - trim + Args: + - s + - cutset + Description: |- + Trim returns converts the strings s removing all leading and trailing characters defined + contained. + Examples: + - - '{{ trim "++Batman--" "+-" }}' + - Batman + TrimLeft: + Aliases: null + Args: + - cutset + - s + Description: |- + TrimLeft returns a slice of the string s with all leading characters + contained in cutset removed. + Examples: + - - '{{ "aabbaa" | strings.TrimLeft "a" }}' + - bbaa + TrimPrefix: + Aliases: null + Args: + - prefix + - s + Description: |- + TrimPrefix returns s without the provided leading prefix string. If s doesn't + start with prefix, s is returned unchanged. + Examples: + - - '{{ "aabbaa" | strings.TrimPrefix "a" }}' + - abbaa + - - '{{ "aabbaa" | strings.TrimPrefix "aa" }}' + - bbaa + TrimRight: + Aliases: null + Args: + - cutset + - s + Description: |- + TrimRight returns a slice of the string s with all trailing characters + contained in cutset removed. + Examples: + - - '{{ "aabbaa" | strings.TrimRight "a" }}' + - aabb + TrimSpace: + Aliases: null + Args: null + Description: "" + Examples: null + TrimSuffix: + Aliases: null + Args: + - suffix + - s + Description: |- + TrimSuffix returns s without the provided trailing suffix string. If s + doesn't end with suffix, s is returned unchanged. + Examples: + - - '{{ "aabbaa" | strings.TrimSuffix "a" }}' + - aabba + - - '{{ "aabbaa" | strings.TrimSuffix "aa" }}' + - aabb + Truncate: + Aliases: + - truncate + Args: + - s + - options + Description: Truncate truncates the string in s to the specified length. + Examples: + - - '{{ "this is a very long text" | truncate 10 " ..." }}' + - this is a ... + - - '{{ "With [Markdown](/markdown) inside." | markdownify | truncate 14 }}' + - With Markdown … + templates: + Current: + Aliases: null + Args: null + Description: "" + Examples: null + Defer: + Aliases: null + Args: + - args + Description: Defer defers the execution of a template block. + Examples: [] + DoDefer: + Aliases: + - doDefer + Args: + - ctx + - id + - optsv + Description: |- + DoDefer defers the execution of a template block. + For internal use only. + Examples: [] + Exists: + Aliases: null + Args: + - name + Description: |- + Exists returns whether the template with the given name exists. + Note that this is the Unix-styled relative path including filename suffix, + e.g. partials/header.html + Examples: + - - '{{ if (templates.Exists "partials/header.html") }}Yes!{{ end }}' + - Yes! + - - '{{ if not (templates.Exists "partials/doesnotexist.html") }}No!{{ end + }}' + - No! + time: + AsTime: + Aliases: null + Args: + - v + - args + Description: |- + AsTime converts the textual representation of the datetime string into + a time.Time interface. + Examples: + - - '{{ (time "2015-01-21").Year }}' + - "2015" + Duration: + Aliases: + - duration + Args: + - unit + - number + Description: |- + Duration converts the given number to a time.Duration. + Unit is one of nanosecond/ns, microsecond/us/µs, millisecond/ms, second/s, minute/m or hour/h. + Examples: + - - '{{ mul 60 60 | duration "second" }}' + - 1h0m0s + Format: + Aliases: + - dateFormat + Args: + - layout + - v + Description: |- + Format converts the textual representation of the datetime string in v into + time.Time if needed and formats it with the given layout. + Examples: + - - 'dateFormat: {{ dateFormat "Monday, Jan 2, 2006" "2015-01-21" }}' + - 'dateFormat: Wednesday, Jan 21, 2015' + In: + Aliases: null + Args: null + Description: "" + Examples: null + Now: + Aliases: + - now + Args: null + Description: Now returns the current local time or `clock` time + Examples: [] + ParseDuration: + Aliases: null + Args: + - s + Description: |- + ParseDuration parses the duration string s. + 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". + See https://golang.org/pkg/time/#ParseDuration + Examples: + - - '{{ "1h12m10s" | time.ParseDuration }}' + - 1h12m10s + transform: + CanHighlight: + Aliases: null + Args: null + Description: "" + Examples: null + Emojify: + Aliases: + - emojify + Args: + - s + Description: |- + Emojify returns a copy of s with all emoji codes replaced with actual emojis. + + See http://www.emoji-cheat-sheet.com/ + Examples: + - - '{{ "I :heart: Hugo" | emojify }}' + - I ❤️ Hugo + HTMLEscape: + Aliases: + - htmlEscape + Args: + - s + Description: HTMLEscape returns a copy of s with reserved HTML characters + escaped. + Examples: + - - '{{ htmlEscape "Cathal Garvey & The Sunshine Band " | + safeHTML }}' + - Cathal Garvey & The Sunshine Band <cathal@foo.bar> + - - '{{ htmlEscape "Cathal Garvey & The Sunshine Band " }}' + - Cathal Garvey &amp; The Sunshine Band &lt;cathal@foo.bar&gt; + - - '{{ htmlEscape "Cathal Garvey & The Sunshine Band " | + htmlUnescape | safeHTML }}' + - Cathal Garvey & The Sunshine Band + HTMLUnescape: + Aliases: + - htmlUnescape + Args: + - s + Description: |- + HTMLUnescape returns a copy of s with HTML escape requences converted to plain + text. + Examples: + - - '{{ htmlUnescape "Cathal Garvey & The Sunshine Band <cathal@foo.bar>" + | safeHTML }}' + - Cathal Garvey & The Sunshine Band + - - '{{ "Cathal Garvey &amp; The Sunshine Band &lt;cathal@foo.bar&gt;" + | htmlUnescape | htmlUnescape | safeHTML }}' + - Cathal Garvey & The Sunshine Band + - - '{{ "Cathal Garvey &amp; The Sunshine Band &lt;cathal@foo.bar&gt;" + | htmlUnescape | htmlUnescape }}' + - Cathal Garvey & The Sunshine Band <cathal@foo.bar> + - - '{{ htmlUnescape "Cathal Garvey & The Sunshine Band <cathal@foo.bar>" + | htmlEscape | safeHTML }}' + - Cathal Garvey & The Sunshine Band <cathal@foo.bar> + Highlight: + Aliases: + - highlight + Args: + - s + - lang + - opts + Description: |- + Highlight returns a copy of s as an HTML string with syntax + highlighting applied. + Examples: [] + HighlightCodeBlock: + Aliases: null + Args: null + Description: "" + Examples: null + Markdownify: + Aliases: + - markdownify + Args: + - ctx + - s + Description: Markdownify renders s from Markdown to HTML. + Examples: + - - '{{ .Title | markdownify }}' + - BatMan + Plainify: + Aliases: + - plainify + Args: + - s + Description: Plainify returns a copy of s with all HTML tags removed. + Examples: + - - '{{ plainify "Hello world, gophers!" }}' + - Hello world, gophers! + PortableText: + Aliases: null + Args: null + Description: "" + Examples: null + Remarshal: + Aliases: null + Args: + - format + - data + Description: |- + Remarshal is used in the Hugo documentation to convert configuration + examples from YAML to JSON, TOML (and possibly the other way around). + The is primarily a helper for the Hugo docs site. + It is not a general purpose YAML to TOML converter etc., and may + change without notice if it serves a purpose in the docs. + Format is one of json, yaml or toml. + Examples: + - - '{{ "title = \"Hello World\"" | transform.Remarshal "json" | safeHTML + }}' + - | + { + "title": "Hello World" + } + ToMath: + Aliases: null + Args: null + Description: "" + Examples: null + Unmarshal: + Aliases: + - unmarshal + Args: + - args + Description: |- + Unmarshal unmarshals the data given, which can be either a string, json.RawMessage + or a Resource. Supported formats are JSON, TOML, YAML, and CSV. + You can optionally provide an options map as the first argument. + Examples: + - - '{{ "hello = \"Hello World\"" | transform.Unmarshal }}' + - map[hello:Hello World] + - - '{{ "hello = \"Hello World\"" | resources.FromString "data/greetings.toml" + | transform.Unmarshal }}' + - map[hello:Hello World] + XMLEscape: + Aliases: null + Args: + - s + Description: |- + XMLEscape returns the given string, removing disallowed characters then + escaping the result to its XML equivalent. + Examples: + - - '{{ transform.XMLEscape "

    abc

    " }}' + - '<p>abc</p>' + urls: + AbsLangURL: + Aliases: + - absLangURL + Args: + - s + Description: |- + AbsLangURL the string s and converts it to an absolute URL according + to a page's position in the project directory structure and the current + language. + Examples: [] + AbsURL: + Aliases: + - absURL + Args: + - s + Description: AbsURL takes the string s and converts it to an absolute URL. + Examples: [] + Anchorize: + Aliases: + - anchorize + Args: + - s + Description: |- + Anchorize creates sanitized anchor name version of the string s that is compatible + with how your configured markdown renderer does it. + Examples: + - - '{{ "This is a title" | anchorize }}' + - this-is-a-title + JoinPath: + Aliases: null + Args: + - elements + Description: |- + JoinPath joins the provided elements into a URL string and cleans the result + of any ./ or ../ elements. If the argument list is empty, JoinPath returns + an empty string. + Examples: + - - '{{ urls.JoinPath "https://example.org" "foo" }}' + - https://example.org/foo + - - '{{ urls.JoinPath (slice "a" "b") }}' + - a/b + Parse: + Aliases: null + Args: null + Description: "" + Examples: null + Ref: + Aliases: + - ref + Args: + - p + - args + Description: Ref returns the absolute URL path to a given content item from + Page p. + Examples: [] + RelLangURL: + Aliases: + - relLangURL + Args: + - s + Description: |- + RelLangURL takes the string s and prepends the relative path according to a + page's position in the project directory structure and the current language. + Examples: [] + RelRef: + Aliases: + - relref + Args: + - p + - args + Description: RelRef returns the relative URL path to a given content item + from Page p. + Examples: [] + RelURL: + Aliases: + - relURL + Args: + - s + Description: |- + RelURL takes the string s and prepends the relative path according to a + page's position in the project directory structure. + Examples: [] + URLize: + Aliases: + - urlize + Args: + - s + Description: URLize returns the strings s formatted as an URL. + Examples: [] diff --cc docs/data/page_filters.yaml index 82de6168e,000000000..e515f843d mode 100644,000000..100644 --- a/docs/data/page_filters.yaml +++ b/docs/data/page_filters.yaml @@@ -1,95 -1,0 +1,95 @@@ - # Do not delete. Required for layouts/shortcodes/list-pages-in-section.html. ++# Do not delete. Required for layouts/_shortcodes/list-pages-in-section.html. +# +# When calling the list-pages-in-section shortcode, you can specify a page +# filter, and whether the pages in the filter should be included or excluded +# from the list. +# +# For example: +# +# {{% list-pages-in-section path=/functions/images filter=functions_images_no_filters filterType=exclude %}} + +functions_fmt_logging: + - /functions/fmt/errorf + - /functions/fmt/erroridf + - /functions/fmt/warnf + - /functions/fmt/warnidf +functions_images_no_filters: + - /functions/images/filter + - /functions/images/config +methods_site_multilingual: + - /methods/site/ismultilingual + - /methods/site/language + - /methods/site/languageprefix + - /methods/site/languages +methods_site_page_collections: + - /methods/site/allpages + - /methods/site/pages + - /methods/site/regularpages + - /methods/site/sections +methods_page_dates: + - /methods/page/date + - /methods/page/expirydate + - /methods/page/lastmod + - /methods/page/publishdate +methods_page_menu: + - /methods/page/hasmenucurrent + - /methods/page/ismenucurrent +methods_page_multilingual: + - /methods/page/alltranslations + - /methods/page/istranslated + - /methods/page/language + - /methods/page/translationkey + - /methods/page/translations +methods_page_page_collections: + - /methods/page/pages + - /methods/page/regularpages + - /methods/page/regularpagesrecursive + - /methods/page/sections +methods_page_parameters: + - /methods/page/param + - /methods/page/params +methods_page_sections: + - /methods/page/ancestors + - /methods/page/currentsection + - /methods/page/firstsection + - /methods/page/insection + - /methods/page/isancestor + - /methods/page/isdescendant + - /methods/page/parent + - /methods/page/sections + - /methods/page/section +methods_pages_sort: + - /methods/pages/bydate + - /methods/pages/byexpirydate + - /methods/pages/bylanguage + - /methods/pages/bylastmod + - /methods/pages/bylength + - /methods/pages/bylinktitle + - /methods/pages/byparam + - /methods/pages/bypublishdate + - /methods/pages/bytitle + - /methods/pages/byweight + - /methods/pages/reverse +methods_pages_group: + - /methods/pages/groupby + - /methods/pages/groupbydate + - /methods/pages/groupbyexpirydate + - /methods/pages/groupbylastmod + - /methods/pages/groupbyparam + - /methods/pages/groupbyparamdate + - /methods/pages/groupbypublishdate + - /methods/pages/groupbydate + - /methods/pages/groupbydate + - /methods/pages/groupbydate + - /methods/pages/groupbydate + - /methods/pages/groupbydate + - /methods/pages/groupbydate + - /methods/pages/reverse +methods_pages_navigation: + - /methods/pages/next + - /methods/pages/prev +methods_page_navigation: + - /methods/page/next + - /methods/page/nextinsection + - /methods/page/prev + - /methods/page/previnsection diff --cc docs/data/sponsors.toml index 033042e93,000000000..84769a453 mode 100644,000000..100644 --- a/docs/data/sponsors.toml +++ b/docs/data/sponsors.toml @@@ -1,21 -1,0 +1,14 @@@ +[[banners]] + name = "Linode" + link = "https://www.linode.com/" + logo = "images/sponsors/linode-logo.svg" + utm_campaign = "hugosponsor" + bgcolor = "#ffffff" + +[[banners]] + name = "GoLand" + title = "The complete IDE crafted for professional Go developers." + no_query_params = true + link = "https://www.jetbrains.com/go/?utm_source=OSS&utm_medium=referral&utm_campaign=hugo" + logo = "images/sponsors/goland.svg" + bgcolor = "#f4f4f4" - - [[banners]] - name = "PinMe" - link = "https://pinme.eth.limo/?s=hugo" - logo = "images/sponsors/logo-pinme.svg" - no_query_params = true - bgcolor = "#fafafa" diff --cc docs/netlify.toml index ad4dd525e,000000000..6d028743d mode 100644,000000..100644 --- a/docs/netlify.toml +++ b/docs/netlify.toml @@@ -1,55 -1,0 +1,55 @@@ +[build] + publish = "public" + command = "hugo --gc --minify" + + [build.environment] - HUGO_VERSION = "0.147.9" ++ HUGO_VERSION = "0.148.2" + +[context.production.environment] + HUGO_ENV = "production" + HUGO_ENABLEGITINFO = "true" + +[context.split1] + command = "hugo --gc --minify --enableGitInfo" + + [context.split1.environment] + HUGO_ENV = "production" + +[context.deploy-preview] + command = "hugo --gc --minify --buildFuture -b $DEPLOY_PRIME_URL --enableGitInfo" + +[context.branch-deploy] + command = "hugo --gc --minify -b $DEPLOY_PRIME_URL" + +[context.next.environment] + HUGO_ENABLEGITINFO = "true" + +[[headers]] + for = "/*.jpg" + + [headers.values] + Cache-Control = "public, max-age=31536000" + +[[headers]] + for = "/*.png" + + [headers.values] + Cache-Control = "public, max-age=31536000" + +[[headers]] + for = "/*.css" + + [headers.values] + Cache-Control = "public, max-age=31536000" + +[[headers]] + for = "/*.js" + + [headers.values] + Cache-Control = "public, max-age=31536000" + +[[headers]] + for = "/*.ttf" + + [headers.values] + Cache-Control = "public, max-age=31536000"