diff options
Diffstat (limited to 'docs/content/en')
1015 files changed, 47552 insertions, 0 deletions
diff --git a/docs/content/en/_common/_index.md b/docs/content/en/_common/_index.md new file mode 100644 index 000000000..612165e5c --- /dev/null +++ b/docs/content/en/_common/_index.md @@ -0,0 +1,13 @@ +--- +cascade: + build: + list: never + publishResources: false + render: never +--- + +<!-- +Files within this headless branch bundle are Markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required. + +Include the rendered content using the "include" shortcode. +--> diff --git a/docs/content/en/_common/content-format-table.md b/docs/content/en/_common/content-format-table.md new file mode 100644 index 000000000..c0a66a146 --- /dev/null +++ b/docs/content/en/_common/content-format-table.md @@ -0,0 +1,13 @@ +--- +_comment: Do not remove front matter. +--- + +Content format|Media type|Identifier|File extensions +:--|:--|:--|:-- +Markdown|`text/markdown`|`markdown`|`markdown`,`md`, `mdown` +HTML|`text/html`|`html`|`htm`, `html` +Emacs Org Mode|`text/org`|`org`|`org` +AsciiDoc|`text/asciidoc`|`asciidoc`|`ad`, `adoc`, `asciidoc` +Pandoc|`text/pandoc`|`pandoc`|`pandoc`, `pdc` +reStructuredText|`text/rst`|`rst`|`rst` +<!-- do not remove this comment --> diff --git a/docs/content/en/_common/filter-sort-group.md b/docs/content/en/_common/filter-sort-group.md new file mode 100644 index 000000000..ac73766da --- /dev/null +++ b/docs/content/en/_common/filter-sort-group.md @@ -0,0 +1,8 @@ +--- +_comment: Do not remove front matter. +--- + +> [!note] +> The [page collections quick reference guide] describes methods and functions to filter, sort, and group page collections. + +[page collections quick reference guide]: /quick-reference/page-collections/ diff --git a/docs/content/en/_common/functions/fmt/format-string.md b/docs/content/en/_common/functions/fmt/format-string.md new file mode 100644 index 000000000..09a9ee867 --- /dev/null +++ b/docs/content/en/_common/functions/fmt/format-string.md @@ -0,0 +1,7 @@ +--- +_comment: Do not remove front matter. +--- + +The documentation for Go's [fmt] package describes the structure and content of the format string. + +[fmt]: https://pkg.go.dev/fmt diff --git a/docs/content/en/_common/functions/go-html-template-package.md b/docs/content/en/_common/functions/go-html-template-package.md new file mode 100644 index 000000000..57992ea66 --- /dev/null +++ b/docs/content/en/_common/functions/go-html-template-package.md @@ -0,0 +1,14 @@ +--- +_comment: Do not remove front matter. +--- + +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. + +To generate HTML output that is safe against code injection, the html/template package escapes strings in certain contexts. + +[text/template]: https://pkg.go.dev/text/template +[html/template]: https://pkg.go.dev/html/template diff --git a/docs/content/en/_common/functions/go-template/text-template.md b/docs/content/en/_common/functions/go-template/text-template.md new file mode 100644 index 000000000..4b934c1e9 --- /dev/null +++ b/docs/content/en/_common/functions/go-template/text-template.md @@ -0,0 +1,7 @@ +--- +_comment: Do not remove front matter. +--- + +See Go's [text/template] documentation for more information. + +[text/template]: https://pkg.go.dev/text/template diff --git a/docs/content/en/_common/functions/images/apply-image-filter.md b/docs/content/en/_common/functions/images/apply-image-filter.md new file mode 100644 index 000000000..08e08238f --- /dev/null +++ b/docs/content/en/_common/functions/images/apply-image-filter.md @@ -0,0 +1,27 @@ +--- +_comment: Do not remove front matter. +--- + +Apply the filter using the [`images.Filter`] function: + +[`images.Filter`]: /functions/images/filter/ + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with . | images.Filter $filter }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +You can also apply the filter using the [`Filter`] method on a `Resource` object: + +[`Filter`]: /methods/resource/filter/ + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Filter $filter }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` diff --git a/docs/content/en/_common/functions/js/options.md b/docs/content/en/_common/functions/js/options.md new file mode 100644 index 000000000..475429d05 --- /dev/null +++ b/docs/content/en/_common/functions/js/options.md @@ -0,0 +1,108 @@ +--- +_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. + +inject +: (`slice`) This option allows you to automatically replace a global variable with an import from another file. The path names must be relative to `assets`. See https://esbuild.github.io/api/#inject. + +shims +: (`map`) This option allows swapping out a component with another. A common use case is to load dependencies like React from a CDN (with _shims_) when in production, but running with the full bundled `node_modules` dependency during development: + + ```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. + +externals +: (`slice`) External dependencies. Use this to trim dependencies you know will never be executed. See https://esbuild.github.io/api/#external. + +defines +: (`map`) This option allows you to define a set of string replacements to be performed when building. It must be a map where each key will be replaced by its value. + + ```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 + +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. + +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. + + 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(<App />, container); + ``` diff --git a/docs/content/en/_common/functions/locales.md b/docs/content/en/_common/functions/locales.md new file mode 100644 index 000000000..1cfd7a1e6 --- /dev/null +++ b/docs/content/en/_common/functions/locales.md @@ -0,0 +1,8 @@ +--- +_comment: Do not remove front matter. +--- + +> [!note] +> Localization of dates, currencies, numbers, and percentages is performed by the [gohugoio/locales] package. The language tag of the current site must match one of the listed locales. + +[gohugoio/locales]: https://github.com/gohugoio/locales diff --git a/docs/content/en/_common/functions/regular-expressions.md b/docs/content/en/_common/functions/regular-expressions.md new file mode 100644 index 000000000..58f81a2ee --- /dev/null +++ b/docs/content/en/_common/functions/regular-expressions.md @@ -0,0 +1,12 @@ +--- +_comment: Do not remove front matter. +--- + +When specifying the regular expression, use a raw [string literal] (backticks) instead of an interpreted string literal (double quotes) to simplify the syntax. With an interpreted string literal you must escape backslashes. + +Go's regular expression package implements the [RE2 syntax]. The RE2 syntax is a subset of that accepted by [PCRE], roughly speaking, and with various [caveats]. Note that the RE2 `\C` escape sequence is not supported. + +[caveats]: https://swtch.com/~rsc/regexp/regexp3.html#caveats +[PCRE]: https://www.pcre.org/ +[RE2 syntax]: https://github.com/google/re2/wiki/Syntax/ +[string literal]: https://go.dev/ref/spec#String_literals diff --git a/docs/content/en/_common/functions/truthy-falsy.md b/docs/content/en/_common/functions/truthy-falsy.md new file mode 100644 index 000000000..e15e58d61 --- /dev/null +++ b/docs/content/en/_common/functions/truthy-falsy.md @@ -0,0 +1,7 @@ +--- +_comment: Do not remove front matter. +--- + +The falsy values are `false`, `0`, any `nil` pointer or interface value, any array, slice, map, or string of length zero, and zero `time.Time` values. + +Everything else is truthy. diff --git a/docs/content/en/_common/functions/urls/anchorize-vs-urlize.md b/docs/content/en/_common/functions/urls/anchorize-vs-urlize.md new file mode 100644 index 000000000..e00c181b8 --- /dev/null +++ b/docs/content/en/_common/functions/urls/anchorize-vs-urlize.md @@ -0,0 +1,35 @@ +--- +_comment: Do not remove front matter. +--- + +The [`anchorize`] and [`urlize`] functions are similar: + +[`anchorize`]: /functions/urls/anchorize/ +[`urlize`]: /functions/urls/urlize/ + +- Use the `anchorize` function to generate an HTML `id` attribute value +- Use the `urlize` function to sanitize a string for usage in a URL + +For example: + +```go-html-template +{{ $s := "A B C" }} +{{ $s | anchorize }} → a-b-c +{{ $s | urlize }} → a-b-c + +{{ $s := "a b c" }} +{{ $s | anchorize }} → a-b---c +{{ $s | urlize }} → a-b-c + +{{ $s := "< a, b, & c >" }} +{{ $s | anchorize }} → -a-b--c- +{{ $s | urlize }} → a-b-c + +{{ $s := "main.go" }} +{{ $s | anchorize }} → maingo +{{ $s | urlize }} → main.go + +{{ $s := "Hugö" }} +{{ $s | anchorize }} → hugö +{{ $s | urlize }} → hug%C3%B6 +``` diff --git a/docs/content/en/_common/glob-patterns.md b/docs/content/en/_common/glob-patterns.md new file mode 100644 index 000000000..d3092dece --- /dev/null +++ b/docs/content/en/_common/glob-patterns.md @@ -0,0 +1,23 @@ +--- +_comment: Do not remove front matter. +--- + +Path|Pattern|Match +:--|:--|:-- +`images/foo/a.jpg`|`images/foo/*.jpg`|`true` +`images/foo/a.jpg`|`images/foo/*.*`|`true` +`images/foo/a.jpg`|`images/foo/*`|`true` +`images/foo/a.jpg`|`images/*/*.jpg`|`true` +`images/foo/a.jpg`|`images/*/*.*`|`true` +`images/foo/a.jpg`|`images/*/*`|`true` +`images/foo/a.jpg`|`*/*/*.jpg`|`true` +`images/foo/a.jpg`|`*/*/*.*`|`true` +`images/foo/a.jpg`|`*/*/*`|`true` +`images/foo/a.jpg`|`**/*.jpg`|`true` +`images/foo/a.jpg`|`**/*.*`|`true` +`images/foo/a.jpg`|`**/*`|`true` +`images/foo/a.jpg`|`**`|`true` +`images/foo/a.jpg`|`*/*.jpg`|`false` +`images/foo/a.jpg`|`*.jpg`|`false` +`images/foo/a.jpg`|`*.*`|`false` +`images/foo/a.jpg`|`*`|`false` diff --git a/docs/content/en/_common/gomodules-info.md b/docs/content/en/_common/gomodules-info.md new file mode 100644 index 000000000..5d88a6f9d --- /dev/null +++ b/docs/content/en/_common/gomodules-info.md @@ -0,0 +1,13 @@ +--- +_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 --git a/docs/content/en/_common/installation/01-editions.md b/docs/content/en/_common/installation/01-editions.md new file mode 100644 index 000000000..634002822 --- /dev/null +++ b/docs/content/en/_common/installation/01-editions.md @@ -0,0 +1,16 @@ +--- +_comment: Do not remove front matter. +--- + +Hugo is available in three editions: standard, extended, and extended/deploy. While the standard edition provides core functionality, the extended and extended/deploy editions offer advanced features. + +Feature|extended edition|extended/deploy edition +:--|:-:|:-: +Encode to the WebP format when [processing images]. You can decode WebP images with any edition.|:heavy_check_mark:|:heavy_check_mark: +[Transpile Sass to CSS] using the embedded LibSass transpiler. You can use the [Dart Sass] transpiler with any edition.|:heavy_check_mark:|:heavy_check_mark: +Deploy your site directly to a Google Cloud Storage bucket, an AWS S3 bucket, or an Azure Storage container. See [details].|:x:|:heavy_check_mark: + +[dart sass]: /functions/css/sass/#dart-sass +[processing images]: /content-management/image-processing/ +[transpile sass to css]: /functions/css/sass/ +[details]: /host-and-deploy/deploy-with-hugo-deploy/ diff --git a/docs/content/en/_common/installation/02-prerequisites.md b/docs/content/en/_common/installation/02-prerequisites.md new file mode 100644 index 000000000..f27d9d56b --- /dev/null +++ b/docs/content/en/_common/installation/02-prerequisites.md @@ -0,0 +1,40 @@ +--- +_comment: Do not remove front matter. +--- + +## Prerequisites + +Although not required in all cases, [Git], [Go], and [Dart Sass] are commonly used when working with Hugo. + +Git is required to: + +- Build Hugo from source +- Use the [Hugo Modules] feature +- Install a theme as a Git submodule +- Access [commit information] from a local Git repository +- Host your site with services such as [CloudCannon], [Cloudflare Pages], [GitHub Pages], [GitLab Pages], and [Netlify] + +Go is required to: + +- Build Hugo from source +- Use the Hugo Modules feature + +Dart Sass is required to transpile Sass to CSS when using the latest features of the Sass language. + +Please refer to the relevant documentation for installation instructions: + +- [Git][git install] +- [Go][go install] +- [Dart Sass][dart sass install] + +[cloudcannon]: https://cloudcannon.com/ +[cloudflare pages]: https://pages.cloudflare.com/ +[dart sass install]: /functions/css/sass/#dart-sass +[dart sass]: https://sass-lang.com/dart-sass +[git install]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[git]: https://git-scm.com/ +[github pages]: https://pages.github.com/ +[gitlab pages]: https://docs.gitlab.com/ee/user/project/pages/ +[go install]: https://go.dev/doc/install +[go]: https://go.dev/ +[netlify]: https://www.netlify.com/ diff --git a/docs/content/en/_common/installation/03-prebuilt-binaries.md b/docs/content/en/_common/installation/03-prebuilt-binaries.md new file mode 100644 index 000000000..34411cddd --- /dev/null +++ b/docs/content/en/_common/installation/03-prebuilt-binaries.md @@ -0,0 +1,23 @@ +--- +_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 --git a/docs/content/en/_common/installation/04-build-from-source.md b/docs/content/en/_common/installation/04-build-from-source.md new file mode 100644 index 000000000..3ce245f4a --- /dev/null +++ b/docs/content/en/_common/installation/04-build-from-source.md @@ -0,0 +1,38 @@ +--- +_comment: Do not remove front matter. +--- + +## Build from source + +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] + +> The install directory is controlled by the `GOPATH` and `GOBIN` environment variables. If `GOBIN` is set, binaries are installed to that directory. If `GOPATH` is set, binaries are installed to the bin subdirectory of the first directory in the `GOPATH` list. Otherwise, binaries are installed to the bin subdirectory of the default `GOPATH` (`$HOME/go` or `%USERPROFILE%\go`). + +To build the standard edition: + +```sh +go install github.com/gohugoio/hugo@latest +``` + +To build the extended edition: + +```sh +CGO_ENABLED=1 go install -tags extended github.com/gohugoio/hugo@latest +``` + +To build the extended/deploy edition: + +```sh +CGO_ENABLED=1 go install -tags extended,withdeploy github.com/gohugoio/hugo@latest +``` + +[Clang]: https://clang.llvm.org/ +[GCC]: https://gcc.gnu.org/ +[Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[Go documentation]: https://go.dev/doc/code#Command +[Go]: https://go.dev/doc/install diff --git a/docs/content/en/_common/installation/homebrew.md b/docs/content/en/_common/installation/homebrew.md new file mode 100644 index 000000000..14f48174e --- /dev/null +++ b/docs/content/en/_common/installation/homebrew.md @@ -0,0 +1,13 @@ +--- +_comment: Do not remove front matter. +--- + +### Homebrew + +[Homebrew] is a free and open-source package manager for macOS and Linux. To install the extended edition of Hugo: + +```sh +brew install hugo +``` + +[Homebrew]: https://brew.sh/ diff --git a/docs/content/en/_common/menu-entries/pre-and-post.md b/docs/content/en/_common/menu-entries/pre-and-post.md new file mode 100644 index 000000000..da3d584d1 --- /dev/null +++ b/docs/content/en/_common/menu-entries/pre-and-post.md @@ -0,0 +1,39 @@ +--- +_comment: Do not remove front matter. +--- + +In this site configuration we enable rendering of [emoji shortcodes], and add emoji shortcodes before (pre) and after (post) each menu entry: + +{{< code-toggle file=hugo >}} +enableEmoji = true + +[[menus.main]] +name = 'About' +pageRef = '/about' +post = ':point_left:' +pre = ':point_right:' +weight = 10 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +post = ':arrow_left:' +pre = ':arrow_right:' +weight = 20 +{{< /code-toggle >}} + +To render the menu: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li> + {{ .Pre | markdownify }} + <a href="{{ .URL }}">{{ .Name }}</a> + {{ .Post | markdownify }} + </li> + {{ end }} +</ul> +``` + +[emoji shortcodes]: /quick-reference/emojis/ diff --git a/docs/content/en/_common/menu-entry-properties.md b/docs/content/en/_common/menu-entry-properties.md new file mode 100644 index 000000000..daeadd79d --- /dev/null +++ b/docs/content/en/_common/menu-entry-properties.md @@ -0,0 +1,31 @@ +--- +_comment: Do not remove front matter. +--- + +<!-- +This description list intentionally excludes the `pageRef` and `url` properties. Add those properties manually after using the include shortcode to include this list. +--> + +identifier +: (`string`) Required when two or more menu entries have the same `name`, or when localizing the `name` using translation tables. Must start with a letter, followed by letters, digits, or underscores. + +name +: (`string`) The text to display when rendering the menu entry. + +params +: (`map`) User-defined properties for the menu entry. + +parent +: (`string`) The `identifier` of the parent menu entry. If `identifier` is not defined, use `name`. Required for child entries in a nested menu. + +post +: (`string`) The HTML to append when rendering the menu entry. + +pre +: (`string`) The HTML to prepend when rendering the menu entry. + +title +: (`string`) The HTML `title` attribute of the rendered menu entry. + +weight +: (`int`) A non-zero integer indicating the entry's position relative the root of the menu, or to its parent for a child entry. Lighter entries float to the top, while heavier entries sink to the bottom. diff --git a/docs/content/en/_common/methods/page/next-and-prev.md b/docs/content/en/_common/methods/page/next-and-prev.md new file mode 100644 index 000000000..f859961a4 --- /dev/null +++ b/docs/content/en/_common/methods/page/next-and-prev.md @@ -0,0 +1,60 @@ +--- +_comment: Do not remove front matter. +--- + +Hugo determines the _next_ and _previous_ page by sorting the site's collection of regular pages according to this sorting hierarchy: + +Field|Precedence|Sort direction +:--|:--|:-- +[`weight`]|1|descending +[`date`]|2|descending +[`linkTitle`]|3|descending +[`path`]|4|descending + +[`date`]: /methods/page/date/ +[`weight`]: /methods/page/weight/ +[`linkTitle`]: /methods/page/linktitle/ +[`path`]: /methods/page/path/ + +The sorted page collection used to determine the _next_ and _previous_ page is independent of other page collections, which may lead to unexpected behavior. + +For example, with this content structure: + +```text +content/ +├── pages/ +│ ├── _index.md +│ ├── page-1.md <-- front matter: weight = 10 +│ ├── page-2.md <-- front matter: weight = 20 +│ └── page-3.md <-- front matter: weight = 30 +└── _index.md +``` + +And these templates: + +```go-html-template {file="layouts/_default/list.html"} +{{ range .Pages.ByWeight }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +```go-html-template {file="layouts/_default/single.html"} +{{ with .Prev }} + <a href="{{ .RelPermalink }}">Previous</a> +{{ end }} + +{{ with .Next }} + <a href="{{ .RelPermalink }}">Next</a> +{{ end }} +``` + +When you visit page-2: + +- The `Prev` method points to page-3 +- The `Next` method points to page-1 + +To reverse the meaning of _next_ and _previous_ you can change the sort direction in your [site configuration], or use the [`Next`] and [`Prev`] methods on a `Pages` object for more flexibility. + +[site configuration]: /configuration/page/ +[`Next`]: /methods/pages/prev +[`Prev`]: /methods/pages/prev diff --git a/docs/content/en/_common/methods/page/nextinsection-and-previnsection.md b/docs/content/en/_common/methods/page/nextinsection-and-previnsection.md new file mode 100644 index 000000000..54d240eb4 --- /dev/null +++ b/docs/content/en/_common/methods/page/nextinsection-and-previnsection.md @@ -0,0 +1,78 @@ +--- +_comment: Do not remove front matter. +--- + +Hugo determines the _next_ and _previous_ page by sorting the current section's regular pages according to this sorting hierarchy: + +Field|Precedence|Sort direction +:--|:--|:-- +[`weight`]|1|descending +[`date`]|2|descending +[`linkTitle`]|3|descending +[`path`]|4|descending + +[`date`]: /methods/page/date/ +[`weight`]: /methods/page/weight/ +[`linkTitle`]: /methods/page/linktitle/ +[`path`]: /methods/page/path/ + +The sorted page collection used to determine the _next_ and _previous_ page is independent of other page collections, which may lead to unexpected behavior. + +For example, with this content structure: + +```text +content/ +├── pages/ +│ ├── _index.md +│ ├── page-1.md <-- front matter: weight = 10 +│ ├── page-2.md <-- front matter: weight = 20 +│ └── page-3.md <-- front matter: weight = 30 +└── _index.md +``` + +And these templates: + +```go-html-template {file="layouts/_default/list.html"} +{{ range .Pages.ByWeight }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +```go-html-template {file="layouts/_default/single.html"} +{{ with .PrevInSection }} + <a href="{{ .RelPermalink }}">Previous</a> +{{ end }} + +{{ with .NextInSection }} + <a href="{{ .RelPermalink }}">Next</a> +{{ end }} +``` + +When you visit page-2: + +- The `PrevInSection` method points to page-3 +- The `NextInSection` method points to page-1 + +To reverse the meaning of _next_ and _previous_ you can change the sort direction in your [site configuration], or use the [`Next`] and [`Prev`] methods on a `Pages` object for more flexibility. + +[site configuration]: /configuration/page/ +[`Next`]: /methods/pages/prev +[`Prev`]: /methods/pages/prev + +## Example + +Code defensively by checking for page existence: + +```go-html-template +{{ with .PrevInSection }} + <a href="{{ .RelPermalink }}">Previous</a> +{{ end }} + +{{ with .NextInSection }} + <a href="{{ .RelPermalink }}">Next</a> +{{ end }} +``` + +## Alternative + +Use the [`Next`] and [`Prev`] methods on a `Pages` object for more flexibility. diff --git a/docs/content/en/_common/methods/page/output-format-methods.md b/docs/content/en/_common/methods/page/output-format-methods.md new file mode 100644 index 000000000..1e914db03 --- /dev/null +++ b/docs/content/en/_common/methods/page/output-format-methods.md @@ -0,0 +1,35 @@ +--- +_comment: Do not remove front matter. +--- + +### Get IDENTIFIER + +(`any`) Returns the `OutputFormat` object with the given identifier. + +### MediaType + +(`media.Type`) Returns the media type of the output format. + +### MediaType.MainType + +(`string`) Returns the main type of the output format's media type. + +### MediaType.SubType + +(`string`) Returns the subtype of the current format's media type. + +### Name + +(`string`) Returns the output identifier of the output format. + +### Permalink + +(`string`) Returns the permalink of the page generated by the current output format. + +### Rel + +(`string`) Returns the `rel` value of the output format, either the default or as defined in the site configuration. + +### RelPermalink + +(`string`) Returns the relative permalink of the page generated by the current output format. diff --git a/docs/content/en/_common/methods/pages/group-sort-order.md b/docs/content/en/_common/methods/pages/group-sort-order.md new file mode 100644 index 000000000..e2997a1bd --- /dev/null +++ b/docs/content/en/_common/methods/pages/group-sort-order.md @@ -0,0 +1,5 @@ +--- +_comment: Do not remove front matter. +--- + +For the optional sort order, specify either `asc` for ascending order, or `desc` for descending order. diff --git a/docs/content/en/_common/methods/pages/next-and-prev.md b/docs/content/en/_common/methods/pages/next-and-prev.md new file mode 100644 index 000000000..462545c3f --- /dev/null +++ b/docs/content/en/_common/methods/pages/next-and-prev.md @@ -0,0 +1,72 @@ +--- +_comment: Do not remove front matter. +--- + +Hugo determines the _next_ and _previous_ page by sorting the page collection according to this sorting hierarchy: + +Field|Precedence|Sort direction +:--|:--|:-- +[`weight`]|1|descending +[`date`]|2|descending +[`linkTitle`]|3|descending +[`path`]|4|descending + +[`date`]: /methods/page/date/ +[`weight`]: /methods/page/weight/ +[`linkTitle`]: /methods/page/linktitle/ +[`path`]: /methods/page/path/ + +The sorted page collection used to determine the _next_ and _previous_ page is independent of other page collections, which may lead to unexpected behavior. + +For example, with this content structure: + +```text +content/ +├── pages/ +│ ├── _index.md +│ ├── page-1.md <-- front matter: weight = 10 +│ ├── page-2.md <-- front matter: weight = 20 +│ └── page-3.md <-- front matter: weight = 30 +└── _index.md +``` + +And these templates: + +```go-html-template {file="layouts/_default/list.html"} +{{ range .Pages.ByWeight }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +```go-html-template {file="layouts/_default/single.html"} +{{ $pages := .CurrentSection.Pages.ByWeight }} + +{{ with $pages.Prev . }} + <a href="{{ .RelPermalink }}">Previous</a> +{{ end }} + +{{ with $pages.Next . }} + <a href="{{ .RelPermalink }}">Next</a> +{{ end }} +``` + +When you visit page-2: + +- The `Prev` method points to page-3 +- The `Next` method points to page-1 + +To reverse the meaning of _next_ and _previous_ you can chain the [`Reverse`] method to the page collection definition: + +```go-html-template {file="layouts/_default/single.html"} +{{ $pages := .CurrentSection.Pages.ByWeight.Reverse }} + +{{ with $pages.Prev . }} + <a href="{{ .RelPermalink }}">Previous</a> +{{ end }} + +{{ with $pages.Next . }} + <a href="{{ .RelPermalink }}">Next</a> +{{ end }} +``` + +[`Reverse`]: /methods/pages/reverse/ diff --git a/docs/content/en/_common/methods/resource/global-page-remote-resources.md b/docs/content/en/_common/methods/resource/global-page-remote-resources.md new file mode 100644 index 000000000..49146aed4 --- /dev/null +++ b/docs/content/en/_common/methods/resource/global-page-remote-resources.md @@ -0,0 +1,6 @@ +--- +_comment: Do not remove front matter. +--- + +> [!note] +> Use this method with [global resources](g), [page resources](g), or [remote resources](g). diff --git a/docs/content/en/_common/methods/resource/processing-spec.md b/docs/content/en/_common/methods/resource/processing-spec.md new file mode 100644 index 000000000..395217328 --- /dev/null +++ b/docs/content/en/_common/methods/resource/processing-spec.md @@ -0,0 +1,36 @@ +--- +_comment: Do not remove front matter. +--- + +## Process specification + +The process specification is a space-delimited, case-insensitive list of one or more of the following in any sequence: + +action +: Applicable to the [`Process`](/methods/resource/process) method only. Specify zero or one of `crop`, `fill`, `fit`, or `resize`. If you specify an action you must also provide dimensions. + +dimensions +: Provide width _or_ height when using the [`Resize`](/methods/resource/resize) method, else provide both width _and_ height. See [details](/content-management/image-processing/#dimensions). + +anchor +: Use with the [`Crop`](/methods/resource/crop) and [`Fill`](/methods/resource/fill) methods. Specify zero or one of `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`. Default is `Smart`. See [details](/content-management/image-processing/#anchor). + +rotation +: Typically specify zero or one of `r90`, `r180`, or `r270`. Also supports arbitrary rotation angles. See [details](/content-management/image-processing/#rotation). + +target format +: Specify zero or one of `gif`, `jpeg`, `png`, `tiff`, or `webp`. See [details](/content-management/image-processing/#target-format). + +quality +: Applicable to JPEG and WebP images. Optionally specify `qN` where `N` is an integer in the range [0, 100]. Default is `75`. See [details](/content-management/image-processing/#quality). + +hint +: Applicable to WebP images and equivalent to the `-preset` flag for the [`cwebp`] encoder. Specify zero or one of `drawing`, `icon`, `photo`, `picture`, or `text`. Default is `photo`. See [details](/content-management/image-processing/#hint). + +[`cwebp`]: https://developers.google.com/speed/webp/docs/cwebp + +background color +: When converting a PNG or WebP with transparency to a format that does not support transparency, optionally specify a background color using a 3-digit or a 6-digit hexadecimal color code. Default is `#ffffff` (white). See [details](/content-management/image-processing/#background-color). + +resampling filter +: Typically specify zero or one of `Box`, `Lanczos`, `CatmullRom`, `MitchellNetravali`, `Linear`, or `NearestNeighbor`. Other resampling filters are available. See [details](/content-management/image-processing/#resampling-filter). diff --git a/docs/content/en/_common/methods/taxonomy/get-a-taxonomy-object.md b/docs/content/en/_common/methods/taxonomy/get-a-taxonomy-object.md new file mode 100644 index 000000000..6fb729c17 --- /dev/null +++ b/docs/content/en/_common/methods/taxonomy/get-a-taxonomy-object.md @@ -0,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: + +```go-html-template {file="layouts/_default/taxonomy.html"} +{{ $taxonomyObject := .Data.Terms }} +``` + +To inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump $taxonomyObject }}</pre> +``` + +Although the [`Alphabetical`] and [`ByCount`] methods provide a better data structure for ranging through the taxonomy, you can render the weighted pages by term directly from the `Taxonomy` object: + +```go-html-template +{{ range $term, $weightedPages := $taxonomyObject }} + <h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a></h2> + <ul> + {{ range $weightedPages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ 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 --git a/docs/content/en/_common/methods/taxonomy/ordered-taxonomy-element-methods.md b/docs/content/en/_common/methods/taxonomy/ordered-taxonomy-element-methods.md new file mode 100644 index 000000000..ec5f8e406 --- /dev/null +++ b/docs/content/en/_common/methods/taxonomy/ordered-taxonomy-element-methods.md @@ -0,0 +1,24 @@ +--- +_comment: Do not remove front matter. +--- + +An ordered taxonomy is a slice, where each element is an object that contains the term and a slice of its weighted pages. + +Each element of the slice provides these methods: + +Count +: (`int`) Returns the number of pages to which the term is assigned. + +Page +: (`page.Page`) Returns the term's `Page` object, useful for linking to the term page. + +Pages +: (`page.Pages`) Returns a `Pages` object containing the `Page` objects to which the term is assigned, sorted by [taxonomic weight](g). To sort or group, use any of the [methods] available to the `Pages` object. For example, sort by the last modification date. + +Term +: (`string`) Returns the term name. + +WeightedPages +: (`page.WeightedPages`) Returns a slice of weighted pages to which the term is assigned, sorted by taxonomic weight. The `Pages` method above is more flexible, allowing you to sort and group. + +[methods]: /methods/pages/ diff --git a/docs/content/en/_common/parsable-date-time-strings.md b/docs/content/en/_common/parsable-date-time-strings.md new file mode 100644 index 000000000..92842767e --- /dev/null +++ b/docs/content/en/_common/parsable-date-time-strings.md @@ -0,0 +1,14 @@ +--- +_comment: Do not remove front matter. +--- + +Format|Time zone +:--|:-- +`2023-10-15T13:18:50-07:00`|`America/Los_Angeles` +`2023-10-15T13:18:50-0700`|`America/Los_Angeles` +`2023-10-15T13:18:50Z`|`Etc/UTC` +`2023-10-15T13:18:50`|Default is `Etc/UTC` +`2023-10-15`|Default is `Etc/UTC` +`15 Oct 2023`|Default is `Etc/UTC` + +The last three examples are not fully qualified, and default to the `Etc/UTC` time zone. diff --git a/docs/content/en/_common/permalink-tokens.md b/docs/content/en/_common/permalink-tokens.md new file mode 100644 index 000000000..4aec68fb8 --- /dev/null +++ b/docs/content/en/_common/permalink-tokens.md @@ -0,0 +1,71 @@ +--- +_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. + +`: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. + +`: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 --git a/docs/content/en/_common/ref-and-relref-error-handling.md b/docs/content/en/_common/ref-and-relref-error-handling.md new file mode 100644 index 000000000..1d67bbc1f --- /dev/null +++ b/docs/content/en/_common/ref-and-relref-error-handling.md @@ -0,0 +1,10 @@ +--- +_comment: Do not remove front matter. +--- + +By default, Hugo will throw an error and fail the build if it cannot resolve the path. You can change this to a warning in your site configuration, and specify a URL to return when the path cannot be resolved. + +{{< code-toggle file=hugo >}} +refLinksErrorLevel = 'warning' +refLinksNotFoundURL = '/some/other/url' +{{< /code-toggle >}} diff --git a/docs/content/en/_common/ref-and-relref-options.md b/docs/content/en/_common/ref-and-relref-options.md new file mode 100644 index 000000000..ed0dd14c6 --- /dev/null +++ b/docs/content/en/_common/ref-and-relref-options.md @@ -0,0 +1,12 @@ +--- +_comment: Do not remove front matter. +--- + +path +: (`string`) The path to the target page. Paths without a leading slash (`/`) are resolved first relative to the current page, and then relative to the rest of the site. + +lang +: (`string`) The language of the target page. Default is the current language. Optional. + +outputFormat +: (`string`) The output format of the target page. Default is the current output format. Optional. diff --git a/docs/content/en/_common/render-hooks/pageinner.md b/docs/content/en/_common/render-hooks/pageinner.md new file mode 100644 index 000000000..a598b880a --- /dev/null +++ b/docs/content/en/_common/render-hooks/pageinner.md @@ -0,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" */%}} +``` + +Any render hook triggered while rendering `/posts/p2` will get: + +- `/posts/p1` when calling `Page` +- `/posts/p2` 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 --git a/docs/content/en/_common/scratch-pad-scope.md b/docs/content/en/_common/scratch-pad-scope.md new file mode 100644 index 000000000..b659497d8 --- /dev/null +++ b/docs/content/en/_common/scratch-pad-scope.md @@ -0,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`] +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 --git a/docs/content/en/_common/store-methods.md b/docs/content/en/_common/store-methods.md new file mode 100644 index 000000000..1dd776130 --- /dev/null +++ b/docs/content/en/_common/store-methods.md @@ -0,0 +1,86 @@ +--- +# Do not remove front matter. +--- + +## Methods + +### Set + +Sets the value of the given key. + +```go-html-template +{{ .Store.Set "greeting" "Hello" }} +``` + +### Get + +Gets the value of the given key. + +```go-html-template +{{ .Store.Set "greeting" "Hello" }} +{{ .Store.Get "greeting" }} → Hello +``` + +### Add + +Adds the given value to the existing value(s) of the given key. + +For single values, `Add` accepts values that support Go's `+` operator. If the first `Add` for a key is an array or slice, the following adds will be appended to that list. + +```go-html-template +{{ .Store.Set "greeting" "Hello" }} +{{ .Store.Add "greeting" "Welcome" }} +{{ .Store.Get "greeting" }} → HelloWelcome +``` + +```go-html-template +{{ .Store.Set "total" 3 }} +{{ .Store.Add "total" 7 }} +{{ .Store.Get "total" }} → 10 +``` + +```go-html-template +{{ .Store.Set "greetings" (slice "Hello") }} +{{ .Store.Add "greetings" (slice "Welcome" "Cheers") }} +{{ .Store.Get "greetings" }} → [Hello Welcome Cheers] +``` + +### SetInMap + +Takes a `key`, `mapKey` and `value` and adds a map of `mapKey` and `value` to the given `key`. + +```go-html-template +{{ .Store.SetInMap "greetings" "english" "Hello" }} +{{ .Store.SetInMap "greetings" "french" "Bonjour" }} +{{ .Store.Get "greetings" }} → map[english:Hello french:Bonjour] + ``` + +### DeleteInMap + +Takes a `key` and `mapKey` and removes the map of `mapKey` from the given `key`. + +```go-html-template +{{ .Store.SetInMap "greetings" "english" "Hello" }} +{{ .Store.SetInMap "greetings" "french" "Bonjour" }} +{{ .Store.DeleteInMap "greetings" "english" }} +{{ .Store.Get "greetings" }} → map[french:Bonjour] +``` + +### GetSortedMapValues + +Returns an array of values from `key` sorted by `mapKey`. + +```go-html-template +{{ .Store.SetInMap "greetings" "english" "Hello" }} +{{ .Store.SetInMap "greetings" "french" "Bonjour" }} +{{ .Store.GetSortedMapValues "greetings" }} → [Hello Bonjour] +``` + +### Delete + +Removes the given key. + +```go-html-template +{{ .Store.Set "greeting" "Hello" }} +{{ .Store.Delete "greeting" }} +``` diff --git a/docs/content/en/_common/syntax-highlighting-options.md b/docs/content/en/_common/syntax-highlighting-options.md new file mode 100644 index 000000000..36144e090 --- /dev/null +++ b/docs/content/en/_common/syntax-highlighting-options.md @@ -0,0 +1,56 @@ +--- +_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 --git a/docs/content/en/_common/time-layout-string.md b/docs/content/en/_common/time-layout-string.md new file mode 100644 index 000000000..3664eaef2 --- /dev/null +++ b/docs/content/en/_common/time-layout-string.md @@ -0,0 +1,46 @@ +--- +_comment: Do not remove front matter. +--- + +Format a `time.Time` value based on [Go's reference time]: + +[Go's reference time]: https://pkg.go.dev/time#pkg-constants + +```text +Mon Jan 2 15:04:05 MST 2006 +``` + +Create a layout string using these components: + +Description|Valid components +:--|:-- +Year|`"2006" "06"` +Month|`"Jan" "January" "01" "1"` +Day of the week|`"Mon" "Monday"` +Day of the month|`"2" "_2" "02"` +Day of the year|`"__2" "002"` +Hour|`"15" "3" "03"` +Minute|`"4" "04"` +Second|`"5" "05"` +AM/PM mark|`"PM"` +Time zone offsets|`"-0700" "-07:00" "-07" "-070000" "-07:00:00"` + +Replace the sign in the layout string with a Z to print Z instead of an offset for the UTC zone. + +Description|Valid components +:--|:-- +Time zone offsets|`"Z0700" "Z07:00" "Z07" "Z070000" "Z07:00:00"` + +```go-html-template +{{ $t := "2023-01-27T23:44:58-08:00" }} +{{ $t = time.AsTime $t }} +{{ $t = $t.Format "Jan 02, 2006 3:04 PM Z07:00" }} + +{{ $t }} → Jan 27, 2023 11:44 PM -08:00 +``` + +Strings such as `PST` and `CET` are not time zones. They are time zone _abbreviations_. + +Strings such as `-07:00` and `+01:00` are not time zones. They are time zone _offsets_. + +A time zone is a geographic area with the same local time. For example, the time zone abbreviated by `PST` and `PDT` (depending on Daylight Savings Time) is `America/Los_Angeles`. diff --git a/docs/content/en/_index.md b/docs/content/en/_index.md new file mode 100644 index 000000000..358f6a4d9 --- /dev/null +++ b/docs/content/en/_index.md @@ -0,0 +1,4 @@ +--- +title: The world's fastest framework for building websites +description: Hugo is one of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again. +--- diff --git a/docs/content/en/about/_index.md b/docs/content/en/about/_index.md new file mode 100644 index 000000000..e55800959 --- /dev/null +++ b/docs/content/en/about/_index.md @@ -0,0 +1,9 @@ +--- +title: About Hugo +linkTitle: About +description: Learn about Hugo and its features, privacy protections, and security model. +categories: [] +keywords: [] +weight: 10 +aliases: [/about-hugo/,/docs/] +--- diff --git a/docs/content/en/about/features.md b/docs/content/en/about/features.md new file mode 100644 index 000000000..ff1a6b8eb --- /dev/null +++ b/docs/content/en/about/features.md @@ -0,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. + +[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 --git a/docs/content/en/about/introduction.md b/docs/content/en/about/introduction.md new file mode 100644 index 000000000..9586d08f8 --- /dev/null +++ b/docs/content/en/about/introduction.md @@ -0,0 +1,34 @@ +--- +title: Introduction +description: Hugo is a static site generator written in Go, optimized for speed and designed for flexibility. +categories: [] +keywords: [] +weight: 10 +aliases: [/about/what-is-hugo/,/about/benefits/] +--- + +Hugo is a [static site generator] written in [Go], optimized for speed and designed for flexibility. With its advanced templating system and fast asset pipelines, Hugo renders a complete site in seconds, often less. + +Due to its flexible framework, multilingual support, and powerful taxonomy system, Hugo is widely used to create: + +- Corporate, government, nonprofit, education, news, event, and project sites +- Documentation sites +- Image portfolios +- Landing pages +- Business, professional, and personal blogs +- Resumes and CVs + +Use Hugo's embedded web server during development to instantly see changes to content, structure, behavior, and presentation. Then deploy the site to your host, or push changes to your Git provider for automated builds and deployment. + +And with [Hugo Modules], you can share content, assets, data, translations, themes, templates, and configuration with other projects via public or private Git repositories. + +Learn more about Hugo's [features], [privacy protections], and [security model]. + +[Go]: https://go.dev +[Hugo Modules]: /hugo-modules/ +[static site generator]: https://en.wikipedia.org/wiki/Static_site_generator +[features]: /about/features/ +[security model]: about/security/ +[privacy protections]: /configuration/privacy + +{{< youtube 0RKpf3rK57I >}} diff --git a/docs/content/en/about/license.md b/docs/content/en/about/license.md new file mode 100644 index 000000000..06a3a695d --- /dev/null +++ b/docs/content/en/about/license.md @@ -0,0 +1,75 @@ +--- +title: License +description: Hugo is released under the Apache 2.0 license. +categories: [] +keywords: [] +weight: 40 +--- + +## Apache License + +_Version 2.0, January 2004_ +_<http://www.apache.org/licenses/>_ + +### Terms and Conditions for use, reproduction, and distribution + +#### 1. Definitions + +“License” shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +“Licensor” shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +“Legal Entity” shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, “control” means **(i)** the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or **(ii)** ownership of fifty percent (50%) or more of the outstanding shares, or **(iii)** beneficial ownership of such entity. + +“You” (or “Your”) shall mean an individual or Legal Entity exercising permissions granted by this License. + +“Source” form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +“Object” form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +“Work” shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +“Derivative Works” shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +“Contribution” shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as “Not a Contribution.” + +“Contributor” shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +#### 2. Grant of Copyright License + +Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +#### 3. Grant of Patent License + +Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +#### 4. Redistribution + +You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +* **(a)** You must give any other recipients of the Work or Derivative Works a copy of this License; and +* **(b)** You must cause any modified files to carry prominent notices stating that You changed the files; and +* **(c)** You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and +* **(d)** If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +#### 5. Submission of Contributions + +Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +#### 6. Trademarks + +This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +#### 7. Disclaimer of Warranty + +Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +#### 8. Limitation of Liability + +In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +#### 9. Accepting Warranty or Additional Liability + +While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. diff --git a/docs/content/en/about/security.md b/docs/content/en/about/security.md new file mode 100644 index 000000000..509ca6a75 --- /dev/null +++ b/docs/content/en/about/security.md @@ -0,0 +1,58 @@ +--- +title: Security model +linkTitle: Security +description: A summary of Hugo's security model. +categories: [] +keywords: [] +weight: 30 +aliases: [/about/security-model/] +--- + +## Runtime security + +Hugo generates static websites, meaning the final output runs directly in the browser and interacts with any integrated APIs. However, during development and site building, the `hugo` executable itself is the runtime environment. + +Securing a runtime is a complex task. Hugo addresses this through a robust sandboxing approach and a strict security policy with default protections. Key features include: + +- Virtual file system: Hugo employs a virtual file system, limiting file access. Only the main project, not external components, can access files or directories outside the project root. +- Read-Only access: User-defined components have read-only access to the file system, preventing unintended modifications. +- Controlled external binaries: While Hugo utilizes external binaries for features like Asciidoctor support, these are strictly predefined with specific flags and are disabled by default. The [security policy] details these limitations. +- No arbitrary commands: To mitigate risks, Hugo intentionally avoids implementing general functions that would allow users to execute arbitrary operating system commands. + +This combination of sandboxing and strict defaults effectively minimizes potential security vulnerabilities during the Hugo build process. + +[security policy]: /configuration/security/ + +## Dependency security + +Hugo utilizes [Go Modules] to manage its dependencies, compiling as a static binary. Go Modules create a `go.sum` file, a critical security feature. This file acts as a database, storing the expected cryptographic checksums of all dependencies, including those required indirectly (transitive dependencies). + +[Hugo Modules], which extend Go Modules' functionality, also produce a `go.sum` file. To ensure dependency integrity, commit this `go.sum` file to your version control. If Hugo detects a checksum mismatch during the build process, it will fail, indicating a possible attempt to [tamper with your project's dependencies]. + +[Go Modules]: https://go.dev/wiki/Modules#modules +[Hugo Modules]: /hugo-modules/ +[tamper with your project's dependencies]: https://julienrenaux.fr/2019/12/20/github-actions-security-risk/ + +## Web application security + +Hugo's security philosophy is rooted in established security standards, primarily aligning with the threats defined by [OWASP]. For HTML output, Hugo operates under a clear trust model. This model assumes that template and configuration authors, the developers, are trustworthy. However, the data supplied to these templates is inherently considered untrusted. This distinction is crucial for understanding how Hugo handles potential security risks. + +[OWASP]: https://en.wikipedia.org/wiki/OWASP + +To prevent unintended escaping of data that developers know is safe, Hugo provides [`safe`] functions, such as [`safeHTML`]. These functions allow developers to explicitly mark data as trusted, bypassing the default escaping mechanisms. This is essential for scenarios where data is generated or sourced from reliable sources. However, an exception exists: enabling [inline shortcodes]. By activating this feature, you are implicitly trusting the logic within the shortcodes and the data contained within your content files. + +[`safeHTML`]: /functions/safe/html/ +[inline shortcodes]: /content-management/shortcodes/#inline + +It's vital to remember that Hugo is a static site generator. This architectural choice significantly reduces the attack surface by eliminating the complexities and vulnerabilities associated with dynamic user input. Unlike dynamic websites, Hugo generates static HTML files, minimizing the risk of real-time attacks. Regarding content, Hugo's default Markdown renderer is [configured to sanitize] potentially unsafe content. This default behavior ensures that potentially malicious code or scripts are removed or escaped. However, this setting can be reconfigured if you have a high degree of confidence in the safety of your content sources. + +[configured to sanitize]: /configuration/markup/#rendererunsafe + +In essence, Hugo prioritizes secure output by establishing a clear trust boundary between developers and data. By default, it errs on the side of caution, sanitizing potentially unsafe content and escaping data. Developers have the flexibility to adjust these defaults through [`safe`] functions and [configuration options], but they must do so with a clear understanding of the security implications. Hugo's static site generation model further strengthens its security posture by minimizing dynamic vulnerabilities. + +[`safe`]: /functions/safe +[configuration options]: /configuration/security + +## Configuration + +See [configure security](/configuration/security/). diff --git a/docs/content/en/commands/_index.md b/docs/content/en/commands/_index.md new file mode 100644 index 000000000..5869bfd9d --- /dev/null +++ b/docs/content/en/commands/_index.md @@ -0,0 +1,8 @@ +--- +title: Command line interface +linkTitle: CLI +description: Use the command line interface (CLI) to manage your site. +categories: [] +keywords: [] +weight: 10 +--- diff --git a/docs/content/en/commands/hugo.md b/docs/content/en/commands/hugo.md new file mode 100644 index 000000000..ef0bca9a5 --- /dev/null +++ b/docs/content/en/commands/hugo.md @@ -0,0 +1,84 @@ +--- +title: "hugo" +slug: hugo +url: /commands/hugo/ +--- +## hugo + +Build your site + +### Synopsis + +hugo is the main command, used to build your Hugo site. + +Hugo is a Fast and Flexible Static Site Generator +built with love by spf13 and friends in Go. + +Complete documentation is available at https://gohugo.io/. + +``` +hugo [flags] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + -D, --buildDrafts include content marked as draft + -E, --buildExpired include expired content + -F, --buildFuture include content with publishdate in the future + --cacheDir string filesystem path to cache directory + --cleanDestinationDir remove files from destination not found in static directories + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -c, --contentDir string filesystem path to content directory + -d, --destination string filesystem path to write files to + --disableKinds strings disable different kind of pages (home, RSS etc.) + --enableGitInfo add Git revision, date, author, and CODEOWNERS info to the pages + -e, --environment string build environment + --forceSyncStatic copy all files when static is changed. + --gc enable to run some cleanup tasks (remove unused cache files) after the build + -h, --help help for hugo + --ignoreCache ignores the cache directory + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + -l, --layoutDir string filesystem path to layout directory + --logLevel string log level (debug|info|warn|error) + --minify minify any supported output format (HTML, XML etc.) + --noBuildLock don't create .hugo_build.lock file + --noChmod don't sync permission mode of files + --noTimes don't sync modification time of files + --panicOnWarning panic on first WARNING log + --poll string set this to a poll interval, e.g --poll 700ms, to use a poll based approach to watch for file system changes + --printI18nWarnings print missing translations + --printMemoryUsage print memory usage to screen at intervals + --printPathWarnings print warnings on duplicate target paths etc. + --printUnusedTemplates print warnings on unused templates. + --quiet build in quiet mode + --renderSegments strings named segments to render (configured in the segments config) + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --templateMetrics display metrics about template executions + --templateMetricsHints calculate some improvement hints when combined with --templateMetrics + -t, --theme strings themes to use (located in /themes/THEMENAME/) + --themesDir string filesystem path to themes directory + --trace file write trace to file (not useful in general) + -w, --watch watch filesystem for changes and recreate as needed +``` + +### SEE ALSO + +* [hugo build](/commands/hugo_build/) - Build your site +* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell +* [hugo config](/commands/hugo_config/) - Display site configuration +* [hugo convert](/commands/hugo_convert/) - Convert front matter to another format +* [hugo deploy](/commands/hugo_deploy/) - Deploy your site to a cloud provider +* [hugo env](/commands/hugo_env/) - Display version and environment info +* [hugo gen](/commands/hugo_gen/) - Generate documentation and syntax highlighting styles +* [hugo import](/commands/hugo_import/) - Import a site from another system +* [hugo list](/commands/hugo_list/) - List content +* [hugo mod](/commands/hugo_mod/) - Manage modules +* [hugo new](/commands/hugo_new/) - Create new content +* [hugo server](/commands/hugo_server/) - Start the embedded web server +* [hugo version](/commands/hugo_version/) - Display version + diff --git a/docs/content/en/commands/hugo_build.md b/docs/content/en/commands/hugo_build.md new file mode 100644 index 000000000..582cbe511 --- /dev/null +++ b/docs/content/en/commands/hugo_build.md @@ -0,0 +1,72 @@ +--- +title: "hugo build" +slug: hugo_build +url: /commands/hugo_build/ +--- +## hugo build + +Build your site + +### Synopsis + +build is the main command, used to build your Hugo site. + +Hugo is a Fast and Flexible Static Site Generator +built with love by spf13 and friends in Go. + +Complete documentation is available at https://gohugo.io/. + +``` +hugo build [flags] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + -D, --buildDrafts include content marked as draft + -E, --buildExpired include expired content + -F, --buildFuture include content with publishdate in the future + --cacheDir string filesystem path to cache directory + --cleanDestinationDir remove files from destination not found in static directories + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -c, --contentDir string filesystem path to content directory + -d, --destination string filesystem path to write files to + --disableKinds strings disable different kind of pages (home, RSS etc.) + --enableGitInfo add Git revision, date, author, and CODEOWNERS info to the pages + -e, --environment string build environment + --forceSyncStatic copy all files when static is changed. + --gc enable to run some cleanup tasks (remove unused cache files) after the build + -h, --help help for build + --ignoreCache ignores the cache directory + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + -l, --layoutDir string filesystem path to layout directory + --logLevel string log level (debug|info|warn|error) + --minify minify any supported output format (HTML, XML etc.) + --noBuildLock don't create .hugo_build.lock file + --noChmod don't sync permission mode of files + --noTimes don't sync modification time of files + --panicOnWarning panic on first WARNING log + --poll string set this to a poll interval, e.g --poll 700ms, to use a poll based approach to watch for file system changes + --printI18nWarnings print missing translations + --printMemoryUsage print memory usage to screen at intervals + --printPathWarnings print warnings on duplicate target paths etc. + --printUnusedTemplates print warnings on unused templates. + --quiet build in quiet mode + --renderSegments strings named segments to render (configured in the segments config) + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --templateMetrics display metrics about template executions + --templateMetricsHints calculate some improvement hints when combined with --templateMetrics + -t, --theme strings themes to use (located in /themes/THEMENAME/) + --themesDir string filesystem path to themes directory + --trace file write trace to file (not useful in general) + -w, --watch watch filesystem for changes and recreate as needed +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site + diff --git a/docs/content/en/commands/hugo_completion.md b/docs/content/en/commands/hugo_completion.md new file mode 100644 index 000000000..ac60dc148 --- /dev/null +++ b/docs/content/en/commands/hugo_completion.md @@ -0,0 +1,46 @@ +--- +title: "hugo completion" +slug: hugo_completion +url: /commands/hugo_completion/ +--- +## hugo completion + +Generate the autocompletion script for the specified shell + +### Synopsis + +Generate the autocompletion script for hugo for the specified shell. +See each sub-command's help for details on how to use the generated script. + + +### Options + +``` + -h, --help help for completion +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site +* [hugo completion bash](/commands/hugo_completion_bash/) - Generate the autocompletion script for bash +* [hugo completion fish](/commands/hugo_completion_fish/) - Generate the autocompletion script for fish +* [hugo completion powershell](/commands/hugo_completion_powershell/) - Generate the autocompletion script for powershell +* [hugo completion zsh](/commands/hugo_completion_zsh/) - Generate the autocompletion script for zsh + diff --git a/docs/content/en/commands/hugo_completion_bash.md b/docs/content/en/commands/hugo_completion_bash.md new file mode 100644 index 000000000..41fb47c0c --- /dev/null +++ b/docs/content/en/commands/hugo_completion_bash.md @@ -0,0 +1,65 @@ +--- +title: "hugo completion bash" +slug: hugo_completion_bash +url: /commands/hugo_completion_bash/ +--- +## hugo completion bash + +Generate the autocompletion script for bash + +### Synopsis + +Generate the autocompletion script for the bash shell. + +This script depends on the 'bash-completion' package. +If it is not installed already, you can install it via your OS's package manager. + +To load completions in your current shell session: + + source <(hugo completion bash) + +To load completions for every new session, execute once: + +#### Linux: + + hugo completion bash > /etc/bash_completion.d/hugo + +#### macOS: + + hugo completion bash > $(brew --prefix)/etc/bash_completion.d/hugo + +You will need to start a new shell for this setup to take effect. + + +``` +hugo completion bash +``` + +### Options + +``` + -h, --help help for bash + --no-descriptions disable completion descriptions +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell + diff --git a/docs/content/en/commands/hugo_completion_fish.md b/docs/content/en/commands/hugo_completion_fish.md new file mode 100644 index 000000000..7f971c3ca --- /dev/null +++ b/docs/content/en/commands/hugo_completion_fish.md @@ -0,0 +1,56 @@ +--- +title: "hugo completion fish" +slug: hugo_completion_fish +url: /commands/hugo_completion_fish/ +--- +## hugo completion fish + +Generate the autocompletion script for fish + +### Synopsis + +Generate the autocompletion script for the fish shell. + +To load completions in your current shell session: + + hugo completion fish | source + +To load completions for every new session, execute once: + + hugo completion fish > ~/.config/fish/completions/hugo.fish + +You will need to start a new shell for this setup to take effect. + + +``` +hugo completion fish [flags] +``` + +### Options + +``` + -h, --help help for fish + --no-descriptions disable completion descriptions +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell + diff --git a/docs/content/en/commands/hugo_completion_powershell.md b/docs/content/en/commands/hugo_completion_powershell.md new file mode 100644 index 000000000..6ea17892b --- /dev/null +++ b/docs/content/en/commands/hugo_completion_powershell.md @@ -0,0 +1,53 @@ +--- +title: "hugo completion powershell" +slug: hugo_completion_powershell +url: /commands/hugo_completion_powershell/ +--- +## hugo completion powershell + +Generate the autocompletion script for powershell + +### Synopsis + +Generate the autocompletion script for powershell. + +To load completions in your current shell session: + + hugo completion powershell | Out-String | Invoke-Expression + +To load completions for every new session, add the output of the above command +to your powershell profile. + + +``` +hugo completion powershell [flags] +``` + +### Options + +``` + -h, --help help for powershell + --no-descriptions disable completion descriptions +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell + diff --git a/docs/content/en/commands/hugo_completion_zsh.md b/docs/content/en/commands/hugo_completion_zsh.md new file mode 100644 index 000000000..b9e79f9f3 --- /dev/null +++ b/docs/content/en/commands/hugo_completion_zsh.md @@ -0,0 +1,67 @@ +--- +title: "hugo completion zsh" +slug: hugo_completion_zsh +url: /commands/hugo_completion_zsh/ +--- +## hugo completion zsh + +Generate the autocompletion script for zsh + +### Synopsis + +Generate the autocompletion script for the zsh shell. + +If shell completion is not already enabled in your environment you will need +to enable it. You can execute the following once: + + echo "autoload -U compinit; compinit" >> ~/.zshrc + +To load completions in your current shell session: + + source <(hugo completion zsh) + +To load completions for every new session, execute once: + +#### Linux: + + hugo completion zsh > "${fpath[1]}/_hugo" + +#### macOS: + + hugo completion zsh > $(brew --prefix)/share/zsh/site-functions/_hugo + +You will need to start a new shell for this setup to take effect. + + +``` +hugo completion zsh [flags] +``` + +### Options + +``` + -h, --help help for zsh + --no-descriptions disable completion descriptions +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo completion](/commands/hugo_completion/) - Generate the autocompletion script for the specified shell + diff --git a/docs/content/en/commands/hugo_config.md b/docs/content/en/commands/hugo_config.md new file mode 100644 index 000000000..2b4eaafa1 --- /dev/null +++ b/docs/content/en/commands/hugo_config.md @@ -0,0 +1,53 @@ +--- +title: "hugo config" +slug: hugo_config +url: /commands/hugo_config/ +--- +## hugo config + +Display site configuration + +### Synopsis + +Display site configuration, both default and custom settings. + +``` +hugo config [command] [flags] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + --format string preferred file format (toml, yaml or json) (default "toml") + -h, --help help for config + --lang string the language to display config for. Defaults to the first language defined. + --printZero include config options with zero values (e.g. false, 0, "") in the output + --renderSegments strings named segments to render (configured in the segments config) + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site +* [hugo config mounts](/commands/hugo_config_mounts/) - Print the configured file mounts + diff --git a/docs/content/en/commands/hugo_config_mounts.md b/docs/content/en/commands/hugo_config_mounts.md new file mode 100644 index 000000000..06a781220 --- /dev/null +++ b/docs/content/en/commands/hugo_config_mounts.md @@ -0,0 +1,45 @@ +--- +title: "hugo config mounts" +slug: hugo_config_mounts +url: /commands/hugo_config_mounts/ +--- +## hugo config mounts + +Print the configured file mounts + +``` +hugo config mounts [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for mounts + --renderSegments strings named segments to render (configured in the segments config) + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo config](/commands/hugo_config/) - Display site configuration + diff --git a/docs/content/en/commands/hugo_convert.md b/docs/content/en/commands/hugo_convert.md new file mode 100644 index 000000000..a8d0b6a38 --- /dev/null +++ b/docs/content/en/commands/hugo_convert.md @@ -0,0 +1,47 @@ +--- +title: "hugo convert" +slug: hugo_convert +url: /commands/hugo_convert/ +--- +## hugo convert + +Convert front matter to another format + +### Synopsis + +Convert front matter to another format. + +See convert's subcommands toJSON, toTOML and toYAML for more information. + +### Options + +``` + -h, --help help for convert + -o, --output string filesystem path to write files to + --unsafe enable less safe operations, please backup first +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site +* [hugo convert toJSON](/commands/hugo_convert_tojson/) - Convert front matter to JSON +* [hugo convert toTOML](/commands/hugo_convert_totoml/) - Convert front matter to TOML +* [hugo convert toYAML](/commands/hugo_convert_toyaml/) - Convert front matter to YAML + diff --git a/docs/content/en/commands/hugo_convert_toJSON.md b/docs/content/en/commands/hugo_convert_toJSON.md new file mode 100644 index 000000000..fe81146f9 --- /dev/null +++ b/docs/content/en/commands/hugo_convert_toJSON.md @@ -0,0 +1,47 @@ +--- +title: "hugo convert toJSON" +slug: hugo_convert_toJSON +url: /commands/hugo_convert_tojson/ +--- +## hugo convert toJSON + +Convert front matter to JSON + +### Synopsis + +toJSON converts all front matter in the content directory +to use JSON for the front matter. + +``` +hugo convert toJSON [flags] [args] +``` + +### Options + +``` + -h, --help help for toJSON +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + -o, --output string filesystem path to write files to + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + --unsafe enable less safe operations, please backup first +``` + +### SEE ALSO + +* [hugo convert](/commands/hugo_convert/) - Convert front matter to another format + diff --git a/docs/content/en/commands/hugo_convert_toTOML.md b/docs/content/en/commands/hugo_convert_toTOML.md new file mode 100644 index 000000000..490b15ee6 --- /dev/null +++ b/docs/content/en/commands/hugo_convert_toTOML.md @@ -0,0 +1,47 @@ +--- +title: "hugo convert toTOML" +slug: hugo_convert_toTOML +url: /commands/hugo_convert_totoml/ +--- +## hugo convert toTOML + +Convert front matter to TOML + +### Synopsis + +toTOML converts all front matter in the content directory +to use TOML for the front matter. + +``` +hugo convert toTOML [flags] [args] +``` + +### Options + +``` + -h, --help help for toTOML +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + -o, --output string filesystem path to write files to + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + --unsafe enable less safe operations, please backup first +``` + +### SEE ALSO + +* [hugo convert](/commands/hugo_convert/) - Convert front matter to another format + diff --git a/docs/content/en/commands/hugo_convert_toYAML.md b/docs/content/en/commands/hugo_convert_toYAML.md new file mode 100644 index 000000000..9b00ce247 --- /dev/null +++ b/docs/content/en/commands/hugo_convert_toYAML.md @@ -0,0 +1,47 @@ +--- +title: "hugo convert toYAML" +slug: hugo_convert_toYAML +url: /commands/hugo_convert_toyaml/ +--- +## hugo convert toYAML + +Convert front matter to YAML + +### Synopsis + +toYAML converts all front matter in the content directory +to use YAML for the front matter. + +``` +hugo convert toYAML [flags] [args] +``` + +### Options + +``` + -h, --help help for toYAML +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + -o, --output string filesystem path to write files to + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory + --unsafe enable less safe operations, please backup first +``` + +### SEE ALSO + +* [hugo convert](/commands/hugo_convert/) - Convert front matter to another format + diff --git a/docs/content/en/commands/hugo_deploy.md b/docs/content/en/commands/hugo_deploy.md new file mode 100644 index 000000000..696acf51f --- /dev/null +++ b/docs/content/en/commands/hugo_deploy.md @@ -0,0 +1,55 @@ +--- +title: "hugo deploy" +slug: hugo_deploy +url: /commands/hugo_deploy/ +--- +## hugo deploy + +Deploy your site to a cloud provider + +### Synopsis + +Deploy your site to a cloud provider + +See https://gohugo.io/hosting-and-deployment/hugo-deploy/ for detailed +documentation. + + +``` +hugo deploy [flags] [args] +``` + +### Options + +``` + --confirm ask for confirmation before making changes to the target + --dryRun dry run + --force force upload of all files + -h, --help help for deploy + --invalidateCDN invalidate the CDN cache listed in the deployment target (default true) + --maxDeletes int maximum # of files to delete, or -1 to disable (default 256) + --target string target deployment from deployments section in config file; defaults to the first one + --workers int number of workers to transfer files. defaults to 10 (default 10) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site + diff --git a/docs/content/en/commands/hugo_env.md b/docs/content/en/commands/hugo_env.md new file mode 100644 index 000000000..7e21733a4 --- /dev/null +++ b/docs/content/en/commands/hugo_env.md @@ -0,0 +1,44 @@ +--- +title: "hugo env" +slug: hugo_env +url: /commands/hugo_env/ +--- +## hugo env + +Display version and environment info + +### Synopsis + +Display version and environment info. This is useful in Hugo bug reports + +``` +hugo env [flags] [args] +``` + +### Options + +``` + -h, --help help for env +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site + diff --git a/docs/content/en/commands/hugo_gen.md b/docs/content/en/commands/hugo_gen.md new file mode 100644 index 000000000..ae11a0321 --- /dev/null +++ b/docs/content/en/commands/hugo_gen.md @@ -0,0 +1,43 @@ +--- +title: "hugo gen" +slug: hugo_gen +url: /commands/hugo_gen/ +--- +## hugo gen + +Generate documentation and syntax highlighting styles + +### Synopsis + +Generate documentation for your project using Hugo's documentation engine, including syntax highlighting for various programming languages. + +### Options + +``` + -h, --help help for gen +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site +* [hugo gen chromastyles](/commands/hugo_gen_chromastyles/) - Generate CSS stylesheet for the Chroma code highlighter +* [hugo gen doc](/commands/hugo_gen_doc/) - Generate Markdown documentation for the Hugo CLI +* [hugo gen man](/commands/hugo_gen_man/) - Generate man pages for the Hugo CLI + diff --git a/docs/content/en/commands/hugo_gen_chromastyles.md b/docs/content/en/commands/hugo_gen_chromastyles.md new file mode 100644 index 000000000..2863e46b4 --- /dev/null +++ b/docs/content/en/commands/hugo_gen_chromastyles.md @@ -0,0 +1,50 @@ +--- +title: "hugo gen chromastyles" +slug: hugo_gen_chromastyles +url: /commands/hugo_gen_chromastyles/ +--- +## hugo gen chromastyles + +Generate CSS stylesheet for the Chroma code highlighter + +### Synopsis + +Generate CSS stylesheet for the Chroma code highlighter for a given style. This stylesheet is needed if markup.highlight.noClasses is disabled in config. + +See https://xyproto.github.io/splash/docs/all.html for a preview of the available styles + +``` +hugo gen chromastyles [flags] [args] +``` + +### Options + +``` + -h, --help help for chromastyles + --highlightStyle string foreground and background colors for highlighted lines, e.g. --highlightStyle "#fff000 bg:#000fff" + --lineNumbersInlineStyle string foreground and background colors for inline line numbers, e.g. --lineNumbersInlineStyle "#fff000 bg:#000fff" + --lineNumbersTableStyle string foreground and background colors for table line numbers, e.g. --lineNumbersTableStyle "#fff000 bg:#000fff" + --style string highlighter style (see https://xyproto.github.io/splash/docs/) (default "friendly") +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo gen](/commands/hugo_gen/) - Generate documentation and syntax highlighting styles + diff --git a/docs/content/en/commands/hugo_gen_doc.md b/docs/content/en/commands/hugo_gen_doc.md new file mode 100644 index 000000000..3d808e75c --- /dev/null +++ b/docs/content/en/commands/hugo_gen_doc.md @@ -0,0 +1,50 @@ +--- +title: "hugo gen doc" +slug: hugo_gen_doc +url: /commands/hugo_gen_doc/ +--- +## hugo gen doc + +Generate Markdown documentation for the Hugo CLI + +### Synopsis + +Generate Markdown documentation for the Hugo CLI. + This command is, mostly, used to create up-to-date documentation + of Hugo's command-line interface for https://gohugo.io/. + + It creates one Markdown file per command with front matter suitable + for rendering in Hugo. + +``` +hugo gen doc [flags] [args] +``` + +### Options + +``` + --dir string the directory to write the doc. (default "/tmp/hugodoc/") + -h, --help help for doc +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo gen](/commands/hugo_gen/) - Generate documentation and syntax highlighting styles + diff --git a/docs/content/en/commands/hugo_gen_man.md b/docs/content/en/commands/hugo_gen_man.md new file mode 100644 index 000000000..14fe859e3 --- /dev/null +++ b/docs/content/en/commands/hugo_gen_man.md @@ -0,0 +1,47 @@ +--- +title: "hugo gen man" +slug: hugo_gen_man +url: /commands/hugo_gen_man/ +--- +## hugo gen man + +Generate man pages for the Hugo CLI + +### Synopsis + +This command automatically generates up-to-date man pages of Hugo's + command-line interface. By default, it creates the man page files + in the "man" directory under the current directory. + +``` +hugo gen man [flags] [args] +``` + +### Options + +``` + --dir string the directory to write the man pages. (default "man/") + -h, --help help for man +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo gen](/commands/hugo_gen/) - Generate documentation and syntax highlighting styles + diff --git a/docs/content/en/commands/hugo_import.md b/docs/content/en/commands/hugo_import.md new file mode 100644 index 000000000..2b8e62951 --- /dev/null +++ b/docs/content/en/commands/hugo_import.md @@ -0,0 +1,43 @@ +--- +title: "hugo import" +slug: hugo_import +url: /commands/hugo_import/ +--- +## hugo import + +Import a site from another system + +### Synopsis + +Import a site from another system. + +Import requires a subcommand, e.g. `hugo import jekyll jekyll_root_path target_path`. + +### Options + +``` + -h, --help help for import +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site +* [hugo import jekyll](/commands/hugo_import_jekyll/) - hugo import from Jekyll + diff --git a/docs/content/en/commands/hugo_import_jekyll.md b/docs/content/en/commands/hugo_import_jekyll.md new file mode 100644 index 000000000..8746c156e --- /dev/null +++ b/docs/content/en/commands/hugo_import_jekyll.md @@ -0,0 +1,47 @@ +--- +title: "hugo import jekyll" +slug: hugo_import_jekyll +url: /commands/hugo_import_jekyll/ +--- +## hugo import jekyll + +hugo import from Jekyll + +### Synopsis + +hugo import from Jekyll. + +Import from Jekyll requires two paths, e.g. `hugo import jekyll jekyll_root_path target_path`. + +``` +hugo import jekyll [flags] [args] +``` + +### Options + +``` + --force allow import into non-empty target directory + -h, --help help for jekyll +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo import](/commands/hugo_import/) - Import a site from another system + diff --git a/docs/content/en/commands/hugo_list.md b/docs/content/en/commands/hugo_list.md new file mode 100644 index 000000000..741ca1d68 --- /dev/null +++ b/docs/content/en/commands/hugo_list.md @@ -0,0 +1,47 @@ +--- +title: "hugo list" +slug: hugo_list +url: /commands/hugo_list/ +--- +## hugo list + +List content + +### Synopsis + +List content. + +List requires a subcommand, e.g. hugo list drafts + +### Options + +``` + -h, --help help for list +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site +* [hugo list all](/commands/hugo_list_all/) - List all content +* [hugo list drafts](/commands/hugo_list_drafts/) - List draft content +* [hugo list expired](/commands/hugo_list_expired/) - List expired content +* [hugo list future](/commands/hugo_list_future/) - List future content +* [hugo list published](/commands/hugo_list_published/) - List published content + diff --git a/docs/content/en/commands/hugo_list_all.md b/docs/content/en/commands/hugo_list_all.md new file mode 100644 index 000000000..e0f1efdcb --- /dev/null +++ b/docs/content/en/commands/hugo_list_all.md @@ -0,0 +1,44 @@ +--- +title: "hugo list all" +slug: hugo_list_all +url: /commands/hugo_list_all/ +--- +## hugo list all + +List all content + +### Synopsis + +List all content including draft, future, and expired. + +``` +hugo list all [flags] [args] +``` + +### Options + +``` + -h, --help help for all +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo list](/commands/hugo_list/) - List content + diff --git a/docs/content/en/commands/hugo_list_drafts.md b/docs/content/en/commands/hugo_list_drafts.md new file mode 100644 index 000000000..25ddc78d3 --- /dev/null +++ b/docs/content/en/commands/hugo_list_drafts.md @@ -0,0 +1,44 @@ +--- +title: "hugo list drafts" +slug: hugo_list_drafts +url: /commands/hugo_list_drafts/ +--- +## hugo list drafts + +List draft content + +### Synopsis + +List draft content. + +``` +hugo list drafts [flags] [args] +``` + +### Options + +``` + -h, --help help for drafts +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo list](/commands/hugo_list/) - List content + diff --git a/docs/content/en/commands/hugo_list_expired.md b/docs/content/en/commands/hugo_list_expired.md new file mode 100644 index 000000000..1936b9920 --- /dev/null +++ b/docs/content/en/commands/hugo_list_expired.md @@ -0,0 +1,44 @@ +--- +title: "hugo list expired" +slug: hugo_list_expired +url: /commands/hugo_list_expired/ +--- +## hugo list expired + +List expired content + +### Synopsis + +List content with a past expiration date. + +``` +hugo list expired [flags] [args] +``` + +### Options + +``` + -h, --help help for expired +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo list](/commands/hugo_list/) - List content + diff --git a/docs/content/en/commands/hugo_list_future.md b/docs/content/en/commands/hugo_list_future.md new file mode 100644 index 000000000..3152639c2 --- /dev/null +++ b/docs/content/en/commands/hugo_list_future.md @@ -0,0 +1,44 @@ +--- +title: "hugo list future" +slug: hugo_list_future +url: /commands/hugo_list_future/ +--- +## hugo list future + +List future content + +### Synopsis + +List content with a future publication date. + +``` +hugo list future [flags] [args] +``` + +### Options + +``` + -h, --help help for future +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo list](/commands/hugo_list/) - List content + diff --git a/docs/content/en/commands/hugo_list_published.md b/docs/content/en/commands/hugo_list_published.md new file mode 100644 index 000000000..a7a08c7b4 --- /dev/null +++ b/docs/content/en/commands/hugo_list_published.md @@ -0,0 +1,44 @@ +--- +title: "hugo list published" +slug: hugo_list_published +url: /commands/hugo_list_published/ +--- +## hugo list published + +List published content + +### Synopsis + +List content that is not draft, future, or expired. + +``` +hugo list published [flags] [args] +``` + +### Options + +``` + -h, --help help for published +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo list](/commands/hugo_list/) - List content + diff --git a/docs/content/en/commands/hugo_mod.md b/docs/content/en/commands/hugo_mod.md new file mode 100644 index 000000000..25a27185d --- /dev/null +++ b/docs/content/en/commands/hugo_mod.md @@ -0,0 +1,59 @@ +--- +title: "hugo mod" +slug: hugo_mod +url: /commands/hugo_mod/ +--- +## hugo mod + +Manage modules + +### Synopsis + +Various helpers to help manage the modules in your project's dependency graph. +Most operations here requires a Go version installed on your system (>= Go 1.12) and the relevant VCS client (typically Git). +This is not needed if you only operate on modules inside /themes or if you have vendored them via "hugo mod vendor". + + +Note that Hugo will always start out by resolving the components defined in the site +configuration, provided by a _vendor directory (if no --ignoreVendorPaths flag provided), +Go Modules, or a folder inside the themes directory, in that order. + +See https://gohugo.io/hugo-modules/ for more information. + + + +### Options + +``` + -h, --help help for mod +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site +* [hugo mod clean](/commands/hugo_mod_clean/) - Delete the Hugo Module cache for the current project +* [hugo mod get](/commands/hugo_mod_get/) - Resolves dependencies in your current Hugo project +* [hugo mod graph](/commands/hugo_mod_graph/) - Print a module dependency graph +* [hugo mod init](/commands/hugo_mod_init/) - Initialize this project as a Hugo Module +* [hugo mod npm](/commands/hugo_mod_npm/) - Various npm helpers +* [hugo mod tidy](/commands/hugo_mod_tidy/) - Remove unused entries in go.mod and go.sum +* [hugo mod vendor](/commands/hugo_mod_vendor/) - Vendor all module dependencies into the _vendor directory +* [hugo mod verify](/commands/hugo_mod_verify/) - Verify dependencies + diff --git a/docs/content/en/commands/hugo_mod_clean.md b/docs/content/en/commands/hugo_mod_clean.md new file mode 100644 index 000000000..ff2255e53 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_clean.md @@ -0,0 +1,51 @@ +--- +title: "hugo mod clean" +slug: hugo_mod_clean +url: /commands/hugo_mod_clean/ +--- +## hugo mod clean + +Delete the Hugo Module cache for the current project + +### Synopsis + +Delete the Hugo Module cache for the current project. + +``` +hugo mod clean [flags] [args] +``` + +### Options + +``` + --all clean entire module cache + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for clean + --pattern string pattern matching module paths to clean (all if not set), e.g. "**hugo*" + --renderSegments strings named segments to render (configured in the segments config) + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Manage modules + diff --git a/docs/content/en/commands/hugo_mod_get.md b/docs/content/en/commands/hugo_mod_get.md new file mode 100644 index 000000000..a5c9a9ea9 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_get.md @@ -0,0 +1,75 @@ +--- +title: "hugo mod get" +slug: hugo_mod_get +url: /commands/hugo_mod_get/ +--- +## hugo mod get + +Resolves dependencies in your current Hugo project + +### Synopsis + + +Resolves dependencies in your current Hugo project. + +Some examples: + +Install the latest version possible for a given module: + + hugo mod get github.com/gohugoio/testshortcodes + +Install a specific version: + + hugo mod get github.com/gohugoio/testshortcodes@v0.3.0 + +Install the latest versions of all direct module dependencies: + + hugo mod get + hugo mod get ./... (recursive) + +Install the latest versions of all module dependencies (direct and indirect): + + hugo mod get -u + hugo mod get -u ./... (recursive) + +Run "go help get" for more information. All flags available for "go get" is also relevant here. + +Note that Hugo will always start out by resolving the components defined in the site +configuration, provided by a _vendor directory (if no --ignoreVendorPaths flag provided), +Go Modules, or a folder inside the themes directory, in that order. + +See https://gohugo.io/hugo-modules/ for more information. + + + +``` +hugo mod get [flags] [args] +``` + +### Options + +``` + -h, --help help for get +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Manage modules + diff --git a/docs/content/en/commands/hugo_mod_graph.md b/docs/content/en/commands/hugo_mod_graph.md new file mode 100644 index 000000000..cb2bdfb5a --- /dev/null +++ b/docs/content/en/commands/hugo_mod_graph.md @@ -0,0 +1,52 @@ +--- +title: "hugo mod graph" +slug: hugo_mod_graph +url: /commands/hugo_mod_graph/ +--- +## hugo mod graph + +Print a module dependency graph + +### Synopsis + +Print a module dependency graph with information about module status (disabled, vendored). +Note that for vendored modules, that is the version listed and not the one from go.mod. + + +``` +hugo mod graph [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + --clean delete module cache for dependencies that fail verification + -c, --contentDir string filesystem path to content directory + -h, --help help for graph + --renderSegments strings named segments to render (configured in the segments config) + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Manage modules + diff --git a/docs/content/en/commands/hugo_mod_init.md b/docs/content/en/commands/hugo_mod_init.md new file mode 100644 index 000000000..3315e97d6 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_init.md @@ -0,0 +1,56 @@ +--- +title: "hugo mod init" +slug: hugo_mod_init +url: /commands/hugo_mod_init/ +--- +## hugo mod init + +Initialize this project as a Hugo Module + +### Synopsis + +Initialize this project as a Hugo Module. + It will try to guess the module path, but you may help by passing it as an argument, e.g: + + hugo mod init github.com/gohugoio/testshortcodes + + Note that Hugo Modules supports multi-module projects, so you can initialize a Hugo Module + inside a subfolder on GitHub, as one example. + + +``` +hugo mod init [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for init + --renderSegments strings named segments to render (configured in the segments config) + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Manage modules + diff --git a/docs/content/en/commands/hugo_mod_npm.md b/docs/content/en/commands/hugo_mod_npm.md new file mode 100644 index 000000000..39a559e0f --- /dev/null +++ b/docs/content/en/commands/hugo_mod_npm.md @@ -0,0 +1,45 @@ +--- +title: "hugo mod npm" +slug: hugo_mod_npm +url: /commands/hugo_mod_npm/ +--- +## hugo mod npm + +Various npm helpers + +### Synopsis + +Various npm (Node package manager) helpers. + +``` +hugo mod npm [command] [flags] +``` + +### Options + +``` + -h, --help help for npm +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Manage modules +* [hugo mod npm pack](/commands/hugo_mod_npm_pack/) - Experimental: Prepares and writes a composite package.json file for your project + diff --git a/docs/content/en/commands/hugo_mod_npm_pack.md b/docs/content/en/commands/hugo_mod_npm_pack.md new file mode 100644 index 000000000..5ece05769 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_npm_pack.md @@ -0,0 +1,59 @@ +--- +title: "hugo mod npm pack" +slug: hugo_mod_npm_pack +url: /commands/hugo_mod_npm_pack/ +--- +## hugo mod npm pack + +Experimental: Prepares and writes a composite package.json file for your project + +### Synopsis + +Prepares and writes a composite package.json file for your project. + +On first run it creates a "package.hugo.json" in the project root if not already there. This file will be used as a template file +with the base dependency set. + +This set will be merged with all "package.hugo.json" files found in the dependency tree, picking the version closest to the project. + +This command is marked as 'Experimental'. We think it's a great idea, so it's not likely to be +removed from Hugo, but we need to test this out in "real life" to get a feel of it, +so this may/will change in future versions of Hugo. + + +``` +hugo mod npm pack [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for pack + --renderSegments strings named segments to render (configured in the segments config) + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo mod npm](/commands/hugo_mod_npm/) - Various npm helpers + diff --git a/docs/content/en/commands/hugo_mod_tidy.md b/docs/content/en/commands/hugo_mod_tidy.md new file mode 100644 index 000000000..c7ae40625 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_tidy.md @@ -0,0 +1,45 @@ +--- +title: "hugo mod tidy" +slug: hugo_mod_tidy +url: /commands/hugo_mod_tidy/ +--- +## hugo mod tidy + +Remove unused entries in go.mod and go.sum + +``` +hugo mod tidy [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for tidy + --renderSegments strings named segments to render (configured in the segments config) + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Manage modules + diff --git a/docs/content/en/commands/hugo_mod_vendor.md b/docs/content/en/commands/hugo_mod_vendor.md new file mode 100644 index 000000000..dc403affe --- /dev/null +++ b/docs/content/en/commands/hugo_mod_vendor.md @@ -0,0 +1,51 @@ +--- +title: "hugo mod vendor" +slug: hugo_mod_vendor +url: /commands/hugo_mod_vendor/ +--- +## hugo mod vendor + +Vendor all module dependencies into the _vendor directory + +### Synopsis + +Vendor all module dependencies into the _vendor directory. + If a module is vendored, that is where Hugo will look for it's dependencies. + + +``` +hugo mod vendor [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + -h, --help help for vendor + --renderSegments strings named segments to render (configured in the segments config) + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Manage modules + diff --git a/docs/content/en/commands/hugo_mod_verify.md b/docs/content/en/commands/hugo_mod_verify.md new file mode 100644 index 000000000..2f22a2e49 --- /dev/null +++ b/docs/content/en/commands/hugo_mod_verify.md @@ -0,0 +1,50 @@ +--- +title: "hugo mod verify" +slug: hugo_mod_verify +url: /commands/hugo_mod_verify/ +--- +## hugo mod verify + +Verify dependencies + +### Synopsis + +Verify checks that the dependencies of the current module, which are stored in a local downloaded source cache, have not been modified since being downloaded. + +``` +hugo mod verify [flags] [args] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + --clean delete module cache for dependencies that fail verification + -c, --contentDir string filesystem path to content directory + -h, --help help for verify + --renderSegments strings named segments to render (configured in the segments config) + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo mod](/commands/hugo_mod/) - Manage modules + diff --git a/docs/content/en/commands/hugo_new.md b/docs/content/en/commands/hugo_new.md new file mode 100644 index 000000000..2788ef168 --- /dev/null +++ b/docs/content/en/commands/hugo_new.md @@ -0,0 +1,50 @@ +--- +title: "hugo new" +slug: hugo_new +url: /commands/hugo_new/ +--- +## hugo new + +Create new content + +### Synopsis + +Create a new content file and automatically set the date and title. +It will guess which kind of file to create based on the path provided. + +You can also specify the kind with `-k KIND`. + +If archetypes are provided in your theme or site, they will be used. + +Ensure you run this within the root directory of your site. + +### Options + +``` + -h, --help help for new +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site +* [hugo new content](/commands/hugo_new_content/) - Create new content +* [hugo new site](/commands/hugo_new_site/) - Create a new site (skeleton) +* [hugo new theme](/commands/hugo_new_theme/) - Create a new theme (skeleton) + diff --git a/docs/content/en/commands/hugo_new_content.md b/docs/content/en/commands/hugo_new_content.md new file mode 100644 index 000000000..9624e9a61 --- /dev/null +++ b/docs/content/en/commands/hugo_new_content.md @@ -0,0 +1,59 @@ +--- +title: "hugo new content" +slug: hugo_new_content +url: /commands/hugo_new_content/ +--- +## hugo new content + +Create new content + +### Synopsis + +Create a new content file and automatically set the date and title. +It will guess which kind of file to create based on the path provided. + +You can also specify the kind with `-k KIND`. + +If archetypes are provided in your theme or site, they will be used. + +Ensure you run this within the root directory of your site. + +``` +hugo new content [path] [flags] +``` + +### Options + +``` + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --cacheDir string filesystem path to cache directory + -c, --contentDir string filesystem path to content directory + --editor string edit new content with this editor, if provided + -f, --force overwrite file if it already exists + -h, --help help for content + -k, --kind string content type to create + --renderSegments strings named segments to render (configured in the segments config) + -t, --theme strings themes to use (located in /themes/THEMENAME/) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo new](/commands/hugo_new/) - Create new content + diff --git a/docs/content/en/commands/hugo_new_site.md b/docs/content/en/commands/hugo_new_site.md new file mode 100644 index 000000000..0f0096ae4 --- /dev/null +++ b/docs/content/en/commands/hugo_new_site.md @@ -0,0 +1,48 @@ +--- +title: "hugo new site" +slug: hugo_new_site +url: /commands/hugo_new_site/ +--- +## hugo new site + +Create a new site (skeleton) + +### Synopsis + +Create a new site in the provided directory. +The new site will have the correct structure, but no content or theme yet. +Use `hugo new [contentPath]` to create new content. + +``` +hugo new site [path] [flags] +``` + +### Options + +``` + -f, --force init inside non-empty directory + --format string preferred file format (toml, yaml or json) (default "toml") + -h, --help help for site +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo new](/commands/hugo_new/) - Create new content + diff --git a/docs/content/en/commands/hugo_new_theme.md b/docs/content/en/commands/hugo_new_theme.md new file mode 100644 index 000000000..b1c937bae --- /dev/null +++ b/docs/content/en/commands/hugo_new_theme.md @@ -0,0 +1,47 @@ +--- +title: "hugo new theme" +slug: hugo_new_theme +url: /commands/hugo_new_theme/ +--- +## hugo new theme + +Create a new theme (skeleton) + +### Synopsis + +Create a new theme (skeleton) called [name] in ./themes. +New theme is a skeleton. Please add content to the touched files. Add your +name to the copyright line in the license and adjust the theme.toml file +according to your needs. + +``` +hugo new theme [name] [flags] +``` + +### Options + +``` + -h, --help help for theme +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo new](/commands/hugo_new/) - Create new content + diff --git a/docs/content/en/commands/hugo_server.md b/docs/content/en/commands/hugo_server.md new file mode 100644 index 000000000..d735f449a --- /dev/null +++ b/docs/content/en/commands/hugo_server.md @@ -0,0 +1,98 @@ +--- +title: "hugo server" +slug: hugo_server +url: /commands/hugo_server/ +--- +## hugo server + +Start the embedded web server + +### Synopsis + +Hugo provides its own webserver which builds and serves the site. +While hugo server is high performance, it is a webserver with limited options. + +The `hugo server` command will by default write and serve files from disk, but +you can render to memory by using the `--renderToMemory` flag. This can be +faster in some cases, but it will consume more memory. + +By default hugo will also watch your files for any changes you make and +automatically rebuild the site. It will then live reload any open browser pages +and push the latest content to them. As most Hugo sites are built in a fraction +of a second, you will be able to save and see your changes nearly instantly. + +``` +hugo server [command] [flags] +``` + +### Options + +``` + --appendPort append port to baseURL (default true) + -b, --baseURL string hostname (and path) to the root, e.g. https://spf13.com/ + --bind string interface to which the server will bind (default "127.0.0.1") + -D, --buildDrafts include content marked as draft + -E, --buildExpired include expired content + -F, --buildFuture include content with publishdate in the future + --cacheDir string filesystem path to cache directory + --cleanDestinationDir remove files from destination not found in static directories + -c, --contentDir string filesystem path to content directory + --disableBrowserError do not show build errors in the browser + --disableFastRender enables full re-renders on changes + --disableKinds strings disable different kind of pages (home, RSS etc.) + --disableLiveReload watch without enabling live browser reload on rebuild + --enableGitInfo add Git revision, date, author, and CODEOWNERS info to the pages + --forceSyncStatic copy all files when static is changed. + --gc enable to run some cleanup tasks (remove unused cache files) after the build + -h, --help help for server + --ignoreCache ignores the cache directory + -l, --layoutDir string filesystem path to layout directory + --liveReloadPort int port for live reloading (i.e. 443 in HTTPS proxy situations) (default -1) + --minify minify any supported output format (HTML, XML etc.) + -N, --navigateToChanged navigate to changed content file on live browser reload + --noChmod don't sync permission mode of files + --noHTTPCache prevent HTTP caching + --noTimes don't sync modification time of files + -O, --openBrowser open the site in a browser after server startup + --panicOnWarning panic on first WARNING log + --poll string set this to a poll interval, e.g --poll 700ms, to use a poll based approach to watch for file system changes + -p, --port int port on which the server will listen (default 1313) + --pprof enable the pprof server (port 8080) + --printI18nWarnings print missing translations + --printMemoryUsage print memory usage to screen at intervals + --printPathWarnings print warnings on duplicate target paths etc. + --printUnusedTemplates print warnings on unused templates. + --renderSegments strings named segments to render (configured in the segments config) + --renderStaticToDisk serve static files from disk and dynamic files from memory + --templateMetrics display metrics about template executions + --templateMetricsHints calculate some improvement hints when combined with --templateMetrics + -t, --theme strings themes to use (located in /themes/THEMENAME/) + --tlsAuto generate and use locally-trusted certificates. + --tlsCertFile string path to TLS certificate file + --tlsKeyFile string path to TLS key file + --trace file write trace to file (not useful in general) + -w, --watch watch filesystem for changes and recreate as needed (default true) +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site +* [hugo server trust](/commands/hugo_server_trust/) - Install the local CA in the system trust store + diff --git a/docs/content/en/commands/hugo_server_trust.md b/docs/content/en/commands/hugo_server_trust.md new file mode 100644 index 000000000..22ca2491e --- /dev/null +++ b/docs/content/en/commands/hugo_server_trust.md @@ -0,0 +1,41 @@ +--- +title: "hugo server trust" +slug: hugo_server_trust +url: /commands/hugo_server_trust/ +--- +## hugo server trust + +Install the local CA in the system trust store + +``` +hugo server trust [flags] [args] +``` + +### Options + +``` + -h, --help help for trust + --uninstall Uninstall the local CA (but do not delete it). +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo server](/commands/hugo_server/) - Start the embedded web server + diff --git a/docs/content/en/commands/hugo_version.md b/docs/content/en/commands/hugo_version.md new file mode 100644 index 000000000..14cc92a00 --- /dev/null +++ b/docs/content/en/commands/hugo_version.md @@ -0,0 +1,44 @@ +--- +title: "hugo version" +slug: hugo_version +url: /commands/hugo_version/ +--- +## hugo version + +Display version + +### Synopsis + +Display version and environment info. This is useful in Hugo bug reports. + +``` +hugo version [flags] [args] +``` + +### Options + +``` + -h, --help help for version +``` + +### Options inherited from parent commands + +``` + --clock string set the clock used by Hugo, e.g. --clock 2021-11-06T22:30:00.00+09:00 + --config string config file (default is hugo.yaml|json|toml) + --configDir string config dir (default "config") + -d, --destination string filesystem path to write files to + -e, --environment string build environment + --ignoreVendorPaths string ignores any _vendor for module paths matching the given Glob pattern + --logLevel string log level (debug|info|warn|error) + --noBuildLock don't create .hugo_build.lock file + --quiet build in quiet mode + -M, --renderToMemory render to memory (mostly useful when running the server) + -s, --source string filesystem path to read files relative from + --themesDir string filesystem path to themes directory +``` + +### SEE ALSO + +* [hugo](/commands/hugo/) - Build your site + diff --git a/docs/content/en/configuration/_index.md b/docs/content/en/configuration/_index.md new file mode 100644 index 000000000..7cb08cc73 --- /dev/null +++ b/docs/content/en/configuration/_index.md @@ -0,0 +1,7 @@ +--- +title: Configuration +description: Configure your site. +categories: [] +keywords: [] +weight: 10 +--- diff --git a/docs/content/en/configuration/all.md b/docs/content/en/configuration/all.md new file mode 100644 index 000000000..9bc05057f --- /dev/null +++ b/docs/content/en/configuration/all.md @@ -0,0 +1,362 @@ +--- +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 `<meta name="generator">` 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 `30s`. + +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 --git a/docs/content/en/configuration/build.md b/docs/content/en/configuration/build.md new file mode 100644 index 000000000..116294f05 --- /dev/null +++ b/docs/content/en/configuration/build.md @@ -0,0 +1,81 @@ +--- +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 --git a/docs/content/en/configuration/caches.md b/docs/content/en/configuration/caches.md new file mode 100644 index 000000000..03b499dcb --- /dev/null +++ b/docs/content/en/configuration/caches.md @@ -0,0 +1,30 @@ +--- +title: Configure file caches +linkTitle: Caches +description: Configure file caches. +categories: [] +keywords: [] +--- + +This is the default configuration: + +{{< code-toggle config=caches />}} + +## Keys + +dir +: (`string`) The absolute file system path where the cached files will be stored. You can begin the path with the `:cacheDir` or `:resourceDir` token. These tokens will be replaced with the actual configured cache directory and resource directory paths, respectively. + +maxAge +: (`string`) The [duration](g) a cached entry remains valid before being evicted. A value of `0` disables the cache. A value of `-1` means the cache entry never expires (the default). + +## Tokens + +`:cacheDir` +: (`string`) The designated cache directory. See [details](/configuration/all/#cachedir). + +`:project` +: (`string`) The base directory name of the current Hugo project. By default, this ensures each project has isolated file caches, so running `hugo --gc` will only affect the current project's cache and not those of other Hugo projects on the same machine. + +`:resourceDir` +: (`string`) The designated directory for caching output from [asset pipelines](g). See [details](/configuration/all/#resourcedir). diff --git a/docs/content/en/configuration/cascade.md b/docs/content/en/configuration/cascade.md new file mode 100644 index 000000000..d91996301 --- /dev/null +++ b/docs/content/en/configuration/cascade.md @@ -0,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 + +<!-- TODO +Update the <version> and <date> below when we actually get around to deprecating _target. + +We deprecated the `_target` front matter key in favor of `target` in <version> on <date>. Remove footnote #1 on or after 2026-03-10 (15 months after deprecation). +--> + +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}`. + +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 --git a/docs/content/en/configuration/content-types.md b/docs/content/en/configuration/content-types.md new file mode 100644 index 000000000..4c5b5a23b --- /dev/null +++ b/docs/content/en/configuration/content-types.md @@ -0,0 +1,63 @@ +--- +title: Configure content types +linkTitle: Content types +description: Configure content types. +categories: [] +keywords: [] +--- + +{{< new-in 0.144.0 />}} + +Hugo supports six [content formats](g): + +{{% include "/_common/content-format-table.md" %}} + +These can be used as either page content or [page resources](g). When used as page resources, their [resource type](g) is `page`. + +Consider this example of a [page bundle](g): + +```text +content/ +└── example/ + ├── index.md <-- content + ├── a.adoc <-- resource (resource type: page) + ├── b.html <-- resource (resource type: page) + ├── c.md <-- resource (resource type: page) + ├── d.org <-- resource (resource type: page) + ├── e.pdc <-- resource (resource type: page) + ├── f.rst <-- resource (resource type: page) + ├── g.jpg <-- resource (resource type: image) + └── h.png <-- resource (resource type: image) +``` + +The `index.md` file is the page's content, while the other files are page resources. Files `a` through `f` are of resource type `page`, while `g` and `h` are of resource type `image`. + +When you build a site, Hugo does not publish page resources having a resource type of `page`. For example, this is the result of building the site above: + +```text +public/ +├── example/ +│ ├── g.jpg +│ ├── h.png +│ └── index.html +└── index.html +``` + +The default behavior is appropriate in most cases. Given that page resources containing markup are typically intended for inclusion in the main content, publishing them independently is generally undesirable. + +The default behavior is determined by the `contentTypes` configuration: + +{{< code-toggle config=contentTypes />}} + +In this default configuration, page resources with those media types will have a resource type of `page`, and will not be automatically published. To change the resource type assignment from `page` to `text` for a given media type, remove the corresponding entry from the list. + +For example, to set the resource type of `text/html` files to `text`, thereby enabling automatic publication, remove the `text/html` entry: + +{{< code-toggle file=hugo >}} +contentTypes: + text/asciidoc: {} + text/markdown: {} + text/org: {} + text/pandoc: {} + text/rst: {} +{{< /code-toggle >}} diff --git a/docs/content/en/configuration/deployment.md b/docs/content/en/configuration/deployment.md new file mode 100644 index 000000000..fad50da63 --- /dev/null +++ b/docs/content/en/configuration/deployment.md @@ -0,0 +1,159 @@ +--- +title: Configure deployment +linkTitle: Deployment +description: Configure deployments to Amazon S3, Azure Blob Storage, or Google Cloud Storage. +categories: [] +keywords: [] +--- + +> [!note] +> This configuration is only relevant when running `hugo deploy`. See [details](/host-and-deploy/deploy-with-hugo-deploy/). + +## Top-level options + +These settings control the overall behavior of the deployment process. This is the default configuration: + +{{< code-toggle file=hugo config=deployment />}} + +confirm +: (`bool`) Whether to prompt for confirmation before deploying. Default is `false`. + +dryRun +: (`bool`) Whether to simulate the deployment without any remote changes. Default is `false`. + +force +: (`bool`) Whether to re-upload all files. Default is `false`. + +invalidateCDN +: (`bool`) Whether to invalidate the CDN cache listed in the deployment target. Default is `true`. + +maxDeletes +: (`int`) The maximum number of files to delete, or `-1` to disable. Default is `256`. + +matchers +: (`[]*Matcher`) A slice of [matchers](#matchers-1). + +order +: (`[]string`) An ordered slice of [regular expressions](g) that determines upload priority (left to right). Files not matching any expression are uploaded last in an arbitrary order. + +target +: (`string`) The target deployment [`name`](#name). Defaults to the first target. + +targets +: (`[]*Target`) A slice of [targets](#targets-1). + +workers +: (`int`) The number of concurrent workers to use when uploading files. Default is `10`. + +## Targets + +A target represents a deployment target such as "staging" or "production". + +cloudFrontDistributionID +: (`string`) The CloudFront Distribution ID, applicable if you are using the Amazon Web Services CloudFront CDN. Hugo will invalidate the CDN when deploying this target. + +exclude +: (`string`) A [glob](g) pattern matching files to exclude when deploying to this target. Local files failing the include/exclude filters are not uploaded, and remote files failing these filters are not deleted. + +googleCloudCDNOrigin +: (`string`) The Google Cloud project and CDN origin to invalidate when deploying this target, specified as `<project>/<origin>`. + +include +: (`string`) A [glob](g) pattern matching files to include when deploying to this target. Local files failing the include/exclude filters are not uploaded, and remote files failing these filters are not deleted. + +name +: (`string`) An arbitrary name for this target. + +stripIndexHTML +: (`bool`) Whether to map files named `<dir>/index.html` to `<dir>` on the remote (except for the root `index.html`). This is useful for key-value cloud storage (e.g., Amazon S3, Google Cloud Storage, Azure Blob Storage) to align canonical URLs with object keys. Default is `false`. + +url +: (`string`) The [destination URL](#destination-urls) for deployment. + +## Matchers + +A Matcher represents a configuration to be applied to files whose paths match +the specified pattern. + +cacheControl +: (`string`) The caching attributes to use when serving the blob. See [details][cacheControl]. + +contentEncoding +: (`string`) The encoding used for the blob's content, if any. See [details][contentEncoding]. + +contentType +: (`string`) The media type of the blob being written. See [details][contentType]. + +force +: (`bool`) Whether matching files should be re-uploaded. Useful when other route-determined metadata (e.g., `contentType`) has changed. Default is `false`. + +gzip +: (`bool`) Whether the file should be gzipped before upload. If so, the `ContentEncoding` field will automatically be set to `gzip`. Default is `false`. + +pattern +: (`string`) A [regular expression](g) used to match paths. Paths are converted to use forward slashes (`/`) before matching. + +[cacheControl]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control +[contentEncoding]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding +[contentType]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type + +## Destination URLs + +Service|URL example +:--|:-- +Amazon Simple Storage Service (S3)|`s3://my-bucket?region=us-west-1` +Azure Blob Storage|`azblob://my-container` +Google Cloud Storage (GCS)|`gs://my-bucket` + +With Google Cloud Storage you can target a subdirectory: + +```text +gs://my-bucket?prefix=a/subdirectory +``` + +You can also to deploy to storage servers compatible with Amazon S3 such as: + +- [Ceph] +- [MinIO] +- [SeaweedFS] + +[Ceph]: https://ceph.com/ +[Minio]: https://www.minio.io/ +[SeaweedFS]: https://github.com/chrislusf/seaweedfs + +For example, the `url` for a MinIO deployment target might resemble this: + +```text +s3://my-bucket?endpoint=https://my.minio.instance&awssdk=v2&use_path_style=true&disable_https=false +``` + +## Example + +{{< code-toggle file=hugo >}} +[deployment] + order = ['.jpg$', '.gif$'] + [[deployment.matchers]] + cacheControl = 'max-age=31536000, no-transform, public' + gzip = true + pattern = '^.+\.(js|css|svg|ttf)$' + [[deployment.matchers]] + cacheControl = 'max-age=31536000, no-transform, public' + gzip = false + pattern = '^.+\.(png|jpg)$' + [[deployment.matchers]] + contentType = 'application/xml' + gzip = true + pattern = '^sitemap\.xml$' + [[deployment.matchers]] + gzip = true + pattern = '^.+\.(html|xml|json)$' + [[deployment.targets]] + url = 's3://my_production_bucket?region=us-west-1' + cloudFrontDistributionID = 'E1234567890ABCDEF0' + exclude = '**.{heic,psd}' + name = 'production' + [[deployment.targets]] + url = 's3://my_staging_bucket?region=us-west-1' + exclude = '**.{heic,psd}' + name = 'staging' +{{< /code-toggle >}} diff --git a/docs/content/en/configuration/front-matter.md b/docs/content/en/configuration/front-matter.md new file mode 100644 index 000000000..9f51b8a5a --- /dev/null +++ b/docs/content/en/configuration/front-matter.md @@ -0,0 +1,91 @@ +--- +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. + +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. + +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`. + +[`slug`]: /content-management/front-matter/#slug + +To enable access to the Git author date, set [`enableGitInfo`] to `true`, or use\ +the `--enableGitInfo` flag when building your site. + +[`enableGitInfo`]: /configuration/all/#enablegitinfo + +Consider this example: + +{{< 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. diff --git a/docs/content/en/configuration/http-cache.md b/docs/content/en/configuration/http-cache.md new file mode 100644 index 000000000..788d22a08 --- /dev/null +++ b/docs/content/en/configuration/http-cache.md @@ -0,0 +1,107 @@ +--- +title: Configure the HTTP cache +linkTitle: HTTP cache +description: Configure the HTTP cache. +categories: [] +keywords: [] +--- + +> [!note] +> This configuration is only relevant when using the [`resources.GetRemote`] function. + +## Layered caching + +Hugo employs a layered caching system. + +```goat {.w-40} + .-----------. +| dynacache | + '-----+-----' + | + v + .----------. +| HTTP cache | + '-----+----' + | + v + .----------. +| file cache | + '-----+----' +``` + +Dynacache +: An in-memory cache employing a Least Recently Used (LRU) eviction policy. Entries are removed from the cache when changes occur, when they match [cache-busting] patterns, or under low-memory conditions. + +HTTP Cache +: An HTTP cache for remote resources as specified in [RFC 9111]. Optimal performance is achieved when resources include appropriate HTTP cache headers. The HTTP cache utilizes the file cache for storage and retrieval of cached resources. + +File cache +: See [configure file caches]. + +The HTTP cache involves two key aspects: determining which content to cache (the caching process itself) and defining the frequency with which to check for updates (the polling strategy). + +## HTTP caching + +The HTTP cache behavior is defined for a configured set of resources. Stale resources will be refreshed from the file cache, even if their configured Time-To-Live (TTL) has not expired. If HTTP caching is disabled for a resource, Hugo will bypass the cache and access the file directly. + +The default configuration disables everything: + +{{< code-toggle file=hugo >}} +[HTTPCache.cache.for] +excludes = ['**'] +includes = [] +{{< /code-toggle >}} + +cache.for.excludes +: (`string`) A list of [glob](g) patterns to exclude from caching. + +cache.for.includes +: (`string`) A list of [glob](g) patterns to cache. + +## HTTP polling + +Polling is used in watch mode (e.g., `hugo server`) to detect changes in remote resources. Polling can be enabled even if HTTP caching is disabled. Detected changes trigger a rebuild of pages using the affected resource. Polling can be disabled for specific resources, typically those known to be static. + +The default configuration disables everything: + +{{< code-toggle file=hugo >}} +[[HTTPCache.polls]] +disable = true +high = '0s' +low = '0s' +[HTTPCache.polls.for] +includes = ['**'] +excludes = [] +{{< /code-toggle >}} + +polls +: A slice of polling configurations. + +polls.disable +: (`bool`) Whether to disable polling for this configuration. + +polls.low +: (`string`) The minimum polling interval expressed as a [duration](g). This is used after a recent change and gradually increases towards `polls.high`. + +polls.high +: (`string`) The maximum polling interval expressed as a [duration](g). This is used when the resource is considered stable. + +polls.for.excludes +: (`string`) A list of [glob](g) patterns to exclude from polling for this configuration. + +polls.for.includes +: (`string`) A list of [glob](g) patterns to include in polling for this configuration. + +## Behavior + +Polling and HTTP caching interact as follows: + +- With polling enabled, rebuilds are triggered only by actual changes, detected via `eTag` changes (Hugo generates an MD5 hash if the server doesn't provide one). +- If polling is enabled but HTTP caching is disabled, the remote is checked for changes only after the file cache's TTL expires (e.g., a `maxAge` of `10h` with a `1s` polling interval is inefficient). +- If both polling and HTTP caching are enabled, changes are checked for even before the file cache's TTL expires. Cached `eTag` and `last-modified` values are sent in `if-none-match` and `if-modified-since` headers, respectively, and a cached response is returned on HTTP [304]. + +[`resources.GetRemote`]: /functions/resources/getremote/ +[304]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304 +[cache-busting]: /configuration/build/#cache-busters +[configure file caches]: /configuration/caches/ +[RFC 9111]: https://datatracker.ietf.org/doc/html/rfc9111 diff --git a/docs/content/en/configuration/imaging.md b/docs/content/en/configuration/imaging.md new file mode 100644 index 000000000..13ecf9c26 --- /dev/null +++ b/docs/content/en/configuration/imaging.md @@ -0,0 +1,69 @@ +--- +title: Configure imaging +linkTitle: Imaging +description: Configure imaging. +categories: [] +keywords: [] +--- + +## Processing options + +These are the default settings for processing images: + +{{< code-toggle file=hugo >}} +[imaging] +anchor = 'Smart' +bgColor = '#ffffff' +hint = 'photo' +quality = 75 +resampleFilter = 'box' +{{< /code-toggle >}} + +anchor +: (`string`) When using the [`Crop`] or [`Fill`] method, the anchor determines the placement of the crop box. One of `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`. Default is `Smart`. + +bgColor +: (`string`) The background color of the resulting image. Applicable when converting from a format that supports transparency to a format that does not support transparency, for example, when converting from PNG to JPEG. Expressed as an RGB [hexadecimal] value. Default is `#ffffff`. + +[hexadecimal]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color + +hint +: (`string`) Applicable to WebP images, this option corresponds to a set of predefined encoding parameters. One of `drawing`, `icon`, `photo`, `picture`, or `text`. Default is `photo`. See [details](/content-management/image-processing/#hint). + +quality +: (`int`) Applicable to JPEG and WebP images, this value determines the quality of the converted image. Higher values produce better quality images, while lower values produce smaller files. Set this value to a whole number between `1` and `100`, inclusive. Default is `75`. + +resampleFilter +: (`string`) The resampling filter used when resizing an image. Default is `box`. See [details](/content-management/image-processing/#resampling-filter) + +## EXIF data + +These are the default settings for extracting EXIF data from images: + +{{< code-toggle file=hugo >}} +[imaging.exif] +includeFields = "" +excludeFields = "" +disableDate = false +disableLatLong = false +{{< /code-toggle >}} + +disableDate +: (`bool`) Whether to disable extraction of the image creation date/time. Default is `false`. + +disableLatLong +: (`bool`) Whether to disable extraction of the GPS latitude and longitude. Default is `false`. + +excludeFields +: (`string`) A [regular expression](g) matching the tags to exclude when extracting EXIF data. + +includeFields +: (`string`) A [regular expression](g) matching the tags to include when extracting EXIF data. To include all available tags, set this value to `".*"`. + +> [!note] +> To improve performance and decrease cache size, Hugo excludes the following tags: `ColorSpace`, `Contrast`, `Exif`, `Exposure[M|P|B]`, `Flash`, `GPS`, `JPEG`, `Metering`, `Resolution`, `Saturation`, `Sensing`, `Sharp`, and `WhiteBalance`. +> +> To control tag availability, change the `excludeFields` or `includeFields` settings as described above. + +[`Crop`]: /methods/resource/crop/ +[`Fill`]: /methods/resource/fill/ diff --git a/docs/content/en/configuration/introduction.md b/docs/content/en/configuration/introduction.md new file mode 100644 index 000000000..121a483c4 --- /dev/null +++ b/docs/content/en/configuration/introduction.md @@ -0,0 +1,284 @@ +--- +title: Introduction +description: Configure your site using files, directories, and environment variables. +categories: [] +keywords: [] +weight: 10 +--- + +## Sensible defaults + +Hugo offers many configuration options, but its defaults are often sufficient. A new site requires only these settings: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/' +languageCode = 'en-us' +title = 'My New Hugo Site' +{{< /code-toggle >}} + +Only define settings that deviate from the defaults. A smaller configuration file is easier to read, understand, and debug. Keep your configuration concise. + +> [!note] +> The best configuration file is a short configuration file. + +## Configuration file + +Create a site configuration file in the root of your project directory, naming it `hugo.toml`, `hugo.yaml`, or `hugo.json`, with that order of precedence. + +```text +my-project/ +└── hugo.toml +``` + +> [!note] +> For versions v0.109.0 and earlier, the site configuration file was named `config`. While you can still use this name, it's recommended to switch to the newer naming convention, `hugo`. + +A simple example: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/' +languageCode = 'en-us' +title = 'ABC Widgets, Inc.' +[params] +subtitle = 'The Best Widgets on Earth' +[params.contact] +email = 'info@example.org' +phone = '+1 202-555-1212' +{{< /code-toggle >}} + +To use a different configuration file when building your site, use the `--config` flag: + +```sh +hugo --config other.toml +``` + +Combine two or more configuration files, with left-to-right precedence: + +```sh +hugo --config a.toml,b.yaml,c.json +``` + +> [!note] +> See the specifications for each file format: [TOML], [YAML], and [JSON]. + +## Configuration directory + +Instead of a single site configuration file, split your configuration by [environment](g), root configuration key, and language. For example: + +```text +my-project/ +└── config/ + ├── _default/ + │ ├── hugo.toml + │ ├── menus.en.toml + │ ├── menus.de.toml + │ └── params.toml + └── production/ + └── params.toml +``` + +The root configuration keys are {{< root-configuration-keys >}}. + +### Omit the root key + +When splitting the configuration by root key, omit the root key in the component file. For example, these are equivalent: + +{{< code-toggle file=config/_default/hugo >}} +[params] +foo = 'bar' +{{< /code-toggle >}} + +{{< code-toggle file=config/_default/params >}} +foo = 'bar' +{{< /code-toggle >}} + +### Recursive parsing + +Hugo parses the `config` directory recursively, allowing you to organize the files into subdirectories. For example: + +```text +my-project/ +└── config/ + └── _default/ + ├── navigation/ + │ ├── menus.de.toml + │ └── menus.en.toml + └── hugo.toml +``` + +### Example + +```text +my-project/ +└── config/ + ├── _default/ + │ ├── hugo.toml + │ ├── menus.en.toml + │ ├── menus.de.toml + │ └── params.toml + ├── production/ + │ ├── hugo.toml + │ └── params.toml + └── staging/ + ├── hugo.toml + └── params.toml +``` + +Considering the structure above, when running `hugo --environment staging`, Hugo will use every setting from `config/_default` and merge `staging`'s on top of those. + +Let's take an example to understand this better. Let's say you are using Google Analytics for your website. This requires you to specify a [Google tag ID] in your site configuration: + +{{< code-toggle file=hugo >}} +[services.googleAnalytics] +ID = 'G-XXXXXXXXX' +{{< /code-toggle >}} + +Now consider the following scenario: + +1. You don't want to load the analytics code when running `hugo server`. +1. You want to use different Google tag IDs for your production and staging environments. For example: + - `G-PPPPPPPPP` for production + - `G-SSSSSSSSS` for staging + +To satisfy these requirements, configure your site as follows: + +1. `config/_default/hugo.toml` + - Exclude the `services.googleAnalytics` section. This will prevent loading of the analytics code when you run `hugo server`. + - By default, Hugo sets its `environment` to `development` when running `hugo server`. In the absence of a `config/development` directory, Hugo uses the `config/_default` directory. +1. `config/production/hugo.toml` + - Include this section only: + + {{< code-toggle file=hugo >}} + [services.googleAnalytics] + ID = 'G-PPPPPPPPP' + {{< /code-toggle >}} + + - You do not need to include other parameters in this file. Include only those parameters that are specific to your production environment. Hugo will merge these parameters with the default configuration. + - By default, Hugo sets its `environment` to `production` when running `hugo`. The analytics code will use the `G-PPPPPPPPP` tag ID. + +1. `config/staging/hugo.toml` + + - Include this section only: + + {{< code-toggle file=hugo >}} + [services.googleAnalytics] + ID = 'G-SSSSSSSSS' + {{< /code-toggle >}} + + - You do not need to include other parameters in this file. Include only those parameters that are specific to your staging environment. Hugo will merge these parameters with the default configuration. + - To build your staging site, run `hugo --environment staging`. The analytics code will use the `G-SSSSSSSSS` tag ID. + +## Merge configuration settings + +Hugo merges configuration settings from themes and modules, prioritizing the project's own settings. Given this simplified project structure with two themes: + +```text +project/ +├── themes/ +│ ├── theme-a/ +│ │ └── hugo.toml +│ └── theme-b/ +│ └── hugo.toml +└── hugo.toml +``` + +and this project-level configuration: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/' +languageCode = 'en-us' +title = 'My New Hugo Site' +theme = ['theme-a','theme-b'] +{{< /code-toggle >}} + +Hugo merges settings in this order: + +1. Project configuration (`hugo.toml` in the project root) +1. `theme-a` configuration +1. `theme-b` configuration + +The `_merge` setting within each top-level configuration key controls _which_ settings are merged and _how_ they are merged. + +The value for `_merge` can be one of: + +none +: No merge. + +shallow +: Only add values for new keys. + +deep +: Add values for new keys, merge existing. + +Note that you don't need to be so verbose as in the default setup below; a `_merge` value higher up will be inherited if not set. + +{{< code-toggle file=hugo dataKey="config_helpers.mergeStrategy" skipHeader=true />}} + +## Environment variables + +You can also configure settings using operating system environment variables: + +```sh +export HUGO_BASEURL=https://example.org/ +export HUGO_ENABLEGITINFO=true +export HUGO_ENVIRONMENT=staging +hugo +``` + +The above sets the [`baseURL`], [`enableGitInfo`], and [`environment`] configuration options and then builds your site. + +> [!note] +> An environment variable takes precedence over the values set in the configuration file. This means that if you set a configuration value with both an environment variable and in the configuration file, the value in the environment variable will be used. + +Environment variables simplify configuration for [CI/CD](g) deployments like GitHub Pages, GitLab Pages, and Netlify by allowing you to set values directly within their respective configuration and workflow files. + +> [!note] +> Environment variable names must be prefixed with `HUGO_`. +> +> To set custom site parameters, prefix the name with `HUGO_PARAMS_`. + +For snake_case variable names, the standard `HUGO_` prefix won't work. Hugo infers the delimiter from the first character following `HUGO`. This allows for variations like `HUGOxPARAMSxAPI_KEY=abcdefgh` using any [permitted delimiter]. + +In addition to configuring standard settings, environment variables may be used to override default values for certain internal settings: + +DART_SASS_BINARY +: (`string`) The absolute path to the Dart Sass executable. By default, Hugo searches for the executable in each of the paths in the `PATH` environment variable. + +HUGO_FILE_LOG_FORMAT +: (`string`) A format string for the file path, line number, and column number displayed when reporting errors, or when calling the `Position` method from a shortcode or Markdown render hook. Valid tokens are `:file`, `:line`, and `:col`. Default is `:file::line::col`. + +HUGO_MEMORYLIMIT +: {{< new-in 0.123.0 />}} +: (`int`) The maximum amount of system memory, in gigabytes, that Hugo can use while rendering your site. Default is 25% of total system memory. Note that The `HUGO_MEMORYLIMIT` is a “best effort” setting. Don't expect Hugo to build a million pages with only 1 GB memory. You can get more information about how this behaves during the build by building with `hugo --logLevel info` and look for the `dynacache` label. + +HUGO_NUMWORKERMULTIPLIER +: (`int`) The number of workers used in parallel processing. Default is the number of logical CPUs. + +## Current configuration + +Display the complete site configuration with: + +```sh +hugo config +``` + +Display a specific configuration setting with: + +```sh +hugo config | grep [key] +``` + +Display the configured file mounts with: + +```sh +hugo config mounts +``` + +[`baseURL`]: /configuration/all#baseurl +[`enableGitInfo`]: /configuration/all#enablegitinfo +[`environment`]: /configuration/all#environment +[Google tag ID]: https://support.google.com/tagmanager/answer/12326985?hl=en +[JSON]: https://datatracker.ietf.org/doc/html/rfc7159 +[permitted delimiter]: https://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html +[TOML]: https://toml.io/en/latest +[YAML]: https://yaml.org/spec/ diff --git a/docs/content/en/configuration/languages.md b/docs/content/en/configuration/languages.md new file mode 100644 index 000000000..540cfd34f --- /dev/null +++ b/docs/content/en/configuration/languages.md @@ -0,0 +1,193 @@ +--- +title: Configure languages +linkTitle: Languages +description: Configure the languages in your multilingual site. +categories: [] +keywords: [] +--- + +## Base settings + +Configure the following base settings within the site's root configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' +defaultContentLanguageInSubdir = false +disableDefaultLanguageRedirect = false +disableLanguages = [] +{{< /code-toggle >}} + +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](#language-keys). Default is `en`. + +defaultContentLanguageInSubdir +: (`bool`) Whether to publish the default language site to a subdirectory matching the `defaultContentLanguage`. 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`. + +disableLanguages +: (`[]string]`) A slice of language keys representing the languages to disable during the build process. Although this is functional, consider using the [`disabled`](#disabled) key under each language instead. + +## Language settings + +Configure each language under the `languages` key: + +{{< code-toggle config=languages />}} + +In the above, `en` is the [language key](#language-keys). + +disabled +: (`bool`) Whether to disable this language when building the site. Default is `false`. + +languageCode +: (`string`) The language tag as described in [RFC 5646]. This value does not affect localization or URLs. Hugo uses this value to populate: + + - The `lang` attribute of the `html` element in the [embedded alias template] + - The `language` element in the [embedded RSS template] + - The `locale` property in the [embedded OpenGraph template] + + Access this value from a template using the [`Language.LanguageCode`] method on a `Site` or `Page` object. + +languageDirection +: (`string`) The language direction, either left-to-right (`ltr`) or right-to-left (`rtl`). Use this value in your templates with the global [`dir`] HTML attribute. Access this value from a template using the [`Language.LanguageDirection`] method on a `Site` or `Page` object. + +languageName +: (`string`) The language name, typically used when rendering a language switcher. Access this value from a template using the [`Language.LanguageName`] method on a `Site` or `Page` object. + +title +: (`string`) The site title for this language. Access this value from a template using the [`Title`] method on a `Site` object. + +weight +: (`int`) The language [weight](g). When set to a non-zero value, this is the primary sort criteria for this language. Access this value from a template using the [`Language.Weight`] method on a `Site` or `Page` object. + +## Localized settings + +Some configuration settings can be defined separately for each language. For example: + +{{< code-toggle file=hugo >}} +[languages.en] +languageCode = 'en-US' +languageName = 'English' +weight = 1 +title = 'Project Documentation' +timeZone = 'America/New_York' +[languages.en.pagination] +path = 'page' +[languages.en.params] +subtitle = 'Reference, Tutorials, and Explanations' +{{< /code-toggle >}} + +The following configuration keys can be defined separately for each language: + +{{< per-lang-config-keys >}} + +Any key not defined in a `languages` object will fall back to the global value in the root of the site configuration. + +## Language keys + +Language keys must conform to the syntax described in [RFC 5646]. For example: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +[languages.de] + weight = 1 +[languages.en-US] + weight = 2 +[languages.pt-BR] + weight = 3 +{{< /code-toggle >}} + +Artificial languages with private use subtags as defined in [RFC 5646 § 2.2.7] are also supported. Omit the `art-x-` prefix from the language key. For example: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' +[languages.en] +weight = 1 +[languages.hugolang] +weight = 2 +{{< /code-toggle >}} + +> [!note] +> Private use subtags must not exceed 8 alphanumeric characters. + +## Example + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = true +disableDefaultLanguageRedirect = false + +[languages.de] +contentDir = 'content/de' +disabled = false +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.de.params] +subtitle = 'Referenz, Tutorials und Erklärungen' + +[languages.en] +contentDir = 'content/en' +disabled = false +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 + +[languages.en.params] +subtitle = 'Reference, Tutorials, and Explanations' +{{< /code-toggle >}} + +> [!note] +> In the example above, omit `contentDir` if [translating by file name]. + +## Multihost + +Hugo supports multiple languages in a multihost configuration. This means you can configure a `baseURL` per `language`. + +> [!note] +> If you define a `baseURL` for one language, you must define a unique `baseURL` for all languages. + +For example: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'fr' +[languages] + [languages.en] + baseURL = 'https://en.example.org/' + languageName = 'English' + title = 'In English' + weight = 2 + [languages.fr] + baseURL = 'https://fr.example.org' + languageName = 'Français' + title = 'En Français' + weight = 1 +{{</ code-toggle >}} + +With the above, Hugo publishes two sites, each with their own root: + +```text +public +├── en +└── fr +``` + +[`dir`]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir +[`Language.LanguageCode`]: /methods/site/language/#languagecode +[`Language.LanguageDirection`]: /methods/site/language/#languagedirection +[`Language.LanguageName`]: /methods/site/language/#languagename +[`Language.Weight`]: /methods/site/language/#weight +[`Title`]: /methods/site/title/ +[embedded alias template]: {{% eturl alias %}} +[embedded OpenGraph template]: {{% eturl opengraph %}} +[embedded RSS template]: {{% eturl rss %}} +[RFC 5646]: https://datatracker.ietf.org/doc/html/rfc5646#section-2.1 +[RFC 5646 § 2.2.7]: https://datatracker.ietf.org/doc/html/rfc5646#section-2.2.7 +[translating by file name]: /content-management/multilingual/#translation-by-file-name diff --git a/docs/content/en/configuration/markup.md b/docs/content/en/configuration/markup.md new file mode 100644 index 000000000..b6135cee5 --- /dev/null +++ b/docs/content/en/configuration/markup.md @@ -0,0 +1,341 @@ +--- +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]|| +`footnote`|[PHP Markdown Extra: Footnotes]|:heavy_check_mark: +`linkify`|[GitHub Flavored Markdown: Autolinks]|:heavy_check_mark: +`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~~`|`<del>foo</del>` +Inserted text|`++bar++`|`<ins>bar</ins>` +Mark text|`==baz==`|`<mark>baz</mark>` +Subscript|`H~2~O`|`H<sub>2</sub>O` +Superscript|`1^st^`|`1<sup>st</sup>` + +To avoid a conflict when enabling the "subscript" feature of the Extras extension, if you want to render subscript and strikethrough text concurrently you must: + +1. Disable the Strikethrough extension +1. Enable the "deleted text" feature of the Extras extension + +For example: + +{{< code-toggle file=hugo >}} +[markup.goldmark.extensions] +strikethrough = false + +[markup.goldmark.extensions.extras.delete] +enable = true + +[markup.goldmark.extensions.extras.subscript] +enable = true +{{< /code-toggle >}} + +#### 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 + +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`. + + - `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 + + This is also the strategy used by the [anchorize](/functions/urls/anchorize) template function. Default is `github`. + +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`. + + > [!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.link.enableDefault +: {{< new-in 0.123.0 />}} +: (`bool`) Whether to enable the [embedded link render hook]. Default is `false`. + + > [!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. + +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 + +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 + +Set the `source-highlighter` attribute in your site configuration. For example: + +{{< code-toggle file=hugo >}} +[markup.asciidocExt.attributes] +source-highlighter = 'rouge' +{{< /code-toggle >}} + +#### Step 2 + +Generate the highlighter CSS. For example: + +```text +rougify style monokai.sublime > assets/css/syntax.css +``` + +#### Step 3 + +In your base template add a link to the CSS file: + +```go-html-template {file="layouts/_default/baseof.html"} +<head> + ... + {{ with resources.Get "css/syntax.css" }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> + {{ end }} + ... +</head> +``` + +Then add the code to be highlighted to your markup: + +```text +[#hello,ruby] +---- +require 'sinatra' + +get '/hi' do + "Hello World!" +end +---- +``` + +### 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/ +[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/ +[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/ +[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 +[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 +[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 +[security policy]: /configuration/security/ +[subscript]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sub +[superscript]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/sup +[AsciiDoc]: https://asciidoc.org/ +[Emacs Org Mode]: https://orgmode.org/ +[Pandoc]: https://www.pandoc.org/ +[reStructuredText]: https://docutils.sourceforge.io/rst.html diff --git a/docs/content/en/configuration/media-types.md b/docs/content/en/configuration/media-types.md new file mode 100644 index 000000000..ea89ee04a --- /dev/null +++ b/docs/content/en/configuration/media-types.md @@ -0,0 +1,82 @@ +--- +title: Configure media types +linkTitle: Media types +description: Configure media types. +categories: [] +keywords: [] +--- + +{{% glossary-term "media type" %}} + +Configured media types serve multiple purposes in Hugo, including the definition of [output formats](g). This is the default media type configuration in tabular form: + +{{< datatable "config" "mediaTypes" "_key" "suffixes" >}} + +The `suffixes` column in the table above shows the suffixes associated with each media type. For example, Hugo associates `.html` and `.htm` files with the `text/html` media type. + +> [!note] +> The first suffix is the primary suffix. Use the primary suffix when naming template files. For example, when creating a template for an RSS feed, use the `xml` suffix. + +## Default configuration + +The following is the default configuration that matches the table above: + +{{< code-toggle file=hugo config=mediaTypes />}} + +delimiter +: (`string`) The delimiter between the file name and the suffix. The delimiter, in conjunction with the suffix, forms the file extension. Default is `"."`. + +suffixes +: (`[]string`) The suffixes associated with this media type. The first suffix is the primary suffix. + +## Modify a media type + +You can modify any of the default media types. For example, to switch the primary suffix for `text/html` from `html` to `htm`: + +{{< code-toggle file=hugo >}} +[mediaTypes.'text/html'] +suffixes = ['htm','html'] +{{< /code-toggle >}} + +If you alter a default media type, you must also explicitly redefine all output formats that utilize that media type. For example, to ensure the changes above affect the `html` output format, redefine the `html` output format: + +{{< code-toggle file=hugo >}} +[outputFormats.html] +mediaType = 'text/html' +{{< /code-toggle >}} + +## Create a media type + +You can create new media types as needed. For example, to create a media type for an Atom feed: + +{{< code-toggle file=hugo >}} +[mediaTypes.'application/atom+xml'] +suffixes = ['atom'] +{{< /code-toggle >}} + +## Media types without suffixes + +Occasionally, you may need to create a media type without a suffix or delimiter. For example, [Netlify] recognizes configuration files named `_redirects` and `_headers`, which Hugo can generate using custom [output formats](g). + +To support these custom output formats, register a custom media type with no suffix or delimiter: + +{{< code-toggle file=hugo >}} +[mediaTypes."text/netlify"] +delimiter = "" +{{< /code-toggle >}} + +The custom output format definitions would look something like this: + +{{< code-toggle file=hugo >}} +[outputFormats.redir] +baseName = "_redirects" +isPlainText = true +mediatype = "text/netlify" +[outputFormats.headers] +baseName = "_headers" +isPlainText = true +mediatype = "text/netlify" +notAlternative = true +{{< /code-toggle >}} + +[Netlify]: https://www.netlify.com/ diff --git a/docs/content/en/configuration/menus.md b/docs/content/en/configuration/menus.md new file mode 100644 index 000000000..759f53ff3 --- /dev/null +++ b/docs/content/en/configuration/menus.md @@ -0,0 +1,135 @@ +--- +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 = '<i class="fa fa-heart"></i>' +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 --git a/docs/content/en/configuration/minify.md b/docs/content/en/configuration/minify.md new file mode 100644 index 000000000..a530cb73d --- /dev/null +++ b/docs/content/en/configuration/minify.md @@ -0,0 +1,15 @@ +--- +title: Configure minify +linkTitle: Minify +description: Configure minify. +categories: [] +keywords: [] +--- + +This is the default configuration: + +{{< code-toggle config=minify />}} + +See the [tdewolff/minify] project page for details. + +[tdewolff/minify]: https://github.com/tdewolff/minify diff --git a/docs/content/en/configuration/module.md b/docs/content/en/configuration/module.md new file mode 100644 index 000000000..d736b7c6f --- /dev/null +++ b/docs/content/en/configuration/module.md @@ -0,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`. + +min +: (`string`) The minimum Hugo version supported, for example `0.123.0`. + +[`themesDir`]: /configuration/all/#themesdir + +## 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 >}} diff --git a/docs/content/en/configuration/output-formats.md b/docs/content/en/configuration/output-formats.md new file mode 100644 index 000000000..2627c6df4 --- /dev/null +++ b/docs/content/en/configuration/output-formats.md @@ -0,0 +1,209 @@ +--- +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`. + +mediaType +: (`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`. + +noUgly +: (`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. + +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`. + +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://`. + +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 + +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 >}} + +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 >}} + +Note that we use the default settings for all other output format properties. + +### Step 3 + +Specify the page [kinds](g) for which to render this output format: + +{{< code-toggle file=hugo >}} +[outputs] +home = ['html', 'rss', 'atom'] +section = ['html', 'rss', 'atom'] +taxonomy = ['html', 'rss', 'atom'] +term = ['html', 'rss', 'atom'] +{{< /code-toggle >}} + +See [configure outputs] for more information. + +### Step 4 + +Create a template to render the output format. Since Atom feeds are lists, you need to create a list template. Consult the [template lookup order] to find the correct template path: + +```text +layouts/_default/list.atom.atom +``` + +We leave writing the template code as an exercise for you. Aim for a result similar to the [embedded RSS template]. + +## 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: + +```go-html-template +{{ range .AlternativeOutputFormats }} + <link rel="{{ .Rel }}" type="{{ .MediaType.Type }}" href="{{ .Permalink | safeURL }}"> +{{ 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. + +For example, in `single.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. + +With `permalinkable` set to true for `json` in the same `single.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]. + +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/_default/section.html.html` +`json`|`layouts/_default/section.json.json` +`rss`|`layouts/_default/section.rss.xml` + +[`AlternativeOutputFormats`]: /methods/page/alternativeoutputformats/ +[`OutputFormats`]: /methods/page/outputformats/ +[`Permalink`]: /methods/page/permalink/ +[`RelPermalink`]: /methods/page/relpermalink/ +[`baseURL`]: /configuration/all/#baseurl +[`permalinkable`]: #permalinkable +[`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 %}} +[html/template]: https://pkg.go.dev/html/template +[template lookup order]: /templates/lookup-order/ +[text/template]: https://pkg.go.dev/text/template diff --git a/docs/content/en/configuration/outputs.md b/docs/content/en/configuration/outputs.md new file mode 100644 index 000000000..9a83cb6e9 --- /dev/null +++ b/docs/content/en/configuration/outputs.md @@ -0,0 +1,49 @@ +--- +title: Configure outputs +linkTitle: Outputs +description: Configure which output formats to render for each page kind. +categories: [] +keywords: [] +--- + +{{% glossary-term "output format" %}} + +Learn more about creating and configuring output formats in the [configure output formats] section. + +## Outputs per page kind + +The following default configuration determines the output formats generated for each page kind: + +{{< code-toggle config=outputs />}} + +To render the built-in `json` output format for the `home` page kind, assuming you've already created the necessary template, add the following to your configuration: + +{{< code-toggle file=hugo >}} +[outputs] +home = ['html','rss','json'] +{{< /code-toggle >}} + +Notice in this example that we only specified the `home` page kind. You don't need to include entries for other page kinds unless you intend to modify their default output formats. + +> [!note] +> The order of the output formats in the arrays above is important. The first element will be the _primary output format_ for that page kind, and in most cases that should be `html` as shown in the default configuration. +> +> The primary output format for a given page kind determines the value returned by the [`Permalink`] and [`RelPermalink`] methods on a `Page` object. +> +> See the [link to output formats] section for details. + +## Outputs per page + +Add output formats to a page's rendering using the `outputs` field in its front matter. For example, to include `json` in the output formats rendered for a specific page: + +{{< code-toggle file=content/example.md fm=true >}} +title = 'Example' +outputs = ['json'] +{{< /code-toggle >}} + +In its default configuration, Hugo will render both the `html` and `json` output formats for this page. The `outputs` field appends to, rather than replaces, the site's configured outputs. + +[`Permalink`]: /methods/page/permalink/ +[`RelPermalink`]: /methods/page/relpermalink/ +[configure output formats]: /configuration/output-formats/ +[link to output formats]: configuration/output-formats/#link-to-output-formats diff --git a/docs/content/en/configuration/page.md b/docs/content/en/configuration/page.md new file mode 100644 index 000000000..81169e546 --- /dev/null +++ b/docs/content/en/configuration/page.md @@ -0,0 +1,34 @@ +--- +title: Configure page +linkTitle: Page +description: Configure page behavior. +categories: [] +keywords: [] +--- + +{{< new-in 0.133.0 />}} + +{{% glossary-term "default sort order" %}} + +Hugo uses the default sort order to determine the _next_ and _previous_ page relative to the current page when calling these methods on a `Page` object: + +- [`Next`](/methods/page/next/) and [`Prev`](/methods/page/prev/) +- [`NextInSection`](/methods/page/nextinsection/) and [`PrevInSection`](/methods/page/previnsection/) + +This is based on this default site configuration: + +{{< code-toggle config=page />}} + +To reverse the meaning of _next_ and _previous_: + +{{< code-toggle file=hugo >}} +[page] + nextPrevInSectionSortOrder = 'asc' + nextPrevSortOrder = 'asc' +{{< /code-toggle >}} + +> [!note] +> These settings do not apply to the [`Next`] or [`Prev`] methods on a `Pages` object. + +[`Next`]: /methods/pages/next +[`Prev`]: /methods/pages/next diff --git a/docs/content/en/configuration/pagination.md b/docs/content/en/configuration/pagination.md new file mode 100644 index 000000000..66b3b8cf4 --- /dev/null +++ b/docs/content/en/configuration/pagination.md @@ -0,0 +1,45 @@ +--- +title: Configure pagination +linkTitle: Pagination +description: Configure pagination. +categories: [] +keywords: [] +--- + +This is the default configuration: + +{{< code-toggle config=pagination />}} + +disableAliases +: (`bool`) Whether to disable alias generation for the first pager. Default is `false`. + +pagerSize +: (`int`) The number of pages per pager. Default is `10`. + +path +: (`string`) The segment of each pager URL indicating that the target page is a pager. Default is `page`. + +With multilingual sites you can define the pagination behavior for each language: + +{{< code-toggle file=hugo >}} +[languages.en] +contentDir = 'content/en' +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +weight = 1 +[languages.en.pagination] +disableAliases = true +pagerSize = 10 +path = 'page' +[languages.de] +contentDir = 'content/de' +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +weight = 2 +[languages.de.pagination] +disableAliases = true +pagerSize = 20 +path = 'blatt' +{{< /code-toggle >}} diff --git a/docs/content/en/configuration/params.md b/docs/content/en/configuration/params.md new file mode 100644 index 000000000..239b0c2da --- /dev/null +++ b/docs/content/en/configuration/params.md @@ -0,0 +1,100 @@ +--- +title: Configure params +linkTitle: Params +description: Create custom site parameters. +categories: [] +keywords: [] +--- + +Use the `params` key for custom parameters: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/' +title = 'Project Documentation' +languageCode = 'en-US' +[params] +subtitle = 'Reference, Tutorials, and Explanations' +[params.contact] +email = 'info@example.org' +phone = '+1 206-555-1212' +{{< /code-toggle >}} + +Access the custom parameters from your templates using the [`Params`] method on a `Site` object: + +[`Params`]: /methods/site/params/ + +```go-html-template +{{ .Site.Params.subtitle }} → Reference, Tutorials, and Explanations +{{ .Site.Params.contact.email }} → info@example.org +``` + +Key names should use camelCase or snake_case. While TOML, YAML, and JSON allow kebab-case keys, they are not valid [identifiers](g) and cannot be used when [chaining](g) identifiers. + +For example, you can do either of these: + +```go-html-template +{{ .Site.params.camelCase.foo }} +{{ .Site.params.snake_case.foo }} +``` + +But you cannot do this: + +```go-html-template +{{ .Site.params.kebab-case.foo }} +``` + +## Multilingual sites + +For multilingual sites, create a `params` key under each language: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/' +defaultContentLanguage = 'en' + +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.de.params] +subtitle = 'Referenz, Tutorials und Erklärungen' + +[languages.de.params.contact] +email = 'info@de.example.org' +phone = '+49 30 1234567' + +[languages.en] +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 + +[languages.en.params] +subtitle = 'Reference, Tutorials, and Explanations' + +[languages.en.params.contact] +email = 'info@example.org' +phone = '+1 206-555-1212' +{{< /code-toggle >}} + +## Namespacing + +To prevent naming conflicts, module and theme developers should namespace any custom parameters specific to their module or theme. + +{{< code-toggle file=hugo >}} +[params.modules.myModule.colors] +background = '#efefef' +font = '#222222' +{{< /code-toggle >}} + +To access the module/theme settings: + +```go-html-template +{{ $cfg := .Site.Params.module.mymodule }} + +{{ $cfg.colors.background }} → #efefef +{{ $cfg.colors.font }} → #222222 +``` diff --git a/docs/content/en/configuration/permalinks.md b/docs/content/en/configuration/permalinks.md new file mode 100644 index 000000000..0810624a6 --- /dev/null +++ b/docs/content/en/configuration/permalinks.md @@ -0,0 +1,162 @@ +--- +title: Configure permalinks +linkTitle: Permalinks +description: Configure permalinks. +categories: [] +keywords: [] +--- + +This is the default configuration: + +{{< code-toggle config=permalinks />}} + +Define a URL pattern for each top-level section. Each URL pattern can target a given language and/or page kind. + +> [!note] +> The [`url`] front matter field overrides any matching permalink pattern. + +## Monolingual example + +With this content structure: + +```text +content/ +├── posts/ +│ ├── bash-in-slow-motion.md +│ └── tls-in-a-nutshell.md +├── tutorials/ +│ ├── git-for-beginners.md +│ └── javascript-bundling-with-hugo.md +└── _index.md +``` + +Render tutorials under "training", and render the posts under "articles" with a date-base hierarchy: + +{{< code-toggle file=hugo >}} +[permalinks.page] +posts = '/articles/:year/:month/:slug/' +tutorials = '/training/:slug/' +[permalinks.section] +posts = '/articles/' +tutorials = '/training/' +{{< /code-toggle >}} + +The structure of the published site will be: + +```text +public/ +├── articles/ +│ ├── 2023/ +│ │ ├── 04/ +│ │ │ └── bash-in-slow-motion/ +│ │ │ └── index.html +│ │ └── 06/ +│ │ └── tls-in-a-nutshell/ +│ │ └── index.html +│ └── index.html +├── training/ +│ ├── git-for-beginners/ +│ │ └── index.html +│ ├── javascript-bundling-with-hugo/ +│ │ └── index.html +│ └── index.html +└── index.html +``` + +To create a date-based hierarchy for regular pages in the content root: + +{{< code-toggle file=hugo >}} +[permalinks.page] +"/" = "/:year/:month/:slug/" +{{< /code-toggle >}} + +Use the same approach with taxonomy terms. For example, to omit the taxonomy segment of the URL: + +{{< code-toggle file=hugo >}} +[permalinks.term] +'tags' = '/:slug/' +{{< /code-toggle >}} + +## Multilingual example + +Use the `permalinks` configuration as a component of your localization strategy. + +With this content structure: + +```text +content/ +├── en/ +│ ├── books/ +│ │ ├── les-miserables.md +│ │ └── the-hunchback-of-notre-dame.md +│ └── _index.md +└── es/ + ├── books/ + │ ├── les-miserables.md + │ └── the-hunchback-of-notre-dame.md + └── _index.md +``` + +And this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' +defaultContentLanguageInSubdir = true + +[languages.en] +contentDir = 'content/en' +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +weight = 1 + +[languages.en.permalinks.page] +books = "/books/:slug/" + +[languages.en.permalinks.section] +books = "/books/" + +[languages.es] +contentDir = 'content/es' +languageCode = 'es-ES' +languageDirection = 'ltr' +languageName = 'Español' +weight = 2 + +[languages.es.permalinks.page] +books = "/libros/:slug/" + +[languages.es.permalinks.section] +books = "/libros/" +{{< /code-toggle >}} + +The structure of the published site will be: + +```text +public/ +├── en/ +│ ├── books/ +│ │ ├── les-miserables/ +│ │ │ └── index.html +│ │ ├── the-hunchback-of-notre-dame/ +│ │ │ └── index.html +│ │ └── index.html +│ └── index.html +├── es/ +│ ├── libros/ +│ │ ├── les-miserables/ +│ │ │ └── index.html +│ │ ├── the-hunchback-of-notre-dame/ +│ │ │ └── index.html +│ │ └── index.html +│ └── index.html +└── index.html +``` + +## Tokens + +Use these tokens when defining a URL pattern. + +{{% include "/_common/permalink-tokens.md" %}} + +[`url`]: /content-management/front-matter/#url diff --git a/docs/content/en/configuration/privacy.md b/docs/content/en/configuration/privacy.md new file mode 100644 index 000000000..c94f2c1c3 --- /dev/null +++ b/docs/content/en/configuration/privacy.md @@ -0,0 +1,43 @@ +--- +title: Configure privacy +linkTitle: Privacy +description: Configure your site to help comply with regional privacy regulations. +categories: [] +keywords: [] +aliases: [/about/privacy/] +--- + +## Responsibility + +Site authors are responsible for ensuring compliance with regional privacy regulations, including but not limited to: + +- GDPR (General Data Protection Regulation): Applies to individuals within the European Union and the European Economic Area. +- CCPA (California Consumer Privacy Act): Applies to California residents. +- CPRA (California Privacy Rights Act): Expands upon the CCPA with stronger consumer privacy protections. +- Virginia Consumer Data Protection Act (CDPA): Applies to businesses that collect, process, or sell the personal data of Virginia residents. + +Hugo's privacy settings can assist in compliance efforts. + +## Embedded templates + +Hugo provides [embedded templates](g) to simplify site and content creation. Some of these templates interact with external services. For example, the `youtube` shortcode connects with YouTube's servers to embed videos on your site. + +Some of these templates include settings to enhance privacy. + +## Configuration + +> [!note] +> These settings affect the behavior of some of Hugo's embedded templates. These settings may or may not affect the behavior of templates provided by third parties in their modules or themes. + +These are the default privacy settings for Hugo's embedded templates: + +{{< code-toggle config=privacy />}} + +See each template's documentation for a description of its privacy settings: + +- [Disqus partial](/templates/embedded/#privacy-disqus) +- [Google Analytics partial](/templates/embedded/#privacy-google-analytics) +- [Instagram shortcode](/shortcodes/instagram/#privacy) +- [Vimeo shortcode](/shortcodes/vimeo/#privacy) +- [X shortcode](/shortcodes/x/#privacy) +- [YouTube shortcode](/shortcodes/youtube/#privacy) diff --git a/docs/content/en/configuration/related-content.md b/docs/content/en/configuration/related-content.md new file mode 100644 index 000000000..c6e182fae --- /dev/null +++ b/docs/content/en/configuration/related-content.md @@ -0,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: + +```go-html-template {file="layouts/partials/related.html" copy=true} +{{ with site.RegularPages.Related . | first 5 }} + <p>Related content:</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +[related content]: /content-management/related-content/ diff --git a/docs/content/en/configuration/security.md b/docs/content/en/configuration/security.md new file mode 100644 index 000000000..f950dd233 --- /dev/null +++ b/docs/content/en/configuration/security.md @@ -0,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. + +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. + +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 --git a/docs/content/en/configuration/segments.md b/docs/content/en/configuration/segments.md new file mode 100644 index 000000000..0c4098770 --- /dev/null +++ b/docs/content/en/configuration/segments.md @@ -0,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}`. + +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 --git a/docs/content/en/configuration/server.md b/docs/content/en/configuration/server.md new file mode 100644 index 000000000..92f0f0cfa --- /dev/null +++ b/docs/content/en/configuration/server.md @@ -0,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. + +[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 --git a/docs/content/en/configuration/services.md b/docs/content/en/configuration/services.md new file mode 100644 index 000000000..dbe3893a7 --- /dev/null +++ b/docs/content/en/configuration/services.md @@ -0,0 +1,52 @@ +--- +title: Configure services +linkTitle: Services +description: Configure embedded templates. +categories: [] +keywords: [] +--- + +Hugo provides [embedded templates](g) to simplify site and content creation. Some of these templates are configurable. For example, the embedded Google Analytics template requires a Google tag ID. + +This is the default configuration: + +{{< code-toggle config=services />}} + +disqus.shortname +: (`string`) The `shortname` used with the Disqus commenting system. See [details](/templates/embedded/#disqus). To access this value from a template: + + ```go-html-template + {{ .Site.Config.Services.Disqus.Shortname }} + ``` + +googleAnalytics.id +: (`string`) The Google tag ID for Google Analytics 4 properties. See [details](/templates/embedded/#google-analytics). To access this value from a template: + + ```go-html-template + {{ .Site.Config.Services.GoogleAnalytics.ID }} + ``` + +instagram.accessToken <!-- TODO: Remove when no longer in docs.yaml --> +: (`string`) Do not use. Deprecated in [v0.123.0]. The embedded `instagram` shortcode no longer uses this setting. + +instagram.disableInlineCSS <!-- TODO: Remove when no longer in docs.yaml --> +: (`bool`) Do not use. Deprecated in [v0.123.0]. The embedded `instagram` shortcode no longer uses this setting. + +rss.limit +: (`int`) The maximum number of items to include in an RSS feed. Set to `-1` for no limit. Default is `-1`. See [details](/templates/rss/). To access this value from a template: + + ```go-html-template + {{ .Site.Config.Services.RSS.Limit }} + ``` + +twitter.disableInlineCSS <!-- TODO: Remove when no longer in docs.yaml --> +: (`bool`) Do not use. Deprecated in [v0.141.0]. Use the `x` shortcode instead. + +x.disableInlineCSS +: (`bool`) Whether to disable the inline CSS rendered by the embedded `x` shortode. See [details](/shortcodes/x/#privacy). Default is `false`. To access this value from a template: + + ```go-html-template + {{ .Site.Config.Services.X.DisableInlineCSS }} + +[v0.141.0]: https://github.com/gohugoio/hugo/releases/tag/v0.141.0 +[v0.123.0]: https://github.com/gohugoio/hugo/releases/tag/v0.123.0 diff --git a/docs/content/en/configuration/sitemap.md b/docs/content/en/configuration/sitemap.md new file mode 100644 index 000000000..bc972994c --- /dev/null +++ b/docs/content/en/configuration/sitemap.md @@ -0,0 +1,24 @@ +--- +title: Configure sitemap +linkTitle: Sitemap +description: Configure the sitemap. +categories: [] +keywords: [] +--- + +These are the default sitemap configuration values. They apply to all pages unless overridden in front matter. + +{{< code-toggle config=sitemap />}} + +changefreq +: (`string`) How frequently a page is likely to change. Valid values are `always`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, and `never`. With the default value of `""` Hugo will omit this field from the sitemap. See [details](https://www.sitemaps.org/protocol.html#changefreqdef). + +disable +: {{< new-in 0.125.0 />}} +: (`bool`) Whether to disable page inclusion. Default is `false`. Set to `true` in front matter to exclude the page. + +filename +: (`string`) The name of the generated file. Default is `sitemap.xml`. + +priority +: (`float`) The priority of a page relative to any other page on the site. Valid values range from 0.0 to 1.0. With the default value of `-1` Hugo will omit this field from the sitemap. See [details](https://www.sitemaps.org/protocol.html#prioritydef). diff --git a/docs/content/en/configuration/taxonomies.md b/docs/content/en/configuration/taxonomies.md new file mode 100644 index 000000000..4b5ba97a5 --- /dev/null +++ b/docs/content/en/configuration/taxonomies.md @@ -0,0 +1,68 @@ +--- +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 = ['categories','tags'] +{{< /code-toggle >}} + +[`disableKinds`]: /configuration/all/#disablekinds + +See the [taxonomies] section for more information. + +[taxonomies]: /content-management/taxonomies/ diff --git a/docs/content/en/configuration/ugly-urls.md b/docs/content/en/configuration/ugly-urls.md new file mode 100644 index 000000000..ec1dd8a49 --- /dev/null +++ b/docs/content/en/configuration/ugly-urls.md @@ -0,0 +1,36 @@ +--- +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 --git a/docs/content/en/content-management/_index.md b/docs/content/en/content-management/_index.md new file mode 100644 index 000000000..4e2060756 --- /dev/null +++ b/docs/content/en/content-management/_index.md @@ -0,0 +1,8 @@ +--- +title: Content management +description: Hugo makes managing large static sites easy with support for archetypes, content types, menus, cross references, summaries, and more. +categories: [] +keywords: [] +weight: 10 +aliases: [/content/,/content/organization] +--- diff --git a/docs/content/en/content-management/archetypes.md b/docs/content/en/content-management/archetypes.md new file mode 100644 index 000000000..db0838504 --- /dev/null +++ b/docs/content/en/content-management/archetypes.md @@ -0,0 +1,186 @@ +--- +title: Archetypes +description: An archetype is a template for new content. +categories: [] +keywords: [] +aliases: [/content/archetypes/] +--- + +## Overview + +A content file consists of [front matter](g) and markup. The markup is typically Markdown, but Hugo also supports other [content formats](g). Front matter can be TOML, YAML, or JSON. + +The `hugo new content` command creates a new file in the `content` directory, using an archetype as a template. This is the default archetype: + +{{< code-toggle file=archetypes/default.md fm=true >}} +title = '{{ replace .File.ContentBaseName `-` ` ` | title }}' +date = '{{ .Date }}' +draft = true +{{< /code-toggle >}} + +When you create new content, Hugo evaluates the [template actions](g) within the archetype. For example: + +```sh +hugo new content posts/my-first-post.md +``` + +With the default archetype shown above, Hugo creates this content file: + +{{< code-toggle file=content/posts/my-first-post.md fm=true >}} +title = 'My First Post' +date = '2023-08-24T11:49:46-07:00' +draft = true +{{< /code-toggle >}} + +You can create an archetype for one or more [content types](g). For example, use one archetype for posts, and use the default archetype for everything else: + +```text +archetypes/ +├── default.md +└── posts.md +``` + +## Lookup order + +Hugo looks for archetypes in the `archetypes` directory in the root of your project, falling back to the `archetypes` directory in themes or installed modules. An archetype for a specific content type takes precedence over the default archetype. + +For example, with this command: + +```sh +hugo new content posts/my-first-post.md +``` + +The archetype lookup order is: + +1. `archetypes/posts.md` +1. `archetypes/default.md` +1. `themes/my-theme/archetypes/posts.md` +1. `themes/my-theme/archetypes/default.md` + +If none of these exists, Hugo uses a built-in default archetype. + +## Functions and context + +You can use any template [function](g) within an archetype. As shown above, the default archetype uses the [`replace`](/functions/strings/replace) function to replace hyphens with spaces when populating the title in front matter. + +Archetypes receive the following [context](g): + +Date +: (`string`) The current date and time, formatted in compliance with RFC3339. + +File +: (`hugolib.fileInfo`) Returns file information for the current page. See [details](/methods/page/file). + +Type +: (`string`) The [content type](g) inferred from the top-level directory name, or as specified by the `--kind` flag passed to the `hugo new content` command. + +Site +: (`page.Site`) The current site object. See [details](/methods/site/). + +## Date format + +To insert date and time with a different format, use the [`time.Now`] function: + +[`time.Now`]: /functions/time/now/ + +{{< code-toggle file=archetypes/default.md fm=true >}} +title = '{{ replace .File.ContentBaseName `-` ` ` | title }}' +date = '{{ time.Now.Format "2006-01-02" }}' +draft = true +{{< /code-toggle >}} + +## Include content + +Although typically used as a front matter template, you can also use an archetype to populate content. + +For example, in a documentation site you might have a section (content type) for functions. Every page within this section should follow the same format: a brief description, the function signature, examples, and notes. We can pre-populate the page to remind content authors of the standard format. + +````text {file="archetypes/functions.md"} +--- +date: '{{ .Date }}' +draft: true +title: '{{ replace .File.ContentBaseName `-` ` ` | title }}' +--- + +A brief description of what the function does, using simple present tense in the third person singular form. For example: + +`someFunction` returns the string `s` repeated `n` times. + +## Signature + +```text +func someFunction(s string, n int) string +``` + +## Examples + +One or more practical examples, each within a fenced code block. + +## Notes + +Additional information to clarify as needed. +```` + +Although you can include [template actions](g) within the content body, remember that Hugo evaluates these once---at the time of content creation. In most cases, place template actions in a [template](g) where Hugo evaluates the actions every time you [build](g) the site. + +## Leaf bundles + +You can also create archetypes for [leaf bundles](g). + +For example, in a photography site you might have a section (content type) for galleries. Each gallery is leaf bundle with content and images. + +Create an archetype for galleries: + +```text +archetypes/ +├── galleries/ +│ ├── images/ +│ │ └── .gitkeep +│ └── index.md <-- same format as default.md +└── default.md +``` + +Subdirectories within an archetype must contain at least one file. Without a file, Hugo will not create the subdirectory when you create new content. The name and size of the file are irrelevant. The example above includes a `.gitkeep` file, an empty file commonly used to preserve otherwise empty directories in a Git repository. + +To create a new gallery: + +```sh +hugo new galleries/bryce-canyon +``` + +This produces: + +```text +content/ +├── galleries/ +│ └── bryce-canyon/ +│ ├── images/ +│ │ └── .gitkeep +│ └── index.md +└── _index.md +``` + +## Specify archetype + +Use the `--kind` command line flag to specify an archetype when creating content. + +For example, let's say your site has two sections: articles and tutorials. Create an archetype for each content type: + +```text +archetypes/ +├── articles.md +├── default.md +└── tutorials.md +``` + +To create an article using the articles archetype: + +```sh +hugo new content articles/something.md +``` + +To create an article using the tutorials archetype: + +```sh +hugo new content --kind tutorials articles/something.md +``` diff --git a/docs/content/en/content-management/build-options.md b/docs/content/en/content-management/build-options.md new file mode 100644 index 000000000..8c29a19b9 --- /dev/null +++ b/docs/content/en/content-management/build-options.md @@ -0,0 +1,303 @@ +--- +title: Build options +description: Build options help define how Hugo must treat a given page when building the site. +categories: [] +keywords: [] +aliases: [/content/build-options/] +--- + +<!-- TODO +We deprecated the `_build` front matter key in favor of `build` in v0.145.0 on 2025-02-26. Remove footnote #1 on or after 2026-05-26 (15 months after deprecation). +--> + +Build options are stored in a reserved front matter object named `build`[^1] with these defaults: + +[^1]: The `_build` alias for `build` is deprecated and will be removed in a future release. + +{{< code-toggle file=content/example/index.md fm=true >}} +[build] +list = 'always' +publishResources = true +render = 'always' +{{< /code-toggle >}} + +list +: When to include the page within page collections. Specify one of: + + - `always`: Include the page in _all_ page collections. For example, `site.RegularPages`, `.Pages`, etc. This is the default value. + - `local`: Include the page in _local_ page collections. For example, `.RegularPages`, `.Pages`, etc. Use this option to create fully navigable but headless content sections. + - `never`: Do not include the page in _any_ page collection. + +publishResources +: Applicable to [page bundles], determines whether to publish the associated [page resources]. Specify one of: + + - `true`: Always publish resources. This is the default value. + - `false`: Only publish a resource when invoking its [`Permalink`], [`RelPermalink`], or [`Publish`] method within a template. + +render +: When to render the page. Specify one of: + + - `always`: Always render the page to disk. This is the default value. + - `link`: Do not render the page to disk, but assign `Permalink` and `RelPermalink` values. + - `never`: Never render the page to disk, and exclude it from all page collections. + +> [!note] +> Any page, regardless of its build options, will always be available by using the [`.Page.GetPage`] or [`.Site.GetPage`] method. + +## Example -- headless page + +Create a unpublished page whose content and resources can be included in other pages. + +```text +content/ +├── headless/ +│ ├── a.jpg +│ ├── b.jpg +│ └── index.md <-- leaf bundle +└── _index.md <-- home page +``` + +Set the build options in front matter: + +{{< code-toggle file=content/headless/index.md fm=true >}} +title = 'Headless page' +[build] + list = 'never' + publishResources = false + render = 'never' +{{< /code-toggle >}} + +To include the content and images on the home page: + +```go-html-template {file="layouts/_default/home.html"} +{{ with .Site.GetPage "/headless" }} + {{ .Content }} + {{ range .Resources.ByType "image" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +The published site will have this structure: + +```text +public/ +├── headless/ +│ ├── a.jpg +│ └── b.jpg +└── index.html +``` + +In the example above, note that: + +1. Hugo did not publish an HTML file for the page. +1. Despite setting `publishResources` to `false` in front matter, Hugo published the [page resources] because we invoked the [`RelPermalink`] method on each resource. This is the expected behavior. + +## Example -- headless section + +Create a unpublished section whose content and resources can be included in other pages. + +```text +content/ +├── headless/ +│ ├── note-1/ +│ │ ├── a.jpg +│ │ ├── b.jpg +│ │ └── index.md <-- leaf bundle +│ ├── note-2/ +│ │ ├── c.jpg +│ │ ├── d.jpg +│ │ └── index.md <-- leaf bundle +│ └── _index.md <-- branch bundle +└── _index.md <-- home page +``` + +Set the build options in front matter, using the `cascade` keyword to "cascade" the values down to descendant pages. + +{{< code-toggle file=content/headless/_index.md fm=true >}} +title = 'Headless section' +[[cascade]] +[cascade.build] + list = 'local' + publishResources = false + render = 'never' +{{< /code-toggle >}} + +In the front matter above, note that we have set `list` to `local` to include the descendant pages in local page collections. + +To include the content and images on the home page: + +```go-html-template {file="layouts/_default/home.html"} +{{ with .Site.GetPage "/headless" }} + {{ range .Pages }} + {{ .Content }} + {{ range .Resources.ByType "image" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} + {{ end }} +{{ end }} +``` + +The published site will have this structure: + +```text +public/ +├── headless/ +│ ├── note-1/ +│ │ ├── a.jpg +│ │ └── b.jpg +│ └── note-2/ +│ ├── c.jpg +│ └── d.jpg +└── index.html +``` + +In the example above, note that: + +1. Hugo did not publish an HTML file for the page. +1. Despite setting `publishResources` to `false` in front matter, Hugo correctly published the [page resources] because we invoked the [`RelPermalink`] method on each resource. This is the expected behavior. + +## Example -- list without publishing + +Publish a section page without publishing the descendant pages. For example, to create a glossary: + +```text +content/ +├── glossary/ +│ ├── _index.md +│ ├── bar.md +│ ├── baz.md +│ └── foo.md +└── _index.md +``` + +Set the build options in front matter, using the `cascade` keyword to "cascade" the values down to descendant pages. + +{{< code-toggle file=content/glossary/_index.md fm=true >}} +title = 'Glossary' +[build] +render = 'always' +[[cascade]] +[cascade.build] + list = 'local' + publishResources = false + render = 'never' +{{< /code-toggle >}} + +To render the glossary: + +```go-html-template {file="layouts/glossary/list.html"} +<dl> + {{ range .Pages }} + <dt>{{ .Title }}</dt> + <dd>{{ .Content }}</dd> + {{ end }} +</dl> +``` + +The published site will have this structure: + +```text +public/ +├── glossary/ +│ └── index.html +└── index.html +``` + +## Example -- publish without listing + +Publish a section's descendant pages without publishing the section page itself. + +```text +content/ +├── books/ +│ ├── _index.md +│ ├── book-1.md +│ └── book-2.md +└── _index.md +``` + +Set the build options in front matter: + +{{< code-toggle file=content/books/_index.md fm=true >}} +title = 'Books' +[build] +render = 'never' +list = 'never' +{{< /code-toggle >}} + +The published site will have this structure: + +```text +public/ +├── books/ +│ ├── book-1/ +│ │ └── index.html +│ └── book-2/ +│ └── index.html +└── index.html +``` + +## Example -- conditionally hide section + +Consider this example. A documentation site has a team of contributors with access to 20 custom shortcodes. Each shortcode takes several arguments, and requires documentation for the contributors to reference when using them. + +Instead of external documentation for the shortcodes, include an "internal" section that is hidden when building the production site. + +```text +content/ +├── internal/ +│ ├── shortcodes/ +│ │ ├── _index.md +│ │ ├── shortcode-1.md +│ │ └── shortcode-2.md +│ └── _index.md +├── reference/ +│ ├── _index.md +│ ├── reference-1.md +│ └── reference-2.md +├── tutorials/ +│ ├── _index.md +│ ├── tutorial-1.md +│ └── tutorial-2.md +└── _index.md +``` + +Set the build options in front matter, using the `cascade` keyword to "cascade" the values down to descendant pages, and use the `target` keyword to target the production environment. + +{{< code-toggle file=content/internal/_index.md >}} +title = 'Internal' +[[cascade]] +[cascade.build] +render = 'never' +list = 'never' +[cascade.target] +environment = 'production' +{{< /code-toggle >}} + +The production site will have this structure: + +```text +public/ +├── reference/ +│ ├── reference-1/ +│ │ └── index.html +│ ├── reference-2/ +│ │ └── index.html +│ └── index.html +├── tutorials/ +│ ├── tutorial-1/ +│ │ └── index.html +│ ├── tutorial-2/ +│ │ └── index.html +│ └── index.html +└── index.html +``` + +[`.Page.GetPage`]: /methods/page/getpage/ +[`.Site.GetPage`]: /methods/site/getpage/ +[`Permalink`]: /methods/resource/permalink/ +[`Publish`]: /methods/resource/publish/ +[`RelPermalink`]: /methods/resource/relpermalink/ +[page bundles]: /content-management/page-bundles/ +[page resources]: /content-management/page-resources/ diff --git a/docs/content/en/content-management/comments.md b/docs/content/en/content-management/comments.md new file mode 100644 index 000000000..fee4fb372 --- /dev/null +++ b/docs/content/en/content-management/comments.md @@ -0,0 +1,72 @@ +--- +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' +{{</ code-toggle >}} + +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 +{{ template "_internal/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 --git a/docs/content/en/content-management/content-adapters.md b/docs/content/en/content-management/content-adapters.md new file mode 100644 index 000000000..3468bb728 --- /dev/null +++ b/docs/content/en/content-management/content-adapters.md @@ -0,0 +1,349 @@ +--- +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/_default/single.html"} +{{ with .Resources.Get "cover.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ 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] +> If the `content.value` is a string Hugo creates a new resource. If the `content.value` is a resource, Hugo obtains the value from the existing resource. +> +> When 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.\ +<https://gohugo.io/shared/examples/data/books.json> + +### Step 3 + +Create the content adapter. + +```go-html-template {file="content/books/_content.gotmpl" copy=true} +{{/* Get remote data. */}} +{{ $data := dict }} +{{ $url := "https://gohugo.io/shared/examples/data/books.json" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "Unable to get remote resource %s: %s" $url . }} + {{ else with .Value }} + {{ $data = . | transform.Unmarshal }} + {{ else }} + {{ errorf "Unable to get remote resource %s" $url }} + {{ end }} +{{ end }} + +{{/* Add pages and page resources. */}} +{{ range $data }} + + {{/* Add page. */}} + {{ $content := dict "mediaType" "text/markdown" "value" .summary }} + {{ $dates := dict "date" (time.AsTime .date) }} + {{ $params := dict "author" .author "isbn" .isbn "rating" .rating "tags" .tags }} + {{ $page := dict + "content" $content + "dates" $dates + "kind" "page" + "params" $params + "path" .title + "title" .title + }} + {{ $.AddPage $page }} + + {{/* Add page resource. */}} + {{ $item := . }} + {{ with $url := $item.cover }} + {{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "Unable to get remote resource %s: %s" $url . }} + {{ else with .Value }} + {{ $content := dict "mediaType" .MediaType.Type "value" .Content }} + {{ $params := dict "alt" $item.title }} + {{ $resource := dict + "content" $content + "params" $params + "path" (printf "%s/cover.%s" $item.title .MediaType.SubType) + }} + {{ $.AddResource $resource }} + {{ else }} + {{ errorf "Unable to get remote resource %s" $url }} + {{ end }} + {{ end }} + {{ end }} + +{{ end }} +``` + +### Step 4 + +Create a single template to render each book review. + +```go-html-template {file="layouts/books/single.html" copy=true} +{{ define "main" }} + <h1>{{ .Title }}</h1> + + {{ with .Resources.GetMatch "cover.*" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="{{ .Params.alt }}"> + {{ end }} + + <p>Author: {{ .Params.author }}</p> + + <p> + ISBN: {{ .Params.isbn }}<br> + Rating: {{ .Params.rating }}<br> + Review date: {{ .Date | time.Format ":date_long" }} + </p> + + {{ with .GetTerms "tags" }} + <p>Tags:</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> + {{ 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 --git a/docs/content/en/content-management/data-sources.md b/docs/content/en/content-management/data-sources.md new file mode 100644 index 000000000..3fc98b36a --- /dev/null +++ b/docs/content/en/content-management/data-sources.md @@ -0,0 +1,111 @@ +--- +title: Data sources +description: Use local and remote data sources to augment or create content. +categories: [] +keywords: [] +aliases: [/extras/datafiles/,/extras/datadrivencontent/,/doc/datafiles/,/templates/data-templates/] +--- + +Hugo can access and [unmarshal](g) local and remote data sources including CSV, JSON, TOML, YAML, and XML. Use this data to augment existing content or to create new content. + +A data source might be a file in the `data` directory, a [global resource](g), a [page resource](g), or a [remote resource](g). + +## Data directory + +The `data` directory in the root of your project may contain one or more data files, in either a flat or nested tree. Hugo merges the data files to create a single data structure, accessible with the `Data` method on a `Site` object. + +Hugo also merges data directories from themes and modules into this single data structure, where the `data` directory in the root of your project takes precedence. + +> [!note] +> Hugo reads the combined data structure into memory and keeps it there for the entire build. For data that is infrequently accessed, use global or page resources instead. + +Theme and module authors may wish to namespace their data files to prevent collisions. For example: + +```text +project/ +└── data/ + └── mytheme/ + └── foo.json +``` + +> [!note] +> Do not place CSV files in the `data` directory. Access CSV files as page, global, or remote resources. + +See the documentation for the [`Data`] method on a `Site` object for details and examples. + +## Global resources + +Use the `resources.Get` and `transform.Unmarshal` functions to access data files that exist as global resources. + +See the [`transform.Unmarshal`](/functions/transform/unmarshal/#global-resource) documentation for details and examples. + +## Page resources + +Use the `Resources.Get` method on a `Page` object combined with the `transform.Unmarshal` function to access data files that exist as page resources. + +See the [`transform.Unmarshal`](/functions/transform/unmarshal/#page-resource) documentation for details and examples. + +## Remote resources + +Use the `resources.GetRemote` and `transform.Unmarshal` functions to access remote data. + +See the [`transform.Unmarshal`](/functions/transform/unmarshal/#remote-resource) documentation for details and examples. + +## Augment existing content + +Use data sources to augment existing content. For example, create a shortcode to render an HTML table from a global CSV resource. + +```csv {file="assets/pets.csv"} +"name","type","breed","age" +"Spot","dog","Collie","3" +"Felix","cat","Malicious","7" +``` + +```text {file="content/example.md"} +{{</* csv-to-table "pets.csv" */>}} +``` + +```go-html-template {file="layouts/shortcodes/csv-to-table.html"} +{{ with $file := .Get 0 }} + {{ with resources.Get $file }} + {{ with . | transform.Unmarshal }} + <table> + <thead> + <tr> + {{ range index . 0 }} + <th>{{ . }}</th> + {{ end }} + </tr> + </thead> + <tbody> + {{ range after 1 . }} + <tr> + {{ range . }} + <td>{{ . }}</td> + {{ end }} + </tr> + {{ end }} + </tbody> + </table> + {{ end }} + {{ else }} + {{ errorf "The %q shortcode was unable to find %s. See %s" $.Name $file $.Position }} + {{ end }} +{{ else }} + {{ errorf "The %q shortcode requires one positional argument, the path to the CSV file relative to the assets directory. See %s" .Name .Position }} +{{ end }} +``` + +Hugo renders this to: + +name|type|breed|age +:--|:--|:--|:-- +Spot|dog|Collie|3 +Felix|cat|Malicious|7 + +## Create new content + +Use [content adapters] to create new content. + +[`Data`]: /methods/site/data/ +[content adapters]: /content-management/content-adapters/ diff --git a/docs/content/en/content-management/diagrams.md b/docs/content/en/content-management/diagrams.md new file mode 100644 index 000000000..0070ced59 --- /dev/null +++ b/docs/content/en/content-management/diagrams.md @@ -0,0 +1,260 @@ +--- +title: Diagrams +description: Use fenced code blocks and Markdown render hooks to include diagrams in your content. +categories: [] +keywords: [] +--- + +## GoAT diagrams (ASCII) + +Hugo natively supports [GoAT] diagrams with an [embedded code block render hook]. This means that this code block: + +````txt +```goat + . . . .--- 1 .-- 1 / 1 + / \ | | .---+ .-+ + + / \ .---+---. .--+--. | '--- 2 | '-- 2 / \ 2 + + + | | | | ---+ ---+ + + / \ / \ .-+-. .-+-. .+. .+. | .--- 3 | .-- 3 \ / 3 + / \ / \ | | | | | | | | '---+ '-+ + + 1 2 3 4 1 2 3 4 1 2 3 4 '--- 4 '-- 4 \ 4 + +``` +```` + +Will be rendered as: + +```goat + + . . . .--- 1 .-- 1 / 1 + / \ | | .---+ .-+ + + / \ .---+---. .--+--. | '--- 2 | '-- 2 / \ 2 + + + | | | | ---+ ---+ + + / \ / \ .-+-. .-+-. .+. .+. | .--- 3 | .-- 3 \ / 3 + / \ / \ | | | | | | | | '---+ '-+ + + 1 2 3 4 1 2 3 4 1 2 3 4 '--- 4 '-- 4 \ 4 +``` + +## Mermaid diagrams + +Hugo does not provide a built-in template for Mermaid diagrams. Create your own using a [code block render hook]: + +```go-html-template {file="layouts/_default/_markup/render-codeblock-mermaid.html" copy=true} +<pre class="mermaid"> + {{ .Inner | htmlEscape | safeHTML }} +</pre> +{{ .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/_default/baseof.html" copy=true} +{{ if .Store.Get "hasMermaid" }} + <script type="module"> + import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs'; + mermaid.initialize({ startOnLoad: true }); + </script> +{{ end }} +``` + +With that you can use the `mermaid` language in Markdown code blocks: + +````text {copy=true} +```mermaid +sequenceDiagram + participant Alice + participant Bob + Alice->>John: Hello John, how are you? + loop Healthcheck + John->>John: Fight against hypochondria + end + Note right of John: Rational thoughts <br/>prevail! + John-->>Alice: Great! + John->>Bob: How about you? + Bob-->>John: Jolly good! +``` +```` + +## Goat ASCII diagram examples + +### Graphics + +```goat + . + 0 3 P * Eye / ^ / + *-------* +y \ +) \ / Reflection + 1 /| 2 /| ^ \ \ \ v + *-------* | | v0 \ v3 --------*-------- + | |4 | |7 | *----\-----* + | *-----|-* +-----> +x / v X \ .-.<-------- o + |/ |/ / / o \ | / | Refraction / \ + *-------* v / \ +-' / \ + 5 6 +z v1 *------------------* v2 | o-----o + v + +``` + +### Complex + +```goat ++-------------------+ ^ .---. +| A Box |__.--.__ __.--> | .-. | | +| | '--' v | * |<--- | | ++-------------------+ '-' | | + Round *---(-. | + .-----------------. .-------. .----------. .-------. | | | + | Mixed Rounded | | | / Diagonals \ | | | | | | + | & Square Corners | '--. .--' / \ |---+---| '-)-' .--------. + '--+------------+-' .--. | '-------+--------' | | | | / Search / + | | | | '---. | '-------' | '-+------' + |<---------->| | | | v Interior | ^ + ' <---' '----' .-----------. ---. .--- v | + .------------------. Diag line | .-------. +---. \ / . | + | if (a > b) +---. .--->| | | | | Curved line \ / / \ | + | obj->fcn() | \ / | '-------' |<--' + / \ | + '------------------' '--' '--+--------' .--. .--. | .-. +Done?+-' + .---+-----. | ^ |\ | | /| .--+ | | \ / + | | | Join \|/ | | Curved | \| |/ | | \ | \ / + | | +----> o --o-- '-' Vertical '--' '--' '-- '--' + .---. + <--+---+-----' | /|\ | | 3 | + v not:line 'quotes' .-' '---' + .-. .---+--------. / A || B *bold* | ^ + | | | Not a dot | <---+---<-- A dash--is not a line v | + '-' '---------+--' / Nor/is this. --- + +``` + +### Process + +```goat + . + .---------. / \ + | START | / \ .-+-------+-. ___________ + '----+----' .-------. A / \ B | |COMPLEX| | / \ .-. + | | END |<-----+CHOICE +----->| | | +--->+ PREPARATION +--->| X | + v '-------' \ / | |PROCESS| | \___________/ '-' + .---------. \ / '-+---+---+-' + / INPUT / \ / + '-----+---' ' + | ^ + v | + .-----------. .-----+-----. .-. + | PROCESS +---------------->| PROCESS |<------+ X | + '-----------' '-----------' '-' +``` + +### File tree + +Created from <https://arthursonzogni.com/Diagon/#Tree> + +```goat {width=300 color="orange"} +───Linux─┬─Android + ├─Debian─┬─Ubuntu─┬─Lubuntu + │ │ ├─Kubuntu + │ │ ├─Xubuntu + │ │ └─Xubuntu + │ └─Mint + ├─Centos + └─Fedora +``` + +### Sequence diagram + +<https://arthursonzogni.com/Diagon/#Sequence> + +```goat {class="w-40"} +┌─────┐ ┌───┐ +│Alice│ │Bob│ +└──┬──┘ └─┬─┘ + │ │ + │ Hello Bob! │ + │───────────>│ + │ │ + │Hello Alice!│ + │<───────────│ +┌──┴──┐ ┌─┴─┐ +│Alice│ │Bob│ +└─────┘ └───┘ + +``` + +### Flowchart + +<https://arthursonzogni.com/Diagon/#Flowchart> + +```goat + _________________ + ╱ ╲ ┌─────┐ + ╱ DO YOU UNDERSTAND ╲____________________________________________________│GOOD!│ + ╲ FLOW CHARTS? ╱yes └──┬──┘ + ╲_________________╱ │ + │no │ + _________▽_________ ______________________ │ + ╱ ╲ ╱ ╲ ┌────┐ │ +╱ OKAY, YOU SEE THE ╲________________╱ ... AND YOU CAN SEE ╲___│GOOD│ │ +╲ LINE LABELED 'YES'? ╱yes ╲ THE ONES LABELED 'NO'? ╱yes└──┬─┘ │ + ╲___________________╱ ╲______________________╱ │ │ + │no │no │ │ + ________▽_________ _________▽__________ │ │ + ╱ ╲ ┌───────────┐ ╱ ╲ │ │ + ╱ BUT YOU SEE THE ╲___│WAIT, WHAT?│ ╱ BUT YOU JUST ╲___ │ │ + ╲ ONES LABELED 'NO'? ╱yes└───────────┘ ╲ FOLLOWED THEM TWICE? ╱yes│ │ │ + ╲__________________╱ ╲____________________╱ │ │ │ + │no │no │ │ │ + ┌───▽───┐ │ │ │ │ + │LISTEN.│ └───────┬───────┘ │ │ + └───┬───┘ ┌──────▽─────┐ │ │ + ┌─────▽────┐ │(THAT WASN'T│ │ │ + │I HATE YOU│ │A QUESTION) │ │ │ + └──────────┘ └──────┬─────┘ │ │ + ┌────▽───┐ │ │ + │SCREW IT│ │ │ + └────┬───┘ │ │ + └─────┬─────┘ │ + │ │ + └─────┬─────┘ + ┌───────▽──────┐ + │LET'S GO DRING│ + └───────┬──────┘ + ┌─────────▽─────────┐ + │HEY, I SHOULD TRY │ + │INSTALLING FREEBSD!│ + └───────────────────┘ + +``` + +### Table + +<https://arthursonzogni.com/Diagon/#Table> + +```goat {class="w-80 dark-blue"} +┌────────────────────────────────────────────────┐ +│ │ +├────────────────────────────────────────────────┤ +│SYNTAX = { PRODUCTION } . │ +├────────────────────────────────────────────────┤ +│PRODUCTION = IDENTIFIER "=" EXPRESSION "." . │ +├────────────────────────────────────────────────┤ +│EXPRESSION = TERM { "|" TERM } . │ +├────────────────────────────────────────────────┤ +│TERM = FACTOR { FACTOR } . │ +├────────────────────────────────────────────────┤ +│FACTOR = IDENTIFIER │ +├────────────────────────────────────────────────┤ +│ | LITERAL │ +├────────────────────────────────────────────────┤ +│ | "[" EXPRESSION "]" │ +├────────────────────────────────────────────────┤ +│ | "(" EXPRESSION ")" │ +├────────────────────────────────────────────────┤ +│ | "{" EXPRESSION "}" . │ +├────────────────────────────────────────────────┤ +│IDENTIFIER = letter { letter } . │ +├────────────────────────────────────────────────┤ +│LITERAL = """" character { character } """" .│ +└────────────────────────────────────────────────┘ +``` + +[code block render hook]: /render-hooks/code-blocks/ +[embedded code block render hook]: {{% eturl render-codeblock-goat %}} +[GoAT]: https://github.com/bep/goat diff --git a/docs/content/en/content-management/formats.md b/docs/content/en/content-management/formats.md new file mode 100644 index 000000000..1acaae063 --- /dev/null +++ b/docs/content/en/content-management/formats.md @@ -0,0 +1,132 @@ +--- +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 use 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 preceded by front matter. Hugo renders Pandoc content to HTML using the Pandoc executable. You must install Pandoc to use the Pandoc content format. + +Hugo passes these CLI flags when calling the Pandoc executable: + +```text +--mathjax +``` + +[Pandoc]: https://pandoc.org/ + +### reStructuredText + +Create your content in the [reStructuredText] format preceded by front matter. Hugo renders reStructuredText content to HTML using [Docutils], specifically rst2html. You must install Docutils and its dependencies (Python) to use the reStructuredText content format. + +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 --git a/docs/content/en/content-management/front-matter.md b/docs/content/en/content-management/front-matter.md new file mode 100644 index 000000000..8bfbd1acc --- /dev/null +++ b/docs/content/en/content-management/front-matter.md @@ -0,0 +1,362 @@ +--- +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. + +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/_default/single.html"} +{{ with .GetTerms "tags" }} + <p>Tags</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ 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 + +<!-- TODO +Update the <version> and <date> below when we actually get around to deprecating _target. + +We deprecated the `_target` front matter key in favor of `target` in <version> on <date>. Remove footnote #1 on or after 2026-03-10 (15 months after deprecation). +--> + +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}`. + +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 + +[`opengraph.html`]: {{% eturl opengraph %}} +[`schema.html`]: {{% eturl schema %}} +[`twitter_cards.html`]: {{% eturl twitter_cards %}} +[embedded templates]: /templates/embedded/ diff --git a/docs/content/en/content-management/image-processing/index.md b/docs/content/en/content-management/image-processing/index.md new file mode 100644 index 000000000..8d60c4f93 --- /dev/null +++ b/docs/content/en/content-management/image-processing/index.md @@ -0,0 +1,447 @@ +--- +title: Image processing +description: Resize, crop, rotate, filter, and convert images. +categories: [] +keywords: [] +--- + +## Image resources + +To process an image you must access the file as a page resource, global resource, or remote resource. + +### Page resource + +{{% glossary-term "page resource" %}} + +```text +content/ +└── posts/ + └── post-1/ <-- page bundle + ├── index.md + └── sunset.jpg <-- page resource +``` + +To access an image as a page resource: + +```go-html-template +{{ $image := .Resources.Get "sunset.jpg" }} +``` + +### Global resource + +{{% glossary-term "global resource" %}} + +```text +assets/ +└── images/ + └── sunset.jpg <-- global resource +``` + +To access an image as a global resource: + +```go-html-template +{{ $image := resources.Get "images/sunset.jpg" }} +``` + +### Remote resource + +{{% glossary-term "remote resource" %}} + +To access an image as a remote resource: + +```go-html-template +{{ $image := resources.GetRemote "https://gohugo.io/img/hugo-logo.png" }} +``` + +## Image rendering + +Once you have accessed an image as a resource, render it in your templates using the `Permalink`, `RelPermalink`, `Width`, and `Height` properties. + +Example 1: Throws an error if the resource is not found. + +```go-html-template +{{ $image := .Resources.GetMatch "sunset.jpg" }} +<img src="{{ $image.RelPermalink }}" width="{{ $image.Width }}" height="{{ $image.Height }}"> +``` + +Example 2: Skips image rendering if the resource is not found. + +```go-html-template +{{ $image := .Resources.GetMatch "sunset.jpg" }} +{{ with $image }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> +{{ end }} +``` + +Example 3: A more concise way to skip image rendering if the resource is not found. + +```go-html-template +{{ with .Resources.GetMatch "sunset.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> +{{ end }} +``` + +Example 4: Skips rendering if there's problem accessing a remote resource. + +```go-html-template +{{ $url := "https://gohugo.io/img/hugo-logo.png" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else with .Value }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> + {{ else }} + {{ errorf "Unable to get remote resource %q" $url }} + {{ end }} +{{ end }} +``` + +## Image processing methods + +The `image` resource implements the [`Process`], [`Resize`], [`Fit`], [`Fill`], [`Crop`], [`Filter`], [`Colors`] and [`Exif`] methods. + +> [!note] +> Metadata (EXIF, IPTC, XMP, etc.) is not preserved during image transformation. Use the `Exif` method with the _original_ image to extract EXIF metadata from JPEG, PNG, TIFF, and WebP images. + +### Process + +{{< new-in 0.119.0 />}} + +> [!note] +> The `Process` method is also available as a filter, which is more effective if you need to apply multiple filters to an image. See [Process filter](/functions/images/process). + +Process processes the image with the given specification. The specification can contain an optional action, one of `resize`, `crop`, `fit` or `fill`. This means that you can use this method instead of [`Resize`], [`Fit`], [`Fill`], or [`Crop`]. + +See [Options](#image-processing-options) for available options. + +You can also use this method apply image processing that does not need any scaling, e.g. format conversions: + +```go-html-template +{{/* Convert the image from JPG to PNG. */}} +{{ $png := $jpg.Process "png" }} +``` + +Some more examples: + +```go-html-template +{{/* Rotate the image 90 degrees counter-clockwise. */}} +{{ $image := $image.Process "r90" }} + +{{/* Scaling actions. */}} +{{ $image := $image.Process "resize 600x" }} +{{ $image := $image.Process "crop 600x400" }} +{{ $image := $image.Process "fit 600x400" }} +{{ $image := $image.Process "fill 600x400" }} +``` + +### Resize + +Resize an image to the given width and/or height. + +If you specify both width and height, the resulting image will be disproportionally scaled unless the original image has the same aspect ratio. + +```go-html-template +{{/* Resize to a width of 600px and preserve aspect ratio */}} +{{ $image := $image.Resize "600x" }} + +{{/* Resize to a height of 400px and preserve aspect ratio */}} +{{ $image := $image.Resize "x400" }} + +{{/* Resize to a width of 600px and a height of 400px */}} +{{ $image := $image.Resize "600x400" }} +``` + +### Fit + +Downscale an image to fit the given dimensions while maintaining aspect ratio. You must provide both width and height. + +```go-html-template +{{ $image := $image.Fit "600x400" }} +``` + +### Fill + +Crop and resize an image to match the given dimensions. You must provide both width and height. Use the [`anchor`] option to change the crop box anchor point. + +```go-html-template +{{ $image := $image.Fill "600x400" }} +``` + +### Crop + +Crop an image to match the given dimensions without resizing. You must provide both width and height. Use the [`anchor`] option to change the crop box anchor point. + +```go-html-template +{{ $image := $image.Crop "600x400" }} +``` + +### Filter + +Apply one or more [filters] to an image. + +```go-html-template +{{ $image := $image.Filter (images.GaussianBlur 6) (images.Pixelate 8) }} +``` + +Write this in a more functional style using pipes. Hugo applies the filters in the order given. + +```go-html-template +{{ $image := $image | images.Filter (images.GaussianBlur 6) (images.Pixelate 8) }} +``` + +Sometimes it can be useful to create the filter chain once and then reuse it. + +```go-html-template +{{ $filters := slice (images.GaussianBlur 6) (images.Pixelate 8) }} +{{ $image1 := $image1.Filter $filters }} +{{ $image2 := $image2.Filter $filters }} +``` + +### Colors + +`.Colors` returns a slice of hex strings with the dominant colors in the image using a simple histogram method. + +```go-html-template +{{ $colors := $image.Colors }} +``` + +This method is fast, but if you also scale down your images, it would be good for performance to extract the colors from the scaled down image. + +### EXIF + +Provides an [EXIF] object containing image metadata. + +You may access EXIF data in JPEG, PNG, TIFF, and WebP images. To prevent errors when processing images without EXIF data, wrap the access in a [`with`] statement. + +```go-html-template +{{ with $image.Exif }} + Date: {{ .Date }} + Lat/Long: {{ .Lat }}/{{ .Long }} + Tags: + {{ range $k, $v := .Tags }} + TAG: {{ $k }}: {{ $v }} + {{ end }} +{{ end }} +``` + +You may also access EXIF fields individually, using the [`lang.FormatNumber`] function to format the fields as needed. + +```go-html-template +{{ with $image.Exif }} + <ul> + {{ with .Date }}<li>Date: {{ .Format "January 02, 2006" }}</li>{{ end }} + {{ with .Tags.ApertureValue }}<li>Aperture: {{ lang.FormatNumber 2 . }}</li>{{ end }} + {{ with .Tags.BrightnessValue }}<li>Brightness: {{ lang.FormatNumber 2 . }}</li>{{ end }} + {{ with .Tags.ExposureTime }}<li>Exposure Time: {{ . }}</li>{{ end }} + {{ with .Tags.FNumber }}<li>F Number: {{ . }}</li>{{ end }} + {{ with .Tags.FocalLength }}<li>Focal Length: {{ . }}</li>{{ end }} + {{ with .Tags.ISOSpeedRatings }}<li>ISO Speed Ratings: {{ . }}</li>{{ end }} + {{ with .Tags.LensModel }}<li>Lens Model: {{ . }}</li>{{ end }} + </ul> +{{ end }} +``` + +#### EXIF methods + +Date +: (`time.Time`) Returns the image creation date/time. Format with the [`time.Format`]function. + +Lat +: (`float64`) Returns the GPS latitude in degrees. + +Long +: (`float64`) Returns the GPS longitude in degrees. + +Tags +: (`exif.Tags`) Returns a collection of the available EXIF tags for this image. You may include or exclude specific tags from this collection in the [site configuration]. + +## Image processing options + +The [`Resize`], [`Fit`], [`Fill`], and [`Crop`] methods accept a space-delimited, case-insensitive list of options. The order of the options within the list is irrelevant. + +### Dimensions + +With the [`Resize`] method you must specify width, height, or both. The [`Fit`], [`Fill`], and [`Crop`] methods require both width and height. All dimensions are in pixels. + +```go-html-template +{{ $image := $image.Resize "600x" }} +{{ $image := $image.Resize "x400" }} +{{ $image := $image.Resize "600x400" }} +{{ $image := $image.Fit "600x400" }} +{{ $image := $image.Fill "600x400" }} +{{ $image := $image.Crop "600x400" }} +``` + +### Rotation + +Rotates an image counter-clockwise by the given angle. Hugo performs rotation _before_ scaling. For example, if the original image is 600x400 and you wish to rotate the image 90 degrees counter-clockwise while scaling it by 50%: + +```go-html-template +{{ $image = $image.Resize "200x r90" }} +``` + +In the example above, the width represents the desired width _after_ rotation. + +To rotate an image without scaling, use the dimensions of the original image: + +```go-html-template +{{ with .Resources.GetMatch "sunset.jpg" }} + {{ with .Resize (printf "%dx%d r90" .Height .Width) }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> + {{ end }} +{{ end }} +``` + +In the example above, on the second line, we have reversed width and height to reflect the desired dimensions _after_ rotation. + +### Anchor + +When using the [`Crop`] or [`Fill`] method, the _anchor_ determines the placement of the crop box. You may specify `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`. + +The default value is `Smart`, which uses [Smartcrop] image analysis to determine the optimal placement of the crop box. You may override the default value in the [site configuration]. + +For example, if you have a 400x200 image with a bird in the upper left quadrant, you can create a 200x100 thumbnail containing the bird: + +```go-html-template +{{ $image.Crop "200x100 TopLeft" }} +``` + +If you apply [rotation](#rotation) when using the [`Crop`] or [`Fill`] method, specify the anchor relative to the rotated image. + +### Target format + +By default, Hugo encodes the image in the source format. You may convert the image to another format by specifying `bmp`, `gif`, `jpeg`, `jpg`, `png`, `tif`, `tiff`, or `webp`. + +```go-html-template +{{ $image.Resize "600x webp" }} +``` + +To convert an image without scaling, use the dimensions of the original image: + +```go-html-template +{{ with .Resources.GetMatch "sunset.jpg" }} + {{ with .Resize (printf "%dx%d webp" .Width .Height) }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> + {{ end }} +{{ end }} +``` + +### Quality + +Applicable to JPEG and WebP images, the `q` value determines the quality of the converted image. Higher values produce better quality images, while lower values produce smaller files. Set this value to a whole number between 1 and 100, inclusive. + +The default value is 75. You may override the default value in the [site configuration]. + +```go-html-template +{{ $image.Resize "600x webp q50" }} +``` + +### Hint + +Applicable to WebP images, this option corresponds to a set of predefined encoding parameters, and is equivalent to the `-preset` flag for the [`cwebp`] encoder. + +Value|Example +:--|:-- +`drawing`|Hand or line drawing with high-contrast details +`icon`|Small colorful image +`photo`|Outdoor photograph with natural lighting +`picture`|Indoor photograph such as a portrait +`text`|Image that is primarily text + +The default value is `photo`. You may override the default value in the [site configuration]. + +```go-html-template +{{ $image.Resize "600x webp picture" }} +``` + +### Background color + +When converting an image from a format that supports transparency (e.g., PNG) to a format that does _not_ support transparency (e.g., JPEG), you may specify the background color of the resulting image. + +Use either a 3-digit or 6-digit hexadecimal color code (e.g., `#00f` or `#0000ff`). + +The default value is `#ffffff` (white). You may override the default value in the [site configuration]. + +```go-html-template +{{ $image.Resize "600x jpg #b31280" }} +``` + +### Resampling filter + +You may specify the resampling filter used when resizing an image. Commonly used resampling filters include: + +Filter|Description +:--|:-- +`Box`|Simple and fast averaging filter appropriate for downscaling +`Lanczos`|High-quality resampling filter for photographic images yielding sharp results +`CatmullRom`|Sharp cubic filter that is faster than the Lanczos filter while providing similar results +`MitchellNetravali`|Cubic filter that produces smoother results with less ringing artifacts than CatmullRom +`Linear`|Bilinear resampling filter, produces smooth output, faster than cubic filters +`NearestNeighbor`|Fastest resampling filter, no antialiasing + +The default value is `Box`. You may override the default value in the [site configuration]. + +```go-html-template +{{ $image.Resize "600x400 Lanczos" }} +``` + +See [github.com/disintegration/imaging] for the complete list of resampling filters. If you wish to improve image quality at the expense of performance, you may wish to experiment with the alternative filters. + +## Image processing examples + +_The photo of the sunset used in the examples below is Copyright [Bjørn Erik Pedersen](https://bep.is) (Creative Commons Attribution-Share Alike 4.0 International license)_ + +{{< imgproc path="sunset.jpg" spec="resize 480x" alt="A sunset" />}} + +{{< imgproc path="sunset.jpg" spec="fill 120x150 left" alt="A sunset" />}} + +{{< imgproc path="sunset.jpg" spec="fill 120x150 right" alt="A sunset" />}} + +{{< imgproc path="sunset.jpg" spec="fit 120x120" alt="A sunset" />}} + +{{< imgproc path="sunset.jpg" spec="crop 240x240 center" alt="A sunset" />}} + +{{< imgproc path="sunset.jpg" spec="resize 360x q10" alt="A sunset" />}} + +## Configuration + +See [configure imaging](/configuration/imaging). + +## Smart cropping of images + +By default, Hugo uses the [Smartcrop] library when cropping images with the `Crop` or `Fill` methods. You can set the anchor point manually, but in most cases the `Smart` option will make a good choice. + +Examples using the sunset image from above: + +{{< imgproc path="sunset.jpg" spec="fill 200x200 smart" alt="A sunset" />}} + +{{< imgproc path="sunset.jpg" spec="crop 200x200 smart" alt="A sunset" />}} + +## Image processing performance consideration + +Hugo caches processed images in the `resources` directory. If you include this directory in source control, Hugo will not have to regenerate the images in a [CI/CD](g) workflow (e.g., GitHub Pages, GitLab Pages, Netlify, etc.). This results in faster builds. + +If you change image processing methods or options, or if you rename or remove images, the `resources` directory will contain unused images. To remove the unused images, perform garbage collection with: + +```sh +hugo --gc +``` + +[`anchor`]: /content-management/image-processing#anchor +[`Colors`]: #colors +[`Crop`]: #crop +[`cwebp`]: https://developers.google.com/speed/webp/docs/cwebp +[`Exif`]: #exif +[`Fill`]: #fill +[`Filter`]: #filter +[`Fit`]: #fit +[`lang.FormatNumber`]: /functions/lang/formatnumber/ +[`Process`]: #process +[`Resize`]: #resize +[`time.Format`]: /functions/time/format/ +[`with`]: /functions/go-template/with/ +[EXIF]: https://en.wikipedia.org/wiki/Exif +[filters]: /functions/images/filter/#image-filters +[github.com/disintegration/imaging]: https://github.com/disintegration/imaging#image-resizing +[site configuration]: /configuration/imaging/ +[Smartcrop]: https://github.com/muesli/smartcrop#smartcrop diff --git a/docs/content/en/content-management/image-processing/sunset.jpg b/docs/content/en/content-management/image-processing/sunset.jpg Binary files differnew file mode 100644 index 000000000..4dbcc0836 --- /dev/null +++ b/docs/content/en/content-management/image-processing/sunset.jpg diff --git a/docs/content/en/content-management/markdown-attributes.md b/docs/content/en/content-management/markdown-attributes.md new file mode 100644 index 000000000..f52a48f17 --- /dev/null +++ b/docs/content/en/content-management/markdown-attributes.md @@ -0,0 +1,108 @@ +--- +title: Markdown attributes +description: Use Markdown attributes to add HTML attributes when rendering Markdown to HTML. +categories: [] +keywords: [] +--- + +## Overview + +Hugo supports Markdown attributes on images and block elements including blockquotes, fenced code blocks, headings, horizontal rules, lists, paragraphs, and tables. + +For example: + +```text +This is a paragraph. +{class="foo bar" id="baz"} +``` + +With `class` and `id` you can use shorthand notation: + +```text +This is a paragraph. +{.foo .bar #baz} +``` + +Hugo renders both of these to: + +```html +<p class="foo bar" id="baz">This is a paragraph.</p> +``` + +## Block elements + +Update your site configuration to enable Markdown attributes for block-level elements. + +{{< code-toggle file=hugo >}} +[markup.goldmark.parser.attribute] +title = true # default is true +block = true # default is false +{{< /code-toggle >}} + +## Standalone images + +By default, when the [Goldmark] Markdown renderer encounters a standalone image element (no other elements or text on the same line), it wraps the image element within a paragraph element per the [CommonMark specification]. + +[CommonMark specification]: https://spec.commonmark.org/current/ +[Goldmark]: https://github.com/yuin/goldmark + +If you were to place an attribute list beneath an image element, Hugo would apply the attributes to the surrounding paragraph, not the image. + +To apply attributes to a standalone image element, you must disable the default wrapping behavior: + +{{< code-toggle file=hugo >}} +[markup.goldmark.parser] +wrapStandAloneImageWithinParagraph = false # default is true +{{< /code-toggle >}} + +## Usage + +You may add [global HTML attributes], or HTML attributes specific to the current element type. Consistent with its content security model, Hugo removes HTML event attributes such as `onclick` and `onmouseover`. + +[global HTML attributes]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes + +The attribute list consists of one or more key-value pairs, separated by spaces or commas, wrapped by braces. You must quote string values that contain spaces. Unlike HTML, boolean attributes must have both key and value. + +For example: + +```text +> This is a blockquote. +{class="foo bar" hidden=hidden} +``` + +Hugo renders this to: + +```html +<blockquote class="foo bar" hidden="hidden"> + <p>This is a blockquote.</p> +</blockquote> +``` + +In most cases, place the attribute list beneath the markup element. For headings and fenced code blocks, place the attribute list on the right. + +Element|Position of attribute list +:--|:-- +blockquote | bottom +fenced code block | right +heading | right +horizontal rule | bottom +image | bottom +list | bottom +paragraph | bottom +table | bottom + +For example: + +````text +## Section 1 {class=foo} + +```bash {class=foo linenos=inline} +declare a=1 +echo "${a}" +``` + +This is a paragraph. +{class=foo} +```` + +As shown above, the attribute list for fenced code blocks is not limited to HTML attributes. You can also configure syntax highlighting by passing one or more of [these options](/functions/transform/highlight/#options). diff --git a/docs/content/en/content-management/mathematics.md b/docs/content/en/content-management/mathematics.md new file mode 100644 index 000000000..e0c8ba4d0 --- /dev/null +++ b/docs/content/en/content-management/mathematics.md @@ -0,0 +1,238 @@ +--- +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 + +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 = [['\(', '\)']] + +[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]. + +> [!note] +> The configuration above precludes the use of the `$...$` delimiter pair for inline equations. Although you can add this delimiter pair to the configuration and JavaScript, you will need to double-escape the `$` symbol when used outside of math contexts to avoid unintended formatting. +> +> See the [inline delimiters](#inline-delimiters) section for details. + +To disable passthrough of inline snippets, omit the `inline` key from the configuration: + +{{< 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]. + +{{< 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. + +```go-html-template {file="layouts/partials/math.html" copy=true} +<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script> +<script> + MathJax = { + tex: { + displayMath: [['\\[', '\\]'], ['$$', '$$']], // block + inlineMath: [['\\(', '\\)']] // inline + }, + loader:{ + load: ['ui/safe'] + }, + }; +</script> +``` + +The delimiters above must match the delimiters in your site configuration. + +### Step 3 + +Conditionally call the partial template from the base template. + +```go-html-template {file="layouts/_default/baseof.html"} +<head> + ... + {{ if .Param "math" }} + {{ partialCached "math.html" . }} + {{ end }} + ... +</head> +``` + +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 4 + +Include mathematical equations and expressions in Markdown using LaTeX markup. + +```text {file="content/math-examples.md" copy=true} +This is an inline \(a^*=x-b^*\) equation. + +These are block equations: + +\[a^*=x-b^*\] + +\[ a^*=x-b^* \] + +\[ +a^*=x-b^* +\] + +These are also block equations: + +$$a^*=x-b^*$$ + +$$ a^*=x-b^* $$ + +$$ +a^*=x-b^* +$$ +``` + +If you set the `math` parameter to `false` in your site configuration, you must set the `math` parameter to `true` in front matter. For example: + +{{< code-toggle file=content/math-examples.md fm=true >}} +title = 'Math examples' +date = 2024-01-24T18:09:49-08:00 +[params] +math = true +{{< /code-toggle >}} + +## Inline delimiters + +The configuration, JavaScript, and examples above use the `\(...\)` delimiter pair for inline equations. The `$...$` delimiter pair is a common alternative, but using it may result in unintended formatting if you use the `$` symbol outside of math contexts. + +If you add the `$...$` delimiter pair to your configuration and JavaScript, you must double-escape the `$` when outside of math contexts, regardless of whether mathematical rendering is enabled on the page. For example: + +```text +A \\$5 bill _saved_ is a \\$5 bill _earned_. +``` + +> [!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: + +```go-html-template {file="layouts/partials/math.html" copy=true} +<link + rel="stylesheet" + href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css" + integrity="sha384-zh0CIslj+VczCZtlzBcjt5ppRcsAmDnRem7ESsYwWwg3m/OaJ2l4x7YBZl9Kxxib" + crossorigin="anonymous" +> +<script + defer + src="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.js" + integrity="sha384-Rma6DA2IPUwhNxmrB/7S3Tno0YY7sFu9WSYMCuulLhIqYSGZ2gKCJWIqhBWqMQfh" + crossorigin="anonymous"> +</script> +<script + defer + src="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/contrib/auto-render.min.js" + integrity="sha384-hCXGrW6PitJEwbkoStFjeJxv+fSOOQKOPbJxSfM6G5sWZjAyWhXiTIIAmQqnlLlh" + crossorigin="anonymous" + onload="renderMathInElement(document.body);"> +</script> +<script> + document.addEventListener("DOMContentLoaded", function() { + renderMathInElement(document.body, { + delimiters: [ + {left: '\\[', right: '\\]', display: true}, // block + {left: '$$', right: '$$', display: true}, // block + {left: '\\(', right: '\\)', display: false}, // inline + ], + throwOnError : false + }); + }); +</script> +``` + +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). + +[`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 --git a/docs/content/en/content-management/menus.md b/docs/content/en/content-management/menus.md new file mode 100644 index 000000000..ab1bcbfa1 --- /dev/null +++ b/docs/content/en/content-management/menus.md @@ -0,0 +1,97 @@ +--- +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] 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 = '<i class="fa-solid fa-code"></i>' +[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 --git a/docs/content/en/content-management/multilingual.md b/docs/content/en/content-management/multilingual.md new file mode 100644 index 000000000..d419f4381 --- /dev/null +++ b/docs/content/en/content-management/multilingual.md @@ -0,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__. + +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. + +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. + +### 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 }} +<h4>{{ i18n "translations" }}</h4> +<ul> + {{ range .Translations }} + <li> + <a href="{{ .RelPermalink }}">{{ .Language.Lang }}: {{ .LinkTitle }}{{ if .IsPage }} ({{ i18n "wordCount" . }}){{ end }}</a> + </li> + {{ end }} +</ul> +{{ end }} +``` + +The above can be put in a `partial` (i.e., inside `layouts/partials/`) and included in any template. It will not print anything if there are no translations for a given page. + +The above 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"} +<ul> +{{ range $.Site.Home.AllTranslations }} +<li><a href="{{ .RelPermalink }}">{{ .Language.LanguageName }}</a></li> +{{ end }} +</ul> +``` + +## 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 --git a/docs/content/en/content-management/organization/index.md b/docs/content/en/content-management/organization/index.md new file mode 100644 index 000000000..a7682bfad --- /dev/null +++ b/docs/content/en/content-management/organization/index.md @@ -0,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/<DIRECTORIES>`) 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 [single 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. + +### `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/ +[single template]: /templates/types/#single diff --git a/docs/content/en/content-management/page-bundles.md b/docs/content/en/content-management/page-bundles.md new file mode 100644 index 000000000..f6a5cf771 --- /dev/null +++ b/docs/content/en/content-management/page-bundles.md @@ -0,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 ` | +| [Page kinds](g) | `page` | `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 --git a/docs/content/en/content-management/page-resources.md b/docs/content/en/content-management/page-resources.md new file mode 100644 index 000000000..204ca5301 --- /dev/null +++ b/docs/content/en/content-management/page-resources.md @@ -0,0 +1,297 @@ +--- +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`] + + 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 }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ 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" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ 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 }} + <p>Books:</p> + <ul> + {{ range . }} + <li>{{ .title }}</li> + {{ end }} + </ul> + {{ 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" +{{</ code-toggle >}} + +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" +{{</ code-toggle >}} + +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] +> 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. +> +> You may override the embedded render hooks as needed, provided they capture the resource as described above. + +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 diff --git a/docs/content/en/content-management/related-content.md b/docs/content/en/content-management/related-content.md new file mode 100644 index 000000000..d7b18dab0 --- /dev/null +++ b/docs/content/en/content-management/related-content.md @@ -0,0 +1,102 @@ +--- +title: Related content +description: List related content in "See Also" sections. +categories: [] +keywords: [] +aliases: [/content/related/,/related/,/content-management/related/] +--- + +Hugo uses a set of factors to identify a page's related content based on front matter parameters. This can be tuned to the desired set of indices and parameters or left to Hugo's default [related content configuration](/configuration/related-content/). + +## List related content + +To list up to 5 related pages (which share the same _date_ or _keyword_ parameters) is as simple as including something similar to this partial in your template: + +```go-html-template {file="layouts/partials/related.html" copy=true} +{{ with site.RegularPages.Related . | first 5 }} + <p>Related content:</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The `Related` method takes one argument which may be a `Page` or an options map. The options map has these options: + +indices +: (`slice`) The indices to search within. + +document +: (`page`) The page for which to find related content. Required when specifying an options map. + +namedSlices +: (`slice`) The keywords to search for, expressed as a slice of `KeyValues` using the [`keyVals`] function. + +fragments +: (`slice`) A list of special keywords that is used for indices configured as type "fragments". This will match the [fragment](g) identifiers of the documents. + +A fictional example using all of the above options: + +```go-html-template +{{ $page := . }} +{{ $opts := dict + "indices" (slice "tags" "keywords") + "document" $page + "namedSlices" (slice (keyVals "tags" "hugo" "rocks") (keyVals "date" $page.Date)) + "fragments" (slice "heading-1" "heading-2") +}} +``` + +> [!note] +> We improved and simplified this feature in Hugo 0.111.0. Before this we had 3 different methods: `Related`, `RelatedTo` and `RelatedIndices`. Now we have only one method: `Related`. The old methods are still available but deprecated. Also see [this blog article](https://regisphilibert.com/blog/2018/04/hugo-optmized-relashionships-with-related-content/) for a great explanation of more advanced usage of this feature. + +## Index content headings + +Hugo can index the headings in your content and use this to find related content. You can enable this by adding a index of type `fragments` to your `related` configuration: + +{{< code-toggle file=hugo >}} +[related] +threshold = 20 +includeNewer = true +toLower = false +[[related.indices]] +name = "fragmentrefs" +type = "fragments" +applyFilter = true +weight = 80 +{{< /code-toggle >}} + +- The `name` maps to a optional front matter slice attribute that can be used to link from the page level down to the fragment/heading level. +- If `applyFilter` is enabled, the `.HeadingsFiltered` on each page in the result will reflect the filtered headings. This is useful if you want to show the headings in the related content listing: + +```go-html-template +{{ $related := .Site.RegularPages.Related . | first 5 }} +{{ with $related }} + <h2>See Also</h2> + <ul> + {{ range $i, $p := . }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + {{ with .HeadingsFiltered }} + <ul> + {{ range . }} + {{ $link := printf "%s#%s" $p.RelPermalink .ID | safeURL }} + <li> + <a href="{{ $link }}">{{ .Title }}</a> + </li> + {{ end }} + </ul> + {{ end }} + </li> + {{ end }} + </ul> +{{ end }} +``` + +## Configuration + +See [configure related content](/configuration/related-content/). + +[`keyVals`]: /functions/collections/keyvals/ diff --git a/docs/content/en/content-management/sections.md b/docs/content/en/content-management/sections.md new file mode 100644 index 000000000..f7a2296f5 --- /dev/null +++ b/docs/content/en/content-management/sections.md @@ -0,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 +:--|:-:|:-: +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 list 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/list.html` +`content/products/product-1`|`layouts/products/list.html` +`content/products/product-1/benefits`|`layouts/products/list.html` + +Content directory|Single template +:--|:-- +`content/products`|`layouts/products/single.html` +`content/products/product-1`|`layouts/products/single.html` +`content/products/product-1/benefits`|`layouts/products/single.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"} +<nav aria-label="breadcrumb" class="breadcrumb"> + <ol> + {{ range .Ancestors.Reverse }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + </li> + {{ end }} + <li class="active"> + <a aria-current="page" href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + </li> + </ol> +</nav> +``` + +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 --git a/docs/content/en/content-management/shortcodes.md b/docs/content/en/content-management/shortcodes.md new file mode 100644 index 000000000..2de387f39 --- /dev/null +++ b/docs/content/en/content-management/shortcodes.md @@ -0,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): + +```go-html-template {file="layouts/shortcodes/audio.html"} +{{ with resources.Get (.Get "src") }} + <audio controls preload="auto" src="{{ .RelPermalink }}"></audio> +{{ end }} +``` + +Then call the shortcode from within markup: + +```text {file="content/example.md"} +{{</* audio src=/audio/test.mp3 */>}} +``` + +Learn more about creating shortcodes in the [shortcode templates] section. + +## Inline + +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: + +{{< 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 +{{</* date.inline ":date_medium" */>}} + {{- now | time.Format (.Get 0) -}} +{{</* /date.inline */>}}. + +Today is {{</* date.inline ":date_full" /*/>}}. +``` + +In the example above, the inline shortcode is executed twice: once upon definition and again when subsequently called. Hugo renders this to: + +```html +<p>Today is Jan 30, 2025.</p> +<p>Today is Thursday, January 30, 2025</p> +``` + +Inline shortcodes process their inner content within the same context as regular shortcode templates, allowing you to use any available [shortcode method]. + +> [!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 +{{</* details summary="See the details" */>}} +This is a **bold** word. +{{</* /details */>}} +``` + +Some shortcodes do not accept content. For example, the embedded [`instagram`] shortcode requires a single _positional_ argument: + +```text +{{</* instagram CxOWiQNP2MO */>}} +``` + +Some shortcodes optionally accept content. For example, you can call the embedded [`qr`] shortcode with content: + +```text +{{</* qr */>}} +https://gohugo.io +{{</* /qr */>}} +``` + +Or use the self-closing syntax with a trailing slash to pass the text as an argument: + +```text +{{</* qr text=https://gohugo.io /*/>}} +``` + +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 +{{</* figure src=/images/kitten.jpg */>}} +``` + +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 +{{</* instagram CxOWiQNP2MO */>}} +``` + +Shortcode arguments are space-delimited, and arguments with internal spaces must be quoted. + +```text +{{</* figure src=/images/kitten.jpg alt="A white kitten" */>}} +``` + +Shortcodes accept [scalar](g) arguments, one of [string](g), [integer](g), [floating point](g), or [boolean](g). + +```text +{{</* my-shortcode name="John Smith" age=24 married=false */>}} +``` + +You can optionally use multiple lines when providing several arguments to a shortcode for better readability: + +```text +{{</* figure + src=/images/kitten.jpg + alt="A white kitten" + caption="This is a white kitten" + loading=lazy +*/>}} +``` + +Use a [raw string literal](g) if you need to pass a multiline string: + +```text +{{</* myshortcode `This is some <b>HTML</b>, +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|`{{</* foo */>}} ## Section 2 {{</* /foo */>}}` + +#### 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: + +```go-html-template {file="layouts/shortcodes/foo.html"} +{{ .Inner }} +``` + +And this markdown: + +```text {file="content/example.md"} +{{%/* foo */%}} ## Section 1 {{%/* /foo */%}} + +{{</* foo */>}} ## Section 2 {{</* /foo */>}} +``` + +Hugo renders this HTML: + +```html +<h2 id="heading">Section 1</h2> + +## 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"} +{{</* gallery class="content-gallery" */>}} + {{</* image src="/images/a.jpg" */>}} + {{</* image src="/images/b.jpg" */>}} + {{</* image src="/images/c.jpg" */>}} +{{</* /gallery */>}} +``` + +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 --git a/docs/content/en/content-management/summaries.md b/docs/content/en/content-management/summaries.md new file mode 100644 index 000000000..da61c2c8e --- /dev/null +++ b/docs/content/en/content-management/summaries.md @@ -0,0 +1,123 @@ +--- +title: Content summaries +linkTitle: Summaries +description: Create and render content summaries. +categories: [] +keywords: [] +aliases: [/content/summaries/,/content-management/content-summaries/] +--- + +<!-- Do not remove the manual summary divider below. --> +<!-- If you do, you will break its first literal usage on this page. --> + +<!--more--> + +You can define a summary manually, in front matter, or automatically. A manual summary takes precedence over a front matter summary, and a front matter summary takes precedence over an automatic summary. + +Review the [comparison table](#comparison) below to understand the characteristics of each summary type. + +## Manual summary + +Use a `<!--more-->` divider to indicate the end of the summary. Hugo will not render the summary divider itself. + +```text {file="content/example.md"} ++++ +title: 'Example' +date: 2024-05-26T09:10:33-07:00 ++++ + +This is the first paragraph. + +<!--more--> + +This is the second paragraph. +``` + +When using the Emacs Org Mode [content format], use a `# more` divider to indicate the end of the summary. + +[content format]: /content-management/formats/ + +## Front matter summary + +Use front matter to define a summary independent of content. + +```text {file="content/example.md"} ++++ +title: 'Example' +date: 2024-05-26T09:10:33-07:00 +summary: 'This summary is independent of the content.' ++++ + +This is the first paragraph. + +This is the second paragraph. +``` + +## Automatic summary + +If you do not define the summary manually or in front matter, Hugo automatically defines the summary based on the [`summaryLength`] in your site configuration. + +[`summaryLength`]: /configuration/all/#summarylength + +```text {file="content/example.md"} ++++ +title: 'Example' +date: 2024-05-26T09:10:33-07:00 ++++ + +This is the first paragraph. + +This is the second paragraph. + +This is the third paragraph. +``` + +For example, with a `summaryLength` of 7, the automatic summary will be: + +```html +<p>This is the first paragraph.</p> +<p>This is the second paragraph.</p> +``` + +## Comparison + +Each summary type has different characteristics: + +Type|Precedence|Renders markdown|Renders shortcodes|Wraps single lines with `<p>` +:--|:-:|:-:|:-:|:-: +Manual|1|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: +Front matter|2|:heavy_check_mark:|:x:|:x: +Automatic|3|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark: + +## Rendering + +Render the summary in a template by calling the [`Summary`] method on a `Page` object. + +[`Summary`]: /methods/page/summary + +```go-html-template +{{ range site.RegularPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + <div class="summary"> + {{ .Summary }} + {{ if .Truncated }} + <a href="{{ .RelPermalink }}">More ...</a> + {{ end }} + </div> +{{ end }} +``` + +## Alternative + +Instead of calling the `Summary` method on a `Page` object, use the [`strings.Truncate`] function for granular control of the summary length. For example: + +[`strings.Truncate`]: /functions/strings/truncate/ + +```go-html-template +{{ range site.RegularPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + <div class="summary"> + {{ .Content | strings.Truncate 42 }} + </div> +{{ end }} +``` diff --git a/docs/content/en/content-management/syntax-highlighting.md b/docs/content/en/content-management/syntax-highlighting.md new file mode 100644 index 000000000..7e87efa49 --- /dev/null +++ b/docs/content/en/content-management/syntax-highlighting.md @@ -0,0 +1,102 @@ +--- +title: Syntax highlighting +description: Add syntax highlighting to code examples. +categories: [] +keywords: [highlight] +aliases: [/extras/highlighting/,/extras/highlight/,/tools/syntax-highlighting/] +--- + +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 + +[`transform.Highlight`]: /functions/transform/highlight/ +[`highlight`]: /shortcodes/highlight/ + +## Fenced code blocks + +In its default configuration, Hugo highlights code examples within fenced code blocks, following this form: + +````text {file="content/example.md"} +```LANG [OPTIONS] +CODE +``` +```` + +CODE +: The code to highlight. + +LANG +: The language of the code to highlight. Choose from one of the [supported languages]. This value is case-insensitive. + +OPTIONS +: One or more space-separated or comma-separated key-value pairs wrapped in braces. Set default values for each option in your [site configuration]. The key names are case-insensitive. + +[supported languages]: #languages +[site configuration]: /configuration/markup/#highlight + +For example, with this Markdown: + +````text {file="content/example.md"} +```go {linenos=inline hl_lines=[3,"6-8"] style=emacs} +package main + +import "fmt" + +func main() { + for i := 0; i < 3; i++ { + fmt.Println("Value of i:", i) + } +} +``` +```` + +Hugo renders this: + +```go {linenos=inline, hl_lines=[3, "6-8"], style=emacs} +package main + +import "fmt" + +func main() { + for i := 0; i < 3; i++ { + fmt.Println("Value of i:", i) + } +} +``` + +## Options + +{{% include "_common/syntax-highlighting-options.md" %}} + +## Escaping + +When documenting shortcode usage, escape the tag delimiters: + +````text {file="content/example.md"} +```text {linenos=inline} +{{</*/* shortcode-1 */*/>}} + +{{%/*/* shortcode-2 */*/%}} +``` +```` + +Hugo renders this to: + +```text {linenos=inline} +{{</* shortcode-1 */>}} + +{{%/* shortcode-2 */%}} +``` + +## Languages + +These are the supported languages. Use one of the identifiers, not the language name, when specifying a language for: + +- The [`transform.Highlight`] function +- The [`highlight`] shortcode +- Fenced code blocks + +{{< chroma-lexers >}} diff --git a/docs/content/en/content-management/taxonomies.md b/docs/content/en/content-management/taxonomies.md new file mode 100644 index 000000000..e8ba04c28 --- /dev/null +++ b/docs/content/en/content-management/taxonomies.md @@ -0,0 +1,125 @@ +--- +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. + +### 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: + +- 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] + +## 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`. + +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 +{{</ code-toggle >}} + +By using taxonomic weight, the same piece of content can appear in different positions in different taxonomies. + +## Add custom metadata to a taxonomy or term + +If you need to add custom metadata to your taxonomy terms, you will need to create a page for that term at `/content/<TAXONOMY>/<TERM>/_index.md` and add your metadata in its front matter. Continuing with our 'Actors' example, let's say you want to add a Wikipedia page link to each actor. Your terms pages would be something like this: + +{{< code-toggle file=content/actors/bruce-willis/_index.md fm=true >}} +title: "Bruce Willis" +wikipedia: "https://en.wikipedia.org/wiki/Bruce_Willis" +{{< /code-toggle >}} + +[content section]: /content-management/sections/ +[content type]: /content-management/types/ +[documentation on archetypes]: /content-management/archetypes/ +[front matter]: /content-management/front-matter/ +[taxonomy templates]: /templates/types/#taxonomy +[site configuration]: /configuration/ diff --git a/docs/content/en/content-management/types.md b/docs/content/en/content-management/types.md new file mode 100644 index 000000000..08e9adda2 --- /dev/null +++ b/docs/content/en/content-management/types.md @@ -0,0 +1,14 @@ +--- +title: Content types +description: Hugo is built around content organized in sections. +categories: [] +keywords: [] +aliases: [/content/types] +--- + +A **content type** is a way to organize your content. Hugo resolves the content type from either the `type` in front matter or, if not set, the first directory in the file path. E.g. `content/blog/my-first-event.md` will be of type `blog` if no `type` is set. + +A content type is used to + +- Determine how the content is rendered. See [Template Lookup Order](/templates/lookup-order/) and [Content Views](/templates/content-view) for more. +- Determine which [archetype](/content-management/archetypes/) template to use for new content. diff --git a/docs/content/en/content-management/urls.md b/docs/content/en/content-management/urls.md new file mode 100644 index 000000000..2630105e5 --- /dev/null +++ b/docs/content/en/content-management/urls.md @@ -0,0 +1,265 @@ +--- +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. + +{{< 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 usetokens 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 +<a href="/about"> → <a href="https://example.org/about/"> +<img src="/a.gif"> → <img src="https://example.org/a.gif"> +``` + +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 +<a href="/about"> → <a href="../../about"> +<img src="/a.gif"> → <img src="../../a.gif"> +``` + +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"} +<!DOCTYPE html> +<html lang="en-us"> + <head> + <title>https://example.org/posts/new-file-name/</title> + <link rel="canonical" href="https://example.org/posts/new-file-name/"> + <meta name="robots" content="noindex"> + <meta charset="utf-8"> + <meta http-equiv="refresh" content="0; url=https://example.org/posts/new-file-name/"> + </head> +</html> +``` + +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 --git a/docs/content/en/contribute/_index.md b/docs/content/en/contribute/_index.md new file mode 100644 index 000000000..d0ae954b0 --- /dev/null +++ b/docs/content/en/contribute/_index.md @@ -0,0 +1,9 @@ +--- +title: Contribute to the Hugo project +linkTitle: Contribute +description: Contribute to development, documentation, and themes. +categories: [] +keywords: [] +weight: 10 +aliases: [/tutorials/how-to-contribute-to-hugo/,/community/contributing/] +--- diff --git a/docs/content/en/contribute/development.md b/docs/content/en/contribute/development.md new file mode 100644 index 000000000..78ca5ec5c --- /dev/null +++ b/docs/content/en/contribute/development.md @@ -0,0 +1,186 @@ +--- +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 + +Fork the [project repository]. + +### Step 2 + +Clone your fork. + +### Step 3 + +Create a new branch with a descriptive name that includes the corresponding issue number. + +For a new feature: + +```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. + +To compile and install the standard edition: + +```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: + +```text +CGO_ENABLED=1 go install -tags extended,withdeploy +``` + +### Step 6 + +Test your changes: + +```text +go test ./... +``` + +### Step 7 + +Commit your changes with a descriptive commit message: + +- Provide a summary on the first line, typically 50 characters or less, followed by a blank line. + - Begin the summary with one of content, theme, config, all, or misc, followed by a colon, a space, and a brief description of the change beginning with a capital letter + - Use imperative present tense + - See the [commit message guidelines] for requirements +- Optionally, provide a detailed description where each line is 72 characters or less, followed by a blank line. +- Add one or more "Fixes" or "Closes" keywords, each on its own line, referencing the [issues] addressed by this change. + +For example: + +```sh +git commit -m "tpl/strings: Create wrap function + +The strings.Wrap function wraps a string into one or more lines, +splitting the string after the given number of characters, but not +splitting in the middle of a word. + +Fixes #99998 +Closes #99999" +``` + +### Step 8 + +Push the new branch to your fork of the documentation repository. + +### Step 9 + +Visit the [project repository] and create a pull request (PR). + +### Step 10 + +A project maintainer will review your PR and may request changes. You may delete your branch after the maintainer merges your PR. + +## 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.144.2 +``` + +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 +``` + +[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 --git a/docs/content/en/contribute/documentation.md b/docs/content/en/contribute/documentation.md new file mode 100644 index 000000000..1d185d21d --- /dev/null +++ b/docs/content/en/contribute/documentation.md @@ -0,0 +1,530 @@ +--- +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) + +### 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", of for booelan 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. + +Seq|Field|Description|Required +--:|:--|:--|:-- +1|`title`|The page title|:heavy_check_mark:| +2|`linkTitle`|A short version of the page title|| +3|`description`|A complete sentence describing the page|:heavy_check_mark:| +4|`categories`|An array of terms in the categories taxonomy|:heavy_check_mark: [^1]| +5|`keywords`|An array of keywords used to identify related content|:heavy_check_mark: [^1]| +6|`publishDate`|Applicable to news items: the publication date|| +7|`params.altTitle`|An alternate title: used in the "see also" panel if provided|| +8|`params.functions_and_methods.aliases`|Applicable to function and method pages: an array of alias names|| +9|`params.functions_and_methods.returnType`|Applicable to function and method pages: the data type returned|| +10|`params.functions_and_methods.signatures`|Applicable to function and method pages: an array of signatures|| +11|`params.hide_in_this_section`|Whether to hide the "in this section" panel|| +12|`params.minversion`|Applicable to the quick start page: the minimum Hugo version required|| +13|`params.permalink`|Reserved for use by the news content adapter|| +14|`params.reference (used in glossary term)`|Applicable to glossary entries: a URL for additional information|| +15|`params.show_publish_date`|Whether to show the `publishDate` when rendering the page|| +16|`weight`|The page weight|| +17|`aliases`|Previous URLs used to access this page|| +18|`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] +altTitle = "Whatever you want" +{{< /code-toggle >}} + +Use of the alternate title is limited to the "See also" sidebar. + +> [!note] +> Think carefully before setting the `altTitle`. 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 filename 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 */*/>}} +{{%/*/* foo */*/%}} +``` +```` + +### Site configuration + +Use the [code-toggle shortcode](#code-toggle) to include site configuration examples: + +```text +{{</* code-toggle file=hugo */>}} +baseURL = 'https://example.org/' +languageCode = 'en-US' +title = 'My Site' +{{</* /code-toggle */>}} +``` + +### Front matter + +Use the [code-toggle shortcode](#code-toggle) to include front matter examples: + +```text +{{</* code-toggle file=content/posts/my-first-post.md fm=true */>}} +title = 'My first post' +date = 2023-11-09T12:56:07-08:00 +draft = false +{{</* /code-toggle */>}} +``` + +## 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 +{{</* code-toggle file=hugo copy=true */>}} +baseURL = 'https://example.org/' +languageCode = 'en-US' +title = 'My Site' +{{</* /code-toggle */>}} +``` + +### deprecated-in + +Use the `deprecated-in` shortcode to indicate that a feature is deprecated: + +```text +{{</* deprecated-in 0.144.0 */>}} + +Use [`hugo.IsServer`] instead. + +[`hugo.IsServer`]: /functions/hugo/isserver/ +{{</* /deprecated-in */>}} +``` + +### 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 +{{</* new-in 0.144.0 /*/>}} +``` + +You can also include details: + +```text +{{</* new-in 0.144.0 */>}} +This is a new feature. +{{</* /new-in */>}} +``` + +## New features + +Use the [new-in shortcode](#new-in) to indicate a new feature: + +```text +{{</* new-in 0.144.0 */>}} +``` + +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 +{{</* deprecated-in 0.144.0 */>}} +Use [`hugo.IsServer`] instead. + +[`hugo.IsServer`]: /functions/hugo/isserver/ +{{</* /deprecated-in */>}} +``` + +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 + +Fork the [documentation repository]. + +### Step 2 + +Clone your fork. + +### Step 3 + +Create a new branch with a descriptive name that includes the corresponding issue number, if any: + +```sh +git checkout -b restructure-foo-page-99999 +``` + +### Step 4 + +Make changes. + +### Step 5 + +Build the site locally to preview your changes. + +### Step 6 + +Commit your changes with a descriptive commit message: + +- 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. + +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. + +[ATX]: https://spec.commonmark.org/0.30/#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/0.30/#fenced-code-blocks +[glossary]: /quick-reference/glossary/ +[indented code blocks]: https://spec.commonmark.org/0.30/#indented-code-blocks +[issues]: https://github.com/gohugoio/hugoDocs/issues +[list items]: https://spec.commonmark.org/0.30/#list-items +[project repository]: https://github.com/gohugoio/hugo +[raw HTML]: https://spec.commonmark.org/0.30/#raw-html +[related content]: /content-management/related-content/ +[setext]: https://spec.commonmark.org/0.30/#setext-heading diff --git a/docs/content/en/contribute/themes.md b/docs/content/en/contribute/themes.md new file mode 100644 index 000000000..8a3457ba3 --- /dev/null +++ b/docs/content/en/contribute/themes.md @@ -0,0 +1,25 @@ +--- +title: Themes +description: If you've built a Hugo theme and want to contribute back to the Hugo Community, please share it with us. +categories: [] +keywords: [] +aliases: [/contribute/theme/] +--- + +Visit [themes.gohugo.io] to browse a collection of themes created by the Hugo community. + +To submit your theme: + +1. Read the [submission guidelines] +1. Open a pull request in the [themes repository] + +Other useful theme directories: + +- [jamstack.club] +- [jamstackthemes.dev] + +[jamstack.club]: https://jamstack.club/#ssg=hugo +[jamstackthemes.dev]: https://jamstackthemes.dev/ssg/hugo +[submission guidelines]: https://github.com/gohugoio/hugoThemesSiteBuilder/tree/main#readme +[themes repository]: https://github.com/gohugoio/hugoThemesSiteBuilder +[themes.gohugo.io]: https://themes.gohugo.io/ diff --git a/docs/content/en/documentation.md b/docs/content/en/documentation.md new file mode 100644 index 000000000..6f96c1f9c --- /dev/null +++ b/docs/content/en/documentation.md @@ -0,0 +1,20 @@ +--- +title: Hugo Documentation +linkTitle: Docs +description: Hugo is the world's fastest static website engine. It's written in Go (aka Golang) and developed by bep, spf13 and friends. +layout: list +--- + +<!-- +If we want content on this page at some point, considering taking it from: + +- https://gohugo.io/about/introduction/ +- https://gohugo.io/about/features/ + +Try to use the same language (e.g., tagline) everywhere: + +- Home: https://gohugo.io/ +- Docs: https://gohugo.io/documentation/ +- Project repo: https://github.com/gohugoio/hugo?tab=readme-ov-file#readme +- Docs repo: https://github.com/gohugoio/hugoDocs?tab=readme-ov-file#readme +--> diff --git a/docs/content/en/featured.png b/docs/content/en/featured.png Binary files differnew file mode 100644 index 000000000..09953aed9 --- /dev/null +++ b/docs/content/en/featured.png diff --git a/docs/content/en/functions/_index.md b/docs/content/en/functions/_index.md new file mode 100644 index 000000000..d3081210b --- /dev/null +++ b/docs/content/en/functions/_index.md @@ -0,0 +1,8 @@ +--- +title: Functions +description: Use these functions within your templates and archetypes. +categories: [] +keywords: [] +weight: 10 +aliases: [/layout/functions/,/templates/functions] +--- diff --git a/docs/content/en/functions/cast/ToFloat.md b/docs/content/en/functions/cast/ToFloat.md new file mode 100644 index 000000000..572042937 --- /dev/null +++ b/docs/content/en/functions/cast/ToFloat.md @@ -0,0 +1,46 @@ +--- +title: cast.ToFloat +description: Converts a value to a decimal floating-point number (base 10). +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [float] + returnType: float64 + signatures: [cast.ToFloat INPUT] +aliases: [/functions/float] +--- + +With a decimal (base 10) input: + +```go-html-template +{{ float 11 }} → 11 (float64) +{{ float "11" }} → 11 (float64) + +{{ float 11.1 }} → 11.1 (float64) +{{ float "11.1" }} → 11.1 (float64) + +{{ float 11.9 }} → 11.9 (float64) +{{ float "11.9" }} → 11.9 (float64) +``` + +With a binary (base 2) input: + +```go-html-template +{{ float 0b11 }} → 3 (float64) +``` + +With an octal (base 8) input (use either notation): + +```go-html-template +{{ float 011 }} → 9 (float64) +{{ float "011" }} → 11 (float64) + +{{ float 0o11 }} → 9 (float64) +``` + +With a hexadecimal (base 16) input: + +```go-html-template +{{ float 0x11 }} → 17 (float64) +``` diff --git a/docs/content/en/functions/cast/ToInt.md b/docs/content/en/functions/cast/ToInt.md new file mode 100644 index 000000000..4ede69229 --- /dev/null +++ b/docs/content/en/functions/cast/ToInt.md @@ -0,0 +1,50 @@ +--- +title: cast.ToInt +description: Converts a value to a decimal integer (base 10). +keywords: [] +params: + functions_and_methods: + aliases: [int] + returnType: int + signatures: [cast.ToInt INPUT] +aliases: [/functions/int] +--- + +With a decimal (base 10) input: + +```go-html-template +{{ int 11 }} → 11 (int) +{{ int "11" }} → 11 (int) + +{{ int 11.1 }} → 11 (int) +{{ int 11.9 }} → 11 (int) +``` + +With a binary (base 2) input: + +```go-html-template +{{ int 0b11 }} → 3 (int) +{{ int "0b11" }} → 3 (int) +``` + +With an octal (base 8) input (use either notation): + +```go-html-template +{{ int 011 }} → 9 (int) +{{ int "011" }} → 9 (int) + +{{ int 0o11 }} → 9 (int) +{{ int "0o11" }} → 9 (int) +``` + +With a hexadecimal (base 16) input: + +```go-html-template +{{ int 0x11 }} → 17 (int) +{{ int "0x11" }} → 17 (int) +``` + +> [!note] +> Values with a leading zero are octal (base 8). When casting a string representation of a decimal (base 10) number, remove leading zeros: + +`{{ strings.TrimLeft "0" "0011" | int }} → 11` diff --git a/docs/content/en/functions/cast/ToString.md b/docs/content/en/functions/cast/ToString.md new file mode 100644 index 000000000..1bba001c9 --- /dev/null +++ b/docs/content/en/functions/cast/ToString.md @@ -0,0 +1,49 @@ +--- +title: cast.ToString +description: Converts a value to a string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [string] + returnType: string + signatures: [cast.ToString INPUT] +aliases: [/functions/string] +--- + +With a decimal (base 10) input: + +```go-html-template +{{ string 11 }} → 11 (string) +{{ string "11" }} → 11 (string) + +{{ string 11.1 }} → 11.1 (string) +{{ string "11.1" }} → 11.1 (string) + +{{ string 11.9 }} → 11.9 (string) +{{ string "11.9" }} → 11.9 (string) +``` + +With a binary (base 2) input: + +```go-html-template +{{ string 0b11 }} → 3 (string) +{{ string "0b11" }} → 0b11 (string) +``` + +With an octal (base 8) input (use either notation): + +```go-html-template +{{ string 011 }} → 9 (string) +{{ string "011" }} → 011 (string) + +{{ string 0o11 }} → 9 (string) +{{ string "0o11" }} → 0o11 (string) +``` + +With a hexadecimal (base 16) input: + +```go-html-template +{{ string 0x11 }} → 17 (string) +{{ string "0x11" }} → 0x11 (string) +``` diff --git a/docs/content/en/functions/cast/_index.md b/docs/content/en/functions/cast/_index.md new file mode 100644 index 000000000..1584ab159 --- /dev/null +++ b/docs/content/en/functions/cast/_index.md @@ -0,0 +1,7 @@ +--- +title: Cast functions +linkTitle: cast +description: Use these functions to cast a value from one data type to another. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/collections/After.md b/docs/content/en/functions/collections/After.md new file mode 100644 index 000000000..c8a822846 --- /dev/null +++ b/docs/content/en/functions/collections/After.md @@ -0,0 +1,67 @@ +--- +title: collections.After +description: Slices an array to the items after the Nth item. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [after] + returnType: any + signatures: [collections.After INDEX COLLECTION] +aliases: [/functions/after] +--- + +The following shows `after` being used in conjunction with the [`slice`]function: + +```go-html-template +{{ $data := slice "one" "two" "three" "four" }} +<ul> + {{ range after 2 $data }} + <li>{{ . }}</li> + {{ end }} +</ul> +``` + +The template above is rendered to: + +```html +<ul> + <li>three</li> + <li>four</li> +</ul> +``` + +## Example of `after` with `first`: 2nd–4th most recent articles + +You can use `after` in combination with the [`first`] function and Hugo's [powerful sorting methods](/quick-reference/page-collections/#sort). Let's assume you have a `section` page at `example.com/articles`. You have 10 articles, but you want your template to show only two rows: + +1. The top row is titled "Featured" and shows only the most recently published article (i.e. by `publishdate` in the content files' front matter). +1. The second row is titled "Recent Articles" and shows only the 2nd- to 4th-most recently published articles. + +```go-html-template {file="layouts/section/articles.html"} +{{ define "main" }} + <section class="row featured-article"> + <h2>Featured Article</h2> + {{ range first 1 .Pages.ByPublishDate.Reverse }} + <header> + <h3><a href="{{ .RelPermalink }}">{{ .Title }}</a></h3> + </header> + <p>{{ .Description }}</p> + {{ end }} + </section> + <div class="row recent-articles"> + <h2>Recent Articles</h2> + {{ range first 3 (after 1 .Pages.ByPublishDate.Reverse) }} + <section class="recent-article"> + <header> + <h3><a href="{{ .RelPermalink }}">{{ .Title }}</a></h3> + </header> + <p>{{ .Description }}</p> + </section> + {{ end }} + </div> +{{ end }} +``` + +[`first`]: /functions/collections/first/ +[`slice`]: /functions/collections/slice/ diff --git a/docs/content/en/functions/collections/Append.md b/docs/content/en/functions/collections/Append.md new file mode 100644 index 000000000..cf1d1a3f5 --- /dev/null +++ b/docs/content/en/functions/collections/Append.md @@ -0,0 +1,100 @@ +--- +title: collections.Append +description: Appends one or more elements to a slice and returns the resulting slice. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [append] + returnType: any + signatures: + - collections.Append ELEMENT [ELEMENT...] COLLECTION + - collections.Append COLLECTION1 COLLECTION2 +aliases: [/functions/append] +--- + +This function appends all elements, excluding the last, to the last element. This allows [pipe](g) constructs as shown below. + +Append a single element to a slice: + +```go-html-template +{{ $s := slice "a" "b" }} +{{ $s }} → [a b] + +{{ $s = $s | append "c" }} +{{ $s }} → [a b c] +``` + +Append two elements to a slice: + +```go-html-template +{{ $s := slice "a" "b" }} +{{ $s }} → [a b] + +{{ $s = $s | append "c" "d" }} +{{ $s }} → [a b c d] +``` + +Append two elements, as a slice, to a slice. This produces the same result as the previous example: + +```go-html-template +{{ $s := slice "a" "b" }} +{{ $s }} → [a b] + +{{ $s = $s | append (slice "c" "d") }} +{{ $s }} → [a b c d] +``` + +Start with an empty slice: + +```go-html-template +{{ $s := slice }} +{{ $s }} → [] + +{{ $s = $s | append "a" }} +{{ $s }} → [a] + +{{ $s = $s | append "b" "c" }} +{{ $s }} → [a b c] + +{{ $s = $s | append (slice "d" "e") }} +{{ $s }} → [a b c d e] +``` + +If you start with a slice of a slice: + +```go-html-template +{{ $s := slice (slice "a" "b") }} +{{ $s }} → [[a b]] + +{{ $s = $s | append (slice "c" "d") }} +{{ $s }} → [[a b] [c d]] +``` + +To create a slice of slices, starting with an empty slice: + +```go-html-template +{{ $s := slice }} +{{ $s }} → [] + +{{ $s = $s | append (slice (slice "a" "b")) }} +{{ $s }} → [[a b]] + +{{ $s = $s | append (slice "c" "d") }} +{{ $s }} → [[a b] [c d]] +``` + +Although the elements in the examples above are strings, you can use the `append` function with any data type, including Pages. For example, on the home page of a corporate site, to display links to the two most recent press releases followed by links to the four most recent articles: + +```go-html-template +{{ $p := where site.RegularPages "Type" "press-releases" | first 2 }} +{{ $p = $p | append (where site.RegularPages "Type" "articles" | first 4) }} + +{{ with $p }} + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/functions/collections/Apply.md b/docs/content/en/functions/collections/Apply.md new file mode 100644 index 000000000..7ffe49053 --- /dev/null +++ b/docs/content/en/functions/collections/Apply.md @@ -0,0 +1,26 @@ +--- +title: collections.Apply +description: Returns a new collection with each element transformed by the given function. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [apply] + returnType: '[]any' + signatures: [collections.Apply COLLECTION FUNCTION PARAM...] +aliases: [/functions/apply] +--- + +The `apply` function takes three or more arguments, depending on the function being applied to the collection elements. + +The first argument is the collection itself, the second argument is the function name, and the remaining arguments are passed to the function, with the string `"."` representing the collection element. + +```go-html-template +{{ $s := slice "hello" "world" }} + +{{ $s = apply $s "strings.FirstUpper" "." }} +{{ $s }} → [Hello World] + +{{ $s = apply $s "strings.Replace" "." "l" "_" }} +{{ $s }} → [He__o Wor_d] +``` diff --git a/docs/content/en/functions/collections/Complement.md b/docs/content/en/functions/collections/Complement.md new file mode 100644 index 000000000..ce810dc00 --- /dev/null +++ b/docs/content/en/functions/collections/Complement.md @@ -0,0 +1,73 @@ +--- +title: collections.Complement +description: Returns the elements of the last collection that are not in any of the others. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [complement] + returnType: any + signatures: ['collections.Complement COLLECTION [COLLECTION...]'] +aliases: [/functions/complement] +--- + +To find the elements within `$c3` that do not exist in `$c1` or `$c2`: + +```go-html-template +{{ $c1 := slice 3 }} +{{ $c2 := slice 4 5 }} +{{ $c3 := slice 1 2 3 4 5 }} + +{{ complement $c1 $c2 $c3 }} → [1 2] +``` + +> [!note] +> Make your code simpler to understand by using a [chained pipeline]: + +```go-html-template +{{ $c3 | complement $c1 $c2 }} → [1 2] +``` + +You can also use the `complement` function with page collections. Let's say your site has five content types: + +```text +content/ +├── blog/ +├── books/ +├── faqs/ +├── films/ +└── songs/ +``` + +To list everything except blog articles (`blog`) and frequently asked questions (`faqs`): + +```go-html-template +{{ $blog := where site.RegularPages "Type" "blog" }} +{{ $faqs := where site.RegularPages "Type" "faqs" }} +{{ range site.RegularPages | complement $blog $faqs }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +{{ end }} +``` + +> [!note] +> Although the example above demonstrates the `complement` function, you could use the [`where`] function as well: + +```go-html-template +{{ range where site.RegularPages "Type" "not in" (slice "blog" "faqs") }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +{{ end }} +``` + +In this example we use the `complement` function to remove [stop words] from a sentence: + +```go-html-template +{{ $text := "The quick brown fox jumps over the lazy dog" }} +{{ $stopWords := slice "a" "an" "in" "over" "the" "under" }} +{{ $filtered := split $text " " | complement $stopWords }} + +{{ delimit $filtered " " }} → The quick brown fox jumps lazy dog +``` + +[`where`]: /functions/collections/where/ +[chained pipeline]: https://pkg.go.dev/text/template#hdr-Pipelines +[stop words]: https://en.wikipedia.org/wiki/Stop_word diff --git a/docs/content/en/functions/collections/Delimit.md b/docs/content/en/functions/collections/Delimit.md new file mode 100644 index 000000000..9d09620aa --- /dev/null +++ b/docs/content/en/functions/collections/Delimit.md @@ -0,0 +1,31 @@ +--- +title: collections.Delimit +description: Loops through any array, slice, or map and returns a string of all the values separated by a delimiter. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [delimit] + returnType: string + signatures: ['collections.Delimit COLLECTION DELIMITER [LAST]'] +aliases: [/functions/delimit] +--- + +Delimit a slice: + +```go-html-template +{{ $s := slice "b" "a" "c" }} +{{ delimit $s ", " }} → b, a, c +{{ delimit $s ", " " and "}} → b, a and c +``` + +Delimit a map: + +> [!note] +> The `delimit` function sorts maps by key, returning the values. + +```go-html-template +{{ $m := dict "b" 2 "a" 1 "c" 3 }} +{{ delimit $m ", " }} → 1, 2, 3 +{{ delimit $m ", " " and "}} → 1, 2 and 3 +``` diff --git a/docs/content/en/functions/collections/Dictionary.md b/docs/content/en/functions/collections/Dictionary.md new file mode 100644 index 000000000..8aa428106 --- /dev/null +++ b/docs/content/en/functions/collections/Dictionary.md @@ -0,0 +1,51 @@ +--- +title: collections.Dictionary +description: Returns a map composed of the given key-value pairs. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [dict] + returnType: map[string]any + signatures: ['collections.Dictionary [VALUE...]'] +aliases: [/functions/dict] +--- + +Specify the key-value pairs as individual arguments: + +```go-html-template +{{ $m := dict "a" 1 "b" 2 }} +``` + +The above produces this data structure: + +```json +{ + "a": 1, + "b": 2 +} +``` + +To create an empty map: + +```go-html-template +{{ $m := dict }} +``` + +Note that the `key` can be either a `string` or a `[]string`. The latter is useful to create a deeply nested structure, e.g.: + +```go-html-template +{{ $m := dict (slice "a" "b" "c") "value" }} +``` + +The above produces this data structure: + +```json +{ + "a": { + "b": { + "c": "value" + } + } +} +``` diff --git a/docs/content/en/functions/collections/First.md b/docs/content/en/functions/collections/First.md new file mode 100644 index 000000000..9a672278d --- /dev/null +++ b/docs/content/en/functions/collections/First.md @@ -0,0 +1,34 @@ +--- +title: collections.First +description: Returns the given collection, limited to the first N elements. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [first] + returnType: any + signatures: [collections.First N COLLECTION] +aliases: [/functions/first] +--- + +```go-html-template +{{ range first 5 .Pages }} + {{ .Render "summary" }} +{{ end }} +``` + +Set `N` to zero to return an empty collection. + +```go-html-template +{{ $emptyPageCollection := first 0 .Pages }} +``` + +Use `first` and [`where`] together. + +```go-html-template +{{ range where .Pages "Section" "articles" | first 5 }} + {{ .Render "summary" }} +{{ end }} +``` + +[`where`]: /functions/collections/where/ diff --git a/docs/content/en/functions/collections/Group.md b/docs/content/en/functions/collections/Group.md new file mode 100644 index 000000000..4b269b92a --- /dev/null +++ b/docs/content/en/functions/collections/Group.md @@ -0,0 +1,31 @@ +--- +title: collections.Group +description: Groups the given page collection by the given key. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [group] + returnType: any + signatures: [collections.Group KEY PAGES] +aliases: [/functions/group] +--- + +```go-html-template +{{ $new := .Site.RegularPages | first 10 | group "New" }} +{{ $old := .Site.RegularPages | last 10 | group "Old" }} +{{ $groups := slice $new $old }} +{{ range $groups }} + <h3>{{ .Key }}{{/* Prints "New", "Old" */}}</h3> + <ul> + {{ range .Pages }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + <div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div> + </li> + {{ end }} + </ul> +{{ end }} +``` + +The page group you get from `group` is of the same type you get from the built-in [group methods](/quick-reference/page-collections/#group) in Hugo. The example above can be [paginated](/templates/pagination/). diff --git a/docs/content/en/functions/collections/In.md b/docs/content/en/functions/collections/In.md new file mode 100644 index 000000000..e94b4b0ed --- /dev/null +++ b/docs/content/en/functions/collections/In.md @@ -0,0 +1,34 @@ +--- +title: collections.In +description: Reports whether the given value is a member of the given set. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [in] + returnType: bool + signatures: [collections.In SET VALUE] +aliases: [/functions/in] +--- + +The `SET` can be an [array](g), [slice](g), or [string](g). + +```go-html-template +{{ $s := slice "a" "b" "c" }} +{{ in $s "b" }} → true +``` + +```go-html-template +{{ $s := slice 1 2 3 }} +{{ in $s 2 }} → true +``` + +```go-html-template +{{ $s := slice 1.11 2.22 3.33 }} +{{ in $s 2.22 }} → true +``` + +```go-html-template +{{ $s := "abc" }} +{{ in $s "b" }} → true +``` diff --git a/docs/content/en/functions/collections/IndexFunction.md b/docs/content/en/functions/collections/IndexFunction.md new file mode 100644 index 000000000..248595961 --- /dev/null +++ b/docs/content/en/functions/collections/IndexFunction.md @@ -0,0 +1,50 @@ +--- +title: collections.Index +description: Returns the object, element, or value associated with the given key or keys. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [index] + returnType: any + signatures: [collections.Index COLLECTION KEY...] +aliases: [/functions/index,/functions/index-function] +--- + +Each indexed item must be a map or a slice: + +```go-html-template +{{ $s := slice "a" "b" "c" }} +{{ index $s 0 }} → a +{{ index $s 1 }} → b + +{{ $m := dict "a" 100 "b" 200 }} +{{ index $m "b" }} → 200 +``` + +Use two or more keys to access a nested value: + +```go-html-template +{{ $m := dict "a" 100 "b" 200 "c" (slice 10 20 30) }} +{{ index $m "c" 1 }} → 20 + +{{ $m := dict "a" 100 "b" 200 "c" (dict "d" 10 "e" 20) }} +{{ index $m "c" "e" }} → 20 +``` + +You may also use a slice of keys to access a nested value: + +```go-html-template +{{ $m := dict "a" 100 "b" 200 "c" (dict "d" 10 "e" 20) }} +{{ $s := slice "c" "e" }} +{{ index $m $s }} → 20 +``` + +Use the `collections.Index` function to access a nested value when the key is variable. For example, these are equivalent: + +```go-html-template +{{ .Site.Params.foo }} + +{{ $k := "foo" }} +{{ index .Site.Params $k }} +``` diff --git a/docs/content/en/functions/collections/Intersect.md b/docs/content/en/functions/collections/Intersect.md new file mode 100644 index 000000000..ffa9c8196 --- /dev/null +++ b/docs/content/en/functions/collections/Intersect.md @@ -0,0 +1,24 @@ +--- +title: collections.Intersect +description: Returns the common elements of two arrays or slices, in the same order as the first array. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [intersect] + returnType: any + signatures: [collections.Intersect SET1 SET2] +aliases: [/functions/intersect] +--- + +A useful example is to use it as `AND` filters when combined with where: + +```go-html-template +{{ $pages := where .Site.RegularPages "Type" "not in" (slice "page" "about") }} +{{ $pages := $pages | union (where .Site.RegularPages "Params.pinned" true) }} +{{ $pages := $pages | intersect (where .Site.RegularPages "Params.images" "!=" nil) }} +``` + +The above fetches regular pages not of `page` or `about` type unless they are pinned. And finally, we exclude all pages with no `images` set in Page parameters. + +See [union](/functions/collections/union) for `OR`. diff --git a/docs/content/en/functions/collections/IsSet.md b/docs/content/en/functions/collections/IsSet.md new file mode 100644 index 000000000..5457df5d4 --- /dev/null +++ b/docs/content/en/functions/collections/IsSet.md @@ -0,0 +1,42 @@ +--- +title: collections.IsSet +description: Reports whether the key exists within the collection. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [isset] + returnType: bool + signatures: [collections.IsSet COLLECTION KEY] +aliases: [/functions/isset] +--- + +For example, consider this site configuration: + +{{< code-toggle file=hugo >}} +[params] +showHeroImage = false +{{< /code-toggle >}} + +It the value of `showHeroImage` is `true`, we can detect that it exists using either `if` or `with`: + +```go-html-template +{{ if site.Params.showHeroImage }} + {{ site.Params.showHeroImage }} → true +{{ end }} + +{{ with site.Params.showHeroImage }} + {{ . }} → true +{{ end }} +``` + +But if the value of `showHeroImage` is `false`, we can't use either `if` or `with` to detect its existence. In this case, you must use the `isset` function: + +```go-html-template +{{ if isset site.Params "showheroimage" }} + <p>The showHeroImage parameter is set to {{ site.Params.showHeroImage }}.<p> +{{ end }} +``` + +> [!note] +> When using the `isset` function you must reference the key using lower case. See the previous example. diff --git a/docs/content/en/functions/collections/KeyVals.md b/docs/content/en/functions/collections/KeyVals.md new file mode 100644 index 000000000..bd58caea0 --- /dev/null +++ b/docs/content/en/functions/collections/KeyVals.md @@ -0,0 +1,42 @@ +--- +title: collections.KeyVals +description: Returns a KeyVals struct. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [keyVals] + returnType: types.KeyValues + signatures: [collections.KeyVals KEY VALUE...] +aliases: [/functions/keyvals] +--- + +The primary application for this function is the definition of the `namedSlices` value in the options map passed to the [`Related`] method on the `Pages` object. + +[`Related`]: /methods/pages/related/ + +See [related content](/content-management/related-content/). + +```go-html-template +{{ $kv := keyVals "foo" "a" "b" "c" }} +``` + +The resulting data structure is: + +```json +{ + "Key": "foo", + "Values": [ + "a", + "b", + "c" + ] +} +``` + +To extract the key and values: + +```go-html-template +{{ $kv.Key }} → foo +{{ $kv.Values }} → [a b c] +``` diff --git a/docs/content/en/functions/collections/Last.md b/docs/content/en/functions/collections/Last.md new file mode 100644 index 000000000..f0cfff219 --- /dev/null +++ b/docs/content/en/functions/collections/Last.md @@ -0,0 +1,34 @@ +--- +title: collections.Last +description: Returns the given collection, limited to the last N elements. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [last] + returnType: any + signatures: [collections.Last N COLLECTION] +aliases: [/functions/last] +--- + +```go-html-template +{{ range last 10 .Pages }} + {{ .Render "summary" }} +{{ end }} +``` + +Set `N` to zero to return an empty collection. + +```go-html-template +{{ $emptyPageCollection := last 0 .Pages }} +``` + +Use `last` and [`where`] together. + +[`where`]: /functions/collections/where/ + +```go-html-template +{{ range where .Pages "Section" "articles" | last 5 }} + {{ .Render "summary" }} +{{ end }} +``` diff --git a/docs/content/en/functions/collections/Merge.md b/docs/content/en/functions/collections/Merge.md new file mode 100644 index 000000000..c9998be39 --- /dev/null +++ b/docs/content/en/functions/collections/Merge.md @@ -0,0 +1,67 @@ +--- +title: collections.Merge +description: Returns the result of merging two or more maps. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [merge] + returnType: any + signatures: [collections.Merge MAP MAP...] +aliases: [/functions/merge] +--- + +Returns the result of merging two or more maps from left to right. If a key already exists, `merge` updates its value. If a key is absent, `merge` inserts the value under the new key. + +Key handling is case-insensitive. + +The following examples use these map definitions: + +```go-html-template +{{ $m1 := dict "x" "foo" }} +{{ $m2 := dict "x" "bar" "y" "wibble" }} +{{ $m3 := dict "x" "baz" "y" "wobble" "z" (dict "a" "huey") }} +``` + +Example 1 + +```go-html-template +{{ $merged := merge $m1 $m2 $m3 }} + +{{ $merged.x }} → baz +{{ $merged.y }} → wobble +{{ $merged.z.a }} → huey +``` + +Example 2 + +```go-html-template +{{ $merged := merge $m3 $m2 $m1 }} + +{{ $merged.x }} → foo +{{ $merged.y }} → wibble +{{ $merged.z.a }} → huey +``` + +Example 3 + +```go-html-template +{{ $merged := merge $m2 $m3 $m1 }} + +{{ $merged.x }} → foo +{{ $merged.y }} → wobble +{{ $merged.z.a }} → huey +``` + +Example 4 + +```go-html-template +{{ $merged := merge $m1 $m3 $m2 }} + +{{ $merged.x }} → bar +{{ $merged.y }} → wibble +{{ $merged.z.a }} → huey +``` + +> [!note] +> Regardless of depth, merging only applies to maps. For slices, use [append](/functions/collections/append). diff --git a/docs/content/en/functions/collections/NewScratch.md b/docs/content/en/functions/collections/NewScratch.md new file mode 100644 index 000000000..34fc7f5d6 --- /dev/null +++ b/docs/content/en/functions/collections/NewScratch.md @@ -0,0 +1,119 @@ +--- +title: collections.NewScratch +description: Returns a locally scoped "scratch pad" to store and manipulate data. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [newScratch] + returnType: maps.Scratch + signatures: [collections.NewScratch ] +--- + +Use the `collections.NewScratch` function to create a locally 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 +{{ $s := newScratch }} +{{ $s.Set "greeting" "Hello" }} +``` + +### Get + +Gets the value of the given key. + +```go-html-template +{{ $s := newScratch }} +{{ $s.Set "greeting" "Hello" }} +{{ $s.Get "greeting" }} → Hello +``` + +### Add + +Adds the 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 +{{ $s := newScratch }} +{{ $s.Set "greeting" "Hello" }} +{{ $s.Add "greeting" "Welcome" }} +{{ $s.Get "greeting" }} → HelloWelcome +``` + +```go-html-template +{{ $s := newScratch }} +{{ $s.Set "total" 3 }} +{{ $s.Add "total" 7 }} +{{ $s.Get "total" }} → 10 +``` + +```go-html-template +{{ $s := newScratch }} +{{ $s.Set "greetings" (slice "Hello") }} +{{ $s.Add "greetings" (slice "Welcome" "Cheers") }} +{{ $s.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 +{{ $s := newScratch }} +{{ $s.SetInMap "greetings" "english" "Hello" }} +{{ $s.SetInMap "greetings" "french" "Bonjour" }} +{{ $s.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 +{{ $s := newScratch }} +{{ $s.SetInMap "greetings" "english" "Hello" }} +{{ $s.SetInMap "greetings" "french" "Bonjour" }} +{{ $s.DeleteInMap "greetings" "english" }} +{{ $s.Get "greetings" }} → map[french:Bonjour] +``` + +### GetSortedMapValues + +Returns an array of values from `key` sorted by `mapKey`. + +```go-html-template +{{ $s := newScratch }} +{{ $s.SetInMap "greetings" "english" "Hello" }} +{{ $s.SetInMap "greetings" "french" "Bonjour" }} +{{ $s.GetSortedMapValues "greetings" }} → [Hello Bonjour] +``` + +### Delete + +Removes the given key. + +```go-html-template +{{ $s := newScratch }} +{{ $s.Set "greeting" "Hello" }} +{{ $s.Delete "greeting" }} +``` + +### Values + +Returns the raw backing map. Do not use with `Store` methods on a `Page` object due to concurrency issues. + +```go-html-template +{{ $s := newScratch }} +{{ $s.SetInMap "greetings" "english" "Hello" }} +{{ $s.SetInMap "greetings" "french" "Bonjour" }} + +{{ $map := $s.Values }} +``` + +{{% include "_common/scratch-pad-scope.md" %}} diff --git a/docs/content/en/functions/collections/Querify.md b/docs/content/en/functions/collections/Querify.md new file mode 100644 index 000000000..fd74935b7 --- /dev/null +++ b/docs/content/en/functions/collections/Querify.md @@ -0,0 +1,48 @@ +--- +title: collections.Querify +description: Returns a URL query string composed of the given key-value pairs, encoded and sorted by key. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [querify] + returnType: string + signatures: ['collections.Querify [VALUE...]'] +aliases: [/functions/querify] +--- + +Specify the key-value pairs as a map, a slice, or a sequence of scalar values. For example, the following are equivalent: + +```go-html-template +{{ collections.Querify (dict "a" 1 "b" 2) }} +{{ collections.Querify (slice "a" 1 "b" 2) }} +{{ collections.Querify "a" 1 "b" 2 }} +``` + +To append a query string to a URL: + +```go-html-template +{{ $qs := collections.Querify (dict "a" 1 "b" 2) }} +{{ $href := printf "https://example.org?%s" $qs }} + +<a href="{{ $href }}">Link</a> +``` + +Hugo renders this to: + +```html +<a href="https://example.org?a=1&b=2">Link</a> +``` + +You can also pass in a map from your site configuration or front matter. For example: + +{{< code-toggle file=content/example.md fm=true >}} +title = 'Example' +[params.query] +a = 1 +b = 2 +{{< /code-toggle >}} + +```go-html-template +{{ collections.Querify .Params.query }} +``` diff --git a/docs/content/en/functions/collections/Reverse.md b/docs/content/en/functions/collections/Reverse.md new file mode 100644 index 000000000..ee455939c --- /dev/null +++ b/docs/content/en/functions/collections/Reverse.md @@ -0,0 +1,16 @@ +--- +title: collections.Reverse +description: Reverses the order of a collection. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: any + signatures: [collections.Reverse COLLECTION] +aliases: [/functions/collections.reverse] +--- + +```go-html-template +{{ slice 2 1 3 | collections.Reverse }} → [3 1 2] +``` diff --git a/docs/content/en/functions/collections/Seq.md b/docs/content/en/functions/collections/Seq.md new file mode 100644 index 000000000..e396f07e3 --- /dev/null +++ b/docs/content/en/functions/collections/Seq.md @@ -0,0 +1,35 @@ +--- +title: collections.Seq +description: Returns a slice of integers. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [seq] + returnType: '[]int' + signatures: + - collections.Seq LAST + - collections.Seq FIRST LAST + - collections.Seq FIRST INCREMENT LAST +aliases: [/functions/seq] +--- + +```go-html-template +{{ seq 2 }} → [1 2] +{{ seq 0 2 }} → [0 1 2] +{{ seq -2 2 }} → [-2 -1 0 1 2] +{{ seq -2 2 2 }} → [-2 0 2] +``` + +A contrived example of iterating over a sequence of integers: + +```go-html-template +{{ $product := 1 }} +{{ range seq 4 }} + {{ $product = mul $product . }} +{{ end }} +{{ $product }} → 24 +``` + +> [!note] +> The slice created by the `seq` function is limited to 2000 elements. diff --git a/docs/content/en/functions/collections/Shuffle.md b/docs/content/en/functions/collections/Shuffle.md new file mode 100644 index 000000000..3a27c099a --- /dev/null +++ b/docs/content/en/functions/collections/Shuffle.md @@ -0,0 +1,19 @@ +--- +title: collections.Shuffle +description: Returns a random permutation of a given array or slice. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [shuffle] + returnType: any + signatures: [collections.Shuffle COLLECTION] +aliases: [/functions/shuffle] +--- + +```go-html-template +{{ shuffle (seq 1 2 3) }} → [3 1 2] +{{ shuffle (slice "a" "b" "c") }} → [b a c] +``` + +The result will vary from one build to the next. diff --git a/docs/content/en/functions/collections/Slice.md b/docs/content/en/functions/collections/Slice.md new file mode 100644 index 000000000..76180fabe --- /dev/null +++ b/docs/content/en/functions/collections/Slice.md @@ -0,0 +1,23 @@ +--- +title: collections.Slice +description: Returns a slice composed of the given values. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [slice] + returnType: any + signatures: ['collections.Slice [VALUE...]'] +aliases: [/functions/slice] +--- + +```go-html-template +{{ $s := slice "a" "b" "c" }} +{{ $s }} → [a b c] +``` + +To create an empty slice: + +```go-html-template +{{ $s := slice }} +``` diff --git a/docs/content/en/functions/collections/Sort.md b/docs/content/en/functions/collections/Sort.md new file mode 100644 index 000000000..67e5de5cb --- /dev/null +++ b/docs/content/en/functions/collections/Sort.md @@ -0,0 +1,150 @@ +--- +title: collections.Sort +description: Sorts slices, maps, and page collections. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [sort] + returnType: any + signatures: ['collections.Sort COLLECTION [KEY] [ORDER]'] +aliases: [/functions/sort] +--- + +The `KEY` is optional when sorting slices in ascending order, otherwise it is required. When sorting slices, use the literal `value` in place of the `KEY`. See examples below. + +The `ORDER` may be either `asc` (ascending) or `desc` (descending). The default sort order is ascending. + +## Sort a slice + +The examples below assume this site configuration: + +{{< code-toggle file=hugo >}} +[params] +grades = ['b','a','c'] +{{< /code-toggle >}} + +### Ascending order {#slice-ascending-order} + +Sort slice elements in ascending order using either of these constructs: + +```go-html-template +{{ sort site.Params.grades }} → [a b c] +{{ sort site.Params.grades "value" "asc" }} → [a b c] +``` + +In the examples above, `value` is the `KEY` representing the value of the slice element. + +### Descending order {#slice-descending-order} + +Sort slice elements in descending order: + +```go-html-template +{{ sort site.Params.grades "value" "desc" }} → [c b a] +``` + +In the example above, `value` is the `KEY` representing the value of the slice element. + +## Sort a map + +The examples below assume this site configuration: + +{{< code-toggle file=hugo >}} +[params.authors.a] +firstName = "Marius" +lastName = "Pontmercy" +[params.authors.b] +firstName = "Victor" +lastName = "Hugo" +[params.authors.c] +firstName = "Jean" +lastName = "Valjean" +{{< /code-toggle >}} + +> [!note] +> When sorting maps, the `KEY` argument must be lowercase. + +### Ascending order {#map-ascending-order} + +Sort map objects in ascending order using either of these constructs: + +```go-html-template +{{ range sort site.Params.authors "firstname" }} + {{ .firstName }} +{{ end }} + +{{ range sort site.Params.authors "firstname" "asc" }} + {{ .firstName }} +{{ end }} +``` + +These produce: + +```text +Jean Marius Victor +``` + +### Descending order {#map-descending-order} + +Sort map objects in descending order: + +```go-html-template +{{ range sort site.Params.authors "firstname" "desc" }} + {{ .firstName }} +{{ end }} +``` + +This produces: + +```text +Victor Marius Jean +``` + +### First level key removal + +Hugo removes the first level keys when sorting a map. + +Original map: + +```json +{ + "felix": { + "breed": "malicious", + "type": "cat" + }, + "spot": { + "breed": "boxer", + "type": "dog" + } +} +``` + +After sorting: + +```json +[ + { + "breed": "malicious", + "type": "cat" + }, + { + "breed": "boxer", + "type": "dog" + } +] +``` + +## Sort a page collection + +> [!note] +> Although you can use the `sort` function to sort a page collection, Hugo provides [sorting and grouping methods] as well. + +In this contrived example, sort the site's regular pages by `.Type` in descending order: + +```go-html-template +{{ range sort site.RegularPages "Type" "desc" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +[sorting and grouping methods]: /methods/pages/ diff --git a/docs/content/en/functions/collections/SymDiff.md b/docs/content/en/functions/collections/SymDiff.md new file mode 100644 index 000000000..8974d2d3e --- /dev/null +++ b/docs/content/en/functions/collections/SymDiff.md @@ -0,0 +1,20 @@ +--- +title: collections.SymDiff +description: Returns the symmetric difference of two collections. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [symdiff] + returnType: any + signatures: [COLLECTION | collections.SymDiff COLLECTION] +aliases: [/functions/symdiff] +--- + +Example: + +```go-html-template +{{ slice 1 2 3 | symdiff (slice 3 4) }} → [1 2 4] +``` + +Also see <https://en.wikipedia.org/wiki/Symmetric_difference>. diff --git a/docs/content/en/functions/collections/Union.md b/docs/content/en/functions/collections/Union.md new file mode 100644 index 000000000..ce6d6d010 --- /dev/null +++ b/docs/content/en/functions/collections/Union.md @@ -0,0 +1,38 @@ +--- +title: collections.Union +description: Given two arrays or slices, returns a new array that contains the elements that belong to either or both arrays/slices. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [union] + returnType: any + signatures: [collections.Union SET1 SET2] +aliases: [/functions/union] +--- + +Given two arrays (or slices) A and B, this function will return a new array that contains the elements or objects that belong to either A or to B or to both. + +```go-html-template +{{ union (slice 1 2 3) (slice 3 4 5) }} → [1 2 3 4 5] + +{{ union (slice 1 2 3) nil }} → [1 2 3] + +{{ union nil (slice 1 2 3) }} → [1 2 3] + +{{ union nil nil }} → [] +``` + +## OR filter in where query + +This is also very useful to use as `OR` filters when combined with where: + +```go-html-template +{{ $pages := where .Site.RegularPages "Type" "not in" (slice "page" "about") }} +{{ $pages = $pages | union (where .Site.RegularPages "Params.pinned" true) }} +{{ $pages = $pages | intersect (where .Site.RegularPages "Params.images" "!=" nil) }} +``` + +The above fetches regular pages not of `page` or `about` type unless they are pinned. And finally, we exclude all pages with no `images` set in Page parameters. + +See [intersect](/functions/collections/intersect) for `AND`. diff --git a/docs/content/en/functions/collections/Uniq.md b/docs/content/en/functions/collections/Uniq.md new file mode 100644 index 000000000..d19298b21 --- /dev/null +++ b/docs/content/en/functions/collections/Uniq.md @@ -0,0 +1,16 @@ +--- +title: collections.Uniq +description: Returns the given collection, removing duplicate elements. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [uniq] + returnType: any + signatures: [collections.Uniq COLLECTION] +aliases: [/functions/uniq] +--- + +```go-html-template +{{ slice 1 3 2 1 | uniq }} → [1 3 2] +``` diff --git a/docs/content/en/functions/collections/Where.md b/docs/content/en/functions/collections/Where.md new file mode 100644 index 000000000..1df84afc4 --- /dev/null +++ b/docs/content/en/functions/collections/Where.md @@ -0,0 +1,422 @@ +--- +title: collections.Where +description: Returns the given collection, removing elements that do not satisfy the comparison condition. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [where] + returnType: any + signatures: ['collections.Where COLLECTION KEY [OPERATOR] VALUE'] +aliases: [/functions/where] +--- + +The `where` function returns the given collection, removing elements that do not satisfy the comparison condition. The comparison condition is composed of the `KEY`, `OPERATOR`, and `VALUE` arguments: + +```text +collections.Where COLLECTION KEY [OPERATOR] VALUE + -------------------- + comparison condition +``` + +Hugo will test for equality if you do not provide an `OPERATOR` argument. For example: + +```go-html-template +{{ $pages := where .Site.RegularPages "Section" "books" }} +{{ $books := where .Site.Data.books "genres" "suspense" }} +``` + +## Arguments + +The where function takes three or four arguments. The `OPERATOR` argument is optional. + +COLLECTION +: (`any`) A [page collection](g) or a [slice](g) of [maps](g). + +KEY +: (`string`) The key of the page or map value to compare with `VALUE`. With page collections, commonly used comparison keys are `Section`, `Type`, and `Params`. To compare with a member of the page `Params` map, [chain](g) the subkey as shown below: + +```go-html-template +{{ $result := where .Site.RegularPages "Params.foo" "bar" }} +``` + +OPERATOR +: (`string`) The logical comparison [operator](#operators). + +VALUE +: (`any`) The value with which to compare. The values to compare must have comparable data types. For example: + +Comparison|Result +:--|:-- +`"123" "eq" "123"`|`true` +`"123" "eq" 123`|`false` +`false "eq" "false"`|`false` +`false "eq" false`|`true` + +When one or both of the values to compare is a slice, use the `in`, `not in`, or `intersect` operators as described below. + +## Operators + +Use any of the following logical operators: + +`=`, `==`, `eq` +: (`bool`) Reports whether the given field value is equal to `VALUE`. + +`!=`, `<>`, `ne` +: (`bool`) Reports whether the given field value is not equal to `VALUE`. + +`>=`, `ge` +: (`bool`) Reports whether the given field value is greater than or equal to `VALUE`. + +`>`, `gt` +: `true` Reports whether the given field value is greater than `VALUE`. + +`<=`, `le` +: (`bool`) Reports whether the given field value is less than or equal to `VALUE`. + +`<`, `lt` +: (`bool`) Reports whether the given field value is less than `VALUE`. + +`in` +: (`bool`) Reports whether the given field value is a member of `VALUE`. Compare string to slice, or string to string. See [details](/functions/collections/in). + +`not in` +: (`bool`) Reports whether the given field value is not a member of `VALUE`. Compare string to slice, or string to string. See [details](/functions/collections/in). + +`intersect` +: (`bool`) Reports whether the given field value (a slice) contains one or more elements in common with `VALUE`. See [details](/functions/collections/intersect). + +`like` +: {{< new-in 0.116.0 />}} +: (`bool`) Reports whether the given field value matches the [regular expression](g) specified in `VALUE`. Use the `like` operator to compare `string` values. The `like` operator returns `false` when comparing other data types to the regular expression. + +> [!note] +> The examples below perform comparisons within a page collection, but the same comparisons are applicable to a slice of maps. + +## String comparison + +Compare the value of the given field to a [`string`](g): + +```go-html-template +{{ $pages := where .Site.RegularPages "Section" "eq" "books" }} +{{ $pages := where .Site.RegularPages "Section" "ne" "books" }} +``` + +## Numeric comparison + +Compare the value of the given field to an [`int`](g) or [`float`](g): + +```go-html-template +{{ $books := where site.RegularPages "Section" "eq" "books" }} + +{{ $pages := where $books "Params.price" "eq" 42 }} +{{ $pages := where $books "Params.price" "ne" 42.67 }} +{{ $pages := where $books "Params.price" "ge" 42 }} +{{ $pages := where $books "Params.price" "gt" 42.67 }} +{{ $pages := where $books "Params.price" "le" 42 }} +{{ $pages := where $books "Params.price" "lt" 42.67 }} +``` + +## Boolean comparison + +Compare the value of the given field to a [`bool`](g): + +```go-html-template +{{ $books := where site.RegularPages "Section" "eq" "books" }} + +{{ $pages := where $books "Params.fiction" "eq" true }} +{{ $pages := where $books "Params.fiction" "eq" false }} +{{ $pages := where $books "Params.fiction" "ne" true }} +{{ $pages := where $books "Params.fiction" "ne" false }} +``` + +## Member comparison + +Compare a [`scalar`](g) to a [`slice`](g). + +For example, to return a collection of pages where the `color` page parameter is either "red" or "yellow": + +```go-html-template +{{ $fruit := where site.RegularPages "Section" "eq" "fruit" }} + +{{ $colors := slice "red" "yellow" }} +{{ $pages := where $fruit "Params.color" "in" $colors }} +``` + +To return a collection of pages where the "color" page parameter is neither "red" nor "yellow": + +```go-html-template +{{ $fruit := where site.RegularPages "Section" "eq" "fruit" }} + +{{ $colors := slice "red" "yellow" }} +{{ $pages := where $fruit "Params.color" "not in" $colors }} +``` + +## Intersection comparison + +Compare a `slice` to a `slice`, returning collection elements with common values. This is frequently used when comparing taxonomy terms. + +For example, to return a collection of pages where any of the terms in the "genres" taxonomy are "suspense" or "romance": + +```go-html-template +{{ $books := where site.RegularPages "Section" "eq" "books" }} + +{{ $genres := slice "suspense" "romance" }} +{{ $pages := where $books "Params.genres" "intersect" $genres }} +``` + +## Regular expression comparison + +{{< new-in 0.116.0 />}} + +To return a collection of pages where the "author" page parameter begins with either "victor" or "Victor": + +```go-html-template +{{ $pages := where .Site.RegularPages "Params.author" "like" `(?i)^victor` }} +``` + +{{% include "/_common/functions/regular-expressions.md" %}} + +> [!note] +> Use the `like` operator to compare string values. Comparing other data types will result in an empty collection. + +## Date comparison + +### Predefined dates + +There are four predefined front matter dates: [`date`], [`publishDate`], [`lastmod`], and [`expiryDate`]. Regardless of the front matter data format (TOML, YAML, or JSON) these are [`time.Time`] values, allowing precise comparisons. + +For example, to return a collection of pages that were created before the current year: + +```go-html-template +{{ $startOfYear := time.AsTime (printf "%d-01-01" now.Year) }} +{{ $pages := where .Site.RegularPages "Date" "lt" $startOfYear }} +``` + +### Custom dates + +With custom front matter dates, the comparison depends on the front matter data format (TOML, YAML, or JSON). + +> [!note] +> Using TOML for pages with custom front matter dates enables precise date comparisons. + +With TOML, date values are first-class citizens. TOML has a date data type while JSON and YAML do not. If you quote a TOML date, it is a string. If you do not quote a TOML date value, it is [`time.Time`] value, enabling precise comparisons. + +In the TOML example below, note that the event date is not quoted. + +```text {file="content/events/2024-user-conference.md"} ++++ +title = '2024 User Conference" +eventDate = 2024-04-01 ++++ +``` + +To return a collection of future events: + +```go-html-template +{{ $events := where .Site.RegularPages "Type" "events" }} +{{ $futureEvents := where $events "Params.eventDate" "gt" now }} +``` + +When working with YAML or JSON, or quoted TOML values, custom dates are strings; you cannot compare them with `time.Time` values. String comparisons may be possible if the custom date layout is consistent from one page to the next. To be safe, filter the pages by ranging through the collection: + +```go-html-template +{{ $events := where .Site.RegularPages "Type" "events" }} +{{ $futureEvents := slice }} +{{ range $events }} + {{ if gt (time.AsTime .Params.eventDate) now }} + {{ $futureEvents = $futureEvents | append . }} + {{ end }} +{{ end }} +``` + +## Nil comparison + +To return a collection of pages where the "color" parameter is present in front matter, compare to `nil`: + +```go-html-template +{{ $pages := where .Site.RegularPages "Params.color" "ne" nil }} +``` + +To return a collection of pages where the "color" parameter is not present in front matter, compare to `nil`: + +```go-html-template +{{ $pages := where .Site.RegularPages "Params.color" "eq" nil }} +``` + +In both examples above, note that `nil` is not quoted. + +## Nested comparison + +These are equivalent: + +```go-html-template +{{ $pages := where .Site.RegularPages "Type" "tutorials" }} +{{ $pages = where $pages "Params.level" "eq" "beginner" }} +``` + +```go-html-template +{{ $pages := where (where .Site.RegularPages "Type" "tutorials") "Params.level" "eq" "beginner" }} +``` + +## Portable section comparison + +Useful for theme authors, avoid hardcoding section names by using the `where` function with the [`MainSections`] method on a `Site` object. + +```go-html-template +{{ $pages := where .Site.RegularPages "Section" "in" .Site.MainSections }} +``` + +With this construct, a theme author can instruct users to specify their main sections in the site configuration: + +{{< code-toggle file=hugo >}} +mainSections = ['blog','galleries'] +{{< /code-toggle >}} + +If `mainSections` is not defined in the site configuration, the `MainSections` method returns a slice with one element---the top-level section with the most pages. + +## Boolean/undefined comparison + +Consider this site content: + +```text +content/ +├── posts/ +│ ├── _index.md +│ ├── post-1.md <-- front matter: exclude = false +│ ├── post-2.md <-- front matter: exclude = true +│ └── post-3.md <-- front matter: exclude not defined +└── _index.md +``` + +The first two pages have an "exclude" field in front matter, but the last page does not. When testing for _equality_, the third page is _excluded_ from the result. When testing for _inequality_, the third page is _included_ in the result. + +### Equality test + +This template: + +```go-html-template +<ul> + {{ range where .Site.RegularPages "Params.exclude" "eq" false }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-1/">Post 1</a></li> +</ul> +``` + +This template: + +```go-html-template +<ul> + {{ range where .Site.RegularPages "Params.exclude" "eq" true }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-2/">Post 2</a></li> +</ul> +``` + +### Inequality test + +This template: + +```go-html-template +<ul> + {{ range where .Site.RegularPages "Params.exclude" "ne" false }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-2/">Post 2</a></li> + <li><a href="/posts/post-3/">Post 3</a></li> +</ul> +``` + +This template: + +```go-html-template +<ul> + {{ range where .Site.RegularPages "Params.exclude" "ne" true }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-1/">Post 1</a></li> + <li><a href="/posts/post-3/">Post 3</a></li> +</ul> +``` + +To exclude a page with an undefined field from a boolean _inequality_ test: + +1. Create a collection using a boolean comparison +1. Create a collection using a nil comparison +1. Subtract the second collection from the first collection using the [`collections.Complement`] function. + +This template: + +```go-html-template +{{ $p1 := where .Site.RegularPages "Params.exclude" "ne" true }} +{{ $p2 := where .Site.RegularPages "Params.exclude" "eq" nil }} +<ul> + {{ range $p1 | complement $p2 }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-1/">Post 1</a></li> +</ul> +``` + +This template: + +```go-html-template +{{ $p1 := where .Site.RegularPages "Params.exclude" "ne" false }} +{{ $p2 := where .Site.RegularPages "Params.exclude" "eq" nil }} +<ul> + {{ range $p1 | complement $p2 }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li><a href="/posts/post-1/">Post 2</a></li> +</ul> +``` + +[`collections.Complement`]: /functions/collections/complement/ +[`date`]: /methods/page/date/ +[`lastmod`]: /methods/page/lastmod/ +[`MainSections`]: /methods/site/mainsections/ +[`time.Time`]: https://pkg.go.dev/time#Time diff --git a/docs/content/en/functions/collections/_index.md b/docs/content/en/functions/collections/_index.md new file mode 100644 index 000000000..c7b856f4f --- /dev/null +++ b/docs/content/en/functions/collections/_index.md @@ -0,0 +1,7 @@ +--- +title: Collections functions +linkTitle: collections +description: Use these functions to work with arrays, slices, maps, and page collections. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/compare/Conditional.md b/docs/content/en/functions/compare/Conditional.md new file mode 100644 index 000000000..c004bf4e6 --- /dev/null +++ b/docs/content/en/functions/compare/Conditional.md @@ -0,0 +1,31 @@ +--- +title: compare.Conditional +description: Returns one of two arguments depending on the value of the control argument. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [cond] + returnType: any + signatures: [compare.Conditional CONTROL ARG1 ARG2] +aliases: [/functions/cond] +--- + +If CONTROL is truthy the function returns ARG1, otherwise it returns ARG2. + +```go-html-template +{{ $qty := 42 }} +{{ cond (le $qty 3) "few" "many" }} → many +``` + +Unlike [ternary operators] in other languages, the `compare.Conditional` function does not perform [short-circuit evaluation]. It evaluates both ARG1 and ARG2 regardless of the CONTROL value. + +[short-circuit evaluation]: https://en.wikipedia.org/wiki/Short-circuit_evaluation +[ternary operators]: https://en.wikipedia.org/wiki/Ternary_conditional_operator + +Due to the absence of short-circuit evaluation, these examples throw an error: + +```go-html-template +{{ cond true "true" (div 1 0) }} +{{ cond false (div 1 0) "false" }} +``` diff --git a/docs/content/en/functions/compare/Default.md b/docs/content/en/functions/compare/Default.md new file mode 100644 index 000000000..f8bd06f06 --- /dev/null +++ b/docs/content/en/functions/compare/Default.md @@ -0,0 +1,47 @@ +--- +title: compare.Default +description: Returns the second argument if set, else the first argument. +keywords: [] +params: + functions_and_methods: + aliases: [default] + returnType: any + signatures: [compare.Default DEFAULT INPUT] +aliases: [/functions/default] +--- + +The `default` function returns the second argument if set, else the first argument. + +> [!note] +> When the second argument is the boolean `false` value, the `default` function returns `false`. All _other_ falsy values are considered unset. +> +> The falsy values are `false`, `0`, any `nil` pointer or interface value, any array, slice, map, or string of length zero, and zero `time.Time` values. +> +> Everything else is truthy. +> +> To set a default value based on truthiness, use the [`or`] operator instead. + +The `default` function returns the second argument if set: + +```go-html-template +{{ default 42 1 }} → 1 +{{ default 42 "foo" }} → foo +{{ default 42 (dict "k" "v") }} → map[k:v] +{{ default 42 (slice "a" "b") }} → [a b] +{{ default 42 true }} → true + +<!-- As noted above, the boolean "false" is considered set --> +{{ default 42 false }} → false +``` + +The `default` function returns the first argument if the second argument is not set: + +```go-html-template +{{ default 42 0 }} → 42 +{{ default 42 "" }} → 42 +{{ default 42 dict }} → 42 +{{ default 42 slice }} → 42 +{{ default 42 <nil> }} → 42 +``` + +[`or`]: /functions/go-template/or/ diff --git a/docs/content/en/functions/compare/Eq.md b/docs/content/en/functions/compare/Eq.md new file mode 100644 index 000000000..583e2e495 --- /dev/null +++ b/docs/content/en/functions/compare/Eq.md @@ -0,0 +1,24 @@ +--- +title: compare.Eq +description: Returns the boolean truth of arg1 == arg2 || arg1 == arg3. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [eq] + returnType: bool + signatures: ['compare.Eq ARG1 ARG2 [ARG...]'] +aliases: [/functions/eq] +--- + +```go-html-template +{{ eq 1 1 }} → true +{{ eq 1 2 }} → false + +{{ eq 1 1 1 }} → true +{{ eq 1 1 2 }} → true +{{ eq 1 2 1 }} → true +{{ eq 1 2 2 }} → false +``` + +You can also use the `compare.Eq` function to compare strings, boolean values, dates, slices, maps, and pages. diff --git a/docs/content/en/functions/compare/Ge.md b/docs/content/en/functions/compare/Ge.md new file mode 100644 index 000000000..fd793f0c9 --- /dev/null +++ b/docs/content/en/functions/compare/Ge.md @@ -0,0 +1,35 @@ +--- +title: compare.Ge +description: Returns the boolean truth of arg1 >= arg2 && arg1 >= arg3. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [ge] + returnType: bool + signatures: ['compare.Ge ARG1 ARG2 [ARG...]'] +aliases: [/functions/ge] +--- + +```go-html-template +{{ ge 1 1 }} → true +{{ ge 1 2 }} → false +{{ ge 2 1 }} → true + +{{ ge 1 1 1 }} → true +{{ ge 1 1 2 }} → false +{{ ge 1 2 1 }} → false +{{ ge 1 2 2 }} → false + +{{ ge 2 1 1 }} → true +{{ ge 2 1 2 }} → true +{{ ge 2 2 1 }} → true +``` + +Use the `compare.Ge` function to compare other data types as well: + +```go-html-template +{{ ge "ab" "a" }} → true +{{ ge time.Now (time.AsTime "1964-12-30") }} → true +{{ ge true false }} → true +``` diff --git a/docs/content/en/functions/compare/Gt.md b/docs/content/en/functions/compare/Gt.md new file mode 100644 index 000000000..f48312cf7 --- /dev/null +++ b/docs/content/en/functions/compare/Gt.md @@ -0,0 +1,35 @@ +--- +title: compare.Gt +description: Returns the boolean truth of arg1 > arg2 && arg1 > arg3. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [gt] + returnType: bool + signatures: ['compare.Gt ARG1 ARG2 [ARG...]'] +aliases: [/functions/gt] +--- + +```go-html-template +{{ gt 1 1 }} → false +{{ gt 1 2 }} → false +{{ gt 2 1 }} → true + +{{ gt 1 1 1 }} → false +{{ gt 1 1 2 }} → false +{{ gt 1 2 1 }} → false +{{ gt 1 2 2 }} → false + +{{ gt 2 1 1 }} → true +{{ gt 2 1 2 }} → false +{{ gt 2 2 1 }} → false +``` + +Use the `compare.Gt` function to compare other data types as well: + +```go-html-template +{{ gt "ab" "a" }} → true +{{ gt time.Now (time.AsTime "1964-12-30") }} → true +{{ gt true false }} → true +``` diff --git a/docs/content/en/functions/compare/Le.md b/docs/content/en/functions/compare/Le.md new file mode 100644 index 000000000..b490d6807 --- /dev/null +++ b/docs/content/en/functions/compare/Le.md @@ -0,0 +1,35 @@ +--- +title: compare.Le +description: Returns the boolean truth of arg1 <= arg2 && arg1 <= arg3. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [le] + returnType: bool + signatures: ['compare.Le ARG1 ARG2 [ARG...]'] +aliases: [/functions/le] +--- + +```go-html-template +{{ le 1 1 }} → true +{{ le 1 2 }} → true +{{ le 2 1 }} → false + +{{ le 1 1 1 }} → true +{{ le 1 1 2 }} → true +{{ le 1 2 1 }} → true +{{ le 1 2 2 }} → true + +{{ le 2 1 1 }} → false +{{ le 2 1 2 }} → false +{{ le 2 2 1 }} → false +``` + +Use the `compare.Le` function to compare other data types as well: + +```go-html-template +{{ le "ab" "a" }} → false +{{ le time.Now (time.AsTime "1964-12-30") }} → false +{{ le true false }} → false +``` diff --git a/docs/content/en/functions/compare/Lt.md b/docs/content/en/functions/compare/Lt.md new file mode 100644 index 000000000..a5578cc84 --- /dev/null +++ b/docs/content/en/functions/compare/Lt.md @@ -0,0 +1,35 @@ +--- +title: compare.Lt +description: Returns the boolean truth of arg1 < arg2 && arg1 < arg3. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [lt] + returnType: bool + signatures: ['compare.Lt ARG1 ARG2 [ARG...]'] +aliases: [/functions/lt] +--- + +```go-html-template +{{ lt 1 1 }} → false +{{ lt 1 2 }} → true +{{ lt 2 1 }} → false + +{{ lt 1 1 1 }} → false +{{ lt 1 1 2 }} → false +{{ lt 1 2 1 }} → false +{{ lt 1 2 2 }} → true + +{{ lt 2 1 1 }} → false +{{ lt 2 1 2 }} → false +{{ lt 2 2 1 }} → false +``` + +Use the `compare.Lt` function to compare other data types as well: + +```go-html-template +{{ lt "ab" "a" }} → false +{{ lt time.Now (time.AsTime "1964-12-30") }} → false +{{ lt true false }} → false +``` diff --git a/docs/content/en/functions/compare/Ne.md b/docs/content/en/functions/compare/Ne.md new file mode 100644 index 000000000..8839983f8 --- /dev/null +++ b/docs/content/en/functions/compare/Ne.md @@ -0,0 +1,24 @@ +--- +title: compare.Ne +description: Returns the boolean truth of arg1 != arg2 && arg1 != arg3. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [ne] + returnType: bool + signatures: ['compare.Ne ARG1 ARG2 [ARG...]'] +aliases: [/functions/ne] +--- + +```go-html-template +{{ ne 1 1 }} → false +{{ ne 1 2 }} → true + +{{ ne 1 1 1 }} → false +{{ ne 1 1 2 }} → false +{{ ne 1 2 1 }} → false +{{ ne 1 2 2 }} → true +``` + +You can also use the `compare.Ne` function to compare strings, boolean values, dates, slices, maps, and pages. diff --git a/docs/content/en/functions/compare/_index.md b/docs/content/en/functions/compare/_index.md new file mode 100644 index 000000000..59673a2c8 --- /dev/null +++ b/docs/content/en/functions/compare/_index.md @@ -0,0 +1,7 @@ +--- +title: Compare functions +linkTitle: compare +description: Use these functions to compare two or more values. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/crypto/FNV32a.md b/docs/content/en/functions/crypto/FNV32a.md new file mode 100644 index 000000000..03bcc57e7 --- /dev/null +++ b/docs/content/en/functions/crypto/FNV32a.md @@ -0,0 +1,18 @@ +--- +title: crypto.FNV32a +description: Returns the 32-bit FNV (Fowler-Noll-Vo) non-cryptographic hash of the given string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: int + signatures: [crypto.FNV32a STRING] +expiryDate: 2026-07-31 # deprecated 2024-07-31 in v0.129.0 +--- + +{{< deprecated-in 0.129.0 >}} +Use [`hash.FNV32a`] instead. + +[`hash.FNV32a`]: /functions/hash/FNV32a/ +{{< /deprecated-in >}} diff --git a/docs/content/en/functions/crypto/HMAC.md b/docs/content/en/functions/crypto/HMAC.md new file mode 100644 index 000000000..5929826dd --- /dev/null +++ b/docs/content/en/functions/crypto/HMAC.md @@ -0,0 +1,27 @@ +--- +title: crypto.HMAC +description: Returns a cryptographic hash that uses a key to sign a message. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [hmac] + returnType: string + signatures: ['crypto.HMAC HASH_TYPE KEY MESSAGE [ENCODING]'] +aliases: [/functions/hmac] +--- + +Set the `HASH_TYPE` argument to `md5`, `sha1`, `sha256`, or `sha512`. + +Set the optional `ENCODING` argument to either `hex` (default) or `binary`. + +```go-html-template +{{ hmac "sha256" "Secret key" "Secret message" }} +5cceb491f45f8b154e20f3b0a30ed3a6ff3027d373f85c78ffe8983180b03c84 + +{{ hmac "sha256" "Secret key" "Secret message" "hex" }} +5cceb491f45f8b154e20f3b0a30ed3a6ff3027d373f85c78ffe8983180b03c84 + +{{ hmac "sha256" "Secret key" "Secret message" "binary" | base64Encode }} +XM60kfRfixVOIPOwow7Tpv8wJ9Nz+Fx4/+iYMYCwPIQ= +``` diff --git a/docs/content/en/functions/crypto/MD5.md b/docs/content/en/functions/crypto/MD5.md new file mode 100644 index 000000000..89bb8cc1b --- /dev/null +++ b/docs/content/en/functions/crypto/MD5.md @@ -0,0 +1,22 @@ +--- +title: crypto.MD5 +description: Hashes the given input and returns its MD5 checksum encoded to a hexadecimal string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [md5] + returnType: string + signatures: [crypto.MD5 INPUT] +aliases: [/functions/md5] +--- + +```go-html-template +{{ md5 "Hello world" }} → 3e25960a79dbc69b674cd4ec67a72c62 +``` + +This can be useful if you want to use [Gravatar](https://en.gravatar.com/) for generating a unique avatar: + +```html +<img src="https://www.gravatar.com/avatar/{{ md5 "your@email.com" }}?s=100&d=identicon"> +``` diff --git a/docs/content/en/functions/crypto/SHA1.md b/docs/content/en/functions/crypto/SHA1.md new file mode 100644 index 000000000..c80dac0a4 --- /dev/null +++ b/docs/content/en/functions/crypto/SHA1.md @@ -0,0 +1,16 @@ +--- +title: crypto.SHA1 +description: Hashes the given input and returns its SHA1 checksum encoded to a hexadecimal string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [sha1] + returnType: string + signatures: [crypto.SHA1 INPUT] +aliases: [/functions/sha,/functions/sha1] +--- + +```go-html-template +{{ sha1 "Hello world" }} → 7b502c3a1f48c8609ae212cdfb639dee39673f5e +``` diff --git a/docs/content/en/functions/crypto/SHA256.md b/docs/content/en/functions/crypto/SHA256.md new file mode 100644 index 000000000..d0a66c069 --- /dev/null +++ b/docs/content/en/functions/crypto/SHA256.md @@ -0,0 +1,16 @@ +--- +title: crypto.SHA256 +description: Hashes the given input and returns its SHA256 checksum encoded to a hexadecimal string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [sha256] + returnType: string + signatures: [crypto.SHA256 INPUT] +aliases: [/functions/sha256] +--- + +```go-html-template +{{ sha256 "Hello world" }} → 64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c +``` diff --git a/docs/content/en/functions/crypto/_index.md b/docs/content/en/functions/crypto/_index.md new file mode 100644 index 000000000..5771630d4 --- /dev/null +++ b/docs/content/en/functions/crypto/_index.md @@ -0,0 +1,7 @@ +--- +title: Crypto functions +linkTitle: crypto +description: Use these functions to create cryptographic hashes. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/css/PostCSS.md b/docs/content/en/functions/css/PostCSS.md new file mode 100644 index 000000000..9cc698248 --- /dev/null +++ b/docs/content/en/functions/css/PostCSS.md @@ -0,0 +1,128 @@ +--- +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 }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ end }} +``` + +## Setup + +Follow the steps below to transform CSS using any of the available [PostCSS plugins]. + +### Step 1 + +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: + +```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]. + +### Step 4 + +Place your CSS file within the `assets/css` directory. + +### Step 5 + +Process the resource with PostCSS: + +```go-html-template +{{ with resources.Get "css/main.css" | postCSS }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ end }} +``` + +## 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 }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ 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 }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> +{{ 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 --git a/docs/content/en/functions/css/Sass.md b/docs/content/en/functions/css/Sass.md new file mode 100644 index 000000000..1d5487130 --- /dev/null +++ b/docs/content/en/functions/css/Sass.md @@ -0,0 +1,234 @@ +--- +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 />}} + +```go-html-template +{{ with resources.Get "sass/main.scss" }} + {{ $opts := dict + "enableSourceMap" (not hugo.IsProduction) + "outputStyle" (cond hugo.IsProduction "compressed" "expanded") + "targetPath" "css/main.css" + "transpiler" "libsass" + }} + {{ with . | toCSS $opts }} + {{ if hugo.IsProduction }} + {{ with . | fingerprint }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> + {{ end }} + {{ else }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> + {{ end }} + {{ end }} +{{ end }} +``` + +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 + +transpiler +: (`string`) The transpiler to use, either `libsass` (default) 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) below. + +targetPath +: (`string`) If not set, the transformed resource's target path will be the original path of the asset file with its extension replaced by `.css`. + +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; +``` + +outputStyle +: (`string`) Output styles available to LibSass include `nested` (default), `expanded`, `compact`, and `compressed`. Output styles available to Dart Sass include `expanded` (default) and `compressed`. + +precision +: (`int`) Precision of floating point math. Not applicable to Dart Sass. + +enableSourceMap +: (`bool`) Whether to generate a source map. Default is `false`. + +sourceMapIncludeSources +: (`bool`) Whether to embed sources in the generated source map. Not applicable to LibSass. 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. + +```go-html-template +{{ $opts := dict + "transpiler" "dartsass" + "targetPath" "css/style.css" + "vars" site.Params.styles + "enableSourceMap" (not hugo.IsProduction) + "includePaths" (slice "node_modules/bootstrap/scss") +}} +{{ with resources.Get "sass/main.scss" | toCSS $opts | minify | fingerprint }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> +{{ end }} +``` + +silenceDeprecations +: (`slice`) {{< new-in 0.139.0 />}} A slice of deprecation IDs to silence. The deprecation IDs are printed to in the warning message, e.g "import" in `WARN Dart Sass: DEPRECATED [import] ...`. This is for Dart Sass only. + +## 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. + +Run `hugo env` to list the active transpilers. + +### Installing in a production environment + +For [CI/CD](g) deployments (e.g., GitHub Pages, GitLab Pages, Netlify, etc.) you must edit the workflow to install Dart Sass before Hugo builds the site[^2]. Some providers allow you to use one of the package managers above, or you can download and extract one of the prebuilt binaries. + +[^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. + +#### GitHub Pages + +To install Dart Sass for your builds on GitHub Pages, add this step to the GitHub Pages workflow file: + +```yaml +- name: Install Dart Sass + run: sudo snap install dart-sass +``` + +If you are using GitHub Pages for the first time with your repository, GitHub provides a [starter workflow] for Hugo that includes Dart Sass. This is the simplest way to get started. + +#### 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.144.2 + DART_SASS_VERSION: 1.85.0 + GIT_DEPTH: 0 + GIT_STRATEGY: clone + GIT_SUBMODULE_STRATEGY: recursive + TZ: America/Los_Angeles +image: + name: golang:1.20-buster +pages: + script: + # Install Dart Sass + - curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz + - tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz + - cp -r dart-sass/* /usr/local/bin + - rm -rf dart-sass* + # Install Hugo + - curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb + - apt install -y ./hugo_extended_${HUGO_VERSION}_linux-amd64.deb + - rm hugo_extended_${HUGO_VERSION}_linux-amd64.deb + # Build + - hugo --gc --minify + artifacts: + paths: + - public + rules: + - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH +``` + +#### Netlify + +To install Dart Sass for your builds on Netlify, the `netlify.toml` file should look something like this: + +```toml +[build.environment] +HUGO_VERSION = "0.144.2" +DART_SASS_VERSION = "1.85.0" +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 \ + """ +``` + +### Example + +To transpile with Dart Sass, set `transpiler` to `dartsass` in the options map passed to `css.Sass`. For example: + +```go-html-template +{{ with resources.Get "sass/main.scss" }} + {{ $opts := dict + "enableSourceMap" (not hugo.IsProduction) + "outputStyle" (cond hugo.IsProduction "compressed" "expanded") + "targetPath" "css/main.css" + "transpiler" "dartsass" + }} + {{ with . | toCSS $opts }} + {{ if hugo.IsProduction }} + {{ with . | fingerprint }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> + {{ end }} + {{ else }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> + {{ end }} + {{ end }} +{{ end }} +``` + +### Miscellaneous + +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. + +[brew.sh]: https://brew.sh/ +[chocolatey.org]: https://community.chocolatey.org/packages/sass +[dart sass]: https://sass-lang.com/dart-sass +[libsass]: https://sass-lang.com/libsass +[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 diff --git a/docs/content/en/functions/css/TailwindCSS.md b/docs/content/en/functions/css/TailwindCSS.md new file mode 100644 index 000000000..6add7373a --- /dev/null +++ b/docs/content/en/functions/css/TailwindCSS.md @@ -0,0 +1,138 @@ +--- +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. + +> [!caution] +> Tailwind CSS v4.0 and later requires a relatively [modern browser](https://tailwindcss.com/docs/compatibility#browser-support) to render correctly. + +## Setup + +### Step 1 + +Install the Tailwind CSS CLI v4.0 or later: + +```sh +npm install --save-dev tailwindcss @tailwindcss/cli +``` + +The TailwindCSS CLI is also available as a [standalone executable] if you want to use it without installing Node.js. + +[standalone executable]: https://github.com/tailwindlabs/tailwindcss/releases/latest + +### Step 2 + +Add this to your site configuration: + +{{< code-toggle file=hugo copy=true >}} +[[module.mounts]] +source = "assets" +target = "assets" +[[module.mounts]] +source = "hugo_stats.json" +target = "assets/notwatching/hugo_stats.json" +disableWatch = true +[build.buildStats] +enable = true +[[build.cachebusters]] +source = "assets/notwatching/hugo_stats\\.json" +target = "css" +[[build.cachebusters]] +source = "(postcss|tailwind)\\.config\\.js" +target = "css" +{{< /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 (templates.Defer (dict "key" "global")) }} + {{ with resources.Get "css/main.css" }} + {{ $opts := dict + "minify" hugo.IsProduction + "inlineImports" true + }} + {{ with . | css.TailwindCSS $opts }} + {{ if hugo.IsProduction }} + {{ with . | fingerprint }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> + {{ end }} + {{ else }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> + {{ end }} + {{ end }} + {{ end }} +{{ end }} +``` + +### Step 5 + +Call the partial template from your base template: + +```go-html-template {file="layouts/_default/baseof.html"} +<head> + ... + {{ partialCached "css.html" . }} + ... +<head> +``` + +### Step 6 + +Optionally create a `tailwind.config.js` file in the root of your project as shown below. This is necessary if you use the [Tailwind CSS IntelliSense +extension] for Visual Studio Code. + +[Tailwind CSS IntelliSense +extension]: https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss + +```js {file="tailwind.config.js" copy=true} +/* +This file is present to satisfy a requirement of the Tailwind CSS IntelliSense +extension for Visual Studio Code. + +https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss + +The rest of this file is intentionally empty. +*/ +``` + +## 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`. + +inlineImports +: (`bool`) Whether to enable 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 --git a/docs/content/en/functions/css/_index.md b/docs/content/en/functions/css/_index.md new file mode 100644 index 000000000..9faabbbe9 --- /dev/null +++ b/docs/content/en/functions/css/_index.md @@ -0,0 +1,7 @@ +--- +title: CSS functions +linkTitle: css +description: Use these functions to work with CSS and Sass files. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/data/GetCSV.md b/docs/content/en/functions/data/GetCSV.md new file mode 100644 index 000000000..39c71b06c --- /dev/null +++ b/docs/content/en/functions/data/GetCSV.md @@ -0,0 +1,144 @@ +--- +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. + +```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 --git a/docs/content/en/functions/data/GetJSON.md b/docs/content/en/functions/data/GetJSON.md new file mode 100644 index 000000000..9cdea9287 --- /dev/null +++ b/docs/content/en/functions/data/GetJSON.md @@ -0,0 +1,146 @@ +--- +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. + +```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. + +```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 --git a/docs/content/en/functions/data/_index.md b/docs/content/en/functions/data/_index.md new file mode 100644 index 000000000..2177bc528 --- /dev/null +++ b/docs/content/en/functions/data/_index.md @@ -0,0 +1,7 @@ +--- +title: Data functions +linkTitle: data +description: Use these functions to read local or remote data files. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/debug/Dump.md b/docs/content/en/functions/debug/Dump.md new file mode 100644 index 000000000..df846ac3d --- /dev/null +++ b/docs/content/en/functions/debug/Dump.md @@ -0,0 +1,33 @@ +--- +title: debug.Dump +description: Returns an object dump as a string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [debug.Dump VALUE] +--- + +```go-html-template +<pre>{{ debug.Dump site.Data.books }}</pre> +``` + +```json +[ + { + "author": "Victor Hugo", + "rating": 4, + "title": "The Hunchback of Notre Dame" + }, + { + "author": "Victor Hugo", + "rating": 5, + "title": "Les Misérables" + } +] +``` + +> [!note] +> Output from this function may change from one release to the next. Use for debugging only. diff --git a/docs/content/en/functions/debug/Timer.md b/docs/content/en/functions/debug/Timer.md new file mode 100644 index 000000000..c2cd59211 --- /dev/null +++ b/docs/content/en/functions/debug/Timer.md @@ -0,0 +1,37 @@ +--- +title: debug.Timer +description: Creates a named timer that reports elapsed time to the console. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: debug.Timer + signatures: [debug.Timer NAME] +--- + +{{< new-in 0.120.0 />}} + +Use the `debug.Timer` function to determine execution time for a block of code, useful for finding performance bottlenecks in templates. + +The timer starts when you instantiate it, and stops when you call its `Stop` method. + +```go-html-template +{{ $t := debug.Timer "TestSqrt" }} +{{ range seq 2000 }} + {{ $f := math.Sqrt . }} +{{ end }} +{{ $t.Stop }} +``` + +Use the `--logLevel info` command line flag when you build the site. + +```sh +hugo --logLevel info +``` + +The results are displayed in the console at the end of the build. You can have as many timers as you want and if you don't stop them, they will be stopped at the end of build. + +```text +INFO timer: name TestSqrt count 1002 duration 2.496017496s average 2.491035ms median 2.282291ms +``` diff --git a/docs/content/en/functions/debug/_index.md b/docs/content/en/functions/debug/_index.md new file mode 100644 index 000000000..49fe416ed --- /dev/null +++ b/docs/content/en/functions/debug/_index.md @@ -0,0 +1,7 @@ +--- +title: Debug functions +linkTitle: debug +description: Use these functions to debug your templates. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/diagrams/Goat.md b/docs/content/en/functions/diagrams/Goat.md new file mode 100644 index 000000000..e2f55eee0 --- /dev/null +++ b/docs/content/en/functions/diagrams/Goat.md @@ -0,0 +1,115 @@ +--- +title: diagrams.Goat +description: Returns an SVGDiagram object created from the given GoAT markup and options. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: diagrams.SVGDiagram + signatures: [diagrams.Goat MARKUP] +--- + +Useful in a [code block render hook], the `diagrams.Goat` function returns an SVGDiagram object created from the given [GoAT] markup. + +## Methods + +The SVGDiagram object has the following methods: + +Inner +: (`template.HTML`) Returns the SVG child elements without a wrapping `svg` element, allowing you to create your own wrapper. + +Wrapped +: (`template.HTML`) Returns the SVG child elements wrapped in an `svg` element. + +Width +: (`int`) Returns the width of the rendered diagram, in pixels. + +Height +: (`int`) Returns the height of the rendered diagram, in pixels. + +## GoAT Diagrams + +Hugo natively supports GoAT diagrams with an [embedded code block render hook]. + +This Markdown: + +````text +```goat +.---. .-. .-. .-. .---. +| A +--->| 1 |<--->| 2 |<--->| 3 |<---+ B | +'---' '-' '+' '+' '---' +``` +```` + +Is rendered to: + +```html +<div class="goat svg-container"> + <svg xmlns="http://www.w3.org/2000/svg" font-family="Menlo,Lucida Console,monospace" viewBox="0 0 352 57"> + ... + </svg> +</div> +``` + +Which appears in your browser as: + +```goat {class="mw6-ns"} +.---. .-. .-. .-. .---. +| A +--->| 1 |<--->| 2 |<--->| 3 |<---+ B | +'---' '-' '+' '+' '---' +``` + +To customize rendering, override Hugo's [embedded code block render hook] for GoAT diagrams. + +## Code block render hook + +By way of example, let's create a code block render hook to render GoAT diagrams as `figure` elements with an optional caption. + +```go-html-template {file="layouts/_default/_markup/render-codeblock-goat.html"} +{{ $caption := or .Attributes.caption "" }} +{{ $class := or .Attributes.class "diagram" }} +{{ $id := or .Attributes.id (printf "diagram-%d" (add 1 .Ordinal)) }} + +<figure id="{{ $id }}"> + {{ with diagrams.Goat (trim .Inner "\n\r") }} + <svg class="{{ $class }}" width="{{ .Width }}" height="{{ .Height }}" xmlns="http://www.w3.org/2000/svg" version="1.1"> + {{ .Inner }} + </svg> + {{ end }} + <figcaption>{{ $caption }}</figcaption> +</figure> +``` + +This Markdown: + +````text {file="content/example.md" } +```goat {class="foo" caption="Diagram 1: Example"} +.---. .-. .-. .-. .---. +| A +--->| 1 |<--->| 2 |<--->| 3 |<---+ B | +'---' '-' '+' '+' '---' +``` +```` + +Is rendered to: + +```html +<figure id="diagram-1"> + <svg class="foo" width="272" height="57" xmlns="http://www.w3.org/2000/svg" version="1.1"> + ... + </svg> + <figcaption>Diagram 1: Example</figcaption> +</figure> +``` + +Use CSS to style the SVG as needed: + +```css +svg.foo { + font-family: "Segoe UI","Noto Sans",Helvetica,Arial,sans-serif +} +``` + +[code block render hook]: /render-hooks/code-blocks/ +[embedded code block render hook]: {{% eturl render-codeblock-goat %}} +[GoAT]: https://github.com/bep/goat diff --git a/docs/content/en/functions/diagrams/_index.md b/docs/content/en/functions/diagrams/_index.md new file mode 100644 index 000000000..6aa407071 --- /dev/null +++ b/docs/content/en/functions/diagrams/_index.md @@ -0,0 +1,7 @@ +--- +title: Diagram functions +linkTitle: diagrams +description: Use these functions to render diagrams. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/encoding/Base64Decode.md b/docs/content/en/functions/encoding/Base64Decode.md new file mode 100644 index 000000000..5237e904f --- /dev/null +++ b/docs/content/en/functions/encoding/Base64Decode.md @@ -0,0 +1,39 @@ +--- +title: encoding.Base64Decode +description: Returns the base64 decoding of the given content. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [base64Decode] + returnType: string + signatures: [encoding.Base64Decode INPUT] +aliases: [/functions/base64Decode] +--- + +```go-html-template +{{ "SHVnbw==" | base64Decode }} → Hugo +``` + +Use the `base64Decode` function to decode responses from APIs. For example, the result of this call to GitHub's API contains the base64-encoded representation of the repository's README file: + +```text +https://api.github.com/repos/gohugoio/hugo/readme +``` + +To retrieve and render the content: + +```go-html-template +{{ $url := "https://api.github.com/repos/gohugoio/hugo/readme" }} +{{ with try (resources.GetRemote $url) }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else with .Value }} + {{ with . | transform.Unmarshal }} + {{ .content | base64Decode | markdownify }} + {{ end }} + {{ else }} + {{ errorf "Unable to get remote resource %q" $url }} + {{ end }} +{{ end }} +``` diff --git a/docs/content/en/functions/encoding/Base64Encode.md b/docs/content/en/functions/encoding/Base64Encode.md new file mode 100644 index 000000000..e19d6773c --- /dev/null +++ b/docs/content/en/functions/encoding/Base64Encode.md @@ -0,0 +1,16 @@ +--- +title: encoding.Base64Encode +description: Returns the base64 decoding of the given content. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [base64Encode] + returnType: string + signatures: [encoding.Base64Encode INPUT] +aliases: [/functions/base64, /functions/base64Encode] +--- + +```go-html-template +{{ "Hugo" | base64Encode }} → SHVnbw== +``` diff --git a/docs/content/en/functions/encoding/Jsonify.md b/docs/content/en/functions/encoding/Jsonify.md new file mode 100644 index 000000000..1d60dd68d --- /dev/null +++ b/docs/content/en/functions/encoding/Jsonify.md @@ -0,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. + +```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 --git a/docs/content/en/functions/encoding/_index.md b/docs/content/en/functions/encoding/_index.md new file mode 100644 index 000000000..f2819f0a7 --- /dev/null +++ b/docs/content/en/functions/encoding/_index.md @@ -0,0 +1,7 @@ +--- +title: Encoding functions +linkTitle: encoding +description: Use these functions to encode and decode data. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/fmt/Errorf.md b/docs/content/en/functions/fmt/Errorf.md new file mode 100644 index 000000000..799622f0e --- /dev/null +++ b/docs/content/en/functions/fmt/Errorf.md @@ -0,0 +1,24 @@ +--- +title: fmt.Errorf +description: Log an ERROR from a template. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [errorf] + returnType: string + signatures: ['fmt.Errorf FORMAT [INPUT]'] +aliases: [/functions/errorf] +--- + +{{% include "/_common/functions/fmt/format-string.md" %}} + +The `errorf` function evaluates the format string, then prints the result to the ERROR log and fails the build. + +```go-html-template +{{ errorf "The %q shortcode requires a src argument. See %s" .Name .Position }} +``` + +Use the [`erroridf`] function to allow optional suppression of specific errors. + +[`erroridf`]: /functions/fmt/erroridf/ diff --git a/docs/content/en/functions/fmt/Erroridf.md b/docs/content/en/functions/fmt/Erroridf.md new file mode 100644 index 000000000..97d628bac --- /dev/null +++ b/docs/content/en/functions/fmt/Erroridf.md @@ -0,0 +1,38 @@ +--- +title: fmt.Erroridf +description: Log a suppressible ERROR from a template. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [erroridf] + returnType: string + signatures: ['fmt.Erroridf ID FORMAT [INPUT]'] +aliases: [/functions/erroridf] +--- + +{{% include "/_common/functions/fmt/format-string.md" %}} + +The `erroridf` function evaluates the format string, then prints the result to the ERROR log and fails the build. Unlike the [`errorf`] function, you may suppress errors logged by the `erroridf` function by adding the message ID to the `ignoreLogs` array in your site configuration. + +This template code: + +```go-html-template +{{ erroridf "error-42" "You should consider fixing this." }} +``` + +Produces this console log: + +```text +ERROR You should consider fixing this. +You can suppress this error by adding the following to your site configuration: +ignoreLogs = ['error-42'] +``` + +To suppress this message: + +{{< code-toggle file=hugo >}} +ignoreLogs = ["error-42"] +{{< /code-toggle >}} + +[`errorf`]: /functions/fmt/errorf/ diff --git a/docs/content/en/functions/fmt/Print.md b/docs/content/en/functions/fmt/Print.md new file mode 100644 index 000000000..f1d169cfa --- /dev/null +++ b/docs/content/en/functions/fmt/Print.md @@ -0,0 +1,18 @@ +--- +title: fmt.Print +description: Prints the default representation of the given arguments using the standard `fmt.Print` function. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [print] + returnType: string + signatures: [fmt.Print INPUT] +aliases: [/functions/print] +--- + +```go-html-template +{{ print "foo" }} → foo +{{ print "foo" "bar" }} → foobar +{{ print (slice 1 2 3) }} → [1 2 3] +``` diff --git a/docs/content/en/functions/fmt/Printf.md b/docs/content/en/functions/fmt/Printf.md new file mode 100644 index 000000000..68df98609 --- /dev/null +++ b/docs/content/en/functions/fmt/Printf.md @@ -0,0 +1,37 @@ +--- +title: fmt.Printf +description: Formats a string using the standard `fmt.Sprintf` function. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [printf] + returnType: string + signatures: ['fmt.Printf FORMAT [INPUT]'] +aliases: [/functions/printf] +--- + +{{% include "/_common/functions/fmt/format-string.md" %}} + +```go-html-template +{{ $var := "world" }} +{{ printf "Hello %s." $var }} → Hello world. +``` + +```go-html-template +{{ $pi := 3.14159265 }} +{{ printf "Pi is approximately %.2f." $pi }} → 3.14 +``` + +Use the `printf` function with the `safeHTMLAttr` function: + +```go-html-template +{{ $desc := "Eat at Joe's" }} +<meta name="description" {{ printf "content=%q" $desc | safeHTMLAttr }}> +``` + +Hugo renders this to: + +```html +<meta name="description" content="Eat at Joe's"> +``` diff --git a/docs/content/en/functions/fmt/Println.md b/docs/content/en/functions/fmt/Println.md new file mode 100644 index 000000000..b7fe608ff --- /dev/null +++ b/docs/content/en/functions/fmt/Println.md @@ -0,0 +1,16 @@ +--- +title: fmt.Println +description: Prints the default representation of the given argument using the standard `fmt.Print` function and enforces a line break. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [println] + returnType: string + signatures: [fmt.Println INPUT] +aliases: [/functions/println] +--- + +```go-html-template +{{ println "foo" }} → foo\n +``` diff --git a/docs/content/en/functions/fmt/Warnf.md b/docs/content/en/functions/fmt/Warnf.md new file mode 100644 index 000000000..887a8d47f --- /dev/null +++ b/docs/content/en/functions/fmt/Warnf.md @@ -0,0 +1,34 @@ +--- +title: fmt.Warnf +description: Log a WARNING from a template. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [warnf] + returnType: string + signatures: ['fmt.Warnf FORMAT [INPUT]'] +aliases: [/functions/warnf] +--- + +{{% include "/_common/functions/fmt/format-string.md" %}} + +The `warnf` function evaluates the format string, then prints the result to the WARNING log. Hugo prints each unique message once to avoid flooding the log with duplicate warnings. + +```go-html-template +{{ warnf "The %q shortcode was unable to find %s. See %s" .Name $file .Position }} +``` + +Use the [`warnidf`] function to allow optional suppression of specific warnings. + +To prevent suppression of duplicate messages when using `warnf` for debugging, make each message unique with the [`math.Counter`] function. For example: + +```go-html-template +{{ range site.RegularPages }} + {{ .Section | warnf "%#[2]v [%[1]d]" math.Counter }} +{{ end }} +``` + +[`math.Counter`]: /functions/math/counter/ + +[`warnidf`]: /functions/fmt/warnidf/ diff --git a/docs/content/en/functions/fmt/Warnidf.md b/docs/content/en/functions/fmt/Warnidf.md new file mode 100644 index 000000000..79ebf81e6 --- /dev/null +++ b/docs/content/en/functions/fmt/Warnidf.md @@ -0,0 +1,40 @@ +--- +title: fmt.Warnidf +description: Log a suppressible WARNING from a template. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [warnidf] + returnType: string + signatures: ['fmt.Warnidf ID FORMAT [INPUT]'] +aliases: [/functions/warnidf] +--- + +{{< new-in 0.123.0 />}} + +{{% include "/_common/functions/fmt/format-string.md" %}} + +The `warnidf` function evaluates the format string, then prints the result to the WARNING log. Unlike the [`warnf`] function, you may suppress warnings logged by the `warnidf` function by adding the message ID to the `ignoreLogs` array in your site configuration. + +This template code: + +```go-html-template +{{ warnidf "warning-42" "You should consider fixing this." }} +``` + +Produces this console log: + +```text +WARN You should consider fixing this. +You can suppress this warning by adding the following to your site configuration: +ignoreLogs = ['warning-42'] +``` + +To suppress this message: + +{{< code-toggle file=hugo >}} +ignoreLogs = ["warning-42"] +{{< /code-toggle >}} + +[`warnf`]: /functions/fmt/warnf/ diff --git a/docs/content/en/functions/fmt/_index.md b/docs/content/en/functions/fmt/_index.md new file mode 100644 index 000000000..d388df112 --- /dev/null +++ b/docs/content/en/functions/fmt/_index.md @@ -0,0 +1,7 @@ +--- +title: Fmt functions +linkTitle: fmt +description: Use these functions to print strings within a template or to print messages to the terminal. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/global/_index.md b/docs/content/en/functions/global/_index.md new file mode 100644 index 000000000..3d935176c --- /dev/null +++ b/docs/content/en/functions/global/_index.md @@ -0,0 +1,6 @@ +--- +title: Global functions +linkTitle: global +description: Use these global functions to access page and site data. +categories: [] +--- diff --git a/docs/content/en/functions/global/page.md b/docs/content/en/functions/global/page.md new file mode 100644 index 000000000..0d4b8070f --- /dev/null +++ b/docs/content/en/functions/global/page.md @@ -0,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., `single.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: + +```go-html-template +{{ 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. + +### 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: + +```go-html-template +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ .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 --git a/docs/content/en/functions/global/site.md b/docs/content/en/functions/global/site.md new file mode 100644 index 000000000..be0c6730e --- /dev/null +++ b/docs/content/en/functions/global/site.md @@ -0,0 +1,30 @@ +--- +title: site +description: Provides global access to the current Site object. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [site] +aliases: [/functions/site] +--- + +Use the `site` function to return the `Site` object regardless of current context. + +```go-html-template +{{ site.Params.foo }} +``` + +When the `Site` object is in context you can use the `Site` property: + +```go-html-template +<!-- current context --> +{{ .Site.Params.foo }} +<!-- template context --> +{{ $.Site.Params.foo }} +``` + +> [!note] +> To simplify your templates, use the global `site` function regardless of whether the `Site` object is in context. diff --git a/docs/content/en/functions/go-template/_index.md b/docs/content/en/functions/go-template/_index.md new file mode 100644 index 000000000..627dc2849 --- /dev/null +++ b/docs/content/en/functions/go-template/_index.md @@ -0,0 +1,7 @@ +--- +title: Go template functions, operators, and statements +linkTitle: go template +description: These are the functions, operators, and statements provided by Go's text/template package. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/go-template/and.md b/docs/content/en/functions/go-template/and.md new file mode 100644 index 000000000..77906df52 --- /dev/null +++ b/docs/content/en/functions/go-template/and.md @@ -0,0 +1,22 @@ +--- +title: and +description: Returns the first falsy argument. If all arguments are truthy, returns the last argument. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: any + signatures: [and VALUE...] +--- + +{{% include "/_common/functions/truthy-falsy.md" %}} + +```go-html-template +{{ and 1 0 "" }} → 0 (int) +{{ and 1 false 0 }} → false (bool) + +{{ and 1 2 3 }} → 3 (int) +{{ and "a" "b" "c" }} → c (string) +{{ and "a" 1 true }} → true (bool) +``` diff --git a/docs/content/en/functions/go-template/block.md b/docs/content/en/functions/go-template/block.md new file mode 100644 index 000000000..bffab1f8c --- /dev/null +++ b/docs/content/en/functions/go-template/block.md @@ -0,0 +1,53 @@ +--- +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/_default/baseof.html"} +<body> + <main> + {{ block "main" . }} + {{ print "default value if 'main' template is empty" }} + {{ end }} + </main> +</body> +``` + +```go-html-template {file="layouts/_default/single.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} +{{ end }} +``` + +```go-html-template {file="layouts/_default/list.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/break.md b/docs/content/en/functions/go-template/break.md new file mode 100644 index 000000000..9236ec91e --- /dev/null +++ b/docs/content/en/functions/go-template/break.md @@ -0,0 +1,31 @@ +--- +title: break +description: Used with the range statement, stops the innermost iteration and bypasses all remaining iterations. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [break] +--- + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + {{ if eq . "bar" }} + {{ break }} + {{ end }} + <p>{{ . }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>foo</p> +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/continue.md b/docs/content/en/functions/go-template/continue.md new file mode 100644 index 000000000..0b9339bf4 --- /dev/null +++ b/docs/content/en/functions/go-template/continue.md @@ -0,0 +1,32 @@ +--- +title: continue +description: Used with the range statement, stops the innermost iteration and continues to the next iteration. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [continue] +--- + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + {{ if eq . "bar" }} + {{ continue }} + {{ end }} + <p>{{ . }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>foo</p> +<p>baz</p> +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/define.md b/docs/content/en/functions/go-template/define.md new file mode 100644 index 000000000..19762a3d6 --- /dev/null +++ b/docs/content/en/functions/go-template/define.md @@ -0,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" }} + <h1>{{ .Title }}</h1> + {{ .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 }} +``` + +[`block`]: /functions/go-template/block/ +[`template`]: /functions/go-template/block/ +[`partial`]: /functions/partials/include/ + +{{% include "/_common/functions/go-template/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/else.md b/docs/content/en/functions/go-template/else.md new file mode 100644 index 000000000..db3980070 --- /dev/null +++ b/docs/content/en/functions/go-template/else.md @@ -0,0 +1,65 @@ +--- +title: else +description: Begins an alternate block for if, with, and range statements. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [else VALUE] +--- + +Use with the [`if`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ if $var }} + {{ $var }} → foo +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +Use with the [`with`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ with $var }} + {{ . }} → foo +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +Use with the [`range`] statement: + +```go-html-template +{{ $var := slice 1 2 3 }} +{{ range $var }} + {{ . }} → 1 2 3 +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +Use `else if` to check multiple conditions. + +```go-html-template +{{ $var := 12 }} +{{ 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 }} +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} + +[`if`]: /functions/go-template/if/ +[`with`]: /functions/go-template/with/ +[`range`]: /functions/go-template/range/ diff --git a/docs/content/en/functions/go-template/end.md b/docs/content/en/functions/go-template/end.md new file mode 100644 index 000000000..6de120724 --- /dev/null +++ b/docs/content/en/functions/go-template/end.md @@ -0,0 +1,60 @@ +--- +title: end +description: Terminates if, with, range, block, and define statements. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [end] +--- + +Use with the [`if`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ if $var }} + {{ $var }} → foo +{{ end }} +``` + +Use with the [`with`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ with $var }} + {{ . }} → foo +{{ end }} +``` + +Use with the [`range`] statement: + +```go-html-template +{{ $var := slice 1 2 3 }} +{{ range $var }} + {{ . }} → 1 2 3 +{{ end }} +``` + +Use with the [`block`] statement: + +```go-html-template +{{ block "main" . }}{{ end }} +``` + +Use with the [`define`] statement: + +```go-html-template +{{ define "main" }} + {{ print "this is the main section" }} +{{ end }} +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} + +[`block`]: /functions/go-template/block/ +[`define`]: /functions/go-template/define/ +[`if`]: /functions/go-template/if/ +[`range`]: /functions/go-template/range/ +[`with`]: /functions/go-template/with/ diff --git a/docs/content/en/functions/go-template/if.md b/docs/content/en/functions/go-template/if.md new file mode 100644 index 000000000..af2989cca --- /dev/null +++ b/docs/content/en/functions/go-template/if.md @@ -0,0 +1,50 @@ +--- +title: if +description: Executes the block if the expression is truthy. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: + signatures: [if EXPR] +--- + +{{% include "/_common/functions/truthy-falsy.md" %}} + +```go-html-template +{{ $var := "foo" }} +{{ if $var }} + {{ $var }} → foo +{{ end }} +``` + +Use with the [`else`] statement: + +```go-html-template +{{ $var := "foo" }} +{{ if $var }} + {{ $var }} → foo +{{ else }} + {{ print "var is falsy" }} +{{ end }} +``` + +Use `else if` to check multiple conditions: + +```go-html-template +{{ $var := 12 }} +{{ 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 }} +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} + +[`else`]: /functions/go-template/else/ diff --git a/docs/content/en/functions/go-template/len.md b/docs/content/en/functions/go-template/len.md new file mode 100644 index 000000000..6a13784e3 --- /dev/null +++ b/docs/content/en/functions/go-template/len.md @@ -0,0 +1,47 @@ +--- +title: len +description: Returns the length of a string, slice, map, or collection. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: int + signatures: [len VALUE] +aliases: [/functions/len] +--- + +With a string: + +```go-html-template +{{ "ab" | len }} → 2 +{{ "" | len }} → 0 +``` + +With a slice: + +```go-html-template +{{ slice "a" "b" | len }} → 2 +{{ slice | len }} → 0 +``` + +With a map: + +```go-html-template +{{ dict "a" 1 "b" 2 | len }} → 2 +{{ dict | len }} → 0 +``` + +With a collection: + +```go-html-template +{{ site.RegularPages | len }} → 42 +``` + +You may also determine the number of pages in a collection with: + +```go-html-template +{{ site.RegularPages.Len }} → 42 +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/not.md b/docs/content/en/functions/go-template/not.md new file mode 100644 index 000000000..fd8b9afae --- /dev/null +++ b/docs/content/en/functions/go-template/not.md @@ -0,0 +1,33 @@ +--- +title: not +description: Returns the boolean negation of its single argument. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [not VALUE] +--- + +Unlike the `and` and `or` operators, the `not` operator always returns a boolean value. + +```go-html-template +{{ not true }} → false +{{ not false }} → true + +{{ not 1 }} → false +{{ not 0 }} → true + +{{ not "x" }} → false +{{ not "" }} → true +``` + +Use the `not` operator, twice in succession, to cast any value to a boolean value. For example: + +```go-html-template +{{ 42 | not | not }} → true +{{ "" | not | not }} → false +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/or.md b/docs/content/en/functions/go-template/or.md new file mode 100644 index 000000000..2f55fe479 --- /dev/null +++ b/docs/content/en/functions/go-template/or.md @@ -0,0 +1,24 @@ +--- +title: or +description: Returns the first truthy argument. If all arguments are falsy, returns the last argument. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: any + signatures: [or VALUE...] +--- + +{{% include "/_common/functions/truthy-falsy.md" %}} + +```go-html-template +{{ or 0 1 2 }} → 1 +{{ or false "a" 1 }} → a +{{ or 0 true "a" }} → true + +{{ or false "" 0 }} → 0 +{{ or 0 "" false }} → false +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/range.md b/docs/content/en/functions/go-template/range.md new file mode 100644 index 000000000..a06907c79 --- /dev/null +++ b/docs/content/en/functions/go-template/range.md @@ -0,0 +1,190 @@ +--- +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] +--- + +{{% include "/_common/functions/truthy-falsy.md" %}} + +```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 }} + <p>{{ . }}</p> +{{ else }} + <p>The collection is empty</p> +{{ 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. + +With this contrived example that uses the [`seq`] function to generate a slice of integers: + +```go-html-template +{{ range seq 3 }} + {{ .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. 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 +{{ range seq 3 }} + {{ $.Title }} +{{ end }} +``` + +> [!note] +> Gaining a thorough understanding of context is critical for anyone writing template code. + +## Array or slice of scalars + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $s }} + <p>{{ . }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>foo</p> +<p>bar</p> +<p>baz</p> +``` + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $v := $s }} + <p>{{ $v }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>foo</p> +<p>bar</p> +<p>baz</p> +``` + +This template code: + +```go-html-template +{{ $s := slice "foo" "bar" "baz" }} +{{ range $k, $v := $s }} + <p>{{ $k }}: {{ $v }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>0: foo</p> +<p>1: bar</p> +<p>2: baz</p> +``` + +## Array or 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 }} + <p>{{ .name }} is {{ .age }}</p> +{{ end }} +``` + +Is rendered to: + +```html +<p>John is 30</p> +<p>Will is 28</p> +<p>Joey is 24</p> +``` + +## Array or slice of pages + +This template code: + +```go-html-template +{{ range where site.RegularPages "Type" "articles" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +Is rendered to: + +```html +<h2><a href="/articles/article-3/">Article 3</a></h2> +<h2><a href="/articles/article-2/">Article 2</a></h2> +<h2><a href="/articles/article-1/">Article 1</a></h2> +``` + +## Maps + +This template code: + +```go-html-template +{{ $m := dict "name" "John" "age" 30 }} +{{ range $k, $v := $m }} + <p>key = {{ $k }} value = {{ $v }}</p> +{{ end }} +``` + +Is rendered to: + +```go-html-template +<p>key = age value = 30</p> +<p>key = name value = John</p> +``` + +Unlike ranging over an array or slice, Hugo sorts by key when ranging over a map. + +{{% include "/_common/functions/go-template/text-template.md" %}} + +[`break`]: /functions/go-template/break/ +[`continue`]: /functions/go-template/continue/ +[`else`]: /functions/go-template/else/ +[`seq`]: /functions/collections/seq/ diff --git a/docs/content/en/functions/go-template/return.md b/docs/content/en/functions/go-template/return.md new file mode 100644 index 000000000..eb6ba30cd --- /dev/null +++ b/docs/content/en/functions/go-template/return.md @@ -0,0 +1,96 @@ +--- +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 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: + +```go-html-template {file="layouts/partials/odd-or-even.html"} +{{ if math.ModBool . 2 }} + <p>{{ . }} is even</p> +{{ else }} + <p>{{ . }} is odd</p> +{{ end }} +``` + +When called, the partial renders HTML: + +```go-html-template +{{ partial "odd-or-even.html" 42 }} → <p>42 is even</p> +``` + +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 }} + <p>{{ $number }} is even</p> +{{ else }} + <p>{{ $number }} is odd</p> +{{ end }} +``` + +Hugo renders: + +```html +<p>42 is even</p> +``` + +See additional examples in the [partial templates] section. + +## 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 }} +``` + +[partial templates]: /templates/partial/#returning-a-value-from-a-partial +[text/template package]: https://pkg.go.dev/text/template diff --git a/docs/content/en/functions/go-template/template.md b/docs/content/en/functions/go-template/template.md new file mode 100644 index 000000000..dac1fa3be --- /dev/null +++ b/docs/content/en/functions/go-template/template.md @@ -0,0 +1,46 @@ +--- +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 [embedded templates]. For example: + +```go-html-template +{{ range (.Paginate .Pages).Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +{{ template "_internal/pagination.html" . }} +``` + +You can also 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: + +```go-html-template +{{ partial "inline/foo.html" (dict "answer" 42) }} + +{{ define "partials/inline/foo.html" }} + {{ printf "The answer is %v." .answer }} +{{ end }} +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} + +[`partial`]: /functions/partials/include/ +[inline partial]: /templates/partial/#inline-partials +[embedded templates]: /templates/embedded/ diff --git a/docs/content/en/functions/go-template/try.md b/docs/content/en/functions/go-template/try.md new file mode 100644 index 000000000..6aef4da36 --- /dev/null +++ b/docs/content/en/functions/go-template/try.md @@ -0,0 +1,111 @@ +--- +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 }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ 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 --git a/docs/content/en/functions/go-template/urlquery.md b/docs/content/en/functions/go-template/urlquery.md new file mode 100644 index 000000000..dc97f867e --- /dev/null +++ b/docs/content/en/functions/go-template/urlquery.md @@ -0,0 +1,27 @@ +--- +title: urlquery +description: Returns the escaped value of the textual representation of its arguments in a form suitable for embedding in a URL query. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: ['urlquery VALUE [VALUE...]'] +aliases: [/functions/urlquery] +--- + +This template code: + +```go-html-template +{{ $u := urlquery "https://" "example.com" | safeURL }} +<a href="https://example.org?url={{ $u }}">Link</a> +``` + +Is rendered to: + +```html +<a href="https://example.org?url=https%3A%2F%2Fexample.com">Link</a> +``` + +{{% include "/_common/functions/go-template/text-template.md" %}} diff --git a/docs/content/en/functions/go-template/with.md b/docs/content/en/functions/go-template/with.md new file mode 100644 index 000000000..c25ce3fba --- /dev/null +++ b/docs/content/en/functions/go-template/with.md @@ -0,0 +1,92 @@ +--- +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. + +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/ diff --git a/docs/content/en/functions/hash/FNV32a.md b/docs/content/en/functions/hash/FNV32a.md new file mode 100644 index 000000000..b108acff8 --- /dev/null +++ b/docs/content/en/functions/hash/FNV32a.md @@ -0,0 +1,16 @@ +--- +title: hash.FNV32a +description: Returns the 32-bit FNV (Fowler-Noll-Vo) non-cryptographic hash of the given string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: int + signatures: [hash.FNV32a STRING] +aliases: [/functions/crypto.fnv32a] +--- + +```go-html-template +{{ hash.FNV32a "Hello world" }} → 1498229191 +``` diff --git a/docs/content/en/functions/hash/XxHash.md b/docs/content/en/functions/hash/XxHash.md new file mode 100644 index 000000000..6a92b2bdc --- /dev/null +++ b/docs/content/en/functions/hash/XxHash.md @@ -0,0 +1,17 @@ +--- +title: hash.XxHash +description: Returns the 64-bit xxHash non-cryptographic hash of the given string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [xxhash] + returnType: string + signatures: [hash.XxHash STRING] +--- + +```go-html-template +{{ hash.XxHash "Hello world" }} → c500b0c912b376d8 +``` + +[xxHash](https://xxhash.com/) is a very fast non-cryptographic hash algorithm. Hugo uses [this Go implementation](https://github.com/cespare/xxhash). diff --git a/docs/content/en/functions/hash/_index.md b/docs/content/en/functions/hash/_index.md new file mode 100644 index 000000000..956f7fb8d --- /dev/null +++ b/docs/content/en/functions/hash/_index.md @@ -0,0 +1,7 @@ +--- +title: Hash functions +linkTitle: hash +description: Use these functions to create non-cryptographic hashes. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/hugo/BuildDate.md b/docs/content/en/functions/hugo/BuildDate.md new file mode 100644 index 000000000..a592283b9 --- /dev/null +++ b/docs/content/en/functions/hugo/BuildDate.md @@ -0,0 +1,19 @@ +--- +title: hugo.BuildDate +description: Returns the compile date of the Hugo binary. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [hugo.BuildDate] +--- + +The `hugo.BuildDate` function returns the compile date of the Hugo binary, formatted per [RFC 3339]. + +[RFC 3339]: https://datatracker.ietf.org/doc/html/rfc3339 + +```go-html-template +{{ hugo.BuildDate }} → 2023-11-01T17:57:00Z +``` diff --git a/docs/content/en/functions/hugo/CommitHash.md b/docs/content/en/functions/hugo/CommitHash.md new file mode 100644 index 000000000..324e985d1 --- /dev/null +++ b/docs/content/en/functions/hugo/CommitHash.md @@ -0,0 +1,15 @@ +--- +title: hugo.CommitHash +description: Returns the Git commit hash of the Hugo binary. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [hugo.CommitHash] +--- + +```go-html-template +{{ hugo.CommitHash }} → a4892a07b41b7b3f1f143140ee4ec0a9a5cf3970 +``` diff --git a/docs/content/en/functions/hugo/Deps.md b/docs/content/en/functions/hugo/Deps.md new file mode 100644 index 000000000..9d8667ee5 --- /dev/null +++ b/docs/content/en/functions/hugo/Deps.md @@ -0,0 +1,66 @@ +--- +title: hugo.Deps +description: Returns a slice of project dependencies, either Hugo Modules or local theme components. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: '[]hugo.Dependency' + signatures: [hugo.Deps] +--- + +The `hugo.Deps` function returns a slice of project dependencies, either Hugo Modules or local theme components. Each dependency contains: + +Owner +: (`hugo.Dependency`) In the dependency tree, this is the first module that defines this module as a dependency (e.g., `github.com/gohugoio/hugo-mod-bootstrap-scss/v5`). + +Path +: (`string`) The module path or the path below your `themes` directory (e.g., `github.com/gohugoio/hugo-mod-jslibs-dist/popperjs/v2`). + +Replace +: (`hugo.Dependency`) Replaced by this dependency. + +Time +: (`time.Time`) The time that the version was created (e.g., `2022-02-13 15:11:28 +0000 UTC`). + +Vendor +: (`bool`) Reports whether the dependency is vendored. + +Version +: (`string`) The module version (e.g., `v2.21100.20000`). + +An example table listing the dependencies: + +```go-html-template +<h2>Dependencies</h2> +<table class="table table-dark"> + <thead> + <tr> + <th scope="col">#</th> + <th scope="col">Owner</th> + <th scope="col">Path</th> + <th scope="col">Version</th> + <th scope="col">Time</th> + <th scope="col">Vendor</th> + </tr> + </thead> + <tbody> + {{ range $index, $element := hugo.Deps }} + <tr> + <th scope="row">{{ add $index 1 }}</th> + <td>{{ with $element.Owner }}{{ .Path }}{{ end }}</td> + <td> + {{ $element.Path }} + {{ with $element.Replace }} + => {{ .Path }} + {{ end }} + </td> + <td>{{ $element.Version }}</td> + <td>{{ with $element.Time }}{{ . }}{{ end }}</td> + <td>{{ $element.Vendor }}</td> + </tr> + {{ end }} + </tbody> +</table> +``` diff --git a/docs/content/en/functions/hugo/Environment.md b/docs/content/en/functions/hugo/Environment.md new file mode 100644 index 000000000..551306255 --- /dev/null +++ b/docs/content/en/functions/hugo/Environment.md @@ -0,0 +1,26 @@ +--- +title: hugo.Environment +description: Returns the current running environment. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [hugo.Environment] +--- + +The `hugo.Environment` function returns the current running [environment](g) as defined through the `--environment` command line flag. + +```go-html-template +{{ hugo.Environment }} → production +``` + +Command line examples: + +Command|Environment +:--|:-- +`hugo`|`production` +`hugo --environment staging`|`staging` +`hugo server`|`development` +`hugo server --environment staging`|`staging` diff --git a/docs/content/en/functions/hugo/Generator.md b/docs/content/en/functions/hugo/Generator.md new file mode 100644 index 000000000..dc72a7af2 --- /dev/null +++ b/docs/content/en/functions/hugo/Generator.md @@ -0,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 }} → <meta name="generator" content="Hugo 0.144.2"> +``` diff --git a/docs/content/en/functions/hugo/GoVersion.md b/docs/content/en/functions/hugo/GoVersion.md new file mode 100644 index 000000000..94e310deb --- /dev/null +++ b/docs/content/en/functions/hugo/GoVersion.md @@ -0,0 +1,15 @@ +--- +title: hugo.GoVersion +description: Returns the Go version used to compile the Hugo binary +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [hugo.GoVersion] +--- + +```go-html-template +{{ hugo.GoVersion }} → go1.21.1 +``` diff --git a/docs/content/en/functions/hugo/IsDevelopment.md b/docs/content/en/functions/hugo/IsDevelopment.md new file mode 100644 index 000000000..cea923acd --- /dev/null +++ b/docs/content/en/functions/hugo/IsDevelopment.md @@ -0,0 +1,17 @@ +--- +title: hugo.IsDevelopment +description: Reports whether the current running environment is "development". +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [hugo.IsDevelopment] +--- + +{{< new-in 0.120.0 />}} + +```go-html-template +{{ hugo.IsDevelopment }} → true/false +``` diff --git a/docs/content/en/functions/hugo/IsExtended.md b/docs/content/en/functions/hugo/IsExtended.md new file mode 100644 index 000000000..ab7e0f7b1 --- /dev/null +++ b/docs/content/en/functions/hugo/IsExtended.md @@ -0,0 +1,15 @@ +--- +title: hugo.IsExtended +description: Reports whether the Hugo binary is either the extended or extended/deploy edition. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [hugo.IsExtended] +--- + +```go-html-template +{{ hugo.IsExtended }} → true/false +``` diff --git a/docs/content/en/functions/hugo/IsMultihost.md b/docs/content/en/functions/hugo/IsMultihost.md new file mode 100644 index 000000000..605afa79a --- /dev/null +++ b/docs/content/en/functions/hugo/IsMultihost.md @@ -0,0 +1,39 @@ +--- +title: hugo.IsMultihost +description: Reports whether each configured language has a unique base URL. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [hugo.IsMultihost] +--- + +{{< new-in 0.124.0 />}} + +Site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = true +[languages] + [languages.de] + baseURL = 'https://de.example.org/' + languageCode = 'de-DE' + languageName = 'Deutsch' + title = 'Projekt Dokumentation' + weight = 1 + [languages.en] + baseURL = 'https://en.example.org/' + languageCode = 'en-US' + languageName = 'English' + title = 'Project Documentation' + weight = 2 +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ hugo.IsMultihost }} → true +``` diff --git a/docs/content/en/functions/hugo/IsMultilingual.md b/docs/content/en/functions/hugo/IsMultilingual.md new file mode 100644 index 000000000..85fc6550f --- /dev/null +++ b/docs/content/en/functions/hugo/IsMultilingual.md @@ -0,0 +1,37 @@ +--- +title: hugo.IsMultilingual +description: Reports whether there are two or more configured languages. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [hugo.IsMultilingual] +--- + +{{< new-in 0.124.0 />}} + +Site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = true +[languages] + [languages.de] + languageCode = 'de-DE' + languageName = 'Deutsch' + title = 'Projekt Dokumentation' + weight = 1 + [languages.en] + languageCode = 'en-US' + languageName = 'English' + title = 'Project Documentation' + weight = 2 +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ hugo.IsMultilingual }} → true +``` diff --git a/docs/content/en/functions/hugo/IsProduction.md b/docs/content/en/functions/hugo/IsProduction.md new file mode 100644 index 000000000..e5433c239 --- /dev/null +++ b/docs/content/en/functions/hugo/IsProduction.md @@ -0,0 +1,15 @@ +--- +title: hugo.IsProduction +description: Reports whether the current running environment is "production". +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [hugo.IsProduction] +--- + +```go-html-template +{{ hugo.IsProduction }} → true/false +``` diff --git a/docs/content/en/functions/hugo/IsServer.md b/docs/content/en/functions/hugo/IsServer.md new file mode 100644 index 000000000..840ff060d --- /dev/null +++ b/docs/content/en/functions/hugo/IsServer.md @@ -0,0 +1,17 @@ +--- +title: hugo.IsServer +description: Reports whether the built-in development server is running. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [hugo.IsServer] +--- + +{{< new-in 0.120.0 />}} + +```go-html-template +{{ hugo.IsServer }} → true/false +``` diff --git a/docs/content/en/functions/hugo/Store.md b/docs/content/en/functions/hugo/Store.md new file mode 100644 index 000000000..08c684146 --- /dev/null +++ b/docs/content/en/functions/hugo/Store.md @@ -0,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. + +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 --git a/docs/content/en/functions/hugo/Version.md b/docs/content/en/functions/hugo/Version.md new file mode 100644 index 000000000..7925af981 --- /dev/null +++ b/docs/content/en/functions/hugo/Version.md @@ -0,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.144.2 +``` diff --git a/docs/content/en/functions/hugo/WorkingDir.md b/docs/content/en/functions/hugo/WorkingDir.md new file mode 100644 index 000000000..e50102558 --- /dev/null +++ b/docs/content/en/functions/hugo/WorkingDir.md @@ -0,0 +1,15 @@ +--- +title: hugo.WorkingDir +description: Returns the project working directory. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [hugo.WorkingDir] +--- + +```go-html-template +{{ hugo.WorkingDir }} → /home/user/projects/my-hugo-site +``` diff --git a/docs/content/en/functions/hugo/_index.md b/docs/content/en/functions/hugo/_index.md new file mode 100644 index 000000000..b1c9216c4 --- /dev/null +++ b/docs/content/en/functions/hugo/_index.md @@ -0,0 +1,7 @@ +--- +title: Hugo functions +linkTitle: hugo +description: Use these functions to access information about the Hugo application and the current environment. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/images/AutoOrient.md b/docs/content/en/functions/images/AutoOrient.md new file mode 100644 index 000000000..fd8d2ed14 --- /dev/null +++ b/docs/content/en/functions/images/AutoOrient.md @@ -0,0 +1,48 @@ +--- +title: images.AutoOrient +description: Returns an image filter that rotates and flips an image as needed per its EXIF orientation tag. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.AutoOrient] +--- + +{{< new-in 0.121.2 />}} + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.AutoOrient }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +> [!note] +> When using with other filters, specify `images.AutoOrient` first. + +```go-html-template +{{ $filters := slice + images.AutoOrient + (images.Process "resize 200x") +}} +{{ with resources.Get "images/original.jpg" }} + {{ with images.Filter $filters . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +## Example + +{{< img + src="images/examples/landscape-exif-orientation-5.jpg" + alt="Zion National Park" + filter="AutoOrient" + filterArgs="" + example=true +>}} diff --git a/docs/content/en/functions/images/Brightness.md b/docs/content/en/functions/images/Brightness.md new file mode 100644 index 000000000..0ddfcba55 --- /dev/null +++ b/docs/content/en/functions/images/Brightness.md @@ -0,0 +1,33 @@ +--- +title: images.Brightness +description: Returns an image filter that changes the brightness of an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Brightness PERCENTAGE] +--- + +The percentage must be in the range [-100, 100] where 0 has no effect. A value of `-100` produces a solid black image, and a value of `100` produces a solid white image. + +## Usage + +Create the image filter: + +```go-html-template +{{ $filter := images.Brightness 12 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Brightness" + filterArgs="12" + example=true +>}} diff --git a/docs/content/en/functions/images/ColorBalance.md b/docs/content/en/functions/images/ColorBalance.md new file mode 100644 index 000000000..be4a2bce8 --- /dev/null +++ b/docs/content/en/functions/images/ColorBalance.md @@ -0,0 +1,33 @@ +--- +title: images.ColorBalance +description: Returns an image filter that changes the color balance of an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.ColorBalance PCTRED PCTGREEN PCTBLUE] +--- + +The percentage for each channel (red, green, blue) must be in the range [-100, 500]. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.ColorBalance -10 10 50 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="ColorBalance" + filterArgs="-10,10,50" + example=true +>}} diff --git a/docs/content/en/functions/images/Colorize.md b/docs/content/en/functions/images/Colorize.md new file mode 100644 index 000000000..6b8cd5966 --- /dev/null +++ b/docs/content/en/functions/images/Colorize.md @@ -0,0 +1,37 @@ +--- +title: images.Colorize +description: Returns an image filter that produces a colorized version of an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Colorize HUE SATURATION PERCENTAGE] +--- + +The hue is the angle on the color wheel, typically in the range [0, 360]. + +The saturation must be in the range [0, 100]. + +The percentage specifies the strength of the effect, and must be in the range [0, 100]. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Colorize 180 50 20 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Colorize" + filterArgs="180,50,20" + example=true +>}} diff --git a/docs/content/en/functions/images/Config.md b/docs/content/en/functions/images/Config.md new file mode 100644 index 000000000..59242fb95 --- /dev/null +++ b/docs/content/en/functions/images/Config.md @@ -0,0 +1,30 @@ +--- +title: images.Config +description: Returns an image.Config structure from the image at the specified path, relative to the working directory. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: image.Config + signatures: [images.Config PATH] +aliases: [/functions/imageconfig] +--- + +See [image processing] for an overview of Hugo's image pipeline. + +```go-html-template +{{ $ic := images.Config "/static/images/a.jpg" }} + +{{ $ic.Width }} → 600 (int) +{{ $ic.Height }} → 400 (int) +``` + +Supported image formats include GIF, JPEG, PNG, TIFF, and WebP. + +> [!note] +> This is a legacy function, superseded by the [`Width`] and [`Height`] methods for [global resources](g), [page resources](g), and [remote resources](g). See the [image processing] section for details. + +[`Height`]: /methods/resource/height/ +[`Width`]: /methods/resource/width/ +[image processing]: /content-management/image-processing/ diff --git a/docs/content/en/functions/images/Contrast.md b/docs/content/en/functions/images/Contrast.md new file mode 100644 index 000000000..f5d607440 --- /dev/null +++ b/docs/content/en/functions/images/Contrast.md @@ -0,0 +1,33 @@ +--- +title: images.Contrast +description: Returns an image filter that changes the contrast of an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Contrast PERCENTAGE] +--- + +The percentage must be in the range [-100, 100] where 0 has no effect. A value of `-100` produces a solid grey image, and a value of `100` produces an over-contrasted image. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Contrast -20 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Contrast" + filterArgs="-20" + example=true +>}} diff --git a/docs/content/en/functions/images/Dither.md b/docs/content/en/functions/images/Dither.md new file mode 100644 index 000000000..eab7743f7 --- /dev/null +++ b/docs/content/en/functions/images/Dither.md @@ -0,0 +1,156 @@ +--- +title: images.Dither +description: Returns an image filter that dithers an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: ['images.Dither [OPTIONS]'] +--- + +{{< new-in 0.123.0 />}} + +## Options + +colors +: (`string array`) A slice of two or more colors that make up the dithering palette, each expressed as an RGB or RGBA [hexadecimal] value, with or without a leading hash mark. The default values are opaque black (`000000ff`) and opaque white (`ffffffff`). + +[hexadecimal]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color + +method +: (`string`) The dithering method. See the [dithering methods](#dithering-methods) section below for a list of the available methods. Default is `FloydSteinberg`. + +serpentine +: (`bool`) Applicable to error diffusion dithering methods, whether to apply the error diffusion matrix in a serpentine manner, meaning that it goes right-to-left every other line. This greatly reduces line-type artifacts. Default is `true`. + +strength +: (`float`) The strength at which to apply the dithering matrix, typically a value in the range [0, 1]. A value of `1.0` applies the dithering matrix at 100% strength (no modification of the dither matrix). The `strength` is inversely proportional to contrast; reducing the strength increases the contrast. Setting `strength` to a value such as `0.8` can be useful to reduce noise in the dithered image. Default is `1.0`. + +## Usage + +Create the options map: + +```go-html-template +{{ $opts := dict + "colors" (slice "222222" "808080" "dddddd") + "method" "ClusteredDot4x4" + "strength" 0.85 +}} +``` + +Create the filter: + +```go-html-template +{{ $filter := images.Dither $opts }} +``` + +Or create the filter using the default settings: + +```go-html-template +{{ $filter := images.Dither }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Dithering methods + +See the [Go documentation] for descriptions of each of the dithering methods below. + +[Go documentation]: https://pkg.go.dev/github.com/makeworld-the-better-one/dither/v2#pkg-variables + +Error diffusion dithering methods: + +- Atkinson +- Burkes +- FalseFloydSteinberg +- FloydSteinberg +- JarvisJudiceNinke +- Sierra +- Sierra2 +- Sierra2_4A +- Sierra3 +- SierraLite +- Simple2D +- StevenPigeon +- Stucki +- TwoRowSierra + +Ordered dithering methods: + +- ClusteredDot4x4 +- ClusteredDot6x6 +- ClusteredDot6x6_2 +- ClusteredDot6x6_3 +- ClusteredDot8x8 +- ClusteredDotDiagonal16x16 +- ClusteredDotDiagonal6x6 +- ClusteredDotDiagonal8x8 +- ClusteredDotDiagonal8x8_2 +- ClusteredDotDiagonal8x8_3 +- ClusteredDotHorizontalLine +- ClusteredDotSpiral5x5 +- ClusteredDotVerticalLine +- Horizontal3x5 +- Vertical5x3 + +## Example + +This example uses the default dithering options. + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Dither" + filterArgs="" + example=true +>}} + +## Recommendations + +Regardless of dithering method, do both of the following to obtain the best results: + +1. Scale the image _before_ dithering +1. Output the image to a lossless format such as GIF or PNG + +The example below does both of these, and it sets the dithering palette to the three most dominant colors in the image. + +```go-html-template +{{ with resources.Get "original.jpg" }} + {{ $opts := dict + "method" "ClusteredDotSpiral5x5" + "colors" (first 3 .Colors) + }} + {{ $filters := slice + (images.Process "resize 800x") + (images.Dither $opts) + (images.Process "png") + }} + {{ with . | images.Filter $filters }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +For best results, if the dithering palette is grayscale, convert the image to grayscale before dithering. + +```go-html-template +{{ $opts := dict "colors" (slice "222" "808080" "ddd") }} +{{ $filters := slice + (images.Process "resize 800x") + (images.Grayscale) + (images.Dither $opts) + (images.Process "png") +}} +{{ with images.Filter $filters . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +The example above: + +1. Resizes the image to be 800 px wide +1. Converts the image to grayscale +1. Dithers the image using the default (`FloydSteinberg`) dithering method with a grayscale palette +1. Converts the image to the PNG format diff --git a/docs/content/en/functions/images/Filter.md b/docs/content/en/functions/images/Filter.md new file mode 100644 index 000000000..1f2c268be --- /dev/null +++ b/docs/content/en/functions/images/Filter.md @@ -0,0 +1,65 @@ +--- +title: images.Filter +description: Applies one or more image filters to the given image resource. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.ImageResource + signatures: [images.Filter FILTERS... IMAGE] +--- + +Apply one or more [image filters](#image-filters) to the given image. + +To apply a single filter: + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with images.Filter images.Grayscale . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +To apply two or more filters, executing from left to right: + +```go-html-template +{{ $filters := slice + images.Grayscale + (images.GaussianBlur 8) +}} +{{ with resources.Get "images/original.jpg" }} + {{ with images.Filter $filters . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +You can also apply image filters using the [`Filter`] method on a `Resource` object. + +[`Filter`]: /methods/resource/filter/ + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with images.Filter images.Grayscale . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Grayscale" + filterArgs="" + example=true +>}} + +## Image filters + +Use any of these filters with the `images.Filter` function, or with the `Filter` method on a `Resource` object. + +{{% list-pages-in-section path=/functions/images filter=functions_images_no_filters filterType=exclude %}} diff --git a/docs/content/en/functions/images/Gamma.md b/docs/content/en/functions/images/Gamma.md new file mode 100644 index 000000000..d8cb076f1 --- /dev/null +++ b/docs/content/en/functions/images/Gamma.md @@ -0,0 +1,33 @@ +--- +title: images.Gamma +description: Returns an image filter that performs gamma correction on an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Gamma GAMMA] +--- + +The gamma value must be positive. A value greater than 1 lightens the image, while a value less than 1 darkens the image. The filter has no effect when the gamma value is 1. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Gamma 1.667 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Gamma" + filterArgs="1.667" + example=true +>}} diff --git a/docs/content/en/functions/images/GaussianBlur.md b/docs/content/en/functions/images/GaussianBlur.md new file mode 100644 index 000000000..c5eb136e2 --- /dev/null +++ b/docs/content/en/functions/images/GaussianBlur.md @@ -0,0 +1,33 @@ +--- +title: images.GaussianBlur +description: Returns an image filter that applies a gaussian blur to an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.GaussianBlur SIGMA] +--- + +The sigma value must be positive, and indicates how much the image will be blurred. The blur-affected radius is approximately 3 times the sigma value. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.GaussianBlur 5 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="GaussianBlur" + filterArgs="5" + example=true +>}} diff --git a/docs/content/en/functions/images/Grayscale.md b/docs/content/en/functions/images/Grayscale.md new file mode 100644 index 000000000..d3651b8dc --- /dev/null +++ b/docs/content/en/functions/images/Grayscale.md @@ -0,0 +1,31 @@ +--- +title: images.Grayscale +description: Returns an image filter that produces a grayscale version of an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Grayscale] +--- + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Grayscale }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Grayscale" + filterArgs="" + example=true +>}} diff --git a/docs/content/en/functions/images/Hue.md b/docs/content/en/functions/images/Hue.md new file mode 100644 index 000000000..f334eebd8 --- /dev/null +++ b/docs/content/en/functions/images/Hue.md @@ -0,0 +1,33 @@ +--- +title: images.Hue +description: Returns an image filter that rotates the hue of an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Hue SHIFT] +--- + +The hue angle shift is typically in the range [-180, 180] where 0 has no effect. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Hue -15 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Hue" + filterArgs="-15" + example=true +>}} diff --git a/docs/content/en/functions/images/Invert.md b/docs/content/en/functions/images/Invert.md new file mode 100644 index 000000000..0f9f9a9d2 --- /dev/null +++ b/docs/content/en/functions/images/Invert.md @@ -0,0 +1,31 @@ +--- +title: images.Invert +description: Returns an image filter that negates the colors of an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Invert] +--- + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Invert }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Invert" + filterArgs="" + example=true +>}} diff --git a/docs/content/en/functions/images/Mask.md b/docs/content/en/functions/images/Mask.md new file mode 100644 index 000000000..4f3b4aa3f --- /dev/null +++ b/docs/content/en/functions/images/Mask.md @@ -0,0 +1,75 @@ +--- +title: images.Mask +description: Returns an image filter that applies a mask to the source image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Mask RESOURCE] +--- + +{{< new-in 0.141.0 />}} + +The `images.Mask` filter applies a mask to an image. Black pixels in the mask make the corresponding areas of the base image transparent, while white pixels keep them opaque. Color images are converted to grayscale for masking purposes. The mask is automatically resized to match the dimensions of the base image. + +> [!note] +> Of the formats supported by Hugo's imaging pipeline, only PNG and WebP have an alpha channel to support transparency. If your source image has a different format and you require transparent masked areas, convert it to either PNG or WebP as shown in the example below. + +When applying a mask to a non-transparent image format such as JPEG, the masked areas will be filled with the color specified by the `bgColor` parameter in your [site configuration]. You can override that color with a `Process` image filter: + +```go-html-template +{{ $filter := images.Process "#00ff00" }} +``` + +## Usage + +Create a slice of filters, one for WebP conversion and the other for mask application: + +```go-html-template +{{ $filter1 := images.Process "webp" }} +{{ $filter2 := images.Mask (resources.Get "images/mask.png") }} +{{ $filters := slice $filter1 $filter2 }} +``` + +Apply the filters using the [`images.Filter`] function: + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with . | images.Filter $filters }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +You can also apply the filter using the [`Filter`] method on a 'Resource' object: + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Filter $filters }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +## Example + +Mask + +{{< img + src="images/examples/mask.png" + example=false +>}} + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="mask" + filterArgs="images/examples/mask.png" + example=true +>}} + +[`Filter`]: /methods/resource/filter/ +[`images.Filter`]: /functions/images/filter/ +[site configuration]: /configuration/imaging/ diff --git a/docs/content/en/functions/images/Opacity.md b/docs/content/en/functions/images/Opacity.md new file mode 100644 index 000000000..b9dcf3fd2 --- /dev/null +++ b/docs/content/en/functions/images/Opacity.md @@ -0,0 +1,49 @@ +--- +title: images.Opacity +description: Returns an image filter that changes the opacity of an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Opacity OPACITY] +--- + +{{< new-in 0.119.0 />}} + +The opacity value must be in the range [0, 1]. A value of `0` produces a transparent image, and a value of `1` produces an opaque image (no transparency). + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Opacity 0.65 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +The `images.Opacity` filter is most useful for target formats such as PNG and WebP that support transparency. If the source image does not support transparency, combine this filter with the `images.Process` filter: + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ $filters := slice + (images.Opacity 0.65) + (images.Process "png") + }} + {{ with . | images.Filter $filters }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Opacity" + filterArgs="0.65" + example=true +>}} diff --git a/docs/content/en/functions/images/Overlay.md b/docs/content/en/functions/images/Overlay.md new file mode 100644 index 000000000..8e5eec3d1 --- /dev/null +++ b/docs/content/en/functions/images/Overlay.md @@ -0,0 +1,45 @@ +--- +title: images.Overlay +description: Returns an image filter that overlays the source image at the given coordinates, relative to the upper left corner. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Overlay RESOURCE X Y] +--- + +## Usage + +Capture the overlay image as a resource: + +```go-html-template +{{ $overlay := "" }} +{{ $path := "images/logo.png" }} +{{ with resources.Get $path }} + {{ $overlay = . }} +{{ else }} + {{ errorf "Unable to get resource %q" $path }} +{{ end }} +``` + +The overlay image can be a [global resource](g), a [page resource](g), or a [remote resource](g). + +Create the filter: + +```go-html-template +{{ $filter := images.Overlay $overlay 20 20 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Overlay" + filterArgs="images/logos/logo-64x64.png,20,20" + example=true +>}} diff --git a/docs/content/en/functions/images/Padding.md b/docs/content/en/functions/images/Padding.md new file mode 100644 index 000000000..da15a44ca --- /dev/null +++ b/docs/content/en/functions/images/Padding.md @@ -0,0 +1,72 @@ +--- +title: images.Padding +description: Returns an image filter that resizes the image canvas without resizing the image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: ['images.Padding V1 [V2] [V3] [V4] [COLOR]'] +--- + +{{< new-in 0.120.0 />}} + +The last argument is the canvas color, expressed as an RGB or RGBA [hexadecimal color]. The default value is `ffffffff` (opaque white). The preceding arguments are the padding values, in pixels, using the CSS [shorthand property] syntax. Negative padding values will crop the image. + +[hexadecimal color]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color +[shorthand property]: https://developer.mozilla.org/en-US/docs/Web/CSS/Shorthand_properties#edges_of_a_box + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Padding 20 40 "#976941" }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +Combine with the [`Colors`] method to create a border with one of the image's most dominant colors: + +[`Colors`]: /methods/resource/colors/ + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ $filter := images.Padding 20 40 (index .Colors 2) }} + {{ with . | images.Filter $filter }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Padding" + filterArgs="20,40,20,40,#976941" + example=true +>}} + +## Other recipes + +This example resizes an image to 300px wide, converts it to the WebP format, adds 20px vertical padding and 50px horizontal padding, then sets the canvas color to dark green with 33% opacity. + +Conversion to WebP is required to support transparency. PNG and WebP images have an alpha channel; JPEG and GIF do not. + +```go-html-template +{{ $img := resources.Get "images/a.jpg" }} +{{ $filters := slice + (images.Process "resize 300x webp") + (images.Padding 20 50 "#0705") +}} +{{ $img = $img.Filter $filters }} +``` + +To add a 2px gray border to an image: + +```go-html-template +{{ $img = $img.Filter (images.Padding 2 "#777") }} +``` diff --git a/docs/content/en/functions/images/Pixelate.md b/docs/content/en/functions/images/Pixelate.md new file mode 100644 index 000000000..954950c8b --- /dev/null +++ b/docs/content/en/functions/images/Pixelate.md @@ -0,0 +1,31 @@ +--- +title: images.Pixelate +description: Returns an image filter that applies a pixelation effect to an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Pixelate SIZE] +--- + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Pixelate 4 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Pixelate" + filterArgs="4" + example=true +>}} diff --git a/docs/content/en/functions/images/Process.md b/docs/content/en/functions/images/Process.md new file mode 100644 index 000000000..134c40c5a --- /dev/null +++ b/docs/content/en/functions/images/Process.md @@ -0,0 +1,110 @@ +--- +title: images.Process +description: Returns an image filter that processes the given image using the given specification. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Process SPEC] +--- + +{{< new-in 0.119.0 />}} + +This filter has the same options as the [`Process`] method on a `Resource` object, but using it as a filter may be more effective if you need to apply multiple filters to an image. + +[`Process`]: /methods/resource/process/ + +The process specification is a space-delimited, case-insensitive list of one or more of the following in any sequence: + +action +: Specify zero or one of `crop`, `fill`, `fit`, or `resize`. If you specify an action you must also provide dimensions. See [details](content-management/image-processing/#image-processing-methods). + +```go-html-template +{{ $filter := images.Process "resize 300x" }} +``` + +dimensions +: Required if you specify an action. Provide width _or_ height when using `resize`, else provide both width _and_ height. See [details](/content-management/image-processing/#dimensions). + +```go-html-template +{{ $filter := images.Process "crop 200x200" }} +``` + +anchor +: Use with the `crop` or `fill` action. Specify zero or one of `TopLeft`, `Top`, `TopRight`, `Left`, `Center`, `Right`, `BottomLeft`, `Bottom`, `BottomRight`, or `Smart`. Default is `Smart`. See [details](/content-management/image-processing/#anchor). + +```go-html-template +{{ $filter := images.Process "crop 200x200 center" }} +``` + +rotation +: Typically specify zero or one of `r90`, `r180`, or `r270`. Also supports arbitrary rotation angles. See [details](/content-management/image-processing/#rotation). + +```go-html-template +{{ $filter := images.Process "r90" }} +{{ $filter := images.Process "crop 200x200 center r90" }} +``` + +target format +: Specify zero or one of `gif`, `jpeg`, `png`, `tiff`, or `webp`. See [details](/content-management/image-processing/#target-format). + +```go-html-template +{{ $filter := images.Process "webp" }} +{{ $filter := images.Process "crop 200x200 center r90 webp" }} +``` + +quality +: Applicable to JPEG and WebP images. Optionally specify `qN` where `N` is an integer in the range [0, 100]. Default is `75`. See [details](/content-management/image-processing/#quality). + +```go-html-template +{{ $filter := images.Process "q50" }} +{{ $filter := images.Process "crop 200x200 center r90 webp q50" }} +``` + +hint +: Applicable to WebP images and equivalent to the `-preset` flag for the [`cwebp`] encoder. Specify zero or one of `drawing`, `icon`, `photo`, `picture`, or `text`. Default is `photo`. See [details](/content-management/image-processing/#hint). + +[`cwebp`]: https://developers.google.com/speed/webp/docs/cwebp + +```go-html-template +{{ $filter := images.Process "webp" "icon" }} +{{ $filter := images.Process "crop 200x200 center r90 webp q50 icon" }} +``` + +background color +: When converting a PNG or WebP with transparency to a format that does not support transparency, optionally specify a background color using a 3-digit or a 6-digit hexadecimal color code. Default is `#ffffff` (white). See [details](/content-management/image-processing/#background-color). + +```go-html-template +{{ $filter := images.Process "jpeg #000" }} +{{ $filter := images.Process "crop 200x200 center r90 q50 jpeg #000" }} +``` + +resampling filter +: Typically specify zero or one of `Box`, `Lanczos`, `CatmullRom`, `MitchellNetravali`, `Linear`, or `NearestNeighbor`. Other resampling filters are available. See [details](/content-management/image-processing/#resampling-filter). + +```go-html-template +{{ $filter := images.Process "resize 300x lanczos" }} +{{ $filter := images.Process "resize 300x r90 q50 jpeg #000 lanczos" }} +``` + +## Usage + +Create a filter: + +```go-html-template +{{ $filter := images.Process "resize 256x q40 webp" }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="resize 256x q40 webp" + example=true +>}} diff --git a/docs/content/en/functions/images/QR.md b/docs/content/en/functions/images/QR.md new file mode 100644 index 000000000..eee2dff14 --- /dev/null +++ b/docs/content/en/functions/images/QR.md @@ -0,0 +1,138 @@ +--- +title: images.QR +description: Encodes the given text into a QR code using the specified options, returning an image resource. +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.ImageResource + signatures: ['images.QR TEXT [OPTIONS]'] +--- + +{{< new-in 0.141.0 />}} + +The `images.QR` function encodes the given text into a [QR code] using the specified options, returning an image resource. The size of the generated image depends on three factors: + +- Data length: Longer text necessitates a larger image to accommodate the increased information density. +- Error correction level: Higher error correction levels enhance the QR code's resistance to damage, but this typically results in a slightly larger image size to maintain readability. +- Pixels per module: The number of image pixels assigned to each individual module (the smallest unit of the QR code) directly impacts the overall image size. A higher pixel count per module leads to a larger, higher-resolution image. + +Although the default option values are sufficient for most applications, you should test the rendered QR code both on-screen and in print. + +## Options + +level +: (`string`) The error correction level to use when encoding the text, one of `low`, `medium`, `quartile`, or `high`. Default is `medium`. + + Error correction level|Redundancy + :--|:--|:-- + low|20% + medium|38% + quartile|55% + high|65% + +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. Use Unix-style slashes (`/`) to separarate path segments. If empty or not provided, the image is placed directly in the `publishDir` root. Hugo automatically creates the necessary subdirectories if they don't exist. + +## Examples + +To create a QR code using the default values for `level` and `scale`: + +```go-html-template +{{ $text := "https://gohugo.io" }} +{{ with images.QR $text }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +{{< qr text="https://gohugo.io" class="qrcode" targetDir="images/qr" />}} + +Specify `level`, `scale`, and `targetDir` as needed to achieve the desired result: + +```go-html-template +{{ $text := "https://gohugo.io" }} +{{ $opts := dict + "level" "high" + "scale" 3 + "targetDir" "images/qr" +}} +{{ with images.QR $text $opts }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +{{< qr text="https://gohugo.io" level="high" scale=3 targetDir="codes" class="qrcode" targetDir="images/qr" />}} + +To include a QR code that points to the `Permalink` of the current page: + +```go-html-template {file="layouts/_default/single.html"} +{{ with images.QR .Permalink }} + <img + src="{{ .RelPermalink }}" + width="{{ .Width }}" + height="{{ .Height }}" + alt="QR code linking to {{ $.Permalink }}" + class="qr-code" + loading="lazy" + > +{{ end }} +``` + +Then hide the QR code with CSS unless printing the page: + +```css +/* Hide QR code by default */ +.qr-code { + display: none; +} + +/* Show QR code when printing */ +@media print { + .qr-code { + display: block; + } +} +``` + +## Scale + +As you decrease the size of a QR code, the maximum distance at which it can be reliably scanned by a device also decreases. + +In the example above, we set the `scale` to `2`, resulting in a QR code where each module consists of 2x2 pixels. While this might be sufficient for on-screen display, it's likely to be problematic when printed at 600 dpi. + +\[ \frac{2\:px}{module} \times \frac{1\:inch}{600\:px} \times \frac{25.4\:mm}{1\:inch} = \frac{0.085\:mm}{module} \] + +This module size is half of the commonly recommended minimum of 0.170 mm.\ +If the QR code will be printed, use the default `scale` value of `4` pixels per module. + +Avoid using Hugo's image processing methods to resize QR codes. Resizing can introduce blurring due to anti-aliasing when a QR code module occupies a fractional number of pixels. + +> [!note] +> Always test the rendered QR code both on-screen and in print. + +## Shortcode + +Call the `qr` shortcode to insert a QR code into your content. + +Use the self-closing syntax to pass the text as an argument: + +```text +{{</* qr text="https://gohugo.io" /*/>}} +``` + +Or insert the text between the opening and closing tags: + +```text +{{</* qr */>}} +https://gohugo.io +{{</* /qr */>}} +``` + +The `qr` shortcode accepts several arguments including `level` and `scale`. See the [related documentation] for details. + +[`publishDir`]: /configuration/all/#publishdir +[QR code]: https://en.wikipedia.org/wiki/QR_code +[related documentation]: /shortcodes/qr/ diff --git a/docs/content/en/functions/images/Saturation.md b/docs/content/en/functions/images/Saturation.md new file mode 100644 index 000000000..d1dd48b24 --- /dev/null +++ b/docs/content/en/functions/images/Saturation.md @@ -0,0 +1,33 @@ +--- +title: images.Saturation +description: Returns an image filter that changes the saturation of an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Saturation PERCENTAGE] +--- + +The percentage must be in the range [-100, 500] where 0 has no effect. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Saturation 65 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Saturation" + filterArgs="65" + example=true +>}} diff --git a/docs/content/en/functions/images/Sepia.md b/docs/content/en/functions/images/Sepia.md new file mode 100644 index 000000000..ae43045db --- /dev/null +++ b/docs/content/en/functions/images/Sepia.md @@ -0,0 +1,33 @@ +--- +title: images.Sepia +description: Returns an image filter that produces a sepia-toned version of an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Sepia PERCENTAGE] +--- + +The percentage must be in the range [0, 100] where 0 has no effect. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Sepia 75 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Sepia" + filterArgs="75" + example=true +>}} diff --git a/docs/content/en/functions/images/Sigmoid.md b/docs/content/en/functions/images/Sigmoid.md new file mode 100644 index 000000000..9bfcaf91b --- /dev/null +++ b/docs/content/en/functions/images/Sigmoid.md @@ -0,0 +1,37 @@ +--- +title: images.Sigmoid +description: Returns an image filter that changes the contrast of an image using a sigmoidal function. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.Sigmoid MIDPOINT FACTOR] +--- + +This is a non-linear contrast change useful for photo adjustments; it preserves highlight and shadow detail. + +The midpoint is the midpoint of contrast. It must be in the range [0, 1], typically 0.5. + +The factor indicates how much to increase or decrease the contrast, typically in the range [-10, 10] where 0 has no effect. A positive value increases contrast, while a negative value decrease contrast. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.Sigmoid 0.6 -4 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Sigmoid" + filterArgs="0.6,-4" + example=true +>}} diff --git a/docs/content/en/functions/images/Text.md b/docs/content/en/functions/images/Text.md new file mode 100644 index 000000000..94cdb4e9d --- /dev/null +++ b/docs/content/en/functions/images/Text.md @@ -0,0 +1,118 @@ +--- +title: images.Text +description: Returns an image filter that adds text to an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: ['images.Text TEXT [OPTIONS]'] +--- + +## Options + +Although none of the options are required, at a minimum you will want to set the `size` to be some reasonable percentage of the image height. + +alignx +: {{< new-in 0.141.0 />}} +: (`string`) The horizontal alignment of the text relative to the horizontal offset, one of `left`, `center`, or `right`. Default is `left`. + +color +: (`string`) The font color, either a 3-digit or 6-digit hexadecimal color code. Default is `#ffffff` (white). + +font +: (`resource.Resource`) The font can be a [global resource](g), a [page resource](g), or a [remote resource](g). Default is [Go Regular], a proportional sans-serif TrueType font. + +linespacing +: (`int`) The number of pixels between each line. For a line height of 1.4, set the `linespacing` to 0.4 multiplied by the `size`. Default is `2`. + +size +: (`int`) The font size in pixels. Default is `20`. + +x +: (`int`) The horizontal offset, in pixels, relative to the left of the image. Default is `10`. + +y +: (`int`) The vertical offset, in pixels, relative to the top of the image. Default is `10`. + +[Go Regular]: https://go.dev/blog/go-fonts#sans-serif + +## Usage + +Set the text and paths: + +```go-html-template +{{ $text := "Zion National Park" }} +{{ $fontPath := "https://github.com/google/fonts/raw/main/ofl/lato/Lato-Regular.ttf" }} +{{ $imagePath := "images/original.jpg" }} +``` + +Capture the font as a resource: + +```go-html-template +{{ $font := "" }} +{{ with try (resources.GetRemote $fontPath) }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else with .Value }} + {{ $font = . }} + {{ else }} + {{ errorf "Unable to get resource %s" $fontPath }} + {{ end }} +{{ end }} +``` + +Create the filter, centering the text horizontally and vertically: + +```go-html-template +{{ $r := "" }} +{{ $filter := "" }} +{{ with $r = resources.Get $imagePath }} + {{ $opts := dict + "alignx" "center" + "color" "#fbfaf5" + "font" $font + "linespacing" 8 + "size" 60 + "x" (mul .Width 0.5 | int) + "y" (mul .Height 0.5 | int) + }} + {{ $filter = images.Text $text $opts }} +{{ else }} + {{ errorf "Unable to get resource %s" $imagePath }} +{{ end }} +``` + +Apply the filter using the [`images.Filter`] function: + +```go-html-template +{{ with $r }} + {{ with . | images.Filter $filter }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +You can also apply the filter using the [`Filter`] method on a `Resource` object: + +```go-html-template +{{ with $r }} + {{ with .Filter $filter }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +[`images.Filter`]: /functions/images/filter/ +[`Filter`]: /methods/resource/filter/ + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Text" + filterArgs="Zion National Park,25,190,40,1.2,#fbfaf5" + example=true +>}} diff --git a/docs/content/en/functions/images/UnsharpMask.md b/docs/content/en/functions/images/UnsharpMask.md new file mode 100644 index 000000000..9c06eb5e1 --- /dev/null +++ b/docs/content/en/functions/images/UnsharpMask.md @@ -0,0 +1,37 @@ +--- +title: images.UnsharpMask +description: Returns an image filter that sharpens an image. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: images.filter + signatures: [images.UnsharpMask SIGMA AMOUNT THRESHOLD] +--- + +The sigma argument is used in a gaussian function and affects the radius of effect. Sigma must be positive. The sharpen radius is approximately 3 times the sigma value. + +The amount argument controls how much darker and how much lighter the edge borders become. Typically between 0.5 and 1.5. + +The threshold argument controls the minimum brightness change that will be sharpened. Typically between 0 and 0.05. + +## Usage + +Create the filter: + +```go-html-template +{{ $filter := images.UnsharpMask 10 0.4 0.03 }} +``` + +{{% include "/_common/functions/images/apply-image-filter.md" %}} + +## Example + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="UnsharpMask" + filterArgs="10,0.4,0.03" + example=true +>}} diff --git a/docs/content/en/functions/images/_index.md b/docs/content/en/functions/images/_index.md new file mode 100644 index 000000000..f92e16e7a --- /dev/null +++ b/docs/content/en/functions/images/_index.md @@ -0,0 +1,7 @@ +--- +title: Image functions +linkTitle: images +description: Use these functions to create an image filter, apply an image filter to an image, and to retrieve image information. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/inflect/Humanize.md b/docs/content/en/functions/inflect/Humanize.md new file mode 100644 index 000000000..d3d785243 --- /dev/null +++ b/docs/content/en/functions/inflect/Humanize.md @@ -0,0 +1,24 @@ +--- +title: inflect.Humanize +description: Returns the humanized version of the input with the first letter capitalized. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [humanize] + returnType: string + signatures: [inflect.Humanize INPUT] +aliases: [/functions/humanize] +--- + +```go-html-template +{{ humanize "my-first-post" }} → My first post +{{ humanize "myCamelPost" }} → My camel post +``` + +If the input is an integer or a string representation of an integer, humanize returns the number with the proper ordinal appended. + +```go-html-template +{{ humanize "52" }} → 52nd +{{ humanize 103 }} → 103rd +``` diff --git a/docs/content/en/functions/inflect/Pluralize.md b/docs/content/en/functions/inflect/Pluralize.md new file mode 100644 index 000000000..f168770d3 --- /dev/null +++ b/docs/content/en/functions/inflect/Pluralize.md @@ -0,0 +1,16 @@ +--- +title: inflect.Pluralize +description: Pluralizes the given word according to a set of common English pluralization rules. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [pluralize] + returnType: string + signatures: [inflect.Pluralize INPUT] +aliases: [/functions/pluralize] +--- + +```go-html-template +{{ "cat" | pluralize }} → cats +``` diff --git a/docs/content/en/functions/inflect/Singularize.md b/docs/content/en/functions/inflect/Singularize.md new file mode 100644 index 000000000..41e05b784 --- /dev/null +++ b/docs/content/en/functions/inflect/Singularize.md @@ -0,0 +1,16 @@ +--- +title: inflect.Singularize +description: Singularizes the given word according to a set of common English singularization rules. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [singularize] + returnType: string + signatures: [inflect.Singularize INPUT] +aliases: [/functions/singularize] +--- + +```go-html-template +{{ "cats" | singularize }} → cat +``` diff --git a/docs/content/en/functions/inflect/_index.md b/docs/content/en/functions/inflect/_index.md new file mode 100644 index 000000000..2afe4fe33 --- /dev/null +++ b/docs/content/en/functions/inflect/_index.md @@ -0,0 +1,7 @@ +--- +title: Inflect functions +linkTitle: inflect +description: These functions provide word inflection features such as singularization and pluralization of English nouns. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/js/Babel.md b/docs/content/en/functions/js/Babel.md new file mode 100644 index 000000000..d0007aaa0 --- /dev/null +++ b/docs/content/en/functions/js/Babel.md @@ -0,0 +1,99 @@ +--- +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 }} + <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script> + {{ end }} + {{ else }} + <script src="{{ .RelPermalink }}"></script> + {{ end }} + {{ end }} +{{ end }} +``` + +## Setup + +### Step 1 + +Install [Node.js](https://nodejs.org/en/download) + +### Step 2 + +Install the required Node.js packages in the root of your project. + +```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 >}} + +## 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` + +<!-- +In the above, technically "none" is not one of the enumerated sourceMap +values but it has the same effect and is easier to document than an empty string. +--> diff --git a/docs/content/en/functions/js/Batch.md b/docs/content/en/functions/js/Batch.md new file mode 100644 index 000000000..a2c8bb893 --- /dev/null +++ b/docs/content/en/functions/js/Batch.md @@ -0,0 +1,307 @@ +--- +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): + +```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" }} + <link href="{{ $s.RelPermalink }}" rel="stylesheet" /> + {{ else }} + <script src="{{ $s.RelPermalink }}" type="module"></script> + {{ 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. + +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 --git a/docs/content/en/functions/js/Build.md b/docs/content/en/functions/js/Build.md new file mode 100644 index 000000000..1bec6b16f --- /dev/null +++ b/docs/content/en/functions/js/Build.md @@ -0,0 +1,121 @@ +--- +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" hugo.IsProduction + "sourceMap" (cond hugo.IsProduction "" "external") + "targetPath" "js/main.js" + }} + {{ with . | js.Build $opts }} + {{ if hugo.IsProduction }} + {{ with . | fingerprint }} + <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script> + {{ end }} + {{ else }} + <script src="{{ .RelPermalink }}"></script> + {{ 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 `<script>` tag. + +{{% include "/_common/functions/js/options.md" %}} + +## Import JS code from the assets directory + +`js.Build` has full support for the virtual union file system in [Hugo Modules](/hugo-modules/). You can see some simple examples in this [test project](https://github.com/gohugoio/hugoTestProjectJSModImports), but in short this means that you can do this: + +```js +import { hello } from 'my/module'; +``` + +And it will resolve to the top-most `index.{js,ts,tsx,jsx}` inside `assets/my/module` in the layered file system. + +```js +import { hello3 } from 'my/module/hello3'; +``` + +Will resolve to `hello3.{js,ts,tsx,jsx}` inside `assets/my/module`. + +Any imports starting with `.` are resolved relative to the current file: + +```js +import { hello4 } from './lib'; +``` + +For other files (e.g. `JSON`, `CSS`) you need to use the relative path including any extension, e.g: + +```js +import * as data from 'my/module/data.json'; +``` + +Any imports in a file outside `assets` or that does not resolve to a component inside `assets` will be resolved by [ESBuild](https://esbuild.github.io/) with the **project directory** as the resolve directory (used as the starting point when looking for `node_modules` etc.). Also see [hugo mod npm pack](/commands/hugo_mod_npm_pack/). If you have any imported npm dependencies in your project, you need to make sure to run `npm install` before you run `hugo`. + +Also note the new `params` option that can be passed from template to 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'; +``` + +Hugo will, by default, generate a `assets/jsconfig.json` file that maps the imports. This is useful for navigation/intellisense help inside code editors, but if you don't need/want it, you can [turn it off](/configuration/build/). + +## Node.js dependencies + +Use the `js.Build` function to include Node.js dependencies. + +Any imports in a file outside `assets` or that does not resolve to a component inside `assets` will be resolved by [esbuild](https://esbuild.github.io/) with the **project directory** as the resolve directory (used as the starting point when looking for `node_modules` etc.). Also see [hugo mod npm pack](/commands/hugo_mod_npm_pack/). If you have any imported npm dependencies in your project, you need to make sure to run `npm install` before you run `hugo`. + +The start directory for resolving npm packages (aka. packages that live inside a `node_modules` directory) is always the main project directory. + +> [!note] +> If you're developing a theme/component that is supposed to be imported and depends on dependencies inside `package.json`, we recommend reading about [hugo mod npm pack](/commands/hugo_mod_npm_pack/), a tool to consolidate all the npm dependencies in a project. + +## Examples + +```go-html-template +{{ $built := resources.Get "js/index.js" | js.Build "main.js" }} +``` + +Or with options: + +```go-html-template +{{ $externals := slice "react" "react-dom" }} +{{ $defines := dict "process.env.NODE_ENV" `"development"` }} + +{{ $opts := dict "targetPath" "main.js" "externals" $externals "defines" $defines }} +{{ $built := resources.Get "scripts/main.js" | js.Build $opts }} +<script src="{{ $built.RelPermalink }}" defer></script> +``` + +[evanw/esbuild]: https://github.com/evanw/esbuild diff --git a/docs/content/en/functions/js/_index.md b/docs/content/en/functions/js/_index.md new file mode 100644 index 000000000..d3557a2d3 --- /dev/null +++ b/docs/content/en/functions/js/_index.md @@ -0,0 +1,7 @@ +--- +title: JavaScript functions +linkTitle: js +description: Use these functions to work with JavaScript and TypeScript files. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/lang/FormatAccounting.md b/docs/content/en/functions/lang/FormatAccounting.md new file mode 100644 index 000000000..d2a1d76f6 --- /dev/null +++ b/docs/content/en/functions/lang/FormatAccounting.md @@ -0,0 +1,17 @@ +--- +title: lang.FormatAccounting +description: Returns a currency representation of a number for the given currency and precision for the current language and region in accounting notation. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [lang.FormatAccounting PRECISION CURRENCY NUMBER] +--- + +```go-html-template +{{ 512.5032 | lang.FormatAccounting 2 "NOK" }} → NOK512.50 +``` + +{{% include "/_common/functions/locales.md" %}} diff --git a/docs/content/en/functions/lang/FormatCurrency.md b/docs/content/en/functions/lang/FormatCurrency.md new file mode 100644 index 000000000..327413c07 --- /dev/null +++ b/docs/content/en/functions/lang/FormatCurrency.md @@ -0,0 +1,17 @@ +--- +title: lang.FormatCurrency +description: Returns a currency representation of a number for the given currency and precision for the current language and region. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [lang.FormatCurrency PRECISION CURRENCY NUMBER] +--- + +```go-html-template +{{ 512.5032 | lang.FormatCurrency 2 "USD" }} → $512.50 +``` + +{{% include "/_common/functions/locales.md" %}} diff --git a/docs/content/en/functions/lang/FormatNumber.md b/docs/content/en/functions/lang/FormatNumber.md new file mode 100644 index 000000000..5bf37996a --- /dev/null +++ b/docs/content/en/functions/lang/FormatNumber.md @@ -0,0 +1,17 @@ +--- +title: lang.FormatNumber +description: Returns a numeric representation of a number with the given precision for the current language and region. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [lang.FormatNumber PRECISION NUMBER] +--- + +```go-html-template +{{ 512.5032 | lang.FormatNumber 2 }} → 512.50 +``` + +{{% include "/_common/functions/locales.md" %}} diff --git a/docs/content/en/functions/lang/FormatNumberCustom.md b/docs/content/en/functions/lang/FormatNumberCustom.md new file mode 100644 index 000000000..0a70cd938 --- /dev/null +++ b/docs/content/en/functions/lang/FormatNumberCustom.md @@ -0,0 +1,30 @@ +--- +title: lang.FormatNumberCustom +description: Returns a numeric representation of a number with the given precision using negative, decimal, and grouping options. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: ['lang.FormatNumberCustom PRECISION NUMBER [OPTIONS...]'] +aliases: ['/functions/numfmt/'] +--- + +This function 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 alternative 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 [`lang.FormatNumber`]. + +```go-html-template +{{ 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 +``` + +{{% include "/_common/functions/locales.md" %}} + +[`lang.FormatNumber`]: /functions/lang/formatnumber/ diff --git a/docs/content/en/functions/lang/FormatPercent.md b/docs/content/en/functions/lang/FormatPercent.md new file mode 100644 index 000000000..aef1fb64c --- /dev/null +++ b/docs/content/en/functions/lang/FormatPercent.md @@ -0,0 +1,17 @@ +--- +title: lang.FormatPercent +description: Returns a percentage representation of a number with the given precision for the current language and region. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [lang.FormatPercent PRECISION NUMBER] +--- + +```go-html-template +{{ 512.5032 | lang.FormatPercent 2 }} → 512.50% +``` + +{{% include "/_common/functions/locales.md" %}} diff --git a/docs/content/en/functions/lang/Merge.md b/docs/content/en/functions/lang/Merge.md new file mode 100644 index 000000000..db40c2669 --- /dev/null +++ b/docs/content/en/functions/lang/Merge.md @@ -0,0 +1,29 @@ +--- +title: lang.Merge +description: Merge missing translations from other languages. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: any + signatures: [lang.Merge FROM TO] +aliases: [/functions/lang.merge] +--- + +As an example: + +```sh +{{ $pages := .Site.RegularPages | lang.Merge $frSite.RegularPages | lang.Merge $enSite.RegularPages }} +``` + +Will "fill in the gaps" in the current site with, from left to right, content from the French site, and lastly the English. + +A more practical example is to fill in the missing translations from the other languages: + +```sh +{{ $pages := .Site.RegularPages }} +{{ range .Site.Home.Translations }} +{{ $pages = $pages | lang.Merge .Site.RegularPages }} +{{ end }} + ``` diff --git a/docs/content/en/functions/lang/Translate.md b/docs/content/en/functions/lang/Translate.md new file mode 100644 index 000000000..00bb0e3f3 --- /dev/null +++ b/docs/content/en/functions/lang/Translate.md @@ -0,0 +1,246 @@ +--- +title: lang.Translate +description: Translates a string using the translation tables in the i18n directory. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [T, i18n] + returnType: string + signatures: ['lang.Translate KEY [CONTEXT]'] +aliases: [/functions/i18n] +--- + +The `lang.Translate` function returns the value associated with given key as defined in the translation table for the current language. + +If the key is not found in the translation table for the current language, the `lang.Translate` function falls back to the translation table for the [`defaultContentLanguage`]. + +If the key is not found in the translation table for the `defaultContentLanguage`, the `lang.Translate` function returns an empty string. + +> [!note] +> To list missing and fallback translations, use the `--printI18nWarnings` flag when building your site. +> +> To render placeholders for missing and fallback translations, set [`enableMissingTranslationPlaceholders`] to `true` in your site configuration. + +## Translation tables + +Create translation tables in the `i18n` directory, naming each file according to [RFC 5646]. Translation tables may be JSON, TOML, or YAML. For example: + +```text +i18n/en.toml +i18n/en-US.toml +``` + +The base name must match the [language key] as defined in your site configuration. + +Artificial languages with private use subtags as defined in [RFC 5646 § 2.2.7] are also supported. You may omit the `art-x-` prefix for brevity. For example: + +```text +i18n/art-x-hugolang.toml +i18n/hugolang.toml +``` + +> [!note] +> Private use subtags must not exceed 8 alphanumeric characters. + +## Simple translations + +Let's say your multilingual site supports two languages, English and Polish. Create a translation table for each language in the `i18n` directory. + +```text +i18n/ +├── en.toml +└── pl.toml +``` + +The English translation table: + +{{< code-toggle file=i18n/en >}} +privacy = 'privacy' +security = 'security' +{{< /code-toggle >}} + +The Polish translation table: + +{{< code-toggle file=i18n/pl >}} +privacy = 'prywatność' +security = 'bezpieczeństwo' +{{< /code-toggle >}} + +> [!note] +> The examples below use the `T` alias for brevity. + +When viewing the English language site: + +```go-html-template +{{ T "privacy" }} → privacy +{{ T "security" }} → security +```` + +When viewing the Polish language site: + +```go-html-template +{{ T "privacy" }} → prywatność +{{ T "security" }} → bezpieczeństwo +``` + +## Translations with pluralization + +Let's say your multilingual site supports two languages, English and Polish. Create a translation table for each language in the `i18n` directory. + +```text +i18n/ +├── en.toml +└── pl.toml +``` + +The Unicode [CLDR Plural Rules chart] describes the pluralization categories for each language. + +The English translation table: + +{{< code-toggle file=i18n/en >}} +[day] +one = 'day' +other = 'days' + +[day_with_count] +one = '{{ . }} day' +other = '{{ . }} days' +{{< /code-toggle >}} + +The Polish translation table: + +{{< code-toggle file=i18n/pl >}} +[day] +one = 'miesiąc' +few = 'miesiące' +many = 'miesięcy' +other = 'miesiąca' + +[day_with_count] +one = '{{ . }} miesiąc' +few = '{{ . }} miesiące' +many = '{{ . }} miesięcy' +other = '{{ . }} miesiąca' +{{< /code-toggle >}} + +> [!note] +> The examples below use the `T` alias for brevity. + +When viewing the English language site: + +```go-html-template +{{ T "day" 0 }} → days +{{ T "day" 1 }} → day +{{ T "day" 2 }} → days +{{ T "day" 5 }} → days + +{{ T "day_with_count" 0 }} → 0 days +{{ T "day_with_count" 1 }} → 1 day +{{ T "day_with_count" 2 }} → 2 days +{{ T "day_with_count" 5 }} → 5 days +```` + +When viewing the Polish language site: + +```go-html-template +{{ T "day" 0 }} → miesięcy +{{ T "day" 1 }} → miesiąc +{{ T "day" 2 }} → miesiące +{{ T "day" 5 }} → miesięcy + +{{ T "day_with_count" 0 }} → 0 miesięcy +{{ T "day_with_count" 1 }} → 1 miesiąc +{{ T "day_with_count" 2 }} → 2 miesiące +{{ T "day_with_count" 5 }} → 5 miesięcy +``` + +In the pluralization examples above, we passed an integer in context (the second argument). You can also pass a map in context, providing a `count` key to control pluralization. + +Translation table: + +{{< code-toggle file=i18n/en >}} +[age] +one = '{{ .name }} is {{ .count }} year old.' +other = '{{ .name }} is {{ .count }} years old.' +{{< /code-toggle >}} + +Template code: + +```go-html-template +{{ T "age" (dict "name" "Will" "count" 1) }} → Will is 1 year old. +{{ T "age" (dict "name" "John" "count" 3) }} → John is 3 years old. +``` + +> [!note] +> Translation tables may contain both simple translations and translations with pluralization. + +## Reserved keys + +Hugo uses the [go-i18n] package to look up values in translation tables. This package reserves the following keys for internal use: + +id +: (`string`) Uniquely identifies the message. + +description +: (`string`) Describes the message to give additional context to translators that may be relevant for translation. + +hash +: (`string`) Uniquely identifies the content of the message that this message was translated from. + +leftdelim +: (`string`) The left Go template delimiter. + +rightdelim +: (`string`) The right Go template delimiter. + +zero +: (`string`) The content of the message for the [CLDR] plural form "zero". + +one +: (`string`) The content of the message for the [CLDR] plural form "one". + +two +: (`string`) The content of the message for the [CLDR] plural form "two". + +few +: (`string`) The content of the message for the [CLDR] plural form "few". + +many +: (`string`) The content of the message for the [CLDR] plural form "many". + +other +: (`string`) The content of the message for the [CLDR] plural form "other". + +If you need to provide a translation for one of the reserved keys, you can prepend the word with an underscore. For example: + +{{< code-toggle file=i18n/es >}} +_description = 'descripción' +_few = 'pocos' +_many = 'muchos' +_one = 'uno' +_other = 'otro' +_two = 'dos' +_zero = 'cero' +{{< /code-toggle >}} + +Then in your templates: + +```go-html-template +{{ T "_description" }} → descripción +{{ T "_few" }} → pocos +{{ T "_many" }} → muchos +{{ T "_one" }} → uno +{{ T "_two" }} → dos +{{ T "_zero" }} → cero +{{ T "_other" }} → otro +``` + +[`defaultContentLanguage`]: /configuration/all/#defaultcontentlanguage +[`enableMissingTranslationPlaceholders`]: /configuration/all/#enablemissingtranslationplaceholders +[CLDR]: https://www.unicode.org/cldr/charts/43/supplemental/language_plural_rules.html +[CLDR Plural Rules chart]: https://www.unicode.org/cldr/charts/43/supplemental/language_plural_rules.html +[go-i18n]: https://github.com/nicksnyder/go-i18n +[language key]: /configuration/languages/#language-keys +[RFC 5646]: https://datatracker.ietf.org/doc/html/rfc5646 +[RFC 5646 § 2.2.7]: https://datatracker.ietf.org/doc/html/rfc5646#section-2.2.7 diff --git a/docs/content/en/functions/lang/_index.md b/docs/content/en/functions/lang/_index.md new file mode 100644 index 000000000..de75cad45 --- /dev/null +++ b/docs/content/en/functions/lang/_index.md @@ -0,0 +1,7 @@ +--- +title: Lang functions +linkTitle: lang +description: Use these functions to adapt your site to meet language and regional requirements. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/math/Abs.md b/docs/content/en/functions/math/Abs.md new file mode 100644 index 000000000..60d8d6d64 --- /dev/null +++ b/docs/content/en/functions/math/Abs.md @@ -0,0 +1,15 @@ +--- +title: math.Abs +description: Returns the absolute value of the given number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Abs VALUE] +--- + +```go-html-template +{{ math.Abs -2.1 }} → 2.1 +``` diff --git a/docs/content/en/functions/math/Acos.md b/docs/content/en/functions/math/Acos.md new file mode 100644 index 000000000..32537e2dd --- /dev/null +++ b/docs/content/en/functions/math/Acos.md @@ -0,0 +1,17 @@ +--- +title: math.Acos +description: Returns the arccosine, in radians, of the given number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Acos VALUE] +--- + +{{< new-in 0.130.0 />}} + +```go-html-template +{{ math.Acos 1 }} → 0 +``` diff --git a/docs/content/en/functions/math/Add.md b/docs/content/en/functions/math/Add.md new file mode 100644 index 000000000..cd137c6c7 --- /dev/null +++ b/docs/content/en/functions/math/Add.md @@ -0,0 +1,23 @@ +--- +title: math.Add +description: Adds two or more numbers. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [add] + returnType: any + signatures: [math.Add VALUE VALUE...] +--- + +If one of the numbers is a [`float`](g), the result is a `float`. + +```go-html-template +{{ add 12 3 2 }} → 17 +``` + +You can also use the `add` function to concatenate strings. + +```go-html-template +{{ add "hu" "go" }} → hugo +``` diff --git a/docs/content/en/functions/math/Asin.md b/docs/content/en/functions/math/Asin.md new file mode 100644 index 000000000..76114a72e --- /dev/null +++ b/docs/content/en/functions/math/Asin.md @@ -0,0 +1,17 @@ +--- +title: math.Asin +description: Returns the arcsine, in radians, of the given number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Asin VALUE] +--- + +{{< new-in 0.130.0 />}} + +```go-html-template +{{ math.Asin 1 }} → 1.5707963267948966 +``` diff --git a/docs/content/en/functions/math/Atan.md b/docs/content/en/functions/math/Atan.md new file mode 100644 index 000000000..5c8268b47 --- /dev/null +++ b/docs/content/en/functions/math/Atan.md @@ -0,0 +1,17 @@ +--- +title: math.Atan +description: Returns the arctangent, in radians, of the given number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Atan VALUE] +--- + +{{< new-in 0.130.0 />}} + +```go-html-template +{{ math.Atan 1 }} → 0.7853981633974483 +``` diff --git a/docs/content/en/functions/math/Atan2.md b/docs/content/en/functions/math/Atan2.md new file mode 100644 index 000000000..942fffdf8 --- /dev/null +++ b/docs/content/en/functions/math/Atan2.md @@ -0,0 +1,17 @@ +--- +title: math.Atan2 +description: Returns the arctangent, in radians, of the given number pair, determining the correct quadrant from their signs. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Atan2 VALUE VALUE] +--- + +{{< new-in 0.130.0 />}} + +```go-html-template +{{ math.Atan2 1 2 }} → 0.4636476090008061 +``` diff --git a/docs/content/en/functions/math/Ceil.md b/docs/content/en/functions/math/Ceil.md new file mode 100644 index 000000000..22a9d0299 --- /dev/null +++ b/docs/content/en/functions/math/Ceil.md @@ -0,0 +1,15 @@ +--- +title: math.Ceil +description: Returns the least integer value greater than or equal to the given number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Ceil VALUE] +--- + +```go-html-template +{{ math.Ceil 2.1 }} → 3 +``` diff --git a/docs/content/en/functions/math/Cos.md b/docs/content/en/functions/math/Cos.md new file mode 100644 index 000000000..249a064bb --- /dev/null +++ b/docs/content/en/functions/math/Cos.md @@ -0,0 +1,17 @@ +--- +title: math.Cos +description: Returns the cosine of the given radian number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Cos VALUE] +--- + +{{< new-in 0.130.0 />}} + +```go-html-template +{{ math.Cos 1 }} → 0.5403023058681398 +``` diff --git a/docs/content/en/functions/math/Counter.md b/docs/content/en/functions/math/Counter.md new file mode 100644 index 000000000..16456cec6 --- /dev/null +++ b/docs/content/en/functions/math/Counter.md @@ -0,0 +1,33 @@ +--- +title: math.Counter +description: Increments and returns a global counter. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: uint64 + signatures: [math.Counter] +--- + +The counter is global for both monolingual and multilingual sites, and its initial value for each build is 1. + +```go-html-template +{{ warnf "single.html called %d times" math.Counter }} +``` + +```sh +WARN single.html called 1 times +WARN single.html called 2 times +WARN single.html called 3 times +``` + +Use this function to: + +- Create unique warnings as shown above; the [`warnf`] function suppresses duplicate messages +- Create unique target paths for the `resources.FromString` function where the target path is also the cache key + +> [!note] +> Due to concurrency, the value returned in a given template for a given page will vary from one build to the next. You cannot use this function to assign a static id to each page. + +[`warnf`]: /functions/fmt/warnf/ diff --git a/docs/content/en/functions/math/Div.md b/docs/content/en/functions/math/Div.md new file mode 100644 index 000000000..0e338a9e9 --- /dev/null +++ b/docs/content/en/functions/math/Div.md @@ -0,0 +1,17 @@ +--- +title: math.Div +description: Divides the first number by one or more numbers. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [div] + returnType: any + signatures: [math.Div VALUE VALUE...] +--- + +If one of the numbers is a [`float`](g), the result is a `float`. + +```go-html-template +{{ div 12 3 2 }} → 2 +``` diff --git a/docs/content/en/functions/math/Floor.md b/docs/content/en/functions/math/Floor.md new file mode 100644 index 000000000..dbfd8620e --- /dev/null +++ b/docs/content/en/functions/math/Floor.md @@ -0,0 +1,15 @@ +--- +title: math.Floor +description: Returns the greatest integer value less than or equal to the given number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Floor VALUE] +--- + +```go-html-template +{{ math.Floor 1.9 }} → 1 +``` diff --git a/docs/content/en/functions/math/Log.md b/docs/content/en/functions/math/Log.md new file mode 100644 index 000000000..123ffacd7 --- /dev/null +++ b/docs/content/en/functions/math/Log.md @@ -0,0 +1,15 @@ +--- +title: math.Log +description: Returns the natural logarithm of the given number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Log VALUE] +--- + +```go-html-template +{{ math.Log 42 }} → 3.737 +``` diff --git a/docs/content/en/functions/math/Max.md b/docs/content/en/functions/math/Max.md new file mode 100644 index 000000000..d3a7676fc --- /dev/null +++ b/docs/content/en/functions/math/Max.md @@ -0,0 +1,15 @@ +--- +title: math.Max +description: Returns the greater of all numbers. Accepts scalars, slices, or both. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Max VALUE...] +--- + +```go-html-template +{{ math.Max 1 (slice 2 3) 4 }} → 4 +``` diff --git a/docs/content/en/functions/math/Min.md b/docs/content/en/functions/math/Min.md new file mode 100644 index 000000000..4f7d7b85a --- /dev/null +++ b/docs/content/en/functions/math/Min.md @@ -0,0 +1,15 @@ +--- +title: math.Min +description: Returns the smaller of all numbers. Accepts scalars, slices, or both. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Min VALUE...] +--- + +```go-html-template +{{ math.Min 1 (slice 2 3) 4 }} → 1 +``` diff --git a/docs/content/en/functions/math/Mod.md b/docs/content/en/functions/math/Mod.md new file mode 100644 index 000000000..6035a361e --- /dev/null +++ b/docs/content/en/functions/math/Mod.md @@ -0,0 +1,15 @@ +--- +title: math.Mod +description: Returns the modulus of two integers. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [mod] + returnType: int64 + signatures: [math.Mod VALUE1 VALUE2] +--- + +```go-html-template +{{ mod 15 3 }} → 0 +``` diff --git a/docs/content/en/functions/math/ModBool.md b/docs/content/en/functions/math/ModBool.md new file mode 100644 index 000000000..fc7813d67 --- /dev/null +++ b/docs/content/en/functions/math/ModBool.md @@ -0,0 +1,15 @@ +--- +title: math.ModBool +description: Reports whether the modulus of two integers equals 0. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [modBool] + returnType: bool + signatures: [math.ModBool VALUE1 VALUE2] +--- + +```go-html-template +{{ modBool 15 3 }} → true +``` diff --git a/docs/content/en/functions/math/Mul.md b/docs/content/en/functions/math/Mul.md new file mode 100644 index 000000000..69f2dbe1b --- /dev/null +++ b/docs/content/en/functions/math/Mul.md @@ -0,0 +1,17 @@ +--- +title: math.Mul +description: Multiplies two or more numbers. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [mul] + returnType: any + signatures: [math.Mul VALUE VALUE...] +--- + +If one of the numbers is a [`float`](g), the result is a `float`. + +```go-html-template +{{ mul 12 3 2 }} → 72 +``` diff --git a/docs/content/en/functions/math/Pi.md b/docs/content/en/functions/math/Pi.md new file mode 100644 index 000000000..0bc74bf03 --- /dev/null +++ b/docs/content/en/functions/math/Pi.md @@ -0,0 +1,17 @@ +--- +title: math.Pi +description: Returns the mathematical constant pi. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Pi] +--- + +{{< new-in 0.130.0 />}} + +```go-html-template +{{ math.Pi }} → 3.141592653589793 +``` diff --git a/docs/content/en/functions/math/Pow.md b/docs/content/en/functions/math/Pow.md new file mode 100644 index 000000000..a4384305d --- /dev/null +++ b/docs/content/en/functions/math/Pow.md @@ -0,0 +1,15 @@ +--- +title: math.Pow +description: Returns the first number raised to the power of the second number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [pow] + returnType: float64 + signatures: [math.Pow VALUE1 VALUE2] +--- + +```go-html-template +{{ math.Pow 2 3 }} → 8 +``` diff --git a/docs/content/en/functions/math/Product.md b/docs/content/en/functions/math/Product.md new file mode 100644 index 000000000..ffb1afe46 --- /dev/null +++ b/docs/content/en/functions/math/Product.md @@ -0,0 +1,15 @@ +--- +title: math.Product +description: Returns the product of all numbers. Accepts scalars, slices, or both. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Product VALUE...] +--- + +```go-html-template +{{ math.Product 1 (slice 2 3) 4 }} → 24 +``` diff --git a/docs/content/en/functions/math/Rand.md b/docs/content/en/functions/math/Rand.md new file mode 100644 index 000000000..d659e651f --- /dev/null +++ b/docs/content/en/functions/math/Rand.md @@ -0,0 +1,43 @@ +--- +title: math.Rand +description: Returns a pseudo-random number in the half-open interval [0.0, 1.0). +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Rand] +--- + +{{< new-in 0.121.2 />}} + +The `math.Rand` function returns a pseudo-random number in the half-open [interval](g) [0.0, 1.0). + +```go-html-template +{{ math.Rand }} → 0.6312770459590062 +``` + +To generate a random integer in the closed interval [0, 5]: + +```go-html-template +{{ math.Rand | mul 6 | math.Floor }} +``` + +To generate a random integer in the closed interval [1, 6]: + +```go-html-template +{{ math.Rand | mul 6 | math.Ceil }} +``` + +To generate a random float, with one digit after the decimal point, in the closed interval [0, 4.9]: + +```go-html-template +{{ div (math.Rand | mul 50 | math.Floor) 10 }} +``` + +To generate a random float, with one digit after the decimal point, in the closed interval [0.1, 5.0]: + +```go-html-template +{{ div (math.Rand | mul 50 | math.Ceil) 10 }} +``` diff --git a/docs/content/en/functions/math/Round.md b/docs/content/en/functions/math/Round.md new file mode 100644 index 000000000..6bc015ce7 --- /dev/null +++ b/docs/content/en/functions/math/Round.md @@ -0,0 +1,15 @@ +--- +title: math.Round +description: Returns the nearest integer, rounding half away from zero. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Round VALUE] +--- + +```go-html-template +{{ math.Round 1.5 }} → 2 +``` diff --git a/docs/content/en/functions/math/Sin.md b/docs/content/en/functions/math/Sin.md new file mode 100644 index 000000000..b5ab86bb8 --- /dev/null +++ b/docs/content/en/functions/math/Sin.md @@ -0,0 +1,17 @@ +--- +title: math.Sin +description: Returns the sine of the given radian number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Sin VALUE] +--- + +{{< new-in 0.130.0 />}} + +```go-html-template +{{ math.Sin 1 }} → 0.8414709848078965 +``` diff --git a/docs/content/en/functions/math/Sqrt.md b/docs/content/en/functions/math/Sqrt.md new file mode 100644 index 000000000..b2f49fdbd --- /dev/null +++ b/docs/content/en/functions/math/Sqrt.md @@ -0,0 +1,15 @@ +--- +title: math.Sqrt +description: Returns the square root of the given number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Sqrt VALUE] +--- + +```go-html-template +{{ math.Sqrt 81 }} → 9 +``` diff --git a/docs/content/en/functions/math/Sub.md b/docs/content/en/functions/math/Sub.md new file mode 100644 index 000000000..49459cd71 --- /dev/null +++ b/docs/content/en/functions/math/Sub.md @@ -0,0 +1,17 @@ +--- +title: math.Sub +description: Subtracts one or more numbers from the first number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [sub] + returnType: any + signatures: [math.Sub VALUE VALUE...] +--- + +If one of the numbers is a [`float`](g), the result is a `float`. + +```go-html-template +{{ sub 12 3 2 }} → 7 +``` diff --git a/docs/content/en/functions/math/Sum.md b/docs/content/en/functions/math/Sum.md new file mode 100644 index 000000000..e14bc924b --- /dev/null +++ b/docs/content/en/functions/math/Sum.md @@ -0,0 +1,14 @@ +--- +title: math.Sum +description: Returns the sum of all numbers. Accepts scalars, slices, or both. +categories: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Sum VALUE...] +--- + +```go-html-template +{{ math.Sum 1 (slice 2 3) 4 }} → 10 +``` diff --git a/docs/content/en/functions/math/Tan.md b/docs/content/en/functions/math/Tan.md new file mode 100644 index 000000000..c4f861c05 --- /dev/null +++ b/docs/content/en/functions/math/Tan.md @@ -0,0 +1,17 @@ +--- +title: math.Tan +description: Returns the tangent of the given radian number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.Tan VALUE] +--- + +{{< new-in 0.130.0 />}} + +```go-html-template +{{ math.Tan 1 }} → 1.557407724654902 +``` diff --git a/docs/content/en/functions/math/ToDegrees.md b/docs/content/en/functions/math/ToDegrees.md new file mode 100644 index 000000000..f01cd4728 --- /dev/null +++ b/docs/content/en/functions/math/ToDegrees.md @@ -0,0 +1,17 @@ +--- +title: math.ToDegrees +description: ToDegrees converts radians into degrees. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.ToDegrees VALUE] +--- + +{{< new-in 0.130.0 />}} + +```go-html-template +{{ math.ToDegrees 1.5707963267948966 }} → 90 +``` diff --git a/docs/content/en/functions/math/ToRadians.md b/docs/content/en/functions/math/ToRadians.md new file mode 100644 index 000000000..b5acbb65b --- /dev/null +++ b/docs/content/en/functions/math/ToRadians.md @@ -0,0 +1,17 @@ +--- +title: math.ToRadians +description: ToRadians converts degrees into radians. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: float64 + signatures: [math.ToRadians VALUE] +--- + +{{< new-in 0.130.0 />}} + +```go-html-template +{{ math.ToRadians 90 }} → 1.5707963267948966 +``` diff --git a/docs/content/en/functions/math/_index.md b/docs/content/en/functions/math/_index.md new file mode 100644 index 000000000..c58a5a704 --- /dev/null +++ b/docs/content/en/functions/math/_index.md @@ -0,0 +1,6 @@ +--- +title: Math functions +linkTitle: math +description: Use these functions to perform mathematical operations. +categories: [] +--- diff --git a/docs/content/en/functions/openapi3/Unmarshal.md b/docs/content/en/functions/openapi3/Unmarshal.md new file mode 100644 index 000000000..d1f928aeb --- /dev/null +++ b/docs/content/en/functions/openapi3/Unmarshal.md @@ -0,0 +1,72 @@ +--- +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 +<pre>{{ debug.Dump $api }}</pre> +``` + +To list the GET and POST operations for each of the API paths: + +```go-html-template +{{ range $path, $details := $api.Paths }} + <p>{{ $path }}</p> + <dl> + {{ with $details.Get }} + <dt>GET</dt> + <dd>{{ .Summary }}</dd> + {{ end }} + {{ with $details.Post }} + <dt>POST</dt> + <dd>{{ .Summary }}</dd> + {{ end }} + </dl> +{{ end }} +``` + +Hugo renders this to: + +```html +<p>/pets</p> +<dl> + <dt>GET</dt> + <dd>List all pets</dd> + <dt>POST</dt> + <dd>Create a pet</dd> +</dl> +<p>/pets/{petId}</p> +<dl> + <dt>GET</dt> + <dd>Info for a specific pet</dd> +</dl> +``` diff --git a/docs/content/en/functions/openapi3/_index.md b/docs/content/en/functions/openapi3/_index.md new file mode 100644 index 000000000..852daf7b5 --- /dev/null +++ b/docs/content/en/functions/openapi3/_index.md @@ -0,0 +1,7 @@ +--- +title: OpenAPI functions +linkTitle: openapi3 +description: Use these functions to work with OpenAPI 3 definitions. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/os/FileExists.md b/docs/content/en/functions/os/FileExists.md new file mode 100644 index 000000000..b8a01a3e7 --- /dev/null +++ b/docs/content/en/functions/os/FileExists.md @@ -0,0 +1,37 @@ +--- +title: os.FileExists +description: Reports whether the file or directory exists. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [fileExists] + returnType: bool + signatures: [os.FileExists PATH] +aliases: [/functions/fileexists] +--- + +The `os.FileExists` function attempts to resolve the path relative to the root of your project directory. If a matching file or directory is not found, it will attempt to resolve the path relative to the [`contentDir`](/configuration/all/#contentdir). A leading path separator (`/`) is optional. + +With this directory structure: + +```text +content/ +├── about.md +├── contact.md +└── news/ + ├── article-1.md + └── article-2.md +``` + +The function returns these values: + +```go-html-template +{{ fileExists "content" }} → true +{{ fileExists "content/news" }} → true +{{ fileExists "content/news/article-1" }} → false +{{ fileExists "content/news/article-1.md" }} → true +{{ fileExists "news" }} → true +{{ fileExists "news/article-1" }} → false +{{ fileExists "news/article-1.md" }} → true +``` diff --git a/docs/content/en/functions/os/Getenv.md b/docs/content/en/functions/os/Getenv.md new file mode 100644 index 000000000..04215e6c3 --- /dev/null +++ b/docs/content/en/functions/os/Getenv.md @@ -0,0 +1,54 @@ +--- +title: os.Getenv +description: Returns the value of an environment variable, or an empty string if the environment variable is not set. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [getenv] + returnType: string + signatures: [os.Getenv VARIABLE] +aliases: [/functions/getenv] +--- + +## Security + +By default, when using the `os.Getenv` function Hugo allows access to: + +- The `CI` environment variable +- Any environment variable beginning with `HUGO_` + +To access other environment variables, adjust your site configuration. For example, to allow access to the `HOME` and `USER` environment variables: + +{{< code-toggle file=hugo >}} +[security.funcs] +getenv = ['^HUGO_', '^CI$', '^USER$', '^HOME$'] +{{< /code-toggle >}} + +For more information see [configure security](/configuration/security). + +## Examples + +```go-html-template +{{ getenv "HOME" }} → /home/victor +{{ getenv "USER" }} → victor +``` + +You can pass values when building your site: + +```sh +MY_VAR1=foo MY_VAR2=bar hugo + +OR + +export MY_VAR1=foo +export MY_VAR2=bar +hugo +``` + +And then retrieve the values within a template: + +```go-html-template +{{ getenv "MY_VAR1" }} → foo +{{ getenv "MY_VAR2" }} → bar +``` diff --git a/docs/content/en/functions/os/ReadDir.md b/docs/content/en/functions/os/ReadDir.md new file mode 100644 index 000000000..65c398a31 --- /dev/null +++ b/docs/content/en/functions/os/ReadDir.md @@ -0,0 +1,45 @@ +--- +title: os.ReadDir +description: Returns an array of FileInfo structures sorted by file name, one element for each directory entry. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [readDir] + returnType: os.FileInfo + signatures: [os.ReadDir PATH] +aliases: [/functions/readdir] +--- + +The `os.ReadDir` function resolves the path relative to the root of your project directory. A leading path separator (`/`) is optional. + +With this directory structure: + +```text +content/ +├── about.md +├── contact.md +└── news/ + ├── article-1.md + └── article-2.md +``` + +This template code: + +```go-html-template +{{ range readDir "content" }} + {{ .Name }} → {{ .IsDir }} +{{ end }} +``` + +Produces: + +```html +about.md → false +contact.md → false +news → true +``` + +Note that `os.ReadDir` is not recursive. + +Details of the `FileInfo` structure are available in the [Go documentation](https://pkg.go.dev/io/fs#FileInfo). diff --git a/docs/content/en/functions/os/ReadFile.md b/docs/content/en/functions/os/ReadFile.md new file mode 100644 index 000000000..7f25327c8 --- /dev/null +++ b/docs/content/en/functions/os/ReadFile.md @@ -0,0 +1,34 @@ +--- +title: os.ReadFile +description: Returns the contents of a file. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [readFile] + returnType: string + signatures: [os.ReadFile PATH] +aliases: [/functions/readfile] +--- + +The `os.ReadFile` function attempts to resolve the path relative to the root of your project directory. If a matching file is not found, it will attempt to resolve the path relative to the [`contentDir`](/configuration/all/#contentdir). A leading path separator (`/`) is optional. + +With a file named README.md in the root of your project directory: + +```text +This is **bold** text. +``` + +This template code: + +```go-html-template +{{ readFile "README.md" }} +``` + +Produces: + +```html +This is **bold** text. +``` + +Note that `os.ReadFile` returns raw (uninterpreted) content. diff --git a/docs/content/en/functions/os/Stat.md b/docs/content/en/functions/os/Stat.md new file mode 100644 index 000000000..63cb3f26a --- /dev/null +++ b/docs/content/en/functions/os/Stat.md @@ -0,0 +1,27 @@ +--- +title: os.Stat +description: Returns a FileInfo structure describing a file or directory. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: os.FileInfo + signatures: [os.Stat PATH] +aliases: [/functions/os.stat] +--- + +The `os.Stat` function attempts to resolve the path relative to the root of your project directory. If a matching file or directory is not found, it will attempt to resolve the path relative to the [`contentDir`](/configuration/all/#contentdir). A leading path separator (`/`) is optional. + +```go-html-template +{{ $f := os.Stat "README.md" }} +{{ $f.IsDir }} → false (bool) +{{ $f.ModTime }} → 2021-11-25 10:06:49.315429236 -0800 PST (time.Time) +{{ $f.Name }} → README.md (string) +{{ $f.Size }} → 241 (int64) + +{{ $d := os.Stat "content" }} +{{ $d.IsDir }} → true (bool) +``` + +Details of the `FileInfo` structure are available in the [Go documentation](https://pkg.go.dev/io/fs#FileInfo). diff --git a/docs/content/en/functions/os/_index.md b/docs/content/en/functions/os/_index.md new file mode 100644 index 000000000..b125f7004 --- /dev/null +++ b/docs/content/en/functions/os/_index.md @@ -0,0 +1,7 @@ +--- +title: OS functions +linkTitle: os +description: Use these functions to interact with the operating system. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/partials/Include.md b/docs/content/en/functions/partials/Include.md new file mode 100644 index 000000000..eb7eeafdc --- /dev/null +++ b/docs/content/en/functions/partials/Include.md @@ -0,0 +1,84 @@ +--- +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. +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: + +```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: + +```go-html-template +<p>{{ .name }} is majoring in {{ .major }}.</p> +<p>Their grade point average is {{ .gpa }}.</p> +<p>See <a href="{{ .page.RelPermalink }}">details.</a></p> +``` + +To return a value from a partial template, it must contain only one `return` statement, placed at the end of the template: + +```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 --git a/docs/content/en/functions/partials/IncludeCached.md b/docs/content/en/functions/partials/IncludeCached.md new file mode 100644 index 000000000..3905ee15e --- /dev/null +++ b/docs/content/en/functions/partials/IncludeCached.md @@ -0,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/_default/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. + +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 --git a/docs/content/en/functions/partials/_index.md b/docs/content/en/functions/partials/_index.md new file mode 100644 index 000000000..09b467399 --- /dev/null +++ b/docs/content/en/functions/partials/_index.md @@ -0,0 +1,7 @@ +--- +title: Partial functions +linkTitle: partials +description: Use these functions to call partial templates. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/path/Base.md b/docs/content/en/functions/path/Base.md new file mode 100644 index 000000000..39d52bfcb --- /dev/null +++ b/docs/content/en/functions/path/Base.md @@ -0,0 +1,20 @@ +--- +title: path.Base +description: Replaces path separators with slashes (`/`) and returns the last element of the given path. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [path.Base PATH] +aliases: [/functions/path.base] +--- + +```go-html-template +{{ path.Base "a/news.html" }} → news.html +{{ path.Base "news.html" }} → news.html +{{ path.Base "a/b/c" }} → c +{{ path.Base "/x/y/z/" }} → z +{{ path.Base "" }} → . +``` diff --git a/docs/content/en/functions/path/BaseName.md b/docs/content/en/functions/path/BaseName.md new file mode 100644 index 000000000..468898a6f --- /dev/null +++ b/docs/content/en/functions/path/BaseName.md @@ -0,0 +1,20 @@ +--- +title: path.BaseName +description: Replaces path separators with slashes (`/`) and returns the last element of the given path, removing the extension if present. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [path.BaseName PATH] +aliases: [/functions/path.basename] +--- + +```go-html-template +{{ path.BaseName "a/news.html" }} → news +{{ path.BaseName "news.html" }} → news +{{ path.BaseName "a/b/c" }} → c +{{ path.BaseName "/x/y/z/" }} → z +{{ path.BaseName "" }} → . +``` diff --git a/docs/content/en/functions/path/Clean.md b/docs/content/en/functions/path/Clean.md new file mode 100644 index 000000000..b9f2de038 --- /dev/null +++ b/docs/content/en/functions/path/Clean.md @@ -0,0 +1,27 @@ +--- +title: path.Clean +description: Replaces path separators with slashes (`/`) and returns the shortest path name equivalent to the given path. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [path.Clean PATH] +aliases: [/functions/path.clean] +--- + +See Go's [`path.Clean`] documentation for details. + +[`path.Clean`]: https://pkg.go.dev/path#Clean + +```go-html-template +{{ path.Clean "foo/bar" }} → foo/bar +{{ path.Clean "/foo/bar" }} → /foo/bar +{{ path.Clean "/foo/bar/" }} → /foo/bar +{{ path.Clean "/foo//bar/" }} → /foo/bar +{{ path.Clean "/foo/./bar/" }} → /foo/bar +{{ path.Clean "/foo/../bar/" }} → /bar +{{ path.Clean "/../foo/../bar/" }} → /bar +{{ path.Clean "" }} → . +``` diff --git a/docs/content/en/functions/path/Dir.md b/docs/content/en/functions/path/Dir.md new file mode 100644 index 000000000..04d5500f5 --- /dev/null +++ b/docs/content/en/functions/path/Dir.md @@ -0,0 +1,21 @@ +--- +title: path.Dir +description: Replaces path separators with slashes (/) and returns all but the last element of the given path. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [path.Dir PATH] +aliases: [/functions/path.dir] +--- + +```go-html-template +{{ path.Dir "a/news.html" }} → a +{{ path.Dir "news.html" }} → . +{{ path.Dir "a/b/c" }} → a/b +{{ path.Dir "/a/b/c" }} → /a/b +{{ path.Dir "/a/b/c/" }} → /a/b/c +{{ path.Dir "" }} → . +``` diff --git a/docs/content/en/functions/path/Ext.md b/docs/content/en/functions/path/Ext.md new file mode 100644 index 000000000..3646d02d0 --- /dev/null +++ b/docs/content/en/functions/path/Ext.md @@ -0,0 +1,18 @@ +--- +title: path.Ext +description: Replaces path separators with slashes (`/`) and returns the file name extension of the given path. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [path.Ext PATH] +aliases: [/functions/path.ext] +--- + +The extension is the suffix beginning at the final dot in the final slash-separated element of path; it is empty if there is no dot. + +```go-html-template +{{ path.Ext "a/b/c/news.html" }} → .html +``` diff --git a/docs/content/en/functions/path/Join.md b/docs/content/en/functions/path/Join.md new file mode 100644 index 000000000..bda46737f --- /dev/null +++ b/docs/content/en/functions/path/Join.md @@ -0,0 +1,28 @@ +--- +title: path.Join +description: Replaces path separators with slashes (`/`), joins the given path elements into a single path, and returns the shortest path name equivalent to the result. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [path.Join ELEMENT...] +aliases: [/functions/path.join] +--- + +See Go's [`path.Join`] and [`path.Clean`] documentation for details. + +[`path.Clean`]: https://pkg.go.dev/path#Clean +[`path.Join`]: https://pkg.go.dev/path#Join + +```go-html-template +{{ path.Join "partial" "news.html" }} → partial/news.html +{{ path.Join "partial/" "news.html" }} → partial/news.html +{{ path.Join "foo/bar" "baz" }} → foo/bar/baz +{{ path.Join "foo" "bar" "baz" }} → foo/bar/baz +{{ path.Join "foo" "" "baz" }} → foo/baz +{{ path.Join "foo" "." "baz" }} → foo/baz +{{ path.Join "foo" ".." "baz" }} → baz +{{ path.Join "/.." "foo" ".." "baz" }} → baz +``` diff --git a/docs/content/en/functions/path/Split.md b/docs/content/en/functions/path/Split.md new file mode 100644 index 000000000..d4f8d08e0 --- /dev/null +++ b/docs/content/en/functions/path/Split.md @@ -0,0 +1,28 @@ +--- +title: path.Split +description: Replaces path separators with slashes (`/`) and splits the resulting path immediately following the final slash, separating it into a directory and file name component. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: paths.DirFile + signatures: [path.Split PATH] +aliases: [/functions/path.split] +--- + +If there is no slash in the given path, `path.Split` returns an empty directory, and file set to path. The returned values have the property that path = dir+file. + +```go-html-template +{{ $dirFile := path.Split "a/news.html" }} +{{ $dirFile.Dir }} → a/ +{{ $dirFile.File }} → news.html + +{{ $dirFile := path.Split "news.html" }} +{{ $dirFile.Dir }} → "" (empty string) +{{ $dirFile.File }} → news.html + +{{ $dirFile := path.Split "a/b/c" }} +{{ $dirFile.Dir }} → a/b/ +{{ $dirFile.File }} → c +``` diff --git a/docs/content/en/functions/path/_index.md b/docs/content/en/functions/path/_index.md new file mode 100644 index 000000000..49b2927ce --- /dev/null +++ b/docs/content/en/functions/path/_index.md @@ -0,0 +1,7 @@ +--- +title: Path functions +linkTitle: path +description: Use these functions to work with file paths. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/reflect/IsMap.md b/docs/content/en/functions/reflect/IsMap.md new file mode 100644 index 000000000..55b9811d7 --- /dev/null +++ b/docs/content/en/functions/reflect/IsMap.md @@ -0,0 +1,17 @@ +--- +title: reflect.IsMap +description: Reports whether the given value is a map. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [reflect.IsMap INPUT] +aliases: [/functions/reflect.ismap] +--- + +```go-html-template +{{ reflect.IsMap (dict "key" "value") }} → true +{{ reflect.IsMap "yo" }} → false +``` diff --git a/docs/content/en/functions/reflect/IsSlice.md b/docs/content/en/functions/reflect/IsSlice.md new file mode 100644 index 000000000..3a5c1229b --- /dev/null +++ b/docs/content/en/functions/reflect/IsSlice.md @@ -0,0 +1,17 @@ +--- +title: reflect.IsSlice +description: Reports whether the given value is a slice. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [reflect.IsSlice INPUT] +aliases: [/functions/reflect.isslice] +--- + +```go-html-template +{{ reflect.IsSlice (slice 1 2 3) }} → true +{{ reflect.IsSlice "yo" }} → false +``` diff --git a/docs/content/en/functions/reflect/_index.md b/docs/content/en/functions/reflect/_index.md new file mode 100644 index 000000000..58f00c3de --- /dev/null +++ b/docs/content/en/functions/reflect/_index.md @@ -0,0 +1,7 @@ +--- +title: Reflect functions +linkTitle: reflect +description: Use these functions to determine a value's data type. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/resources/Babel.md b/docs/content/en/functions/resources/Babel.md new file mode 100644 index 000000000..799823fc5 --- /dev/null +++ b/docs/content/en/functions/resources/Babel.md @@ -0,0 +1,18 @@ +--- +title: resources.Babel +description: Compiles the given JavaScript resource with Babel. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: ['resources.Babel [OPTIONS] RESOURCE'] +expiryDate: 2026-06-24 # deprecated 2024-06-24 in v0.128.0 +--- + +{{< deprecated-in 0.128.0 >}} +Use [`js.Babel`] instead. + +[`js.Babel`]: /functions/js/babel/ +{{< /deprecated-in >}} diff --git a/docs/content/en/functions/resources/ByType.md b/docs/content/en/functions/resources/ByType.md new file mode 100644 index 000000000..99e2b9771 --- /dev/null +++ b/docs/content/en/functions/resources/ByType.md @@ -0,0 +1,27 @@ +--- +title: resources.ByType +description: Returns a collection of global resources of the given media type, or nil if none found. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resources + signatures: [resources.ByType MEDIATYPE] +--- + +The [media type] is typically one of `image`, `text`, `audio`, `video`, or `application`. + +```go-html-template +{{ range resources.ByType "image" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +> [!note] +> This function operates on global resources. A global resource is a file within the `assets` directory, or within any directory mounted to the `assets` directory. +> +> For page resources, use the [`Resources.ByType`] method on a `Page` object. + +[`Resources.ByType`]: /methods/page/resources/ +[media type]: https://en.wikipedia.org/wiki/Media_type diff --git a/docs/content/en/functions/resources/Concat.md b/docs/content/en/functions/resources/Concat.md new file mode 100644 index 000000000..fe7226e1b --- /dev/null +++ b/docs/content/en/functions/resources/Concat.md @@ -0,0 +1,26 @@ +--- +title: resources.Concat +description: Returns a concatenated slice of resources. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: ['resources.Concat TARGETPATH [RESOURCE...]'] +--- + +The `resources.Concat` function returns a concatenated slice of resources, caching the result using the target path as its cache key. Each resource must have the same [media type]. + +Hugo publishes the resource to the target path when you call its [`Publish`], [`Permalink`], or [`RelPermalink`] method. + +[media type]: https://en.wikipedia.org/wiki/Media_type +[`publish`]: /methods/resource/publish/ +[`permalink`]: /methods/resource/permalink/ +[`relpermalink`]: /methods/resource/relpermalink/ + +```go-html-template +{{ $plugins := resources.Get "js/plugins.js" }} +{{ $global := resources.Get "js/global.js" }} +{{ $js := slice $plugins $global | resources.Concat "js/bundle.js" }} +``` diff --git a/docs/content/en/functions/resources/Copy.md b/docs/content/en/functions/resources/Copy.md new file mode 100644 index 000000000..220a3db4c --- /dev/null +++ b/docs/content/en/functions/resources/Copy.md @@ -0,0 +1,27 @@ +--- +title: resources.Copy +description: Copies the given resource to the target path. +categories: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: [resources.Copy TARGETPATH RESOURCE] +--- + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ with resources.Copy "img/new-image-name.jpg" . }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +The relative URL of the new published resource will be: + +```text +/img/new-image-name.jpg +``` + +> [!note] +> Use the `resources.Copy` function with global, page, and remote resources. diff --git a/docs/content/en/functions/resources/ExecuteAsTemplate.md b/docs/content/en/functions/resources/ExecuteAsTemplate.md new file mode 100644 index 000000000..bff83832e --- /dev/null +++ b/docs/content/en/functions/resources/ExecuteAsTemplate.md @@ -0,0 +1,61 @@ +--- +title: resources.ExecuteAsTemplate +description: Returns a resource created from a Go template, parsed and executed with the given context. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: [resources.ExecuteAsTemplate TARGETPATH CONTEXT RESOURCE] +--- + +The `resources.ExecuteAsTemplate` function returns a resource created from a Go template, parsed and executed with the given context, 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. + +Let's say you have a CSS file that you wish to populate with values from your site configuration: + +```go-html-template {file="assets/css/template.css"} +body { + background-color: {{ site.Params.style.bg_color }}; + color: {{ site.Params.style.text_color }}; +} +``` + +And your site configuration contains: + +{{< code-toggle file=hugo >}} +[params.style] +bg_color = '#fefefe' +text_color = '#222' +{{< /code-toggle >}} + +Place this in your baseof.html template: + +```go-html-template +{{ with resources.Get "css/template.css" }} + {{ with resources.ExecuteAsTemplate "css/main.css" $ . }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> + {{ end }} +{{ end }} +``` + +The example above: + +1. Captures the template as a resource +1. Executes the resource as a template, passing the current page in context +1. Publishes the resource to css/main.css + +The result is: + +```css {file="public/css/main.css"} +body { + background-color: #fefefe; + color: #222; +} +``` + +[`publish`]: /methods/resource/publish/ +[`permalink`]: /methods/resource/permalink/ +[`relpermalink`]: /methods/resource/relpermalink/ diff --git a/docs/content/en/functions/resources/Fingerprint.md b/docs/content/en/functions/resources/Fingerprint.md new file mode 100644 index 000000000..6757a0b6f --- /dev/null +++ b/docs/content/en/functions/resources/Fingerprint.md @@ -0,0 +1,36 @@ +--- +title: resources.Fingerprint +description: Cryptographically hashes the content of the given resource. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [fingerprint] + returnType: resource.Resource + signatures: ['resources.Fingerprint [ALGORITHM] RESOURCE'] +--- + +```go-html-template +{{ with resources.Get "js/main.js" }} + {{ with . | fingerprint "sha256" }} + <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script> + {{ end }} +{{ end }} +``` + +Hugo renders this to something like: + +```html +<script src="/js/main.62e...df1.js" integrity="sha256-Yuh...rfE=" crossorigin="anonymous"></script> +``` + +Although most commonly used with CSS and JavaScript resources, you can use the `resources.Fingerprint` function with any resource type. + +The hash algorithm may be one of `md5`, `sha256` (default), `sha384`, or `sha512`. + +After cryptographically hashing the resource content: + +1. The values returned by the `.Permalink` and `.RelPermalink` methods include the hash sum +1. The resource's `.Data.Integrity` method returns a [Subresource Integrity] (SRI) value consisting of the name of the hash algorithm, one hyphen, and the base64-encoded hash sum + +[Subresource Integrity]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity diff --git a/docs/content/en/functions/resources/FromString.md b/docs/content/en/functions/resources/FromString.md new file mode 100644 index 000000000..4cd04f609 --- /dev/null +++ b/docs/content/en/functions/resources/FromString.md @@ -0,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-01-16T19:14:41-08:00", + "hugo_version": "0.141.0", + "last_modified": "2025-01-16T19:14:46-08: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 --git a/docs/content/en/functions/resources/Get.md b/docs/content/en/functions/resources/Get.md new file mode 100644 index 000000000..db91f0a9a --- /dev/null +++ b/docs/content/en/functions/resources/Get.md @@ -0,0 +1,24 @@ +--- +title: resources.Get +description: Returns a global resource from the given path, or nil if none found. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: [resources.Get PATH] +--- + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +> [!note] +> This function operates on global resources. A global resource is a file within the `assets` directory, or within any directory mounted to the `assets` directory. +> +> For page resources, use the [`Resources.Get`] method on a `Page` object. + +[`Resources.Get`]: /methods/page/resources/ diff --git a/docs/content/en/functions/resources/GetMatch.md b/docs/content/en/functions/resources/GetMatch.md new file mode 100644 index 000000000..8f1b004fe --- /dev/null +++ b/docs/content/en/functions/resources/GetMatch.md @@ -0,0 +1,28 @@ +--- +title: resources.GetMatch +description: Returns the first global resource from paths matching the given glob pattern, or nil if none found. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: [resources.GetMatch PATTERN] +--- + +```go-html-template +{{ with resources.GetMatch "images/*.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +> [!note] +> This function operates on global resources. A global resource is a file within the `assets` directory, or within any directory mounted to the `assets` directory. +> +> For page resources, use the [`Resources.GetMatch`] method on a `Page` object. + +Hugo determines a match using a case-insensitive [glob](g) pattern. + +{{% include "/_common/glob-patterns.md" %}} + +[`Resources.GetMatch`]: /methods/page/resources/ diff --git a/docs/content/en/functions/resources/GetRemote.md b/docs/content/en/functions/resources/GetRemote.md new file mode 100644 index 000000000..c6f6742b3 --- /dev/null +++ b/docs/content/en/functions/resources/GetRemote.md @@ -0,0 +1,236 @@ +--- +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 }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ 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. + +###### key + +(`string`) The cache key. Hugo derives the default value from the URL and options map. See [caching](#caching). + +###### method + +(`string`) The action to perform on the requested resource, typically one of `GET`, `POST`, or `HEAD`. + +###### responseHeaders +{{< new-in 0.143.0 />}} + +(`[]string`) The headers to extract from the server's response, accessible through the resource's [`Data.Headers`] method. Header name matching is case-insensitive. + +[`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 }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ 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 }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ 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 diff --git a/docs/content/en/functions/resources/Match.md b/docs/content/en/functions/resources/Match.md new file mode 100644 index 000000000..6c7d83649 --- /dev/null +++ b/docs/content/en/functions/resources/Match.md @@ -0,0 +1,29 @@ +--- +title: resources.Match +description: Returns a collection of global resources from paths matching the given glob pattern, or nil if none found. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resources + signatures: [resources.Match PATTERN] +--- + +```go-html-template +{{ range resources.Match "images/*.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +> [!note] +> This function operates on global resources. A global resource is a file within the `assets` directory, or within any directory mounted to the `assets` directory. +> +> For page resources, use the [`Resources.Match`] method on a `Page` object. + +Hugo determines a match using a case-insensitive [glob pattern]. + +{{% include "/_common/glob-patterns.md" %}} + +[`Resources.Match`]: /methods/page/resources/ +[glob pattern]: https://github.com/gobwas/glob#example diff --git a/docs/content/en/functions/resources/Minify.md b/docs/content/en/functions/resources/Minify.md new file mode 100644 index 000000000..183e6671a --- /dev/null +++ b/docs/content/en/functions/resources/Minify.md @@ -0,0 +1,18 @@ +--- +title: resources.Minify +description: Minifies the given resource. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [minify] + returnType: resource.Resource + signatures: [resources.Minify RESOURCE] +--- + +```go-html-template +{{ $css := resources.Get "css/main.css" }} +{{ $style := $css | minify }} +``` + +Any CSS, JS, JSON, HTML, SVG, or XML resource can be minified using resources.Minify which takes for argument the resource object. diff --git a/docs/content/en/functions/resources/PostCSS.md b/docs/content/en/functions/resources/PostCSS.md new file mode 100644 index 000000000..3ec0b84cf --- /dev/null +++ b/docs/content/en/functions/resources/PostCSS.md @@ -0,0 +1,18 @@ +--- +title: resources.PostCSS +description: Processes the given resource with PostCSS using any PostCSS plugin. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: ['resources.PostCSS [OPTIONS] RESOURCE'] +expiryDate: 2026-06-24 # deprecated 2024-06-24 in v0.128.0 +--- + +{{< deprecated-in 0.128.0 >}} +Use [`css.PostCSS`] instead. + +[`css.PostCSS`]: /functions/css/postcss/ +{{< /deprecated-in >}} diff --git a/docs/content/en/functions/resources/PostProcess.md b/docs/content/en/functions/resources/PostProcess.md new file mode 100644 index 000000000..d70437694 --- /dev/null +++ b/docs/content/en/functions/resources/PostProcess.md @@ -0,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 + +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 +``` + +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 >}} + +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]. + +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 }} + <link rel="stylesheet" href="{{ .RelPermalink }}"> + {{ else }} + {{ with . | postCSS | minify | fingerprint | resources.PostProcess }} + <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"> + {{ end }} + {{ end }} +{{ end }} +``` + +## 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". + +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 --git a/docs/content/en/functions/resources/ToCSS.md b/docs/content/en/functions/resources/ToCSS.md new file mode 100644 index 000000000..7be1b8d45 --- /dev/null +++ b/docs/content/en/functions/resources/ToCSS.md @@ -0,0 +1,18 @@ +--- +title: resources.ToCSS +description: Transpiles Sass to CSS. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: resource.Resource + signatures: ['resources.ToCSS [OPTIONS] RESOURCE'] +expiryDate: 2026-06-24 # deprecated 2024-06-24 in v0.128.0 +--- + +{{< deprecated-in 0.128.0 >}} +Use [`css.Sass`] instead. + +[`css.Sass`]: /functions/css/sass/ +{{< /deprecated-in >}} diff --git a/docs/content/en/functions/resources/_index.md b/docs/content/en/functions/resources/_index.md new file mode 100644 index 000000000..030cafd42 --- /dev/null +++ b/docs/content/en/functions/resources/_index.md @@ -0,0 +1,7 @@ +--- +title: Resource functions +linkTitle: resources +description: Use these functions to work with resources. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/safe/CSS.md b/docs/content/en/functions/safe/CSS.md new file mode 100644 index 000000000..12ebbf8aa --- /dev/null +++ b/docs/content/en/functions/safe/CSS.md @@ -0,0 +1,62 @@ +--- +title: safe.CSS +description: Declares the given string as a safe CSS string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [safeCSS] + returnType: template.CSS + signatures: [safe.CSS INPUT] +aliases: [/functions/safecss] +--- + +## Introduction + +{{% include "/_common/functions/go-html-template-package.md" %}} + +## Usage + +Use the `safe.CSS` function to encapsulate known safe content that matches any of: + +1. The CSS3 stylesheet production, such as `p { color: purple }`. +1. The CSS3 rule production, such as `a[href=~"https:"].foo#bar`. +1. CSS3 declaration productions, such as `color: red; margin: 2px`. +1. The CSS3 value production, such as `rgba(0, 0, 255, 127)`. + +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +See the [Go documentation] for details. + +## Example + +Without a safe declaration: + +```go-html-template +{{ $style := "color: red;" }} +<p style="{{ $style }}">foo</p> +``` + +Hugo renders the above to: + +```html +<p style="ZgotmplZ">foo</p> +``` + +> [!note] +> `ZgotmplZ` is a special value that indicates that unsafe content reached a CSS or URL context at runtime. + +To declare the string as safe: + +```go-html-template +{{ $style := "color: red;" }} +<p style="{{ $style | safeCSS }}">foo</p> +``` + +Hugo renders the above to: + +```html +<p style="color: red;">foo</p> +``` + +[Go documentation]: https://pkg.go.dev/html/template#CSS diff --git a/docs/content/en/functions/safe/HTML.md b/docs/content/en/functions/safe/HTML.md new file mode 100644 index 000000000..25ffb3318 --- /dev/null +++ b/docs/content/en/functions/safe/HTML.md @@ -0,0 +1,54 @@ +--- +title: safe.HTML +description: Declares the given string as a safeHTML string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [safeHTML] + returnType: template.HTML + signatures: [safe.HTML INPUT] +aliases: [/functions/safehtml] +--- + +## Introduction + +{{% include "/_common/functions/go-html-template-package.md" %}} + +## Usage + +Use the `safe.HTML` function to encapsulate a known safe HTML document fragment. It should not be used for HTML from a third-party, or HTML with unclosed tags or comments. + +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +See the [Go documentation] for details. + +[Go documentation]: https://pkg.go.dev/html/template#HTML + +## Example + +Without a safe declaration: + +```go-html-template +{{ $html := "<em>emphasized</em>" }} +{{ $html }} +``` + +Hugo renders the above to: + +```html +<em>emphasized</em> +``` + +To declare the string as safe: + +```go-html-template +{{ $html := "<em>emphasized</em>" }} +{{ $html | safeHTML }} +``` + +Hugo renders the above to: + +```html +<em>emphasized</em> +``` diff --git a/docs/content/en/functions/safe/HTMLAttr.md b/docs/content/en/functions/safe/HTMLAttr.md new file mode 100644 index 000000000..7cfefdfb2 --- /dev/null +++ b/docs/content/en/functions/safe/HTMLAttr.md @@ -0,0 +1,60 @@ +--- +title: safe.HTMLAttr +description: Declares the given key-value pair as a safe HTML attribute. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [safeHTMLAttr] + returnType: template.HTMLAttr + signatures: [safe.HTMLAttr INPUT] +aliases: [/functions/safehtmlattr] +--- + +## Introduction + +{{% include "/_common/functions/go-html-template-package.md" %}} + +## Usage + +Use the `safe.HTMLAttr` function to encapsulate an HTML attribute from a trusted source. + +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +See the [Go documentation] for details. + +[Go documentation]: https://pkg.go.dev/html/template#HTMLAttr + +## Example + +Without a safe declaration: + +```go-html-template +{{ with .Date }} + {{ $humanDate := time.Format "2 Jan 2006" . }} + {{ $machineDate := time.Format "2006-01-02T15:04:05-07:00" . }} + <time datetime="{{ $machineDate }}">{{ $humanDate }}</time> +{{ end }} +``` + +Hugo renders the above to: + +```html +<time datetime="2024-05-26T07:19:55+02:00">26 May 2024</time> +``` + +To declare the key-value pair as safe: + +```go-html-template +{{ with .Date }} + {{ $humanDate := time.Format "2 Jan 2006" . }} + {{ $machineDate := time.Format "2006-01-02T15:04:05-07:00" . }} + <time {{ printf "datetime=%q" $machineDate | safeHTMLAttr }}>{{ $humanDate }}</time> +{{ end }} +``` + +Hugo renders the above to: + +```html +<time datetime="2024-05-26T07:19:55+02:00">26 May 2024</time> +``` diff --git a/docs/content/en/functions/safe/JS.md b/docs/content/en/functions/safe/JS.md new file mode 100644 index 000000000..0c4d9009d --- /dev/null +++ b/docs/content/en/functions/safe/JS.md @@ -0,0 +1,60 @@ +--- +title: safe.JS +description: Declares the given string as a safe JavaScript expression. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [safeJS] + returnType: template.JS + signatures: [safe.JS INPUT] +aliases: [/functions/safejs] +--- + +## Introduction + +{{% include "/_common/functions/go-html-template-package.md" %}} + +## Usage + +Use the `safe.JS` function to encapsulate a known safe EcmaScript5 Expression. + +Template authors are responsible for ensuring that typed expressions do not break the intended precedence and that there is no statement/expression ambiguity as when passing an expression like `{ foo: bar() }\n['foo']()`, which is both a valid Expression and a valid Program with a very different meaning. + +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +Using the `safe.JS` function to include valid but untrusted JSON is not safe. A safe alternative is to parse the JSON with the [`transform.Unmarshal`] function and then pass the resultant object into the template, where it will be converted to sanitized JSON when presented in a JavaScript context. + +[`transform.Unmarshal`]: /functions/transform/unmarshal/ + +See the [Go documentation] for details. + +[Go documentation]: https://pkg.go.dev/html/template#JS + +## Example + +Without a safe declaration: + +```go-html-template +{{ $js := "x + y" }} +<script>const a = {{ $js }}</script> +``` + +Hugo renders the above to: + +```html +<script>const a = "x + y"</script> +``` + +To declare the string as safe: + +```go-html-template +{{ $js := "x + y" }} +<script>const a = {{ $js | safeJS }}</script> +``` + +Hugo renders the above to: + +```html +<script>const a = x + y</script> +``` diff --git a/docs/content/en/functions/safe/JSStr.md b/docs/content/en/functions/safe/JSStr.md new file mode 100644 index 000000000..81946a14c --- /dev/null +++ b/docs/content/en/functions/safe/JSStr.md @@ -0,0 +1,62 @@ +--- +title: safe.JSStr +description: Declares the given string as a safe JavaScript string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [safeJSStr] + returnType: template.JSStr + signatures: [safe.JSStr INPUT] +aliases: [/functions/safejsstr] +--- + +## Introduction + +{{% include "/_common/functions/go-html-template-package.md" %}} + +## Usage + +Use the `safe.JSStr` function to encapsulate a sequence of characters meant to be embedded between quotes in a JavaScript expression. + +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +See the [Go documentation] for details. + +[Go documentation]: https://pkg.go.dev/html/template#JSStr + +## Example + +Without a safe declaration: + +```go-html-template +{{ $title := "Lilo & Stitch" }} +<script> + const a = "Title: " + {{ $title }}; +</script> +``` + +Hugo renders the above to: + +```html +<script> + const a = "Title: " + "Lilo \u0026 Stitch"; +</script> +``` + +To declare the string as safe: + +```go-html-template +{{ $title := "Lilo & Stitch" }} +<script> + const a = "Title: " + {{ $title | safeJSStr }}; +</script> +``` + +Hugo renders the above to: + +```html +<script> + const a = "Title: " + "Lilo & Stitch"; +</script> +``` diff --git a/docs/content/en/functions/safe/URL.md b/docs/content/en/functions/safe/URL.md new file mode 100644 index 000000000..44bed8064 --- /dev/null +++ b/docs/content/en/functions/safe/URL.md @@ -0,0 +1,61 @@ +--- +title: safe.URL +description: Declares the given string as a safe URL or URL substring. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [safeURL] + returnType: template.URL + signatures: [safe.URL INPUT] +aliases: [/functions/safeurl] +--- + +## Introduction + +{{% include "/_common/functions/go-html-template-package.md" %}} + +## Usage + +Use the `safe.URL` function to encapsulate a known safe URL or URL substring. Schemes other than the following are considered unsafe: + +- `http:` +- `https:` +- `mailto:` + +Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output. + +See the [Go documentation] for details. + +## Example + +Without a safe declaration: + +```go-html-template +{{ $href := "irc://irc.freenode.net/#golang" }} +<a href="{{ $href }}">IRC</a> +``` + +Hugo renders the above to: + +```html +<a href="#ZgotmplZ">IRC</a> +``` + +> [!note] +> `ZgotmplZ` is a special value that indicates that unsafe content reached a CSS or URL context at runtime. + +To declare the string as safe: + +```go-html-template +{{ $href := "irc://irc.freenode.net/#golang" }} +<a href="{{ $href | safeURL }}">IRC</a> +``` + +Hugo renders the above to: + +```html +<a href="irc://irc.freenode.net/#golang">IRC</a> +``` + +[Go documentation]: https://pkg.go.dev/html/template#URL diff --git a/docs/content/en/functions/safe/_index.md b/docs/content/en/functions/safe/_index.md new file mode 100644 index 000000000..8d5697b8d --- /dev/null +++ b/docs/content/en/functions/safe/_index.md @@ -0,0 +1,7 @@ +--- +title: Safe functions +linkTitle: safe +description: Use these functions to declare a value as safe in the context of Go's html/template package. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/strings/Chomp.md b/docs/content/en/functions/strings/Chomp.md new file mode 100644 index 000000000..1ff2b7f47 --- /dev/null +++ b/docs/content/en/functions/strings/Chomp.md @@ -0,0 +1,22 @@ +--- +title: strings.Chomp +description: Returns the given string, removing all trailing newline characters and carriage returns. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [chomp] + returnType: any + signatures: [strings.Chomp STRING] +aliases: [/functions/chomp] +--- + +If the argument is of type `template.HTML`, returns `template.HTML`, else returns a `string`. + +```go-html-template +{{ chomp "foo\n" }} → foo +{{ chomp "foo\n\n" }} → foo + +{{ chomp "foo\r\n" }} → foo +{{ chomp "foo\r\n\r\n" }} → foo +``` diff --git a/docs/content/en/functions/strings/Contains.md b/docs/content/en/functions/strings/Contains.md new file mode 100644 index 000000000..e0e3b087c --- /dev/null +++ b/docs/content/en/functions/strings/Contains.md @@ -0,0 +1,22 @@ +--- +title: strings.Contains +description: Reports whether the given string contains the given substring. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [strings.Contains STRING SUBSTRING] +aliases: [/functions/strings.contains] +--- + +```go-html-template +{{ strings.Contains "Hugo" "go" }} → true +``` + +The check is case sensitive: + +```go-html-template +{{ strings.Contains "Hugo" "Go" }} → false +``` diff --git a/docs/content/en/functions/strings/ContainsAny.md b/docs/content/en/functions/strings/ContainsAny.md new file mode 100644 index 000000000..521ff3421 --- /dev/null +++ b/docs/content/en/functions/strings/ContainsAny.md @@ -0,0 +1,22 @@ +--- +title: strings.ContainsAny +description: Reports whether the given string contains any character within the given set. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [strings.ContainsAny STRING SET] +aliases: [/functions/strings.containsany] +--- + +```go-html-template +{{ strings.ContainsAny "Hugo" "gm" }} → true +``` + +The check is case sensitive: + +```go-html-template +{{ strings.ContainsAny "Hugo" "Gm" }} → false +``` diff --git a/docs/content/en/functions/strings/ContainsNonSpace.md b/docs/content/en/functions/strings/ContainsNonSpace.md new file mode 100644 index 000000000..7b8dcb730 --- /dev/null +++ b/docs/content/en/functions/strings/ContainsNonSpace.md @@ -0,0 +1,22 @@ +--- +title: strings.ContainsNonSpace +description: Reports whether the given string contains any non-space characters as defined by Unicode. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [strings.ContainsNonSpace STRING] +aliases: [/functions/strings.containsnonspace] +--- + +Whitespace characters include `\t`, `\n`, `\v`, `\f`, `\r`, and characters in the [Unicode Space Separator] category. + +[Unicode Space Separator]: https://www.compart.com/en/unicode/category/Zs + +```go-html-template +{{ strings.ContainsNonSpace "\n" }} → false +{{ strings.ContainsNonSpace " " }} → false +{{ strings.ContainsNonSpace "\n abc" }} → true +``` diff --git a/docs/content/en/functions/strings/Count.md b/docs/content/en/functions/strings/Count.md new file mode 100644 index 000000000..76378b27d --- /dev/null +++ b/docs/content/en/functions/strings/Count.md @@ -0,0 +1,21 @@ +--- +title: strings.Count +description: Returns the number of non-overlapping instances of the given substring within the given string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: int + signatures: [strings.Count SUBSTR STRING] +aliases: [/functions/strings.count] +--- + +If `SUBSTR` is an empty string, this function returns 1 plus the number of Unicode code points in `STRING`. + +```go-html-template +{{ "aaabaab" | strings.Count "a" }} → 5 +{{ "aaabaab" | strings.Count "aa" }} → 2 +{{ "aaabaab" | strings.Count "aaa" }} → 1 +{{ "aaabaab" | strings.Count "" }} → 8 +``` diff --git a/docs/content/en/functions/strings/CountRunes.md b/docs/content/en/functions/strings/CountRunes.md new file mode 100644 index 000000000..8ad6b00da --- /dev/null +++ b/docs/content/en/functions/strings/CountRunes.md @@ -0,0 +1,20 @@ +--- +title: strings.CountRunes +description: Returns the number of runes in the given string excluding whitespace. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [countrunes] + returnType: int + signatures: [strings.CountRunes INPUT] +aliases: [/functions/countrunes] +--- + +In contrast with the [`strings.RuneCount`] function, which counts every rune in a string, `strings.CountRunes` excludes whitespace. + +```go-html-template +{{ "Hello, 世界" | strings.CountRunes }} → 8 +``` + +[`strings.RuneCount`]: /functions/strings/runecount/ diff --git a/docs/content/en/functions/strings/CountWords.md b/docs/content/en/functions/strings/CountWords.md new file mode 100644 index 000000000..e50febf69 --- /dev/null +++ b/docs/content/en/functions/strings/CountWords.md @@ -0,0 +1,16 @@ +--- +title: strings.CountWords +description: Returns the number of words in the given string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [countwords] + returnType: int + signatures: [strings.CountWords INPUT] +aliases: [/functions/countwords] +--- + +```go-html-template +{{ "Hugo is a static site generator." | countwords }} → 6 +``` diff --git a/docs/content/en/functions/strings/Diff/diff-screen-capture.png b/docs/content/en/functions/strings/Diff/diff-screen-capture.png Binary files differnew file mode 100644 index 000000000..62baa4563 --- /dev/null +++ b/docs/content/en/functions/strings/Diff/diff-screen-capture.png diff --git a/docs/content/en/functions/strings/Diff/index.md b/docs/content/en/functions/strings/Diff/index.md new file mode 100644 index 000000000..1426764a9 --- /dev/null +++ b/docs/content/en/functions/strings/Diff/index.md @@ -0,0 +1,33 @@ +--- +title: strings.Diff +description: Returns an anchored diff of the two texts OLD and NEW in the unified diff format. If OLD and NEW are identical, returns an empty string. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [strings.Diff OLDNAME OLD NEWNAME NEW] +--- + +{{< new-in 0.125.0 />}} + +Use `strings.Diff` to compare two strings and render a highlighted diff: + +```go-html-template +{{ $want := ` +<p>The product of 6 and 7 is 42.</p> +<p>The product of 7 and 6 is 42.</p> +`}} + +{{ $got := ` +<p>The product of 6 and 7 is 42.</p> +<p>The product of 7 and 6 is 13.</p> +`}} + +{{ $diff := strings.Diff "want" $want "got" $got }} +{{ transform.Highlight $diff "diff" }} +``` + +Rendered: + + diff --git a/docs/content/en/functions/strings/FindRESubmatch.md b/docs/content/en/functions/strings/FindRESubmatch.md new file mode 100644 index 000000000..d039607fb --- /dev/null +++ b/docs/content/en/functions/strings/FindRESubmatch.md @@ -0,0 +1,86 @@ +--- +title: strings.FindRESubmatch +description: Returns a slice of all successive matches of the regular expression. 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. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [findRESubmatch] + returnType: '[][]string' + signatures: ['strings.FindRESubmatch PATTERN INPUT [LIMIT]'] +aliases: [/functions/findresubmatch] +--- + +By default, `findRESubmatch` finds all matches. You can limit the number of matches with an optional LIMIT argument. A return value of nil indicates no match. + +{{% include "/_common/functions/regular-expressions.md" %}} + +## Demonstrative examples + +```go-html-template +{{ findRESubmatch `a(x*)b` "-ab-" }} → [["ab" ""]] +{{ findRESubmatch `a(x*)b` "-axxb-" }} → [["axxb" "xx"]] +{{ findRESubmatch `a(x*)b` "-ab-axb-" }} → [["ab" ""] ["axb" "x"]] +{{ findRESubmatch `a(x*)b` "-axxb-ab-" }} → [["axxb" "xx"] ["ab" ""]] +{{ findRESubmatch `a(x*)b` "-axxb-ab-" 1 }} → [["axxb" "xx"]] +``` + +## Practical example + +This Markdown: + +```text +- [Example](https://example.org) +- [Hugo](https://gohugo.io) +``` + +Produces this HTML: + +```html +<ul> + <li><a href="https://example.org">Example</a></li> + <li><a href="https://gohugo.io">Hugo</a></li> +</ul> +``` + +To match the anchor elements, capturing the link destination and text: + +```go-html-template +{{ $regex := `<a\s*href="(.+?)">(.+?)</a>` }} +{{ $matches := findRESubmatch $regex .Content }} +``` + +Viewed as JSON, the data structure of `$matches` in the code above is: + +```json +[ + [ + "<a href=\"https://example.org\"></a>Example</a>", + "https://example.org", + "Example" + ], + [ + "<a href=\"https://gohugo.io\">Hugo</a>", + "https://gohugo.io", + "Hugo" + ] +] +``` + +To render the `href` attributes: + +```go-html-template +{{ range $matches }} + {{ index . 1 }} +{{ end }} +``` + +Result: + +```text +https://example.org +https://gohugo.io +``` + +> [!note] +> You can write and test your regular expression using [regex101.com](https://regex101.com/). Be sure to select the Go flavor before you begin. diff --git a/docs/content/en/functions/strings/FindRe.md b/docs/content/en/functions/strings/FindRe.md new file mode 100644 index 000000000..45129ec91 --- /dev/null +++ b/docs/content/en/functions/strings/FindRe.md @@ -0,0 +1,32 @@ +--- +title: strings.FindRE +description: Returns a slice of strings that match the regular expression. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [findRE] + returnType: '[]string' + signatures: ['strings.FindRE PATTERN INPUT [LIMIT]'] +aliases: [/functions/findre] +--- +By default, `findRE` finds all matches. You can limit the number of matches with an optional LIMIT argument. + +{{% include "/_common/functions/regular-expressions.md" %}} + +This example returns a slice of all second level headings (`h2` elements) within the rendered `.Content`: + +```go-html-template +{{ findRE `(?s)<h2.*?>.*?</h2>` .Content }} +``` + +The `s` flag causes `.` to match `\n` as well, allowing us to find an `h2` element that contains newlines. + +To limit the number of matches to one: + +```go-html-template +{{ findRE `(?s)<h2.*?>.*?</h2>` .Content 1 }} +``` + +> [!note] +> You can write and test your regular expression using [regex101.com](https://regex101.com/). Be sure to select the Go flavor before you begin. diff --git a/docs/content/en/functions/strings/FirstUpper.md b/docs/content/en/functions/strings/FirstUpper.md new file mode 100644 index 000000000..41bf1f70a --- /dev/null +++ b/docs/content/en/functions/strings/FirstUpper.md @@ -0,0 +1,16 @@ +--- +title: strings.FirstUpper +description: Returns the given string, capitalizing the first character. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [strings.FirstUpper STRING] +aliases: [/functions/strings.firstupper] +--- + +```go-html-template +{{ strings.FirstUpper "foo" }} → Foo +``` diff --git a/docs/content/en/functions/strings/HasPrefix.md b/docs/content/en/functions/strings/HasPrefix.md new file mode 100644 index 000000000..2babe8552 --- /dev/null +++ b/docs/content/en/functions/strings/HasPrefix.md @@ -0,0 +1,16 @@ +--- +title: strings.HasPrefix +description: Reports whether the given string begins with the given prefix. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [hasPrefix] + returnType: bool + signatures: [strings.HasPrefix STRING PREFIX] +aliases: [/functions/hasprefix,/functions/strings.hasprefix] +--- + +```go-html-template +{{ hasPrefix "Hugo" "Hu" }} → true +``` diff --git a/docs/content/en/functions/strings/HasSuffix.md b/docs/content/en/functions/strings/HasSuffix.md new file mode 100644 index 000000000..c6b5f4ded --- /dev/null +++ b/docs/content/en/functions/strings/HasSuffix.md @@ -0,0 +1,16 @@ +--- +title: strings.HasSuffix +description: Reports whether the given string ends with the given suffix. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [hasSuffix] + returnType: bool + signatures: [strings.HasSuffix STRING SUFFIX] +aliases: [/functions/hassuffix,/functions/strings/hassuffix] +--- + +```go-html-template +{{ hasSuffix "Hugo" "go" }} → true +``` diff --git a/docs/content/en/functions/strings/Repeat.md b/docs/content/en/functions/strings/Repeat.md new file mode 100644 index 000000000..b6027368e --- /dev/null +++ b/docs/content/en/functions/strings/Repeat.md @@ -0,0 +1,16 @@ +--- +title: strings.Repeat +description: Returns a new string consisting of zero or more copies of another string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [strings.Repeat COUNT INPUT] +aliases: [/functions/strings.repeat] +--- + +```go-html-template +{{ strings.Repeat 3 "yo" }} → yoyoyo +``` diff --git a/docs/content/en/functions/strings/Replace.md b/docs/content/en/functions/strings/Replace.md new file mode 100644 index 000000000..b449ea84d --- /dev/null +++ b/docs/content/en/functions/strings/Replace.md @@ -0,0 +1,23 @@ +--- +title: strings.Replace +description: Returns a copy of INPUT, replacing all occurrences of OLD with NEW. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [replace] + returnType: string + signatures: ['strings.Replace INPUT OLD NEW [LIMIT]'] +aliases: [/functions/replace] +--- + +```go-html-template +{{ $s := "Batman and Robin" }} +{{ replace $s "Robin" "Catwoman" }} → Batman and Catwoman +``` + +Limit the number of replacements using the `LIMIT` argument: + +```go-html-template +{{ replace "aabbaabb" "a" "z" 2 }} → zzbbaabb +``` diff --git a/docs/content/en/functions/strings/ReplaceRE.md b/docs/content/en/functions/strings/ReplaceRE.md new file mode 100644 index 000000000..dba4bd15a --- /dev/null +++ b/docs/content/en/functions/strings/ReplaceRE.md @@ -0,0 +1,38 @@ +--- +title: strings.ReplaceRE +description: Returns a copy of INPUT, replacing all occurrences of a regular expression with a replacement pattern. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [replaceRE] + returnType: string + signatures: ['strings.ReplaceRE PATTERN REPLACEMENT INPUT [LIMIT]'] +aliases: [/functions/replacere] +--- + +{{% include "/_common/functions/regular-expressions.md" %}} + +```go-html-template +{{ $s := "a-b--c---d" }} +{{ replaceRE `(-{2,})` "-" $s }} → a-b-c-d +``` + +Limit the number of replacements using the LIMIT argument: + +```go-html-template +{{ $s := "a-b--c---d" }} +{{ replaceRE `(-{2,})` "-" $s 1 }} → a-b-c---d +``` + +Use `$1`, `$2`, etc. within the replacement string to insert the content of each capturing group within the regular expression: + +```go-html-template +{{ $s := "http://gohugo.io/docs" }} +{{ replaceRE "^https?://([^/]+).*" "$1" $s }} → gohugo.io +``` + +> [!note] +> You can write and test your regular expression using [regex101.com]. Be sure to select the Go flavor before you begin. + +[regex101.com]: https://regex101.com/ diff --git a/docs/content/en/functions/strings/RuneCount.md b/docs/content/en/functions/strings/RuneCount.md new file mode 100644 index 000000000..8c0e24342 --- /dev/null +++ b/docs/content/en/functions/strings/RuneCount.md @@ -0,0 +1,20 @@ +--- +title: strings.RuneCount +description: Returns the number of runes in the given string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: int + signatures: [strings.RuneCount INPUT] +aliases: [/functions/strings.runecount] +--- + +In contrast with the [`strings.CountRunes`] function, which excludes whitespace, `strings.RuneCount` counts every rune in a string. + +```go-html-template +{{ "Hello, 世界" | strings.RuneCount }} → 9 +``` + +[`strings.CountRunes`]: /functions/strings/countrunes/ diff --git a/docs/content/en/functions/strings/SliceString.md b/docs/content/en/functions/strings/SliceString.md new file mode 100644 index 000000000..69e4f6f33 --- /dev/null +++ b/docs/content/en/functions/strings/SliceString.md @@ -0,0 +1,24 @@ +--- +title: strings.SliceString +description: Returns a substring of the given string, beginning with the start position and ending before the end position. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [slicestr] + returnType: string + signatures: ['strings.SliceString STRING [START] [END]'] +aliases: [/functions/slicestr] +--- + +The START and END positions are zero-based, where `0` represents the first character of the string. If START is not specified, the substring will begin at position `0`. If END is not specified, the substring will end after the last character. + +```go-html-template +{{ slicestr "BatMan" }} → BatMan +{{ slicestr "BatMan" 3 }} → Man +{{ slicestr "BatMan" 0 3 }} → Bat +``` + +The START and END arguments represent the endpoints of a half-open [interval](g), a concept that may be difficult to grasp when first encountered. You may find that the [`strings.Substr`] function is easier to understand. + +[`strings.Substr`]: /functions/strings/substr/ diff --git a/docs/content/en/functions/strings/Split.md b/docs/content/en/functions/strings/Split.md new file mode 100644 index 000000000..bcab1b4d7 --- /dev/null +++ b/docs/content/en/functions/strings/Split.md @@ -0,0 +1,24 @@ +--- +title: strings.Split +description: Returns a slice of strings by splitting the given string by a delimiter. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [split] + returnType: '[]string' + signatures: [strings.Split STRING DELIM] +aliases: [/functions/split] +--- + +Examples: + +```go-html-template +{{ split "tag1,tag2,tag3" "," }} → ["tag1", "tag2", "tag3"] +{{ split "abc" "" }} → ["a", "b", "c"] +``` + +> [!note] +> The `strings.Split` function essentially does the opposite of the [`collections.Delimit`] function. While `split` creates a slice from a string, `delimit` creates a string from a slice. + +[`collections.Delimit`]: /functions/collections/delimit/ diff --git a/docs/content/en/functions/strings/Substr.md b/docs/content/en/functions/strings/Substr.md new file mode 100644 index 000000000..a4c779f7d --- /dev/null +++ b/docs/content/en/functions/strings/Substr.md @@ -0,0 +1,36 @@ +--- +title: strings.Substr +description: Returns a substring of the given string, beginning with the start position and ending after the given length. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [substr] + returnType: string + signatures: ['strings.Substr STRING [START] [LENGTH]'] +aliases: [/functions/substr] +--- + +The start position is zero-based, where `0` represents the first character of the string. If START is not specified, the substring will begin at position `0`. Specify a negative START position to extract characters from the end of the string. + +If LENGTH is not specified, the substring will include all characters from the START position to the end of the string. If negative, that number of characters will be omitted from the end of string. + +```go-html-template +{{ substr "abcdef" 0 }} → abcdef +{{ substr "abcdef" 1 }} → bcdef + +{{ substr "abcdef" 0 1 }} → a +{{ substr "abcdef" 1 1 }} → b + +{{ substr "abcdef" 0 -1 }} → abcde +{{ substr "abcdef" 1 -1 }} → bcde + +{{ substr "abcdef" -1 }} → f +{{ substr "abcdef" -2 }} → ef + +{{ substr "abcdef" -1 1 }} → f +{{ substr "abcdef" -2 1 }} → e + +{{ substr "abcdef" -3 -1 }} → de +{{ substr "abcdef" -3 -2 }} → d +``` diff --git a/docs/content/en/functions/strings/Title.md b/docs/content/en/functions/strings/Title.md new file mode 100644 index 000000000..d1b4aca01 --- /dev/null +++ b/docs/content/en/functions/strings/Title.md @@ -0,0 +1,29 @@ +--- +title: strings.Title +description: Returns the given string, converting it to title case. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [title] + returnType: string + signatures: [strings.Title STRING] +aliases: [/functions/title] +--- + +```go-html-template +{{ title "table of contents (TOC)" }} → Table of Contents (TOC) +``` + +By default, Hugo follows the capitalization rules published in the [Associated Press Stylebook]. Change your [site configuration] if you would prefer to: + +- Follow the capitalization rules published in the [Chicago Manual of Style] +- Capitalize the first letter of every word +- Capitalize the first letter of the first word +- Disable the effects of the `title` function + +The last option is useful if your theme uses the `title` function, and you would prefer to manually capitalize strings as needed. + +[Associated Press Stylebook]: https://www.apstylebook.com/ +[Chicago Manual of Style]: https://www.chicagomanualofstyle.org/home.html +[site configuration]: /configuration/all/#title-case-style diff --git a/docs/content/en/functions/strings/ToLower.md b/docs/content/en/functions/strings/ToLower.md new file mode 100644 index 000000000..c329b5e55 --- /dev/null +++ b/docs/content/en/functions/strings/ToLower.md @@ -0,0 +1,16 @@ +--- +title: strings.ToLower +description: Returns the given string, converting all characters to lowercase. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [lower] + returnType: string + signatures: [strings.ToLower INPUT] +aliases: [/functions/lower] +--- + +```go-html-template +{{ lower "BatMan" }} → batman +``` diff --git a/docs/content/en/functions/strings/ToUpper.md b/docs/content/en/functions/strings/ToUpper.md new file mode 100644 index 000000000..acccb4124 --- /dev/null +++ b/docs/content/en/functions/strings/ToUpper.md @@ -0,0 +1,16 @@ +--- +title: strings.ToUpper +description: Returns the given string, converting all characters to uppercase. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [upper] + returnType: string + signatures: [strings.ToUpper INPUT] +aliases: [/functions/upper] +--- + +```go-html-template +{{ upper "BatMan" }} → BATMAN +``` diff --git a/docs/content/en/functions/strings/Trim.md b/docs/content/en/functions/strings/Trim.md new file mode 100644 index 000000000..1afa0627f --- /dev/null +++ b/docs/content/en/functions/strings/Trim.md @@ -0,0 +1,16 @@ +--- +title: strings.Trim +description: Returns the given string, removing leading and trailing characters specified in the cutset. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [trim] + returnType: string + signatures: [strings.Trim INPUT CUTSET] +aliases: [/functions/trim] +--- + +```go-html-template +{{ trim "++foo--" "+-" }} → foo +``` diff --git a/docs/content/en/functions/strings/TrimLeft.md b/docs/content/en/functions/strings/TrimLeft.md new file mode 100644 index 000000000..c5d6ba60f --- /dev/null +++ b/docs/content/en/functions/strings/TrimLeft.md @@ -0,0 +1,23 @@ +--- +title: strings.TrimLeft +description: Returns the given string, removing leading characters specified in the cutset. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [strings.TrimLeft CUTSET STRING] +aliases: [/functions/strings.trimleft] +--- + +```go-html-template +{{ strings.TrimLeft "a" "abba" }} → bba +``` + +The `strings.TrimLeft` function converts the arguments to strings if possible: + +```go-html-template +{{ strings.TrimLeft 21 12345 }} → 345 (string) +{{ strings.TrimLeft "rt" true }} → ue +``` diff --git a/docs/content/en/functions/strings/TrimPrefix.md b/docs/content/en/functions/strings/TrimPrefix.md new file mode 100644 index 000000000..b897d8777 --- /dev/null +++ b/docs/content/en/functions/strings/TrimPrefix.md @@ -0,0 +1,18 @@ +--- +title: strings.TrimPrefix +description: Returns the given string, removing the prefix from the beginning of the string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [strings.TrimPrefix PREFIX STRING] +aliases: [/functions/strings.trimprefix] +--- + +```go-html-template +{{ strings.TrimPrefix "a" "aabbaa" }} → abbaa +{{ strings.TrimPrefix "aa" "aabbaa" }} → bbaa +{{ strings.TrimPrefix "aaa" "aabbaa" }} → aabbaa +``` diff --git a/docs/content/en/functions/strings/TrimRight.md b/docs/content/en/functions/strings/TrimRight.md new file mode 100644 index 000000000..05c2ed324 --- /dev/null +++ b/docs/content/en/functions/strings/TrimRight.md @@ -0,0 +1,23 @@ +--- +title: strings.TrimRight +description: Returns the given string, removing trailing characters specified in the cutset. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [strings.TrimRight CUTSET STRING] +aliases: [/functions/strings.trimright] +--- + +```go-html-template +{{ strings.TrimRight "a" "abba" }} → abb +``` + +The `strings.TrimRight` function converts the arguments to strings if possible: + +```go-html-template +{{ strings.TrimRight 54 12345 }} → 123 (string) +{{ strings.TrimRight "eu" true }} → tr +``` diff --git a/docs/content/en/functions/strings/TrimSpace.md b/docs/content/en/functions/strings/TrimSpace.md new file mode 100644 index 000000000..cb38b5ab1 --- /dev/null +++ b/docs/content/en/functions/strings/TrimSpace.md @@ -0,0 +1,20 @@ +--- +title: strings.TrimSpace +description: Returns the given string, removing leading and trailing whitespace as defined by Unicode. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [strings.TrimSpace INPUT] +--- + +{{< new-in 0.136.3 />}} + +Whitespace characters include `\t`, `\n`, `\v`, `\f`, `\r`, and characters in the [Unicode Space Separator] category. + +[Unicode Space Separator]: https://www.compart.com/en/unicode/category/Zs + +```go-html-template +{{ strings.TrimSpace "\n\r\t foo \n\r\t" }} → foo +``` diff --git a/docs/content/en/functions/strings/TrimSuffix.md b/docs/content/en/functions/strings/TrimSuffix.md new file mode 100644 index 000000000..802842105 --- /dev/null +++ b/docs/content/en/functions/strings/TrimSuffix.md @@ -0,0 +1,18 @@ +--- +title: strings.TrimSuffix +description: Returns the given string, removing the suffix from the end of the string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [strings.TrimSuffix SUFFIX STRING] +aliases: [/functions/strings.trimsuffix] +--- + +```go-html-template +{{ strings.TrimSuffix "a" "aabbaa" }} → aabba +{{ strings.TrimSuffix "aa" "aabbaa" }} → aabb +{{ strings.TrimSuffix "aaa" "aabbaa" }} → aabbaa +``` diff --git a/docs/content/en/functions/strings/Truncate.md b/docs/content/en/functions/strings/Truncate.md new file mode 100644 index 000000000..c4198229e --- /dev/null +++ b/docs/content/en/functions/strings/Truncate.md @@ -0,0 +1,23 @@ +--- +title: strings.Truncate +description: Returns the given string, truncating it to a maximum length without cutting words or leaving unclosed HTML tags. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [truncate] + returnType: template.HTML + signatures: ['strings.Truncate SIZE [ELLIPSIS] INPUT'] +aliases: [/functions/truncate] +--- + +Since Go templates are HTML-aware, `truncate` will intelligently handle normal strings vs HTML strings: + +```go-html-template +{{ "<em>Keep my HTML</em>" | safeHTML | truncate 10 }} → <em>Keep my …</em> +``` + +> [!note] +> If you have a raw string that contains HTML tags you want to remain treated as HTML, you will need to convert the string to HTML using the [`safeHTML`]function before sending the value to `truncate`. Otherwise, the HTML tags will be escaped when passed through the `truncate` function. + +[`safeHTML`]: /functions/safe/html/ diff --git a/docs/content/en/functions/strings/_index.md b/docs/content/en/functions/strings/_index.md new file mode 100644 index 000000000..28f26f170 --- /dev/null +++ b/docs/content/en/functions/strings/_index.md @@ -0,0 +1,7 @@ +--- +title: String functions +linkTitle: strings +description: Use these functions to work with strings. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/templates/Defer.md b/docs/content/en/functions/templates/Defer.md new file mode 100644 index 000000000..6a9ca56ae --- /dev/null +++ b/docs/content/en/functions/templates/Defer.md @@ -0,0 +1,92 @@ +--- +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 is meant to be used in the main page layout files/templates, and has undefined behavior when used from shortcodes, partials or render hook templates. See [this issue](https://github.com/gohugoio/hugo/issues/13492#issuecomment-2734700391) for more info. + +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 +{{ with (templates.Defer (dict "key" "global")) }} + {{ $t := debug.Timer "tailwindcss" }} + {{ with resources.Get "css/styles.css" }} + {{ $opts := dict + "inlineImports" true + "optimize" hugo.IsProduction + }} + {{ with . | css.TailwindCSS $opts }} + {{ if hugo.IsDevelopment }} + <link rel="stylesheet" href="{{ .RelPermalink }}" /> + {{ else }} + {{ with . | minify | fingerprint }} + <link + rel="stylesheet" + href="{{ .RelPermalink }}" + integrity="{{ .Data.Integrity }}" + crossorigin="anonymous" /> + {{ end }} + {{ end }} + {{ end }} + {{ end }} + {{ $t.Stop }} +{{ 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 >}} +[module] +[[module.mounts]] +source = "hugo_stats.json" +target = "assets/notwatching/hugo_stats.json" +disableWatch = true +[build.buildStats] +enable = true +[[build.cachebusters]] +source = "assets/notwatching/hugo_stats\\.json" +target = "styles\\.css" +[[build.cachebusters]] +source = "(postcss|tailwind)\\.config\\.js" +target = "css" +{{< /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 --git a/docs/content/en/functions/templates/Exists.md b/docs/content/en/functions/templates/Exists.md new file mode 100644 index 000000000..79fc561c8 --- /dev/null +++ b/docs/content/en/functions/templates/Exists.md @@ -0,0 +1,27 @@ +--- +title: templates.Exists +description: Reports whether a template file exists under the given path relative to the layouts directory. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [templates.Exists PATH] +aliases: [/functions/templates.exists] +--- + +A template file is any file within the `layouts` directory of either the project or any of its theme components. + +Use the `templates.Exists` function with dynamic template paths: + +```go-html-template +{{ $partialPath := printf "headers/%s.html" .Type }} +{{ if templates.Exists ( printf "partials/%s" $partialPath ) }} + {{ partial $partialPath . }} +{{ else }} + {{ partial "headers/default.html" . }} +{{ end }} +``` + +In the example above, if a "headers" partial does not exist for the given content type, Hugo falls back to a default template. diff --git a/docs/content/en/functions/templates/_index.md b/docs/content/en/functions/templates/_index.md new file mode 100644 index 000000000..a385604ea --- /dev/null +++ b/docs/content/en/functions/templates/_index.md @@ -0,0 +1,7 @@ +--- +title: Template functions +linkTitle: templates +description: Use these functions to query the template system. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/time/AsTime.md b/docs/content/en/functions/time/AsTime.md new file mode 100644 index 000000000..760329a13 --- /dev/null +++ b/docs/content/en/functions/time/AsTime.md @@ -0,0 +1,48 @@ +--- +title: time.AsTime +description: Returns the given string representation of a date/time value as a time.Time value. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [time] + returnType: time.Time + signatures: ['time.AsTime INPUT [TIMEZONE]'] +aliases: [/functions/time] +--- + +## Overview + +Hugo provides [functions] and [methods] to format, localize, parse, compare, and manipulate date/time values. Before you can do any of these with string representations of date/time values, you must first convert them to [`time.Time`] values using the `time.AsTime` function. + +```go-html-template +{{ $t := "2023-10-15T13:18:50-07:00" }} +{{ time.AsTime $t }} → 2023-10-15 13:18:50 -0700 PDT (time.Time) +``` + +## Parsable strings + +As shown above, the first argument must be a parsable string representation of a date/time value. For example: + +{{% include "/_common/parsable-date-time-strings.md" %}} + +To override the default time zone, set the [`timeZone`] in your site configuration or provide a second argument to the `time.AsTime` function. For example: + +```go-html-template +{{ time.AsTime "15 Oct 2023" "America/Los_Angeles" }} +``` + +The list of valid time zones may be system dependent, but should include `UTC`, `Local`, or any location in the [IANA Time Zone database]. + +The order of precedence for determining the time zone is: + +1. The time zone offset in the date/time string +1. The time zone provided as the second argument to the `time.AsTime` function +1. The time zone specified in your site configuration +1. The `Etc/UTC` time zone + +[IANA Time Zone database]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones +[`time.Time`]: https://pkg.go.dev/time#Time +[`timeZone`]: /configuration/all/#timezone +[functions]: /functions/time/ +[methods]: /methods/time/ diff --git a/docs/content/en/functions/time/Duration.md b/docs/content/en/functions/time/Duration.md new file mode 100644 index 000000000..bd6adfbfa --- /dev/null +++ b/docs/content/en/functions/time/Duration.md @@ -0,0 +1,41 @@ +--- +title: time.Duration +description: Returns a time.Duration value using the given time unit and number. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [duration] + returnType: time.Duration + signatures: [time.Duration TIME_UNIT NUMBER] +aliases: [/functions/duration] +--- + +The `time.Duration` function returns a [`time.Duration`] value that you can use with any of the `Duration` [methods]. + +This template: + +```go-html-template +{{ $duration := time.Duration "hour" 24 }} +{{ printf "There are %.0f seconds in one day." $duration.Seconds }} +``` + +Is rendered to: + +```text +There are 86400 seconds in one day. +``` + +The time unit must be one of the following: + +Duration|Valid time units +:--|:-- +hours|`hour`, `h` +minutes|`minute`, `m` +seconds|`second`, `s` +milliseconds|`millisecond`, `ms` +microseconds|`microsecond`, `us`, `µs` +nanoseconds|`nanosecond`, `ns` + +[`time.Duration`]: https://pkg.go.dev/time#Duration +[methods]: /methods/duration/ diff --git a/docs/content/en/functions/time/Format.md b/docs/content/en/functions/time/Format.md new file mode 100644 index 000000000..f1b0d6d83 --- /dev/null +++ b/docs/content/en/functions/time/Format.md @@ -0,0 +1,80 @@ +--- +title: time.Format +description: Returns the given date/time as a formatted and localized string. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [dateFormat] + returnType: string + signatures: [time.Format LAYOUT INPUT] +aliases: [/functions/dateformat] +--- + +Use the `time.Format` function with `time.Time` values: + +```go-html-template +{{ $t := time.AsTime "2023-10-15T13:18:50-07:00" }} +{{ time.Format "2 Jan 2006" $t }} → 15 Oct 2023 +``` + +Or use `time.Format` with a parsable string representation of a date/time value: + +```go-html-template +{{ $t := "15 Oct 2023" }} +{{ time.Format "January 2, 2006" $t }} → October 15, 2023 +``` + +Examples of parsable string representations: + +{{% include "/_common/parsable-date-time-strings.md" %}} + +To override the default time zone, set the [`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 + +[`timeZone`]: /configuration/all/#timezone + +## Layout string + +{{% include "/_common/time-layout-string.md" %}} + +## Localization + +Use the `time.Format` function to localize `time.Time` values for the current language and region. + +{{% include "/_common/functions/locales.md" %}} + +Use the layout string as described above, or one of the tokens below. For example: + +```go-html-template +{{ .Date | time.Format ":date_medium" }} → Jan 27, 2023 +``` + +Localized to en-US: + +Token|Result +:--|:-- +`:date_full`|`Friday, January 27, 2023` +`:date_long`|`January 27, 2023` +`:date_medium`|`Jan 27, 2023` +`:date_short`|`1/27/23` +`:time_full`|`11:44:58 pm Pacific Standard Time` +`:time_long`|`11:44:58 pm PST` +`:time_medium`|`11:44:58 pm` +`:time_short`|`11:44 pm` + +Localized to de-DE: + +Token|Result +:--|:-- +`:date_full`|`Freitag, 27. Januar 2023` +`:date_long`|`27. Januar 2023` +`:date_medium`|`27.01.2023` +`:date_short`|`27.01.23` +`:time_full`|`23:44:58 Nordamerikanische Westküsten-Normalzeit` +`:time_long`|`23:44:58 PST` +`:time_medium`|`23:44:58` +`:time_short`|`23:44` diff --git a/docs/content/en/functions/time/Now.md b/docs/content/en/functions/time/Now.md new file mode 100644 index 000000000..9b6fa4692 --- /dev/null +++ b/docs/content/en/functions/time/Now.md @@ -0,0 +1,42 @@ +--- +title: time.Now +description: Returns the current local time. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [now] + returnType: time.Time + signatures: [time.Now] +aliases: [/functions/now] +--- + +For example, when building a site on October 15, 2023 in the America/Los_Angeles time zone: + +```go-html-template +{{ time.Now }} +``` + +This produces a `time.Time` value, with a string representation such as: + +```text +2023-10-15 12:59:28.337140706 -0700 PDT m=+0.041752605 +``` + +To format and [localize](g) the value, pass it through the [`time.Format`] function: + +```go-html-template +{{ time.Now | time.Format "Jan 2006" }} → Oct 2023 +``` + +The `time.Now` function returns a `time.Time` value, so you can chain any of the [time methods] to the resulting value. For example: + +```go-html-template +{{ time.Now.Year }} → 2023 (int) +{{ time.Now.Weekday.String }} → Sunday +{{ time.Now.Month.String }} → October +{{ time.Now.Unix }} → 1697400955 (int64) +``` + +[`time.Format`]: /functions/time/format/ +[time methods]: /methods/time/ diff --git a/docs/content/en/functions/time/ParseDuration.md b/docs/content/en/functions/time/ParseDuration.md new file mode 100644 index 000000000..af5d73ad5 --- /dev/null +++ b/docs/content/en/functions/time/ParseDuration.md @@ -0,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]. + +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 --git a/docs/content/en/functions/time/_index.md b/docs/content/en/functions/time/_index.md new file mode 100644 index 000000000..9c2ff2161 --- /dev/null +++ b/docs/content/en/functions/time/_index.md @@ -0,0 +1,7 @@ +--- +title: Time functions +linkTitle: time +description: Use these functions to work with time values. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/transform/CanHighlight.md b/docs/content/en/functions/transform/CanHighlight.md new file mode 100644 index 000000000..c00445605 --- /dev/null +++ b/docs/content/en/functions/transform/CanHighlight.md @@ -0,0 +1,16 @@ +--- +title: transform.CanHighlight +description: Reports whether the given code language is supported by the Chroma highlighter. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: bool + signatures: [transform.CanHighlight LANGUAGE] +--- + +```go-html-template +{{ transform.CanHighlight "go" }} → true +{{ transform.CanHighlight "klingon" }} → false +``` diff --git a/docs/content/en/functions/transform/Emojify.md b/docs/content/en/functions/transform/Emojify.md new file mode 100644 index 000000000..31c5dce70 --- /dev/null +++ b/docs/content/en/functions/transform/Emojify.md @@ -0,0 +1,27 @@ +--- +title: transform.Emojify +description: Runs a string through the Emoji emoticons processor. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [emojify] + returnType: template.HTML + signatures: [transform.Emojify INPUT] +aliases: [/functions/emojify] +--- + +`emojify` runs a passed string through the Emoji emoticons processor. + +See the list of [emoji shortcodes] for available emoticons. + +The `emojify` function can be called in your templates but not directly in your content files by default. For emojis in content files, set [`enableEmoji`] to `true` in your site's configuration. Then you can write emoji shorthand directly into your content files; + +```text +I :heart: Hugo! +``` + +I :heart: Hugo! + +[`enableEmoji`]: /configuration/all/#enableemoji +[emoji shortcodes]: /quick-reference/emojis/ diff --git a/docs/content/en/functions/transform/HTMLEscape.md b/docs/content/en/functions/transform/HTMLEscape.md new file mode 100644 index 000000000..069fd92f2 --- /dev/null +++ b/docs/content/en/functions/transform/HTMLEscape.md @@ -0,0 +1,29 @@ +--- +title: transform.HTMLEscape +description: Returns the given string, escaping special characters by replacing them with HTML entities. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [htmlEscape] + returnType: string + signatures: [transform.HTMLEscape INPUT] +aliases: [/functions/htmlescape] +--- + +The `transform.HTMLEscape` function escapes five special characters by replacing them with [HTML entities]: + +- `&` → `&` +- `<` → `<` +- `>` → `>` +- `'` → `'` +- `"` → `"` + +For example: + +```go-html-template +{{ htmlEscape "Lilo & Stitch" }} → Lilo & Stitch +{{ htmlEscape "7 > 6" }} → 7 > 6 +``` + +[html entities]: https://developer.mozilla.org/en-US/docs/Glossary/Entity diff --git a/docs/content/en/functions/transform/HTMLUnescape.md b/docs/content/en/functions/transform/HTMLUnescape.md new file mode 100644 index 000000000..563e63cf6 --- /dev/null +++ b/docs/content/en/functions/transform/HTMLUnescape.md @@ -0,0 +1,29 @@ +--- +title: transform.HTMLUnescape +description: Returns the given string, replacing each HTML entity with its corresponding character. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [htmlUnescape] + returnType: string + signatures: [transform.HTMLUnescape INPUT] +aliases: [/functions/htmlunescape] +--- + +The `transform.HTMLUnescape` function replaces [HTML entities] with their corresponding characters. + +```go-html-template +{{ htmlUnescape "Lilo & Stitch" }} → Lilo & Stitch +{{ htmlUnescape "7 > 6" }} → 7 > 6 +``` + +In most contexts Go's [html/template] package will escape special characters. To bypass this behavior, pass the unescaped string through the [`safeHTML`] function. + +```go-html-template +{{ htmlUnescape "Lilo & Stitch" | safeHTML }} +``` + +[`safehtml`]: /functions/safe/html/ +[html entities]: https://developer.mozilla.org/en-us/docs/glossary/entity +[html/template]: https://pkg.go.dev/html/template diff --git a/docs/content/en/functions/transform/Highlight.md b/docs/content/en/functions/transform/Highlight.md new file mode 100644 index 000000000..5633f2256 --- /dev/null +++ b/docs/content/en/functions/transform/Highlight.md @@ -0,0 +1,53 @@ +--- +title: transform.Highlight +description: Renders code with a syntax highlighter. +categories: [] +keywords: [highlight] +params: + functions_and_methods: + aliases: [highlight] + returnType: template.HTML + signatures: ['transform.Highlight CODE LANG [OPTIONS]'] +aliases: [/functions/highlight] +--- + +The `highlight` function uses the [Chroma] syntax highlighter, supporting over 200 languages with more than 40 [highlighting styles]. + +[chroma]: https://github.com/alecthomas/chroma +[highlighting styles]: /quick-reference/syntax-highlighting-styles/ + +## Arguments + +The `transform.Highlight` shortcode takes three arguments. + +CODE +: (`string`) The code to highlight. + +LANG +: (`string`) The language of the code to highlight. Choose from one of the [supported languages]. This value is case-insensitive. + +OPTIONS +: (`map or string`) A map or comma-separated key-value pairs wrapped in quotation marks. Set default values for each option in your [site configuration]. The key names are case-insensitive. + +[site configuration]: /configuration/markup#highlight +[supported languages]: /content-management/syntax-highlighting#languages + +## Examples + +```go-html-template +{{ $input := `fmt.Println("Hello World!")` }} +{{ transform.Highlight $input "go" }} + +{{ $input := `console.log('Hello World!');` }} +{{ $lang := "js" }} +{{ transform.Highlight $input $lang "lineNos=table, style=api" }} + +{{ $input := `echo "Hello World!"` }} +{{ $lang := "bash" }} +{{ $opts := dict "lineNos" "table" "style" "dracula" }} +{{ transform.Highlight $input $lang $opts }} +``` + +## Options + +{{% include "_common/syntax-highlighting-options.md" %}} diff --git a/docs/content/en/functions/transform/HighlightCodeBlock.md b/docs/content/en/functions/transform/HighlightCodeBlock.md new file mode 100644 index 000000000..bbebf9459 --- /dev/null +++ b/docs/content/en/functions/transform/HighlightCodeBlock.md @@ -0,0 +1,36 @@ +--- +title: transform.HighlightCodeBlock +description: Highlights code received in context within a code block render hook. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: highlight.HighlightResult + signatures: ['transform.HighlightCodeBlock CONTEXT [OPTIONS]'] +--- + +This function is only useful within a code block render hook. + +Given the context passed into a code block render hook, `transform.HighlightCodeBlock` returns a `HighlightResult` object with two methods. + +.Wrapped +: (`template.HTML`) Returns highlighted code wrapped in `<div>`, `<pre>`, and `<code>` elements. This is identical to the value returned by the transform.Highlight function. + +.Inner +: (`template.HTML`) Returns highlighted code without any wrapping elements, allowing you to create your own wrapper. + +```go-html-template +{{ $result := transform.HighlightCodeBlock . }} +{{ $result.Wrapped }} +``` + +To override the default [highlighting options]: + +```go-html-template +{{ $opts := merge .Options (dict "linenos" true) }} +{{ $result := transform.HighlightCodeBlock . $opts }} +{{ $result.Wrapped }} +``` + +[highlighting options]: /functions/transform/highlight/#options diff --git a/docs/content/en/functions/transform/Markdownify.md b/docs/content/en/functions/transform/Markdownify.md new file mode 100644 index 000000000..c22de1efe --- /dev/null +++ b/docs/content/en/functions/transform/Markdownify.md @@ -0,0 +1,27 @@ +--- +title: transform.Markdownify +description: Renders Markdown to HTML. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [markdownify] + returnType: template.HTML + signatures: [transform.Markdownify INPUT] +aliases: [/functions/markdownify] +--- + +```go-html-template +<h2>{{ .Title | markdownify }}</h2> +``` + +If the resulting HTML is a single paragraph, Hugo removes the wrapping `p` tags to produce inline HTML as required per the example above. + +To keep the wrapping `p` tags for a single paragraph, use the [`RenderString`] method on the `Page` object, setting the `display` option to `block`. + +> [!note] +> Although the `markdownify` function honors [Markdown render hooks] when rendering Markdown to HTML, use the `RenderString` method instead of `markdownify` if a render hook accesses `.Page` context. See issue [#9692] for details. + +[#9692]: https://github.com/gohugoio/hugo/issues/9692 +[`RenderString`]: /methods/page/renderstring/ +[Markdown render hooks]: /render-hooks/ diff --git a/docs/content/en/functions/transform/Plainify.md b/docs/content/en/functions/transform/Plainify.md new file mode 100644 index 000000000..780cf461a --- /dev/null +++ b/docs/content/en/functions/transform/Plainify.md @@ -0,0 +1,16 @@ +--- +title: transform.Plainify +description: Returns a string with all HTML tags removed. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [plainify] + returnType: template.HTML + signatures: [transform.Plainify INPUT] +aliases: [/functions/plainify] +--- + +```go-html-template +{{ "<b>BatMan</b>" | plainify }} → BatMan +``` diff --git a/docs/content/en/functions/transform/PortableText.md b/docs/content/en/functions/transform/PortableText.md new file mode 100644 index 000000000..7baba99d4 --- /dev/null +++ b/docs/content/en/functions/transform/PortableText.md @@ -0,0 +1,213 @@ +--- +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 --git a/docs/content/en/functions/transform/Remarshal.md b/docs/content/en/functions/transform/Remarshal.md new file mode 100644 index 000000000..ecf7fc905 --- /dev/null +++ b/docs/content/en/functions/transform/Remarshal.md @@ -0,0 +1,89 @@ +--- +title: transform.Remarshal +description: Marshals a string of serialized data, or a map, into a string of serialized data in the specified format. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [transform.Remarshal FORMAT INPUT] +aliases: [/functions/transform.remarshal] +--- + +The format must be one of `json`, `toml`, `yaml`, or `xml`. If the input is a string of serialized data, it must be valid JSON, TOML, YAML, or XML. + +> [!note] +> This function is primarily a helper for Hugo's documentation, used to convert configuration and front matter examples to JSON, TOML, and YAML. +> +> This is not a general purpose converter, and may change without notice if required for Hugo's documentation site. + +Example 1 +: Convert a string of TOML to JSON. + +```go-html-template +{{ $s := ` + baseURL = 'https://example.org/' + languageCode = 'en-US' + title = 'ABC Widgets' +`}} +<pre>{{ transform.Remarshal "json" $s }}</pre> +``` + +Resulting HTML: + +```html +<pre>{ + "baseURL": "https://example.org/", + "languageCode": "en-US", + "title": "ABC Widgets" +} +</pre> +``` + +Rendered in browser: + +```text +{ + "baseURL": "https://example.org/", + "languageCode": "en-US", + "title": "ABC Widgets" +} +``` + +Example 2 +: Convert a map to YAML. + +```go-html-template +{{ $m := dict + "a" "Hugo rocks!" + "b" (dict "question" "What is 6x7?" "answer" 42) + "c" (slice "foo" "bar") +}} +<pre>{{ transform.Remarshal "yaml" $m }}</pre> +``` + +Resulting HTML: + +```html +<pre>a: Hugo rocks! +b: + answer: 42 + question: What is 6x7? +c: +- foo +- bar +</pre> +``` + +Rendered in browser: + +```text +a: Hugo rocks! +b: + answer: 42 + question: What is 6x7? +c: +- foo +- bar +``` diff --git a/docs/content/en/functions/transform/ToMath.md b/docs/content/en/functions/transform/ToMath.md new file mode 100644 index 000000000..a9f12c546 --- /dev/null +++ b/docs/content/en/functions/transform/ToMath.md @@ -0,0 +1,164 @@ +--- +title: transform.ToMath +description: Renders mathematical equations and expressions written in the LaTeX markup language. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: types.Result[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 }} + ``` + +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. + + ```html + <link href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css" rel="stylesheet"> + +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 + +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 will need to 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/_default/_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/_default/baseof.html" copy=true} +<head> + {{ $noop := .WordCount }} + {{ if .Page.Store.Get "hasMath" }} + <link href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css" rel="stylesheet"> + {{ end }} +</head> +``` + +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 --git a/docs/content/en/functions/transform/Unmarshal.md b/docs/content/en/functions/transform/Unmarshal.md new file mode 100644 index 000000000..d159122f5 --- /dev/null +++ b/docs/content/en/functions/transform/Unmarshal.md @@ -0,0 +1,293 @@ +--- +title: transform.Unmarshal +description: Parses serialized data and returns a map or an array. Supports CSV, JSON, TOML, YAML, and XML. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [unmarshal] + returnType: any + signatures: ['transform.Unmarshal [OPTIONS] INPUT'] +aliases: [/functions/transform.unmarshal] +--- + +The input can be a string or a [resource](g). + +## Unmarshal a string + +```go-html-template +{{ $string := ` +title: Les Misérables +author: Victor Hugo +`}} + +{{ $book := unmarshal $string }} +{{ $book.title }} → Les Misérables +{{ $book.author }} → Victor Hugo +``` + +## Unmarshal a resource + +Use the `transform.Unmarshal` function with global, page, and remote resources. + +### Global resource + +A global resource is a file within the `assets` directory, or within any directory mounted to the `assets` directory. + +```text +assets/ +└── data/ + └── books.json +``` + +```go-html-template +{{ $data := dict }} +{{ $path := "data/books.json" }} +{{ with resources.Get $path }} + {{ with . | transform.Unmarshal }} + {{ $data = . }} + {{ end }} +{{ else }} + {{ errorf "Unable to get global resource %q" $path }} +{{ end }} + +{{ range where $data "author" "Victor Hugo" }} + {{ .title }} → Les Misérables +{{ end }} +``` + +### Page resource + +A page resource is a file within a [page bundle]. + +```text +content/ +├── post/ +│ └── book-reviews/ +│ ├── books.json +│ └── index.md +└── _index.md +``` + +```go-html-template +{{ $data := dict }} +{{ $path := "books.json" }} +{{ with .Resources.Get $path }} + {{ with . | transform.Unmarshal }} + {{ $data = . }} + {{ end }} +{{ else }} + {{ errorf "Unable to get page resource %q" $path }} +{{ end }} + +{{ range where $data "author" "Victor Hugo" }} + {{ .title }} → Les Misérables +{{ end }} +``` + +### Remote resource + +A remote resource is a file on a remote server, accessible via HTTP or HTTPS. + +```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 }} + +{{ range where $data "author" "Victor Hugo" }} + {{ .title }} → Les Misérables +{{ 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 }}` + +## Options + +When unmarshaling a CSV file, provide an optional map of options. + +delimiter +: (`string`) The delimiter used, default is `,`. + +comment +: (`string`) The comment character used in the CSV. If set, lines beginning with the comment character without preceding whitespace are ignored. + +lazyQuotes +: {{< new-in 0.122.0 />}} +: (`bool`) Whether to allow a quote in an unquoted field, or to allow a non-doubled quote in a quoted field. Default is `false`. + +```go-html-template +{{ $csv := "a;b;c" | transform.Unmarshal (dict "delimiter" ";") }} +``` + +## Working with XML + +When unmarshaling an XML file, do not include the root node when accessing data. For example, after unmarshaling the RSS feed below, access the feed title with `$data.channel.title`. + +```xml +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> + <channel> + <title>Books on Example Site</title> + <link>https://example.org/books/</link> + <description>Recent content in Books on Example Site</description> + <language>en-US</language> + <atom:link href="https://example.org/books/index.xml" rel="self" type="application/rss+xml" /> + <item> + <title>The Hunchback of Notre Dame</title> + <description>Written by Victor Hugo</description> + <link>https://example.org/books/the-hunchback-of-notre-dame/</link> + <pubDate>Mon, 09 Oct 2023 09:27:12 -0700</pubDate> + <guid>https://example.org/books/the-hunchback-of-notre-dame/</guid> + </item> + <item> + <title>Les Misérables</title> + <description>Written by Victor Hugo</description> + <link>https://example.org/books/les-miserables/</link> + <pubDate>Mon, 09 Oct 2023 09:27:11 -0700</pubDate> + <guid>https://example.org/books/les-miserables/</guid> + </item> + </channel> +</rss> +``` + +Get the remote data: + +```go-html-template +{{ $data := dict }} +{{ $url := "https://example.org/books/index.xml" }} +{{ 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 }} +``` + +Inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump $data }}</pre> +``` + +List the book titles: + +```go-html-template +{{ with $data.channel.item }} + <ul> + {{ range . }} + <li>{{ .title }}</li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo renders this to: + +```html +<ul> + <li>The Hunchback of Notre Dame</li> + <li>Les Misérables</li> +</ul> +``` + +### XML attributes and namespaces + +Let's add a `lang` attribute to the `title` nodes of our RSS feed, and a namespaced node for the ISBN number: + +```xml +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<rss version="2.0" + xmlns:atom="http://www.w3.org/2005/Atom" + xmlns:isbn="http://schemas.isbn.org/ns/1999/basic.dtd" +> + <channel> + <title>Books on Example Site</title> + <link>https://example.org/books/</link> + <description>Recent content in Books on Example Site</description> + <language>en-US</language> + <atom:link href="https://example.org/books/index.xml" rel="self" type="application/rss+xml" /> + <item> + <title lang="en">The Hunchback of Notre Dame</title> + <description>Written by Victor Hugo</description> + <isbn:number>9780140443530</isbn:number> + <link>https://example.org/books/the-hunchback-of-notre-dame/</link> + <pubDate>Mon, 09 Oct 2023 09:27:12 -0700</pubDate> + <guid>https://example.org/books/the-hunchback-of-notre-dame/</guid> + </item> + <item> + <title lang="fr">Les Misérables</title> + <description>Written by Victor Hugo</description> + <isbn:number>9780451419439</isbn:number> + <link>https://example.org/books/les-miserables/</link> + <pubDate>Mon, 09 Oct 2023 09:27:11 -0700</pubDate> + <guid>https://example.org/books/les-miserables/</guid> + </item> + </channel> +</rss> +``` + +After retrieving the remote data, inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump $data }}</pre> +``` + +Each item node looks like this: + +```json +{ + "description": "Written by Victor Hugo", + "guid": "https://example.org/books/the-hunchback-of-notre-dame/", + "link": "https://example.org/books/the-hunchback-of-notre-dame/", + "number": "9780140443530", + "pubDate": "Mon, 09 Oct 2023 09:27:12 -0700", + "title": { + "#text": "The Hunchback of Notre Dame", + "-lang": "en" + } +} +``` + +The title keys do not begin with an underscore or a letter---they are not valid [identifiers](g). Use the [`index`] function to access the values: + +```go-html-template +{{ with $data.channel.item }} + <ul> + {{ range . }} + {{ $title := index .title "#text" }} + {{ $lang := index .title "-lang" }} + {{ $ISBN := .number }} + <li>{{ $title }} ({{ $lang }}) {{ $ISBN }}</li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo renders this to: + +```html +<ul> + <li>The Hunchback of Notre Dame (en) 9780140443530</li> + <li>Les Misérables (fr) 9780451419439</li> +</ul> +``` + +[`index`]: /functions/collections/indexfunction/ +[Content-Type]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type +[page bundle]: /content-management/page-bundles/ diff --git a/docs/content/en/functions/transform/XMLEscape.md b/docs/content/en/functions/transform/XMLEscape.md new file mode 100644 index 000000000..9e6c77927 --- /dev/null +++ b/docs/content/en/functions/transform/XMLEscape.md @@ -0,0 +1,40 @@ +--- +title: transform.XMLEscape +description: Returns the given string, removing disallowed characters then escaping the result to its XML equivalent. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [transform.XMLEscape INPUT] +--- + +{{< new-in 0.121.0 />}} + +The `transform.XMLEscape` function removes [disallowed characters] as defined in the XML specification, then escapes the result by replacing the following characters with [HTML entities]: + +- `"` → `"` +- `'` → `'` +- `&` → `&` +- `<` → `<` +- `>` → `>` +- `\t` → `	` +- `\n` → `
` +- `\r` → `
` + +For example: + +```go-html-template +{{ transform.XMLEscape "<p>abc</p>" }} → <p>abc</p> +``` + +When using `transform.XMLEscape` in a template rendered by Go's [html/template] package, declare the string to be safe HTML to avoid double escaping. For example, in an RSS template: + +```xml {file="layouts/_default/rss.xml"} +<description>{{ .Summary | transform.XMLEscape | safeHTML }}</description> +``` + +[disallowed characters]: https://www.w3.org/TR/xml/#charsets +[html entities]: https://developer.mozilla.org/en-us/docs/glossary/entity +[html/template]: https://pkg.go.dev/html/template diff --git a/docs/content/en/functions/transform/_index.md b/docs/content/en/functions/transform/_index.md new file mode 100644 index 000000000..19c271b65 --- /dev/null +++ b/docs/content/en/functions/transform/_index.md @@ -0,0 +1,7 @@ +--- +title: Transform functions +linkTitle: transform +description: Use these functions to transform values from one format to another. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/functions/urls/AbsLangURL.md b/docs/content/en/functions/urls/AbsLangURL.md new file mode 100644 index 000000000..da45ca224 --- /dev/null +++ b/docs/content/en/functions/urls/AbsLangURL.md @@ -0,0 +1,72 @@ +--- +title: urls.AbsLangURL +description: Returns an absolute URL with a language prefix, if any. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [absLangURL] + returnType: string + signatures: [urls.AbsLangURL INPUT] +aliases: [/functions/abslangurl] +--- + +Use this function with both monolingual and multilingual configurations. The URL returned by this function depends on: + +- Whether the input begins with a slash (`/`) +- The `baseURL` in your site configuration +- The language prefix, if any + +This is the site configuration for the examples that follow: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' +defaultContentLanguageInSubdir = true +[languages.en] +weight = 1 +[languages.es] +weight = 2 +{{< /code-toggle >}} + +## Input does not begin with a slash + +If the input does not begin with a slash, the path in the resulting URL will be relative to the `baseURL` in your site configuration. + +When rendering the `en` site with `baseURL = https://example.org/` + +```go-html-template +{{ absLangURL "" }} → https://example.org/en/ +{{ absLangURL "articles" }} → https://example.org/en/articles +{{ absLangURL "style.css" }} → https://example.org/en/style.css +``` + +When rendering the `en` site with `baseURL = https://example.org/docs/` + +```go-html-template +{{ absLangURL "" }} → https://example.org/docs/en/ +{{ absLangURL "articles" }} → https://example.org/docs/en/articles +{{ absLangURL "style.css" }} → https://example.org/docs/en/style.css +``` + +## Input begins with a slash + +If the input begins with a slash, the path in the resulting URL will be relative to the protocol+host of the `baseURL` in your site configuration. + +When rendering the `en` site with `baseURL = https://example.org/` + +```go-html-template +{{ absLangURL "/" }} → https://example.org/en/ +{{ absLangURL "/articles" }} → https://example.org/en/articles +{{ absLangURL "/style.css" }} → https://example.org/en/style.css +``` + +When rendering the `en` site with `baseURL = https://example.org/docs/` + +```go-html-template +{{ absLangURL "/" }} → https://example.org/en/ +{{ absLangURL "/articles" }} → https://example.org/en/articles +{{ absLangURL "/style.css" }} → https://example.org/en/style.css +``` + +> [!note] +> As illustrated by the previous example, using a leading slash is rarely desirable and can lead to unexpected outcomes. In nearly all cases, omit the leading slash. diff --git a/docs/content/en/functions/urls/AbsURL.md b/docs/content/en/functions/urls/AbsURL.md new file mode 100644 index 000000000..72613cd0b --- /dev/null +++ b/docs/content/en/functions/urls/AbsURL.md @@ -0,0 +1,62 @@ +--- +title: urls.AbsURL +description: Returns an absolute URL. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [absURL] + returnType: string + signatures: [urls.AbsURL INPUT] +aliases: [/functions/absurl] +--- + +With multilingual configurations, use the [`urls.AbsLangURL`] function instead. The URL returned by this function depends on: + +- Whether the input begins with a slash (`/`) +- The `baseURL` in your site configuration + +## Input does not begin with a slash + +If the input does not begin with a slash, the path in the resulting URL will be relative to the `baseURL` in your site configuration. + +With `baseURL = https://example.org/` + +```go-html-template +{{ absURL "" }} → https://example.org/ +{{ absURL "articles" }} → https://example.org/articles +{{ absURL "style.css" }} → https://example.org/style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ absURL "" }} → https://example.org/docs/ +{{ absURL "articles" }} → https://example.org/docs/articles +{{ absURL "style.css" }} → https://example.org/docs/style.css +``` + +## Input begins with a slash + +If the input begins with a slash, the path in the resulting URL will be relative to the protocol+host of the `baseURL` in your site configuration. + +With `baseURL = https://example.org/` + +```go-html-template +{{ absURL "/" }} → https://example.org/ +{{ absURL "/articles" }} → https://example.org/articles +{{ absURL "/style.css" }} → https://example.org/style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ absURL "/" }} → https://example.org/ +{{ absURL "/articles" }} → https://example.org/articles +{{ absURL "/style.css" }} → https://example.org/style.css +``` + +> [!note] +> As illustrated by the previous example, using a leading slash is rarely desirable and can lead to unexpected outcomes. In nearly all cases, omit the leading slash. + +[`urls.AbsLangURL`]: /functions/urls/abslangurl/ diff --git a/docs/content/en/functions/urls/Anchorize.md b/docs/content/en/functions/urls/Anchorize.md new file mode 100644 index 000000000..d18bd9a4d --- /dev/null +++ b/docs/content/en/functions/urls/Anchorize.md @@ -0,0 +1,36 @@ +--- +title: urls.Anchorize +description: Returns the given string, sanitized for usage in an HTML id attribute. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [anchorize] + returnType: string + signatures: [urls.Anchorize INPUT] +aliases: [/functions/anchorize] +--- + +{{% include "/_common/functions/urls/anchorize-vs-urlize.md" %}} + +## Sanitizing logic + +With the default Markdown renderer, Goldmark, the sanitizing logic is controlled by your site configuration: + +{{< code-toggle file=hugo >}} +[markup.goldmark.parser] +autoHeadingIDType = 'github' +{{< /code-toggle >}} + +This controls the behavior of the `anchorize` function and the generation of heading IDs when rendering Markdown to HTML. + +Set `autoHeadingIDType` to one of: + +github +: Compatible with GitHub. This is the default. + +github-ascii +: Similar to the `github` setting, but removes non-ASCII characters. + +blackfriday +: Provided for backwards compatibility with Hugo v0.59.1 and earlier. This option will be removed in a future release. diff --git a/docs/content/en/functions/urls/JoinPath.md b/docs/content/en/functions/urls/JoinPath.md new file mode 100644 index 000000000..b9da7e437 --- /dev/null +++ b/docs/content/en/functions/urls/JoinPath.md @@ -0,0 +1,27 @@ +--- +title: urls.JoinPath +description: 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. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: string + signatures: [urls.JoinPath ELEMENT...] +aliases: [/functions/urls.joinpath] +--- + +```go-html-template +{{ urls.JoinPath }} → "" (empty string) +{{ urls.JoinPath "" }} → / +{{ urls.JoinPath "a" }} → a +{{ urls.JoinPath "a" "b" }} → a/b +{{ urls.JoinPath "/a" "b" }} → /a/b +{{ urls.JoinPath "https://example.org" "b" }} → https://example.org/b + +{{ urls.JoinPath (slice "a" "b") }} → a/b +``` + +Unlike the [`path.Join`] function, `urls.JoinPath` retains consecutive leading slashes. + +[`path.Join`]: /functions/path/join/ diff --git a/docs/content/en/functions/urls/Parse.md b/docs/content/en/functions/urls/Parse.md new file mode 100644 index 000000000..7def5fb1d --- /dev/null +++ b/docs/content/en/functions/urls/Parse.md @@ -0,0 +1,35 @@ +--- +title: urls.Parse +description: Parses a URL into a URL structure. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [] + returnType: url.URL + signatures: [urls.Parse URL] +aliases: [/functions/urls.parse] +--- + +The `urls.Parse` function parses a URL into a [URL structure](https://godoc.org/net/url#URL). The URL may be relative (a path, without a host) or absolute (starting with a [scheme]). Hugo throws an error when parsing an invalid URL. + +[scheme]: https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml#uri-schemes-1 + +```go-html-template +{{ $url := "https://example.org:123/foo?a=6&b=7#bar" }} +{{ $u := urls.Parse $url }} + +{{ $u.String }} → https://example.org:123/foo?a=6&b=7#bar +{{ $u.IsAbs }} → true +{{ $u.Scheme }} → https +{{ $u.Host }} → example.org:123 +{{ $u.Hostname }} → example.org +{{ $u.RequestURI }} → /foo?a=6&b=7 +{{ $u.Path }} → /foo +{{ $u.RawQuery }} → a=6&b=7 +{{ $u.Query }} → map[a:[6] b:[7]] +{{ $u.Query.a }} → [6] +{{ $u.Query.Get "a" }} → 6 +{{ $u.Query.Has "b" }} → true +{{ $u.Fragment }} → bar +``` diff --git a/docs/content/en/functions/urls/Ref.md b/docs/content/en/functions/urls/Ref.md new file mode 100644 index 000000000..92abed91a --- /dev/null +++ b/docs/content/en/functions/urls/Ref.md @@ -0,0 +1,46 @@ +--- +title: urls.Ref +description: Returns the absolute URL of the page with the given path, language, and output format. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [ref] + returnType: string + signatures: + - urls.Ref PAGE PATH + - urls.Ref PAGE OPTIONS +aliases: [/functions/ref] +--- + +## Usage + +The `ref` function takes two arguments: + +1. The context for resolving relative paths (typically the current page). +1. Either the target page's path or an options map (see below). + +## Options + +{{% include "_common/ref-and-relref-options.md" %}} + +## Examples + +The following examples show the rendered output for a page on the English version of the site: + +```go-html-template +{{ ref . "/books/book-1" }} → https://example.org/en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" }} +{{ ref . $opts }} → https://example.org/en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" }} +{{ ref . $opts }} → https://example.org/de/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" "outputFormat" "json" }} +{{ ref . $opts }} → https://example.org/de/books/book-1/index.json +``` + +## Error handling + +{{% include "_common/ref-and-relref-error-handling.md" %}} diff --git a/docs/content/en/functions/urls/RelLangURL.md b/docs/content/en/functions/urls/RelLangURL.md new file mode 100644 index 000000000..af8bff3d7 --- /dev/null +++ b/docs/content/en/functions/urls/RelLangURL.md @@ -0,0 +1,82 @@ +--- +title: urls.RelLangURL +description: Returns a relative URL with a language prefix, if any. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [relLangURL] + returnType: string + signatures: [urls.RelLangURL INPUT] +aliases: [/functions/rellangurl] +--- + +Use this function with both monolingual and multilingual configurations. The URL returned by this function depends on: + +- Whether the input begins with a slash (`/`) +- The `baseURL` in your site configuration +- The language prefix, if any + +This is the site configuration for the examples that follow: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'en' +defaultContentLanguageInSubdir = true +[languages.en] +weight = 1 +[languages.es] +weight = 2 +{{< /code-toggle >}} + +## Input does not begin with a slash + +If the input does not begin with a slash, the resulting URL will be relative to the `baseURL` in your site configuration. + +When rendering the `en` site with `baseURL = https://example.org/` + +```go-html-template +{{ relLangURL "" }} → /en/ +{{ relLangURL "articles" }} → /en/articles +{{ relLangURL "style.css" }} → /en/style.css +{{ relLangURL "https://example.org" }} → https://example.org +{{ relLangURL "https://example.org/" }} → /en +{{ relLangURL "https://www.example.org" }} → https://www.example.org +{{ relLangURL "https://www.example.org/" }} → https://www.example.org/ +``` + +When rendering the `en` site with `baseURL = https://example.org/docs/` + +```go-html-template +{{ relLangURL "" }} → /docs/en/ +{{ relLangURL "articles" }} → /docs/en/articles +{{ relLangURL "style.css" }} → /docs/en/style.css +{{ relLangURL "https://example.org" }} → https://example.org +{{ relLangURL "https://example.org/" }} → https://example.org/ +{{ relLangURL "https://example.org/docs" }} → https://example.org/docs +{{ relLangURL "https://example.org/docs/" }} → /docs/en +{{ relLangURL "https://www.example.org" }} → https://www.example.org +{{ relLangURL "https://www.example.org/" }} → https://www.example.org/ +``` + +## Input begins with a slash + +If the input begins with a slash, the resulting URL will be relative to the protocol+host of the `baseURL` in your site configuration. + +When rendering the `en` site with `baseURL = https://example.org/` + +```go-html-template +{{ relLangURL "/" }} → /en/ +{{ relLangURL "/articles" }} → /en/articles +{{ relLangURL "/style.css" }} → /en/style.css +``` + +When rendering the `en` site with `baseURL = https://example.org/docs/` + +```go-html-template +{{ relLangURL "/" }} → /en/ +{{ relLangURL "/articles" }} → /en/articles +{{ relLangURL "/style.css" }} → /en/style.css +``` + +> [!note] +> As illustrated by the previous example, using a leading slash is rarely desirable and can lead to unexpected outcomes. In nearly all cases, omit the leading slash. diff --git a/docs/content/en/functions/urls/RelRef.md b/docs/content/en/functions/urls/RelRef.md new file mode 100644 index 000000000..aa7acf50b --- /dev/null +++ b/docs/content/en/functions/urls/RelRef.md @@ -0,0 +1,46 @@ +--- +title: urls.RelRef +description: Returns the relative URL of the page with the given path, language, and output format. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [relref] + returnType: string + signatures: + - urls.RelRef PAGE PATH + - urls.RelRef PAGE OPTIONS +aliases: [/functions/relref] +--- + +## Usage + +The `relref` function takes two arguments: + +1. The context for resolving relative paths (typically the current page). +1. Either the target page's path or an options map (see below). + +## Options + +{{% include "_common/ref-and-relref-options.md" %}} + +## Examples + +The following examples show the rendered output for a page on the English version of the site: + +```go-html-template +{{ relref . "/books/book-1" }} → /en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" }} +{{ relref . $opts }} → /en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" }} +{{ relref . $opts }} → /de/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" "outputFormat" "json" }} +{{ relref . $opts }} → /de/books/book-1/index.json +``` + +## Error handling + +{{% include "_common/ref-and-relref-error-handling.md" %}} diff --git a/docs/content/en/functions/urls/RelURL.md b/docs/content/en/functions/urls/RelURL.md new file mode 100644 index 000000000..0aef4043f --- /dev/null +++ b/docs/content/en/functions/urls/RelURL.md @@ -0,0 +1,72 @@ +--- +title: urls.RelURL +description: Returns a relative URL. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [relURL] + returnType: string + signatures: [urls.RelURL INPUT] +aliases: [/functions/relurl] +--- + +With multilingual configurations, use the [`urls.RelLangURL`] function instead. The URL returned by this function depends on: + +- Whether the input begins with a slash (`/`) +- The `baseURL` in your site configuration + +## Input does not begin with a slash + +If the input does not begin with a slash, the resulting URL will be relative to the `baseURL` in your site configuration. + +With `baseURL = https://example.org/` + +```go-html-template +{{ relURL "" }} → / +{{ relURL "articles" }} → /articles +{{ relURL "style.css" }} → /style.css +{{ relURL "https://example.org" }} → https://example.org +{{ relURL "https://example.org/" }} → / +{{ relURL "https://www.example.org" }} → https://www.example.org +{{ relURL "https://www.example.org/" }} → https://www.example.org/ +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ relURL "" }} → /docs/ +{{ relURL "articles" }} → /docs/articles +{{ relURL "style.css" }} → /docs/style.css +{{ relURL "https://example.org" }} → https://example.org +{{ relURL "https://example.org/" }} → https://example.org/ +{{ relURL "https://example.org/docs" }} → https://example.org/docs +{{ relURL "https://example.org/docs/" }} → /docs +{{ relURL "https://www.example.org" }} → https://www.example.org +{{ relURL "https://www.example.org/" }} → https://www.example.org/ +``` + +## Input begins with a slash + +If the input begins with a slash, the resulting URL will be relative to the protocol+host of the `baseURL` in your site configuration. + +With `baseURL = https://example.org/` + +```go-html-template +{{ relURL "/" }} → / +{{ relURL "/articles" }} → /articles +{{ relURL "/style.css" }} → /style.css +``` + +With `baseURL = https://example.org/docs/` + +```go-html-template +{{ relURL "/" }} → / +{{ relURL "/articles" }} → /articles +{{ relURL "/style.css" }} → /style.css +``` + +> [!note] +> As illustrated by the previous example, using a leading slash is rarely desirable and can lead to unexpected outcomes. In nearly all cases, omit the leading slash. + +[`urls.RelLangURL`]: /functions/urls/rellangurl/ diff --git a/docs/content/en/functions/urls/URLize.md b/docs/content/en/functions/urls/URLize.md new file mode 100644 index 000000000..b0cc812ec --- /dev/null +++ b/docs/content/en/functions/urls/URLize.md @@ -0,0 +1,61 @@ +--- +title: urls.URLize +description: Returns the given string, sanitized for usage in a URL. +categories: [] +keywords: [] +params: + functions_and_methods: + aliases: [urlize] + returnType: string + signatures: [urls.URLize INPUT] +aliases: [/functions/urlize] +--- + +{{% include "/_common/functions/urls/anchorize-vs-urlize.md" %}} + +## Example + +Use the `urlize` function to create a link to a [term page](g). + +Consider this site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +author = 'authors' +{{< /code-toggle >}} + +And this front matter: + +{{< code-toggle file=content/books/les-miserables.md fm=true >}} +title = 'Les Misérables' +authors = ['Victor Hugo'] +{{< /code-toggle >}} + +The published site will have this structure: + +```text +public/ +├── authors/ +│ ├── victor-hugo/ +│ │ └── index.html +│ └── index.html +├── books/ +│ ├── les-miserables/ +│ │ └── index.html +│ └── index.html +└── index.html +``` + +To create a link to the term page: + +```go-html-template +{{ $taxonomy := "authors" }} +{{ $term := "Victor Hugo" }} +{{ with index .Site.Taxonomies $taxonomy (urlize $term) }} + <a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> +{{ end }} +``` + +To generate a list of term pages associated with a given content page, use the [`GetTerms`] method on a `Page` object. + +[`GetTerms`]: /methods/page/getterms/ diff --git a/docs/content/en/functions/urls/_index.md b/docs/content/en/functions/urls/_index.md new file mode 100644 index 000000000..3a1962d7a --- /dev/null +++ b/docs/content/en/functions/urls/_index.md @@ -0,0 +1,7 @@ +--- +title: URL functions +linkTitle: urls +description: Use these functions to work with URLs. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/getting-started/_index.md b/docs/content/en/getting-started/_index.md new file mode 100644 index 000000000..2e2f57127 --- /dev/null +++ b/docs/content/en/getting-started/_index.md @@ -0,0 +1,8 @@ +--- +title: Getting started +description: How to get started with Hugo. +categories: [] +keywords: [] +weight: 10 +aliases: [/overview/introduction/] +--- diff --git a/docs/content/en/getting-started/directory-structure.md b/docs/content/en/getting-started/directory-structure.md new file mode 100644 index 000000000..3feecd135 --- /dev/null +++ b/docs/content/en/getting-started/directory-structure.md @@ -0,0 +1,207 @@ +--- +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 +``` + +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 --git a/docs/content/en/getting-started/external-learning-resources/build-websites-with-hugo.png b/docs/content/en/getting-started/external-learning-resources/build-websites-with-hugo.png Binary files differnew file mode 100644 index 000000000..ebed7e89f --- /dev/null +++ b/docs/content/en/getting-started/external-learning-resources/build-websites-with-hugo.png diff --git a/docs/content/en/getting-started/external-learning-resources/hugo-in-action.png b/docs/content/en/getting-started/external-learning-resources/hugo-in-action.png Binary files differnew file mode 100644 index 000000000..7bc5c9930 --- /dev/null +++ b/docs/content/en/getting-started/external-learning-resources/hugo-in-action.png diff --git a/docs/content/en/getting-started/external-learning-resources/index.md b/docs/content/en/getting-started/external-learning-resources/index.md new file mode 100644 index 000000000..7838b6810 --- /dev/null +++ b/docs/content/en/getting-started/external-learning-resources/index.md @@ -0,0 +1,83 @@ +--- +title: External learning resources +linkTitle: External resources +description: Use these third-party resources to learn Hugo. +categories: [] +keywords: [] +weight: 40 +--- + +## 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/archetypes/) +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 --git a/docs/content/en/getting-started/quick-start.md b/docs/content/en/getting-started/quick-start.md new file mode 100644 index 000000000..dfb78f42e --- /dev/null +++ b/docs/content/en/getting-started/quick-start.md @@ -0,0 +1,218 @@ +--- +title: Quick start +description: Create a Hugo site in minutes. +categories: [] +keywords: [] +params: + minVersion: v0.128.0 +weight: 10 +aliases: [/quickstart/,/overview/quickstart/] +--- + +In this tutorial you will: + +1. Create a site +1. Add content +1. Configure the site +1. Publish the site + +## Prerequisites + +Before you begin this tutorial you must: + +1. [Install Hugo] (extended or extended/deploy edition, {{% param "minVersion" %}} or later) +1. [Install Git] + +You must also be comfortable working from the command line. + +## Create a site + +### Commands + +> [!note] +> **If you are a Windows user:** +> +> - Do not use the Command Prompt +> - Do not use Windows PowerShell +> - Run these commands from [PowerShell] or a Linux terminal such as WSL or Git > Bash +> +> PowerShell and Windows PowerShell [are different applications]. + +Verify that you have installed Hugo {{% param "minVersion" %}} or later. + +```text +hugo version +``` + +Run these commands to create a Hugo site with the [Ananke] theme. The next section provides an explanation of each command. + +```text +hugo new site quickstart +cd quickstart +git init +git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke +echo "theme = 'ananke'" >> hugo.toml +hugo server +``` + +View your site at the URL displayed in your terminal. Press `Ctrl + C` to stop Hugo's development server. + +### Explanation of commands + +Create the [directory structure] for your project in the `quickstart` directory. + +```text +hugo new site quickstart +``` + +Change the current directory to the root of your project. + +```text +cd quickstart +``` + +Initialize an empty Git repository in the current directory. + +```text +git init +``` + +Clone the [Ananke] theme into the `themes` directory, adding it to your project as a [Git submodule]. + +```text +git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke +``` + +Append a line to the site configuration file, indicating the current theme. + +```text +echo "theme = 'ananke'" >> hugo.toml +``` + +Start Hugo's development server to view the site. + +```text +hugo server +``` + +Press `Ctrl + C` to stop Hugo's development server. + +## Add content + +Add a new page to your site. + +```text +hugo new content content/posts/my-first-post.md +``` + +Hugo created the file in the `content/posts` directory. Open the file with your editor. + +```text ++++ +title = 'My First Post' +date = 2024-01-14T07:07:07+01:00 +draft = true ++++ +``` + +Notice the `draft` value in the [front matter] is `true`. By default, Hugo does not publish draft content when you build the site. Learn more about [draft, future, and expired content]. + +Add some [Markdown] to the body of the post, but do not change the `draft` value. + +```text ++++ +title = 'My First Post' +date = 2024-01-14T07:07:07+01:00 +draft = true ++++ +## Introduction + +This is **bold** text, and this is *emphasized* text. + +Visit the [Hugo](https://gohugo.io) website! +``` + +Save the file, then start Hugo's development server to view the site. You can run either of the following commands to include draft content. + +```text +hugo server --buildDrafts +hugo server -D +``` + +View your site at the URL displayed in your terminal. Keep the development server running as you continue to add and change content. + +When satisfied with your new content, set the front matter `draft` parameter to `false`. + +> [!note] +> Hugo's rendering engine conforms to the CommonMark [specification] for Markdown. The CommonMark organization provides a useful [live testing tool] powered by the reference implementation. + +## Configure the site + +With your editor, open the [site configuration] file (`hugo.toml`) in the root of your project. + +```text +baseURL = 'https://example.org/' +languageCode = 'en-us' +title = 'My New Hugo Site' +theme = 'ananke' +``` + +Make the following changes: + +1. Set the `baseURL` for your production site. This value must begin with the protocol and end with a slash, as shown above. +1. Set the `languageCode` to your language and region. +1. Set the `title` for your production site. + +Start Hugo's development server to see your changes, remembering to include draft content. + +```text +hugo server -D +``` + +> [!note] +> Most theme authors provide configuration guidelines and options. Make sure to visit your theme's repository or documentation site for details. +> +> [The New Dynamic], authors of the Ananke theme, provide [documentation] for configuration and usage. They also provide a [demonstration site]. + +## Publish the site + +In this step you will _publish_ your site, but you will not _deploy_ it. + +When you _publish_ your site, Hugo creates the entire static site in the `public` directory in the root of your project. This includes the HTML files, and assets such as images, CSS files, and JavaScript files. + +When you publish your site, you typically do _not_ want to include [draft, future, or expired content]. The command is simple. + +```text +hugo +``` + +To learn how to _deploy_ your site, see the [host and deploy] section. + +## Ask for help + +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. + +## Other resources + +For other resources to help you learn Hugo, including books and video tutorials, see the [external learning resources](/getting-started/external-learning-resources/) page. + +[Ananke]: https://github.com/theNewDynamic/gohugo-theme-ananke +[are different applications]: https://learn.microsoft.com/en-us/powershell/scripting/whats-new/differences-from-windows-powershell?view=powershell-7.3 +[demonstration site]: https://gohugo-ananke-theme-demo.netlify.app/ +[directory structure]: /getting-started/directory-structure/ +[documentation]: https://github.com/theNewDynamic/gohugo-theme-ananke#readme +[draft, future, and expired content]: /getting-started/usage/#draft-future-and-expired-content +[draft, future, or expired content]: /getting-started/usage/#draft-future-and-expired-content +[forum]: https://discourse.gohugo.io/ +[front matter]: /content-management/front-matter/ +[Git submodule]: https://git-scm.com/book/en/v2/Git-Tools-Submodules +[host and deploy]: /host-and-deploy/ +[Install Git]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git +[Install Hugo]: /installation/ +[live testing tool]: https://spec.commonmark.org/dingus/ +[Markdown]: https://daringfireball.net/projects/markdown +[PowerShell]: https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows +[requesting help]: https://discourse.gohugo.io/t/requesting-help/9132 +[site configuration]: /configuration/ +[specification]: https://spec.commonmark.org/ +[The New Dynamic]: https://www.thenewdynamic.com/ diff --git a/docs/content/en/getting-started/usage.md b/docs/content/en/getting-started/usage.md new file mode 100644 index 000000000..d6bc42550 --- /dev/null +++ b/docs/content/en/getting-started/usage.md @@ -0,0 +1,166 @@ +--- +title: Basic usage +description: Use the command-line interface (CLI) to perform basic tasks. +categories: [] +keywords: [] +weight: 20 +aliases: [/overview/usage/,/extras/livereload/,/doc/usage/,/usage/] +--- + +## Test your installation + +After [installing] Hugo, test your installation by running: + +```sh +hugo version +``` + +You should see something like: + +```text +hugo v0.123.0-3c8a4713908e48e6523f058ca126710397aa4ed5+extended linux/amd64 BuildDate=2024-02-19T16:32:38Z VendorInfo=gohugoio +``` + +## Display available commands + +To see a list of the available commands and flags: + +```sh +hugo help +``` + +To get help with a subcommand, use the `--help` flag. For example: + +```sh +hugo server --help +``` + +## Build your site + +To build your site, `cd` into your project directory and run: + +```sh +hugo +``` + +The [`hugo`] command builds your site, publishing the files to the `public` directory. To publish your site to a different directory, use the [`--destination`] flag or set [`publishDir`] in your site configuration. + +> [!note] +> Hugo does not clear the `public` directory before building your site. Existing files are overwritten, but not deleted. This behavior is intentional to prevent the inadvertent removal of files that you may have added to the `public` directory after the build. +> +> Depending on your needs, you may wish to manually clear the contents of the `public` directory before every build. + +## Draft, future, and expired content + +Hugo allows you to set `draft`, `date`, `publishDate`, and `expiryDate` in the [front matter] of your content. By default, Hugo will not publish content when: + +- The `draft` value is `true` +- The `date` is in the future +- The `publishDate` is in the future +- The `expiryDate` is in the past + +{{< new-in 0.123.0 />}} + +> [!note] +> Hugo publishes descendants of draft, future, and expired [node](g) pages. To prevent publication of these descendants, use the [`cascade`] front matter field to cascade [build options] to the descendant pages. + +You can override the default behavior when running `hugo` or `hugo server` with command line flags: + +```sh +hugo --buildDrafts # or -D +hugo --buildExpired # or -E +hugo --buildFuture # or -F +``` + +Although you can also set these values in your site configuration, it can lead to unwanted results unless all content authors are aware of, and understand, the settings. + +> [!note] +> As noted above, Hugo does not clear the `public` directory before building your site. Depending on the _current_ evaluation of the four conditions above, after the build your `public` directory may contain extraneous files from a previous build. +> +> A common practice is to manually clear the contents of the `public` directory before each build to remove draft, expired, and future content. + +## Develop and test your site + +To view your site while developing layouts or creating content, `cd` into your project directory and run: + +```sh +hugo server +``` + +The [`hugo server`] command builds your site and serves your pages using a minimal HTTP server. When you run `hugo server` it will display the URL of your local site: + +```text +Web Server is available at http://localhost:1313/ +``` + +While the server is running, it watches your project directory for changes to assets, configuration, content, data, layouts, translations, and static files. When it detects a change, the server rebuilds your site and refreshes your browser using [LiveReload]. + +Most Hugo builds are so fast that you may not notice the change unless you are looking directly at your browser. + +### LiveReload + +While the server is running, Hugo injects JavaScript into the generated HTML pages. The LiveReload script creates a connection from the browser to the server via web sockets. You do not need to install any software or browser plugins, nor is any configuration required. + +### Automatic redirection + +When editing content, if you want your browser to automatically redirect to the page you last modified, run: + +```sh +hugo server --navigateToChanged +``` + +## Deploy your site + +> [!note] +> As noted above, Hugo does not clear the `public` directory before building your site. Manually clear the contents of the `public` directory before each build to remove draft, expired, and future content. + +When you are ready to deploy your site, run: + +```sh +hugo +``` + +This builds your site, publishing the files to the `public` directory. The directory structure will look something like this: + +```text +public/ +├── categories/ +│ ├── index.html +│ └── index.xml <-- RSS feed for this section +├── posts/ +│ ├── my-first-post/ +│ │ └── index.html +│ ├── index.html +│ └── index.xml <-- RSS feed for this section +├── tags/ +│ ├── index.html +│ └── index.xml <-- RSS feed for this section +├── index.html +├── index.xml <-- RSS feed for the site +└── sitemap.xml +``` + +In a simple hosting environment, where you typically `ftp`, `rsync`, or `scp` your files to the root of a virtual host, the contents of the `public` directory are all that you need. + +Most of our users deploy their sites using a [CI/CD](g) workflow, where a push[^1] to their GitHub or GitLab repository triggers a build and deployment. Popular providers include [AWS Amplify], [CloudCannon], [Cloudflare Pages], [GitHub Pages], [GitLab Pages], and [Netlify]. + +Learn more in the [host and deploy] section. + +[^1]: The Git repository contains the entire project directory, typically excluding the `public` directory because the site is built _after_ the push. + +[`--destination`]: /commands/hugo/#options +[`cascade`]: /content-management/front-matter/#cascade +[`hugo server`]: /commands/hugo_server/ +[`hugo`]: /commands/hugo/ +[`publishDir`]: /configuration/all/#publishdir +[AWS Amplify]: https://aws.amazon.com/amplify/ +[build options]: /content-management/build-options/ +[CloudCannon]: https://cloudcannon.com/ +[Cloudflare Pages]: https://pages.cloudflare.com/ +[front matter]: /content-management/front-matter/ +[GitHub Pages]: https://pages.github.com/ +[GitLab Pages]: https://docs.gitlab.com/ee/user/project/pages/ +[host and deploy]: /host-and-deploy/ +[installing]: /installation/ +[LiveReload]: https://github.com/livereload/livereload-js +[Netlify]: https://www.netlify.com/ diff --git a/docs/content/en/host-and-deploy/_index.md b/docs/content/en/host-and-deploy/_index.md new file mode 100644 index 000000000..627f12c36 --- /dev/null +++ b/docs/content/en/host-and-deploy/_index.md @@ -0,0 +1,8 @@ +--- +title: Host and deploy +description: Services and tools to host and deploy your site. +categories: [] +keywords: [] +weight: 10 +aliases: [/hosting-and-deployment/] +--- diff --git a/docs/content/en/host-and-deploy/deploy-with-hugo-deploy.md b/docs/content/en/host-and-deploy/deploy-with-hugo-deploy.md new file mode 100644 index 000000000..8feeccbae --- /dev/null +++ b/docs/content/en/host-and-deploy/deploy-with-hugo-deploy.md @@ -0,0 +1,97 @@ +--- +title: Deploy with hugo +description: Deploy your site with the hugo CLI. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hugo-deploy/] +--- + +Use the `hugo deploy` command to deploy your site Amazon S3, Azure Blob Storage, or Google Cloud Storage. + +> [!note] +> This feature requires the Hugo extended/deploy edition. See the [installation] section for details. + +## Assumptions + +1. You have completed the [Quick Start] or have a Hugo website you are ready to deploy and share with the world. +1. You have an account with the service provider ([AWS], [Azure], or [Google Cloud]) that you want to deploy to. +1. You have authenticated. + - AWS: [Install the CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) and run [`aws configure`](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). + - Azure: [Install the CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and run [`az login`](https://docs.microsoft.com/en-us/cli/azure/authenticate-azure-cli). + - Google Cloud: [Install the CLI](https://cloud.google.com/sdk) and run [`gcloud auth login`](https://cloud.google.com/sdk/gcloud/reference/auth/login). + + Each service supports various authentication methods, including environment variables. See [details](https://gocloud.dev/howto/blob/#services). + +1. You have created a bucket to deploy to. If you want your site to be + public, be sure to configure the bucket to be publicly readable as a static website. + - AWS: [create a bucket](https://docs.aws.amazon.com/AmazonS3/latest/gsg/CreatingABucket.html) and [host a static website](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html) + - Azure: [create a storage container](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-quickstart-blobs-portal) and [host a static website](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website) + + - Google Cloud: [create a bucket](https://cloud.google.com/storage/docs/creating-buckets) and [host a static website](https://cloud.google.com/storage/docs/hosting-static-website) + +## Configuration + +Create a deployment target in your [site configuration]. The only required parameters are [`name`] and [`url`]: + +{{< code-toggle file=hugo >}} +[deployment] + [[deployment.targets]] + name = 'production' + url = 's3://my_bucket?region=us-west-1' +{{< /code-toggle >}} + +## Deploy + +To deploy to a target: + +```bash +hugo deploy [--target=<target name>] +``` + +This command syncs the contents of your local `public` directory (the default publish directory) with the destination bucket. If no target is specified, Hugo deploys to the first configured target. + +For more command-line options, see `hugo help deploy` or the [CLI documentation]. + +### File list creation + +`hugo deploy` creates local and remote file lists by traversing the local publish directory and the remote bucket. Inclusion and exclusion are determined by the deployment target's [configuration]: + +- `include`: All files are skipped by default except those that match the pattern. +- `exclude`: Files matching the pattern are skipped. + +> [!note] +> During local file list creation, Hugo skips `.DS_Store` files and hidden directories (those starting with a period, like `.git`), except for the [`.well-known`] directory, which is traversed if present. + +### File list comparison + +Hugo compares the local and remote file lists to identify necessary changes. It first compares file names. If both exist, it compares sizes and MD5 checksums. Any difference triggers a re-upload, and remote files not present locally are deleted. + +> [!note] +> Excluded remote files (due to `include`/`exclude` configuration) won't be deleted. + +The `--force` flag forces all files to be re-uploaded, even if Hugo detects no local/remote differences. + +The `--confirm` or `--dryRun` flags cause Hugo to display the detected differences and then pause or stop. + +### Synchronization + +Hugo applies the changes to the remote bucket: uploading missing or changed files and deleting remote files not present locally. Uploaded file headers are configured remotely based on the matchers configuration. + +> [!note] +> To prevent accidental data loss, Hugo will not delete more than 256 remote files by default. Use the `--maxDeletes` flag to override this limit. + +## Advanced configuration + +See [configure deployment](/configuration/deployment/). + +[`.well-known`]: https://en.wikipedia.org/wiki/Well-known_URI +[`name`]: /configuration/deployment/#name +[`url`]: /configuration/deployment/#url +[AWS]: https://aws.amazon.com +[Azure]: https://azure.microsoft.com +[CLI documentation]: /commands/hugo_deploy/ +[configuration]: /configuration/deployment/#targets-1 +[Google Cloud]: https://cloud.google.com/ +[installation]: /installation/ +[Quick Start]: /getting-started/quick-start/ +[site configuration]: /configuration/deployment/ diff --git a/docs/content/en/host-and-deploy/deploy-with-rclone.md b/docs/content/en/host-and-deploy/deploy-with-rclone.md new file mode 100644 index 000000000..8f641bc5d --- /dev/null +++ b/docs/content/en/host-and-deploy/deploy-with-rclone.md @@ -0,0 +1,43 @@ +--- +title: Deploy with rclone +description: Deploy your site with the rclone CLI. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/deployment-with-rclone/] +--- + +## Assumptions + +- A web host running a web server. This could be a shared hosting environment or a VPS. +- Access to your web host with any of the [protocols supported by rclone](https://rclone.org/#providers), such as SFTP. +- A functional static website built with Hugo +- Deploying from an [Rclone](https://rclone.org) compatible operating system +- You have [installed Rclone](https://rclone.org/install/). + +**NB**: You can remove ``--interactive`` in the commands below once you are comfortable with rclone, if you wish. Also, ``--gc`` and ``--minify`` are optional in the ``hugo`` commands below. + +## Getting started + +The spoiler is that you can even deploy your entire website from any compatible OS with no configuration. Using SFTP for example: + +```txt +hugo --gc --minify +rclone sync --interactive --sftp-host sftp.example.com --sftp-user www-data --sftp-ask-password public/ :sftp:www/ +``` + +## Configure Rclone for even easier usage + +The easiest way is simply to run `rclone config`. + +The [Rclone docs](https://rclone.org/docs/) provide [an example of configuring Rclone to use SFTP](https://rclone.org/sftp/). + +For the next commands, we will assume you configured a remote you named ``hugo-www`` + +The above 'spoiler' commands could become: + +```txt +hugo --gc --minify +rclone sync --interactive public/ hugo-www:www/ +``` + +After you issue the above commands (and respond to any prompts), check your website and you will see that it is deployed. diff --git a/docs/content/en/host-and-deploy/deploy-with-rsync.md b/docs/content/en/host-and-deploy/deploy-with-rsync.md new file mode 100644 index 000000000..d073107fe --- /dev/null +++ b/docs/content/en/host-and-deploy/deploy-with-rsync.md @@ -0,0 +1,135 @@ +--- +title: Deploy with rsync +description: Deploy your site with the rsync CLI. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/deployment-with-rsync/] +--- + +## Assumptions + +- A web host running a web server. This could be a shared hosting environment or a VPS. +- Access to your web host with SSH +- A functional static website built with Hugo + +The spoiler is that you can deploy your entire website with a command that looks like the following: + +```txt +hugo && rsync -avz --delete public/ www-data@ftp.topologix.fr:~/www/ +``` + +As you will see, we'll put this command in a shell script file, which makes building and deployment as easy as executing `./deploy`. + +## Copy Your SSH Key to your host + +To make logging in to your server more secure and less interactive, you can upload your SSH key. If you have already installed your SSH key to your server, you can move on to the next section. + +First, install the ssh client. On Debian distributions, use the following command: + +```sh {file="install-openssh.sh"} +sudo apt-get install openssh-client +``` + +Then generate your ssh key. First, create the `.ssh` directory in your home directory if it doesn't exist: + +```txt +~$ cd && mkdir .ssh & cd .ssh +``` + +Next, execute this command to generate a new keypair called `rsa_id`: + +```txt +~/.ssh/$ ssh-keygen -t rsa -q -C "For SSH" -f rsa_id +``` + +You'll be prompted for a passphrase, which is an extra layer of protection. Enter the passphrase you'd like to use, and then enter it again when prompted, or leave it blank if you don't want to have a passphrase. Not using a passphrase will let you transfer files non-interactively, as you won't be prompted for a password when you log in, but it is slightly less secure. + +To make logging in easier, add a definition for your web host to the file `~/.ssh/config` with the following command, replacing `HOST` with the IP address or hostname of your web host, and `USER` with the username you use to log in to your web host when transferring files: + +```txt +~/.ssh/$ cat >> config <<EOF +Host HOST + Hostname HOST + Port 22 + User USER + IdentityFile ~/.ssh/rsa_id +EOF +``` + +Then copy your ssh public key to the remote server with the `ssh-copy-id` command: + +```txt +~/.ssh/$ ssh-copy-id -i rsa_id.pub USER@HOST.com +``` + +Now you can easily connect to the remote server: + +```txt +~$ ssh user@host +Enter passphrase for key '/home/mylogin/.ssh/rsa_id': +``` + +Now that you can log in with your SSH key, let's create a script to automate deployment of your Hugo site. + +## Shell script + +Create a new script called `deploy` the root of your Hugo tree: + +```txt +~/websites/topologix.fr$ editor deploy +``` + +Add the following content. Replace the `USER`, `HOST`, and `DIR` values with your own values: + +```sh +#!/bin/sh +USER=my-user +HOST=my-server.com +DIR=my/directory/to/topologix.fr/ # the directory where your website files should go + +hugo && rsync -avz --delete public/ ${USER}@${HOST}:~/${DIR} # this will delete everything on the server that's not in the local public directory + +exit 0 +``` + +Note that `DIR` is the relative path from the remote user's home. If you have to specify a full path (for instance `/var/www/mysite/`) you must change `~/${DIR}` to `${DIR}` inside the command-line. For most cases you should not have to. + +Save and close, and make the `deploy` file executable: + +```txt +~/websites/topologix.fr$ chmod +x deploy +``` + +Now you only have to enter the following command to deploy and update your website: + +```txt +~/websites/topologix.fr$ ./deploy +``` + +Your site builds and deploys: + +```txt +Started building sites ... +Built site for language en: +0 draft content +0 future content +0 expired content +5 pages created +0 non-page files copied +0 paginator pages created +0 tags created +0 categories created +total in 56 ms +sending incremental file list +404.html +index.html +index.xml +sitemap.xml +posts/ +posts/index.html + +sent 9,550 bytes received 1,708 bytes 7,505.33 bytes/sec +total size is 966,557 speedup is 85.86 +``` + +You can incorporate other processing tasks into this deployment script as well. diff --git a/docs/content/en/host-and-deploy/host-on-21yunbox.md b/docs/content/en/host-and-deploy/host-on-21yunbox.md new file mode 100644 index 000000000..9ef684fd8 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-21yunbox.md @@ -0,0 +1,52 @@ +--- +title: Host on 21YunBox +description: Host your site on 21YunBox. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-21yunbox/] +--- + +[21YunBox](https://www.21cloudbox.com/) is a fully-managed cloud platform dedicated to make web deployment easy within the Chinese Great Firewall where you can host static sites, backend APIs, databases, cron jobs, and all your other apps in one place. It provides blazing fast Chinese CDN, continuous deployment, one-click HTTPS and [other services like managed databases and backend web services](https://www.21cloudbox.com/docs/), providing an avenue to launch web projects in China. + +21YunBox includes the following features: + +- Continuous, automatic builds & deploys from GitHub and Gitee +- Automatic SSL certificates through [Let's Encrypt](https://letsencrypt.org) +- Instant cache invalidation with a blazing fast, Chinese CDN +- Unlimited [custom domains](https://www.21cloudbox.com/dns-configuration.html) +- Automatic [Brotli compression](https://en.wikipedia.org/wiki/Brotli) for faster sites +- Native HTTP/2 support +- Automatic HTTP → HTTPS redirects +- Custom URL redirects and rewrites + +## Prerequisites + +This guide assumes you already have a Hugo project to deploy. If you need a project, use the [Quick Start](/getting-started/quick-start/) to get started or fork 21YunBox's [Hugo Example](https://gitee.com/eryiyunbox-examples/hello-hugo) before continuing. + +## Setup + +You can set up a Hugo site on 21YunBox in two quick steps: + +1. Create a new web service on 21YunBox, and give 21YunBox permission to access your GitHub or Gitee repo. +1. Use the following values during creation:<!-- do not insert blank line --> + | Field | Value | + | ----------------- | ------------------------------------------------ | + | Environment | `Static Site` | + | Build Command | `hugo --gc --minify` (or your own build command) | + | Publish Directory | `./public` (or your own output directory) | + +That's it! Your site will be live on your 21YunBox URL (which looks like `yoursite.21yunbox.com`) as soon as the build is done. + +## Continuous deploys + +Now that 21YunBox is connected to your repo, it will automatically build and publish your site any time you push to GitHub. + +Every deploy automatically and instantly invalidates the CDN cache, so your users can always access the latest content on your site. + +## Custom domains + +Add your own domains to your site easily using 21YunBox's [custom domains](https://www.21cloudbox.com/dns-configuration.html) guide. + +## Support + +Click [here](https://www.21cloudbox.com/contact.html) to contact with 21YunBox' experts if you need help. diff --git a/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-05.png b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-05.png Binary files differnew file mode 100644 index 000000000..bb98d974a --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-05.png diff --git a/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-06.png b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-06.png Binary files differnew file mode 100644 index 000000000..2e9b96e2b --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-06.png diff --git a/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-07.png b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-07.png Binary files differnew file mode 100644 index 000000000..b3260157b --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-07.png diff --git a/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-08.png b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-08.png Binary files differnew file mode 100644 index 000000000..55e80e710 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-08.png diff --git a/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-09.png b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-09.png Binary files differnew file mode 100644 index 000000000..b422e3ad6 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-09.png diff --git a/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-11.png b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-11.png Binary files differnew file mode 100644 index 000000000..e147edfb9 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-aws-amplify/amplify-step-11.png diff --git 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 new file mode 100644 index 000000000..aadb89116 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-aws-amplify/index.md @@ -0,0 +1,160 @@ +--- +title: Host on AWS Amplify +description: Host your site on AWS Amplify. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-aws-amplify/] +--- + +## 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 + +## 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.85.0 + GO_VERSION: 1.23.3 + HUGO_VERSION: 0.144.2 + # 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 6 + +Authorize AWS Amplify to access your GitHub account. + +  + +### Step 7 + +Select your personal account or relevant organization. + +  + +### Step 8 + +Authorize access to one or more repositories. + +  + +### Step 9 + +Select a repository and branch, then press the **Next** button. + +  + +### 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 + +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. + +  diff --git a/docs/content/en/host-and-deploy/host-on-azure-static-web-apps.md b/docs/content/en/host-and-deploy/host-on-azure-static-web-apps.md new file mode 100644 index 000000000..68fe145ab --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-azure-static-web-apps.md @@ -0,0 +1,11 @@ +--- +title: Host on Azure Static Web Apps +description: Host your site on Azure Static Web Apps. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-azure-static-web-apps/] +--- + +You can create and deploy a Hugo web application to Azure Static Web Apps. The final result is a new Azure Static Web App with associated GitHub Actions that give you control over how the app is built and published. You'll learn how to create a Hugo app, set up an Azure Static Web App and deploy the Hugo app to Azure. + +Here's the tutorial on how to [Publish a Hugo site to Azure Static Web Apps](https://docs.microsoft.com/en-us/azure/static-web-apps/publish-hugo). diff --git a/docs/content/en/host-and-deploy/host-on-cloudflare-pages.md b/docs/content/en/host-and-deploy/host-on-cloudflare-pages.md new file mode 100644 index 000000000..1c3627288 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-cloudflare-pages.md @@ -0,0 +1,11 @@ +--- +title: Host on Cloudflare Pages +description: Host your site on Cloudflare Pages. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-cloudflare-pages/] +--- + +[Cloudflare Pages](https://developers.cloudflare.com/pages/) are super fast, always up-to-date, and deployed directly from your [Git provider](https://developers.cloudflare.com/pages/get-started/#connect-your-git-provider-to-pages). + +Cloudflare Pages docs have a detailed tutorial on [how to deploy a Hugo site](https://developers.cloudflare.com/pages/framework-guides/deploy-a-hugo-site/). diff --git a/docs/content/en/host-and-deploy/host-on-codeberg-pages.md b/docs/content/en/host-and-deploy/host-on-codeberg-pages.md new file mode 100644 index 000000000..cd137c420 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-codeberg-pages.md @@ -0,0 +1,82 @@ +--- +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 `<YourUsername>` refer to your actual Codeberg username and must be substituted accordingly. Likewise, `<YourWebsite>` 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://<YourUsername>.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/<YourUsername>/pages.git +git push -u origin main +``` + +## Automated deployment + +In order to automatically deploy your Hugo website, you need to have or [request] access to Codeberg's CI, 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. `<YourWebsite>`) 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/<YourUsername>/<YourWebsite>.git +git push -u origin main +``` + +Your project will then be built and deployed by Codeberg's CI. + +## Other resources + +- [Codeberg Pages](https://codeberg.page/) +- [Codeberg Pages official documentation](https://docs.codeberg.org/codeberg-pages/) diff --git a/docs/content/en/host-and-deploy/host-on-firebase.md b/docs/content/en/host-and-deploy/host-on-firebase.md new file mode 100644 index 000000000..267c8d127 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-firebase.md @@ -0,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? + +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) + +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? + +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? + +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 + +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 --git a/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-1.png b/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-1.png Binary files differnew file mode 100644 index 000000000..29912f25c --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-1.png diff --git a/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-2.png b/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-2.png Binary files differnew file mode 100644 index 000000000..0050d33e2 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-2.png diff --git a/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-3.png b/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-3.png Binary files differnew file mode 100644 index 000000000..d2904cae1 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-3.png diff --git a/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-4.png b/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-4.png Binary files differnew file mode 100644 index 000000000..75774462b --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-4.png diff --git a/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-5.png b/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-5.png Binary files differnew file mode 100644 index 000000000..efe26129a --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-github-pages/gh-pages-5.png diff --git 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 new file mode 100644 index 000000000..4c00fbc8e --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-github-pages/index.md @@ -0,0 +1,230 @@ +--- +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: + + +{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. + + +{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: + HUGO_VERSION: 0.145.0 + 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: sudo snap install dart-sass + - 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: 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: + + +{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. + + +{style="max-width: 350px"} + +### Step 11 + +Click on the commit message as shown above. You will see this: + + +{style="max-width: 611px"} + +Under the deploy step, you will see a link to your live site. + +In the future, whenever you push a change from your local repository, GitHub will rebuild your site and deploy the changes. + +## 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/ diff --git a/docs/content/en/host-and-deploy/host-on-gitlab-pages.md b/docs/content/en/host-and-deploy/host-on-gitlab-pages.md new file mode 100644 index 000000000..4b308cc19 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-gitlab-pages.md @@ -0,0 +1,96 @@ +--- +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://<YourUsername>.gitlab.io/<your-hugo-site>/`) 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.85.0 + GIT_DEPTH: 0 + GIT_STRATEGY: clone + GIT_SUBMODULE_STRATEGY: recursive + HUGO_VERSION: 0.144.2 + NODE_VERSION: 23.x + TZ: America/Los_Angeles +image: + name: golang:1.23.4-bookworm + +pages: + script: + # Install brotli + - apt-get update + - apt-get install -y brotli + # 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 + # 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 + # Install Node.js + - curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION} | bash - + - apt-get install -y nodejs + # Install Node.js dependencies + - "[[ -f package-lock.json || -f npm-shrinkwrap.json ]] && npm ci || true" + # 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 {} \; + 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. + +```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/<YourUsername>/<your-hugo-site>/pipelines`. + +After the build has passed, your new website is available at `https://<YourUsername>.gitlab.io/<your-hugo-site>/`. + +## 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 --git a/docs/content/en/host-and-deploy/host-on-keycdn/index.md b/docs/content/en/host-and-deploy/host-on-keycdn/index.md new file mode 100644 index 000000000..828e250c6 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-keycdn/index.md @@ -0,0 +1,86 @@ +--- +title: Host on KeyCDN +description: Host your site on KeyCDN. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-keycdn/] +--- + +[KeyCDN](https://www.keycdn.com/) provides a multitude of features to help accelerate and secure your Hugo site globally including Brotli compression, Let's Encrypt support, Origin Shield, and more. + +## Assumptions + +- You already have a Hugo page configured +- You have a GitLab account +- You have a KeyCDN account + +## Create a KeyCDN Pull Zone + +The first step will be to log in to your KeyCDN account and create a new zone. Name this whatever you like and select the [Pull Zone](https://www.keycdn.com/support/create-a-pull-zone/) option. As for the origin URL, your site will be running on [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/getting_started_part_one.html) with a URL of `https://youruser.gitlab.io/reponame/`. Use this as the Origin URL. + + + +While the origin location doesn't exist yet, you will need to use your new Zone URL address (or [Zone Alias](https://www.keycdn.com/support/create-a-zone-alias/)) in the `.gitlab-ci.yml` file that will be uploaded to your GitLab project. + +Ensure that you use your Zone URL or Zone alias as the `BASEURL` variable in the example below. This will be the user-visible website address. + +## Configure Your .gitlab-ci.yml File + +Your `.gitlab-ci.yml` file should look similar to the example below. Be sure to modify any variables that are specific to your setup. + +```yml +image: alpine:latest + +variables: + BASEURL: "https://cipull-7bb7.kxcdn.com/" + HUGO_VERSION: "0.26" + HUGO_CHECKSUM: "67e4ba5ec2a02c8164b6846e30a17cc765b0165a5b183d5e480149baf54e1a50" + KEYCDN_ZONE_ID: "75544" + +before_script: + - apk update + - apk add curl + +pages: + stage: deploy + script: + - apk add git + - git submodule update --init + - curl -sSL https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.tar.gz -o /tmp/hugo.tar.gz + - echo "${HUGO_CHECKSUM} /tmp/hugo.tar.gz" | sha256sum -c + - tar xf /tmp/hugo.tar.gz hugo -C /tmp/ && cp /tmp/hugo /usr/bin + - hugo --baseURL ${BASEURL} + - curl "https://api.keycdn.com/zones/purge/${KEYCDN_ZONE_ID}.json" -u "${KEYCDN_API_KEY}:" + artifacts: + paths: + - public + only: + - master +``` + +Using this integration method, you will have to specify the Zone ID and your [KeyCDN API](https://www.keycdn.com/api) key as secret variables. To do this, navigate to the top-left menu bar in GitLab and select Projects. Then, select your project and click on the Settings page. Finally, select Pipelines from the sub-menu and scroll down to the Secret Variable section. + +The Secret Variable for your Zone ID should look similar to: + + + +While the Secret Variable for your API Key will look similar to: + + + +While not strictly required, providing your Zone ID and API key is recommended for purging your zone. Without them, the CDN may continue serving outdated versions of your assets for an extended period. + +## Push your changes to GitLab + +Now it's time to push the newly created repository to GitLab: + +```sh +git remote add origin git@gitlab.com:youruser/ci-example.git +git push -u origin master +``` + +You can watch the progress and CI job output in your GitLab project under “Pipelines”. + +After verifying your CI job ran without issues, first check that your GitLab page shows up under `https://youruser.gitlab.io/reponame/` (it might look broken depending on your browser settings as all links point to your KeyCDN zone---don't worry about that) and then by heading to whatever Zone alias / Zone URL you defined. + +To learn more about Hugo hosting options with KeyCDN, check out the complete [Hugo hosting with KeyCDN integration guide](https://www.keycdn.com/support/hugo-hosting/). diff --git a/docs/content/en/host-and-deploy/host-on-keycdn/keycdn-pull-zone.png b/docs/content/en/host-and-deploy/host-on-keycdn/keycdn-pull-zone.png Binary files differnew file mode 100644 index 000000000..7cde4a6a2 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-keycdn/keycdn-pull-zone.png diff --git a/docs/content/en/host-and-deploy/host-on-keycdn/secret-api-key.png b/docs/content/en/host-and-deploy/host-on-keycdn/secret-api-key.png Binary files differnew file mode 100644 index 000000000..ad99341d5 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-keycdn/secret-api-key.png diff --git a/docs/content/en/host-and-deploy/host-on-keycdn/secret-zone-id.png b/docs/content/en/host-and-deploy/host-on-keycdn/secret-zone-id.png Binary files differnew file mode 100644 index 000000000..2e5cf5f41 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-keycdn/secret-zone-id.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/index.md b/docs/content/en/host-and-deploy/host-on-netlify/index.md new file mode 100644 index 000000000..f3601331a --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/index.md @@ -0,0 +1,143 @@ +--- +title: Host on Netlify +description: Host your site on Netlify. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-netlify/] +--- + +## 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 + +## 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 + +Select your deployment method. + +  + +### Step 3 + +Authorize Netlify to connect with your GitHub account by pressing the **Authorize Netlify** button. + + + +### Step 4 + +Press the **Configure Netlify on GitHub** button. + + + +### Step 5 + +Install the Netlify app by selecting your GitHub account. + + + +### Step 6 + +Press the **Install** button. + + + +### Step 7 + +Click on the site's repository from the list. + + + +### Step 8 + +Set the site name and branch from which to deploy. + + + +### Step 9 + +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]. + +[latest version]: https://github.com/gohugoio/hugo/releases/latest + + + +### Step 11 + +Press the "Deploy my new site" button at the bottom of the page. + + + +### Step 12 + +At the bottom of the screen, wait for the deploy to complete, then click on the deploy log entry. + + + +### Step 13 + +Press the **Open production deploy** button to view the live site. + + + +## 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: + +```toml {file="netlify.toml"} +[build.environment] +HUGO_VERSION = "0.144.2" +NODE_VERSION = "22" +TZ = "America/Los_Angeles" + +[build] +publish = "public" +command = "hugo --gc --minify" +``` + +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] +HUGO_VERSION = "0.144.2" +DART_SASS_VERSION = "1.85.0" +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 \ + """ +``` diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-02.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-02.png Binary files differnew file mode 100644 index 000000000..31fceff27 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-02.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-03.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-03.png Binary files differnew file mode 100644 index 000000000..7b98e0b8f --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-03.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-04.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-04.png Binary files differnew file mode 100644 index 000000000..31304894b --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-04.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-05.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-05.png Binary files differnew file mode 100644 index 000000000..6d6eef01d --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-05.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-06.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-06.png Binary files differnew file mode 100644 index 000000000..1b766a785 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-06.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-07.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-07.png Binary files differnew file mode 100644 index 000000000..7bb3b6eca --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-07.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-08.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-08.png Binary files differnew file mode 100644 index 000000000..df8e9e59f --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-08.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-09.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-09.png Binary files differnew file mode 100644 index 000000000..3f925accc --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-09.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-10.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-10.png Binary files differnew file mode 100644 index 000000000..e9196d0ce --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-10.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-11.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-11.png Binary files differnew file mode 100644 index 000000000..2ac2b08af --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-11.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-12.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-12.png Binary files differnew file mode 100644 index 000000000..e251305a4 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-12.png diff --git a/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-13.png b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-13.png Binary files differnew file mode 100644 index 000000000..f955f6369 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-netlify/netlify-step-13.png diff --git a/docs/content/en/host-and-deploy/host-on-render.md b/docs/content/en/host-and-deploy/host-on-render.md new file mode 100644 index 000000000..ac486fcbf --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-render.md @@ -0,0 +1,78 @@ +--- +title: Host on Render +description: Host your on Render. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-render/] +--- + +## Introduction + +[Render](https://render.com) is a fully-managed cloud platform where you can host static sites, backend APIs, databases, cron jobs, and all your other apps in one place. + +Static sites are **completely free** on Render and include the following: + +- Continuous, automatic builds & deploys from [GitHub](https://render.com/docs/github) and [GitLab](https://render.com/docs/gitlab). +- Automatic SSL certificates through [Let's Encrypt](https://letsencrypt.org). +- Instant cache invalidation with a lightning fast, global CDN. +- Unlimited collaborators. +- Unlimited [custom domains](https://render.com/docs/custom-domains). +- Automatic [Brotli compression](https://en.wikipedia.org/wiki/Brotli) for faster sites. +- Native HTTP/2 support. +- [Pull Request Previews](https://render.com/docs/pull-request-previews). +- Automatic HTTP → HTTPS redirects. +- Custom URL redirects and rewrites. + +## Assumptions + +- You have an account with GitHub or GitLab. +- You have completed the [Quick Start] or have a Hugo website you are ready to deploy and share with the world. +- You have a Render account. You can sign up at https://render.com/register. + +## Deployment + +You can set up a Hugo site on Render in two quick steps: + +1. Create a new **Static Site** on Render, and give Render permission to access your GitHub/GitLab repo. +1. Use the following values during creation: + +Field | Value +------------------- | ------------------- +**Build Command** | `hugo --gc --minify` (or your own build command) +**Publish Directory** | `public` (or your own output directory) + +That's it! Your site will be live on your Render URL (which looks like `yoursite.onrender.com`) as soon as the build is done. + +## Continuous deploys + +Now that Render is connected to your repo, it will **automatically build and publish your site** any time you push to your GitHub/GitLab. + +You can choose to disable auto deploys under the **Settings** section for your site and deploy it manually from the Render dashboard. + +## CDN and cache invalidation + +Render hosts your site on a global, lightning fast CDN which ensures the fastest possible download times for all your users across the globe. + +Every deploy automatically and instantly invalidates the CDN cache, so your users can always access the latest content on your site. + +## Custom domains + +Add your own domains to your site easily using Render's [custom domains](https://render.com/docs/custom-domains) guide. + +## Pull Request previews + +With Pull Request (PR) previews, you can visualize changes introduced in a pull request instead of simply relying on code reviews. + +Once enabled, every PR for your site will automatically generate a new static site based on the code in the PR. It will have its own URL, and it will be deleted automatically when the PR is closed. + +Read more about [Pull Request Previews](https://render.com/docs/pull-request-previews) on Render. + +## Hugo themes + +Render automatically downloads all Git submodules defined in your Git repo on every build. This way Hugo themes added as submodules work as expected. + +## Support + +Chat with Render developers at https://render.com/chat or email `support@render.com` if you need help. + +[Quick Start]: /getting-started/quick-start/ diff --git a/docs/content/en/host-and-deploy/host-on-sourcehut-pages.md b/docs/content/en/host-and-deploy/host-on-sourcehut-pages.md new file mode 100644 index 000000000..6b092fbf2 --- /dev/null +++ b/docs/content/en/host-and-deploy/host-on-sourcehut-pages.md @@ -0,0 +1,94 @@ +--- +title: Host on SourceHut Pages +description: Host your site on SourceHut Pages. +categories: [] +keywords: [] +aliases: [/hosting-and-deployment/hosting-on-sourcehut/] +--- + +## Assumptions + +- Working familiarity with [Git] or [Mercurial] for version control +- Completion of the Hugo [Quick Start] +- A [SourceHut account] +- A Hugo website on your local machine that you are ready to publish + +[Git]: https://git-scm.com/ +[Mercurial]: https://www.mercurial-scm.org/ +[SourceHut account]: https://meta.sr.ht/login +[Quick Start]: /getting-started/quick-start/ + +Any and all mentions of `<YourUsername>` refer to your actual SourceHut username and must be substituted accordingly. + +## BaseURL + +The [`baseURL`] in your site configuration must reflect the full URL provided by SourceHut Pages if you are using the default address (e.g. `https://<YourUsername>.srht.site/`). If you want to use another domain, check the [custom domain section] of the official documentation. + +[`baseURL`]: /configuration/all/#baseurl +[custom domain section]: https://srht.site/custom-domains + +## Manual deployment + +This method does not require a paid account. To proceed you will need to create a [SourceHut personal access token] and install and configure the [hut]CLI tool: + +[SourceHut personal access token]: https://meta.sr.ht/oauth2/personal-token/ +[hut]: https://sr.ht/~xenrox/hut/ + +```sh +hugo +tar -C public -cvz . > site.tar.gz +hut init +hut pages publish -d <YourUsername>.srht.site site.tar.gz +``` + +A TLS certificate will be automatically obtained for you, and your new website will be available at `https://<YourUsername>.srht.site/` (or the provided custom domain). + +## Automated deployment + +This method requires a paid account and relies on the SourceHut build system. + +First, define your [build manifest] by creating a `.build.yml` file in the root of your project. The following is a bare-bones template: + +[build manifest]: https://man.sr.ht/builds.sr.ht/#build-manifests + +```yaml {file=".build.yml" copy=true} +image: alpine/edge +packages: + - hugo + - hut +oauth: pages.sr.ht/PAGES:RW +environment: + site: <YourUsername>.srht.site +tasks: +- package: | + cd $site + hugo + tar -C public -cvz . > ../site.tar.gz +- upload: | + hut pages publish -d $site site.tar.gz +``` + +Now what's left is creating a repository titled `<YourUsername>.srht.site` (or your custom domain, if applicable) and pushing your local project. Here's an example using Git: + +```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://git.sr.ht/~<YourUsername>/<YourUsername>.srht.site +git push -u origin main +``` + +You can now follow the build progress of your page at `https://builds.sr.ht/`. + +After the build has passed, a TLS certificate will be automatically obtained for you and your new website will be available at `https://<YourUsername>.srht.site/` (or the provided custom domain). + +## Other resources + +- [SourceHut Pages](https://srht.site/) +- [SourceHut Builds user manual](https://man.sr.ht/builds.sr.ht/) diff --git a/docs/content/en/hugo-modules/_index.md b/docs/content/en/hugo-modules/_index.md new file mode 100644 index 000000000..7a538ea15 --- /dev/null +++ b/docs/content/en/hugo-modules/_index.md @@ -0,0 +1,8 @@ +--- +title: Hugo Modules +description: Use Hugo Modules to manage the content, presentation, and behavior of your site. +categories: [] +keywords: [] +weight: 10 +aliases: [/themes/overview/,/themes/] +--- diff --git a/docs/content/en/hugo-modules/introduction.md b/docs/content/en/hugo-modules/introduction.md new file mode 100644 index 000000000..b45607dc0 --- /dev/null +++ b/docs/content/en/hugo-modules/introduction.md @@ -0,0 +1,19 @@ +--- +title: Introduction +description: A brief introduction to Hugo Modules. +categories: [] +keywords: [] +weight: 10 +--- + +Hugo uses modules as its fundamental organizational units. A module can be a full Hugo project or a smaller, reusable piece providing one or more of Hugo's seven component types: static files, content, layouts, data, assets, internationalization (i18n) resources, and archetypes. + +Modules are combinable in any arrangement, and external directories (including those from non-Hugo projects) can be mounted, effectively creating a single, unified file system. + +Some example projects: + +[https://github.com/bep/docuapi](https://github.com/bep/docuapi) +: A theme that has been ported to Hugo Modules while testing this feature. It is a good example of a non-Hugo-project mounted into Hugo's directory structure. It even shows a JS Bundler implementation in regular Go templates. + +[https://github.com/bep/my-modular-site](https://github.com/bep/my-modular-site) +: A simple site used for testing. diff --git a/docs/content/en/hugo-modules/theme-components.md b/docs/content/en/hugo-modules/theme-components.md new file mode 100644 index 000000000..03891ed7a --- /dev/null +++ b/docs/content/en/hugo-modules/theme-components.md @@ -0,0 +1,35 @@ +--- +title: Theme components +description: Hugo provides advanced theming support with theme components. +categories: [] +keywords: [] +weight: 30 +aliases: [/themes/customize/,/themes/customizing/] +--- + +A project can configure a theme as a composite of as many theme components as you need: + +{{< code-toggle file=hugo >}} +theme = ["my-shortcodes", "base-theme", "hyde"] +{{< /code-toggle >}} + +You can even nest this, and have the theme component itself include theme components in its own `hugo.toml` (theme inheritance). + +The theme definition example above in `hugo.toml` creates a theme with 3 theme components with precedence from left to right. + +For any given file, data entry, etc., Hugo will look first in the project and then in `my-shortcodes`, `base-theme`, and lastly `hyde`. + +Hugo uses two different algorithms to merge the file systems, depending on the file type: + +- For `i18n` and `data` files, Hugo merges deeply using the translation ID and data key inside the files. +- For `static`, `layouts` (templates), and `archetypes` files, these are merged on file level. So the left-most file will be chosen. + +The name used in the `theme` definition above must match a directory in `/your-site/themes`, e.g. `/your-site/themes/my-shortcodes`. + +Also note that a component that is part of a theme can have its own configuration file, e.g. `hugo.toml`. There are currently some restrictions to what a theme component can configure: + +- `params` (global and per language) +- `menu` (global and per language) +- `outputformats` and `mediatypes` + +The same rules apply here: The left-most parameter/menu etc. with the same ID will win. There are some hidden and experimental namespace support in the above, which we will work to improve in the future, but theme authors are encouraged to create their own namespaces to avoid naming conflicts. diff --git a/docs/content/en/hugo-modules/use-modules.md b/docs/content/en/hugo-modules/use-modules.md new file mode 100644 index 000000000..86d2ad1cc --- /dev/null +++ b/docs/content/en/hugo-modules/use-modules.md @@ -0,0 +1,154 @@ +--- +title: Use Hugo Modules +description: How to use Hugo Modules. +categories: [] +keywords: [] +weight: 20 +aliases: [/themes/usage/,/themes/installing/,/installing-and-using-themes/] +--- + +## Prerequisite + +{{% include "/_common/gomodules-info.md" %}} + +## Initialize a new module + +Use `hugo mod init` to initialize a new Hugo Module. If it fails to guess the module path, you must provide it as an argument, e.g.: + +```sh +hugo mod init github.com/<your_user>/<your_project> +``` + +Also see the [CLI Doc](/commands/hugo_mod_init/). + +## Use a module for a theme + +The easiest way to use a Module for a theme is to import it in the configuration. + +1. Initialize the hugo module system: `hugo mod init github.com/<your_user>/<your_project>` +1. Import the theme: + + {{< code-toggle file=hugo >}} + [module] + [[module.imports]] + path = "github.com/spf13/hyde" + {{< /code-toggle >}} + +## Update modules + +Modules will be downloaded and added when you add them as imports to your configuration. See [configure modules](/configuration/module/#imports). + +To update or manage versions, you can use `hugo mod get`. + +Some examples: + +### Update all modules + +```sh +hugo mod get -u +``` + +### Update all modules recursively + +```sh +hugo mod get -u ./... +``` + +### Update one module + +```sh +hugo mod get -u github.com/gohugoio/myShortcodes +``` + +### Get a specific version + +```sh +hugo mod get github.com/gohugoio/myShortcodes@v1.0.7 +``` + +Also see the [CLI Doc](/commands/hugo_mod_get/). + +## Make and test changes in a module + +One way to do local development of a module imported in a project is to add a replace directive to a local directory with the source in `go.mod`: + +```sh +replace github.com/bep/hugotestmods/mypartials => /Users/bep/hugotestmods/mypartials +``` + +If you have the `hugo server` running, the configuration will be reloaded and `/Users/bep/hugotestmods/mypartials` put on the watch list. + +Instead of modifying the `go.mod` files, you can also use the modules configuration [`replacements`](/configuration/module/#top-level-options) option. + +## Print dependency graph + +Use `hugo mod graph` from the relevant module directory and it will print the dependency graph, including vendoring, module replacement or disabled status. + +E.g.: + +```txt +hugo mod graph + +github.com/bep/my-modular-site github.com/bep/hugotestmods/mymounts@v1.2.0 +github.com/bep/my-modular-site github.com/bep/hugotestmods/mypartials@v1.0.7 +github.com/bep/hugotestmods/mypartials@v1.0.7 github.com/bep/hugotestmods/myassets@v1.0.4 +github.com/bep/hugotestmods/mypartials@v1.0.7 github.com/bep/hugotestmods/myv2@v1.0.0 +DISABLED github.com/bep/my-modular-site github.com/spf13/hyde@v0.0.0-20190427180251-e36f5799b396 +github.com/bep/my-modular-site github.com/bep/hugo-fresh@v1.0.1 +github.com/bep/my-modular-site in-themesdir +``` + +Also see the [CLI Doc](/commands/hugo_mod_graph/). + +## Vendor your modules + +`hugo mod vendor` will write all the module dependencies to a `_vendor` directory, which will then be used for all subsequent builds. + +Note that: + +- You can run `hugo mod vendor` on any level in the module tree. +- Vendoring will not store modules stored in your `themes` directory. +- Most commands accept a `--ignoreVendorPaths` flag, which will then not use the vendored modules in `_vendor` for the module paths matching the given [glob](g) pattern. + +Also see the [CLI Doc](/commands/hugo_mod_vendor/). + +## Tidy go.mod, go.sum + +Run `hugo mod tidy` to remove unused entries in `go.mod` and `go.sum`. + +Also see the [CLI Doc](/commands/hugo_mod_clean/). + +## Clean module cache + +Run `hugo mod clean` to delete the entire modules cache. + +Note that you can also configure the `modules` cache with a `maxAge`. See [configure caches](/configuration/caches/). + +Also see the [CLI Doc](/commands/hugo_mod_clean/). + +## Module workspaces + +Workspace support was added in [Go 1.18](https://go.dev/blog/get-familiar-with-workspaces) and Hugo got solid support for it in the `v0.109.0` version. + +A common use case for a workspace is to simplify local development of a site with its theme modules. + +A workspace can be configured in a `*.work` file and activated with the [module.workspace](/configuration/module/) setting, which for this use is commonly controlled via the `HUGO_MODULE_WORKSPACE` OS environment variable. + +See the [hugo.work](https://github.com/gohugoio/hugo/blob/master/docs/hugo.work) file in the Hugo Docs repo for an example: + +```text +go 1.20 + +use . +use ../gohugoioTheme +``` + +Using the `use` directive, list all the modules you want to work on, pointing to its relative location. As in the example above, it's recommended to always include the main project (the `.`) in the list. + +With that you can start the Hugo server with that workspace enabled: + +```sh +HUGO_MODULE_WORKSPACE=hugo.work hugo server --ignoreVendorPaths "**" +``` + +The `--ignoreVendorPaths` flag is added above to ignore any of the vendored dependencies inside `_vendor`. If you don't use vendoring, you don't need that flag. But now the server is set up watching the files and directories in the workspace and you can see your local edits reloaded. diff --git a/docs/content/en/hugo-pipes/_index.md b/docs/content/en/hugo-pipes/_index.md new file mode 100755 index 000000000..51028152b --- /dev/null +++ b/docs/content/en/hugo-pipes/_index.md @@ -0,0 +1,7 @@ +--- +title: Hugo Pipes +description: Use asset pipelines to transform and optimize images, stylesheets, and JavaScript. +categories: [] +keywords: [] +weight: 10 +--- diff --git a/docs/content/en/hugo-pipes/bundling.md b/docs/content/en/hugo-pipes/bundling.md new file mode 100755 index 000000000..335cc5cae --- /dev/null +++ b/docs/content/en/hugo-pipes/bundling.md @@ -0,0 +1,9 @@ +--- +title: Concat +linkTitle: Concatenating assets +description: Bundle any number of assets into one resource. +categories: [] +keywords: [] +--- + +See the [`resources.Concat`](/functions/resources/concat/) function. diff --git a/docs/content/en/hugo-pipes/fingerprint.md b/docs/content/en/hugo-pipes/fingerprint.md new file mode 100755 index 000000000..d38dfc106 --- /dev/null +++ b/docs/content/en/hugo-pipes/fingerprint.md @@ -0,0 +1,9 @@ +--- +title: Fingerprint +linkTitle: Fingerprinting and SRI hashing +description: Cryptographically hash the content of the given resource. +categories: [] +keywords: [] +--- + +See the [`resources.Fingerprint`](/functions/resources/fingerprint/) function. diff --git a/docs/content/en/hugo-pipes/introduction.md b/docs/content/en/hugo-pipes/introduction.md new file mode 100755 index 000000000..d1b93094f --- /dev/null +++ b/docs/content/en/hugo-pipes/introduction.md @@ -0,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 }} +<link rel="stylesheet" href="{{ $style.Permalink }}"> +``` + +## Caching + +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 --git a/docs/content/en/hugo-pipes/js.md b/docs/content/en/hugo-pipes/js.md new file mode 100644 index 000000000..18572d538 --- /dev/null +++ b/docs/content/en/hugo-pipes/js.md @@ -0,0 +1,9 @@ +--- +title: JavaScript +linkTitle: JavaScript building +description: Bundle, transpile, tree shake, code split, and minify JavaScript resources. +categories: [] +keywords: [] +--- + +See [JS functions](/functions/js/). diff --git a/docs/content/en/hugo-pipes/minification.md b/docs/content/en/hugo-pipes/minification.md new file mode 100755 index 000000000..4ba1ea641 --- /dev/null +++ b/docs/content/en/hugo-pipes/minification.md @@ -0,0 +1,9 @@ +--- +title: Minify +linkTitle: Asset minification +description: Minify a given resource. +categories: [] +keywords: [] +--- + +See the [`resources.Minify`](/functions/resources/minify/) function. diff --git a/docs/content/en/hugo-pipes/postcss.md b/docs/content/en/hugo-pipes/postcss.md new file mode 100755 index 000000000..1b47e8aef --- /dev/null +++ b/docs/content/en/hugo-pipes/postcss.md @@ -0,0 +1,8 @@ +--- +title: PostCSS +description: Process the given resource with PostCSS using any PostCSS plugin. +categories: [] +keywords: [] +--- + +See the [`css.PostCSS`](/functions/css/postcss/) function. diff --git a/docs/content/en/hugo-pipes/postprocess.md b/docs/content/en/hugo-pipes/postprocess.md new file mode 100755 index 000000000..72540fd5d --- /dev/null +++ b/docs/content/en/hugo-pipes/postprocess.md @@ -0,0 +1,8 @@ +--- +title: PostProcess +description: Process the given resource after the build. +categories: [] +keywords: [] +--- + +See the [`resources.PostProcess`](/functions/resources/postprocess/) function. diff --git a/docs/content/en/hugo-pipes/resource-from-string.md b/docs/content/en/hugo-pipes/resource-from-string.md new file mode 100755 index 000000000..ed5eaff80 --- /dev/null +++ b/docs/content/en/hugo-pipes/resource-from-string.md @@ -0,0 +1,9 @@ +--- +title: FromString +linkTitle: Resource from string +description: Create a resource from a string. +categories: [] +keywords: [] +--- + +See the [`resources.FromString`](/functions/resources/fromstring/) function. diff --git a/docs/content/en/hugo-pipes/resource-from-template.md b/docs/content/en/hugo-pipes/resource-from-template.md new file mode 100755 index 000000000..bc50f630b --- /dev/null +++ b/docs/content/en/hugo-pipes/resource-from-template.md @@ -0,0 +1,9 @@ +--- +title: ExecuteAsTemplate +linkTitle: Resource from template +description: Create a resource from a Go template, parsed and executed with the given context. +categories: [] +keywords: [] +--- + +See the [`resources.ExecuteAsTemplate`](/functions/resources/executeastemplate/) function. diff --git a/docs/content/en/hugo-pipes/transpile-sass-to-css.md b/docs/content/en/hugo-pipes/transpile-sass-to-css.md new file mode 100644 index 000000000..756914297 --- /dev/null +++ b/docs/content/en/hugo-pipes/transpile-sass-to-css.md @@ -0,0 +1,10 @@ +--- +title: ToCSS +linkTitle: Transpile Sass to CSS +description: Transpile Sass to CSS. +categories: [] +keywords: [] +aliases: [/hugo-pipes/transform-to-css/] +--- + +See the [`css.Sass`](/functions/css/sass) function. diff --git a/docs/content/en/installation/_index.md b/docs/content/en/installation/_index.md new file mode 100644 index 000000000..fdcb8f9eb --- /dev/null +++ b/docs/content/en/installation/_index.md @@ -0,0 +1,8 @@ +--- +title: Installation +description: Install Hugo on macOS, Linux, Windows, BSD, and on any machine that can run the Go compiler tool chain. +categories: [] +keywords: [] +weight: 10 +aliases: [/getting-started/installing/] +--- diff --git a/docs/content/en/installation/bsd.md b/docs/content/en/installation/bsd.md new file mode 100644 index 000000000..2f6519e6d --- /dev/null +++ b/docs/content/en/installation/bsd.md @@ -0,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 +:--|:--:|:--:|:--: +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 --git a/docs/content/en/installation/linux.md b/docs/content/en/installation/linux.md new file mode 100644 index 000000000..731cfce4c --- /dev/null +++ b/docs/content/en/installation/linux.md @@ -0,0 +1,202 @@ +--- +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 enable or revoke access to removable media: + +```sh +sudo snap connect hugo:removable-media +sudo snap disconnect hugo:removable-media +``` + +To enable or revoke access to SSH keys: + +```sh +sudo snap connect hugo:ssh-keys +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 +:--|:--:|:--:|:--:|:--: +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 --git a/docs/content/en/installation/macos.md b/docs/content/en/installation/macos.md new file mode 100644 index 000000000..a873b512a --- /dev/null +++ b/docs/content/en/installation/macos.md @@ -0,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 +:--|:--:|:--:|:--: +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 --git a/docs/content/en/installation/windows.md b/docs/content/en/installation/windows.md new file mode 100644 index 000000000..a5920d45f --- /dev/null +++ b/docs/content/en/installation/windows.md @@ -0,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 +:--|:--:|:--:|:--: +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 --git a/docs/content/en/methods/_index.md b/docs/content/en/methods/_index.md new file mode 100644 index 000000000..39f2b6146 --- /dev/null +++ b/docs/content/en/methods/_index.md @@ -0,0 +1,8 @@ +--- +title: Methods +description: Use these methods within your templates. +categories: [] +keywords: [] +weight: 10 +aliases: ['/variables/'] +--- diff --git a/docs/content/en/methods/duration/Abs.md b/docs/content/en/methods/duration/Abs.md new file mode 100644 index 000000000..2e85797ea --- /dev/null +++ b/docs/content/en/methods/duration/Abs.md @@ -0,0 +1,15 @@ +--- +title: Abs +description: Returns the absolute value of the given time.Duration value. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Duration + signatures: [DURATION.Abs] +--- + +```go-html-template +{{ $d = time.ParseDuration "-3h" }} +{{ $d.Abs }} → 3h0m0s +``` diff --git a/docs/content/en/methods/duration/Hours.md b/docs/content/en/methods/duration/Hours.md new file mode 100644 index 000000000..23655510e --- /dev/null +++ b/docs/content/en/methods/duration/Hours.md @@ -0,0 +1,15 @@ +--- +title: Hours +description: Returns the time.Duration value as a floating point number of hours. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: float64 + signatures: [DURATION.Hours] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Hours }} → 3.5420833333333333 +``` diff --git a/docs/content/en/methods/duration/Microseconds.md b/docs/content/en/methods/duration/Microseconds.md new file mode 100644 index 000000000..c090316d0 --- /dev/null +++ b/docs/content/en/methods/duration/Microseconds.md @@ -0,0 +1,15 @@ +--- +title: Microseconds +description: Returns the time.Duration value as an integer microsecond count. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int64 + signatures: [DURATION.Microseconds] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Microseconds }} → 12751500000 +``` diff --git a/docs/content/en/methods/duration/Milliseconds.md b/docs/content/en/methods/duration/Milliseconds.md new file mode 100644 index 000000000..288f3695a --- /dev/null +++ b/docs/content/en/methods/duration/Milliseconds.md @@ -0,0 +1,15 @@ +--- +title: Milliseconds +description: Returns the time.Duration value as an integer millisecond count. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int64 + signatures: [DURATION.Milliseconds] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Milliseconds }} → 12751500 +``` diff --git a/docs/content/en/methods/duration/Minutes.md b/docs/content/en/methods/duration/Minutes.md new file mode 100644 index 000000000..aec904fa7 --- /dev/null +++ b/docs/content/en/methods/duration/Minutes.md @@ -0,0 +1,15 @@ +--- +title: Minutes +description: Returns the time.Duration value as a floating point number of minutes. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: float64 + signatures: [DURATION.Minutes] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Minutes }} → 212.525 +``` diff --git a/docs/content/en/methods/duration/Nanoseconds.md b/docs/content/en/methods/duration/Nanoseconds.md new file mode 100644 index 000000000..fd1b9e496 --- /dev/null +++ b/docs/content/en/methods/duration/Nanoseconds.md @@ -0,0 +1,15 @@ +--- +title: Nanoseconds +description: Returns the time.Duration value as an integer nanosecond count. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int64 + signatures: [DURATION.Nanoseconds] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Nanoseconds }} → 12751500000000 +``` diff --git a/docs/content/en/methods/duration/Round.md b/docs/content/en/methods/duration/Round.md new file mode 100644 index 000000000..dfd06253f --- /dev/null +++ b/docs/content/en/methods/duration/Round.md @@ -0,0 +1,18 @@ +--- +title: Round +description: Returns the result of rounding DURATION1 to the nearest multiple of DURATION2. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: + signatures: [DURATION1.Round DURATION2] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} + +{{ $d.Round (time.ParseDuration "2h") }} → 4h0m0s +{{ $d.Round (time.ParseDuration "3m") }} → 3h33m0s +{{ $d.Round (time.ParseDuration "4s") }} → 3h32m32s +``` diff --git a/docs/content/en/methods/duration/Seconds.md b/docs/content/en/methods/duration/Seconds.md new file mode 100644 index 000000000..8b6d060b9 --- /dev/null +++ b/docs/content/en/methods/duration/Seconds.md @@ -0,0 +1,15 @@ +--- +title: Seconds +description: Returns the time.Duration value as a floating point number of seconds. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: float64 + signatures: [DURATION.Seconds] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} +{{ $d.Seconds }} → 12751.5 +``` diff --git a/docs/content/en/methods/duration/Truncate.md b/docs/content/en/methods/duration/Truncate.md new file mode 100644 index 000000000..5a785a77a --- /dev/null +++ b/docs/content/en/methods/duration/Truncate.md @@ -0,0 +1,18 @@ +--- +title: Truncate +description: Returns the result of rounding DURATION1 toward zero to a multiple of DURATION2. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Duration + signatures: [DURATION1.Truncate DURATION2] +--- + +```go-html-template +{{ $d = time.ParseDuration "3.5h2.5m1.5s" }} + +{{ $d.Truncate (time.ParseDuration "2h") }} → 2h0m0s +{{ $d.Truncate (time.ParseDuration "3m") }} → 3h30m0s +{{ $d.Truncate (time.ParseDuration "4s") }} → 3h32m28s +``` diff --git a/docs/content/en/methods/duration/_index.md b/docs/content/en/methods/duration/_index.md new file mode 100644 index 000000000..aeb113820 --- /dev/null +++ b/docs/content/en/methods/duration/_index.md @@ -0,0 +1,7 @@ +--- +title: Duration methods +linkTitle: Duration +description: Use these methods with time.Duration values. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/methods/menu-entry/Children.md b/docs/content/en/methods/menu-entry/Children.md new file mode 100644 index 000000000..ecad415fa --- /dev/null +++ b/docs/content/en/methods/menu-entry/Children.md @@ -0,0 +1,66 @@ +--- +title: Children +description: Returns a collection of child menu entries, if any, under the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: navigation.Menu + signatures: [MENUENTRY.Children] +--- + +Use the `Children` method when rendering a nested menu. + +With this site configuration: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Products' +pageRef = '/product' +weight = 10 + +[[menus.main]] +name = 'Product 1' +pageRef = '/products/product-1' +parent = 'Products' +weight = 1 + +[[menus.main]] +name = 'Product 2' +pageRef = '/products/product-2' +parent = 'Products' +weight = 2 +{{< /code-toggle >}} + +And this template: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li> + <a href="{{ .URL }}">{{ .Name }}</a> + {{ if .HasChildren }} + <ul> + {{ range .Children }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} + </ul> + {{ end }} + </li> + {{ end }} +</ul> +``` + +Hugo renders this HTML: + +```html +<ul> + <li> + <a href="/products/">Products</a> + <ul> + <li><a href="/products/product-1/">Product 1</a></li> + <li><a href="/products/product-2/">Product 2</a></li> + </ul> + </li> +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/HasChildren.md b/docs/content/en/methods/menu-entry/HasChildren.md new file mode 100644 index 000000000..03e6cb672 --- /dev/null +++ b/docs/content/en/methods/menu-entry/HasChildren.md @@ -0,0 +1,66 @@ +--- +title: HasChildren +description: Reports whether the given menu entry has child menu entries. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [MENUENTRY.HasChildren] +--- + +Use the `HasChildren` method when rendering a nested menu. + +With this site configuration: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Products' +pageRef = '/product' +weight = 10 + +[[menus.main]] +name = 'Product 1' +pageRef = '/products/product-1' +parent = 'Products' +weight = 1 + +[[menus.main]] +name = 'Product 2' +pageRef = '/products/product-2' +parent = 'Products' +weight = 2 +{{< /code-toggle >}} + +And this template: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li> + <a href="{{ .URL }}">{{ .Name }}</a> + {{ if .HasChildren }} + <ul> + {{ range .Children }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} + </ul> + {{ end }} + </li> + {{ end }} +</ul> +``` + +Hugo renders this HTML: + +```html +<ul> + <li> + <a href="/products/">Products</a> + <ul> + <li><a href="/products/product-1/">Product 1</a></li> + <li><a href="/products/product-2/">Product 2</a></li> + </ul> + </li> +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/Identifier.md b/docs/content/en/methods/menu-entry/Identifier.md new file mode 100644 index 000000000..809624459 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Identifier.md @@ -0,0 +1,41 @@ +--- +title: Identifier +description: Returns the `identifier` property of the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [MENUENTRY.Identifier] +--- + +The `Identifier` method returns the `identifier` property of the menu entry. If you define the menu entry [automatically], it returns the page's section. + +{{< code-toggle file=hugo >}} +[[menus.main]] +identifier = 'about' +name = 'About' +pageRef = '/about' +weight = 10 + +[[menus.main]] +identifier = 'contact' +name = 'Contact' +pageRef = '/contact' +weight = 20 +{{< /code-toggle >}} + +This example uses the `Identifier` method when querying the translation table on a multilingual site, falling back the `name` property if a matching key in the translation table does not exist: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ or (T .Identifier) .Name }}</a></li> + {{ end }} +</ul> +``` + +> [!note] +> In the menu definition above, note that the `identifier` property is only required when two or more menu entries have the same name, or when localizing the name using translation tables. + +[automatically]: /content-management/menus/#define-automatically diff --git a/docs/content/en/methods/menu-entry/KeyName.md b/docs/content/en/methods/menu-entry/KeyName.md new file mode 100644 index 000000000..d614a5a87 --- /dev/null +++ b/docs/content/en/methods/menu-entry/KeyName.md @@ -0,0 +1,39 @@ +--- +title: KeyName +description: Returns the `identifier` property of the given menu entry, falling back to its `name` property. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [MENUENTRY.KeyName] +--- + +In this menu definition, the second entry does not contain an `identifier`, so the `Identifier` method returns its `name` property instead: + +{{< code-toggle file=hugo >}} +[[menus.main]] +identifier = 'about' +name = 'About' +pageRef = '/about' +weight = 10 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +weight = 20 +{{< /code-toggle >}} + +This example uses the `KeyName` method when querying the translation table on a multilingual site, falling back the `name` property if a matching key in the translation table does not exist: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ or (T (.KeyName | lower)) .Name }}</a></li> + {{ end }} +</ul> +``` + +In the example above, we need to pass the value returned by `.KeyName` through the [`lower`] function because the keys in the translation table are lowercase. + +[`lower`]: /functions/strings/tolower/ diff --git a/docs/content/en/methods/menu-entry/Menu.md b/docs/content/en/methods/menu-entry/Menu.md new file mode 100644 index 000000000..074911eeb --- /dev/null +++ b/docs/content/en/methods/menu-entry/Menu.md @@ -0,0 +1,22 @@ +--- +title: Menu +description: Returns the identifier of the menu that contains the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [MENUENTRY.Menu] +--- + +```go-html-template +{{ range .Site.Menus.main }} + {{ .Menu }} → main +{{ end }} +``` + +Use this method with the [`IsMenuCurrent`] and [`HasMenuCurrent`] methods on a `Page` object to set "active" and "ancestor" classes on a rendered entry. See [this example]. + +[`HasMenuCurrent`]: /methods/page/hasmenucurrent/ +[`IsMenuCurrent`]: /methods/page/ismenucurrent/ +[this example]: /templates/menu/#example diff --git a/docs/content/en/methods/menu-entry/Name.md b/docs/content/en/methods/menu-entry/Name.md new file mode 100644 index 000000000..706d0f8c8 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Name.md @@ -0,0 +1,28 @@ +--- +title: Name +description: Returns the `name` property of the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [MENUENTRY.Name] +--- + +If you define the menu entry [automatically], the `Name` method returns the page's [`LinkTitle`], falling back to its [`Title`]. + +If you define the menu entry [in front matter] or [in site configuration], the `Name` method returns the `name` property of the given menu entry. If the `name` is not defined, and the menu entry resolves to a page, the `Name` returns the page [`LinkTitle`], falling back to its [`Title`]. + +[`LinkTitle`]: /methods/page/linktitle/ +[`Title`]: /methods/page/title/ +[automatically]: /content-management/menus/#define-automatically +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/#define-in-site-configuration + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/Page.md b/docs/content/en/methods/menu-entry/Page.md new file mode 100644 index 000000000..489ee7acc --- /dev/null +++ b/docs/content/en/methods/menu-entry/Page.md @@ -0,0 +1,53 @@ +--- +title: Page +description: Returns the Page object associated with the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [MENUENTRY.Page] +--- + +Regardless of how you [define menu entries], an entry associated with a page has access to its [methods]. + +In this menu definition, the first two entries are associated with a page, the last entry is not: + +{{< code-toggle file=hugo >}} +[[menus.main]] +pageRef = '/about' +weight = 10 + +[[menus.main]] +pageRef = '/contact' +weight = 20 + +[[menus.main]] +name = 'Hugo' +url = 'https://gohugo.io' +weight = 30 +{{< /code-toggle >}} + +In this example, if the menu entry is associated with a page, we use page's [`RelPermalink`] and [`LinkTitle`] when rendering the anchor element. + +If the entry is not associated with a page, we use its `url` and `name` properties. + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + {{ with .Page }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ else }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} + {{ end }} +</ul> +``` + +See the [menu templates] section for more information. + +[`LinkTitle`]: /methods/page/linktitle/ +[`RelPermalink`]: /methods/page/relpermalink/ +[define menu entries]: /content-management/menus/ +[menu templates]: /templates/menu/#page-references +[methods]: /methods/page/ diff --git a/docs/content/en/methods/menu-entry/PageRef.md b/docs/content/en/methods/menu-entry/PageRef.md new file mode 100644 index 000000000..979879b03 --- /dev/null +++ b/docs/content/en/methods/menu-entry/PageRef.md @@ -0,0 +1,109 @@ +--- +title: PageRef +description: Returns the `pageRef` property of the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [MENUENTRY.PageRef] +--- + +The use case for this method is rare. + +In almost also scenarios you should use the [`URL`] method instead. + +## Explanation + +If you specify a `pageRef` property when [defining a menu entry] in your site configuration, Hugo looks for a matching page when rendering the entry. + +If a matching page is found: + +- The [`URL`] method returns the page's relative permalink +- The [`Page`] method returns the corresponding `Page` object +- The [`HasMenuCurrent`] and [`IsMenuCurrent`] methods on a `Page` object return the expected values + +If a matching page is not found: + +- The [`URL`] method returns the entry's `url` property if set, else an empty string +- The [`Page`] method returns nil +- The [`HasMenuCurrent`] and [`IsMenuCurrent`] methods on a `Page` object return `false` + +> [!note] +> In almost also scenarios you should use the [`URL`] method instead. + +## Example + +This example is contrived. + +> [!note] +> In almost also scenarios you should use the [`URL`] method instead. + +Consider this content structure: + +```text +content/ +├── products.md +└── _index.md +``` + +And this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Products' +pageRef = '/products' +weight = 10 +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 20 +{{< /code-toggle >}} + +With this template code: + +```go-html-template {file="layouts/partials/menu.html"} +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +Hugo render this HTML: + +```html +<ul> + <li><a href="/products/">Products</a></li> + <li><a href="">Services</a></li> +</ul> +``` + +In the above note that the `href` attribute of the second `anchor` element is blank because Hugo was unable to find the "services" page. + +With this template code: + +```go-html-template {file="layouts/partials/menu.html"} +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ or .URL .PageRef }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this HTML: + +```html +<ul> + <li><a href="/products/">Products</a></li> + <li><a href="/services">Services</a></li> +</ul> +``` + +In the above note that Hugo populates the `href` attribute of the second `anchor` element with the `pageRef` property as defined in the site configuration because the template code falls back to the `PageRef` method. + +[`HasMenuCurrent`]: /methods/page/hasmenucurrent/ +[`IsMenuCurrent`]: /methods/page/ismenucurrent/ +[`Page`]: /methods/menu-entry/page/ +[`URL`]: /methods/menu-entry/url/ +[defining a menu entry]: /content-management/menus/#define-in-site-configuration diff --git a/docs/content/en/methods/menu-entry/Params.md b/docs/content/en/methods/menu-entry/Params.md new file mode 100644 index 000000000..20c4f7fc7 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Params.md @@ -0,0 +1,61 @@ +--- +title: Params +description: Returns the `params` property of the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: maps.Params + signatures: [MENUENTRY.Params] +--- + +When you define menu entries [in site configuration] or [in front matter], you can include a `params` key to attach additional information to the entry. For example: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'About' +pageRef = '/about' +weight = 10 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +weight = 20 + +[[menus.main]] +name = 'Hugo' +url = 'https://gohugo.io' +weight = 30 +[menus.main.params] + rel = 'external' +{{< /code-toggle >}} + +With this template: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li> + <a href="{{ .URL }}" {{ with .Params.rel }}rel="{{ . }}"{{ end }}> + {{ .Name }} + </a> + </li> + {{ end }} +</ul> +``` + +Hugo renders: + +```html +<ul> + <li><a href="/about/">About</a></li> + <li><a href="/contact/">Contact</a></li> + <li><a href="https://gohugo.io" rel="external">Hugo</a></li> +</ul> +``` + +See the [menu templates] section for more information. + +[menu templates]: /templates/menu/#menu-entry-parameters +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/ diff --git a/docs/content/en/methods/menu-entry/Parent.md b/docs/content/en/methods/menu-entry/Parent.md new file mode 100644 index 000000000..7c617527b --- /dev/null +++ b/docs/content/en/methods/menu-entry/Parent.md @@ -0,0 +1,50 @@ +--- +title: Parent +description: Returns the `parent` property of the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [MENUENTRY.Parent] +--- + +With this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Products' +pageRef = '/product' +weight = 10 + +[[menus.main]] +name = 'Product 1' +pageRef = '/products/product-1' +parent = 'Products' +weight = 1 + +[[menus.main]] +name = 'Product 2' +pageRef = '/products/product-2' +parent = 'Products' +weight = 2 +{{< /code-toggle >}} + +This template renders the nested menu, listing the `parent` property next each of the child entries: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li> + <a href="{{ .URL }}">{{ .Name }}</a> + {{ if .HasChildren }} + <ul> + {{ range .Children }} + <li><a href="{{ .URL }}">{{ .Name }}</a> ({{ .Parent }})</li> + {{ end }} + </ul> + {{ end }} + </li> + {{ end }} +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/Post.md b/docs/content/en/methods/menu-entry/Post.md new file mode 100644 index 000000000..2da8c38d8 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Post.md @@ -0,0 +1,12 @@ +--- +title: Post +description: Returns the `post` property of the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: [MENUENTRY.Post] +--- + +{{% include "/_common/menu-entries/pre-and-post.md" %}} diff --git a/docs/content/en/methods/menu-entry/Pre.md b/docs/content/en/methods/menu-entry/Pre.md new file mode 100644 index 000000000..19af243e7 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Pre.md @@ -0,0 +1,12 @@ +--- +title: Pre +description: Returns the `pre` property of the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: [MENUENTRY.Pre] +--- + +{{% include "/_common/menu-entries/pre-and-post.md" %}} diff --git a/docs/content/en/methods/menu-entry/Title.md b/docs/content/en/methods/menu-entry/Title.md new file mode 100644 index 000000000..526132d7c --- /dev/null +++ b/docs/content/en/methods/menu-entry/Title.md @@ -0,0 +1,22 @@ +--- +title: Title +description: Returns the `title` property of the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [MENUENTRY.Title] +--- + +The `Title` method returns the `title` property of the given menu entry. If the `title` is not defined, and the menu entry resolves to a page, the `Title` returns the page [`Title`]. + +[`Title`]: /methods/page/title/ + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}" title="{{ .Title }}>{{ .Name }}</a></li> + {{ end }} +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/URL.md b/docs/content/en/methods/menu-entry/URL.md new file mode 100644 index 000000000..e29a6f058 --- /dev/null +++ b/docs/content/en/methods/menu-entry/URL.md @@ -0,0 +1,22 @@ +--- +title: URL +description: Returns the relative permalink of the page associated with the given menu entry, else its `url` property. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [MENUENTRY.URL] +--- + +For menu entries associated with a page, the `URL` method returns the page's [`RelPermalink`], otherwise it returns the entry's `url` property. + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +[`RelPermalink`]: /methods/page/relpermalink/ diff --git a/docs/content/en/methods/menu-entry/Weight.md b/docs/content/en/methods/menu-entry/Weight.md new file mode 100644 index 000000000..b96e2cc87 --- /dev/null +++ b/docs/content/en/methods/menu-entry/Weight.md @@ -0,0 +1,31 @@ +--- +title: Weight +description: Returns the `weight` property of the given menu entry. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [MENUENTRY.Weight] +--- + +If you define the menu entry [automatically], the `Weight` method returns the page's [`Weight`]. + +If you define the menu entry [in front matter] or [in site configuration], the `Weight` method returns the `weight` property, falling back to the page's `Weight`. + +[`Weight`]: /methods/page/weight/ +[automatically]: /content-management/menus/#define-automatically +[in front matter]: /content-management/menus/#define-in-front-matter +[in site configuration]: /content-management/menus/#define-in-site-configuration + +In this contrived example, we limit the number of menu entries based on weight: + +```go-html-template +<ul> + {{ range .Site.Menus.main }} + {{ if le .Weight 42 }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} + {{ end }} +</ul> +``` diff --git a/docs/content/en/methods/menu-entry/_index.md b/docs/content/en/methods/menu-entry/_index.md new file mode 100644 index 000000000..129e9bcdc --- /dev/null +++ b/docs/content/en/methods/menu-entry/_index.md @@ -0,0 +1,7 @@ +--- +title: Menu entry methods +linkTitle: Menu entry +description: Use these methods in your menu templates. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/methods/menu/ByName.md b/docs/content/en/methods/menu/ByName.md new file mode 100644 index 000000000..d98a4aced --- /dev/null +++ b/docs/content/en/methods/menu/ByName.md @@ -0,0 +1,65 @@ +--- +title: ByName +description: Returns the given menu with its entries sorted by name. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: navigation.Menu + signatures: [MENU.ByName] +--- + +The `Sort` method returns the given menu with its entries sorted by `name`. + +Consider this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 10 + +[[menus.main]] +name = 'About' +pageRef = '/about' +weight = 20 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +weight = 30 +{{< /code-toggle >}} + +To sort the entries by `name`: + +```go-html-template +<ul> + {{ range .Site.Menus.main.ByName }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this to: + +```html +<ul> + <li><a href="/about/">About</a></li> + <li><a href="/contact">Contact</a></li> + <li><a href="/services/">Services</a></li> +</ul> +``` + +You can also sort menu entries using the [`sort`] function. For example, to sort by `name` in descending order: + +```go-html-template +<ul> + {{ range sort .Site.Menus.main "Name" "desc" }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +When using the sort function with menu entries, specify any of the following keys: `Identifier`, `Name`, `Parent`, `Post`, `Pre`, `Title`, `URL`, or `Weight`. + +[`sort`]: /functions/collections/sort/ diff --git a/docs/content/en/methods/menu/ByWeight.md b/docs/content/en/methods/menu/ByWeight.md new file mode 100644 index 000000000..013d37e13 --- /dev/null +++ b/docs/content/en/methods/menu/ByWeight.md @@ -0,0 +1,71 @@ +--- +title: ByWeight +description: Returns the given menu with its entries sorted by weight, then by name, then by identifier. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: navigation.Menu + signatures: [MENU.ByWeight] +--- + +The `ByWeight` method returns the given menu with its entries sorted by [`weight`](g), then by `name`, then by `identifier`. This is the default sort order. + +Consider this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +identifier = 'about' +name = 'About' +pageRef = '/about' +weight = 20 + +[[menus.main]] +identifier = 'services' +name = 'Services' +pageRef = '/services' +weight = 10 + +[[menus.main]] +identifier = 'contact' +name = 'Contact' +pageRef = '/contact' +weight = 30 +{{< /code-toggle >}} + +To sort the entries by `weight`, then by `name`, then by `identifier`: + +```go-html-template +<ul> + {{ range .Site.Menus.main.ByWeight }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this to: + +```html +<ul> + <li><a href="/services/">Services</a></li> + <li><a href="/about/">About</a></li> + <li><a href="/contact">Contact</a></li> +</ul> +``` + +> [!note] +> In the menu definition above, note that the `identifier` property is only required when two or more menu entries have the same name, or when localizing the name using translation tables. + +You can also sort menu entries using the [`sort`] function. For example, to sort by `weight` in descending order: + +```go-html-template +<ul> + {{ range sort .Site.Menus.main "Weight" "desc" }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +When using the sort function with menu entries, specify any of the following keys: `Identifier`, `Name`, `Parent`, `Post`, `Pre`, `Title`, `URL`, or `Weight`. + +[`sort`]: /functions/collections/sort/ diff --git a/docs/content/en/methods/menu/Limit.md b/docs/content/en/methods/menu/Limit.md new file mode 100644 index 000000000..005fef144 --- /dev/null +++ b/docs/content/en/methods/menu/Limit.md @@ -0,0 +1,50 @@ +--- +title: Limit +description: Returns the given menu, limited to the first N entries. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: navigation.Menu + signatures: [MENU.Limit N] +--- + +The `Limit` method returns the given menu, limited to the first N entries. + +Consider this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 10 + +[[menus.main]] +name = 'About' +pageRef = '/about' +weight = 20 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +weight = 30 +{{< /code-toggle >}} + +To sort the entries by name, and limit to the first 2 entries: + +```go-html-template +<ul> + {{ range .Site.Menus.main.ByName.Limit 2 }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this to: + +```html +<ul> + <li><a href="/about/">About</a></li> + <li><a href="/contact">Contact</a></li> +</ul> +``` diff --git a/docs/content/en/methods/menu/Reverse.md b/docs/content/en/methods/menu/Reverse.md new file mode 100644 index 000000000..1ee31aa51 --- /dev/null +++ b/docs/content/en/methods/menu/Reverse.md @@ -0,0 +1,51 @@ +--- +title: Reverse +description: Returns the given menu, reversing the sort order of its entries. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: navigation.Menu + signatures: [MENU.Reverse] +--- + +The `Reverse` method returns the given menu, reversing the sort order of its entries. + +Consider this menu definition: + +{{< code-toggle file=hugo >}} +[[menus.main]] +name = 'Services' +pageRef = '/services' +weight = 10 + +[[menus.main]] +name = 'About' +pageRef = '/about' +weight = 20 + +[[menus.main]] +name = 'Contact' +pageRef = '/contact' +weight = 30 +{{< /code-toggle >}} + +To sort the entries by name in descending order: + +```go-html-template +<ul> + {{ range .Site.Menus.main.ByName.Reverse }} + <li><a href="{{ .URL }}">{{ .Name }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this to: + +```html +<ul> + <li><a href="/services/">Services</a></li> + <li><a href="/contact">Contact</a></li> + <li><a href="/about/">About</a></li> +</ul> +``` diff --git a/docs/content/en/methods/menu/_index.md b/docs/content/en/methods/menu/_index.md new file mode 100644 index 000000000..41084fdba --- /dev/null +++ b/docs/content/en/methods/menu/_index.md @@ -0,0 +1,7 @@ +--- +title: Menu methods +linkTitle: Menu +description: Use these methods when ranging through menu entries. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/methods/page/Aliases.md b/docs/content/en/methods/page/Aliases.md new file mode 100644 index 000000000..775404bd3 --- /dev/null +++ b/docs/content/en/methods/page/Aliases.md @@ -0,0 +1,29 @@ +--- +title: Aliases +description: Returns the URL aliases as defined in front matter. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: '[]string' + signatures: [PAGE.Aliases] +--- + +The `Aliases` method on a `Page` object returns the URL [aliases] as defined in front matter. + +For example: + +{{< code-toggle file=content/about.md fm=true >}} +title = 'About' +aliases = ['/old-url','/really-old-url'] +{{< /code-toggle >}} + +To list the aliases: + +```go-html-template +{{ range .Aliases }} + {{ . }} +{{ end }} +``` + +[aliases]: /content-management/urls/#aliases diff --git a/docs/content/en/methods/page/AllTranslations.md b/docs/content/en/methods/page/AllTranslations.md new file mode 100644 index 000000000..62117b429 --- /dev/null +++ b/docs/content/en/methods/page/AllTranslations.md @@ -0,0 +1,88 @@ +--- +title: AllTranslations +description: Returns all translations of the given page, including the current language. +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 }} + <ul> + {{ range . }} + <li> + <a href="{{ .RelPermalink }}" hreflang="{{ .Language.LanguageCode }}">{{ .LinkTitle }} ({{ or .Language.LanguageName .Language.Lang }})</a> + </li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo will render this list on the "Book 1" page of each site: + +```html +<ul> + <li><a href="/books/book-1/" hreflang="en-US">Book 1 (English)</a></li> + <li><a href="/de/books/book-1/" hreflang="de-DE">Book 1 (Deutsch)</a></li> + <li><a href="/fr/books/book-1/" hreflang="fr-FR">Book 1 (Français)</a></li> +</ul> +``` + +On the "Book 2" page of the English and German sites, Hugo will render this: + +```html +<ul> + <li><a href="/books/book-1/" hreflang="en-US">Book 1 (English)</a></li> + <li><a href="/de/books/book-1/" hreflang="de-DE">Book 1 (Deutsch)</a></li> +</ul> +``` diff --git a/docs/content/en/methods/page/AlternativeOutputFormats.md b/docs/content/en/methods/page/AlternativeOutputFormats.md new file mode 100644 index 000000000..c4075d010 --- /dev/null +++ b/docs/content/en/methods/page/AlternativeOutputFormats.md @@ -0,0 +1,42 @@ +--- +title: AlternativeOutputFormats +description: Returns a slice of OutputFormat objects, excluding the current output format, each representing one of the output formats enabled for the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.OutputFormats + signatures: [PAGE.AlternativeOutputFormats] +--- + +{{% glossary-term "output format" %}} + +The `AlternativeOutputFormats` method on a `Page` object returns a slice of `OutputFormat` objects, excluding the current output format, each representing one of the output formats enabled for the given page. See [details](/configuration/output-formats/). + +## Methods + +{{% include "/_common/methods/page/output-format-methods.md" %}} + +## Example + +Generate a `link` element in the `<head>` of each page for each of the alternative output formats: + +```go-html-template +<head> + ... + {{ $title := printf "%s | %s" .Title site.Title }} + {{ if .IsHome }} + {{ $title = site.Title }} + {{ end }} + {{ range .AlternativeOutputFormats }} + {{ printf `<link rel=%q type=%q href=%q title=%q>` .Rel .MediaType.Type .Permalink $title | safeHTML }} + {{ end }} + ... +</head> +``` + +On the site's home page, Hugo renders this to: + +```html +<link rel="alternate" type="application/rss+xml" href="https://example.org/index.xml" title="ABC Widgets, Inc."> +``` diff --git a/docs/content/en/methods/page/Ancestors.md b/docs/content/en/methods/page/Ancestors.md new file mode 100644 index 000000000..d8275cf76 --- /dev/null +++ b/docs/content/en/methods/page/Ancestors.md @@ -0,0 +1,76 @@ +--- +title: Ancestors +description: Returns a collection of Page objects, one for each ancestor section of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGE.Ancestors] +--- + +With this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md <-- front matter: weight = 202311 +│ │ ├── auction-1.md +│ │ └── auction-2.md +│ ├── 2023-12/ +│ │ ├── _index.md <-- front matter: weight = 202312 +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md <-- front matter: weight = 30 +│ ├── bidding.md +│ └── payment.md +├── books/ +│ ├── _index.md <-- front matter: weight = 10 +│ ├── book-1.md +│ └── book-2.md +├── films/ +│ ├── _index.md <-- front matter: weight = 20 +│ ├── film-1.md +│ └── film-2.md +└── _index.md +``` + +And this template: + +```go-html-template +{{ range .Ancestors }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +{{ end }} +``` + +On the November 2023 auctions page, Hugo renders: + +```html +<a href="/auctions/2023-11/">Auctions in November 2023</a> +<a href="/auctions/">Auctions</a> +<a href="/">Home</a> +``` + +In the example above, notice that Hugo orders the ancestors from closest to furthest. This makes breadcrumb navigation simple: + +```go-html-template +<nav aria-label="breadcrumb" class="breadcrumb"> + <ol> + {{ range .Ancestors.Reverse }} + <li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + </li> + {{ end }} + <li class="active"> + <a aria-current="page" href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + </li> + </ol> +</nav> +``` + +With some CSS, the code above renders something like this, where each breadcrumb links to its page: + +```text +Home > Auctions > Auctions in November 2023 > Auction 1 +``` diff --git a/docs/content/en/methods/page/BundleType.md b/docs/content/en/methods/page/BundleType.md new file mode 100644 index 000000000..e919511da --- /dev/null +++ b/docs/content/en/methods/page/BundleType.md @@ -0,0 +1,33 @@ +--- +title: BundleType +description: Returns the bundle type of the given page, or an empty string if the page is not a page bundle. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.BundleType] +--- + +A page bundle is a directory that encapsulates both content and associated [resources](g). There are two types of page bundles: [leaf bundles](g) and [branch bundles](g). See [details](/content-management/page-bundles/). + +The `BundleType` method on a `Page` object returns `branch` for branch bundles, `leaf` for leaf bundles, and an empty string if the page is not a page bundle. + +```text +content/ +├── films/ +│ ├── film-1/ +│ │ ├── a.jpg +│ │ └── index.md <-- leaf bundle +│ ├── _index.md <-- branch bundle +│ ├── b.jpg +│ ├── film-2.md +│ └── film-3.md +└── _index.md <-- branch bundle +``` + +To get the value within a template: + +```go-html-template +{{ .BundleType }} +``` diff --git a/docs/content/en/methods/page/CodeOwners.md b/docs/content/en/methods/page/CodeOwners.md new file mode 100644 index 000000000..00afa7549 --- /dev/null +++ b/docs/content/en/methods/page/CodeOwners.md @@ -0,0 +1,65 @@ +--- +title: CodeOwners +description: Returns of slice of code owners for the given page, derived from the CODEOWNERS file in the root of the project directory. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: '[]string' + signatures: [PAGE.CodeOwners] +--- + +GitHub and GitLab support CODEOWNERS files. This file specifies the users responsible for developing and maintaining software and documentation. This definition can apply to the entire repository, specific directories, or to individual files. To learn more: + +- [GitHub CODEOWNERS documentation] +- [GitLab CODEOWNERS documentation] + +Use the `CodeOwners` method on a `Page` object to determine the code owners for the given page. + +[GitHub CODEOWNERS documentation]: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners +[GitLab CODEOWNERS documentation]: https://docs.gitlab.com/ee/user/project/code_owners.html + +To use the `CodeOwners` method you must enable access to your local Git repository: + +{{< code-toggle file=hugo >}} +enableGitInfo = true +{{< /code-toggle >}} + +Consider this project structure: + +```text +my-project/ +├── content/ +│ ├── books/ +│ │ └── les-miserables.md +│ └── films/ +│ └── the-hunchback-of-notre-dame.md +└── CODEOWNERS +``` + +And this CODEOWNERS file: + +```text +* @jdoe +/content/books/ @tjones +/content/films/ @mrichards @rsmith +``` + +The table below shows the slice of code owners returned for each file: + +Path|Code owners +:--|:-- +`books/les-miserables.md`|`[@tjones]` +`films/the-hunchback-of-notre-dame.md`|`[@mrichards @rsmith]` + +Render the code owners for each content page: + +```go-html-template +{{ range .CodeOwners }} + {{ . }} +{{ end }} +``` + +Combine this method with [`resources.GetRemote`] to retrieve names and avatars from your Git provider by querying their API. + +[`resources.GetRemote`]: /functions/resources/getremote/ diff --git a/docs/content/en/methods/page/Content.md b/docs/content/en/methods/page/Content.md new file mode 100644 index 000000000..21348ebe6 --- /dev/null +++ b/docs/content/en/methods/page/Content.md @@ -0,0 +1,16 @@ +--- +title: Content +description: Returns the rendered content of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: [PAGE.Content] +--- + +The `Content` method on a `Page` object renders Markdown and shortcodes to HTML. + +```go-html-template +{{ .Content }} +``` diff --git a/docs/content/en/methods/page/ContentWithoutSummary.md b/docs/content/en/methods/page/ContentWithoutSummary.md new file mode 100644 index 000000000..4923b1197 --- /dev/null +++ b/docs/content/en/methods/page/ContentWithoutSummary.md @@ -0,0 +1,22 @@ +--- +title: ContentWithoutSummary +description: Returns the rendered content of the given page, excluding the content summary. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: [PAGE.ContentWithoutSummary] +--- + +{{< new-in 0.134.0 />}} + +Applicable when using manual or automatic [content summaries], the `ContentWithoutSummary` method on a `Page` object renders Markdown and shortcodes to HTML, excluding the content summary from the result. + +[content summaries]: /content-management/summaries/#manual-summary + +```go-html-template +{{ .ContentWithoutSummary }} +``` + +The `ContentWithoutSummary` method returns the same as `Content` if you define the content summary in front matter. diff --git a/docs/content/en/methods/page/CurrentSection.md b/docs/content/en/methods/page/CurrentSection.md new file mode 100644 index 000000000..93457f13f --- /dev/null +++ b/docs/content/en/methods/page/CurrentSection.md @@ -0,0 +1,48 @@ +--- +title: CurrentSection +description: Returns the Page object of the section in which the given page resides. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [PAGE.CurrentSection] +--- + +{{% glossary-term section %}} + +> [!note] +> The current section of a [section page](g), [taxonomy page](g), [term page](g), or the home page, is itself. + +Consider this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md <-- current section: 2023-11 +│ │ ├── auction-1.md +│ │ └── auction-2.md <-- current section: 2023-11 +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md <-- current section: auctions +│ ├── bidding.md +│ └── payment.md <-- current section: auctions +├── books/ +│ ├── _index.md <-- current section: books +│ ├── book-1.md +│ └── book-2.md <-- current section: books +├── films/ +│ ├── _index.md <-- current section: films +│ ├── film-1.md +│ └── film-2.md <-- current section: films +└── _index.md <-- current section: home +``` + +To create a link to the current section page: + +```go-html-template +<a href="{{ .CurrentSection.RelPermalink }}">{{ .CurrentSection.LinkTitle }}</a> +``` diff --git a/docs/content/en/methods/page/Data.md b/docs/content/en/methods/page/Data.md new file mode 100644 index 000000000..ae0bdc57f --- /dev/null +++ b/docs/content/en/methods/page/Data.md @@ -0,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 list 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. + +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. + +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 --git a/docs/content/en/methods/page/Date.md b/docs/content/en/methods/page/Date.md new file mode 100644 index 000000000..b6c2042c2 --- /dev/null +++ b/docs/content/en/methods/page/Date.md @@ -0,0 +1,34 @@ +--- +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 --git a/docs/content/en/methods/page/Description.md b/docs/content/en/methods/page/Description.md new file mode 100644 index 000000000..5287aa699 --- /dev/null +++ b/docs/content/en/methods/page/Description.md @@ -0,0 +1,27 @@ +--- +title: Description +description: Returns the description of the given page as defined in front matter. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Description] +--- + +Conceptually different from a [content summary], a page description is typically used in metadata about the page. + +{{< code-toggle file=content/recipes/sushi.md fm=true >}} +title = 'How to make spicy tuna hand rolls' +description = 'Instructions for making spicy tuna hand rolls.' +{{< /code-toggle >}} + +```go-html-template {file="layouts/_default/baseof.html"} +<head> + ... + <meta name="description" content="{{ .Description }}"> + ... +</head> +``` + +[content summary]: /content-management/summaries/ diff --git a/docs/content/en/methods/page/Draft.md b/docs/content/en/methods/page/Draft.md new file mode 100644 index 000000000..482a370bf --- /dev/null +++ b/docs/content/en/methods/page/Draft.md @@ -0,0 +1,21 @@ +--- +title: Draft +description: Reports whether the given page is a draft as defined in front matter. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.Draft] +--- + +By default, Hugo does not publish draft pages when you build your site. To include draft pages when you build your site, use the `--buildDrafts` command line flag. + +{{< code-toggle file=content/posts/post-1.md fm=true >}} +title = 'Post 1' +draft = true +{{< /code-toggle >}} + +```go-html-template +{{ .Draft }} → true +``` diff --git a/docs/content/en/methods/page/Eq.md b/docs/content/en/methods/page/Eq.md new file mode 100644 index 000000000..4947a4bfa --- /dev/null +++ b/docs/content/en/methods/page/Eq.md @@ -0,0 +1,21 @@ +--- +title: Eq +description: Reports whether two Page objects are equal. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE1.Eq PAGE2] +--- + +In this contrived example from a single template, we list all pages in the current section except for the current page. + +```go-html-template +{{ $currentPage := . }} +{{ range .CurrentSection.Pages }} + {{ if not (.Eq $currentPage) }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + {{ end }} +{{ end }} +``` diff --git a/docs/content/en/methods/page/ExpiryDate.md b/docs/content/en/methods/page/ExpiryDate.md new file mode 100644 index 000000000..a72155c33 --- /dev/null +++ b/docs/content/en/methods/page/ExpiryDate.md @@ -0,0 +1,32 @@ +--- +title: ExpiryDate +description: Returns the expiry date of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [PAGE.ExpiryDate] +--- + +By default, Hugo excludes expired pages when building your site. To include expired pages, use the `--buildExpired` command line flag. + +Set the expiry date in front matter: + +{{< code-toggle file=content/news/article-1.md fm=true >}} +title = 'Article 1' +expiryDate = 2024-10-19T00:32:13-07:00 +{{< /code-toggle >}} + +The expiry 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 +{{ .ExpiryDate | time.Format ":date_medium" }} → Oct 19, 2024 +``` + +In the example above we explicitly set the expiry date in front matter. With Hugo's default configuration, the `ExpiryDate` method returns the front matter value. This behavior is configurable, allowing you to set fallback values if the expiry date is not defined in front matter. See [details]. + +[`time.Format`]: /functions/time/format/ +[details]: /configuration/front-matter/#dates +[time methods]: /methods/time/ +[time.Time]: https://pkg.go.dev/time#Time diff --git a/docs/content/en/methods/page/File.md b/docs/content/en/methods/page/File.md new file mode 100644 index 000000000..2af60a719 --- /dev/null +++ b/docs/content/en/methods/page/File.md @@ -0,0 +1,194 @@ +--- +title: File +description: For pages backed by a file, returns file information for the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: hugolib.fileInfo + signatures: [PAGE.File] +--- + +By default, not all pages are backed by a file, including top-level [section pages](g), [taxonomy pages](g), and [term pages](g). By definition, you cannot retrieve file information when the file does not exist. + +To back one of the pages above with a file, create an `_index.md` file in the corresponding directory. For example: + +```text +content/ +└── books/ + ├── _index.md <-- the top-slevel section page + ├── book-1.md + └── book-2.md +``` + +> [!note] +> Code defensively by verifying file existence as shown in the examples below. + +## Methods + +> [!note] +> The path separators (slash or backslash) in `Path`, `Dir`, and `Filename` depend on the operating system. + +### BaseFileName + +(`string`) The file name, excluding the extension. + +```go-html-template +{{ with .File }} + {{ .BaseFileName }} +{{ end }} +``` + +### ContentBaseName + +(`string`) If the page is a branch or leaf bundle, the name of the containing directory, else the `TranslationBaseName`. + +```go-html-template +{{ with .File }} + {{ .ContentBaseName }} +{{ end }} +``` + +### Dir + +(`string`) The file path, excluding the file name, relative to the `content` directory. + +```go-html-template +{{ with .File }} + {{ .Dir }} +{{ end }} +``` + +### Ext + +(`string`) The file extension. + +```go-html-template +{{ with .File }} + {{ .Ext }} +{{ end }} +``` + +### Filename + +(`string`) The absolute file path. + +```go-html-template +{{ with .File }} + {{ .Filename }} +{{ end }} +``` + +### IsContentAdapter + +{{< new-in 0.126.0 />}} + +(`bool`) Reports whether the file is a [content adapter]. + +```go-html-template +{{ with .File }} + {{ .IsContentAdapter }} +{{ end }} +``` + +### LogicalName + +(`string`) The file name. + +```go-html-template +{{ with .File }} + {{ .LogicalName }} +{{ end }} +``` + +### Path + +(`string`) The file path, relative to the `content` directory. + +```go-html-template +{{ with .File }} + {{ .Path }} +{{ end }} +``` + +### Section + +(`string`) The name of the top-level section in which the file resides. + +```go-html-template +{{ with .File }} + {{ .Section }} +{{ end }} +``` + +### TranslationBaseName + +(`string`) The file name, excluding the extension and language identifier. + +```go-html-template +{{ with .File }} + {{ .TranslationBaseName }} +{{ end }} +``` + +### UniqueID + +(`string`) The MD5 hash of `.File.Path`. + +```go-html-template +{{ with .File }} + {{ .UniqueID }} +{{ end }} +``` + +## Examples + +Consider this content structure in a multilingual project: + +```text +content/ +├── news/ +│ ├── b/ +│ │ ├── index.de.md <-- leaf bundle +│ │ └── index.en.md <-- leaf bundle +│ ├── a.de.md <-- regular content +│ ├── a.en.md <-- regular content +│ ├── _index.de.md <-- branch bundle +│ └── _index.en.md <-- branch bundle +├── _index.de.md +└── _index.en.md +``` + +With the English language site: + + |regular content|leaf bundle|branch bundle +:--|:--|:--|:-- +BaseFileName|a.en|index.en|_index.en +ContentBaseName|a|b|news +Dir|news/|news/b/|news/ +Ext|md|md|md +Filename|/home/user/...|/home/user/...|/home/user/... +IsContentAdapter|false|false|false +LogicalName|a.en.md|index.en.md|_index.en.md +Path|news/a.en.md|news/b/index.en.md|news/_index.en.md +Section|news|news|news +TranslationBaseName|a|index|_index +UniqueID|15be14b...|186868f...|7d9159d... + +## Defensive coding + +Some of the pages on a site may not be backed by a file. For example: + +- Top-level section pages +- Taxonomy pages +- Term pages + +Without a backing file, Hugo will throw an error if you attempt to access a `.File` property. To code defensively, first check for file existence: + +```go-html-template +{{ with .File }} + {{ .ContentBaseName }} +{{ end }} +``` + +[content adapter]: /content-management/content-adapters/ diff --git a/docs/content/en/methods/page/FirstSection.md b/docs/content/en/methods/page/FirstSection.md new file mode 100644 index 000000000..73ddd2d7b --- /dev/null +++ b/docs/content/en/methods/page/FirstSection.md @@ -0,0 +1,48 @@ +--- +title: FirstSection +description: Returns the Page object of the top-level section of which the given page is a descendant. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [PAGE.FirstSection] +--- + +{{% glossary-term section %}} + +> [!note] +> When called on the home page, the `FirstSection` method returns the `Page` object of the home page itself. + +Consider this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md <-- first section: auctions +│ │ ├── auction-1.md +│ │ └── auction-2.md <-- first section: auctions +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md <-- first section: auctions +│ ├── bidding.md +│ └── payment.md <-- first section: auctions +├── books/ +│ ├── _index.md <-- first section: books +│ ├── book-1.md +│ └── book-2.md <-- first section: books +├── films/ +│ ├── _index.md <-- first section: films +│ ├── film-1.md +│ └── film-2.md <-- first section: films +└── _index.md <-- first section: home +``` + +To link to the top-level section of which the current page is a descendant: + +```go-html-template +<a href="{{ .FirstSection.RelPermalink }}">{{ .FirstSection.LinkTitle }}</a> +``` diff --git a/docs/content/en/methods/page/Fragments.md b/docs/content/en/methods/page/Fragments.md new file mode 100644 index 000000000..2c0460def --- /dev/null +++ b/docs/content/en/methods/page/Fragments.md @@ -0,0 +1,109 @@ +--- +title: Fragments +description: Returns a data structure of the fragments in the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: tableofcontents.Fragments + signatures: [PAGE.Fragments] +--- + +In a URL, whether absolute or relative, the [fragment](g) links to an `id` attribute of an HTML element on the page. + +```text +/articles/article-1#section-2 +------------------- --------- + path fragment +``` + +Hugo assigns an `id` attribute to each Markdown [ATX] and [setext] heading within the page content. You can override the `id` with a [Markdown attribute](g) as needed. This creates the relationship between an entry in the [table of contents] (TOC) and a heading on the page. + +Use the `Fragments` method on a `Page` object to create a table of contents with the `Fragments.ToHTML` method, or by [walking](g) the `Fragments.Map` data structure. + +## Methods + +### Headings + +(`slice`) A slice of maps of all headings on the page, with first-level keys for each heading. Each map contains the following keys: `ID`, `Level`, `Title` and `Headings`. To inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump .Fragments.Headings }}</pre> +``` + +### HeadingsMap + +(`map`) A nested map of all headings on the page. Each map contains the following keys: `ID`, `Level`, `Title` and `Headings`. To inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump .Fragments.HeadingsMap }}</pre> +``` + +### Identifiers + +(`slice`) A slice containing the `id` attribute of each heading on the page. If so configured, will also contain the `id` attribute of each description term (i.e., `dt` element) on the page. + +See [configure Markup](/configuration/markup/#parserautodefinitiontermid). + +To inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump .Fragments.Identifiers }}</pre> +``` + +### Identifiers.Contains ID + +(`bool`) Reports whether one or more headings on the page has the given `id` attribute, useful for validating fragments within a link [render hook](g). + +```go-html-template +{{ .Fragments.Identifiers.Contains "section-2" }} → true +``` + +### Identifiers.Count ID + +(`int`) The number of headings on a page with the given `id` attribute, useful for detecting duplicates. + +```go-html-template +{{ .Fragments.Identifiers.Count "section-2" }} → 1 +``` + +### ToHTML + +(`template.HTML`) Returns a TOC as a nested list, either ordered or unordered, identical to the HTML returned by the [`TableOfContents`] method. This method take three arguments: the start level (`int`), the end level (`int`), and a boolean (`true` to return an ordered list, `false` to return an unordered list). + +Use this method when you want to control the start level, end level, or list type independently from the table of contents settings in your site configuration. + +```go-html-template +{{ $startLevel := 2 }} +{{ $endLevel := 3 }} +{{ $ordered := true }} +{{ .Fragments.ToHTML $startLevel $endLevel $ordered }} +``` + +Hugo renders this to: + +```html +<nav id="TableOfContents"> + <ol> + <li><a href="#section-1">Section 1</a> + <ol> + <li><a href="#section-11">Section 1.1</a></li> + <li><a href="#section-12">Section 1.2</a></li> + </ol> + </li> + <li><a href="#section-2">Section 2</a></li> + </ol> +</nav> +``` + +> [!note] +> It is safe to use the `Fragments` methods within a render hook, even for the current page. +> +> When using the `Fragments` methods within a shortcode, call the shortcode using [standard notation]. If you use [Markdown notation] the rendered shortcode is included in the creation of the fragments map, resulting in a circular loop. + +[`TableOfContents`]: /methods/page/tableofcontents/ +[ATX]: https://spec.commonmark.org/0.30/#atx-headings +[Markdown notation]: /content-management/shortcodes/#notation +[setext]: https://spec.commonmark.org/0.30/#setext-headings +[standard notation]: /content-management/shortcodes/#notation +[table of contents]: /methods/page/tableofcontents/ diff --git a/docs/content/en/methods/page/FuzzyWordCount.md b/docs/content/en/methods/page/FuzzyWordCount.md new file mode 100644 index 000000000..815a07402 --- /dev/null +++ b/docs/content/en/methods/page/FuzzyWordCount.md @@ -0,0 +1,18 @@ +--- +title: FuzzyWordCount +description: Returns the number of words in the content of the given page, rounded up to the nearest multiple of 100. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGE.FuzzyWordCount] +--- + +```go-html-template +{{ .FuzzyWordCount }} → 200 +``` + +To get the exact word count, use the [`WordCount`] method. + +[`WordCount`]: /methods/page/wordcount/ diff --git a/docs/content/en/methods/page/GetPage.md b/docs/content/en/methods/page/GetPage.md new file mode 100644 index 000000000..02f6888e0 --- /dev/null +++ b/docs/content/en/methods/page/GetPage.md @@ -0,0 +1,64 @@ +--- +title: GetPage +description: Returns a Page object from the given path. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [PAGE.GetPage PATH] +aliases: [/functions/getpage] +--- + +The `GetPage` method is also available on a `Site` object. See [details]. + +[details]: /methods/site/getpage/ + +When using the `GetPage` method on the `Page` object, specify a path relative to the current directory or relative to the `content` directory. + +If Hugo cannot resolve the path to a page, the method returns nil. If the path is ambiguous, Hugo throws an error and fails the build. + +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 +``` + +The examples below depict the result of rendering works/paintings/the-mona-lisa.md: + +```go-html-template {file="layouts/works/single.html"} +{{ with .GetPage "starry-night" }} + {{ .Title }} → Starry Night +{{ end }} + +{{ with .GetPage "./starry-night" }} + {{ .Title }} → Starry Night +{{ end }} + +{{ with .GetPage "../paintings/starry-night" }} + {{ .Title }} → Starry Night +{{ end }} + +{{ with .GetPage "/works/paintings/starry-night" }} + {{ .Title }} → Starry Night +{{ end }} + +{{ with .GetPage "../sculptures/david" }} + {{ .Title }} → David +{{ end }} + +{{ with .GetPage "/works/sculptures/david" }} + {{ .Title }} → David +{{ end }} +``` diff --git a/docs/content/en/methods/page/GetTerms.md b/docs/content/en/methods/page/GetTerms.md new file mode 100644 index 000000000..53b996fc5 --- /dev/null +++ b/docs/content/en/methods/page/GetTerms.md @@ -0,0 +1,41 @@ +--- +title: GetTerms +description: Returns a collection of term pages for terms defined on the given page in the given taxonomy, ordered according to the sequence in which they appear in front matter. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGE.GetTerms TAXONOMY] +--- + +Given this front matter: + +{{< code-toggle file=content/books/les-miserables.md fm=true >}} +title = 'Les Misérables' +tags = ['historical','classic','fiction'] +{{< /code-toggle >}} + +This template code: + +```go-html-template +{{ with .GetTerms "tags" }} + <p>Tags</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +Is rendered to: + +```html +<p>Tags</p> +<ul> + <li><a href="/tags/historical/">historical</a></li> + <li><a href="/tags/classic/">classic</a></li> + <li><a href="/tags/fiction/">fiction</a></li> +</ul> +``` diff --git a/docs/content/en/methods/page/GitInfo.md b/docs/content/en/methods/page/GitInfo.md new file mode 100644 index 000000000..5fde05b07 --- /dev/null +++ b/docs/content/en/methods/page/GitInfo.md @@ -0,0 +1,151 @@ +--- +title: GitInfo +description: Returns Git information related to the last commit of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: source.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. + +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 }} +``` + +## 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. + +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 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 configure a Cloudflare Pages site for deep cloning, run `git fetch --unshallow` before building the site. + +[^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). + +[^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). + +[details]: /configuration/front-matter/#dates +[gitmailmap]: https://git-scm.com/docs/gitmailmap +[site configuration]: /configuration/front-matter/ diff --git a/docs/content/en/methods/page/HasMenuCurrent.md b/docs/content/en/methods/page/HasMenuCurrent.md new file mode 100644 index 000000000..207882167 --- /dev/null +++ b/docs/content/en/methods/page/HasMenuCurrent.md @@ -0,0 +1,33 @@ +--- +title: HasMenuCurrent +description: Reports whether the given Page object matches the Page object associated with one of the child menu entries under the given menu entry in the given menu. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.HasMenuCurrent MENU MENUENTRY] +aliases: [/functions/hasmenucurrent] +--- + +If the `Page` object associated with the menu entry is a section, this method also returns `true` for any descendant of that section. + +```go-html-template +{{ $currentPage := . }} +{{ range site.Menus.main }} + {{ if $currentPage.IsMenuCurrent .Menu . }} + <a class="active" aria-current="page" href="{{ .URL }}">{{ .Name }}</a> + {{ else if $currentPage.HasMenuCurrent .Menu . }} + <a class="ancestor" aria-current="true" href="{{ .URL }}">{{ .Name }}</a> + {{ else }} + <a href="{{ .URL }}">{{ .Name }}</a> + {{ end }} +{{ end }} +``` + +See [menu templates] for a complete example. + +> [!note] +> When using this method you must either define the menu entry in front matter, or specify a `pageRef` property when defining the menu entry in your site configuration. + +[menu templates]: /templates/menu/#example diff --git a/docs/content/en/methods/page/HasShortcode.md b/docs/content/en/methods/page/HasShortcode.md new file mode 100644 index 000000000..616b6de09 --- /dev/null +++ b/docs/content/en/methods/page/HasShortcode.md @@ -0,0 +1,50 @@ +--- +title: HasShortcode +description: Reports whether the given shortcode is called by the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.HasShortcode NAME] +--- + +By example, let's use [Plotly] to render a chart: + +[Plotly]: https://plotly.com/javascript/ + +```text {file="content/example.md"} +{{</* plotly */>}} +{ + "data": [ + { + "x": ["giraffes", "orangutans", "monkeys"], + "y": [20, 14, 23], + "type": "bar" + } + ], +} +{{</* /plotly */>}} +``` + +The shortcode is simple: + +```go-html-template {file="layouts/shortcodes/plotly.html"} +{{ $id := printf "plotly-%02d" .Ordinal }} +<div id="{{ $id }}"></div> +<script> + Plotly.newPlot(document.getElementById({{ $id }}), {{ .Inner | safeJS }}); +</script> +``` + +Now we can selectively load the required JavaScript on pages that call the "plotly" shortcode: + +```go-html-template {file="layouts/_default/baseof.html"} +<head> + ... + {{ if .HasShortcode "plotly" }} + <script src="https://cdn.plot.ly/plotly-2.28.0.min.js"></script> + {{ end }} + ... +</head> +``` diff --git a/docs/content/en/methods/page/HeadingsFiltered.md b/docs/content/en/methods/page/HeadingsFiltered.md new file mode 100644 index 000000000..86c989d43 --- /dev/null +++ b/docs/content/en/methods/page/HeadingsFiltered.md @@ -0,0 +1,16 @@ +--- +title: HeadingsFiltered +description: Returns a slice of headings for each page related to the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: tableofcontents.Headings + signatures: [PAGE.HeadingsFiltered] +--- + +Use in conjunction with the [`Related`] method on a [`Pages`] object. See [details]. + +[`Pages`]: /methods/pages/ +[`Related`]: /methods/pages/related/ +[details]: /content-management/related-content/#index-content-headings diff --git a/docs/content/en/methods/page/InSection.md b/docs/content/en/methods/page/InSection.md new file mode 100644 index 000000000..adca82d86 --- /dev/null +++ b/docs/content/en/methods/page/InSection.md @@ -0,0 +1,91 @@ +--- +title: InSection +description: Reports whether the given page is in the given section. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.InSection SECTION] +--- + +{{% glossary-term section %}} + +The `InSection` method on a `Page` object reports whether the given page is in the given section. Note that the method returns `true` when comparing a page to a sibling. + +With this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md +│ │ ├── auction-1.md +│ │ └── auction-2.md +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md +│ ├── bidding.md +│ └── payment.md +└── _index.md +``` + +When rendering the "auction-1" page: + +```go-html-template +{{ with .Site.GetPage "/" }} + {{ $.InSection . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions" }} + {{ $.InSection . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11" }} + {{ $.InSection . }} → true +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11/auction-2" }} + {{ $.InSection . }} → true +{{ end }} +``` + +In the examples above we are coding defensively using the [`with`] statement, returning nothing if the page does not exist. By adding an [`else`] clause we can do some error reporting: + +```go-html-template +{{ $path := "/auctions/2023-11" }} +{{ with .Site.GetPage $path }} + {{ $.InSection . }} → true +{{ else }} + {{ errorf "Unable to find the section with path %s" $path }} +{{ end }} + ``` + +## Understanding context + +Inside of the `with` block, the [context](g) (the dot) is the section `Page` object, not the `Page` object passed into the template. If we were to use this syntax: + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ .InSection . }} → true +{{ end }} +``` + +The result would be wrong when rendering the "auction-1" page because we are comparing the section page to itself. + +> [!note] +> Use the `$` to get the context passed into the template. + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ $.InSection . }} → true +{{ end }} +``` + +> [!note] +> Gaining a thorough understanding of context is critical for anyone writing template code. + +[`else`]: /functions/go-template/else/ +[`with`]: /functions/go-template/with/ diff --git a/docs/content/en/methods/page/IsAncestor.md b/docs/content/en/methods/page/IsAncestor.md new file mode 100644 index 000000000..fe1b78454 --- /dev/null +++ b/docs/content/en/methods/page/IsAncestor.md @@ -0,0 +1,87 @@ +--- +title: IsAncestor +description: Reports whether PAGE1 is an ancestor of PAGE2. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE1.IsAncestor PAGE2] +--- + +With this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md +│ │ ├── auction-1.md +│ │ └── auction-2.md +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md +│ ├── bidding.md +│ └── payment.md +└── _index.md +``` + +When rendering the "auctions" page: + +```go-html-template +{{ with .Site.GetPage "/" }} + {{ $.IsAncestor . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions" }} + {{ $.IsAncestor . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11" }} + {{ $.IsAncestor . }} → true +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11/auction-2" }} + {{ $.IsAncestor . }} → true +{{ end }} +``` + +In the examples above we are coding defensively using the [`with`] statement, returning nothing if the page does not exist. By adding an [`else`] clause we can do some error reporting: + +```go-html-template +{{ $path := "/auctions/2023-11" }} +{{ with .Site.GetPage $path }} + {{ $.IsAncestor . }} → true +{{ else }} + {{ errorf "Unable to find the section with path %s" $path }} +{{ end }} + ``` + +## Understanding context + +Inside of the `with` block, the [context](g) (the dot) is the section `Page` object, not the `Page` object passed into the template. If we were to use this syntax: + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ .IsAncestor . }} → true +{{ end }} +``` + +The result would be wrong when rendering the "auction-1" page because we are comparing the section page to itself. + +> [!note] +> Use the `$` to get the context passed into the template. + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ $.IsAncestor . }} → true +{{ end }} +``` + +> [!note] +> Gaining a thorough understanding of context is critical for anyone writing template code. + +[`else`]: /functions/go-template/else/ +[`with`]: /functions/go-template/with/ diff --git a/docs/content/en/methods/page/IsDescendant.md b/docs/content/en/methods/page/IsDescendant.md new file mode 100644 index 000000000..6ee8d3c4f --- /dev/null +++ b/docs/content/en/methods/page/IsDescendant.md @@ -0,0 +1,87 @@ +--- +title: IsDescendant +description: Reports whether PAGE1 is a descendant of PAGE2. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE1.IsDescendant PAGE2] +--- + +With this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md +│ │ ├── auction-1.md +│ │ └── auction-2.md +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md +│ ├── bidding.md +│ └── payment.md +└── _index.md +``` + +When rendering the "auctions" page: + +```go-html-template +{{ with .Site.GetPage "/" }} + {{ $.IsDescendant . }} → true +{{ end }} + +{{ with .Site.GetPage "/auctions" }} + {{ $.IsDescendant . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11" }} + {{ $.IsDescendant . }} → false +{{ end }} + +{{ with .Site.GetPage "/auctions/2023-11/auction-2" }} + {{ $.IsDescendant . }} → false +{{ end }} +``` + +In the examples above we are coding defensively using the [`with`] statement, returning nothing if the page does not exist. By adding an [`else`] clause we can do some error reporting: + +```go-html-template +{{ $path := "/auctions/2023-11" }} +{{ with .Site.GetPage $path }} + {{ $.IsDescendant . }} → true +{{ else }} + {{ errorf "Unable to find the section with path %s" $path }} +{{ end }} + ``` + +## Understanding context + +Inside of the `with` block, the [context](g) (the dot) is the section `Page` object, not the `Page` object passed into the template. If we were to use this syntax: + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ .IsDescendant . }} → true +{{ end }} +``` + +The result would be wrong when rendering the "auction-1" page because we are comparing the section page to itself. + +> [!note] +> Use the `$` to get the context passed into the template. + +```go-html-template +{{ with .Site.GetPage "/auctions" }} + {{ $.IsDescendant . }} → true +{{ end }} +``` + +> [!note] +> Gaining a thorough understanding of context is critical for anyone writing template code. + +[`else`]: /functions/go-template/else/ +[`with`]: /functions/go-template/with/ diff --git a/docs/content/en/methods/page/IsHome.md b/docs/content/en/methods/page/IsHome.md new file mode 100644 index 000000000..66d8180b0 --- /dev/null +++ b/docs/content/en/methods/page/IsHome.md @@ -0,0 +1,26 @@ +--- +title: IsHome +description: Reports whether the given page is the home page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.IsHome] +--- + +The `IsHome` method on a `Page` object returns `true` if the [page kind](g) is `home`. + +```text +content/ +├── books/ +│ ├── book-1/ +│ │ └── index.md <-- kind = page +│ ├── book-2.md <-- kind = page +│ └── _index.md <-- kind = section +└── _index.md <-- kind = home +``` + +```go-html-template +{{ .IsHome }} +``` diff --git a/docs/content/en/methods/page/IsMenuCurrent.md b/docs/content/en/methods/page/IsMenuCurrent.md new file mode 100644 index 000000000..9bbacd018 --- /dev/null +++ b/docs/content/en/methods/page/IsMenuCurrent.md @@ -0,0 +1,31 @@ +--- +title: IsMenuCurrent +description: Reports whether the given Page object matches the Page object associated with the given menu entry in the given menu. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.IsMenuCurrent MENU MENUENTRY] +aliases: [/functions/ismenucurrent] +--- + +```go-html-template +{{ $currentPage := . }} +{{ range site.Menus.main }} + {{ if $currentPage.IsMenuCurrent .Menu . }} + <a class="active" aria-current="page" href="{{ .URL }}">{{ .Name }}</a> + {{ else if $currentPage.HasMenuCurrent .Menu . }} + <a class="ancestor" aria-current="true" href="{{ .URL }}">{{ .Name }}</a> + {{ else }} + <a href="{{ .URL }}">{{ .Name }}</a> + {{ end }} +{{ end }} +``` + +See [menu templates] for a complete example. + +> [!note] +> When using this method you must either define the menu entry in front matter, or specify a `pageRef` property when defining the menu entry in your site configuration. + +[menu templates]: /templates/menu/#example diff --git a/docs/content/en/methods/page/IsNode.md b/docs/content/en/methods/page/IsNode.md new file mode 100644 index 000000000..194a2cac8 --- /dev/null +++ b/docs/content/en/methods/page/IsNode.md @@ -0,0 +1,32 @@ +--- +title: IsNode +description: Reports whether the given page is a node. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.IsNode] +--- + +The `IsNode` method on a `Page` object returns `true` if the [page kind](g) is `home`, `section`, `taxonomy`, or `term`. + +It returns `false` is the page kind is `page`. + +```text +content/ +├── books/ +│ ├── book-1/ +│ │ └── index.md <-- kind = page, node = false +│ ├── book-2.md <-- kind = page, node = false +│ └── _index.md <-- kind = section, node = true +├── tags/ +│ ├── fiction/ +│ │ └── _index.md <-- kind = term, node = true +│ └── _index.md <-- kind = taxonomy, node = true +└── _index.md <-- kind = home, node = true +``` + +```go-html-template +{{ .IsNode }} +``` diff --git a/docs/content/en/methods/page/IsPage.md b/docs/content/en/methods/page/IsPage.md new file mode 100644 index 000000000..910a3a7e1 --- /dev/null +++ b/docs/content/en/methods/page/IsPage.md @@ -0,0 +1,26 @@ +--- +title: IsPage +description: Reports whether the given page is a regular page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.IsPage] +--- + +The `IsPage` method on a `Page` object returns `true` if the [page kind](g) is `page`. + +```text +content/ +├── books/ +│ ├── book-1/ +│ │ └── index.md <-- kind = page +│ ├── book-2.md <-- kind = page +│ └── _index.md <-- kind = section +└── _index.md <-- kind = home +``` + +```go-html-template +{{ .IsPage }} +``` diff --git a/docs/content/en/methods/page/IsSection.md b/docs/content/en/methods/page/IsSection.md new file mode 100644 index 000000000..7a04fbd8f --- /dev/null +++ b/docs/content/en/methods/page/IsSection.md @@ -0,0 +1,26 @@ +--- +title: IsSection +description: Reports whether the given page is a section page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.IsSection] +--- + +The `IsSection` method on a `Page` object returns `true` if the [page kind](g) is `section`. + +```text +content/ +├── books/ +│ ├── book-1/ +│ │ └── index.md <-- kind = page +│ ├── book-2.md <-- kind = page +│ └── _index.md <-- kind = section +└── _index.md <-- kind = home +``` + +```go-html-template +{{ .IsSection }} +``` diff --git a/docs/content/en/methods/page/IsTranslated.md b/docs/content/en/methods/page/IsTranslated.md new file mode 100644 index 000000000..2cdf911ac --- /dev/null +++ b/docs/content/en/methods/page/IsTranslated.md @@ -0,0 +1,56 @@ +--- +title: IsTranslated +description: Reports whether the given page has one or more translations. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.IsTranslated] +--- + +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 +{{< /code-toggle >}} + +And this content: + +```text +content/ +├── de/ +│ ├── books/ +│ │ └── book-1.md +│ └── _index.md +├── en/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +└── _index.md +``` + +When rendering `content/en/books/book-1.md`: + +```go-html-template +{{ .IsTranslated }} → true +``` + +When rendering `content/en/books/book-2.md`: + +```go-html-template +{{ .IsTranslated }} → false +``` diff --git a/docs/content/en/methods/page/Keywords.md b/docs/content/en/methods/page/Keywords.md new file mode 100644 index 000000000..7c940984e --- /dev/null +++ b/docs/content/en/methods/page/Keywords.md @@ -0,0 +1,46 @@ +--- +title: Keywords +description: Returns a slice of keywords as defined in front matter. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: '[]string' + signatures: [PAGE.Keywords] +--- + +By default, Hugo evaluates the keywords when creating collections of [related content]. + +[related content]: /content-management/related-content/ + +{{< code-toggle file=content/recipes/sushi.md fm=true >}} +title = 'How to make spicy tuna hand rolls' +keywords = ['tuna','sriracha','nori','rice'] +{{< /code-toggle >}} + +To list the keywords within a template: + +```go-html-template +{{ range .Keywords }} + {{ . }} +{{ end }} +``` + +Or use the [delimit] function: + +```go-html-template +{{ delimit .Keywords ", " ", and " }} → tuna, sriracha, nori, and rice +``` + +[delimit]: /functions/collections/delimit/ + +Keywords are also a useful [taxonomy]: + +{{< code-toggle file=hugo >}} +[taxonomies] +tag = 'tags' +keyword = 'keywords' +category = 'categories' +{{< /code-toggle >}} + +[taxonomy]: /content-management/taxonomies/ diff --git a/docs/content/en/methods/page/Kind.md b/docs/content/en/methods/page/Kind.md new file mode 100644 index 000000000..a01877e8c --- /dev/null +++ b/docs/content/en/methods/page/Kind.md @@ -0,0 +1,32 @@ +--- +title: Kind +description: Returns the kind of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Kind] +--- + +The [page kind](g) is one of `home`, `page`, `section`, `taxonomy`, or `term`. + +```text +content/ +├── books/ +│ ├── book-1/ +│ │ └── index.md <-- kind = page +│ ├── book-2.md <-- kind = page +│ └── _index.md <-- kind = section +├── tags/ +│ ├── fiction/ +│ │ └── _index.md <-- kind = term +│ └── _index.md <-- kind = taxonomy +└── _index.md <-- kind = home +``` + +To get the value within a template: + +```go-html-template +{{ .Kind }} +``` diff --git a/docs/content/en/methods/page/Language.md b/docs/content/en/methods/page/Language.md new file mode 100644 index 000000000..9fd604df3 --- /dev/null +++ b/docs/content/en/methods/page/Language.md @@ -0,0 +1,69 @@ +--- +title: Language +description: Returns the language object for the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: langs.Language + signatures: [PAGE.Language] +--- + +The `Language` method on a `Page` object returns the language object for the given page. The language object points to the language definition in the site configuration. + +You can also use the `Language` method on a `Site` object. See [details]. + +## Methods + +The examples below assume the following in your site configuration: + +{{< code-toggle file=hugo >}} +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +weight = 2 +{{< /code-toggle >}} + +### Lang + +(`string`) The language tag as defined by [RFC 5646]. + +```go-html-template +{{ .Language.Lang }} → de +``` + +### LanguageCode + +(`string`) The language code from the site configuration. Falls back to `Lang` if not defined. + +```go-html-template +{{ .Language.LanguageCode }} → de-DE +``` + +### LanguageDirection + +(`string`) The language direction from the site configuration, either `ltr` or `rtl`. + +```go-html-template +{{ .Language.LanguageDirection }} → ltr +``` + +### LanguageName + +(`string`) The language name from the site configuration. + +```go-html-template +{{ .Language.LanguageName }} → Deutsch +``` + +### Weight + +(`int`) The language weight from the site configuration which determines its order in the slice of languages returned by the `Languages` method on a `Site` object. + +```go-html-template +{{ .Language.Weight }} → 2 +``` + +[details]: /methods/site/language/ +[RFC 5646]: https://datatracker.ietf.org/doc/html/rfc5646 diff --git a/docs/content/en/methods/page/Lastmod.md b/docs/content/en/methods/page/Lastmod.md new file mode 100644 index 000000000..643eddc5e --- /dev/null +++ b/docs/content/en/methods/page/Lastmod.md @@ -0,0 +1,36 @@ +--- +title: Lastmod +description: Returns the last modification date of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [PAGE.Lastmod] +--- + +Set the last modification date in front matter: + +{{< code-toggle file=content/news/article-1.md fm=true >}} +title = 'Article 1' +lastmod = 2023-10-19T00:40:04-07:00 +{{< /code-toggle >}} + +The last modification 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 +{{ .Lastmod | time.Format ":date_medium" }} → Oct 19, 2023 +``` + +In the example above we explicitly set the last modification date in front matter. With Hugo's default configuration, the `Lastmod` method returns the front matter value. This behavior is configurable, allowing you to: + +- Set the last modification date to the Author Date of the last Git commit for that file. See [`GitInfo`] for details. +- Set fallback values if the last modification date is not defined in front matter. + +Learn more about [date configuration]. + +[`gitinfo`]: /methods/page/gitinfo/ +[`time.format`]: /functions/time/format/ +[date configuration]: /configuration/front-matter/#dates +[time methods]: /methods/time/ +[time.time]: https://pkg.go.dev/time#Time diff --git a/docs/content/en/methods/page/Layout.md b/docs/content/en/methods/page/Layout.md new file mode 100644 index 000000000..f9aa5b6ab --- /dev/null +++ b/docs/content/en/methods/page/Layout.md @@ -0,0 +1,39 @@ +--- +title: Layout +description: Returns the layout for the given page as defined in front matter. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Layout] +--- + +Specify the `layout` field in front matter to target a particular template. See [details]. + +[details]: /templates/lookup-order/#target-a-template + +{{< code-toggle file=content/contact.md fm=true >}} +title = 'Contact' +layout = 'contact' +{{< /code-toggle >}} + +Hugo will render the page using contact.html. + +```text +layouts/ +└── _default/ + ├── baseof.html + ├── contact.html + ├── home.html + ├── list.html + └── single.html +``` + +Although rarely used within a template, you can access the value with: + +```go-html-template +{{ .Layout }} +``` + +The `Layout` method returns an empty string if the `layout` field in front matter is not defined. diff --git a/docs/content/en/methods/page/Len.md b/docs/content/en/methods/page/Len.md new file mode 100644 index 000000000..010da88d1 --- /dev/null +++ b/docs/content/en/methods/page/Len.md @@ -0,0 +1,14 @@ +--- +title: Len +description: Returns the length, in bytes, of the rendered content of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGE.Len] +--- + +```go-html-template +{{ .Len }} → 42 +``` diff --git a/docs/content/en/methods/page/LinkTitle.md b/docs/content/en/methods/page/LinkTitle.md new file mode 100644 index 000000000..fcfd5318d --- /dev/null +++ b/docs/content/en/methods/page/LinkTitle.md @@ -0,0 +1,29 @@ +--- +title: LinkTitle +description: Returns the link title of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.LinkTitle] +--- + +The `LinkTitle` method returns the `linkTitle` field as defined in front matter, falling back to the value returned by the [`Title`] method. + +[`Title`]: /methods/page/title/ + +{{< code-toggle file=content/articles/healthy-desserts.md fm=true >}} +title = 'Seventeen delightful recipes for healthy desserts' +linkTitle = 'Dessert recipes' +{{< /code-toggle >}} + +```go-html-template +{{ .LinkTitle }} → Dessert recipes +``` + +As demonstrated above, defining a link title in front matter is advantageous when the page title is long. Use it when generating anchor elements in your templates: + +```go-html-template +<a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +``` diff --git a/docs/content/en/methods/page/Next.md b/docs/content/en/methods/page/Next.md new file mode 100644 index 000000000..996603083 --- /dev/null +++ b/docs/content/en/methods/page/Next.md @@ -0,0 +1,12 @@ +--- +title: Next +description: Returns the next page in a site's collection of regular pages, relative to the current page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [PAGE.Next] +--- + +{{% include "/_common/methods/page/next-and-prev.md" %}} diff --git a/docs/content/en/methods/page/NextInSection.md b/docs/content/en/methods/page/NextInSection.md new file mode 100644 index 000000000..eb02c9492 --- /dev/null +++ b/docs/content/en/methods/page/NextInSection.md @@ -0,0 +1,12 @@ +--- +title: NextInSection +description: Returns the next regular page in a section, relative to the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [PAGE.NextInSection] +--- + +{{% include "/_common/methods/page/nextinsection-and-previnsection.md" %}} diff --git a/docs/content/en/methods/page/OutputFormats.md b/docs/content/en/methods/page/OutputFormats.md new file mode 100644 index 000000000..0e648efaa --- /dev/null +++ b/docs/content/en/methods/page/OutputFormats.md @@ -0,0 +1,38 @@ +--- +title: OutputFormats +description: Returns a slice of OutputFormat objects, each representing one of the output formats enabled for the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: '[]OutputFormat' + signatures: [PAGE.OutputFormats] +--- + +{{% glossary-term "output format" %}} + +The `OutputFormats` method on a `Page` object returns a slice of `OutputFormat` objects, each representing one of the output formats enabled for the given page. See [details](/configuration/output-formats/). + +## Methods + +{{% include "/_common/methods/page/output-format-methods.md" %}} + +## Example + +To link to the RSS feed for the current page: + +```go-html-template +{{ with .OutputFormats.Get "rss" }} + <a href="{{ .RelPermalink }}">RSS Feed</a> +{{ end }} +``` + +On the site's home page, Hugo renders this to: + +```html +<a href="/index.xml">RSS Feed</a> +``` + +Please see the [link to output formats] section to understand the importance of the construct above. + +[link to output formats]: /configuration/output-formats/#link-to-output-formats diff --git a/docs/content/en/methods/page/Page.md b/docs/content/en/methods/page/Page.md new file mode 100644 index 000000000..7c7728b2f --- /dev/null +++ b/docs/content/en/methods/page/Page.md @@ -0,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. + +```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`. + +```go-html-template {file="layouts/_default/single.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. + +```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`. + +> [!note] +> And yes, that means you can do `.Page.Page.Page.Page.Title` too. +> +> But don't. diff --git a/docs/content/en/methods/page/Pages.md b/docs/content/en/methods/page/Pages.md new file mode 100644 index 000000000..ba43c36a8 --- /dev/null +++ b/docs/content/en/methods/page/Pages.md @@ -0,0 +1,82 @@ +--- +title: Pages +description: Returns a collection of regular pages within the current section, and section pages of immediate descendant sections. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGE.Pages] +--- + +The `Pages` method on a `Page` object is available to these [page kinds](g): `home`, `section`, `taxonomy`, and `term`. The templates for these page kinds receive a page [collection](g) in [context](g), in the [default sort order](g). + +Range through the page collection in your template: + +```go-html-template +{{ range .Pages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +Consider this content structure: + +```text +content/ +├── lessons/ +│ ├── lesson-1/ +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── lesson-2/ +│ │ ├── resources/ +│ │ │ ├── task-list.md +│ │ │ └── worksheet.md +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── _index.md +│ ├── grading-policy.md +│ └── lesson-plan.md +├── _index.md +├── contact.md +└── legal.md +``` + +When rendering the home page, the `Pages` method returns: + + contact.md + legal.md + lessons/_index.md + +When rendering the lessons page, the `Pages` method returns: + + lessons/grading-policy.md + lessons/lesson-plan.md + lessons/lesson-1/_index.md + lessons/lesson-2/_index.md + +When rendering lesson-1, the `Pages` method returns: + + lessons/lesson-1/part-1.md + lessons/lesson-1/part-2.md + +When rendering lesson-2, the `Pages` method returns: + + lessons/lesson-2/part-1.md + lessons/lesson-2/part-2.md + lessons/lesson-2/resources/task-list.md + lessons/lesson-2/resources/worksheet.md + +In the last example, the collection includes pages in the resources subdirectory. That directory is not a [section](g)---it does not contain an `_index.md` file. Its contents are part of the lesson-2 section. + +> [!note] +> When used with a `Site` object, the `Pages` method recursively returns all pages within the site. See [details]. + +```go-html-template +{{ range .Site.Pages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +[details]: /methods/site/pages/ diff --git a/docs/content/en/methods/page/Paginate.md b/docs/content/en/methods/page/Paginate.md new file mode 100644 index 000000000..0b699d6b2 --- /dev/null +++ b/docs/content/en/methods/page/Paginate.md @@ -0,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]. + +```go-html-template {file="layouts/_default/list.html"} +{{ $pages := where .Site.RegularPages "Section" "articles" }} +{{ $pages = $pages.ByTitle }} +{{ range (.Paginate $pages 7).Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +{{ template "_internal/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 +[site configuration]: /configuration/pagination/ +[taxonomy templates]: /templates/types/#taxonomy +[term templates]: /templates/types/#term diff --git a/docs/content/en/methods/page/Paginator.md b/docs/content/en/methods/page/Paginator.md new file mode 100644 index 000000000..bff7ea90c --- /dev/null +++ b/docs/content/en/methods/page/Paginator.md @@ -0,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. + +```go-html-template {file="layouts/_default/list.html"} +{{ range .Paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +{{ template "_internal/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 +[site configuration]: /configuration/pagination/ +[taxonomy templates]: /templates/types/#taxonomy +[term templates]: /templates/types/#term +[`Paginate`]: /methods/page/paginate/ diff --git a/docs/content/en/methods/page/Param.md b/docs/content/en/methods/page/Param.md new file mode 100644 index 000000000..b07c1cd92 --- /dev/null +++ b/docs/content/en/methods/page/Param.md @@ -0,0 +1,48 @@ +--- +title: Param +description: Returns a page parameter with the given key, falling back to a site parameter if present. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: any + signatures: [PAGE.Param KEY] +aliases: [/functions/param] +--- + +The `Param` method on a `Page` object looks for the given `KEY` in page parameters, and returns the corresponding value. If it cannot find the `KEY` in page parameters, it looks for the `KEY` in site parameters. If it cannot find the `KEY` in either location, the `Param` method returns `nil`. + +Site and theme developers commonly set parameters at the site level, allowing content authors to override those parameters at the page level. + +For example, to show a table of contents on every page, but allow authors to hide the table of contents as needed: + +Configuration: + +{{< code-toggle file=hugo >}} +[params] +display_toc = true +{{< /code-toggle >}} + +Content: + +{{< code-toggle file=content/example.md fm=true >}} +title = 'Example' +date = 2023-01-01 +draft = false +[params] +display_toc = false +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ if .Param "display_toc" }} + {{ .TableOfContents }} +{{ end }} +``` + +The `Param` method returns the value associated with the given `KEY`, regardless of whether the value is truthy or falsy. If you need to ignore falsy values, use this construct instead: + +```go-html-template +{{ or .Params.foo site.Params.foo }} +``` diff --git a/docs/content/en/methods/page/Params.md b/docs/content/en/methods/page/Params.md new file mode 100644 index 000000000..eeb253437 --- /dev/null +++ b/docs/content/en/methods/page/Params.md @@ -0,0 +1,42 @@ +--- +title: Params +description: Returns a map of custom parameters as defined in the front matter of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: maps.Params + signatures: [PAGE.Params] +--- + +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 +``` + +[`index`]: /functions/collections/indexfunction/ +[front matter fields]: /content-management/front-matter/#fields diff --git a/docs/content/en/methods/page/Parent.md b/docs/content/en/methods/page/Parent.md new file mode 100644 index 000000000..0946a7993 --- /dev/null +++ b/docs/content/en/methods/page/Parent.md @@ -0,0 +1,52 @@ +--- +title: Parent +description: Returns the Page object of the parent section of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [PAGE.Parent] +--- + +{{% glossary-term section %}} + +> [!note] +> The parent section of a regular page is the [current section]. + +Consider this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md <-- parent: auctions +│ │ ├── auction-1.md +│ │ └── auction-2.md <-- parent: 2023-11 +│ ├── 2023-12/ +│ │ ├── _index.md +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md <-- parent: home +│ ├── bidding.md +│ └── payment.md <-- parent: auctions +├── books/ +│ ├── _index.md <-- parent: home +│ ├── book-1.md +│ └── book-2.md <-- parent: books +├── films/ +│ ├── _index.md <-- parent: home +│ ├── film-1.md +│ └── film-2.md <-- parent: films +└── _index.md <-- parent: nil +``` + +In the example above, note the parent section of the home page is nil. Code defensively by verifying existence of the parent section before calling methods on its `Page` object. To create a link to the parent section page of the current page: + +```go-html-template +{{ with .Parent }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +{{ end }} +``` + +[current section]: /methods/page/currentsection/ diff --git a/docs/content/en/methods/page/Path.md b/docs/content/en/methods/page/Path.md new file mode 100644 index 000000000..db4e7d629 --- /dev/null +++ b/docs/content/en/methods/page/Path.md @@ -0,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`]||| + +> [!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 --git a/docs/content/en/methods/page/Permalink.md b/docs/content/en/methods/page/Permalink.md new file mode 100644 index 000000000..cc74f3342 --- /dev/null +++ b/docs/content/en/methods/page/Permalink.md @@ -0,0 +1,24 @@ +--- +title: Permalink +description: Returns the permalink of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Permalink] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +title = 'Documentation' +baseURL = 'https://example.org/docs/' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ $page := .Site.GetPage "/about" }} +{{ $page.Permalink }} → https://example.org/docs/about/ +``` diff --git a/docs/content/en/methods/page/Plain.md b/docs/content/en/methods/page/Plain.md new file mode 100644 index 000000000..65d11166e --- /dev/null +++ b/docs/content/en/methods/page/Plain.md @@ -0,0 +1,23 @@ +--- +title: Plain +description: Returns the rendered content of the given page, removing all HTML tags. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Plain] +--- + +The `Plain` method on a `Page` object renders Markdown and [shortcodes](g) to HTML, then strips the HTML [tags]. It does not strip HTML [entities]. + +To prevent Go's [html/template] package from escaping HTML entities, pass the result through the [`htmlUnescape`] function. + +```go-html-template +{{ .Plain | htmlUnescape }} +``` + +[html/template]: https://pkg.go.dev/html/template +[entities]: https://developer.mozilla.org/en-US/docs/Glossary/Entity +[tags]: https://developer.mozilla.org/en-US/docs/Glossary/Tag +[`htmlUnescape`]: /functions/transform/htmlunescape/ diff --git a/docs/content/en/methods/page/PlainWords.md b/docs/content/en/methods/page/PlainWords.md new file mode 100644 index 000000000..5749a21f9 --- /dev/null +++ b/docs/content/en/methods/page/PlainWords.md @@ -0,0 +1,31 @@ +--- +title: PlainWords +description: Calls the Plain method, splits the result into a slice of words, and returns the slice. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: '[]string' + signatures: [PAGE.PlainWords] +--- + +The `PlainWords` method on a `Page` object calls the [`Plain`] method, then uses Go's [`strings.Fields`] function to split the result into words. + +> [!note] +> `Fields` splits the string `s` around each instance of one or more consecutive whitespace characters, as defined by [`unicode.IsSpace`], returning a slice of substrings of `s` or an empty slice if `s` contains only whitespace. + +As a result, elements within the slice may contain leading or trailing punctuation. + +```go-html-template +{{ .PlainWords }} +``` + +To determine the approximate number of unique words on a page: + +```go-html-template +{{ .PlainWords | uniq }} → 42 +``` + +[`Plain`]: /methods/page/plain/ +[`strings.Fields`]: https://pkg.go.dev/strings#Fields +[`unicode.IsSpace`]: https://pkg.go.dev/unicode#IsSpace diff --git a/docs/content/en/methods/page/Prev.md b/docs/content/en/methods/page/Prev.md new file mode 100644 index 000000000..5a6e2162d --- /dev/null +++ b/docs/content/en/methods/page/Prev.md @@ -0,0 +1,12 @@ +--- +title: Prev +description: Returns the previous page in a site's collection of regular pages, relative to the current page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [PAGE.Prev] +--- + +{{% include "/_common/methods/page/next-and-prev.md" %}} diff --git a/docs/content/en/methods/page/PrevInSection.md b/docs/content/en/methods/page/PrevInSection.md new file mode 100644 index 000000000..14d3ca082 --- /dev/null +++ b/docs/content/en/methods/page/PrevInSection.md @@ -0,0 +1,12 @@ +--- +title: PrevInSection +description: Returns the previous regular page in a section, relative to the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [PAGE.PrevInSection] +--- + +{{% include "/_common/methods/page/nextinsection-and-previnsection.md" %}} diff --git a/docs/content/en/methods/page/PublishDate.md b/docs/content/en/methods/page/PublishDate.md new file mode 100644 index 000000000..7500a08aa --- /dev/null +++ b/docs/content/en/methods/page/PublishDate.md @@ -0,0 +1,32 @@ +--- +title: PublishDate +description: Returns the publish date of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [PAGE.PublishDate] +--- + +By default, Hugo excludes pages with future publish dates when building your site. To include future pages, use the `--buildFuture` command line flag. + +Set the publish date in front matter: + +{{< code-toggle file=content/news/article-1.md fm=true >}} +title = 'Article 1' +publishDate = 2023-10-19T00:40:04-07:00 +{{< /code-toggle >}} + +The publish 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 +{{ .PublishDate | time.Format ":date_medium" }} → Oct 19, 2023 +``` + +In the example above we explicitly set the publish date in front matter. With Hugo's default configuration, the `PublishDate` method returns the front matter value. This behavior is configurable, allowing you to set fallback values if the publish date is not defined in front matter. See [details]. + +[`time.Format`]: /functions/time/format/ +[details]: /configuration/front-matter/#dates +[time methods]: /methods/time/ +[time.Time]: https://pkg.go.dev/time#Time diff --git a/docs/content/en/methods/page/RawContent.md b/docs/content/en/methods/page/RawContent.md new file mode 100644 index 000000000..41215ef53 --- /dev/null +++ b/docs/content/en/methods/page/RawContent.md @@ -0,0 +1,23 @@ +--- +title: RawContent +description: Returns the raw content of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.RawContent] +--- + +The `RawContent` method on a `Page` object returns the raw content. The raw content does not include front matter. + +```go-html-template +{{ .RawContent }} +``` + +This is useful when rendering a page in a plain text [output format](g). + +> [!note] +> [Shortcodes](g) within the content are not rendered. To get the raw content with shortcodes rendered, use the [`RenderShortcodes`] method on a `Page` object. + +[`RenderShortcodes`]: /methods/page/rendershortcodes/ diff --git a/docs/content/en/methods/page/ReadingTime.md b/docs/content/en/methods/page/ReadingTime.md new file mode 100644 index 000000000..1bd7dea31 --- /dev/null +++ b/docs/content/en/methods/page/ReadingTime.md @@ -0,0 +1,47 @@ +--- +title: ReadingTime +description: Returns the estimated reading time, in minutes, for the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGE.ReadingTime] +--- + +The estimated reading time is calculated by dividing the number of words in the content by the reading speed. + +By default, Hugo assumes a reading speed of 212 words per minute. For CJK languages, it assumes 500 words per minute. + +```go-html-template +{{ printf "Estimated reading time: %d minutes" .ReadingTime }} +``` + +Reading speed varies by language. Create language-specific estimated reading times on your multilingual site using site parameters. + +{{< code-toggle file=hugo >}} +[languages] + [languages.de] + contentDir = 'content/de' + languageCode = 'de-DE' + languageName = 'Deutsch' + weight = 2 + [languages.de.params] + reading_speed = 179 + [languages.en] + contentDir = 'content/en' + languageCode = 'en-US' + languageName = 'English' + weight = 1 + [languages.en.params] + reading_speed = 228 +{{< /code-toggle >}} + +Then in your template: + +```go-html-template +{{ $readingTime := div (float .WordCount) .Site.Params.reading_speed }} +{{ $readingTime = math.Ceil $readingTime }} +``` + +We cast the `.WordCount` to a float to obtain a float when we divide by the reading speed. Then round up to the nearest integer. diff --git a/docs/content/en/methods/page/Ref.md b/docs/content/en/methods/page/Ref.md new file mode 100644 index 000000000..35f9460ba --- /dev/null +++ b/docs/content/en/methods/page/Ref.md @@ -0,0 +1,37 @@ +--- +title: Ref +description: Returns the absolute URL of the page with the given path, language, and output format. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Ref OPTIONS] +--- + +## Usage + +The `Ref` method accepts a single argument: an options map. + +## Options + +{{% include "_common/ref-and-relref-options.md" %}} + +## Examples + +The following examples show the rendered output for a page on the English version of the site: + +```go-html-template +{{ $opts := dict "path" "/books/book-1" }} +{{ .Ref $opts }} → https://example.org/en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" }} +{{ .Ref $opts }} → https://example.org/de/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" "outputFormat" "json" }} +{{ .Ref $opts }} → https://example.org/de/books/book-1/index.json +``` + +## Error handling + +{{% include "_common/ref-and-relref-error-handling.md" %}} diff --git a/docs/content/en/methods/page/RegularPages.md b/docs/content/en/methods/page/RegularPages.md new file mode 100644 index 000000000..761de3af5 --- /dev/null +++ b/docs/content/en/methods/page/RegularPages.md @@ -0,0 +1,79 @@ +--- +title: RegularPages +description: Returns a collection of regular pages within the current section. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGE.RegularPages] +--- + +The `RegularPages` method on a `Page` object is available to these [page kinds](g): `home`, `section`, `taxonomy`, and `term`. The templates for these page kinds receive a page [collection](g) in [context](g), in the [default sort order](g). + +Range through the page collection in your template: + +```go-html-template +{{ range .RegularPages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +Consider this content structure: + +```text +content/ +├── lessons/ +│ ├── lesson-1/ +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── lesson-2/ +│ │ ├── resources/ +│ │ │ ├── task-list.md +│ │ │ └── worksheet.md +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── _index.md +│ ├── grading-policy.md +│ └── lesson-plan.md +├── _index.md +├── contact.md +└── legal.md +``` + +When rendering the home page, the `RegularPages` method returns: + + contact.md + legal.md + +When rendering the lessons page, the `RegularPages` method returns: + + lessons/grading-policy.md + lessons/lesson-plan.md + +When rendering lesson-1, the `RegularPages` method returns: + + lessons/lesson-1/part-1.md + lessons/lesson-1/part-2.md + +When rendering lesson-2, the `RegularPages` method returns: + + lessons/lesson-2/part-1.md + lessons/lesson-2/part-2.md + lessons/lesson-2/resources/task-list.md + lessons/lesson-2/resources/worksheet.md + +In the last example, the collection includes pages in the resources subdirectory. That directory is not a [section](g)---it does not contain an `_index.md` file. Its contents are part of the lesson-2 section. + +> [!note] +> When used with the `Site` object, the `RegularPages` method recursively returns all regular pages within the site. See [details]. + +```go-html-template +{{ range .Site.RegularPages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +[details]: /methods/site/regularpages/ diff --git a/docs/content/en/methods/page/RegularPagesRecursive.md b/docs/content/en/methods/page/RegularPagesRecursive.md new file mode 100644 index 000000000..d85cd0b48 --- /dev/null +++ b/docs/content/en/methods/page/RegularPagesRecursive.md @@ -0,0 +1,83 @@ +--- +title: RegularPagesRecursive +description: Returns a collection of regular pages within the current section, and regular pages within all descendant sections. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGE.RegularPagesRecursive] +--- + +The `RegularPagesRecursive` method on a `Page` object is available to these [page kinds](g): `home`, `section`, `taxonomy`, and `term`. The templates for these page kinds receive a page [collection](g) in [context](g), in the [default sort order](g). + +Range through the page collection in your template: + +```go-html-template +{{ range .RegularPagesRecursive.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +Consider this content structure: + +```text +content/ +├── lessons/ +│ ├── lesson-1/ +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── lesson-2/ +│ │ ├── resources/ +│ │ │ ├── task-list.md +│ │ │ └── worksheet.md +│ │ ├── _index.md +│ │ ├── part-1.md +│ │ └── part-2.md +│ ├── _index.md +│ ├── grading-policy.md +│ └── lesson-plan.md +├── _index.md +├── contact.md +└── legal.md +``` + +When rendering the home page, the `RegularPagesRecursive` method returns: + + contact.md + lessons/grading-policy.md + legal.md + lessons/lesson-plan.md + lessons/lesson-2/part-1.md + lessons/lesson-1/part-1.md + lessons/lesson-2/part-2.md + lessons/lesson-1/part-2.md + lessons/lesson-2/resources/task-list.md + lessons/lesson-2/resources/worksheet.md + +When rendering the lessons page, the `RegularPagesRecursive` method returns: + + lessons/grading-policy.md + lessons/lesson-plan.md + lessons/lesson-2/part-1.md + lessons/lesson-1/part-1.md + lessons/lesson-2/part-2.md + lessons/lesson-1/part-2.md + lessons/lesson-2/resources/task-list.md + lessons/lesson-2/resources/worksheet.md + +When rendering lesson-1, the `RegularPagesRecursive` method returns: + + lessons/lesson-1/part-1.md + lessons/lesson-1/part-2.md + +When rendering lesson-2, the `RegularPagesRecursive` method returns: + + lessons/lesson-2/part-1.md + lessons/lesson-2/part-2.md + lessons/lesson-2/resources/task-list.md + lessons/lesson-2/resources/worksheet.md + +> [!note] +> The `RegularPagesRecursive` method is not available on a `Site` object. diff --git a/docs/content/en/methods/page/RelPermalink.md b/docs/content/en/methods/page/RelPermalink.md new file mode 100644 index 000000000..a3c610d50 --- /dev/null +++ b/docs/content/en/methods/page/RelPermalink.md @@ -0,0 +1,24 @@ +--- +title: RelPermalink +description: Returns the relative permalink of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.RelPermalink] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +title = 'Documentation' +baseURL = 'https://example.org/docs/' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ $page := .Site.GetPage "/about" }} +{{ $page.RelPermalink }} → /docs/about/ +``` diff --git a/docs/content/en/methods/page/RelRef.md b/docs/content/en/methods/page/RelRef.md new file mode 100644 index 000000000..7edab5740 --- /dev/null +++ b/docs/content/en/methods/page/RelRef.md @@ -0,0 +1,37 @@ +--- +title: RelRef +description: Returns the relative URL of the page with the given path, language, and output format. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.RelRef OPTIONS] +--- + +## Usage + +The `RelRef` method accepts a single argument: an options map. + +## Options + +{{% include "_common/ref-and-relref-options.md" %}} + +## Examples + +The following examples show the rendered output for a page on the English version of the site: + +```go-html-template +{{ $opts := dict "path" "/books/book-1" }} +{{ .RelRef $opts }} → /en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" }} +{{ .RelRef $opts }} → /de/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" "outputFormat" "json" }} +{{ .RelRef $opts }} → /de/books/book-1/index.json +``` + +## Error handling + +{{% include "_common/ref-and-relref-error-handling.md" %}} diff --git a/docs/content/en/methods/page/Render.md b/docs/content/en/methods/page/Render.md new file mode 100644 index 000000000..10f7f9ca5 --- /dev/null +++ b/docs/content/en/methods/page/Render.md @@ -0,0 +1,72 @@ +--- +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 }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ .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| +:--|:-- +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/ +├── _default/ +│ ├── baseof.html +│ ├── home.html +│ ├── li.html <-- used for other content types +│ ├── list.html +│ ├── single.html +│ └── summary.html +└── books/ + ├── li.html <-- used when content type is "books" + └── summary.html +``` + +And this template: + +```go-html-template +<ul> + {{ range site.RegularPages.ByDate }} + {{ .Render "li" }} + {{ end }} +</ul> +``` + +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/_default/li.html +``` + +See [content views] for more examples. + +[content views]: /templates/content-view/ +[`partial`]: /functions/partials/include/ diff --git a/docs/content/en/methods/page/RenderShortcodes.md b/docs/content/en/methods/page/RenderShortcodes.md new file mode 100644 index 000000000..d124606f0 --- /dev/null +++ b/docs/content/en/methods/page/RenderShortcodes.md @@ -0,0 +1,89 @@ +--- +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] +--- + +{{< new-in 0.117.0 />}} + +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: + +- `{{</* myshortcode */>}}` 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 ++++ + +{{</* ref "privacy" */>}} + +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 --git a/docs/content/en/methods/page/RenderString.md b/docs/content/en/methods/page/RenderString.md new file mode 100644 index 000000000..c7774774c --- /dev/null +++ b/docs/content/en/methods/page/RenderString.md @@ -0,0 +1,49 @@ +--- +title: RenderString +description: Renders markup to HTML. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: ['PAGE.RenderString [OPTIONS] MARKUP'] +aliases: [/functions/renderstring] +--- + +```go-html-template +{{ $s := "An *emphasized* word" }} +{{ $s | .RenderString }} → An <em>emphasized</em> word +``` + +This method takes an optional map of options: + +display +: (`string`) Specify either `inline` or `block`. If `inline`, removes surrounding `p` tags from short snippets. Default is `inline`. + +markup +: (`string`) Specify a [markup identifier] for the provided markup. Default is the `markup` front matter value, falling back to the value derived from the page's file extension. + +Render with the default markup renderer: + +```go-html-template +{{ $s := "An *emphasized* word" }} +{{ $s | .RenderString }} → An <em>emphasized</em> word + +{{ $opts := dict "display" "block" }} +{{ $s | .RenderString $opts }} → <p>An <em>emphasized</em> word</p> +``` + +Render with [Pandoc]: + +```go-html-template +{{ $s := "H~2~O" }} + +{{ $opts := dict "markup" "pandoc" }} +{{ $s | .RenderString $opts }} → H<sub>2</sub>O + +{{ $opts := dict "display" "block" "markup" "pandoc" }} +{{ .RenderString $opts $s }} → <p>H<sub>2</sub>O</p> +``` + +[markup identifier]: /content-management/formats/#classification +[pandoc]: https://www.pandoc.org/ diff --git a/docs/content/en/methods/page/Resources.md b/docs/content/en/methods/page/Resources.md new file mode 100644 index 000000000..dd472de88 --- /dev/null +++ b/docs/content/en/methods/page/Resources.md @@ -0,0 +1,90 @@ +--- +title: Resources +description: Returns a collection of page resources. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: resource.Resources + signatures: [PAGE.Resources] +--- + +The `Resources` method on a `Page` object returns a collection of page resources. A page resource is a file within a [page bundle](g). + +To work with global or remote resources, see the [`resources`] functions. + +## Methods + +### ByType + +(`resource.Resources`) Returns a collection of page resources of the given [media type], or nil if none found. The media type is typically one of `image`, `text`, `audio`, `video`, or `application`. + +```go-html-template +{{ range .Resources.ByType "image" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +When working with global resources instead of page resources, use the [`resources.ByType`] function. + +### Get + +(`resource.Resource`) Returns a page resource from the given path, or nil if none found. + +```go-html-template +{{ with .Resources.Get "images/a.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +When working with global resources instead of page resources, use the [`resources.Get`] function. + +### GetMatch + +(`resource.Resource`) Returns the first page resource from paths matching the given [glob](g) pattern, or nil if none found. + +```go-html-template +{{ with .Resources.GetMatch "images/*.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +When working with global resources instead of page resources, use the [`resources.GetMatch`] function. + +### Match + +(`resource.Resources`) Returns a collection of page resources from paths matching the given [glob](g) pattern, or nil if none found. + +```go-html-template +{{ range .Resources.Match "images/*.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> +{{ end }} +``` + +When working with global resources instead of page resources, use the [`resources.Match`] function. + +### Mount + +{{< new-in 0.140.0 />}} + +(`ResourceGetter`) Mounts the given resources from the two arguments base (`string`) to the given target path (`string`) and returns an object that implements [Get](#get). Note that leading slashes in target marks an absolute path. Relative target paths allows you to mount resources relative to another set, e.g. a [Page bundle](/content-management/page-bundles/): + +```go-html-template +{{ $common := resources.Match "/js/headlessui/*.*" }} +{{ $importContext := (slice $.Page ($common.Mount "/js/headlessui" ".")) }} +``` + +This method is currently only useful in [js.Batch](/functions/js/batch/#import-context). + +## Pattern matching + +With the `GetMatch` and `Match` methods, Hugo determines a match using a case-insensitive [glob](g) pattern. + +{{% include "/_common/glob-patterns.md" %}} + +[`resources.ByType`]: /functions/resources/ByType/ +[`resources.GetMatch`]: /functions/resources/ByType/ +[`resources.Get`]: /functions/resources/ByType/ +[`resources.Match`]: /functions/resources/ByType/ +[`resources`]: /functions/resources/ +[media type]: https://en.wikipedia.org/wiki/Media_type diff --git a/docs/content/en/methods/page/Scratch.md b/docs/content/en/methods/page/Scratch.md new file mode 100644 index 000000000..61c5dc19e --- /dev/null +++ b/docs/content/en/methods/page/Scratch.md @@ -0,0 +1,21 @@ +--- +title: Scratch +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.Scratch] +expiryDate: 2026-11-18 # deprecated 2024-11-18 (soft) +--- + +{{< deprecated-in 0.138.0 >}} +Use the [`PAGE.Store`] method instead. + +This is a soft deprecation. This method will be removed in a future release, but the removal date has not been established. Although Hugo will not emit a warning if you continue to use this method, you should begin using `PAGE.Store` as soon as possible. + +Beginning with v0.138.0 the `PAGE.Scratch` method is aliased to `PAGE.Store`. + +[`PAGE.Store`]: /methods/page/store/ +{{< /deprecated-in >}} diff --git a/docs/content/en/methods/page/Section.md b/docs/content/en/methods/page/Section.md new file mode 100644 index 000000000..04c6a8a24 --- /dev/null +++ b/docs/content/en/methods/page/Section.md @@ -0,0 +1,54 @@ +--- +title: Section +description: Returns the name of the top-level section in which the given page resides. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Section] +--- + +{{% glossary-term section %}} + +With this content structure: + +```text +content/ +├── lessons/ +│ ├── math/ +│ │ ├── _index.md +│ │ ├── lesson-1.md +│ │ └── lesson-2.md +│ └── _index.md +└── _index.md +``` + +When rendering lesson-1.md: + +```go-html-template +{{ .Section }} → lessons +``` + +In the example above "lessons" is the top-level section. + +The `Section` method is often used with the [`where`] function to build a page collection. + +```go-html-template +{{ range where .Site.RegularPages "Section" "lessons" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +This is similar to using the [`Type`] method with the `where` function + +```go-html-template +{{ range where .Site.RegularPages "Type" "lessons" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +However, if the `type` field in front matter has been defined on one or more pages, the page collection based on `Type` will be different than the page collection based on `Section`. + +[`where`]: /functions/collections/where/ +[`Type`]: /methods/page/type/ diff --git a/docs/content/en/methods/page/Sections.md b/docs/content/en/methods/page/Sections.md new file mode 100644 index 000000000..12f0a8c24 --- /dev/null +++ b/docs/content/en/methods/page/Sections.md @@ -0,0 +1,62 @@ +--- +title: Sections +description: Returns a collection of section pages, one for each immediate descendant section of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGE.Sections] +--- + +The `Sections` method on a `Page` object is available to these [page kinds](g): `home`, `section`, and `taxonomy`. The templates for these page kinds receive a page [collection](g) in [context](g), in the [default sort order](g). + +With this content structure: + +```text +content/ +├── auctions/ +│ ├── 2023-11/ +│ │ ├── _index.md <-- front matter: weight = 202311 +│ │ ├── auction-1.md +│ │ └── auction-2.md +│ ├── 2023-12/ +│ │ ├── _index.md <-- front matter: weight = 202312 +│ │ ├── auction-3.md +│ │ └── auction-4.md +│ ├── _index.md <-- front matter: weight = 30 +│ ├── bidding.md +│ └── payment.md +├── books/ +│ ├── _index.md <-- front matter: weight = 20 +│ ├── book-1.md +│ └── book-2.md +├── films/ +│ ├── _index.md <-- front matter: weight = 10 +│ ├── film-1.md +│ └── film-2.md +└── _index.md +``` + +And this template: + +```go-html-template +{{ range .Sections.ByWeight }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +On the home page, Hugo renders: + +```html +<h2><a href="/films/">Films</a></h2> +<h2><a href="/books/">Books</a></h2> +<h2><a href="/auctions/">Auctions</a></h2> +``` + +On the auctions page, Hugo renders: + +```html +<h2><a href="/auctions/2023-11/">Auctions in November 2023</a></h2> +<h2><a href="/auctions/2023-12/">Auctions in December 2023</a></h2> +``` diff --git a/docs/content/en/methods/page/Site.md b/docs/content/en/methods/page/Site.md new file mode 100644 index 000000000..4649e5e00 --- /dev/null +++ b/docs/content/en/methods/page/Site.md @@ -0,0 +1,18 @@ +--- +title: Site +description: Returns the Site object. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.siteWrapper + signatures: [PAGE.Site] +--- + +See [Site methods]. + +[Site methods]: /methods/site/ + +```go-html-template +{{ .Site.Title }} +``` diff --git a/docs/content/en/methods/page/Sitemap.md b/docs/content/en/methods/page/Sitemap.md new file mode 100644 index 000000000..bb1360493 --- /dev/null +++ b/docs/content/en/methods/page/Sitemap.md @@ -0,0 +1,81 @@ +--- +title: Sitemap +description: Returns the sitemap settings for the given page as defined in front matter, falling back to the sitemap settings as defined in the site configuration. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: config.SitemapConfig + signatures: [PAGE.Sitemap] +--- + +Access to the `Sitemap` method on a `Page` object is restricted to [sitemap templates]. + +## Methods + +### ChangeFreq + +(`string`) How frequently a page is likely to change. Valid values are `always`, `hourly`, `daily`, `weekly`, `monthly`, `yearly`, and `never`. With the default value of `""` Hugo will omit this field from the sitemap. See [details](https://www.sitemaps.org/protocol.html#changefreqdef). + +```go-html-template +{{ .Sitemap.ChangeFreq }} +``` + +### Disable + +{{< new-in 0.125.0 />}} + +(`bool`) Whether to disable page inclusion. Default is `false`. Set to `true` in front matter to exclude the page. + +```go-html-template +{{ .Sitemap.Disable }} +``` + +### Priority + +(`float`) The priority of a page relative to any other page on the site. Valid values range from 0.0 to 1.0. With the default value of `-1` Hugo will omit this field from the sitemap. See [details](https://www.sitemaps.org/protocol.html#prioritydef). + +```go-html-template +{{ .Sitemap.Priority }} +``` + +## Example + +With this site configuration: + +{{< code-toggle file=hugo >}} +[sitemap] +changeFreq = 'monthly' +{{< /code-toggle >}} + +And this content: + +{{< code-toggle file=content/news.md fm=true >}} +title = 'News' +[sitemap] +changeFreq = 'hourly' +{{< /code-toggle >}} + +And this simplistic sitemap template: + +```xml {file="layouts/_default/sitemap.xml"} +{{ printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }} +<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" + xmlns:xhtml="http://www.w3.org/1999/xhtml"> + {{ range .Pages }} + <url> + <loc>{{ .Permalink }}</loc> + {{ if not .Lastmod.IsZero }} + <lastmod>{{ .Lastmod.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</lastmod> + {{ end }} + {{ with .Sitemap.ChangeFreq }} + <changefreq>{{ . }}</changefreq> + {{ end }} + </url> + {{ end }} +</urlset> +``` + +The change frequency will be `hourly` for the news page, and `monthly` for other pages. + +[sitemap templates]: /templates/sitemap/ diff --git a/docs/content/en/methods/page/Sites.md b/docs/content/en/methods/page/Sites.md new file mode 100644 index 000000000..8677226d7 --- /dev/null +++ b/docs/content/en/methods/page/Sites.md @@ -0,0 +1,68 @@ +--- +title: Sites +description: Returns a collection of all Site objects, one for each language, ordered by language weight. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Sites + signatures: [PAGE.Sites] +--- + +This is a convenience method to access `.Site.Sites`. + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = false + +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.en] +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 +{{< /code-toggle >}} + +This template: + +```go-html-template +<ul> + {{ range .Sites }} + <li><a href="{{ .Home.Permalink }}">{{ .Title }}</a></li> + {{ end }} +</ul> +``` + +Produces a list of links to each home page: + +```html +<ul> + <li><a href="https://example.org/de/">Projekt Dokumentation</a></li> + <li><a href="https://example.org/en/">Project Documentation</a></li> +</ul> +``` + +To render a link to the home page of the site corresponding to the default content language: + +```go-html-template +{{ with .Sites.Default }} + <a href="{{ .Home.Permalink }}">{{ .Title }}</a> +{{ end }} +``` + +This is equivalent to: + +```go-html-template +{{ with index .Sites 0 }} + <a href="{{ .Home.Permalink }}">{{ .Title }}</a> +{{ end }} +``` diff --git a/docs/content/en/methods/page/Slug.md b/docs/content/en/methods/page/Slug.md new file mode 100644 index 000000000..34000b660 --- /dev/null +++ b/docs/content/en/methods/page/Slug.md @@ -0,0 +1,25 @@ +--- +title: Slug +description: Returns the URL slug of the given page as defined in front matter. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Slug] +--- + +{{< code-toggle file=content/recipes/spicy-tuna-hand-rolls.md fm=true >}} +title = 'How to make spicy tuna hand rolls' +slug = 'sushi' +{{< /code-toggle >}} + +This page will be served from: + + https://example.org/recipes/sushi + +To get the slug value within a template: + +```go-html-template +{{ .Slug }} → sushi +``` diff --git a/docs/content/en/methods/page/Store.md b/docs/content/en/methods/page/Store.md new file mode 100644 index 000000000..0b1049b0a --- /dev/null +++ b/docs/content/en/methods/page/Store.md @@ -0,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. + +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 --git a/docs/content/en/methods/page/Summary.md b/docs/content/en/methods/page/Summary.md new file mode 100644 index 000000000..9158e571d --- /dev/null +++ b/docs/content/en/methods/page/Summary.md @@ -0,0 +1,44 @@ +--- +title: Summary +description: Returns the summary of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: [PAGE.Summary] +--- + +<!-- Do not remove the manual summary divider below. --> +<!-- If you do, you will break its first literal usage on this page. --> + +<!--more--> + +You can define a [summary] manually, in front matter, or automatically. A manual summary takes precedence over a front matter summary, and a front matter summary takes precedence over an automatic summary. + +To list the pages in a section with a summary beneath each link: + +```go-html-template +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ .Summary }} +{{ end }} +``` + +Depending on content length and how you define the summary, the summary may be equivalent to the content itself. To determine whether the content length exceeds the summary length, use the [`Truncated`] method on a `Page` object. This is useful for conditionally rendering a “read more” link: + +```go-html-template +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ .Summary }} + {{ if .Truncated }} + <a href="{{ .RelPermalink }}">Read more...</a> + {{ end }} +{{ end }} +``` + +> [!note] +> The `Truncated` method returns `false` if you define the summary in front matter. + +[`Truncated`]: /methods/page/truncated +[summary]: /content-management/summaries/ diff --git a/docs/content/en/methods/page/TableOfContents.md b/docs/content/en/methods/page/TableOfContents.md new file mode 100644 index 000000000..7ec9fe614 --- /dev/null +++ b/docs/content/en/methods/page/TableOfContents.md @@ -0,0 +1,47 @@ +--- +title: TableOfContents +description: Returns a table of contents for the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: [PAGE.TableOfContents] +aliases: [/content-management/toc/] +--- + +The `TableOfContents` method on a `Page` object returns an ordered or unordered list of the Markdown [ATX] and [setext] headings within the page content. + +[atx]: https://spec.commonmark.org/0.30/#atx-headings +[setext]: https://spec.commonmark.org/0.30/#setext-headings + +This template code: + +```go-html-template +{{ .TableOfContents }} +``` + +Produces this HTML: + +```html +<nav id="TableOfContents"> + <ul> + <li><a href="#section-1">Section 1</a> + <ul> + <li><a href="#section-11">Section 1.1</a></li> + <li><a href="#section-12">Section 1.2</a></li> + </ul> + </li> + <li><a href="#section-2">Section 2</a></li> + </ul> +</nav> +``` + +By default, the `TableOfContents` method returns an unordered list of level 2 and level 3 headings. You can adjust this in your site configuration: + +{{< code-toggle file=hugo >}} +[markup.tableOfContents] +endLevel = 3 +ordered = false +startLevel = 2 +{{< /code-toggle >}} diff --git a/docs/content/en/methods/page/Title.md b/docs/content/en/methods/page/Title.md new file mode 100644 index 000000000..dae4ba6dd --- /dev/null +++ b/docs/content/en/methods/page/Title.md @@ -0,0 +1,39 @@ +--- +title: Title +description: Returns the title of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Title] +--- + +With pages backed by a file, the `Title` method returns the `title` field as defined in front matter: + +{{< code-toggle file=content/about.md fm=true >}} +title = 'About us' +{{< /code-toggle >}} + +```go-html-template +{{ .Title }} → About us +``` + +With section, taxonomy, and term pages not backed by a file, the `Title` method returns the section name, capitalized and pluralized. You can disable these transformations by setting [`capitalizeListTitles`] and [`pluralizeListTitles`] in your site configuration. For example: + +{{< code-toggle file=hugo >}} +capitalizeListTitles = false +pluralizeListTitles = false +{{< /code-toggle >}} + +You can change the capitalization style in your site configuration to one of `ap`, `chicago`, `go`, `firstupper`, or `none`. For example: + +{{< code-toggle file=hugo >}} +titleCaseStyle = "firstupper" +{{< /code-toggle >}} + + See [details]. + +[`capitalizeListTitles`]: /configuration/all/#capitalizelisttitles +[`pluralizeListTitles`]: /configuration/all/#pluralizelisttitles +[details]: /configuration/all/#title-case-style diff --git a/docs/content/en/methods/page/TranslationKey.md b/docs/content/en/methods/page/TranslationKey.md new file mode 100644 index 000000000..1e930687e --- /dev/null +++ b/docs/content/en/methods/page/TranslationKey.md @@ -0,0 +1,71 @@ +--- +title: TranslationKey +description: Returns the translation key of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.TranslationKey] +--- + +The translation key creates a relationship between all translations of a given page. The translation key is derived from the file path, or from the `translationKey` parameter if defined in front matter. + +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 +{{< /code-toggle >}} + +And this content: + +```text +content/ +├── de/ +│ ├── books/ +│ │ ├── buch-1.md +│ │ └── book-2.md +│ └── _index.md +├── en/ +│ ├── books/ +│ │ ├── book-1.md +│ │ └── book-2.md +│ └── _index.md +└── _index.md +``` + +And this front matter: + +{{< code-toggle file=content/en/books/book-1.md fm=true >}} +title = 'Book 1' +translationKey = 'foo' +{{< /code-toggle >}} + +{{< code-toggle file=content/de/books/buch-1.md fm=true >}} +title = 'Buch 1' +translationKey = 'foo' +{{< /code-toggle >}} + +When rendering either either of the pages above: + +```go-html-template +{{ .TranslationKey }} → page/foo +``` + +If the front matter of Book 2, in both languages, does not include a translation key: + +```go-html-template +{{ .TranslationKey }} → page/books/book-2 +``` diff --git a/docs/content/en/methods/page/Translations.md b/docs/content/en/methods/page/Translations.md new file mode 100644 index 000000000..4bab9fe11 --- /dev/null +++ b/docs/content/en/methods/page/Translations.md @@ -0,0 +1,86 @@ +--- +title: Translations +description: Returns all translations of the given page, excluding the current language. +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 }} + <ul> + {{ range . }} + <li> + <a href="{{ .RelPermalink }}" hreflang="{{ .Language.LanguageCode }}">{{ .LinkTitle }} ({{ or .Language.LanguageName .Language.Lang }})</a> + </li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo will render this list on the "Book 1" page of the English site: + +```html +<ul> + <li><a href="/de/books/book-1/" hreflang="de-DE">Book 1 (Deutsch)</a></li> + <li><a href="/fr/books/book-1/" hreflang="fr-FR">Book 1 (Français)</a></li> +</ul> +``` + +Hugo will render this list on the "Book 2" page of the English site: + +```html +<ul> + <li><a href="/de/books/book-1/" hreflang="de-DE">Book 1 (Deutsch)</a></li> +</ul> +``` diff --git a/docs/content/en/methods/page/Truncated.md b/docs/content/en/methods/page/Truncated.md new file mode 100644 index 000000000..8c2573069 --- /dev/null +++ b/docs/content/en/methods/page/Truncated.md @@ -0,0 +1,29 @@ +--- +title: Truncated +description: Reports whether the content length exceeds the summary length. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGE.Truncated] +--- + +You can define a [summary] manually, in front matter, or automatically. A manual summary takes precedence over a front matter summary, and a front matter summary takes precedence over an automatic summary. + +[summary]: /content-management/summaries/ + +The `Truncated` method returns `true` if the content length exceeds the summary length. This is useful for conditionally rendering a "read more" link: + +```go-html-template +{{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ .Summary }} + {{ if .Truncated }} + <a href="{{ .RelPermalink }}">Read more...</a> + {{ end }} +{{ end }} +``` + +> [!note] +> The `Truncated` method returns `false` if you define the summary in front matter. diff --git a/docs/content/en/methods/page/Type.md b/docs/content/en/methods/page/Type.md new file mode 100644 index 000000000..6f855fbe3 --- /dev/null +++ b/docs/content/en/methods/page/Type.md @@ -0,0 +1,51 @@ +--- +title: Type +description: Returns the content type of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGE.Type] +--- + +The `Type` method on a `Page` object returns the [content type](g) of the given page. The content type is defined by the `type` field in front matter, or inferred from the top-level directory name if the `type` field in front matter is not defined. + +With this content structure: + +```text +content/ +├── auction/ +│ ├── _index.md +│ ├── item-1.md +│ └── item-2.md <-- front matter: type = books +├── books/ +│ ├── _index.md +│ ├── book-1.md +│ └── book-2.md +├── films/ +│ ├── _index.md +│ ├── film-1.md +│ └── film-2.md +└── _index.md +``` + +To list the books, regardless of [section](g): + +```go-html-template +{{ range where .Site.RegularPages.ByTitle "Type" "books" }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +Hugo renders this to; + +```html +<h2><a href="/books/book-1/">Book 1</a></h2> +<h2><a href="/books/book-2/">Book 2</a></h2> +<h2><a href="/auction/item-2/">Item 2</a></h2> +``` + +The `type` field in front matter is also useful for targeting a template. See [details]. + +[details]: /templates/lookup-order/#target-a-template diff --git a/docs/content/en/methods/page/Weight.md b/docs/content/en/methods/page/Weight.md new file mode 100644 index 000000000..c14af0257 --- /dev/null +++ b/docs/content/en/methods/page/Weight.md @@ -0,0 +1,25 @@ +--- +title: Weight +description: Returns the weight of the given page as defined in front matter. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGE.Weight] +--- + +The `Weight` method on a `Page` object returns the [weight](g) of the given page as defined in front matter. + +{{< code-toggle file=content/recipes/sushi.md fm=true >}} +title = 'How to make spicy tuna hand rolls' +weight = 42 +{{< /code-toggle >}} + +Page weight controls the position of a page within a collection that is sorted by weight. Assign weights using non-zero integers. Lighter items float to the top, while heavier items sink to the bottom. Unweighted or zero-weighted elements are placed at the end of the collection. + +Although rarely used within a template, you can access the value with: + +```go-html-template +{{ .Weight }} → 42 +``` diff --git a/docs/content/en/methods/page/WordCount.md b/docs/content/en/methods/page/WordCount.md new file mode 100644 index 000000000..3950244ca --- /dev/null +++ b/docs/content/en/methods/page/WordCount.md @@ -0,0 +1,18 @@ +--- +title: WordCount +description: Returns the number of words in the content of the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGE.WordCount] +--- + +```go-html-template +{{ .WordCount }} → 103 +``` + +To round up to nearest multiple of 100, use the [`FuzzyWordCount`] method. + +[`FuzzyWordCount`]: /methods/page/fuzzywordcount/ diff --git a/docs/content/en/methods/page/_index.md b/docs/content/en/methods/page/_index.md new file mode 100644 index 000000000..c7ae7ad5d --- /dev/null +++ b/docs/content/en/methods/page/_index.md @@ -0,0 +1,8 @@ +--- +title: Page methods +linkTitle: Page +description: Use these methods with a Page object. +categories: [] +keywords: [] +aliases: [/variables/page/] +--- diff --git a/docs/content/en/methods/pager/First.md b/docs/content/en/methods/pager/First.md new file mode 100644 index 000000000..9cd58989b --- /dev/null +++ b/docs/content/en/methods/pager/First.md @@ -0,0 +1,38 @@ +--- +title: First +description: Returns the first pager in the pager collection. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pager + signatures: [PAGER.First] +--- + +Use the `First` method to build navigation between pagers. + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ with .First }} + <li><a href="{{ .URL }}">First</a></li> + {{ end }} + {{ with .Prev }} + <li><a href="{{ .URL }}">Previous</a></li> + {{ end }} + {{ with .Next }} + <li><a href="{{ .URL }}">Next</a></li> + {{ end }} + {{ with .Last }} + <li><a href="{{ .URL }}">Last</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pager/HasNext.md b/docs/content/en/methods/pager/HasNext.md new file mode 100644 index 000000000..cf3688efd --- /dev/null +++ b/docs/content/en/methods/pager/HasNext.md @@ -0,0 +1,66 @@ +--- +title: HasNext +description: Reports whether there is a pager after the current pager. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGER.HasNext] +--- + +Use the `HasNext` method to build navigation between pagers. + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ with .First }} + <li><a href="{{ .URL }}">First</a></li> + {{ end }} + {{ if .HasPrev }} + <li><a href="{{ .Prev.URL }}">Previous</a></li> + {{ end }} + {{ if .HasNext }} + <li><a href="{{ .Next.URL }}">Next</a></li> + {{ end }} + {{ with .Last }} + <li><a href="{{ .URL }}">Last</a></li> + {{ end }} + </ul> +{{ end }} +``` + +You can also write the above without using the `HasNext` method: + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ with .First }} + <li><a href="{{ .URL }}">First</a></li> + {{ end }} + {{ with .Prev }} + <li><a href="{{ .URL }}">Previous</a></li> + {{ end }} + {{ with .Next }} + <li><a href="{{ .URL }}">Next</a></li> + {{ end }} + {{ with .Last }} + <li><a href="{{ .URL }}">Last</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pager/HasPrev.md b/docs/content/en/methods/pager/HasPrev.md new file mode 100644 index 000000000..4b486b7c5 --- /dev/null +++ b/docs/content/en/methods/pager/HasPrev.md @@ -0,0 +1,66 @@ +--- +title: HasPrev +description: Reports whether there is a pager before the current pager. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [PAGER.HasPrev] +--- + +Use the `HasPrev` method to build navigation between pagers. + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ with .First }} + <li><a href="{{ .URL }}">First</a></li> + {{ end }} + {{ if .HasPrev }} + <li><a href="{{ .Prev.URL }}">Previous</a></li> + {{ end }} + {{ if .HasNext }} + <li><a href="{{ .Next.URL }}">Next</a></li> + {{ end }} + {{ with .Last }} + <li><a href="{{ .URL }}">Last</a></li> + {{ end }} + </ul> +{{ end }} +``` + +You can also write the above without using the `HasPrev` method: + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ with .First }} + <li><a href="{{ .URL }}">First</a></li> + {{ end }} + {{ with .Prev }} + <li><a href="{{ .URL }}">Previous</a></li> + {{ end }} + {{ with .Next }} + <li><a href="{{ .URL }}">Next</a></li> + {{ end }} + {{ with .Last }} + <li><a href="{{ .URL }}">Last</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pager/Last.md b/docs/content/en/methods/pager/Last.md new file mode 100644 index 000000000..71dea183d --- /dev/null +++ b/docs/content/en/methods/pager/Last.md @@ -0,0 +1,38 @@ +--- +title: Last +description: Returns the last pager in the pager collection. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pager + signatures: [PAGER.Last] +--- + +Use the `Last` method to build navigation between pagers. + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ with .First }} + <li><a href="{{ .URL }}">First</a></li> + {{ end }} + {{ with .Prev }} + <li><a href="{{ .URL }}">Previous</a></li> + {{ end }} + {{ with .Next }} + <li><a href="{{ .URL }}">Next</a></li> + {{ end }} + {{ with .Last }} + <li><a href="{{ .URL }}">Last</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pager/Next.md b/docs/content/en/methods/pager/Next.md new file mode 100644 index 000000000..d7ea9caa4 --- /dev/null +++ b/docs/content/en/methods/pager/Next.md @@ -0,0 +1,38 @@ +--- +title: Next +description: Returns the next pager in the pager collection. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pager + signatures: [PAGER.Next] +--- + +Use the `Next` method to build navigation between pagers. + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ with .First }} + <li><a href="{{ .URL }}">First</a></li> + {{ end }} + {{ with .Prev }} + <li><a href="{{ .URL }}">Previous</a></li> + {{ end }} + {{ with .Next }} + <li><a href="{{ .URL }}">Next</a></li> + {{ end }} + {{ with .Last }} + <li><a href="{{ .URL }}">Last</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pager/NumberOfElements.md b/docs/content/en/methods/pager/NumberOfElements.md new file mode 100644 index 000000000..9f88126fc --- /dev/null +++ b/docs/content/en/methods/pager/NumberOfElements.md @@ -0,0 +1,23 @@ +--- +title: NumberOfElements +description: Returns the number of pages in the current pager. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGER.NumberOfElements] +--- + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + {{ .NumberOfElements }} +{{ end }} +``` diff --git a/docs/content/en/methods/pager/PageGroups.md b/docs/content/en/methods/pager/PageGroups.md new file mode 100644 index 000000000..46f6d81cb --- /dev/null +++ b/docs/content/en/methods/pager/PageGroups.md @@ -0,0 +1,28 @@ +--- +title: PageGroups +description: Returns the page groups in the current pager. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.PagesGroup + signatures: [PAGER.PageGroups] +--- + +Use the `PageGroups` method with any of the [grouping methods]. + +[grouping methods]: /quick-reference/page-collections/#group + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate ($pages.GroupByDate "Jan 2006") }} + +{{ range $paginator.PageGroups }} + <h2>{{ .Key }}</h2> + {{ range .Pages }} + <h3><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h3> + {{ end }} +{{ end }} + +{{ template "_internal/pagination.html" . }} +``` diff --git a/docs/content/en/methods/pager/PageNumber.md b/docs/content/en/methods/pager/PageNumber.md new file mode 100644 index 000000000..6d0b8e35d --- /dev/null +++ b/docs/content/en/methods/pager/PageNumber.md @@ -0,0 +1,29 @@ +--- +title: PageNumber +description: Returns the current pager's number within the pager collection. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGER.PageNumber] +--- + +Use the `PageNumber` method to build navigation between pagers. + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ range .Pagers }} + <li><a href="{{ .URL }}">{{ .PageNumber }}</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pager/PageSize.md b/docs/content/en/methods/pager/PageSize.md new file mode 100644 index 000000000..5aad88682 --- /dev/null +++ b/docs/content/en/methods/pager/PageSize.md @@ -0,0 +1,17 @@ +--- +title: PageSize +description: Returns the number of pages per pager. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGER.PageSize] +expiryDate: 2026-06-09 # deprecated 2024-06-09 in v0.128.0 +--- + +{{< deprecated-in 0.128.0 >}} +Use [`PAGER.PagerSize`] instead. + +[`PAGER.PagerSize`]: /methods/pager/pagersize/ +{{< /deprecated-in >}} diff --git a/docs/content/en/methods/pager/PagerSize.md b/docs/content/en/methods/pager/PagerSize.md new file mode 100644 index 000000000..b2397a3e8 --- /dev/null +++ b/docs/content/en/methods/pager/PagerSize.md @@ -0,0 +1,30 @@ +--- +title: PagerSize +description: Returns the number of pages per pager. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGER.PagerSize] +--- + +{{< new-in 0.128.0 />}} + +The number of pages per pager is determined by the optional second argument passed to the [`Paginate`] method, falling back to the `pagerSize` as defined in your [site configuration]. + +[`Paginate`]: /methods/page/paginate/ +[site configuration]: /templates/pagination/#configuration + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + {{ .PagerSize }} +{{ end }} +``` diff --git a/docs/content/en/methods/pager/Pagers.md b/docs/content/en/methods/pager/Pagers.md new file mode 100644 index 000000000..e431069f4 --- /dev/null +++ b/docs/content/en/methods/pager/Pagers.md @@ -0,0 +1,29 @@ +--- +title: Pagers +description: Returns the pagers collection. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.pagers + signatures: [PAGER.Pagers] +--- + +Use the `Pagers` method to build navigation between pagers. + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ range .Pagers }} + <li><a href="{{ .URL }}">{{ .PageNumber }}</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pager/Pages.md b/docs/content/en/methods/pager/Pages.md new file mode 100644 index 000000000..6e5772a48 --- /dev/null +++ b/docs/content/en/methods/pager/Pages.md @@ -0,0 +1,21 @@ +--- +title: Pages +description: Returns the pages in the current pager. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGER.Pages] +--- + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ template "_internal/pagination.html" . }} +``` diff --git a/docs/content/en/methods/pager/Prev.md b/docs/content/en/methods/pager/Prev.md new file mode 100644 index 000000000..eb79f96e9 --- /dev/null +++ b/docs/content/en/methods/pager/Prev.md @@ -0,0 +1,38 @@ +--- +title: Prev +description: Returns the previous pager in the pager collection. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pager + signatures: [PAGER.Prev] +--- + +Use the `Prev` method to build navigation between pagers. + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ with .First }} + <li><a href="{{ .URL }}">First</a></li> + {{ end }} + {{ with .Prev }} + <li><a href="{{ .URL }}">Previous</a></li> + {{ end }} + {{ with .Next }} + <li><a href="{{ .URL }}">Next</a></li> + {{ end }} + {{ with .Last }} + <li><a href="{{ .URL }}">Last</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pager/TotalNumberOfElements.md b/docs/content/en/methods/pager/TotalNumberOfElements.md new file mode 100644 index 000000000..ad29a01f3 --- /dev/null +++ b/docs/content/en/methods/pager/TotalNumberOfElements.md @@ -0,0 +1,23 @@ +--- +title: TotalNumberOfElements +description: Returns the number of pages in the pager collection. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGER.TotalNumberOfElements] +--- + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + {{ .TotalNumberOfElements }} +{{ end }} +``` diff --git a/docs/content/en/methods/pager/TotalPages.md b/docs/content/en/methods/pager/TotalPages.md new file mode 100644 index 000000000..63da5d786 --- /dev/null +++ b/docs/content/en/methods/pager/TotalPages.md @@ -0,0 +1,39 @@ +--- +title: TotalPages +description: Returns the number of pagers in the pager collection. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGER.TotalPages] +--- + +Use the `TotalPages` method to build navigation between pagers. + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <p>Pager {{ .PageNumber }} of {{ .TotalPages }}</p> + <ul> + {{ with .First }} + <li><a href="{{ .URL }}">First</a></li> + {{ end }} + {{ with .Prev }} + <li><a href="{{ .URL }}">Previous</a></li> + {{ end }} + {{ with .Next }} + <li><a href="{{ .URL }}">Next</a></li> + {{ end }} + {{ with .Last }} + <li><a href="{{ .URL }}">Last</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pager/URL.md b/docs/content/en/methods/pager/URL.md new file mode 100644 index 000000000..a3558ba7c --- /dev/null +++ b/docs/content/en/methods/pager/URL.md @@ -0,0 +1,38 @@ +--- +title: URL +description: Returns the URL of the current pager relative to the site root. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [PAGER.URL] +--- + +Use the `URL` method to build navigation between pagers. + +```go-html-template +{{ $pages := where site.RegularPages "Type" "posts" }} +{{ $paginator := .Paginate $pages }} + +{{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ with $paginator }} + <ul> + {{ with .First }} + <li><a href="{{ .URL }}">First</a></li> + {{ end }} + {{ with .Prev }} + <li><a href="{{ .URL }}">Previous</a></li> + {{ end }} + {{ with .Next }} + <li><a href="{{ .URL }}">Next</a></li> + {{ end }} + {{ with .Last }} + <li><a href="{{ .URL }}">Last</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pager/_index.md b/docs/content/en/methods/pager/_index.md new file mode 100644 index 000000000..7a79bf42f --- /dev/null +++ b/docs/content/en/methods/pager/_index.md @@ -0,0 +1,6 @@ +--- +title: Pager methods +linkTitle: Pager +description: Use these methods with Pager objects when building navigation for a paginated list page. +keywords: [] +--- diff --git a/docs/content/en/methods/pages/ByDate.md b/docs/content/en/methods/pages/ByDate.md new file mode 100644 index 000000000..18f1b985e --- /dev/null +++ b/docs/content/en/methods/pages/ByDate.md @@ -0,0 +1,28 @@ +--- +title: ByDate +description: Returns the given page collection sorted by date in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.ByDate] +--- + +When sorting by date, the value is determined by your [site configuration], defaulting to the `date` field in front matter. + +[site configuration]: /configuration/front-matter/#dates + +```go-html-template +{{ range .Pages.ByDate }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByDate.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByExpiryDate.md b/docs/content/en/methods/pages/ByExpiryDate.md new file mode 100644 index 000000000..703988c4e --- /dev/null +++ b/docs/content/en/methods/pages/ByExpiryDate.md @@ -0,0 +1,28 @@ +--- +title: ByExpiryDate +description: Returns the given page collection sorted by expiration date in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.ByExpiryDate] +--- + +When sorting by expiration date, the value is determined by your [site configuration], defaulting to the `expiryDate` field in front matter. + +[site configuration]: /configuration/front-matter/#dates + +```go-html-template +{{ range .Pages.ByExpiryDate }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByExpiryDate.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByLanguage.md b/docs/content/en/methods/pages/ByLanguage.md new file mode 100644 index 000000000..36244eb4d --- /dev/null +++ b/docs/content/en/methods/pages/ByLanguage.md @@ -0,0 +1,24 @@ +--- +title: ByLanguage +description: Returns the given page collection sorted by language in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.ByLanguage] +--- + +```go-html-template +{{ range .Site.AllPages.ByLanguage }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Site.AllPages.ByLanguage.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByLastmod.md b/docs/content/en/methods/pages/ByLastmod.md new file mode 100644 index 000000000..3c03d2a6e --- /dev/null +++ b/docs/content/en/methods/pages/ByLastmod.md @@ -0,0 +1,28 @@ +--- +title: ByLastmod +description: Returns the given page collection sorted by last modification date in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.ByLastmod] +--- + +When sorting by last modification date, the value is determined by your [site configuration], defaulting to the `lastmod` field in front matter. + +[site configuration]: /configuration/front-matter/#dates + +```go-html-template +{{ range .Pages.ByLastmod }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByLastmod.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByLength.md b/docs/content/en/methods/pages/ByLength.md new file mode 100644 index 000000000..c47bf98ba --- /dev/null +++ b/docs/content/en/methods/pages/ByLength.md @@ -0,0 +1,24 @@ +--- +title: ByLength +description: Returns the given page collection sorted by content length in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.ByLength] +--- + +```go-html-template +{{ range .Pages.ByLength }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByLength.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByLinkTitle.md b/docs/content/en/methods/pages/ByLinkTitle.md new file mode 100644 index 000000000..4a024d25a --- /dev/null +++ b/docs/content/en/methods/pages/ByLinkTitle.md @@ -0,0 +1,24 @@ +--- +title: ByLinkTitle +description: Returns the given page collection sorted by link title in ascending order, falling back to title if link title is not defined. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.ByLinkTitle] +--- + +```go-html-template +{{ range .Pages.ByLinkTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByLinkTitle.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByParam.md b/docs/content/en/methods/pages/ByParam.md new file mode 100644 index 000000000..9544122a6 --- /dev/null +++ b/docs/content/en/methods/pages/ByParam.md @@ -0,0 +1,34 @@ +--- +title: ByParam +description: Returns the given page collection sorted by the given parameter in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.ByParam PARAM] +--- + +If the given parameter is not present in front matter, Hugo will use the matching parameter in your site configuration if present. + +```go-html-template +{{ range .Pages.ByParam "author" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range (.Pages.ByParam "author").Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +If the targeted parameter is nested, access the field using dot notation: + +```go-html-template +{{ range .Pages.ByParam "author.last_name" }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByPublishDate.md b/docs/content/en/methods/pages/ByPublishDate.md new file mode 100644 index 000000000..3dde6fd95 --- /dev/null +++ b/docs/content/en/methods/pages/ByPublishDate.md @@ -0,0 +1,28 @@ +--- +title: ByPublishDate +description: Returns the given page collection sorted by publish date in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.ByPublishDate] +--- + +When sorting by publish date, the value is determined by your [site configuration], defaulting to the `publishDate` field in front matter. + +[site configuration]: /configuration/front-matter/#dates + +```go-html-template +{{ range .Pages.ByPublishDate }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByPublishDate.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByTitle.md b/docs/content/en/methods/pages/ByTitle.md new file mode 100644 index 000000000..e10c41714 --- /dev/null +++ b/docs/content/en/methods/pages/ByTitle.md @@ -0,0 +1,24 @@ +--- +title: ByTitle +description: Returns the given page collection sorted by title in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.ByTitle] +--- + +```go-html-template +{{ range .Pages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByTitle.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/ByWeight.md b/docs/content/en/methods/pages/ByWeight.md new file mode 100644 index 000000000..ba255d3c3 --- /dev/null +++ b/docs/content/en/methods/pages/ByWeight.md @@ -0,0 +1,26 @@ +--- +title: ByWeight +description: Returns the given page collection sorted by weight in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.ByWeight] +--- + +Assign a [weight](g) to a page using the `weight` field in front matter. The weight must be a non-zero integer. Lighter items float to the top, while heavier items sink to the bottom. Unweighted or zero-weighted pages are placed at the end of the collection. + +```go-html-template +{{ range .Pages.ByWeight }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +To sort in descending order: + +```go-html-template +{{ range .Pages.ByWeight.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/GroupBy.md b/docs/content/en/methods/pages/GroupBy.md new file mode 100644 index 000000000..aff0800e9 --- /dev/null +++ b/docs/content/en/methods/pages/GroupBy.md @@ -0,0 +1,36 @@ +--- +title: GroupBy +description: Returns the given page collection grouped by the given field in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.PagesGroup + signatures: ['PAGES.GroupBy FIELD [SORT]'] +--- + +{{% include "/_common/methods/pages/group-sort-order.md" %}} + +```go-html-template +{{ range .Pages.GroupBy "Section" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in descending order: + +```go-html-template +{{ range .Pages.GroupBy "Section" "desc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/GroupByDate.md b/docs/content/en/methods/pages/GroupByDate.md new file mode 100644 index 000000000..7ef4843a4 --- /dev/null +++ b/docs/content/en/methods/pages/GroupByDate.md @@ -0,0 +1,63 @@ +--- +title: GroupByDate +description: Returns the given page collection grouped by date in descending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.PagesGroup + signatures: ['PAGES.GroupByDate LAYOUT [SORT]'] +--- + +When grouping by date, the value is determined by your [site configuration], defaulting to the `date` field in front matter. + +The [layout string] has the same format as the layout string for the [`time.Format`] function. The resulting group key is [localized](g) for language and region. + +[`time.Format`]: /functions/time/format/ +[layout string]: #layout-string +[site configuration]: /configuration/front-matter/#dates + +{{% include "/_common/methods/pages/group-sort-order.md" %}} + +To group content by year and month: + +```go-html-template +{{ range .Pages.GroupByDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in ascending order: + +```go-html-template +{{ range .Pages.GroupByDate "January 2006" "asc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The pages within each group will also be sorted by date, either ascending or descending depending on the grouping option. To sort the pages within each group, use one of the sorting methods. For example, to sort the pages within each group by title: + +```go-html-template +{{ range .Pages.GroupByDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Layout string + +{{% include "/_common/time-layout-string.md" %}} diff --git a/docs/content/en/methods/pages/GroupByExpiryDate.md b/docs/content/en/methods/pages/GroupByExpiryDate.md new file mode 100644 index 000000000..d209e6c2b --- /dev/null +++ b/docs/content/en/methods/pages/GroupByExpiryDate.md @@ -0,0 +1,63 @@ +--- +title: GroupByExpiryDate +description: Returns the given page collection grouped by expiration date in descending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.PagesGroup + signatures: ['PAGES.GroupByExpiryDate LAYOUT [SORT]'] +--- + +When grouping by expiration date, the value is determined by your [site configuration], defaulting to the `expiryDate` field in front matter. + +The [layout string] has the same format as the layout string for the [`time.Format`] function. The resulting group key is [localized](g) for language and region. + +[`time.Format`]: /functions/time/format/ +[layout string]: #layout-string +[site configuration]: /configuration/front-matter/#dates + +{{% include "/_common/methods/pages/group-sort-order.md" %}} + +To group content by year and month: + +```go-html-template +{{ range .Pages.GroupByExpiryDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in ascending order: + +```go-html-template +{{ range .Pages.GroupByExpiryDate "January 2006" "asc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The pages within each group will also be sorted by expiration date, either ascending or descending depending on your grouping option. To sort the pages within each group, use one of the sorting methods. For example, to sort the pages within each group by title: + +```go-html-template +{{ range .Pages.GroupByExpiryDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Layout string + +{{% include "/_common/time-layout-string.md" %}} diff --git a/docs/content/en/methods/pages/GroupByLastmod.md b/docs/content/en/methods/pages/GroupByLastmod.md new file mode 100644 index 000000000..8729cd3c9 --- /dev/null +++ b/docs/content/en/methods/pages/GroupByLastmod.md @@ -0,0 +1,63 @@ +--- +title: GroupByLastmod +description: Returns the given page collection grouped by last modification date in descending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.PagesGroup + signatures: ['PAGES.GroupByLastmod LAYOUT [SORT]'] +--- + +When grouping by last modification date, the value is determined by your [site configuration], defaulting to the `lastmod` field in front matter. + +The [layout string] has the same format as the layout string for the [`time.Format`] function. The resulting group key is [localized](g) for language and region. + +[`time.Format`]: /functions/time/format/ +[layout string]: #layout-string +[site configuration]: /configuration/front-matter/#dates + +{{% include "/_common/methods/pages/group-sort-order.md" %}} + +To group content by year and month: + +```go-html-template +{{ range .Pages.GroupByLastmod "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in ascending order: + +```go-html-template +{{ range .Pages.GroupByLastmod "January 2006" "asc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The pages within each group will also be sorted by last modification date, either ascending or descending depending on your grouping option. To sort the pages within each group, use one of the sorting methods. For example, to sort the pages within each group by title: + +```go-html-template +{{ range .Pages.GroupByLastmod "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Layout string + +{{% include "/_common/time-layout-string.md" %}} diff --git a/docs/content/en/methods/pages/GroupByParam.md b/docs/content/en/methods/pages/GroupByParam.md new file mode 100644 index 000000000..6764144d6 --- /dev/null +++ b/docs/content/en/methods/pages/GroupByParam.md @@ -0,0 +1,36 @@ +--- +title: GroupByParam +description: Returns the given page collection grouped by the given parameter in ascending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.PagesGroup + signatures: ['PAGES.GroupByParam PARAM [SORT]'] +--- + +{{% include "/_common/methods/pages/group-sort-order.md" %}} + +```go-html-template +{{ range .Pages.GroupByParam "color" }} + <p>{{ .Key | title }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in descending order: + +```go-html-template +{{ range .Pages.GroupByParam "color" "desc" }} + <p>{{ .Key | title }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/GroupByParamDate.md b/docs/content/en/methods/pages/GroupByParamDate.md new file mode 100644 index 000000000..b05a096d2 --- /dev/null +++ b/docs/content/en/methods/pages/GroupByParamDate.md @@ -0,0 +1,60 @@ +--- +title: GroupByParamDate +description: Returns the given page collection grouped by the given date parameter in descending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.PagesGroup + signatures: ['PAGES.GroupByParamDate PARAM LAYOUT [SORT]'] +--- + +The [layout string] has the same format as the layout string for the [`time.Format`] function. The resulting group key is [localized](g) for language and region. + +[`time.Format`]: /functions/time/format/ +[layout string]: #layout-string + +{{% include "/_common/methods/pages/group-sort-order.md" %}} + +To group content by year and month: + +```go-html-template +{{ range .Pages.GroupByParamDate "eventDate" "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in ascending order: + +```go-html-template +{{ range .Pages.GroupByParamDate "eventDate" "January 2006" "asc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The pages within each group will also be sorted by the parameter date, either ascending or descending depending on your grouping option. To sort the pages within each group, use one of the sorting methods. For example, to sort the pages within each group by title: + +```go-html-template +{{ range .Pages.GroupByParamDate "eventDate" "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Layout string + +{{% include "/_common/time-layout-string.md" %}} diff --git a/docs/content/en/methods/pages/GroupByPublishDate.md b/docs/content/en/methods/pages/GroupByPublishDate.md new file mode 100644 index 000000000..50e12f085 --- /dev/null +++ b/docs/content/en/methods/pages/GroupByPublishDate.md @@ -0,0 +1,63 @@ +--- +title: GroupByPublishDate +description: Returns the given page collection grouped by publish date in descending order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.PagesGroup + signatures: ['PAGES.GroupByPublishDate LAYOUT [SORT]'] +--- + +When grouping by publish date, the value is determined by your [site configuration], defaulting to the `publishDate` field in front matter. + +The [layout string] has the same format as the layout string for the [`time.Format`] function. The resulting group key is [localized](g) for language and region. + +[`time.Format`]: /functions/time/format/ +[layout string]: #layout-string +[site configuration]: /configuration/front-matter/#dates + +{{% include "/_common/methods/pages/group-sort-order.md" %}} + +To group content by year and month: + +```go-html-template +{{ range .Pages.GroupByPublishDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To sort the groups in ascending order: + +```go-html-template +{{ range .Pages.GroupByPublishDate "January 2006" "asc" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +The pages within each group will also be sorted by publish date, either ascending or descending depending on your grouping option. To sort the pages within each group, use one of the sorting methods. For example, to sort the pages within each group by title: + +```go-html-template +{{ range .Pages.GroupByPublishDate "January 2006" }} + <p>{{ .Key }}</p> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Layout string + +{{% include "/_common/time-layout-string.md" %}} diff --git a/docs/content/en/methods/pages/Len.md b/docs/content/en/methods/pages/Len.md new file mode 100644 index 000000000..85b3267cd --- /dev/null +++ b/docs/content/en/methods/pages/Len.md @@ -0,0 +1,14 @@ +--- +title: Len +description: Returns the number of pages in the given page collection. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [PAGES.Len] +--- + +```go-html-template +{{ .Pages.Len }} → 42 +``` diff --git a/docs/content/en/methods/pages/Limit.md b/docs/content/en/methods/pages/Limit.md new file mode 100644 index 000000000..6ee3de24d --- /dev/null +++ b/docs/content/en/methods/pages/Limit.md @@ -0,0 +1,16 @@ +--- +title: Limit +description: Returns the first N pages from the given page collection. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.Limit NUMBER] +--- + +```go-html-template +{{ range .Pages.Limit 3 }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/Next.md b/docs/content/en/methods/pages/Next.md new file mode 100644 index 000000000..ce091c1ab --- /dev/null +++ b/docs/content/en/methods/pages/Next.md @@ -0,0 +1,12 @@ +--- +title: Next +description: Returns the next page in a page collection, relative to the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [PAGES.Next PAGE] +--- + +{{% include "/_common/methods/pages/next-and-prev.md" %}} diff --git a/docs/content/en/methods/pages/Prev.md b/docs/content/en/methods/pages/Prev.md new file mode 100644 index 000000000..004b9496d --- /dev/null +++ b/docs/content/en/methods/pages/Prev.md @@ -0,0 +1,12 @@ +--- +title: Prev +description: Returns the previous page in a page collection, relative to the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.Prev PAGE] +--- + +{{% include "/_common/methods/pages/next-and-prev.md" %}} diff --git a/docs/content/en/methods/pages/Related.md b/docs/content/en/methods/pages/Related.md new file mode 100644 index 000000000..22eeb4dfa --- /dev/null +++ b/docs/content/en/methods/pages/Related.md @@ -0,0 +1,75 @@ +--- +title: Related +description: Returns a collection of pages related to the given page. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: + - PAGES.Related PAGE + - PAGES.Related OPTIONS +--- + +Based on front matter, Hugo uses several factors to identify content related to the given page. Use the default [related content configuration], or tune the results to the desired indices and parameters. See [details]. + +The argument passed to the `Related` method may be a `Page` or an options map. For example, to pass the current page: + +```go-html-template {file="layouts/_default/single.html"} +{{ with .Site.RegularPages.Related . | first 5 }} + <p>Related pages:</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +To pass an options map: + +```go-html-template {file="layouts/_default/single.html"} +{{ $opts := dict + "document" . + "indices" (slice "tags" "keywords") +}} +{{ with .Site.RegularPages.Related $opts | first 5 }} + <p>Related pages:</p> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +## Options + +indices +: (`slice`) The indices to search within. + +document +: (`page`) The page for which to find related content. Required when specifying an options map. + +namedSlices +: (`slice`) The keywords to search for, expressed as a slice of `KeyValues` using the [`keyVals`] function. + +[`keyVals`]: /functions/collections/keyvals/ + +fragments +: (`slice`) A list of special keywords that is used for indices configured as type "fragments". This will match the [fragment](g) identifiers of the documents. + +A contrived example using all of the above: + +```go-html-template +{{ $page := . }} +{{ $opts := dict + "indices" (slice "tags" "keywords") + "document" $page + "namedSlices" (slice (keyVals "tags" "hugo" "rocks") (keyVals "date" $page.Date)) + "fragments" (slice "heading-1" "heading-2") +}} +``` + +[details]: /content-management/related-content/ +[related content configuration]: /configuration/related-content/ diff --git a/docs/content/en/methods/pages/Reverse.md b/docs/content/en/methods/pages/Reverse.md new file mode 100644 index 000000000..23c4b0324 --- /dev/null +++ b/docs/content/en/methods/pages/Reverse.md @@ -0,0 +1,16 @@ +--- +title: Reverse +description: Returns the given page collection in reverse order. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [PAGES.Reverse] +--- + +```go-html-template +{{ range .Pages.ByDate.Reverse }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/pages/_index.md b/docs/content/en/methods/pages/_index.md new file mode 100644 index 000000000..f2495ae49 --- /dev/null +++ b/docs/content/en/methods/pages/_index.md @@ -0,0 +1,8 @@ +--- +title: Pages methods +linkTitle: Pages +description: Use these methods with a collection of Page objects. +categories: [] +keywords: [] +aliases: [/variables/pages] +--- diff --git a/docs/content/en/methods/resource/Colors.md b/docs/content/en/methods/resource/Colors.md new file mode 100644 index 000000000..14d0a40d8 --- /dev/null +++ b/docs/content/en/methods/resource/Colors.md @@ -0,0 +1,174 @@ +--- +title: Colors +description: Applicable to images, returns a slice of the most dominant colors using a simple histogram method. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: '[]images.Color' + signatures: [RESOURCE.Colors] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +The `Resources.Colors` method returns a slice of the most dominant colors in an image, ordered from most dominant to least dominant. This method is fast, but if you also downsize your image you can improve performance by extracting the colors from the scaled image. + +## Methods + +Each color is an object with the following methods: + +### ColorHex + +{{< new-in 0.125.0 />}} + +(`string`) Returns the [hexadecimal color] value, prefixed with a hash sign. + +### Luminance + +{{< new-in 0.125.0 />}} + +(`float64`) Returns the [relative luminance] of the color in the sRGB colorspace in the range [0, 1]. A value of `0` represents the darkest black, while a value of `1` represents the lightest white. + +> [!note] +> Image filters such as [`images.Dither`], [`images.Padding`], and [`images.Text`] accept either hexadecimal color values or `images.Color` objects as arguments. +> +> Hugo renders an `images.Color` object as a hexadecimal color value. + +## Sorting + +As a contrived example, create a table of an image's dominant colors with the most dominant color first, and display the relative luminance of each dominant color: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + <table> + <thead> + <tr> + <th>Color</th> + <th>Relative luminance</th> + </tr> + </thead> + <tbody> + {{ range .Colors }} + <tr> + <td>{{ .ColorHex }}</td> + <td>{{ .Luminance | lang.FormatNumber 4 }}</td> + </tr> + {{ end }} + </tbody> + </table> +{{ end }} +``` + +Hugo renders this to: + +ColorHex|Relative luminance +:--|:-- +`#bebebd`|`0.5145` +`#514947`|`0.0697` +`#768a9a`|`0.2436` +`#647789`|`0.1771` +`#90725e`|`0.1877` +`#a48974`|`0.2704` + +To sort by dominance with the least dominant color first: + +```go-html-template +{{ range .Colors | collections.Reverse }} +``` + +To sort by relative luminance with the darkest color first: + +```go-html-template +{{ range sort .Colors "Luminance" }} +``` + +To sort by relative luminance with the lightest color first, use either of these constructs: + +```go-html-template +{{ range sort .Colors "Luminance" | collections.Reverse }} +{{ range sort .Colors "Luminance" "desc" }} +``` + +## Examples + +### Image borders + +To add a 5 pixel border to an image using the most dominant color: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ $mostDominant := index .Colors 0 }} + {{ $filter := images.Padding 5 $mostDominant }} + {{ with .Filter $filter }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +To add a 5 pixel border to an image using the darkest dominant color: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ $darkest := index (sort .Colors "Luminance") 0 }} + {{ $filter := images.Padding 5 $darkest }} + {{ with .Filter $filter }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +### Light text on dark background + +To create a text box where the foreground and background colors are derived from an image's lightest and darkest dominant colors: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ $darkest := index (sort .Colors "Luminance") 0 }} + {{ $lightest := index (sort .Colors "Luminance" "desc") 0 }} + <div style="background: {{ $darkest }};"> + <div style="color: {{ $lightest }};"> + <p>This is light text on a dark background.</p> + </div> + </div> +{{ end }} +``` + +### WCAG contrast ratio + +In the previous example we placed light text on a dark background, but does this color combination conform to [WCAG] guidelines for either the [minimum] or the [enhanced] contrast ratio? + +The WCAG defines the [contrast ratio] as: + +$$contrast\ ratio = { L_1 + 0.05 \over L_2 + 0.05 }$$ + +where $L_1$ is the relative luminance of the lightest color and $L_2$ is the relative luminance of the darkest color. + +Calculate the contrast ratio to determine WCAG conformance: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ $lightest := index (sort .Colors "Luminance" "desc") 0 }} + {{ $darkest := index (sort .Colors "Luminance") 0 }} + {{ $cr := div + (add $lightest.Luminance 0.05) + (add $darkest.Luminance 0.05) + }} + {{ if ge $cr 7.5 }} + {{ printf "The %.2f contrast ratio conforms to WCAG Level AAA." $cr }} + {{ else if ge $cr 4.5 }} + {{ printf "The %.2f contrast ratio conforms to WCAG Level AA." $cr }} + {{ else }} + {{ printf "The %.2f contrast ratio does not conform to WCAG guidelines." $cr }} + {{ end }} +{{ end }} +``` + +[`images.Dither`]: /functions/images/dither/ +[`images.Padding`]: /functions/images/padding/ +[`images.Text`]: /functions/images/text/ +[contrast ratio]: https://www.w3.org/TR/WCAG21/#dfn-contrast-ratio +[enhanced]: https://www.w3.org/WAI/WCAG22/quickref/?showtechniques=145#contrast-enhanced +[hexadecimal color]: https://developer.mozilla.org/en-US/docs/Web/CSS/hex-color +[minimum]: https://www.w3.org/WAI/WCAG22/quickref/?showtechniques=145#contrast-minimum +[relative luminance]: https://www.w3.org/TR/WCAG21/#dfn-relative-luminance +[WCAG]: https://en.wikipedia.org/wiki/Web_Content_Accessibility_Guidelines diff --git a/docs/content/en/methods/resource/Content.md b/docs/content/en/methods/resource/Content.md new file mode 100644 index 000000000..2c2c12d3a --- /dev/null +++ b/docs/content/en/methods/resource/Content.md @@ -0,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`. + +[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" }} + <img src="data:{{ .MediaType.Type }};base64,{{ .Content | base64Encode }}"> +{{ end }} +``` + +To create inline CSS: + +```go-html-template +{{ with resources.Get "css/style.css" }} + <style>{{ .Content | safeCSS }}</style> +{{ end }} +``` + +To create inline JavaScript: + +```go-html-template +{{ with resources.Get "js/script.js" }} + <script>{{ .Content | safeJS }}</script> +{{ end }} +``` diff --git a/docs/content/en/methods/resource/Crop.md b/docs/content/en/methods/resource/Crop.md new file mode 100644 index 000000000..97b3b95d3 --- /dev/null +++ b/docs/content/en/methods/resource/Crop.md @@ -0,0 +1,42 @@ +--- +title: Crop +description: Applicable to images, returns an image resource cropped to the given dimensions without resizing. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: images.ImageResource + signatures: [RESOURCE.Crop SPEC] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +Crop an image to match the given dimensions without resizing. You must provide both width and height. + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Crop "200x200" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{% include "/_common/methods/resource/processing-spec.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Crop "200x200 topright webp q85 lanczos" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="crop 200x200 topright webp q85 lanczos" + example=true +>}} diff --git a/docs/content/en/methods/resource/Data.md b/docs/content/en/methods/resource/Data.md new file mode 100644 index 000000000..0709ca50a --- /dev/null +++ b/docs/content/en/methods/resource/Data.md @@ -0,0 +1,66 @@ +--- +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 --git a/docs/content/en/methods/resource/Err.md b/docs/content/en/methods/resource/Err.md new file mode 100644 index 000000000..591af8266 --- /dev/null +++ b/docs/content/en/methods/resource/Err.md @@ -0,0 +1,60 @@ +--- +title: Err +description: Applicable to resources returned by the resources.GetRemote function, returns an error message if the HTTP request fails, else nil. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: resource.resourceError + signatures: [RESOURCE.Err] +expiryDate: 2027-01-16 # deprecated 2025-01-16 in v0.141.0 +--- + +{{< deprecated-in 0.141.0 >}} +Use the `try` statement instead. See [example]. + +[example]: /functions/go-template/try/#example +{{< /deprecated-in >}} + +The `Err` method on a resource returned by the [`resources.GetRemote`] function returns an error message if the HTTP request fails, else nil. If you do not handle the error yourself, Hugo will fail the build. + +[`resources.GetRemote`]: /functions/resources/getremote/ + +In this example we send an HTTP request to a nonexistent domain: + +```go-html-template +{{ $url := "https://broken-example.org/images/a.jpg" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ errorf "%s" . }} + {{ else }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +The code above captures the error from the HTTP request, then fails the build: + +```text +ERROR error calling resources.GetRemote: Get "https://broken-example.org/images/a.jpg": dial tcp: lookup broken-example.org on 127.0.0.53:53: no such host +``` + +To log an error as a warning instead of an error: + +```go-html-template +{{ $url := "https://broken-example.org/images/a.jpg" }} +{{ with resources.GetRemote $url }} + {{ with .Err }} + {{ warnf "%s" . }} + {{ else }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ else }} + {{ errorf "Unable to get remote resource %q" $url }} +{{ end }} +``` + +> [!note] +> An HTTP response with a 404 status code is not an HTTP request error. To handle 404 status codes, code defensively using the nested `with-else-end` construct as shown above. diff --git a/docs/content/en/methods/resource/Exif.md b/docs/content/en/methods/resource/Exif.md new file mode 100644 index 000000000..443a0ee1a --- /dev/null +++ b/docs/content/en/methods/resource/Exif.md @@ -0,0 +1,82 @@ +--- +title: Exif +description: Applicable to JPEG, PNG, TIFF, and WebP images, returns an EXIF object containing image metadata. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: exif.ExifInfo + signatures: [RESOURCE.Exif] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +Applicable to JPEG, PNG, TIFF, and WebP images, the `Exif` method on an image `Resource` object returns an [EXIF] object containing image metadata. + +## Methods + +### Date + +(`time.Time`) Returns the image creation date/time. Format with the [`time.Format`] function. + +### Lat + +(`float64`) Returns the GPS latitude in degrees. + +### Long + +(`float64`) Returns the GPS longitude in degrees. + +### Tags + +(`exif.Tags`) Returns a collection of the available EXIF tags for this image. You may include or exclude specific tags from this collection. See [configure imaging]. + +[configure imaging]: /configuration/imaging/#exif-data + +## Examples + +To list the creation date, location, and EXIF tags: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ with .Exif }} + <p>Date: {{ .Date }}</p> + <p>Lat/Long: {{ .Lat }}/{{ .Long }}</p> + {{ with .Tags }} + <p>Tags</p> + <table> + <thead> + <tr><th>Tag</th><th>Value</th></tr> + </thead> + <tbody> + {{ range $k, $v := . }} + <tr><td>{{ $k }}</td><td>{{ $v }}</td></tr> + {{ end }} + </tbody> + </table> + {{ end }} + {{ end }} +{{ end }} +``` + +To list specific values: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ with .Exif }} + <ul> + {{ with .Date }}<li>Date: {{ .Format "January 02, 2006" }}</li>{{ end }} + {{ with .Tags.ApertureValue }}<li>Aperture: {{ lang.FormatNumber 2 . }}</li>{{ end }} + {{ with .Tags.BrightnessValue }}<li>Brightness: {{ lang.FormatNumber 2 . }}</li>{{ end }} + {{ with .Tags.ExposureTime }}<li>Exposure Time: {{ . }}</li>{{ end }} + {{ with .Tags.FNumber }}<li>F Number: {{ . }}</li>{{ end }} + {{ with .Tags.FocalLength }}<li>Focal Length: {{ . }}</li>{{ end }} + {{ with .Tags.ISOSpeedRatings }}<li>ISO Speed Ratings: {{ . }}</li>{{ end }} + {{ with .Tags.LensModel }}<li>Lens Model: {{ . }}</li>{{ end }} + </ul> + {{ end }} +{{ end }} +``` + +[exif]: https://en.wikipedia.org/wiki/Exif +[`time.Format`]: /functions/time/format/ diff --git a/docs/content/en/methods/resource/Fill.md b/docs/content/en/methods/resource/Fill.md new file mode 100644 index 000000000..82c696c91 --- /dev/null +++ b/docs/content/en/methods/resource/Fill.md @@ -0,0 +1,42 @@ +--- +title: Fill +description: Applicable to images, returns an image resource cropped and resized to the given dimensions. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: images.ImageResource + signatures: [RESOURCE.Fill SPEC] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +Crop and resize an image to match the given dimensions. You must provide both width and height. + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Fill "200x200" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{% include "/_common/methods/resource/processing-spec.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Fill "200x200 top webp q85 lanczos" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="fill 200x200 top webp q85 lanczos" + example=true +>}} diff --git a/docs/content/en/methods/resource/Filter.md b/docs/content/en/methods/resource/Filter.md new file mode 100644 index 000000000..b83c3d8cb --- /dev/null +++ b/docs/content/en/methods/resource/Filter.md @@ -0,0 +1,66 @@ +--- +title: Filter +description: Applicable to images, applies one or more image filters to the given image resource. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: images.ImageResource + signatures: [RESOURCE.Filter FILTER...] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +Apply one or more [image filters](#image-filters) to the given image. + +To apply a single filter: + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Filter images.Grayscale }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +To apply two or more filters, executing from left to right: + +```go-html-template +{{ $filters := slice + images.Grayscale + (images.GaussianBlur 8) +}} +{{ with resources.Get "images/original.jpg" }} + {{ with .Filter $filters }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +You can also apply image filters using the [`images.Filter`] function. + +[`images.Filter`]: /functions/images/filter/ + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Filter images.Grayscale }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Grayscale" + filterArgs="" + example=true +>}} + +## Image filters + +Use any of these filters with the `Filter` method. + +{{% list-pages-in-section path=/functions/images filter=functions_images_no_filters filterType=exclude %}} diff --git a/docs/content/en/methods/resource/Fit.md b/docs/content/en/methods/resource/Fit.md new file mode 100644 index 000000000..7b416c4a1 --- /dev/null +++ b/docs/content/en/methods/resource/Fit.md @@ -0,0 +1,42 @@ +--- +title: Fit +description: Applicable to images, returns an image resource downscaled to fit the given dimensions while maintaining aspect ratio. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: images.ImageResource + signatures: [RESOURCE.Fit SPEC] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +Downscale an image to fit the given dimensions while maintaining aspect ratio. You must provide both width and height. + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Fit "200x200" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{% include "/_common/methods/resource/processing-spec.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Fit "300x175 webp q85 lanczos" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="fit 300x175 webp q85 lanczos" + example=true +>}} diff --git a/docs/content/en/methods/resource/Height.md b/docs/content/en/methods/resource/Height.md new file mode 100644 index 000000000..cc131378a --- /dev/null +++ b/docs/content/en/methods/resource/Height.md @@ -0,0 +1,26 @@ +--- +title: Height +description: Applicable to images, returns the height of the given resource. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [RESOURCE.Height] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Height }} → 400 +{{ end }} +``` + +Use the `Width` and `Height` methods together when rendering an `img` element: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> +{{ end }} +``` diff --git a/docs/content/en/methods/resource/MediaType.md b/docs/content/en/methods/resource/MediaType.md new file mode 100644 index 000000000..7721f69ba --- /dev/null +++ b/docs/content/en/methods/resource/MediaType.md @@ -0,0 +1,66 @@ +--- +title: MediaType +description: Returns a media type object for the given resource. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: media.Type + signatures: [RESOURCE.MediaType] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +The `MediaType` method on a `Resource` object returns an object with additional methods. + +## Methods + +### Type + +(`string`) The resource's media type. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .MediaType.Type }} → image/jpeg +{{ end }} +``` + +### MainType + +(`string`) The main type of the resource's media type. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .MediaType.MainType }} → image +{{ end }} +``` + +### SubType + +(`string`) The subtype of the resource's media type. This may or may not correspond to the file suffix. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .MediaType.SubType }} → jpeg +{{ end }} +``` + +### Suffixes + +(`slice`) A slice of possible file suffixes for the resource's media type. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .MediaType.Suffixes }} → [jpg jpeg jpe jif jfif] +{{ end }} +``` + +### FirstSuffix.Suffix + +(`string`) The first of the possible file suffixes for the resource's media type. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .MediaType.FirstSuffix.Suffix }} → jpg +{{ end }} +``` diff --git a/docs/content/en/methods/resource/Name.md b/docs/content/en/methods/resource/Name.md new file mode 100644 index 000000000..c678c96c9 --- /dev/null +++ b/docs/content/en/methods/resource/Name.md @@ -0,0 +1,88 @@ +--- +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 --git a/docs/content/en/methods/resource/Params.md b/docs/content/en/methods/resource/Params.md new file mode 100644 index 000000000..38f2ef6c2 --- /dev/null +++ b/docs/content/en/methods/resource/Params.md @@ -0,0 +1,61 @@ +--- +title: Params +description: Returns a map of resource parameters as defined in front matter. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: map + signatures: [RESOURCE.Params] +--- + +Use the `Params` method with [page resources](g). It is not applicable to either [global resources](g) or [remote resources](g). + +With this content structure: + +```text +content/ +├── posts/ +│ ├── cats/ +│ │ ├── images/ +│ │ │ └── a.jpg +│ │ └── index.md +│ └── _index.md +└── _index.md +``` + +And this front matter: + +{{< code-toggle file=content/posts/cats.md fm=true >}} +title = 'Cats' +[[resources]] + src = 'images/a.jpg' + title = 'Felix the cat' + [resources.params] + alt = 'Photograph of black cat' + temperament = 'vicious' +{{< /code-toggle >}} + +And this template: + +```go-html-template +{{ with .Resources.Get "images/a.jpg" }} + <figure> + <img alt="{{ .Params.alt }}" src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> + <figcaption>{{ .Title }} is {{ .Params.temperament }}</figcaption> + </figure> +{{ end }} +``` + +Hugo renders: + +```html +<figure> + <img alt="Photograph of black cat" src="/posts/post-1/images/a.jpg" width="600" height="400"> + <figcaption>Felix the cat is vicious</figcaption> +</figure> +``` + +See the [page resources] section for more information. + +[page resources]: /content-management/page-resources/ diff --git a/docs/content/en/methods/resource/Permalink.md b/docs/content/en/methods/resource/Permalink.md new file mode 100644 index 000000000..a8ec2d323 --- /dev/null +++ b/docs/content/en/methods/resource/Permalink.md @@ -0,0 +1,20 @@ +--- +title: Permalink +description: Publishes the given resource and returns its permalink. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [RESOURCE.Permalink] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +The `Permalink` method on a `Resource` object writes the resource to the publish directory, typically `public`, and returns its [permalink](g). + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Permalink }} → https://example.org/images/a.jpg +{{ end }} +``` diff --git a/docs/content/en/methods/resource/Process.md b/docs/content/en/methods/resource/Process.md new file mode 100644 index 000000000..fb27da54e --- /dev/null +++ b/docs/content/en/methods/resource/Process.md @@ -0,0 +1,60 @@ +--- +title: Process +description: Applicable to images, returns an image resource processed with the given specification. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: images.ImageResource + signatures: [RESOURCE.Process SPEC] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +Process an image with the given specification. The specification can contain an optional action, one of `crop`, `fill`, `fit`, or `resize`. This means that you can use this method instead of [`Crop`], [`Fill`], [`Fit`], or [`Resize`]. + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Process "crop 200x200" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +You can also use this method to apply simple transformations such as rotation and conversion: + +```go-html-template +{{/* Rotate 90 degrees counter-clockwise. */}} +{{ $image := $image.Process "r90" }} + +{{/* Convert to WebP. */}} +{{ $image := $image.Process "webp" }} +``` + +The `Process` method is also available as a filter, which is more effective if you need to apply multiple filters to an image. See [`images.Process`]. + +{{% include "/_common/methods/resource/processing-spec.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Process "crop 200x200 topright webp q85 lanczos" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="crop 200x200 topright webp q85 lanczos" + example=true +>}} + +[`Crop`]: /methods/resource/crop/ +[`Fill`]: /methods/resource/fill/ +[`Fit`]: /methods/resource/fit/ +[`Resize`]: /methods/resource/resize/ +[`images.Process`]: /functions/images/process/ diff --git a/docs/content/en/methods/resource/Publish.md b/docs/content/en/methods/resource/Publish.md new file mode 100644 index 000000000..0ecdf7e74 --- /dev/null +++ b/docs/content/en/methods/resource/Publish.md @@ -0,0 +1,32 @@ +--- +title: Publish +description: Publishes the given resource. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: nil + signatures: [RESOURCE.Publish] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +The `Publish` method on a `Resource` object writes the resource to the publish directory, typically `public`. + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Publish }} +{{ end }} +``` + +The `Permalink` and `RelPermalink` methods also publish a resource. `Publish` is a convenience method for publishing without a return value. For example, this: + +```go-html-template +{{ $resource.Publish }} +``` + +Instead of this: + +```go-html-template +{{ $noop := $resource.Permalink }} +``` diff --git a/docs/content/en/methods/resource/RelPermalink.md b/docs/content/en/methods/resource/RelPermalink.md new file mode 100644 index 000000000..d4c907bff --- /dev/null +++ b/docs/content/en/methods/resource/RelPermalink.md @@ -0,0 +1,20 @@ +--- +title: RelPermalink +description: Publishes the given resource and returns its relative permalink. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [RESOURCE.RelPermalink] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +The `Permalink` method on a `Resource` object writes the resource to the publish directory, typically `public`, and returns its [relative permalink](g). + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .RelPermalink }} → /images/a.jpg +{{ end }} +``` diff --git a/docs/content/en/methods/resource/Resize.md b/docs/content/en/methods/resource/Resize.md new file mode 100644 index 000000000..93c029ba6 --- /dev/null +++ b/docs/content/en/methods/resource/Resize.md @@ -0,0 +1,44 @@ +--- +title: Resize +description: Applicable to images, returns an image resource resized to the given width and/or height. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: images.ImageResource + signatures: [RESOURCE.Resize SPEC] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +Resize an image to the given width and/or height. + +If you specify both width and height, the resulting image will be disproportionally scaled unless the original image has the same aspect ratio. + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Resize "300x" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{% include "/_common/methods/resource/processing-spec.md" %}} + +## Example + +```go-html-template +{{ with resources.Get "images/original.jpg" }} + {{ with .Resize "300x webp q85 lanczos" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +{{< img + src="images/examples/zion-national-park.jpg" + alt="Zion National Park" + filter="Process" + filterArgs="resize 300x webp q85 lanczos" + example=true +>}} diff --git a/docs/content/en/methods/resource/ResourceType.md b/docs/content/en/methods/resource/ResourceType.md new file mode 100644 index 000000000..0ea9c0cf9 --- /dev/null +++ b/docs/content/en/methods/resource/ResourceType.md @@ -0,0 +1,43 @@ +--- +title: ResourceType +description: Returns the main type of the given resource's media type. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [RESOURCE.ResourceType] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +Common resource types include `audio`, `image`, `text`, and `video`. + +```go-html-template +{{ with resources.Get "image/a.jpg" }} + {{ .ResourceType }} → image + {{ .MediaType.MainType }} → image +{{ end }} +``` + +When working with content files, the resource type is `page`. + +```text +content/ +├── lessons/ +│ ├── lesson-1/ +│ │ ├── _objectives.md <-- resource type = page +│ │ ├── _topics.md <-- resource type = page +│ │ ├── _example.jpg <-- resource type = image +│ │ └── index.md +│ └── _index.md +└── _index.md +``` + +With the structure above, we can range through page resources of type `page` to build content: + +```go-html-template {file="layouts/lessons/single.html"} +{{ range .Resources.ByType "page" }} + {{ .Content }} +{{ end }} +``` diff --git a/docs/content/en/methods/resource/Title.md b/docs/content/en/methods/resource/Title.md new file mode 100644 index 000000000..c02d29ff8 --- /dev/null +++ b/docs/content/en/methods/resource/Title.md @@ -0,0 +1,81 @@ +--- +title: Title +description: Returns the title of the given resource as optionally defined in front matter, falling back to a relative path or hashed file name depending on resource type. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [RESOURCE.Title] +--- + +The value returned by the `Title` method on a `Resource` object depends on the resource type. + +## Global resource + +With a [global resource](g), the `Title` 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" }} + {{ .Title }} → /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 `Title` method returns the value of the `title` 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' +title = 'A beautiful sunrise in Bryce Canyon' +{{< /code-toggle >}} + +```go-html-template +{{ with .Resources.Get "images/a.jpg" }} + {{ .Title }} → A beautiful sunrise in Bryce Canyon +{{ end }} +``` + +If you do not create an element in the `resources` array in front matter, the `Title` 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 "Sunrise in Bryce Canyon.jpg" }} + {{ .Title }} → images/Sunrise in Bryce Canyon.jpg +{{ end }} +``` + +## Remote resource + +With a [remote resource](g), the `Title` method returns a hashed file name. + +```go-html-template +{{ with resources.GetRemote "https://example.org/images/a.jpg" }} + {{ .Title }} → /a_18432433023265451104.jpg +{{ end }} +``` diff --git a/docs/content/en/methods/resource/Width.md b/docs/content/en/methods/resource/Width.md new file mode 100644 index 000000000..e1b43f44c --- /dev/null +++ b/docs/content/en/methods/resource/Width.md @@ -0,0 +1,26 @@ +--- +title: Width +description: Applicable to images, returns the width of the given resource. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [RESOURCE.Width] +--- + +{{% include "/_common/methods/resource/global-page-remote-resources.md" %}} + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + {{ .Width }} → 600 +{{ end }} +``` + +Use the `Width` and `Height` methods together when rendering an `img` element: + +```go-html-template +{{ with resources.Get "images/a.jpg" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}"> +{{ end }} +``` diff --git a/docs/content/en/methods/resource/_index.md b/docs/content/en/methods/resource/_index.md new file mode 100644 index 000000000..edfbc5b14 --- /dev/null +++ b/docs/content/en/methods/resource/_index.md @@ -0,0 +1,7 @@ +--- +title: Resource methods +linkTitle: Resource +description: Use these methods with global, page, and remote Resource objects. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/methods/shortcode/Get.md b/docs/content/en/methods/shortcode/Get.md new file mode 100644 index 000000000..b9c01cfc4 --- /dev/null +++ b/docs/content/en/methods/shortcode/Get.md @@ -0,0 +1,46 @@ +--- +title: Get +description: Returns the value of the given argument. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: any + signatures: [SHORTCODE.Get ARG] +--- + +Specify the argument by position or by name. When calling a shortcode within Markdown, use either positional or named argument, but not both. + +> [!note] +> Some shortcodes support positional arguments, some support named arguments, and others support both. Refer to the shortcode's documentation for usage details. + +## Positional arguments + +This shortcode call uses positional arguments: + +```text {file="content/about.md"} +{{</* myshortcode "Hello" "world" */>}} +``` + +To retrieve arguments by position: + +```go-html-template {file="layouts/shortcodes/myshortcode.html"} +{{ printf "%s %s." (.Get 0) (.Get 1) }} → Hello world. +``` + +## Named arguments + +This shortcode call uses named arguments: + +```text {file="content/about.md"} +{{</* myshortcode greeting="Hello" firstName="world" */>}} +``` + +To retrieve arguments by name: + +```go-html-template {file="layouts/shortcodes/myshortcode.html"} +{{ printf "%s %s." (.Get "greeting") (.Get "firstName") }} → Hello world. +``` + +> [!note] +> Argument names are case-sensitive. diff --git a/docs/content/en/methods/shortcode/Inner.md b/docs/content/en/methods/shortcode/Inner.md new file mode 100644 index 000000000..cdce4c1c3 --- /dev/null +++ b/docs/content/en/methods/shortcode/Inner.md @@ -0,0 +1,143 @@ +--- +title: Inner +description: Returns the content between opening and closing shortcode tags, applicable when the shortcode call includes a closing tag. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: [SHORTCODE.Inner] +--- + +This content: + +```text {file="content/services.md"} +{{</* card title="Product Design" */>}} +We design the **best** widgets in the world. +{{</* /card */>}} +``` + +With this shortcode: + +```go-html-template {file="layouts/shortcodes/card.html"} +<div class="card"> + {{ with .Get "title" }} + <div class="card-title">{{ . }}</div> + {{ end }} + <div class="card-content"> + {{ .Inner | strings.TrimSpace }} + </div> +</div> +``` + +Is rendered to: + +```html +<div class="card"> + <div class="card-title">Product Design</div> + <div class="card-content"> + We design the **best** widgets in the world. + </div> +</div> +``` + +> [!note] +> Content between opening and closing shortcode tags may include leading and/or trailing newlines, depending on placement within the Markdown. Use the [`strings.TrimSpace`] function as shown above to remove carriage returns and newlines. + +> [!note] +> In the example above, the value returned by `Inner` is Markdown, but it was rendered as plain text. Use either of the following approaches to render Markdown to HTML. + +## Use RenderString + +Let's modify the example above to pass the value returned by `Inner` through the [`RenderString`] method on the `Page` object: + +```go-html-template {file="layouts/shortcodes/card.html"} +<div class="card"> + {{ with .Get "title" }} + <div class="card-title">{{ . }}</div> + {{ end }} + <div class="card-content"> + {{ .Inner | strings.TrimSpace | .Page.RenderString }} + </div> +</div> +``` + +Hugo renders this to: + +```html +<div class="card"> + <div class="card-title">Product design</div> + <div class="card-content"> + We produce the <strong>best</strong> widgets in the world. + </div> +</div> +``` + +You can use the [`markdownify`] function instead of the `RenderString` method, but the latter is more flexible. See [details]. + +## Alternative notation + +Instead of calling the shortcode with the `{{</* */>}}` notation, use the `{{%/* */%}}` notation: + +```text {file="content/services.md"} +{{%/* card title="Product Design" */%}} +We design the **best** widgets in the world. +{{%/* /card */%}} +``` + +When you use the `{{%/* */%}}` notation, Hugo renders the entire shortcode as Markdown, requiring the following changes. + +First, configure the renderer to allow raw HTML within Markdown: + +{{< code-toggle file=hugo >}} +[markup.goldmark.renderer] +unsafe = true +{{< /code-toggle >}} + +This configuration is not unsafe if _you_ control the content. Read more about Hugo's [security model]. + +Second, because we are rendering the entire shortcode as Markdown, we must adhere to the rules governing [indentation] and inclusion of [raw HTML blocks] as provided in the [CommonMark] specification. + +```go-html-template {file="layouts/shortcodes/card.html"} +<div class="card"> + {{ with .Get "title" }} + <div class="card-title">{{ . }}</div> + {{ end }} + <div class="card-content"> + + {{ .Inner | strings.TrimSpace }} + </div> +</div> +``` + +The difference between this and the previous example is subtle but required. Note the change in indentation, the addition of a blank line, and removal of the `RenderString` method. + +```diff +--- layouts/shortcodes/a.html ++++ layouts/shortcodes/b.html +@@ -1,8 +1,9 @@ + <div class="card"> + {{ with .Get "title" }} +- <div class="card-title">{{ . }}</div> ++ <div class="card-title">{{ . }}</div> + {{ end }} + <div class="card-content"> +- {{ .Inner | strings.TrimSpace | .Page.RenderString }} ++ ++ {{ .Inner | strings.TrimSpace }} + </div> + </div> +``` + +> [!note] +> Don't process the `Inner` value with `RenderString` or `markdownify` when using [Markdown notation] to call the shortcode. + +[`markdownify`]: /functions/transform/markdownify/ +[`RenderString`]: /methods/page/renderstring/ +[`strings.TrimSpace`]: /functions/strings/trimspace/ +[CommonMark]: https://spec.commonmark.org/current/ +[details]: /methods/page/renderstring/ +[indentation]: https://spec.commonmark.org/0.30/#indented-code-blocks +[Markdown notation]: /content-management/shortcodes/#notation +[raw HTML blocks]: https://spec.commonmark.org/0.31.2/#html-blocks +[security model]: /about/security/ diff --git a/docs/content/en/methods/shortcode/InnerDeindent.md b/docs/content/en/methods/shortcode/InnerDeindent.md new file mode 100644 index 000000000..0b8c8e2d8 --- /dev/null +++ b/docs/content/en/methods/shortcode/InnerDeindent.md @@ -0,0 +1,98 @@ +--- +title: InnerDeindent +description: Returns the content between opening and closing shortcode tags, with indentation removed, applicable when the shortcode call includes a closing tag. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: template.HTML + signatures: [SHORTCODE.InnerDeindent] +--- + +Similar to the [`Inner`] method, `InnerDeindent` returns the content between opening and closing shortcode tags. However, with `InnerDeindent`, indentation before the content is removed. + +This allows us to effectively bypass the rules governing [indentation] as provided in the [CommonMark] specification. + +Consider this Markdown, an unordered list with a small gallery of thumbnail images within each list item: + +```text {file="content/about.md"} +- Gallery one + + {{</* gallery */>}} +  +  + {{</* /gallery */>}} + +- Gallery two + + {{</* gallery */>}} +  +  + {{</* /gallery */>}} +``` + +In the example above, notice that the content between the opening and closing shortcode tags is indented by four spaces. Per the CommonMark specification, this is treated as an indented code block. + +With this shortcode, calling `Inner` instead of `InnerDeindent`: + +```go-html-template {file="layouts/shortcodes/gallery.html"} +<div class="gallery"> + {{ .Inner | strings.TrimSpace | .Page.RenderString }} +</div> +``` + +Hugo renders the Markdown to: + +```html +<ul> + <li> + <p>Gallery one</p> + <div class="gallery"> + <pre><code> +  + </code></pre> + </div> + </li> + <li> + <p>Gallery two</p> + <div class="gallery"> + <pre><code> +  + </code></pre> + </div> + </li> +</ul> +``` + +Although technically correct per the CommonMark specification, this is not what we want. If we remove the indentation using the `InnerDeindent` method: + +```go-html-template {file="layouts/shortcodes/gallery.html"} +<div class="gallery"> + {{ .InnerDeindent | strings.TrimSpace | .Page.RenderString }} +</div> +``` + +Hugo renders the Markdown to: + +```html +<ul> + <li> + <p>Gallery one</p> + <div class="gallery"> + <img src="images/a.jpg" alt="kitten a"> + <img src="images/b.jpg" alt="kitten b"> + </div> + </li> + <li> + <p>Gallery two</p> + <div class="gallery"> + <img src="images/c.jpg" alt="kitten c"> + <img src="images/d.jpg" alt="kitten d"> + </div> + </li> +</ul> +``` + +[commonmark]: https://commonmark.org/ +[indentation]: https://spec.commonmark.org/0.30/#indented-code-blocks +[`Inner`]: /methods/shortcode/inner/ diff --git a/docs/content/en/methods/shortcode/IsNamedParams.md b/docs/content/en/methods/shortcode/IsNamedParams.md new file mode 100644 index 000000000..1e0a7f00e --- /dev/null +++ b/docs/content/en/methods/shortcode/IsNamedParams.md @@ -0,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: + +```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"} +{{</* myshortcode greeting="Hello" firstName="world" */>}} +{{</* myshortcode "Hello" "world" */>}} +``` diff --git a/docs/content/en/methods/shortcode/Name.md b/docs/content/en/methods/shortcode/Name.md new file mode 100644 index 000000000..b5f9b6c17 --- /dev/null +++ b/docs/content/en/methods/shortcode/Name.md @@ -0,0 +1,27 @@ +--- +title: Name +description: Returns the shortcode file name, excluding the file extension. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [SHORTCODE.Name] +--- + +The `Name` method is useful for error reporting. For example, if your shortcode requires a "greeting" argument: + +```go-html-template {file="layouts/shortcodes/myshortcode.html"} +{{ $greeting := "" }} +{{ with .Get "greeting" }} + {{ $greeting = . }} +{{ else }} + {{ errorf "The %q shortcode requires a 'greeting' argument. See %s" .Name .Position }} +{{ end }} +``` + +In the absence of a "greeting" argument, Hugo will throw an error message and fail the build: + +```text +ERROR The "myshortcode" shortcode requires a 'greeting' argument. See "/home/user/project/content/about.md:11:1" +``` diff --git a/docs/content/en/methods/shortcode/Ordinal.md b/docs/content/en/methods/shortcode/Ordinal.md new file mode 100644 index 000000000..def0c016f --- /dev/null +++ b/docs/content/en/methods/shortcode/Ordinal.md @@ -0,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"} +{{</* img src="images/a.jpg" */>}} + +{{</* img src="images/b.jpg" */>}} +``` + +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 }} + <img id="{{ $id }}" src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ 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 +<img id="img-000" src="/images/a.jpg" width="600" height="400" alt=""> +<img id="img-001" src="/images/b.jpg" width="600" height="400" alt=""> +``` + +> [!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. + +[`with`]: /functions/go-template/with/ diff --git a/docs/content/en/methods/shortcode/Page.md b/docs/content/en/methods/shortcode/Page.md new file mode 100644 index 000000000..774caf9fc --- /dev/null +++ b/docs/content/en/methods/shortcode/Page.md @@ -0,0 +1,36 @@ +--- +title: Page +description: Returns the Page object from which the shortcode was called. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: hugolib.pageForShortcode + signatures: [SHORTCODE.Page] +--- + +With this content: + +{{< code-toggle file=content/books/les-miserables.md fm=true >}} +title = 'Les Misérables' +author = 'Victor Hugo' +publication_year = 1862 +isbn = '978-0451419439' +{{< /code-toggle >}} + +Calling this shortcode: + +```text +{{</* book-details */>}} +``` + +We can access the front matter values using the `Page` method: + +```go-html-template {file="layouts/shortcodes/book-details.html"} +<ul> + <li>Title: {{ .Page.Title }}</li> + <li>Author: {{ .Page.Params.author }}</li> + <li>Published: {{ .Page.Params.publication_year }}</li> + <li>ISBN: {{ .Page.Params.isbn }}</li> +</ul> +``` diff --git a/docs/content/en/methods/shortcode/Params.md b/docs/content/en/methods/shortcode/Params.md new file mode 100644 index 000000000..f001e737f --- /dev/null +++ b/docs/content/en/methods/shortcode/Params.md @@ -0,0 +1,32 @@ +--- +title: Params +description: Returns a collection of the shortcode arguments. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: any + signatures: [SHORTCODE.Params] +--- + +When you call a shortcode using positional arguments, the `Params` method returns a slice. + +```text {file="content/about.md"} +{{</* myshortcode "Hello" "world" */>}} +``` + +```go-html-template {file="layouts/shortcodes/myshortcode.html"} +{{ index .Params 0 }} → Hello +{{ index .Params 1 }} → world +``` + +When you call a shortcode using named arguments, the `Params` method returns a map. + +```text {file="content/about.md"} +{{</* myshortcode greeting="Hello" name="world" */>}} +``` + +```go-html-template {file="layouts/shortcodes/myshortcode.html"} +{{ .Params.greeting }} → Hello +{{ .Params.name }} → world +``` diff --git a/docs/content/en/methods/shortcode/Parent.md b/docs/content/en/methods/shortcode/Parent.md new file mode 100644 index 000000000..91c445d2a --- /dev/null +++ b/docs/content/en/methods/shortcode/Parent.md @@ -0,0 +1,50 @@ +--- +title: Parent +description: Returns the parent shortcode context in nested shortcodes. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: hugolib.ShortcodeWithPage + signatures: [SHORTCODE.Parent] +--- + +This is useful for inheritance of common shortcode arguments from the root. + +In this contrived example, the "greeting" shortcode is the parent, and the "now" shortcode is child. + +```text {file="content/welcome.md"} +{{</* greeting dateFormat="Jan 2, 2006" */>}} +Welcome. Today is {{</* now */>}}. +{{</* /greeting */>}} +``` + +```go-html-template {file="layouts/shortcodes/greeting.html"} +<div class="greeting"> + {{ .Inner | strings.TrimSpace | .Page.RenderString }} +</div> +``` + +```go-html-template {file="layouts/shortcodes/now.html"} +{{- $dateFormat := "January 2, 2006 15:04:05" }} + +{{- with .Params }} + {{- with .dateFormat }} + {{- $dateFormat = . }} + {{- end }} +{{- else }} + {{- with .Parent.Params }} + {{- with .dateFormat }} + {{- $dateFormat = . }} + {{- end }} + {{- end }} +{{- end }} + +{{- now | time.Format $dateFormat -}} +``` + +The "now" shortcode formats the current time using: + +1. The `dateFormat` argument passed to the "now" shortcode, if present +1. The `dateFormat` argument passed to the "greeting" shortcode, if present +1. The default layout string defined at the top of the shortcode diff --git a/docs/content/en/methods/shortcode/Position.md b/docs/content/en/methods/shortcode/Position.md new file mode 100644 index 000000000..24810e825 --- /dev/null +++ b/docs/content/en/methods/shortcode/Position.md @@ -0,0 +1,30 @@ +--- +title: Position +description: Returns the file name and position from which the shortcode was called. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: text.Position + signatures: [SHORTCODE.Position] +--- + +The `Position` method is useful for error reporting. For example, if your shortcode requires a "greeting" argument: + +```go-html-template {file="layouts/shortcodes/myshortcode.html"} +{{ $greeting := "" }} +{{ with .Get "greeting" }} + {{ $greeting = . }} +{{ else }} + {{ errorf "The %q shortcode requires a 'greeting' argument. See %s" .Name .Position }} +{{ end }} +``` + +In the absence of a "greeting" argument, Hugo will throw an error message and fail the build: + +```text +ERROR The "myshortcode" shortcode requires a 'greeting' argument. See "/home/user/project/content/about.md:11:1" +``` + +> [!note] +> The position can be expensive to calculate. Limit its use to error reporting. diff --git a/docs/content/en/methods/shortcode/Ref.md b/docs/content/en/methods/shortcode/Ref.md new file mode 100644 index 000000000..3a877d568 --- /dev/null +++ b/docs/content/en/methods/shortcode/Ref.md @@ -0,0 +1,37 @@ +--- +title: Ref +description: Returns the absolute URL of the page with the given path, language, and output format. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [SHORTCODE.Ref OPTIONS] +--- + +## Usage + +The `Ref` method accepts a single argument: an options map. + +## Options + +{{% include "_common/ref-and-relref-options.md" %}} + +## Examples + +The following examples show the rendered output for a page on the English version of the site: + +```go-html-template +{{ $opts := dict "path" "/books/book-1" }} +{{ .Ref $opts }} → https://example.org/en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" }} +{{ .Ref $opts }} → https://example.org/de/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" "outputFormat" "json" }} +{{ .Ref $opts }} → https://example.org/de/books/book-1/index.json +``` + +## Error handling + +{{% include "_common/ref-and-relref-error-handling.md" %}} diff --git a/docs/content/en/methods/shortcode/RelRef.md b/docs/content/en/methods/shortcode/RelRef.md new file mode 100644 index 000000000..273705a95 --- /dev/null +++ b/docs/content/en/methods/shortcode/RelRef.md @@ -0,0 +1,37 @@ +--- +title: RelRef +description: Returns the relative URL of the page with the given path, language, and output format. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [SHORTCODE.RelRef OPTIONS] +--- + +## Usage + +The `RelRef` method accepts a single argument: an options map. + +## Options + +{{% include "_common/ref-and-relref-options.md" %}} + +## Examples + +The following examples show the rendered output for a page on the English version of the site: + +```go-html-template +{{ $opts := dict "path" "/books/book-1" }} +{{ .RelRef $opts }} → /en/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" }} +{{ .RelRef $opts }} → /de/books/book-1/ + +{{ $opts := dict "path" "/books/book-1" "lang" "de" "outputFormat" "json" }} +{{ .RelRef $opts }} → /de/books/book-1/index.json +``` + +## Error handling + +{{% include "_common/ref-and-relref-error-handling.md" %}} diff --git a/docs/content/en/methods/shortcode/Scratch.md b/docs/content/en/methods/shortcode/Scratch.md new file mode 100644 index 000000000..6efec2097 --- /dev/null +++ b/docs/content/en/methods/shortcode/Scratch.md @@ -0,0 +1,21 @@ +--- +title: Scratch +description: Returns a "scratch pad" to store and manipulate data, scoped to the current shortcode. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: maps.Scratch + signatures: [SHORTCODE.Scratch] +expiryDate: 2026-11-18 # deprecated 2024-11-18 (soft) +--- + +{{< deprecated-in 0.139.0 >}} +Use the [`SHORTCODE.Store`] method instead. + +This is a soft deprecation. This method will be removed in a future release, but the removal date has not been established. Although Hugo will not emit a warning if you continue to use this method, you should begin using `SHORTCODE.Store` as soon as possible. + +Beginning with v0.139.0 the `SHORTCODE.Scratch` method is aliased to `SHORTCODE.Store`. + +[`SHORTCODE.Store`]: /methods/shortcode/store/ +{{< /deprecated-in >}} diff --git a/docs/content/en/methods/shortcode/Site.md b/docs/content/en/methods/shortcode/Site.md new file mode 100644 index 000000000..4c5a9a9b5 --- /dev/null +++ b/docs/content/en/methods/shortcode/Site.md @@ -0,0 +1,18 @@ +--- +title: Site +description: Returns the Site object. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.siteWrapper + signatures: [SHORTCODE.Site] +--- + +See [Site methods]. + +[Site methods]: /methods/site/ + +```go-html-template +{{ .Site.Title }} +``` diff --git a/docs/content/en/methods/shortcode/Store.md b/docs/content/en/methods/shortcode/Store.md new file mode 100644 index 000000000..76cb9237d --- /dev/null +++ b/docs/content/en/methods/shortcode/Store.md @@ -0,0 +1,24 @@ +--- +title: Store +description: Returns a "scratch pad" to store and manipulate data, scoped to the current shortcode. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: maps.Scratch + signatures: [SHORTCODE.Store] +--- + +{{< new-in 0.139.0 />}} + +Use the `Store` method to create a [scratch pad](g) to store and manipulate data, scoped to the current shortcode. To create a scratch pad with a different [scope](g), refer to the [scope](#scope) section below. + +> [!note] +> With the introduction of the [`newScratch`] function, and the ability to [assign values to template variables] after initialization, the `Store` method within a shortcode is mostly obsolete. + +{{% include "_common/store-methods.md" %}} + +{{% include "_common/scratch-pad-scope.md" %}} + +[`newScratch`]: /functions/collections/newScratch/ +[assign values to template variables]: https://go.dev/doc/go1.11#texttemplatepkgtexttemplate diff --git a/docs/content/en/methods/shortcode/_index.md b/docs/content/en/methods/shortcode/_index.md new file mode 100644 index 000000000..0064f42aa --- /dev/null +++ b/docs/content/en/methods/shortcode/_index.md @@ -0,0 +1,8 @@ +--- +title: Shortcode methods +linkTitle: Shortcode +description: Use these methods in your shortcode templates. +categories: [] +keywords: [] +aliases: [/variables/shortcodes] +--- diff --git a/docs/content/en/methods/site/AllPages.md b/docs/content/en/methods/site/AllPages.md new file mode 100644 index 000000000..90cceee8c --- /dev/null +++ b/docs/content/en/methods/site/AllPages.md @@ -0,0 +1,22 @@ +--- +title: AllPages +description: Returns a collection of all pages in all languages. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [SITE.AllPages] +--- + +This method returns all page [kinds](g) in all languages, in the [default sort order](g). That includes the home page, section pages, taxonomy pages, term pages, and regular pages. + +In most cases you should use the [`RegularPages`] method instead. + +[`RegularPages`]: /methods/site/regularpages/ + +```go-html-template +{{ range .Site.AllPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/site/BaseURL.md b/docs/content/en/methods/site/BaseURL.md new file mode 100644 index 000000000..3644443cb --- /dev/null +++ b/docs/content/en/methods/site/BaseURL.md @@ -0,0 +1,32 @@ +--- +title: BaseURL +description: Returns the base URL as defined in the site configuration. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [SITE.BaseURL] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/docs/' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.BaseURL }} → https://example.org/docs/ +``` + +> [!note] +> There is almost never a good reason to use this method in your templates. Its usage tends to be fragile due to misconfiguration. +> +> Use the [`absURL`], [`absLangURL`], [`relURL`], or [`relLangURL`] functions instead. + +[`absLangURL`]: /functions/urls/absLangURL/ +[`absURL`]: /functions/urls/absURL/ +[`relLangURL`]: /functions/urls/relLangURL/ +[`relURL`]: /functions/urls/relURL/ diff --git a/docs/content/en/methods/site/BuildDrafts.md b/docs/content/en/methods/site/BuildDrafts.md new file mode 100644 index 000000000..4beceeb6b --- /dev/null +++ b/docs/content/en/methods/site/BuildDrafts.md @@ -0,0 +1,28 @@ +--- +title: BuildDrafts +description: Reports whether the current build includes draft pages. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [SITE.BuildDrafts] +--- + +By default, draft pages are not published when building a site. You can change this behavior with a command line flag: + +```sh +hugo --buildDrafts +``` + +Or by setting `buildDrafts` to `true` in your site configuration: + +{{< code-toggle file=hugo >}} +buildDrafts = true +{{< /code-toggle >}} + +Use the `BuildDrafts` method on a `Site` object to determine the current configuration: + +```go-html-template +{{ .Site.BuildDrafts }} → true +``` diff --git a/docs/content/en/methods/site/Config.md b/docs/content/en/methods/site/Config.md new file mode 100644 index 000000000..d1b4d1f42 --- /dev/null +++ b/docs/content/en/methods/site/Config.md @@ -0,0 +1,52 @@ +--- +title: Config +description: Returns a subset of the site configuration. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.SiteConfig + signatures: [SITE.Config] +--- + +The `Config` method on a `Site` object provides access to a subset of the site configuration, specifically the `services` and `privacy` keys. + +## Services + +See [configure services](/configuration/services). + +For example, to use Hugo's built-in Google Analytics template you must add a [Google tag ID]: + +[Google tag ID]: https://support.google.com/tagmanager/answer/12326985?hl=en + +{{< code-toggle file=hugo >}} +[services.googleAnalytics] +id = 'G-XXXXXXXXX' +{{< /code-toggle >}} + +To access this value from a template: + +```go-html-template +{{ .Site.Config.Services.GoogleAnalytics.ID }} → G-XXXXXXXXX +``` + +You must capitalize each identifier as shown above. + +## Privacy + +See [configure privacy](/configuration/privacy). + +For example, to disable usage of the built-in YouTube shortcode: + +{{< code-toggle file=hugo >}} +[privacy.youtube] +disable = true +{{< /code-toggle >}} + +To access this value from a template: + +```go-html-template +{{ .Site.Config.Privacy.YouTube.Disable }} → true +``` + +You must capitalize each identifier as shown above. diff --git a/docs/content/en/methods/site/Copyright.md b/docs/content/en/methods/site/Copyright.md new file mode 100644 index 000000000..dd8bdb4a3 --- /dev/null +++ b/docs/content/en/methods/site/Copyright.md @@ -0,0 +1,22 @@ +--- +title: Copyright +description: Returns the copyright notice as defined in the site configuration. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [SITE.Copyright] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +copyright = '© 2023 ABC Widgets, Inc.' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.Copyright }} → © 2023 ABC Widgets, Inc. +``` diff --git a/docs/content/en/methods/site/Data.md b/docs/content/en/methods/site/Data.md new file mode 100644 index 000000000..296851874 --- /dev/null +++ b/docs/content/en/methods/site/Data.md @@ -0,0 +1,103 @@ +--- +title: Data +description: Returns a data structure composed from the files in the data directory. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: map + signatures: [SITE.Data] +--- + +Use the `Data` method on a `Site` object to access data within the `data` directory, or within any directory [mounted] to the `data` directory. Supported data formats include JSON, TOML, YAML, and XML. + +> [!note] +> Although Hugo can unmarshal CSV files with the [`transform.Unmarshal`] function, do not place CSV files in the `data` directory. You cannot access data within CSV files using this method. + +Consider this `data` directory: + +```text +data/ +├── books/ +│ ├── fiction.yaml +│ └── nonfiction.yaml +├── films.json +├── paintings.xml +└── sculptures.toml +``` + +And these data files: + +```yaml {file="data/books/fiction.yaml"} +- title: The Hunchback of Notre Dame + author: Victor Hugo + isbn: 978-0140443530 +- title: Les Misérables + author: Victor Hugo + isbn: 978-0451419439 +``` + +```yaml {file="data/books/nonfiction.yaml"} +- title: The Ancien Régime and the Revolution + author: Alexis de Tocqueville + isbn: 978-0141441641 +- title: Interpreting the French Revolution + author: François Furet + isbn: 978-0521280495 +``` + +Access the data by [chaining](g) the [identifiers](g): + +```go-html-template +{{ range $category, $books := .Site.Data.books }} + <p>{{ $category | title }}</p> + <ul> + {{ range $books }} + <li>{{ .title }} ({{ .isbn }})</li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo renders this to: + +```html +<p>Fiction</p> +<ul> + <li>The Hunchback of Notre Dame (978-0140443530)</li> + <li>Les Misérables (978-0451419439)</li> +</ul> +<p>Nonfiction</p> +<ul> + <li>The Ancien Régime and the Revolution (978-0141441641)</li> + <li>Interpreting the French Revolution (978-0521280495)</li> +</ul> +``` + +To limit the listing to fiction, and sort by title: + +```go-html-template +<ul> + {{ range sort .Site.Data.books.fiction "title" }} + <li>{{ .title }} ({{ .author }})</li> + {{ end }} +</ul> +``` + +To find a fiction book by ISBN: + +```go-html-template +{{ range where .Site.Data.books.fiction "isbn" "978-0140443530" }} + <li>{{ .title }} ({{ .author }})</li> +{{ end }} +``` + +In the template examples 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. For example: + +```go-html-template +{{ index .Site.Data.books "historical-fiction" }} +``` + +[`index`]: /functions/collections/indexfunction/ +[`transform.Unmarshal`]: /functions/transform/unmarshal/ +[mounted]: /configuration/module/#mounts diff --git a/docs/content/en/methods/site/DisqusShortname.md b/docs/content/en/methods/site/DisqusShortname.md new file mode 100644 index 000000000..de679fd7e --- /dev/null +++ b/docs/content/en/methods/site/DisqusShortname.md @@ -0,0 +1,17 @@ +--- +title: DisqusShortname +description: Returns the Disqus shortname as defined in the site configuration. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [SITE.DisqusShortname] +expiryDate: 2025-10-30 # deprecated 2023-10-30 in v0.120.0 +--- + +{{< deprecated-in 0.120.0 >}} +Use [`Site.Config.Services.Disqus.Shortname`] instead. + +[`Site.Config.Services.Disqus.Shortname`]: /methods/site/config/ +{{< /deprecated-in >}} diff --git a/docs/content/en/methods/site/GetPage.md b/docs/content/en/methods/site/GetPage.md new file mode 100644 index 000000000..2a3bd7d59 --- /dev/null +++ b/docs/content/en/methods/site/GetPage.md @@ -0,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: + +```go-html-template +{{ with .Site.GetPage "/works/paintings" }} + <ul> + {{ range .Pages }} + <li>{{ .Title }} by {{ .Params.artist }}</li> + {{ end }} + </ul> +{{ end }} +``` + +Is rendered to: + +```html +<ul> + <li>Starry Night by Vincent van Gogh</li> + <li>The Mona Lisa by Leonardo da Vinci</li> +</ul> +``` + +To get a regular page instead of a section page: + +```go-html-template +{{ 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): + +```go-html-template +{{ with .Site.GetPage "/headless" }} + {{ range .Resources.ByType "image" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` diff --git a/docs/content/en/methods/site/GoogleAnalytics.md b/docs/content/en/methods/site/GoogleAnalytics.md new file mode 100644 index 000000000..e4d28bcce --- /dev/null +++ b/docs/content/en/methods/site/GoogleAnalytics.md @@ -0,0 +1,17 @@ +--- +title: GoogleAnalytics +description: Returns the Google Analytics tracking ID as defined in the site configuration. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [SITE.GoogleAnalytics] +expiryDate: 2025-10-30 # deprecated 2023-10-30 in v0.120.0 +--- + +{{< deprecated-in 0.120.0 >}} +Use [`Site.Config.Services.GoogleAnalytics.ID`] instead. + +[`Site.Config.Services.GoogleAnalytics.ID`]: /methods/site/config/ +{{< /deprecated-in >}} diff --git a/docs/content/en/methods/site/Home.md b/docs/content/en/methods/site/Home.md new file mode 100644 index 000000000..19ab61747 --- /dev/null +++ b/docs/content/en/methods/site/Home.md @@ -0,0 +1,25 @@ +--- +title: Home +description: Returns the home Page object for the given site. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [SITE.Home] +--- + +This method is useful for obtaining a link to the home page. + +Site configuration: + +{{< code-toggle file=hugo >}} +baseURL = 'https://example.org/docs/' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.Home.Permalink }} → https://example.org/docs/ +{{ .Site.Home.RelPermalink }} → /docs/ +``` diff --git a/docs/content/en/methods/site/IsDevelopment.md b/docs/content/en/methods/site/IsDevelopment.md new file mode 100644 index 000000000..cddd18818 --- /dev/null +++ b/docs/content/en/methods/site/IsDevelopment.md @@ -0,0 +1,17 @@ +--- +title: IsDevelopment +description: Reports whether the current running environment is “development”. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [SITE.IsDevelopment] +expiryDate: 2025-10-30 # deprecated 2023-10-30 in v0.120.0 +--- + +{{< deprecated-in 0.120.0 >}} +Use [`hugo.IsDevelopment`] instead. + +[`hugo.IsDevelopment`]: /functions/hugo/isdevelopment/ +{{< /deprecated-in >}} diff --git a/docs/content/en/methods/site/IsMultiLingual.md b/docs/content/en/methods/site/IsMultiLingual.md new file mode 100644 index 000000000..3f9723f1c --- /dev/null +++ b/docs/content/en/methods/site/IsMultiLingual.md @@ -0,0 +1,17 @@ +--- +title: IsMultiLingual +description: Reports whether there are two or more configured languages. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [SITE.IsMultiLingual] +expiryDate: 2026-03-16 # deprecated 2024-03-16 in 0.124.0 +--- + +{{< deprecated-in 0.124.0 >}} +Use [`hugo.IsMultilingual`] instead. + +[`hugo.IsMultilingual`]: /functions/hugo/ismultilingual/ +{{< /deprecated-in >}} diff --git a/docs/content/en/methods/site/IsServer.md b/docs/content/en/methods/site/IsServer.md new file mode 100644 index 000000000..8b09c8492 --- /dev/null +++ b/docs/content/en/methods/site/IsServer.md @@ -0,0 +1,17 @@ +--- +title: IsServer +description: Reports whether the built-in development server is running. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [SITE.IsServer] +expiryDate: 2025-10-30 # deprecated 2023-10-30 in v0.120.0 +--- + +{{< deprecated-in 0.120.0 >}} +Use [`hugo.IsServer`] instead. + +[`hugo.IsServer`]: /functions/hugo/isserver/ +{{< /deprecated-in >}} diff --git a/docs/content/en/methods/site/Language.md b/docs/content/en/methods/site/Language.md new file mode 100644 index 000000000..31f15b8cb --- /dev/null +++ b/docs/content/en/methods/site/Language.md @@ -0,0 +1,80 @@ +--- +title: Language +description: Returns the language object for the given site. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: langs.Language + signatures: [SITE.Language] +--- + +The `Language` method on a `Site` object returns the language object for the given site. The language object points to the language definition in the site configuration. + +You can also use the `Language` method on a `Page` object. See [details]. + +## Methods + +The examples below assume the following in your site configuration: + +{{< code-toggle file=hugo >}} +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +weight = 1 +{{< /code-toggle >}} + +### Lang + +(`string`) The language tag as defined by [RFC 5646]. + +```go-html-template +{{ .Site.Language.Lang }} → de +``` + +### LanguageCode + +(`string`) The language code from the site configuration. Falls back to `Lang` if not defined. + +```go-html-template +{{ .Site.Language.LanguageCode }} → de-DE +``` + +### LanguageDirection + +(`string`) The language direction from the site configuration, either `ltr` or `rtl`. + +```go-html-template +{{ .Site.Language.LanguageDirection }} → ltr +``` + +### LanguageName + +(`string`) The language name from the site configuration. + +```go-html-template +{{ .Site.Language.LanguageName }} → Deutsch +``` + +### Weight + +(`int`) The language weight from the site configuration which determines its order in the slice of languages returned by the `Languages` method on a `Site` object. + +```go-html-template +{{ .Site.Language.Weight }} → 1 +``` + +## Example + +Some of the methods above are commonly used in a base template as attributes for the `html` element. + +```go-html-template +<html + lang="{{ .Site.Language.LanguageCode }}" + dir="{{ or .Site.Language.LanguageDirection `ltr` }} +> +``` + +[details]: /methods/page/language/ +[RFC 5646]: https://datatracker.ietf.org/doc/html/rfc5646 diff --git a/docs/content/en/methods/site/LanguagePrefix.md b/docs/content/en/methods/site/LanguagePrefix.md new file mode 100644 index 000000000..81a5e8607 --- /dev/null +++ b/docs/content/en/methods/site/LanguagePrefix.md @@ -0,0 +1,51 @@ +--- +title: LanguagePrefix +description: Returns the URL language prefix, if any, for the given site. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [SITE.LanguagePrefix] +--- + +Consider this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = false + +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.en] +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 +{{< /code-toggle >}} + +When visiting the German language site: + +```go-html-template +{{ .Site.LanguagePrefix }} → "" +``` + +When visiting the English language site: + +```go-html-template +{{ .Site.LanguagePrefix }} → /en +``` + +If you change `defaultContentLanguageInSubdir` to `true`, when visiting the German language site: + +```go-html-template +{{ .Site.LanguagePrefix }} → /de +``` + +You may use the `LanguagePrefix` method with both monolingual and multilingual sites. diff --git a/docs/content/en/methods/site/Languages.md b/docs/content/en/methods/site/Languages.md new file mode 100644 index 000000000..056d6193a --- /dev/null +++ b/docs/content/en/methods/site/Languages.md @@ -0,0 +1,58 @@ +--- +title: Languages +description: Returns a collection of language objects for all sites, ordered by language weight. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: langs.Languages + signatures: [SITE.Languages] +--- + +The `Languages` method on a `Site` object returns a collection of language objects for all sites, ordered by language weight. Each language object points to its language definition in the site configuration. + +To inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump .Site.Languages }}</pre> +``` + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = false + +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.en] +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 +{{< /code-toggle >}} + +This template: + +```go-html-template +<ul> + {{ range .Site.Languages }} + <li>{{ .Title }} ({{ .LanguageName }})</li> + {{ end }} +</ul> +``` + +Is rendered to: + +```html +<ul> + <li>Projekt Dokumentation (Deutsch)</li> + <li>Project Documentation (English)</li> +</ul> +``` diff --git a/docs/content/en/methods/site/LastChange.md b/docs/content/en/methods/site/LastChange.md new file mode 100644 index 000000000..e02937bf1 --- /dev/null +++ b/docs/content/en/methods/site/LastChange.md @@ -0,0 +1,17 @@ +--- +title: LastChange +description: Returns the last modification date of site content. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [SITE.LastChange] +expiryDate: 2026-02-19 # deprecated 2024-02-19 in v0.123.0 +--- + +{{< deprecated-in 0.123.0 >}} +Use [`.Site.Lastmod`] instead. + +[`.Site.Lastmod`]: /methods/site/lastmod/ +{{< /deprecated-in >}} diff --git a/docs/content/en/methods/site/Lastmod.md b/docs/content/en/methods/site/Lastmod.md new file mode 100644 index 000000000..38f6da2fa --- /dev/null +++ b/docs/content/en/methods/site/Lastmod.md @@ -0,0 +1,23 @@ +--- +title: Lastmod +description: Returns the last modification date of site content. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [SITE.Lastmod] +--- + +{{< new-in 0.123.0 />}} + +The `Lastmod` method on a `Site` object returns a [`time.Time`] value. Use this with time [functions] and [methods]. For example: + +```go-html-template +{{ .Site.Lastmod | time.Format ":date_long" }} → January 31, 2024 + +``` + +[`time.Time`]: https://pkg.go.dev/time#Time +[functions]: /functions/time/ +[methods]: /methods/time/ diff --git a/docs/content/en/methods/site/MainSections.md b/docs/content/en/methods/site/MainSections.md new file mode 100644 index 000000000..bee4f2d57 --- /dev/null +++ b/docs/content/en/methods/site/MainSections.md @@ -0,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: + +```go-html-template +{{ range where .Site.RegularPages "Section" "in" .Site.MainSections }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/site/Menus.md b/docs/content/en/methods/site/Menus.md new file mode 100644 index 000000000..398a9b022 --- /dev/null +++ b/docs/content/en/methods/site/Menus.md @@ -0,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 }} + <nav class="menu"> + {{ range . }} + {{ if $.IsMenuCurrent .Menu . }} + <a class="active" aria-current="page" href="{{ .URL }}">{{ .Name }}</a> + {{ else }} + <a href="{{ .URL }}">{{ .Name }}</a> + {{ end }} + {{ end }} + </nav> +{{ end }} +``` + +When viewing the home page, the result is: + +```html +<nav class="menu"> + <a class="active" aria-current="page" href="/">Home</a> + <a href="/books/">Books</a> + <a href="/films/">Films</a> +</nav> +``` + +When viewing the "books" page, the result is: + +```html +<nav class="menu"> + <a href="/">Home</a> + <a class="active" aria-current="page" href="/books/">Books</a> + <a href="/films/">Films</a> +</nav> +``` + +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 --git a/docs/content/en/methods/site/Pages.md b/docs/content/en/methods/site/Pages.md new file mode 100644 index 000000000..a6ba5e029 --- /dev/null +++ b/docs/content/en/methods/site/Pages.md @@ -0,0 +1,22 @@ +--- +title: Pages +description: Returns a collection of all pages. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [SITE.Pages] +--- + +This method returns all page [kinds](g) in the current language, in the [default sort order](g). That includes the home page, section pages, taxonomy pages, term pages, and regular pages. + +In most cases you should use the [`RegularPages`] method instead. + +[`RegularPages`]: /methods/site/regularpages/ + +```go-html-template +{{ range .Site.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` diff --git a/docs/content/en/methods/site/Param.md b/docs/content/en/methods/site/Param.md new file mode 100644 index 000000000..929e30e98 --- /dev/null +++ b/docs/content/en/methods/site/Param.md @@ -0,0 +1,28 @@ +--- +title: Param +description: Returns the site parameter with the given key. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: any + signatures: [SITE.Param KEY] +--- + +The `Param` method on a `Site` object is a convenience method to return the value of a user-defined parameter in the site configuration. + +{{< code-toggle file=hugo >}} +[params] +display_toc = true +{{< /code-toggle >}} + +```go-html-template +{{ .Site.Param "display_toc" }} → true +``` + +The above is equivalent to either of these: + +```go-html-template +{{ .Site.Params.display_toc }} +{{ index .Site.Params "display_toc" }} +``` diff --git a/docs/content/en/methods/site/Params.md b/docs/content/en/methods/site/Params.md new file mode 100644 index 000000000..8467be41d --- /dev/null +++ b/docs/content/en/methods/site/Params.md @@ -0,0 +1,42 @@ +--- +title: Params +description: Returns a map of custom parameters as defined in the site configuration. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: maps.Params + signatures: [SITE.Params] +--- + +With this site configuration: + +{{< code-toggle file=hugo >}} +[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 parameters by [chaining](g) the [identifiers](g): + +```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 +``` + +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 .Site.Params "copyright-year" }} → 2023 +``` + +[`index`]: /functions/collections/indexfunction/ diff --git a/docs/content/en/methods/site/RegularPages.md b/docs/content/en/methods/site/RegularPages.md new file mode 100644 index 000000000..69a460529 --- /dev/null +++ b/docs/content/en/methods/site/RegularPages.md @@ -0,0 +1,32 @@ +--- +title: RegularPages +description: Returns a collection of all regular pages. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [SITE.RegularPages] +--- + +The `RegularPages` method on a `Site` object returns a collection of all [regular pages](g), in the [default sort order](g). + +```go-html-template +{{ range .Site.RegularPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +{{% glossary-term "default sort order" %}} + +[default sort order](g) + +To change the sort order, use any of the `Pages` [sorting methods]. For example: + +```go-html-template +{{ range .Site.RegularPages.ByTitle }} + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> +{{ end }} +``` + +[sorting methods]: /methods/pages/ diff --git a/docs/content/en/methods/site/Sections.md b/docs/content/en/methods/site/Sections.md new file mode 100644 index 000000000..0ddaf0626 --- /dev/null +++ b/docs/content/en/methods/site/Sections.md @@ -0,0 +1,40 @@ +--- +title: Sections +description: Returns a collection of top-level section pages. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Pages + signatures: [SITE.Sections] +--- + +The `Sections` method on a `Site` object returns a collection of top-level [section pages](g), in the [default sort order](g). + +Given this content structure: + +```text +content/ +├── books/ +│ ├── book-1.md +│ └── book-2.md +├── films/ +│ ├── film-1.md +│ └── film-2.md +└── _index.md +``` + +This template: + +```go-html-template +{{ range .Site.Sections }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +Is rendered to: + +```html +<h2><a href="/books/">Books</a></h2> +<h2><a href="/films/">Films</a></h2> +``` diff --git a/docs/content/en/methods/site/Sites.md b/docs/content/en/methods/site/Sites.md new file mode 100644 index 000000000..cca71a40a --- /dev/null +++ b/docs/content/en/methods/site/Sites.md @@ -0,0 +1,66 @@ +--- +title: Sites +description: Returns a collection of all Site objects, one for each language, ordered by default content language then by language weight. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Sites + signatures: [SITE.Sites] +--- + +With this site configuration: + +{{< code-toggle file=hugo >}} +defaultContentLanguage = 'de' +defaultContentLanguageInSubdir = false + +[languages.de] +languageCode = 'de-DE' +languageDirection = 'ltr' +languageName = 'Deutsch' +title = 'Projekt Dokumentation' +weight = 1 + +[languages.en] +languageCode = 'en-US' +languageDirection = 'ltr' +languageName = 'English' +title = 'Project Documentation' +weight = 2 +{{< /code-toggle >}} + +This template: + +```go-html-template +<ul> + {{ range .Site.Sites }} + <li><a href="{{ .Home.Permalink }}">{{ .Title }}</a></li> + {{ end }} +</ul> +``` + +Produces a list of links to each home page: + +```html +<ul> + <li><a href="https://example.org/de/">Projekt Dokumentation</a></li> + <li><a href="https://example.org/en/">Project Documentation</a></li> +</ul> +``` + +To render a link to the home page of the site corresponding to the default content language: + +```go-html-template +{{ with .Site.Sites.Default }} + <a href="{{ .Home.Permalink }}">{{ .Title }}</a> +{{ end }} +``` + +This is equivalent to: + +```go-html-template +{{ with index .Site.Sites 0 }} + <a href="{{ .Home.Permalink }}">{{ .Title }}</a> +{{ end }} +``` diff --git a/docs/content/en/methods/site/Store.md b/docs/content/en/methods/site/Store.md new file mode 100644 index 000000000..7dcf7d095 --- /dev/null +++ b/docs/content/en/methods/site/Store.md @@ -0,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. + +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 --git a/docs/content/en/methods/site/Taxonomies.md b/docs/content/en/methods/site/Taxonomies.md new file mode 100644 index 000000000..92dc41a9b --- /dev/null +++ b/docs/content/en/methods/site/Taxonomies.md @@ -0,0 +1,176 @@ +--- +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 +<ul> + {{ range .Site.Taxonomies.genres.suspense }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} +</ul> +``` + +Hugo renders this to: + +```html +<ul> + <li><a href="/books/and-then-there-were-none/">And Then There Were None</a></li> + <li><a href="/books/death-on-the-nile/">Death on the Nile</a></li> + <li><a href="/books/jamaica-inn/">Jamaica Inn</a></li> +</ul> +``` + +> [!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 +<ul> + {{ range .Site.Taxonomies.series.golang }} + <li><a href="{{ .Page.RelPermalink }}">{{ .Page.Title }}</a></li> + {{ end }} +</ul> +``` + +### 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 +<section id="menu"> + <ul> + {{ range $term, $taxonomy := .Site.Taxonomies.featured }} + <li>{{ $term }}</li> + <ul> + {{ range $taxonomy.Pages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> + {{ end }} + </ul> +</section> +``` + +### Render a site's taxonomies + +The following example displays all terms in a site's tags taxonomy: + +```go-html-template +<ul> + {{ range .Site.Taxonomies.tags }} + <li><a href="{{ .Page.Permalink }}">{{ .Page.Title }}</a> {{ .Count }}</li> + {{ end }} +</ul> +``` +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 }} + <ul> + {{ range $taxonomy, $terms := . }} + {{ with $terms }} + <li> + <a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> + <ul> + {{ range $term, $weightedPages := . }} + <li> + <a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> + <ul> + {{ range $weightedPages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> + </li> + {{ end }} + </ul> + </li> + {{ end }} + {{ end }} + </ul> + {{ end }} +{{ end }} +``` + +[taxonomies]: /content-management/taxonomies/ diff --git a/docs/content/en/methods/site/Title.md b/docs/content/en/methods/site/Title.md new file mode 100644 index 000000000..935edda0c --- /dev/null +++ b/docs/content/en/methods/site/Title.md @@ -0,0 +1,22 @@ +--- +title: Title +description: Returns the title as defined in the site configuration. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [SITE.Title] +--- + +Site configuration: + +{{< code-toggle file=hugo >}} +title = 'My Documentation Site' +{{< /code-toggle >}} + +Template: + +```go-html-template +{{ .Site.Title }} → My Documentation Site +``` diff --git a/docs/content/en/methods/site/_index.md b/docs/content/en/methods/site/_index.md new file mode 100644 index 000000000..f395a3693 --- /dev/null +++ b/docs/content/en/methods/site/_index.md @@ -0,0 +1,8 @@ +--- +title: Site methods +linkTitle: Site +description: Use these methods with Site objects. +categories: [] +keywords: [] +aliases: [/variables/site/] +--- diff --git a/docs/content/en/methods/taxonomy/Alphabetical.md b/docs/content/en/methods/taxonomy/Alphabetical.md new file mode 100644 index 000000000..af4af596c --- /dev/null +++ b/docs/content/en/methods/taxonomy/Alphabetical.md @@ -0,0 +1,69 @@ +--- +title: Alphabetical +description: Returns an ordered taxonomy, sorted alphabetically by term. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.OrderedTaxonomy + signatures: [TAXONOMY.Alphabetical] +--- + +The `Alphabetical` method on a `Taxonomy` object returns an [ordered taxonomy](g), sorted alphabetically by [term](g). + +While a `Taxonomy` object is a [map](g), an ordered taxonomy is a [slice](g), where each element is an object that contains the term and a slice of its [weighted pages](g). + +{{% include "/_common/methods/taxonomy/get-a-taxonomy-object.md" %}} + +## Get the ordered taxonomy + +Now that we have captured the “genres” Taxonomy object, let's get the ordered taxonomy sorted alphabetically by term: + +```go-html-template +{{ $taxonomyObject.Alphabetical }} +``` + +To reverse the sort order: + +```go-html-template +{{ $taxonomyObject.Alphabetical.Reverse }} +``` + +To inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump $taxonomyObject.Alphabetical }}</pre> +``` + +{{% include "/_common/methods/taxonomy/ordered-taxonomy-element-methods.md" %}} + +## Example + +With this template: + +```go-html-template +{{ range $taxonomyObject.Alphabetical }} + <h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> ({{ .Count }})</h2> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo renders: + +```html +<h2><a href="/genres/romance/">romance</a> (2)</h2> +<ul> + <li><a href="/books/jamaica-inn/">Jamaica inn</a></li> + <li><a href="/books/pride-and-prejudice/">Pride and prejudice</a></li> +</ul> +<h2><a href="/genres/suspense/">suspense</a> (3)</h2> +<ul> + <li><a href="/books/and-then-there-were-none/">And then there were none</a></li> + <li><a href="/books/death-on-the-nile/">Death on the nile</a></li> + <li><a href="/books/jamaica-inn/">Jamaica inn</a></li> +</ul> +``` diff --git a/docs/content/en/methods/taxonomy/ByCount.md b/docs/content/en/methods/taxonomy/ByCount.md new file mode 100644 index 000000000..fbf9bb4a1 --- /dev/null +++ b/docs/content/en/methods/taxonomy/ByCount.md @@ -0,0 +1,69 @@ +--- +title: ByCount +description: Returns an ordered taxonomy, sorted by the number of pages associated with each term. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.OrderedTaxonomy + signatures: [TAXONOMY.ByCount] +--- + +The `ByCount` method on a `Taxonomy` object returns an [ordered taxonomy](g), sorted by the number of pages associated with each [term](g). + +While a `Taxonomy` object is a [map](g), an ordered taxonomy is a [slice](g), where each element is an object that contains the term and a slice of its [weighted pages](g). + +{{% include "/_common/methods/taxonomy/get-a-taxonomy-object.md" %}} + +## Get the ordered taxonomy + +Now that we have captured the “genres” Taxonomy object, let's get the ordered taxonomy sorted by the number of pages associated with each term: + +```go-html-template +{{ $taxonomyObject.ByCount }} +``` + +To reverse the sort order: + +```go-html-template +{{ $taxonomyObject.ByCount.Reverse }} +``` + +To inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump $taxonomyObject.ByCount }}</pre> +``` + +{{% include "/_common/methods/taxonomy/ordered-taxonomy-element-methods.md" %}} + +## Example + +With this template: + +```go-html-template +{{ range $taxonomyObject.ByCount }} + <h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> ({{ .Count }})</h2> + <ul> + {{ range .Pages.ByTitle }} + <li><a href="{{ .RelPermalink }}">{{ .Title }}</a></li> + {{ end }} + </ul> +{{ end }} +``` + +Hugo renders: + +```html +<h2><a href="/genres/suspense/">suspense</a> (3)</h2> +<ul> + <li><a href="/books/and-then-there-were-none/">And then there were none</a></li> + <li><a href="/books/death-on-the-nile/">Death on the nile</a></li> + <li><a href="/books/jamaica-inn/">Jamaica inn</a></li> +</ul> +<h2><a href="/genres/romance/">romance</a> (2)</h2> +<ul> + <li><a href="/books/jamaica-inn/">Jamaica inn</a></li> + <li><a href="/books/pride-and-prejudice/">Pride and prejudice</a></li> +</ul> +``` diff --git a/docs/content/en/methods/taxonomy/Count.md b/docs/content/en/methods/taxonomy/Count.md new file mode 100644 index 000000000..76af8ee04 --- /dev/null +++ b/docs/content/en/methods/taxonomy/Count.md @@ -0,0 +1,22 @@ +--- +title: Count +description: Returns the number of number of weighted pages to which the given term has been assigned. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [TAXONOMY.Count TERM] +--- + +The `Count` method on a `Taxonomy` object returns the number of number of [weighted pages](g) to which the given [term](g) has been assigned. + +{{% include "/_common/methods/taxonomy/get-a-taxonomy-object.md" %}} + +## Count the weighted pages + +Now that we have captured the "genres" `Taxonomy` object, let's count the number of weighted pages to which the "suspense" term has been assigned: + +```go-html-template +{{ $taxonomyObject.Count "suspense" }} → 3 +``` diff --git a/docs/content/en/methods/taxonomy/Get.md b/docs/content/en/methods/taxonomy/Get.md new file mode 100644 index 000000000..03c184868 --- /dev/null +++ b/docs/content/en/methods/taxonomy/Get.md @@ -0,0 +1,67 @@ +--- +title: Get +description: Returns a slice of weighted pages to which the given term has been assigned. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.WeightedPages + signatures: [TAXONOMY.Get TERM] +--- + +The `Get` method on a `Taxonomy` object returns a slice of [weighted pages](g) to which the given [term](g) has been assigned. + +{{% include "/_common/methods/taxonomy/get-a-taxonomy-object.md" %}} + +## Get the weighted pages + +Now that we have captured the "genres" `Taxonomy` object, let's get the weighted pages to which the "suspense" term has been assigned: + +```go-html-template +{{ $weightedPages := $taxonomyObject.Get "suspense" }} +``` + +The above is equivalent to: + +```go-html-template +{{ $weightedPages := $taxonomyObject.suspense }} +``` + +But, if the term is not a valid [identifier](g), you cannot use the [chaining](g) syntax. For example, this will throw an error because the identifier contains a hyphen: + +```go-html-template +{{ $weightedPages := $taxonomyObject.my-genre }} +``` + +You could also use the [`index`] function, but the syntax is more verbose: + +```go-html-template +{{ $weightedPages := index $taxonomyObject "my-genre" }} +``` + +To inspect the data structure: + +```go-html-template +<pre>{{ debug.Dump $weightedPages }}</pre> +``` + +## Example + +With this template: + +```go-html-template +{{ $weightedPages := $taxonomyObject.Get "suspense" }} +{{ range $weightedPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} +``` + +Hugo renders: + +```html +<h2><a href="/books/jamaica-inn/">Jamaica inn</a></h2> +<h2><a href="/books/death-on-the-nile/">Death on the nile</a></h2> +<h2><a href="/books/and-then-there-were-none/">And then there were none</a></h2> +``` + +[`index`]: /functions/collections/indexfunction/ diff --git a/docs/content/en/methods/taxonomy/Page.md b/docs/content/en/methods/taxonomy/Page.md new file mode 100644 index 000000000..b0b5d3aff --- /dev/null +++ b/docs/content/en/methods/taxonomy/Page.md @@ -0,0 +1,26 @@ +--- +title: Page +description: Returns the taxonomy page or nil if the taxonomy has no terms. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: page.Page + signatures: [TAXONOMY.Page] +--- + +{{< new-in 0.125.0 />}} + +This `TAXONOMY` method returns nil if the taxonomy has no terms, so you must code defensively: + +```go-html-template +{{ with .Site.Taxonomies.tags.Page }} + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> +{{ end }} +``` + +This is rendered to: + +```html +<a href="/tags/">Tags</a> +``` diff --git a/docs/content/en/methods/taxonomy/_index.md b/docs/content/en/methods/taxonomy/_index.md new file mode 100644 index 000000000..13acdb10c --- /dev/null +++ b/docs/content/en/methods/taxonomy/_index.md @@ -0,0 +1,7 @@ +--- +title: Taxonomy methods +linkTitle: Taxonomy +description: Use these methods with Taxonomy objects. +keywords: [] +aliases: [/variables/taxonomy/] +--- diff --git a/docs/content/en/methods/time/Add.md b/docs/content/en/methods/time/Add.md new file mode 100644 index 000000000..e518a1633 --- /dev/null +++ b/docs/content/en/methods/time/Add.md @@ -0,0 +1,20 @@ +--- +title: Add +description: Returns the given time plus the given duration. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [TIME.Add DURATION] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} + +{{ $d1 = time.ParseDuration "3h20m10s" }} +{{ $d2 = time.ParseDuration "-3h20m10s" }} + +{{ $t.Add $d1 }} → 2023-01-28 03:05:08 -0800 PST +{{ $t.Add $d2 }} → 2023-01-27 20:24:48 -0800 PST +``` diff --git a/docs/content/en/methods/time/AddDate.md b/docs/content/en/methods/time/AddDate.md new file mode 100644 index 000000000..ffc93c712 --- /dev/null +++ b/docs/content/en/methods/time/AddDate.md @@ -0,0 +1,37 @@ +--- +title: AddDate +description: Returns the time corresponding to adding the given number of years, months, and days to the given time.Time value. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [TIME.AddDate YEARS MONTHS DAYS] +aliases: [/functions/adddate] +--- + +```go-html-template +{{ $d := "2022-01-01" | time.AsTime }} + +{{ $d.AddDate 0 0 1 | time.Format "2006-01-02" }} → 2022-01-02 +{{ $d.AddDate 0 1 1 | time.Format "2006-01-02" }} → 2022-02-02 +{{ $d.AddDate 1 1 1 | time.Format "2006-01-02" }} → 2023-02-02 + +{{ $d.AddDate -1 -1 -1 | time.Format "2006-01-02" }} → 2020-11-30 +``` + +> [!note] +> When adding months or years, Hugo normalizes the final `time.Time` value if the resulting day does not exist. For example, adding one month to 31 January produces 2 March or 3 March, depending on the year. +> +> See [this explanation](https://github.com/golang/go/issues/31145#issuecomment-479067967) from the Go team. + +```go-html-template +{{ $d := "2023-01-31" | time.AsTime }} +{{ $d.AddDate 0 1 0 | time.Format "2006-01-02" }} → 2023-03-03 + +{{ $d := "2024-01-31" | time.AsTime }} +{{ $d.AddDate 0 1 0 | time.Format "2006-01-02" }} → 2024-03-02 + +{{ $d := "2024-02-29" | time.AsTime }} +{{ $d.AddDate 1 0 0 | time.Format "2006-01-02" }} → 2025-03-01 +``` diff --git a/docs/content/en/methods/time/After.md b/docs/content/en/methods/time/After.md new file mode 100644 index 000000000..1c8d41f64 --- /dev/null +++ b/docs/content/en/methods/time/After.md @@ -0,0 +1,17 @@ +--- +title: After +description: Reports whether TIME1 is after TIME2. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [TIME1.After TIME2] +--- + +```go-html-template +{{ $t1 := time.AsTime "2023-01-01T17:00:00-08:00" }} +{{ $t2 := time.AsTime "2010-01-01T17:00:00-08:00" }} + +{{ $t1.After $t2 }} → true +``` diff --git a/docs/content/en/methods/time/Before.md b/docs/content/en/methods/time/Before.md new file mode 100644 index 000000000..f6dc3a8e7 --- /dev/null +++ b/docs/content/en/methods/time/Before.md @@ -0,0 +1,16 @@ +--- +title: Before +description: Reports whether TIME1 is before TIME2. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [TIME1.Before TIME2] +--- + +```go-html-template +{{ $t1 := time.AsTime "2023-01-01T17:00:00-08:00" }} +{{ $t2 := time.AsTime "2030-01-01T17:00:00-08:00" }} + +{{ $t1.Before $t2 }} → true diff --git a/docs/content/en/methods/time/Day.md b/docs/content/en/methods/time/Day.md new file mode 100644 index 000000000..e9e67873c --- /dev/null +++ b/docs/content/en/methods/time/Day.md @@ -0,0 +1,15 @@ +--- +title: Day +description: Returns the day of the month of the given time.Time value. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [TIME.Day] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Day }} → 27 +``` diff --git a/docs/content/en/methods/time/Equal.md b/docs/content/en/methods/time/Equal.md new file mode 100644 index 000000000..6db10423c --- /dev/null +++ b/docs/content/en/methods/time/Equal.md @@ -0,0 +1,17 @@ +--- +title: Equal +description: Reports whether TIME1 is equal to TIME2. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [TIME1.Equal TIME2] +--- + +```go-html-template +{{ $t1 := time.AsTime "2023-01-01T17:00:00-08:00" }} +{{ $t2 := time.AsTime "2023-01-01T20:00:00-05:00" }} + +{{ $t1.Equal $t2 }} → true +``` diff --git a/docs/content/en/methods/time/Format.md b/docs/content/en/methods/time/Format.md new file mode 100644 index 000000000..8a484b74e --- /dev/null +++ b/docs/content/en/methods/time/Format.md @@ -0,0 +1,88 @@ +--- +title: Format +description: Returns a textual representation of the time.Time value formatted according to the layout string. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: string + signatures: [TIME.Format LAYOUT] +aliases: [/methods/time/format] +--- + +```go-template +{{ $t := "2023-01-27T23:44:58-08:00" }} +{{ $t = time.AsTime $t }} +{{ $format := "2 Jan 2006" }} + +{{ $t.Format $format }} → 27 Jan 2023 +``` + +> [!note] +> To [localize](g) the return value, use the [`time.Format`] function instead. + +Use the `Format` method with any `time.Time` value, including the four predefined front matter dates: + +```go-html-template +{{ $format := "2 Jan 2006" }} + +{{ .Date.Format $format }} +{{ .PublishDate.Format $format }} +{{ .ExpiryDate.Format $format }} +{{ .Lastmod.Format $format }} +``` + +> [!note] +> Use the [`time.Format`] function to format string representations of dates, and to format raw TOML dates that exclude time and time zone offset. + +## Layout string + +{{% include "/_common/time-layout-string.md" %}} + +## Examples + +Given this front matter: + +{{< code-toggle fm=true >}} +title = "About time" +date = 2023-01-27T23:44:58-08:00 +{{< /code-toggle >}} + +The examples below were rendered in the `America/Los_Angeles` time zone: + +Format string|Result +:--|:-- +`Monday, January 2, 2006`|`Friday, January 27, 2023` +`Mon Jan 2 2006`|`Fri Jan 27 2023` +`January 2006`|`January 2023` +`2006-01-02`|`2023-01-27` +`Monday`|`Friday` +`02 Jan 06 15:04 MST`|`27 Jan 23 23:44 PST` +`Mon, 02 Jan 2006 15:04:05 MST`|`Fri, 27 Jan 2023 23:44:58 PST` +`Mon, 02 Jan 2006 15:04:05 -0700`|`Fri, 27 Jan 2023 23:44:58 -0800` + +## UTC and local time + +Convert and format any `time.Time` value to either Coordinated Universal Time (UTC) or local time. + +```go-html-template +{{ $t := "2023-01-27T23:44:58-08:00" }} +{{ $t = time.AsTime $t }} +{{ $format := "2 Jan 2006 3:04:05 PM MST" }} + +{{ $t.UTC.Format $format }} → 28 Jan 2023 7:44:58 AM UTC +{{ $t.Local.Format $format }} → 27 Jan 2023 11:44:58 PM PST +``` + +## Ordinal representation + +Use the [`humanize`](/functions/inflect/humanize) function to render the day of the month as an ordinal number: + +```go-html-template +{{ $t := "2023-01-27T23:44:58-08:00" }} +{{ $t = time.AsTime $t }} + +{{ humanize $t.Day }} of {{ $t.Format "January 2006" }} → 27th of January 2023 +``` + +[`time.Format`]: /functions/time/format/ diff --git a/docs/content/en/methods/time/Hour.md b/docs/content/en/methods/time/Hour.md new file mode 100644 index 000000000..28ecf62ac --- /dev/null +++ b/docs/content/en/methods/time/Hour.md @@ -0,0 +1,15 @@ +--- +title: Hour +description: Returns the hour within the day of the given time.Time value, in the range [0, 23]. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [TIME.Hour] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Hour }} → 23 +``` diff --git a/docs/content/en/methods/time/IsDST.md b/docs/content/en/methods/time/IsDST.md new file mode 100644 index 000000000..28177b105 --- /dev/null +++ b/docs/content/en/methods/time/IsDST.md @@ -0,0 +1,18 @@ +--- +title: IsDST +description: Reports whether the given time.Time value is in Daylight Savings Time. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [TIME.IsDST] +--- + +```go-html-template +{{ $t1 := time.AsTime "2023-01-01T00:00:00-08:00" }} +{{ $t2 := time.AsTime "2023-07-01T00:00:00-07:00" }} + +{{ $t1.IsDST }} → false +{{ $t2.IsDST }} → true +``` diff --git a/docs/content/en/methods/time/IsZero.md b/docs/content/en/methods/time/IsZero.md new file mode 100644 index 000000000..400172794 --- /dev/null +++ b/docs/content/en/methods/time/IsZero.md @@ -0,0 +1,18 @@ +--- +title: IsZero +description: Reports whether the given time.Time value represents the zero time instant, January 1, year 1, 00:00:00 UTC. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: bool + signatures: [TIME.IsZero] +--- + +````go-html-template +{{ $t1 := time.AsTime "2023-01-01T00:00:00-08:00" }} +{{ $t2 := time.AsTime "0001-01-01T00:00:00-00:00" }} + +{{ $t1.IsZero }} → false +{{ $t2.IsZero }} → true +``` diff --git a/docs/content/en/methods/time/Local.md b/docs/content/en/methods/time/Local.md new file mode 100644 index 000000000..74fe889e0 --- /dev/null +++ b/docs/content/en/methods/time/Local.md @@ -0,0 +1,15 @@ +--- +title: Local +description: Returns the given time.Time value with the location set to local time. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [TIME.Local] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-28T07:44:58+00:00" }} +{{ $t.Local }} → 2023-01-27 23:44:58 -0800 PST +``` diff --git a/docs/content/en/methods/time/Minute.md b/docs/content/en/methods/time/Minute.md new file mode 100644 index 000000000..b53db6d83 --- /dev/null +++ b/docs/content/en/methods/time/Minute.md @@ -0,0 +1,15 @@ +--- +title: Minute +description: Returns the minute offset within the hour of the given time.Time value, in the range [0, 59]. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [TIME.Minute] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Minute }} → 44 +``` diff --git a/docs/content/en/methods/time/Month.md b/docs/content/en/methods/time/Month.md new file mode 100644 index 000000000..b0ccea9c3 --- /dev/null +++ b/docs/content/en/methods/time/Month.md @@ -0,0 +1,24 @@ +--- +title: Month +description: Returns the month of the year of the given time.Time value. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Month + signatures: [TIME.Month] +--- + +To convert the `time.Month` value to a string: + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Month.String }} → January +``` + +To convert the `time.Month` value to an integer. + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Month | int }} → 1 +``` diff --git a/docs/content/en/methods/time/Nanosecond.md b/docs/content/en/methods/time/Nanosecond.md new file mode 100644 index 000000000..d895f9622 --- /dev/null +++ b/docs/content/en/methods/time/Nanosecond.md @@ -0,0 +1,15 @@ +--- +title: Nanosecond +description: Returns the nanosecond offset within the second of the given time.Time value, in the range [0, 999999999]. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [TIME.Nanosecond] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Nanosecond }} → 0 +``` diff --git a/docs/content/en/methods/time/Round.md b/docs/content/en/methods/time/Round.md new file mode 100644 index 000000000..816d41b44 --- /dev/null +++ b/docs/content/en/methods/time/Round.md @@ -0,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"}} + +{{ ($t.Round $d).Format "2006-01-02T15:04:05-00:00" }} → 2023-01-28T00:00:00-00:00 +``` diff --git a/docs/content/en/methods/time/Second.md b/docs/content/en/methods/time/Second.md new file mode 100644 index 000000000..3af086fd3 --- /dev/null +++ b/docs/content/en/methods/time/Second.md @@ -0,0 +1,15 @@ +--- +title: Second +description: Returns the second offset within the minute of the given time.Time value, in the range [0, 59]. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [TIME.Second] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Second }} → 58 +``` diff --git a/docs/content/en/methods/time/Sub.md b/docs/content/en/methods/time/Sub.md new file mode 100644 index 000000000..d48bf3467 --- /dev/null +++ b/docs/content/en/methods/time/Sub.md @@ -0,0 +1,17 @@ +--- +title: Sub +description: Returns the duration computed by subtracting TIME2 from TIME1. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Duration + signatures: [TIME1.Sub TIME2] +--- + +```go-html-template +{{ $t1 := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t2 := time.AsTime "2023-01-26T22:34:38-08:00" }} + +{{ $t1.Sub $t2 }} → 25h10m20s +``` diff --git a/docs/content/en/methods/time/Truncate.md b/docs/content/en/methods/time/Truncate.md new file mode 100644 index 000000000..b797afec0 --- /dev/null +++ b/docs/content/en/methods/time/Truncate.md @@ -0,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"}} + +{{ ($t.Truncate $d).Format "2006-01-02T15:04:05-00:00" }} → 2023-01-27T23:00:00-00:00 +``` diff --git a/docs/content/en/methods/time/UTC.md b/docs/content/en/methods/time/UTC.md new file mode 100644 index 000000000..e131a003e --- /dev/null +++ b/docs/content/en/methods/time/UTC.md @@ -0,0 +1,14 @@ +--- +title: UTC +description: Returns the given time.Time value with the location set to UTC. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Time + signatures: [TIME.UTC] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.UTC }} → 2023-01-28 07:44:58 +0000 UTC diff --git a/docs/content/en/methods/time/Unix.md b/docs/content/en/methods/time/Unix.md new file mode 100644 index 000000000..73deb524e --- /dev/null +++ b/docs/content/en/methods/time/Unix.md @@ -0,0 +1,17 @@ +--- +title: Unix +description: Returns the given time.Time value expressed as the number of seconds elapsed since January 1, 1970 UTC. +categories: [] +params: + functions_and_methods: + returnType: int64 + signatures: [TIME.Unix] +aliases: [/functions/unix] +--- + +See [Unix epoch](https://en.wikipedia.org/wiki/Unix_time). + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Unix }} → 1674891898 +``` diff --git a/docs/content/en/methods/time/UnixMicro.md b/docs/content/en/methods/time/UnixMicro.md new file mode 100644 index 000000000..fadb0916c --- /dev/null +++ b/docs/content/en/methods/time/UnixMicro.md @@ -0,0 +1,17 @@ +--- +title: UnixMicro +description: Returns the given time.Time value expressed as the number of microseconds elapsed since January 1, 1970 UTC. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int64 + signatures: [TIME.UnixMicro] +--- + +See [Unix epoch](https://en.wikipedia.org/wiki/Unix_time). + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.UnixMicro }} → 1674891898000000 +``` diff --git a/docs/content/en/methods/time/UnixMilli.md b/docs/content/en/methods/time/UnixMilli.md new file mode 100644 index 000000000..9d2261d91 --- /dev/null +++ b/docs/content/en/methods/time/UnixMilli.md @@ -0,0 +1,17 @@ +--- +title: UnixMilli +description: Returns the given time.Time value expressed as the number of milliseconds elapsed since January 1, 1970 UTC. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int64 + signatures: [TIME.UnixMilli] +--- + +See [Unix epoch](https://en.wikipedia.org/wiki/Unix_time). + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.UnixMilli }} → 1674891898000 +``` diff --git a/docs/content/en/methods/time/UnixNano.md b/docs/content/en/methods/time/UnixNano.md new file mode 100644 index 000000000..4159ddee2 --- /dev/null +++ b/docs/content/en/methods/time/UnixNano.md @@ -0,0 +1,17 @@ +--- +title: UnixNano +description: Returns the given time.Time value expressed as the number of nanoseconds elapsed since January 1, 1970 UTC. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int64 + signatures: [TIME.UnixNano] +--- + +See [Unix epoch](https://en.wikipedia.org/wiki/Unix_time). + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.UnixNano }} → 1674891898000000000 +``` diff --git a/docs/content/en/methods/time/Weekday.md b/docs/content/en/methods/time/Weekday.md new file mode 100644 index 000000000..da939ff87 --- /dev/null +++ b/docs/content/en/methods/time/Weekday.md @@ -0,0 +1,23 @@ +--- +title: Weekday +description: Returns the day of the week of the given time.Time value. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: time.Weekday + signatures: [TIME.Weekday] +--- + +To convert the `time.Weekday` value to a string: + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Weekday.String }} → Friday +``` + +To convert the `time.Weekday` value to an integer. + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Weekday | int }} → 5 diff --git a/docs/content/en/methods/time/Year.md b/docs/content/en/methods/time/Year.md new file mode 100644 index 000000000..3f647ea34 --- /dev/null +++ b/docs/content/en/methods/time/Year.md @@ -0,0 +1,15 @@ +--- +title: Year +description: Returns the year of the given time.Time value. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [TIME.Year] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.Year }} → 2023 +``` diff --git a/docs/content/en/methods/time/YearDay.md b/docs/content/en/methods/time/YearDay.md new file mode 100644 index 000000000..a93158b45 --- /dev/null +++ b/docs/content/en/methods/time/YearDay.md @@ -0,0 +1,15 @@ +--- +title: YearDay +description: Returns the day of the year of the given time.Time value, in the range [1, 365] for non-leap years, and [1, 366] in leap years. +categories: [] +keywords: [] +params: + functions_and_methods: + returnType: int + signatures: [TIME.YearDay] +--- + +```go-html-template +{{ $t := time.AsTime "2023-01-27T23:44:58-08:00" }} +{{ $t.YearDay }} → 27 +``` diff --git a/docs/content/en/methods/time/_index.md b/docs/content/en/methods/time/_index.md new file mode 100644 index 000000000..8114664d3 --- /dev/null +++ b/docs/content/en/methods/time/_index.md @@ -0,0 +1,7 @@ +--- +title: Time methods +linkTitle: Time +description: Use these methods with time.Time values. +categories: [] +keywords: [] +--- diff --git a/docs/content/en/news/_content.gotmpl b/docs/content/en/news/_content.gotmpl new file mode 100644 index 000000000..f979c9adc --- /dev/null +++ b/docs/content/en/news/_content.gotmpl @@ -0,0 +1,30 @@ +{{/* Get releases from GitHub. */}} +{{ $u := "https://api.github.com/repos/gohugoio/hugo/releases" }} +{{ $releases := partial "helpers/funcs/get-remote-data.html" $u }} +{{ $releases = where $releases "draft" false }} +{{ $releases = where $releases "prerelease" false }} + +{{/* Add pages. */}} +{{ range $releases | first 24 }} + {{ $publishDate := .published_at | time.AsTime }} + + {{/* Correct the v0.138.0 release date. See https://github.com/gohugoio/hugo/issues/13066. */}} + {{ if eq .name "v0.138.0" }} + {{ $publishDate = "2024-11-06T11:22:34Z" }} + {{ end }} + + {{ $content := dict "mediaType" "text/markdown" "value" "" }} + {{ $dates := dict "publishDate" (time.AsTime $publishDate) }} + {{ $params := dict "permalink" .html_url }} + {{ $build := dict "render" "never" "list" "local" }} + {{ $page := dict + "build" $build + "content" $content + "dates" $dates + "kind" "page" + "params" $params + "path" .name + "title" (printf "Release %s" .name) + }} + {{ $.AddPage $page }} +{{ end }} diff --git a/docs/content/en/news/_index.md b/docs/content/en/news/_index.md new file mode 100644 index 000000000..23c082cb7 --- /dev/null +++ b/docs/content/en/news/_index.md @@ -0,0 +1,9 @@ +--- +title: News +description: Stay up-to-date with the latest news and announcements. +outputs: + - html + - rss +weight: 10 +aliases: [/release-notes/] +--- diff --git a/docs/content/en/quick-reference/_index.md b/docs/content/en/quick-reference/_index.md new file mode 100644 index 000000000..98f978f4f --- /dev/null +++ b/docs/content/en/quick-reference/_index.md @@ -0,0 +1,8 @@ +--- +title: Quick reference guides +linkTitle: Quick reference +description: Use these quick reference guides for quick access to key information. +categories: [] +keywords: [] +weight: 10 +--- diff --git a/docs/content/en/quick-reference/emojis.md b/docs/content/en/quick-reference/emojis.md new file mode 100644 index 000000000..15c2e60e6 --- /dev/null +++ b/docs/content/en/quick-reference/emojis.md @@ -0,0 +1,1679 @@ +--- +title: Emojis +description: Include emoji shortcodes in your Markdown or templates. +categories: [] +keywords: [] +--- + +## Attribution + +This quick reference guide was generated using the [ikatyang/emoji-cheat-sheet] project which reads from the [GitHub Emoji API] and the [Unicode Full Emoji List]. + +Note that GitHub [custom emoji] are not supported. + +[custom emoji]: #github-custom-emoji +[github emoji api]: https://api.github.com/emojis +[ikatyang/emoji-cheat-sheet]: https://github.com/ikatyang/emoji-cheat-sheet/ +[unicode full emoji list]: https://unicode.org/emoji/charts/full-emoji-list.html + +## Usage + +Configure Hugo to enable emoji processing in Markdown: + +{{< code-toggle file=hugo >}} +enableEmoji = true +{{< /code-toggle >}} + +With emoji processing enabled, this Markdown: + +```md +Hello! :wave: +``` + +Is rendered to: + +```html +Hello! 👋 +``` + +And in your browser... Hello! :wave: + +To process an emoji shortcode from within a template, use the [`emojify`] function or pass the string through the [`RenderString`] method on a `Page` object: + +```go-html-template +{{ "Hello! :wave:" | .RenderString }} +``` + +[`emojify`]: /functions/transform/emojify/ +[`RenderString`]: /methods/page/renderstring/ + +<!-- +To generate the sections below: + + git clone https://github.com/ikatyang/emoji-cheat-sheet + cd emoji-cheat-sheet + npm install + npm run generate + +Then... + + 1. Copy and paste from README.md + 2. Search/replace (regex) "^###\s" with "## " + 3. Search/replace "^####\s " with "### " + 4. Search/replace (regex) "<br />" "" +--> + +## Table of Contents + +- [Smileys & Emotion](#smileys--emotion) +- [People & Body](#people--body) +- [Animals & Nature](#animals--nature) +- [Food & Drink](#food--drink) +- [Travel & Places](#travel--places) +- [Activities](#activities) +- [Objects](#objects) +- [Symbols](#symbols) +- [Flags](#flags) +- [GitHub Custom Emoji](#github-custom-emoji) + +## Smileys & Emotion + +- [Face Smiling](#face-smiling) +- [Face Affection](#face-affection) +- [Face Tongue](#face-tongue) +- [Face Hand](#face-hand) +- [Face Neutral Skeptical](#face-neutral-skeptical) +- [Face Sleepy](#face-sleepy) +- [Face Unwell](#face-unwell) +- [Face Hat](#face-hat) +- [Face Glasses](#face-glasses) +- [Face Concerned](#face-concerned) +- [Face Negative](#face-negative) +- [Face Costume](#face-costume) +- [Cat Face](#cat-face) +- [Monkey Face](#monkey-face) +- [Heart](#heart) +- [Emotion](#emotion) + +### Face Smiling + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :grinning: | `:grinning:` | :smiley: | `:smiley:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :smile: | `:smile:` | :grin: | `:grin:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :laughing: | `:laughing:` `:satisfied:` | :sweat_smile: | `:sweat_smile:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :rofl: | `:rofl:` | :joy: | `:joy:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :slightly_smiling_face: | `:slightly_smiling_face:` | :upside_down_face: | `:upside_down_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :melting_face: | `:melting_face:` | :wink: | `:wink:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :blush: | `:blush:` | :innocent: | `:innocent:` | [top](#table-of-contents) | + +### Face Affection + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :smiling_face_with_three_hearts: | `:smiling_face_with_three_hearts:` | :heart_eyes: | `:heart_eyes:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :star_struck: | `:star_struck:` | :kissing_heart: | `:kissing_heart:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :kissing: | `:kissing:` | :relaxed: | `:relaxed:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :kissing_closed_eyes: | `:kissing_closed_eyes:` | :kissing_smiling_eyes: | `:kissing_smiling_eyes:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :smiling_face_with_tear: | `:smiling_face_with_tear:` | | | [top](#table-of-contents) | + +### Face Tongue + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :yum: | `:yum:` | :stuck_out_tongue: | `:stuck_out_tongue:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :stuck_out_tongue_winking_eye: | `:stuck_out_tongue_winking_eye:` | :zany_face: | `:zany_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :stuck_out_tongue_closed_eyes: | `:stuck_out_tongue_closed_eyes:` | :money_mouth_face: | `:money_mouth_face:` | [top](#table-of-contents) | + +### Face Hand + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :hugs: | `:hugs:` | :hand_over_mouth: | `:hand_over_mouth:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :face_with_open_eyes_and_hand_over_mouth: | `:face_with_open_eyes_and_hand_over_mouth:` | :face_with_peeking_eye: | `:face_with_peeking_eye:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :shushing_face: | `:shushing_face:` | :thinking: | `:thinking:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :saluting_face: | `:saluting_face:` | | | [top](#table-of-contents) | + +### Face Neutral Skeptical + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :zipper_mouth_face: | `:zipper_mouth_face:` | :raised_eyebrow: | `:raised_eyebrow:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :neutral_face: | `:neutral_face:` | :expressionless: | `:expressionless:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :no_mouth: | `:no_mouth:` | :dotted_line_face: | `:dotted_line_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :face_in_clouds: | `:face_in_clouds:` | :smirk: | `:smirk:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :unamused: | `:unamused:` | :roll_eyes: | `:roll_eyes:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :grimacing: | `:grimacing:` | :face_exhaling: | `:face_exhaling:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :lying_face: | `:lying_face:` | :shaking_face: | `:shaking_face:` | [top](#table-of-contents) | + +### Face Sleepy + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :relieved: | `:relieved:` | :pensive: | `:pensive:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :sleepy: | `:sleepy:` | :drooling_face: | `:drooling_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :sleeping: | `:sleeping:` | | | [top](#table-of-contents) | + +### Face Unwell + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :mask: | `:mask:` | :face_with_thermometer: | `:face_with_thermometer:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :face_with_head_bandage: | `:face_with_head_bandage:` | :nauseated_face: | `:nauseated_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :vomiting_face: | `:vomiting_face:` | :sneezing_face: | `:sneezing_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :hot_face: | `:hot_face:` | :cold_face: | `:cold_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :woozy_face: | `:woozy_face:` | :dizzy_face: | `:dizzy_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :face_with_spiral_eyes: | `:face_with_spiral_eyes:` | :exploding_head: | `:exploding_head:` | [top](#table-of-contents) | + +### Face Hat + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :cowboy_hat_face: | `:cowboy_hat_face:` | :partying_face: | `:partying_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :disguised_face: | `:disguised_face:` | | | [top](#table-of-contents) | + +### Face Glasses + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :sunglasses: | `:sunglasses:` | :nerd_face: | `:nerd_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :monocle_face: | `:monocle_face:` | | | [top](#table-of-contents) | + +### Face Concerned + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :confused: | `:confused:` | :face_with_diagonal_mouth: | `:face_with_diagonal_mouth:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :worried: | `:worried:` | :slightly_frowning_face: | `:slightly_frowning_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :frowning_face: | `:frowning_face:` | :open_mouth: | `:open_mouth:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :hushed: | `:hushed:` | :astonished: | `:astonished:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :flushed: | `:flushed:` | :pleading_face: | `:pleading_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :face_holding_back_tears: | `:face_holding_back_tears:` | :frowning: | `:frowning:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :anguished: | `:anguished:` | :fearful: | `:fearful:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :cold_sweat: | `:cold_sweat:` | :disappointed_relieved: | `:disappointed_relieved:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :cry: | `:cry:` | :sob: | `:sob:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :scream: | `:scream:` | :confounded: | `:confounded:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :persevere: | `:persevere:` | :disappointed: | `:disappointed:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :sweat: | `:sweat:` | :weary: | `:weary:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :tired_face: | `:tired_face:` | :yawning_face: | `:yawning_face:` | [top](#table-of-contents) | + +### Face Negative + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :triumph: | `:triumph:` | :pout: | `:pout:` `:rage:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :angry: | `:angry:` | :cursing_face: | `:cursing_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :smiling_imp: | `:smiling_imp:` | :imp: | `:imp:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :skull: | `:skull:` | :skull_and_crossbones: | `:skull_and_crossbones:` | [top](#table-of-contents) | + +### Face Costume + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :hankey: | `:hankey:` `:poop:` `:shit:` | :clown_face: | `:clown_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :japanese_ogre: | `:japanese_ogre:` | :japanese_goblin: | `:japanese_goblin:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :ghost: | `:ghost:` | :alien: | `:alien:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :space_invader: | `:space_invader:` | :robot: | `:robot:` | [top](#table-of-contents) | + +### Cat Face + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :smiley_cat: | `:smiley_cat:` | :smile_cat: | `:smile_cat:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :joy_cat: | `:joy_cat:` | :heart_eyes_cat: | `:heart_eyes_cat:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :smirk_cat: | `:smirk_cat:` | :kissing_cat: | `:kissing_cat:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :scream_cat: | `:scream_cat:` | :crying_cat_face: | `:crying_cat_face:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :pouting_cat: | `:pouting_cat:` | | | [top](#table-of-contents) | + +### Monkey Face + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :see_no_evil: | `:see_no_evil:` | :hear_no_evil: | `:hear_no_evil:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :speak_no_evil: | `:speak_no_evil:` | | | [top](#table-of-contents) | + +### Heart + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :love_letter: | `:love_letter:` | :cupid: | `:cupid:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :gift_heart: | `:gift_heart:` | :sparkling_heart: | `:sparkling_heart:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :heartpulse: | `:heartpulse:` | :heartbeat: | `:heartbeat:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :revolving_hearts: | `:revolving_hearts:` | :two_hearts: | `:two_hearts:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :heart_decoration: | `:heart_decoration:` | :heavy_heart_exclamation: | `:heavy_heart_exclamation:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :broken_heart: | `:broken_heart:` | :heart_on_fire: | `:heart_on_fire:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :mending_heart: | `:mending_heart:` | :heart: | `:heart:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :pink_heart: | `:pink_heart:` | :orange_heart: | `:orange_heart:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :yellow_heart: | `:yellow_heart:` | :green_heart: | `:green_heart:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :blue_heart: | `:blue_heart:` | :light_blue_heart: | `:light_blue_heart:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :purple_heart: | `:purple_heart:` | :brown_heart: | `:brown_heart:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :black_heart: | `:black_heart:` | :grey_heart: | `:grey_heart:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :white_heart: | `:white_heart:` | | | [top](#table-of-contents) | + +### Emotion + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#smileys--emotion) | :kiss: | `:kiss:` | :100: | `:100:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :anger: | `:anger:` | :boom: | `:boom:` `:collision:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :dizzy: | `:dizzy:` | :sweat_drops: | `:sweat_drops:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :dash: | `:dash:` | :hole: | `:hole:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :speech_balloon: | `:speech_balloon:` | :eye_speech_bubble: | `:eye_speech_bubble:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :left_speech_bubble: | `:left_speech_bubble:` | :right_anger_bubble: | `:right_anger_bubble:` | [top](#table-of-contents) | +| [top](#smileys--emotion) | :thought_balloon: | `:thought_balloon:` | :zzz: | `:zzz:` | [top](#table-of-contents) | + +## People & Body + +- [Hand Fingers Open](#hand-fingers-open) +- [Hand Fingers Partial](#hand-fingers-partial) +- [Hand Single Finger](#hand-single-finger) +- [Hand Fingers Closed](#hand-fingers-closed) +- [Hands](#hands) +- [Hand Prop](#hand-prop) +- [Body Parts](#body-parts) +- [Person](#person) +- [Person Gesture](#person-gesture) +- [Person Role](#person-role) +- [Person Fantasy](#person-fantasy) +- [Person Activity](#person-activity) +- [Person Sport](#person-sport) +- [Person Resting](#person-resting) +- [Family](#family) +- [Person Symbol](#person-symbol) + +### Hand Fingers Open + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :wave: | `:wave:` | :raised_back_of_hand: | `:raised_back_of_hand:` | [top](#table-of-contents) | +| [top](#people--body) | :raised_hand_with_fingers_splayed: | `:raised_hand_with_fingers_splayed:` | :hand: | `:hand:` `:raised_hand:` | [top](#table-of-contents) | +| [top](#people--body) | :vulcan_salute: | `:vulcan_salute:` | :rightwards_hand: | `:rightwards_hand:` | [top](#table-of-contents) | +| [top](#people--body) | :leftwards_hand: | `:leftwards_hand:` | :palm_down_hand: | `:palm_down_hand:` | [top](#table-of-contents) | +| [top](#people--body) | :palm_up_hand: | `:palm_up_hand:` | :leftwards_pushing_hand: | `:leftwards_pushing_hand:` | [top](#table-of-contents) | +| [top](#people--body) | :rightwards_pushing_hand: | `:rightwards_pushing_hand:` | | | [top](#table-of-contents) | + +### Hand Fingers Partial + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :ok_hand: | `:ok_hand:` | :pinched_fingers: | `:pinched_fingers:` | [top](#table-of-contents) | +| [top](#people--body) | :pinching_hand: | `:pinching_hand:` | :v: | `:v:` | [top](#table-of-contents) | +| [top](#people--body) | :crossed_fingers: | `:crossed_fingers:` | :hand_with_index_finger_and_thumb_crossed: | `:hand_with_index_finger_and_thumb_crossed:` | [top](#table-of-contents) | +| [top](#people--body) | :love_you_gesture: | `:love_you_gesture:` | :metal: | `:metal:` | [top](#table-of-contents) | +| [top](#people--body) | :call_me_hand: | `:call_me_hand:` | | | [top](#table-of-contents) | + +### Hand Single Finger + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :point_left: | `:point_left:` | :point_right: | `:point_right:` | [top](#table-of-contents) | +| [top](#people--body) | :point_up_2: | `:point_up_2:` | :fu: | `:fu:` `:middle_finger:` | [top](#table-of-contents) | +| [top](#people--body) | :point_down: | `:point_down:` | :point_up: | `:point_up:` | [top](#table-of-contents) | +| [top](#people--body) | :index_pointing_at_the_viewer: | `:index_pointing_at_the_viewer:` | | | [top](#table-of-contents) | + +### Hand Fingers Closed + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :+1: | `:+1:` `:thumbsup:` | :-1: | `:-1:` `:thumbsdown:` | [top](#table-of-contents) | +| [top](#people--body) | :fist: | `:fist:` `:fist_raised:` | :facepunch: | `:facepunch:` `:fist_oncoming:` `:punch:` | [top](#table-of-contents) | +| [top](#people--body) | :fist_left: | `:fist_left:` | :fist_right: | `:fist_right:` | [top](#table-of-contents) | + +### Hands + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :clap: | `:clap:` | :raised_hands: | `:raised_hands:` | [top](#table-of-contents) | +| [top](#people--body) | :heart_hands: | `:heart_hands:` | :open_hands: | `:open_hands:` | [top](#table-of-contents) | +| [top](#people--body) | :palms_up_together: | `:palms_up_together:` | :handshake: | `:handshake:` | [top](#table-of-contents) | +| [top](#people--body) | :pray: | `:pray:` | | | [top](#table-of-contents) | + +### Hand Prop + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :writing_hand: | `:writing_hand:` | :nail_care: | `:nail_care:` | [top](#table-of-contents) | +| [top](#people--body) | :selfie: | `:selfie:` | | | [top](#table-of-contents) | + +### Body Parts + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :muscle: | `:muscle:` | :mechanical_arm: | `:mechanical_arm:` | [top](#table-of-contents) | +| [top](#people--body) | :mechanical_leg: | `:mechanical_leg:` | :leg: | `:leg:` | [top](#table-of-contents) | +| [top](#people--body) | :foot: | `:foot:` | :ear: | `:ear:` | [top](#table-of-contents) | +| [top](#people--body) | :ear_with_hearing_aid: | `:ear_with_hearing_aid:` | :nose: | `:nose:` | [top](#table-of-contents) | +| [top](#people--body) | :brain: | `:brain:` | :anatomical_heart: | `:anatomical_heart:` | [top](#table-of-contents) | +| [top](#people--body) | :lungs: | `:lungs:` | :tooth: | `:tooth:` | [top](#table-of-contents) | +| [top](#people--body) | :bone: | `:bone:` | :eyes: | `:eyes:` | [top](#table-of-contents) | +| [top](#people--body) | :eye: | `:eye:` | :tongue: | `:tongue:` | [top](#table-of-contents) | +| [top](#people--body) | :lips: | `:lips:` | :biting_lip: | `:biting_lip:` | [top](#table-of-contents) | + +### Person + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :baby: | `:baby:` | :child: | `:child:` | [top](#table-of-contents) | +| [top](#people--body) | :boy: | `:boy:` | :girl: | `:girl:` | [top](#table-of-contents) | +| [top](#people--body) | :adult: | `:adult:` | :blond_haired_person: | `:blond_haired_person:` | [top](#table-of-contents) | +| [top](#people--body) | :man: | `:man:` | :bearded_person: | `:bearded_person:` | [top](#table-of-contents) | +| [top](#people--body) | :man_beard: | `:man_beard:` | :woman_beard: | `:woman_beard:` | [top](#table-of-contents) | +| [top](#people--body) | :red_haired_man: | `:red_haired_man:` | :curly_haired_man: | `:curly_haired_man:` | [top](#table-of-contents) | +| [top](#people--body) | :white_haired_man: | `:white_haired_man:` | :bald_man: | `:bald_man:` | [top](#table-of-contents) | +| [top](#people--body) | :woman: | `:woman:` | :red_haired_woman: | `:red_haired_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :person_red_hair: | `:person_red_hair:` | :curly_haired_woman: | `:curly_haired_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :person_curly_hair: | `:person_curly_hair:` | :white_haired_woman: | `:white_haired_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :person_white_hair: | `:person_white_hair:` | :bald_woman: | `:bald_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :person_bald: | `:person_bald:` | :blond_haired_woman: | `:blond_haired_woman:` `:blonde_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :blond_haired_man: | `:blond_haired_man:` | :older_adult: | `:older_adult:` | [top](#table-of-contents) | +| [top](#people--body) | :older_man: | `:older_man:` | :older_woman: | `:older_woman:` | [top](#table-of-contents) | + +### Person Gesture + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :frowning_person: | `:frowning_person:` | :frowning_man: | `:frowning_man:` | [top](#table-of-contents) | +| [top](#people--body) | :frowning_woman: | `:frowning_woman:` | :pouting_face: | `:pouting_face:` | [top](#table-of-contents) | +| [top](#people--body) | :pouting_man: | `:pouting_man:` | :pouting_woman: | `:pouting_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :no_good: | `:no_good:` | :ng_man: | `:ng_man:` `:no_good_man:` | [top](#table-of-contents) | +| [top](#people--body) | :ng_woman: | `:ng_woman:` `:no_good_woman:` | :ok_person: | `:ok_person:` | [top](#table-of-contents) | +| [top](#people--body) | :ok_man: | `:ok_man:` | :ok_woman: | `:ok_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :information_desk_person: | `:information_desk_person:` `:tipping_hand_person:` | :sassy_man: | `:sassy_man:` `:tipping_hand_man:` | [top](#table-of-contents) | +| [top](#people--body) | :sassy_woman: | `:sassy_woman:` `:tipping_hand_woman:` | :raising_hand: | `:raising_hand:` | [top](#table-of-contents) | +| [top](#people--body) | :raising_hand_man: | `:raising_hand_man:` | :raising_hand_woman: | `:raising_hand_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :deaf_person: | `:deaf_person:` | :deaf_man: | `:deaf_man:` | [top](#table-of-contents) | +| [top](#people--body) | :deaf_woman: | `:deaf_woman:` | :bow: | `:bow:` | [top](#table-of-contents) | +| [top](#people--body) | :bowing_man: | `:bowing_man:` | :bowing_woman: | `:bowing_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :facepalm: | `:facepalm:` | :man_facepalming: | `:man_facepalming:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_facepalming: | `:woman_facepalming:` | :shrug: | `:shrug:` | [top](#table-of-contents) | +| [top](#people--body) | :man_shrugging: | `:man_shrugging:` | :woman_shrugging: | `:woman_shrugging:` | [top](#table-of-contents) | + +### Person Role + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :health_worker: | `:health_worker:` | :man_health_worker: | `:man_health_worker:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_health_worker: | `:woman_health_worker:` | :student: | `:student:` | [top](#table-of-contents) | +| [top](#people--body) | :man_student: | `:man_student:` | :woman_student: | `:woman_student:` | [top](#table-of-contents) | +| [top](#people--body) | :teacher: | `:teacher:` | :man_teacher: | `:man_teacher:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_teacher: | `:woman_teacher:` | :judge: | `:judge:` | [top](#table-of-contents) | +| [top](#people--body) | :man_judge: | `:man_judge:` | :woman_judge: | `:woman_judge:` | [top](#table-of-contents) | +| [top](#people--body) | :farmer: | `:farmer:` | :man_farmer: | `:man_farmer:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_farmer: | `:woman_farmer:` | :cook: | `:cook:` | [top](#table-of-contents) | +| [top](#people--body) | :man_cook: | `:man_cook:` | :woman_cook: | `:woman_cook:` | [top](#table-of-contents) | +| [top](#people--body) | :mechanic: | `:mechanic:` | :man_mechanic: | `:man_mechanic:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_mechanic: | `:woman_mechanic:` | :factory_worker: | `:factory_worker:` | [top](#table-of-contents) | +| [top](#people--body) | :man_factory_worker: | `:man_factory_worker:` | :woman_factory_worker: | `:woman_factory_worker:` | [top](#table-of-contents) | +| [top](#people--body) | :office_worker: | `:office_worker:` | :man_office_worker: | `:man_office_worker:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_office_worker: | `:woman_office_worker:` | :scientist: | `:scientist:` | [top](#table-of-contents) | +| [top](#people--body) | :man_scientist: | `:man_scientist:` | :woman_scientist: | `:woman_scientist:` | [top](#table-of-contents) | +| [top](#people--body) | :technologist: | `:technologist:` | :man_technologist: | `:man_technologist:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_technologist: | `:woman_technologist:` | :singer: | `:singer:` | [top](#table-of-contents) | +| [top](#people--body) | :man_singer: | `:man_singer:` | :woman_singer: | `:woman_singer:` | [top](#table-of-contents) | +| [top](#people--body) | :artist: | `:artist:` | :man_artist: | `:man_artist:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_artist: | `:woman_artist:` | :pilot: | `:pilot:` | [top](#table-of-contents) | +| [top](#people--body) | :man_pilot: | `:man_pilot:` | :woman_pilot: | `:woman_pilot:` | [top](#table-of-contents) | +| [top](#people--body) | :astronaut: | `:astronaut:` | :man_astronaut: | `:man_astronaut:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_astronaut: | `:woman_astronaut:` | :firefighter: | `:firefighter:` | [top](#table-of-contents) | +| [top](#people--body) | :man_firefighter: | `:man_firefighter:` | :woman_firefighter: | `:woman_firefighter:` | [top](#table-of-contents) | +| [top](#people--body) | :cop: | `:cop:` `:police_officer:` | :policeman: | `:policeman:` | [top](#table-of-contents) | +| [top](#people--body) | :policewoman: | `:policewoman:` | :detective: | `:detective:` | [top](#table-of-contents) | +| [top](#people--body) | :male_detective: | `:male_detective:` | :female_detective: | `:female_detective:` | [top](#table-of-contents) | +| [top](#people--body) | :guard: | `:guard:` | :guardsman: | `:guardsman:` | [top](#table-of-contents) | +| [top](#people--body) | :guardswoman: | `:guardswoman:` | :ninja: | `:ninja:` | [top](#table-of-contents) | +| [top](#people--body) | :construction_worker: | `:construction_worker:` | :construction_worker_man: | `:construction_worker_man:` | [top](#table-of-contents) | +| [top](#people--body) | :construction_worker_woman: | `:construction_worker_woman:` | :person_with_crown: | `:person_with_crown:` | [top](#table-of-contents) | +| [top](#people--body) | :prince: | `:prince:` | :princess: | `:princess:` | [top](#table-of-contents) | +| [top](#people--body) | :person_with_turban: | `:person_with_turban:` | :man_with_turban: | `:man_with_turban:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_with_turban: | `:woman_with_turban:` | :man_with_gua_pi_mao: | `:man_with_gua_pi_mao:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_with_headscarf: | `:woman_with_headscarf:` | :person_in_tuxedo: | `:person_in_tuxedo:` | [top](#table-of-contents) | +| [top](#people--body) | :man_in_tuxedo: | `:man_in_tuxedo:` | :woman_in_tuxedo: | `:woman_in_tuxedo:` | [top](#table-of-contents) | +| [top](#people--body) | :person_with_veil: | `:person_with_veil:` | :man_with_veil: | `:man_with_veil:` | [top](#table-of-contents) | +| [top](#people--body) | :bride_with_veil: | `:bride_with_veil:` `:woman_with_veil:` | :pregnant_woman: | `:pregnant_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :pregnant_man: | `:pregnant_man:` | :pregnant_person: | `:pregnant_person:` | [top](#table-of-contents) | +| [top](#people--body) | :breast_feeding: | `:breast_feeding:` | :woman_feeding_baby: | `:woman_feeding_baby:` | [top](#table-of-contents) | +| [top](#people--body) | :man_feeding_baby: | `:man_feeding_baby:` | :person_feeding_baby: | `:person_feeding_baby:` | [top](#table-of-contents) | + +### Person Fantasy + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :angel: | `:angel:` | :santa: | `:santa:` | [top](#table-of-contents) | +| [top](#people--body) | :mrs_claus: | `:mrs_claus:` | :mx_claus: | `:mx_claus:` | [top](#table-of-contents) | +| [top](#people--body) | :superhero: | `:superhero:` | :superhero_man: | `:superhero_man:` | [top](#table-of-contents) | +| [top](#people--body) | :superhero_woman: | `:superhero_woman:` | :supervillain: | `:supervillain:` | [top](#table-of-contents) | +| [top](#people--body) | :supervillain_man: | `:supervillain_man:` | :supervillain_woman: | `:supervillain_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :mage: | `:mage:` | :mage_man: | `:mage_man:` | [top](#table-of-contents) | +| [top](#people--body) | :mage_woman: | `:mage_woman:` | :fairy: | `:fairy:` | [top](#table-of-contents) | +| [top](#people--body) | :fairy_man: | `:fairy_man:` | :fairy_woman: | `:fairy_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :vampire: | `:vampire:` | :vampire_man: | `:vampire_man:` | [top](#table-of-contents) | +| [top](#people--body) | :vampire_woman: | `:vampire_woman:` | :merperson: | `:merperson:` | [top](#table-of-contents) | +| [top](#people--body) | :merman: | `:merman:` | :mermaid: | `:mermaid:` | [top](#table-of-contents) | +| [top](#people--body) | :elf: | `:elf:` | :elf_man: | `:elf_man:` | [top](#table-of-contents) | +| [top](#people--body) | :elf_woman: | `:elf_woman:` | :genie: | `:genie:` | [top](#table-of-contents) | +| [top](#people--body) | :genie_man: | `:genie_man:` | :genie_woman: | `:genie_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :zombie: | `:zombie:` | :zombie_man: | `:zombie_man:` | [top](#table-of-contents) | +| [top](#people--body) | :zombie_woman: | `:zombie_woman:` | :troll: | `:troll:` | [top](#table-of-contents) | + +### Person Activity + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :massage: | `:massage:` | :massage_man: | `:massage_man:` | [top](#table-of-contents) | +| [top](#people--body) | :massage_woman: | `:massage_woman:` | :haircut: | `:haircut:` | [top](#table-of-contents) | +| [top](#people--body) | :haircut_man: | `:haircut_man:` | :haircut_woman: | `:haircut_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :walking: | `:walking:` | :walking_man: | `:walking_man:` | [top](#table-of-contents) | +| [top](#people--body) | :walking_woman: | `:walking_woman:` | :standing_person: | `:standing_person:` | [top](#table-of-contents) | +| [top](#people--body) | :standing_man: | `:standing_man:` | :standing_woman: | `:standing_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :kneeling_person: | `:kneeling_person:` | :kneeling_man: | `:kneeling_man:` | [top](#table-of-contents) | +| [top](#people--body) | :kneeling_woman: | `:kneeling_woman:` | :person_with_probing_cane: | `:person_with_probing_cane:` | [top](#table-of-contents) | +| [top](#people--body) | :man_with_probing_cane: | `:man_with_probing_cane:` | :woman_with_probing_cane: | `:woman_with_probing_cane:` | [top](#table-of-contents) | +| [top](#people--body) | :person_in_motorized_wheelchair: | `:person_in_motorized_wheelchair:` | :man_in_motorized_wheelchair: | `:man_in_motorized_wheelchair:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_in_motorized_wheelchair: | `:woman_in_motorized_wheelchair:` | :person_in_manual_wheelchair: | `:person_in_manual_wheelchair:` | [top](#table-of-contents) | +| [top](#people--body) | :man_in_manual_wheelchair: | `:man_in_manual_wheelchair:` | :woman_in_manual_wheelchair: | `:woman_in_manual_wheelchair:` | [top](#table-of-contents) | +| [top](#people--body) | :runner: | `:runner:` `:running:` | :running_man: | `:running_man:` | [top](#table-of-contents) | +| [top](#people--body) | :running_woman: | `:running_woman:` | :dancer: | `:dancer:` `:woman_dancing:` | [top](#table-of-contents) | +| [top](#people--body) | :man_dancing: | `:man_dancing:` | :business_suit_levitating: | `:business_suit_levitating:` | [top](#table-of-contents) | +| [top](#people--body) | :dancers: | `:dancers:` | :dancing_men: | `:dancing_men:` | [top](#table-of-contents) | +| [top](#people--body) | :dancing_women: | `:dancing_women:` | :sauna_person: | `:sauna_person:` | [top](#table-of-contents) | +| [top](#people--body) | :sauna_man: | `:sauna_man:` | :sauna_woman: | `:sauna_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :climbing: | `:climbing:` | :climbing_man: | `:climbing_man:` | [top](#table-of-contents) | +| [top](#people--body) | :climbing_woman: | `:climbing_woman:` | | | [top](#table-of-contents) | + +### Person Sport + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :person_fencing: | `:person_fencing:` | :horse_racing: | `:horse_racing:` | [top](#table-of-contents) | +| [top](#people--body) | :skier: | `:skier:` | :snowboarder: | `:snowboarder:` | [top](#table-of-contents) | +| [top](#people--body) | :golfing: | `:golfing:` | :golfing_man: | `:golfing_man:` | [top](#table-of-contents) | +| [top](#people--body) | :golfing_woman: | `:golfing_woman:` | :surfer: | `:surfer:` | [top](#table-of-contents) | +| [top](#people--body) | :surfing_man: | `:surfing_man:` | :surfing_woman: | `:surfing_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :rowboat: | `:rowboat:` | :rowing_man: | `:rowing_man:` | [top](#table-of-contents) | +| [top](#people--body) | :rowing_woman: | `:rowing_woman:` | :swimmer: | `:swimmer:` | [top](#table-of-contents) | +| [top](#people--body) | :swimming_man: | `:swimming_man:` | :swimming_woman: | `:swimming_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :bouncing_ball_person: | `:bouncing_ball_person:` | :basketball_man: | `:basketball_man:` `:bouncing_ball_man:` | [top](#table-of-contents) | +| [top](#people--body) | :basketball_woman: | `:basketball_woman:` `:bouncing_ball_woman:` | :weight_lifting: | `:weight_lifting:` | [top](#table-of-contents) | +| [top](#people--body) | :weight_lifting_man: | `:weight_lifting_man:` | :weight_lifting_woman: | `:weight_lifting_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :bicyclist: | `:bicyclist:` | :biking_man: | `:biking_man:` | [top](#table-of-contents) | +| [top](#people--body) | :biking_woman: | `:biking_woman:` | :mountain_bicyclist: | `:mountain_bicyclist:` | [top](#table-of-contents) | +| [top](#people--body) | :mountain_biking_man: | `:mountain_biking_man:` | :mountain_biking_woman: | `:mountain_biking_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :cartwheeling: | `:cartwheeling:` | :man_cartwheeling: | `:man_cartwheeling:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_cartwheeling: | `:woman_cartwheeling:` | :wrestling: | `:wrestling:` | [top](#table-of-contents) | +| [top](#people--body) | :men_wrestling: | `:men_wrestling:` | :women_wrestling: | `:women_wrestling:` | [top](#table-of-contents) | +| [top](#people--body) | :water_polo: | `:water_polo:` | :man_playing_water_polo: | `:man_playing_water_polo:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_playing_water_polo: | `:woman_playing_water_polo:` | :handball_person: | `:handball_person:` | [top](#table-of-contents) | +| [top](#people--body) | :man_playing_handball: | `:man_playing_handball:` | :woman_playing_handball: | `:woman_playing_handball:` | [top](#table-of-contents) | +| [top](#people--body) | :juggling_person: | `:juggling_person:` | :man_juggling: | `:man_juggling:` | [top](#table-of-contents) | +| [top](#people--body) | :woman_juggling: | `:woman_juggling:` | | | [top](#table-of-contents) | + +### Person Resting + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :lotus_position: | `:lotus_position:` | :lotus_position_man: | `:lotus_position_man:` | [top](#table-of-contents) | +| [top](#people--body) | :lotus_position_woman: | `:lotus_position_woman:` | :bath: | `:bath:` | [top](#table-of-contents) | +| [top](#people--body) | :sleeping_bed: | `:sleeping_bed:` | | | [top](#table-of-contents) | + +### Family + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :people_holding_hands: | `:people_holding_hands:` | :two_women_holding_hands: | `:two_women_holding_hands:` | [top](#table-of-contents) | +| [top](#people--body) | :couple: | `:couple:` | :two_men_holding_hands: | `:two_men_holding_hands:` | [top](#table-of-contents) | +| [top](#people--body) | :couplekiss: | `:couplekiss:` | :couplekiss_man_woman: | `:couplekiss_man_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :couplekiss_man_man: | `:couplekiss_man_man:` | :couplekiss_woman_woman: | `:couplekiss_woman_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :couple_with_heart: | `:couple_with_heart:` | :couple_with_heart_woman_man: | `:couple_with_heart_woman_man:` | [top](#table-of-contents) | +| [top](#people--body) | :couple_with_heart_man_man: | `:couple_with_heart_man_man:` | :couple_with_heart_woman_woman: | `:couple_with_heart_woman_woman:` | [top](#table-of-contents) | +| [top](#people--body) | :family_man_woman_boy: | `:family_man_woman_boy:` | :family_man_woman_girl: | `:family_man_woman_girl:` | [top](#table-of-contents) | +| [top](#people--body) | :family_man_woman_girl_boy: | `:family_man_woman_girl_boy:` | :family_man_woman_boy_boy: | `:family_man_woman_boy_boy:` | [top](#table-of-contents) | +| [top](#people--body) | :family_man_woman_girl_girl: | `:family_man_woman_girl_girl:` | :family_man_man_boy: | `:family_man_man_boy:` | [top](#table-of-contents) | +| [top](#people--body) | :family_man_man_girl: | `:family_man_man_girl:` | :family_man_man_girl_boy: | `:family_man_man_girl_boy:` | [top](#table-of-contents) | +| [top](#people--body) | :family_man_man_boy_boy: | `:family_man_man_boy_boy:` | :family_man_man_girl_girl: | `:family_man_man_girl_girl:` | [top](#table-of-contents) | +| [top](#people--body) | :family_woman_woman_boy: | `:family_woman_woman_boy:` | :family_woman_woman_girl: | `:family_woman_woman_girl:` | [top](#table-of-contents) | +| [top](#people--body) | :family_woman_woman_girl_boy: | `:family_woman_woman_girl_boy:` | :family_woman_woman_boy_boy: | `:family_woman_woman_boy_boy:` | [top](#table-of-contents) | +| [top](#people--body) | :family_woman_woman_girl_girl: | `:family_woman_woman_girl_girl:` | :family_man_boy: | `:family_man_boy:` | [top](#table-of-contents) | +| [top](#people--body) | :family_man_boy_boy: | `:family_man_boy_boy:` | :family_man_girl: | `:family_man_girl:` | [top](#table-of-contents) | +| [top](#people--body) | :family_man_girl_boy: | `:family_man_girl_boy:` | :family_man_girl_girl: | `:family_man_girl_girl:` | [top](#table-of-contents) | +| [top](#people--body) | :family_woman_boy: | `:family_woman_boy:` | :family_woman_boy_boy: | `:family_woman_boy_boy:` | [top](#table-of-contents) | +| [top](#people--body) | :family_woman_girl: | `:family_woman_girl:` | :family_woman_girl_boy: | `:family_woman_girl_boy:` | [top](#table-of-contents) | +| [top](#people--body) | :family_woman_girl_girl: | `:family_woman_girl_girl:` | | | [top](#table-of-contents) | + +### Person Symbol + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#people--body) | :speaking_head: | `:speaking_head:` | :bust_in_silhouette: | `:bust_in_silhouette:` | [top](#table-of-contents) | +| [top](#people--body) | :busts_in_silhouette: | `:busts_in_silhouette:` | :people_hugging: | `:people_hugging:` | [top](#table-of-contents) | +| [top](#people--body) | :family: | `:family:` | :footprints: | `:footprints:` | [top](#table-of-contents) | + +## Animals & Nature + +- [Animal Mammal](#animal-mammal) +- [Animal Bird](#animal-bird) +- [Animal Amphibian](#animal-amphibian) +- [Animal Reptile](#animal-reptile) +- [Animal Marine](#animal-marine) +- [Animal Bug](#animal-bug) +- [Plant Flower](#plant-flower) +- [Plant Other](#plant-other) + +### Animal Mammal + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :monkey_face: | `:monkey_face:` | :monkey: | `:monkey:` | [top](#table-of-contents) | +| [top](#animals--nature) | :gorilla: | `:gorilla:` | :orangutan: | `:orangutan:` | [top](#table-of-contents) | +| [top](#animals--nature) | :dog: | `:dog:` | :dog2: | `:dog2:` | [top](#table-of-contents) | +| [top](#animals--nature) | :guide_dog: | `:guide_dog:` | :service_dog: | `:service_dog:` | [top](#table-of-contents) | +| [top](#animals--nature) | :poodle: | `:poodle:` | :wolf: | `:wolf:` | [top](#table-of-contents) | +| [top](#animals--nature) | :fox_face: | `:fox_face:` | :raccoon: | `:raccoon:` | [top](#table-of-contents) | +| [top](#animals--nature) | :cat: | `:cat:` | :cat2: | `:cat2:` | [top](#table-of-contents) | +| [top](#animals--nature) | :black_cat: | `:black_cat:` | :lion: | `:lion:` | [top](#table-of-contents) | +| [top](#animals--nature) | :tiger: | `:tiger:` | :tiger2: | `:tiger2:` | [top](#table-of-contents) | +| [top](#animals--nature) | :leopard: | `:leopard:` | :horse: | `:horse:` | [top](#table-of-contents) | +| [top](#animals--nature) | :moose: | `:moose:` | :donkey: | `:donkey:` | [top](#table-of-contents) | +| [top](#animals--nature) | :racehorse: | `:racehorse:` | :unicorn: | `:unicorn:` | [top](#table-of-contents) | +| [top](#animals--nature) | :zebra: | `:zebra:` | :deer: | `:deer:` | [top](#table-of-contents) | +| [top](#animals--nature) | :bison: | `:bison:` | :cow: | `:cow:` | [top](#table-of-contents) | +| [top](#animals--nature) | :ox: | `:ox:` | :water_buffalo: | `:water_buffalo:` | [top](#table-of-contents) | +| [top](#animals--nature) | :cow2: | `:cow2:` | :pig: | `:pig:` | [top](#table-of-contents) | +| [top](#animals--nature) | :pig2: | `:pig2:` | :boar: | `:boar:` | [top](#table-of-contents) | +| [top](#animals--nature) | :pig_nose: | `:pig_nose:` | :ram: | `:ram:` | [top](#table-of-contents) | +| [top](#animals--nature) | :sheep: | `:sheep:` | :goat: | `:goat:` | [top](#table-of-contents) | +| [top](#animals--nature) | :dromedary_camel: | `:dromedary_camel:` | :camel: | `:camel:` | [top](#table-of-contents) | +| [top](#animals--nature) | :llama: | `:llama:` | :giraffe: | `:giraffe:` | [top](#table-of-contents) | +| [top](#animals--nature) | :elephant: | `:elephant:` | :mammoth: | `:mammoth:` | [top](#table-of-contents) | +| [top](#animals--nature) | :rhinoceros: | `:rhinoceros:` | :hippopotamus: | `:hippopotamus:` | [top](#table-of-contents) | +| [top](#animals--nature) | :mouse: | `:mouse:` | :mouse2: | `:mouse2:` | [top](#table-of-contents) | +| [top](#animals--nature) | :rat: | `:rat:` | :hamster: | `:hamster:` | [top](#table-of-contents) | +| [top](#animals--nature) | :rabbit: | `:rabbit:` | :rabbit2: | `:rabbit2:` | [top](#table-of-contents) | +| [top](#animals--nature) | :chipmunk: | `:chipmunk:` | :beaver: | `:beaver:` | [top](#table-of-contents) | +| [top](#animals--nature) | :hedgehog: | `:hedgehog:` | :bat: | `:bat:` | [top](#table-of-contents) | +| [top](#animals--nature) | :bear: | `:bear:` | :polar_bear: | `:polar_bear:` | [top](#table-of-contents) | +| [top](#animals--nature) | :koala: | `:koala:` | :panda_face: | `:panda_face:` | [top](#table-of-contents) | +| [top](#animals--nature) | :sloth: | `:sloth:` | :otter: | `:otter:` | [top](#table-of-contents) | +| [top](#animals--nature) | :skunk: | `:skunk:` | :kangaroo: | `:kangaroo:` | [top](#table-of-contents) | +| [top](#animals--nature) | :badger: | `:badger:` | :feet: | `:feet:` `:paw_prints:` | [top](#table-of-contents) | + +### Animal Bird + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :turkey: | `:turkey:` | :chicken: | `:chicken:` | [top](#table-of-contents) | +| [top](#animals--nature) | :rooster: | `:rooster:` | :hatching_chick: | `:hatching_chick:` | [top](#table-of-contents) | +| [top](#animals--nature) | :baby_chick: | `:baby_chick:` | :hatched_chick: | `:hatched_chick:` | [top](#table-of-contents) | +| [top](#animals--nature) | :bird: | `:bird:` | :penguin: | `:penguin:` | [top](#table-of-contents) | +| [top](#animals--nature) | :dove: | `:dove:` | :eagle: | `:eagle:` | [top](#table-of-contents) | +| [top](#animals--nature) | :duck: | `:duck:` | :swan: | `:swan:` | [top](#table-of-contents) | +| [top](#animals--nature) | :owl: | `:owl:` | :dodo: | `:dodo:` | [top](#table-of-contents) | +| [top](#animals--nature) | :feather: | `:feather:` | :flamingo: | `:flamingo:` | [top](#table-of-contents) | +| [top](#animals--nature) | :peacock: | `:peacock:` | :parrot: | `:parrot:` | [top](#table-of-contents) | +| [top](#animals--nature) | :wing: | `:wing:` | :black_bird: | `:black_bird:` | [top](#table-of-contents) | +| [top](#animals--nature) | :goose: | `:goose:` | | | [top](#table-of-contents) | + +### Animal Amphibian + +| | ico | shortcode | | +| - | :-: | - | - | +| [top](#animals--nature) | :frog: | `:frog:` | [top](#table-of-contents) | + +### Animal Reptile + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :crocodile: | `:crocodile:` | :turtle: | `:turtle:` | [top](#table-of-contents) | +| [top](#animals--nature) | :lizard: | `:lizard:` | :snake: | `:snake:` | [top](#table-of-contents) | +| [top](#animals--nature) | :dragon_face: | `:dragon_face:` | :dragon: | `:dragon:` | [top](#table-of-contents) | +| [top](#animals--nature) | :sauropod: | `:sauropod:` | :t-rex: | `:t-rex:` | [top](#table-of-contents) | + +### Animal Marine + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :whale: | `:whale:` | :whale2: | `:whale2:` | [top](#table-of-contents) | +| [top](#animals--nature) | :dolphin: | `:dolphin:` `:flipper:` | :seal: | `:seal:` | [top](#table-of-contents) | +| [top](#animals--nature) | :fish: | `:fish:` | :tropical_fish: | `:tropical_fish:` | [top](#table-of-contents) | +| [top](#animals--nature) | :blowfish: | `:blowfish:` | :shark: | `:shark:` | [top](#table-of-contents) | +| [top](#animals--nature) | :octopus: | `:octopus:` | :shell: | `:shell:` | [top](#table-of-contents) | +| [top](#animals--nature) | :coral: | `:coral:` | :jellyfish: | `:jellyfish:` | [top](#table-of-contents) | + +### Animal Bug + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :snail: | `:snail:` | :butterfly: | `:butterfly:` | [top](#table-of-contents) | +| [top](#animals--nature) | :bug: | `:bug:` | :ant: | `:ant:` | [top](#table-of-contents) | +| [top](#animals--nature) | :bee: | `:bee:` `:honeybee:` | :beetle: | `:beetle:` | [top](#table-of-contents) | +| [top](#animals--nature) | :lady_beetle: | `:lady_beetle:` | :cricket: | `:cricket:` | [top](#table-of-contents) | +| [top](#animals--nature) | :cockroach: | `:cockroach:` | :spider: | `:spider:` | [top](#table-of-contents) | +| [top](#animals--nature) | :spider_web: | `:spider_web:` | :scorpion: | `:scorpion:` | [top](#table-of-contents) | +| [top](#animals--nature) | :mosquito: | `:mosquito:` | :fly: | `:fly:` | [top](#table-of-contents) | +| [top](#animals--nature) | :worm: | `:worm:` | :microbe: | `:microbe:` | [top](#table-of-contents) | + +### Plant Flower + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :bouquet: | `:bouquet:` | :cherry_blossom: | `:cherry_blossom:` | [top](#table-of-contents) | +| [top](#animals--nature) | :white_flower: | `:white_flower:` | :lotus: | `:lotus:` | [top](#table-of-contents) | +| [top](#animals--nature) | :rosette: | `:rosette:` | :rose: | `:rose:` | [top](#table-of-contents) | +| [top](#animals--nature) | :wilted_flower: | `:wilted_flower:` | :hibiscus: | `:hibiscus:` | [top](#table-of-contents) | +| [top](#animals--nature) | :sunflower: | `:sunflower:` | :blossom: | `:blossom:` | [top](#table-of-contents) | +| [top](#animals--nature) | :tulip: | `:tulip:` | :hyacinth: | `:hyacinth:` | [top](#table-of-contents) | + +### Plant Other + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#animals--nature) | :seedling: | `:seedling:` | :potted_plant: | `:potted_plant:` | [top](#table-of-contents) | +| [top](#animals--nature) | :evergreen_tree: | `:evergreen_tree:` | :deciduous_tree: | `:deciduous_tree:` | [top](#table-of-contents) | +| [top](#animals--nature) | :palm_tree: | `:palm_tree:` | :cactus: | `:cactus:` | [top](#table-of-contents) | +| [top](#animals--nature) | :ear_of_rice: | `:ear_of_rice:` | :herb: | `:herb:` | [top](#table-of-contents) | +| [top](#animals--nature) | :shamrock: | `:shamrock:` | :four_leaf_clover: | `:four_leaf_clover:` | [top](#table-of-contents) | +| [top](#animals--nature) | :maple_leaf: | `:maple_leaf:` | :fallen_leaf: | `:fallen_leaf:` | [top](#table-of-contents) | +| [top](#animals--nature) | :leaves: | `:leaves:` | :empty_nest: | `:empty_nest:` | [top](#table-of-contents) | +| [top](#animals--nature) | :nest_with_eggs: | `:nest_with_eggs:` | :mushroom: | `:mushroom:` | [top](#table-of-contents) | + +## Food & Drink + +- [Food Fruit](#food-fruit) +- [Food Vegetable](#food-vegetable) +- [Food Prepared](#food-prepared) +- [Food Asian](#food-asian) +- [Food Marine](#food-marine) +- [Food Sweet](#food-sweet) +- [Drink](#drink) +- [Dishware](#dishware) + +### Food Fruit + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :grapes: | `:grapes:` | :melon: | `:melon:` | [top](#table-of-contents) | +| [top](#food--drink) | :watermelon: | `:watermelon:` | :mandarin: | `:mandarin:` `:orange:` `:tangerine:` | [top](#table-of-contents) | +| [top](#food--drink) | :lemon: | `:lemon:` | :banana: | `:banana:` | [top](#table-of-contents) | +| [top](#food--drink) | :pineapple: | `:pineapple:` | :mango: | `:mango:` | [top](#table-of-contents) | +| [top](#food--drink) | :apple: | `:apple:` | :green_apple: | `:green_apple:` | [top](#table-of-contents) | +| [top](#food--drink) | :pear: | `:pear:` | :peach: | `:peach:` | [top](#table-of-contents) | +| [top](#food--drink) | :cherries: | `:cherries:` | :strawberry: | `:strawberry:` | [top](#table-of-contents) | +| [top](#food--drink) | :blueberries: | `:blueberries:` | :kiwi_fruit: | `:kiwi_fruit:` | [top](#table-of-contents) | +| [top](#food--drink) | :tomato: | `:tomato:` | :olive: | `:olive:` | [top](#table-of-contents) | +| [top](#food--drink) | :coconut: | `:coconut:` | | | [top](#table-of-contents) | + +### Food Vegetable + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :avocado: | `:avocado:` | :eggplant: | `:eggplant:` | [top](#table-of-contents) | +| [top](#food--drink) | :potato: | `:potato:` | :carrot: | `:carrot:` | [top](#table-of-contents) | +| [top](#food--drink) | :corn: | `:corn:` | :hot_pepper: | `:hot_pepper:` | [top](#table-of-contents) | +| [top](#food--drink) | :bell_pepper: | `:bell_pepper:` | :cucumber: | `:cucumber:` | [top](#table-of-contents) | +| [top](#food--drink) | :leafy_green: | `:leafy_green:` | :broccoli: | `:broccoli:` | [top](#table-of-contents) | +| [top](#food--drink) | :garlic: | `:garlic:` | :onion: | `:onion:` | [top](#table-of-contents) | +| [top](#food--drink) | :peanuts: | `:peanuts:` | :beans: | `:beans:` | [top](#table-of-contents) | +| [top](#food--drink) | :chestnut: | `:chestnut:` | :ginger_root: | `:ginger_root:` | [top](#table-of-contents) | +| [top](#food--drink) | :pea_pod: | `:pea_pod:` | | | [top](#table-of-contents) | + +### Food Prepared + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :bread: | `:bread:` | :croissant: | `:croissant:` | [top](#table-of-contents) | +| [top](#food--drink) | :baguette_bread: | `:baguette_bread:` | :flatbread: | `:flatbread:` | [top](#table-of-contents) | +| [top](#food--drink) | :pretzel: | `:pretzel:` | :bagel: | `:bagel:` | [top](#table-of-contents) | +| [top](#food--drink) | :pancakes: | `:pancakes:` | :waffle: | `:waffle:` | [top](#table-of-contents) | +| [top](#food--drink) | :cheese: | `:cheese:` | :meat_on_bone: | `:meat_on_bone:` | [top](#table-of-contents) | +| [top](#food--drink) | :poultry_leg: | `:poultry_leg:` | :cut_of_meat: | `:cut_of_meat:` | [top](#table-of-contents) | +| [top](#food--drink) | :bacon: | `:bacon:` | :hamburger: | `:hamburger:` | [top](#table-of-contents) | +| [top](#food--drink) | :fries: | `:fries:` | :pizza: | `:pizza:` | [top](#table-of-contents) | +| [top](#food--drink) | :hotdog: | `:hotdog:` | :sandwich: | `:sandwich:` | [top](#table-of-contents) | +| [top](#food--drink) | :taco: | `:taco:` | :burrito: | `:burrito:` | [top](#table-of-contents) | +| [top](#food--drink) | :tamale: | `:tamale:` | :stuffed_flatbread: | `:stuffed_flatbread:` | [top](#table-of-contents) | +| [top](#food--drink) | :falafel: | `:falafel:` | :egg: | `:egg:` | [top](#table-of-contents) | +| [top](#food--drink) | :fried_egg: | `:fried_egg:` | :shallow_pan_of_food: | `:shallow_pan_of_food:` | [top](#table-of-contents) | +| [top](#food--drink) | :stew: | `:stew:` | :fondue: | `:fondue:` | [top](#table-of-contents) | +| [top](#food--drink) | :bowl_with_spoon: | `:bowl_with_spoon:` | :green_salad: | `:green_salad:` | [top](#table-of-contents) | +| [top](#food--drink) | :popcorn: | `:popcorn:` | :butter: | `:butter:` | [top](#table-of-contents) | +| [top](#food--drink) | :salt: | `:salt:` | :canned_food: | `:canned_food:` | [top](#table-of-contents) | + +### Food Asian + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :bento: | `:bento:` | :rice_cracker: | `:rice_cracker:` | [top](#table-of-contents) | +| [top](#food--drink) | :rice_ball: | `:rice_ball:` | :rice: | `:rice:` | [top](#table-of-contents) | +| [top](#food--drink) | :curry: | `:curry:` | :ramen: | `:ramen:` | [top](#table-of-contents) | +| [top](#food--drink) | :spaghetti: | `:spaghetti:` | :sweet_potato: | `:sweet_potato:` | [top](#table-of-contents) | +| [top](#food--drink) | :oden: | `:oden:` | :sushi: | `:sushi:` | [top](#table-of-contents) | +| [top](#food--drink) | :fried_shrimp: | `:fried_shrimp:` | :fish_cake: | `:fish_cake:` | [top](#table-of-contents) | +| [top](#food--drink) | :moon_cake: | `:moon_cake:` | :dango: | `:dango:` | [top](#table-of-contents) | +| [top](#food--drink) | :dumpling: | `:dumpling:` | :fortune_cookie: | `:fortune_cookie:` | [top](#table-of-contents) | +| [top](#food--drink) | :takeout_box: | `:takeout_box:` | | | [top](#table-of-contents) | + +### Food Marine + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :crab: | `:crab:` | :lobster: | `:lobster:` | [top](#table-of-contents) | +| [top](#food--drink) | :shrimp: | `:shrimp:` | :squid: | `:squid:` | [top](#table-of-contents) | +| [top](#food--drink) | :oyster: | `:oyster:` | | | [top](#table-of-contents) | + +### Food Sweet + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :icecream: | `:icecream:` | :shaved_ice: | `:shaved_ice:` | [top](#table-of-contents) | +| [top](#food--drink) | :ice_cream: | `:ice_cream:` | :doughnut: | `:doughnut:` | [top](#table-of-contents) | +| [top](#food--drink) | :cookie: | `:cookie:` | :birthday: | `:birthday:` | [top](#table-of-contents) | +| [top](#food--drink) | :cake: | `:cake:` | :cupcake: | `:cupcake:` | [top](#table-of-contents) | +| [top](#food--drink) | :pie: | `:pie:` | :chocolate_bar: | `:chocolate_bar:` | [top](#table-of-contents) | +| [top](#food--drink) | :candy: | `:candy:` | :lollipop: | `:lollipop:` | [top](#table-of-contents) | +| [top](#food--drink) | :custard: | `:custard:` | :honey_pot: | `:honey_pot:` | [top](#table-of-contents) | + +### Drink + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :baby_bottle: | `:baby_bottle:` | :milk_glass: | `:milk_glass:` | [top](#table-of-contents) | +| [top](#food--drink) | :coffee: | `:coffee:` | :teapot: | `:teapot:` | [top](#table-of-contents) | +| [top](#food--drink) | :tea: | `:tea:` | :sake: | `:sake:` | [top](#table-of-contents) | +| [top](#food--drink) | :champagne: | `:champagne:` | :wine_glass: | `:wine_glass:` | [top](#table-of-contents) | +| [top](#food--drink) | :cocktail: | `:cocktail:` | :tropical_drink: | `:tropical_drink:` | [top](#table-of-contents) | +| [top](#food--drink) | :beer: | `:beer:` | :beers: | `:beers:` | [top](#table-of-contents) | +| [top](#food--drink) | :clinking_glasses: | `:clinking_glasses:` | :tumbler_glass: | `:tumbler_glass:` | [top](#table-of-contents) | +| [top](#food--drink) | :pouring_liquid: | `:pouring_liquid:` | :cup_with_straw: | `:cup_with_straw:` | [top](#table-of-contents) | +| [top](#food--drink) | :bubble_tea: | `:bubble_tea:` | :beverage_box: | `:beverage_box:` | [top](#table-of-contents) | +| [top](#food--drink) | :mate: | `:mate:` | :ice_cube: | `:ice_cube:` | [top](#table-of-contents) | + +### Dishware + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#food--drink) | :chopsticks: | `:chopsticks:` | :plate_with_cutlery: | `:plate_with_cutlery:` | [top](#table-of-contents) | +| [top](#food--drink) | :fork_and_knife: | `:fork_and_knife:` | :spoon: | `:spoon:` | [top](#table-of-contents) | +| [top](#food--drink) | :hocho: | `:hocho:` `:knife:` | :jar: | `:jar:` | [top](#table-of-contents) | +| [top](#food--drink) | :amphora: | `:amphora:` | | | [top](#table-of-contents) | + +## Travel & Places + +- [Place Map](#place-map) +- [Place Geographic](#place-geographic) +- [Place Building](#place-building) +- [Place Religious](#place-religious) +- [Place Other](#place-other) +- [Transport Ground](#transport-ground) +- [Transport Water](#transport-water) +- [Transport Air](#transport-air) +- [Hotel](#hotel) +- [Time](#time) +- [Sky & Weather](#sky--weather) + +### Place Map + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :earth_africa: | `:earth_africa:` | :earth_americas: | `:earth_americas:` | [top](#table-of-contents) | +| [top](#travel--places) | :earth_asia: | `:earth_asia:` | :globe_with_meridians: | `:globe_with_meridians:` | [top](#table-of-contents) | +| [top](#travel--places) | :world_map: | `:world_map:` | :japan: | `:japan:` | [top](#table-of-contents) | +| [top](#travel--places) | :compass: | `:compass:` | | | [top](#table-of-contents) | + +### Place Geographic + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :mountain_snow: | `:mountain_snow:` | :mountain: | `:mountain:` | [top](#table-of-contents) | +| [top](#travel--places) | :volcano: | `:volcano:` | :mount_fuji: | `:mount_fuji:` | [top](#table-of-contents) | +| [top](#travel--places) | :camping: | `:camping:` | :beach_umbrella: | `:beach_umbrella:` | [top](#table-of-contents) | +| [top](#travel--places) | :desert: | `:desert:` | :desert_island: | `:desert_island:` | [top](#table-of-contents) | +| [top](#travel--places) | :national_park: | `:national_park:` | | | [top](#table-of-contents) | + +### Place Building + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :stadium: | `:stadium:` | :classical_building: | `:classical_building:` | [top](#table-of-contents) | +| [top](#travel--places) | :building_construction: | `:building_construction:` | :bricks: | `:bricks:` | [top](#table-of-contents) | +| [top](#travel--places) | :rock: | `:rock:` | :wood: | `:wood:` | [top](#table-of-contents) | +| [top](#travel--places) | :hut: | `:hut:` | :houses: | `:houses:` | [top](#table-of-contents) | +| [top](#travel--places) | :derelict_house: | `:derelict_house:` | :house: | `:house:` | [top](#table-of-contents) | +| [top](#travel--places) | :house_with_garden: | `:house_with_garden:` | :office: | `:office:` | [top](#table-of-contents) | +| [top](#travel--places) | :post_office: | `:post_office:` | :european_post_office: | `:european_post_office:` | [top](#table-of-contents) | +| [top](#travel--places) | :hospital: | `:hospital:` | :bank: | `:bank:` | [top](#table-of-contents) | +| [top](#travel--places) | :hotel: | `:hotel:` | :love_hotel: | `:love_hotel:` | [top](#table-of-contents) | +| [top](#travel--places) | :convenience_store: | `:convenience_store:` | :school: | `:school:` | [top](#table-of-contents) | +| [top](#travel--places) | :department_store: | `:department_store:` | :factory: | `:factory:` | [top](#table-of-contents) | +| [top](#travel--places) | :japanese_castle: | `:japanese_castle:` | :european_castle: | `:european_castle:` | [top](#table-of-contents) | +| [top](#travel--places) | :wedding: | `:wedding:` | :tokyo_tower: | `:tokyo_tower:` | [top](#table-of-contents) | +| [top](#travel--places) | :statue_of_liberty: | `:statue_of_liberty:` | | | [top](#table-of-contents) | + +### Place Religious + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :church: | `:church:` | :mosque: | `:mosque:` | [top](#table-of-contents) | +| [top](#travel--places) | :hindu_temple: | `:hindu_temple:` | :synagogue: | `:synagogue:` | [top](#table-of-contents) | +| [top](#travel--places) | :shinto_shrine: | `:shinto_shrine:` | :kaaba: | `:kaaba:` | [top](#table-of-contents) | + +### Place Other + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :fountain: | `:fountain:` | :tent: | `:tent:` | [top](#table-of-contents) | +| [top](#travel--places) | :foggy: | `:foggy:` | :night_with_stars: | `:night_with_stars:` | [top](#table-of-contents) | +| [top](#travel--places) | :cityscape: | `:cityscape:` | :sunrise_over_mountains: | `:sunrise_over_mountains:` | [top](#table-of-contents) | +| [top](#travel--places) | :sunrise: | `:sunrise:` | :city_sunset: | `:city_sunset:` | [top](#table-of-contents) | +| [top](#travel--places) | :city_sunrise: | `:city_sunrise:` | :bridge_at_night: | `:bridge_at_night:` | [top](#table-of-contents) | +| [top](#travel--places) | :hotsprings: | `:hotsprings:` | :carousel_horse: | `:carousel_horse:` | [top](#table-of-contents) | +| [top](#travel--places) | :playground_slide: | `:playground_slide:` | :ferris_wheel: | `:ferris_wheel:` | [top](#table-of-contents) | +| [top](#travel--places) | :roller_coaster: | `:roller_coaster:` | :barber: | `:barber:` | [top](#table-of-contents) | +| [top](#travel--places) | :circus_tent: | `:circus_tent:` | | | [top](#table-of-contents) | + +### Transport Ground + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :steam_locomotive: | `:steam_locomotive:` | :railway_car: | `:railway_car:` | [top](#table-of-contents) | +| [top](#travel--places) | :bullettrain_side: | `:bullettrain_side:` | :bullettrain_front: | `:bullettrain_front:` | [top](#table-of-contents) | +| [top](#travel--places) | :train2: | `:train2:` | :metro: | `:metro:` | [top](#table-of-contents) | +| [top](#travel--places) | :light_rail: | `:light_rail:` | :station: | `:station:` | [top](#table-of-contents) | +| [top](#travel--places) | :tram: | `:tram:` | :monorail: | `:monorail:` | [top](#table-of-contents) | +| [top](#travel--places) | :mountain_railway: | `:mountain_railway:` | :train: | `:train:` | [top](#table-of-contents) | +| [top](#travel--places) | :bus: | `:bus:` | :oncoming_bus: | `:oncoming_bus:` | [top](#table-of-contents) | +| [top](#travel--places) | :trolleybus: | `:trolleybus:` | :minibus: | `:minibus:` | [top](#table-of-contents) | +| [top](#travel--places) | :ambulance: | `:ambulance:` | :fire_engine: | `:fire_engine:` | [top](#table-of-contents) | +| [top](#travel--places) | :police_car: | `:police_car:` | :oncoming_police_car: | `:oncoming_police_car:` | [top](#table-of-contents) | +| [top](#travel--places) | :taxi: | `:taxi:` | :oncoming_taxi: | `:oncoming_taxi:` | [top](#table-of-contents) | +| [top](#travel--places) | :car: | `:car:` `:red_car:` | :oncoming_automobile: | `:oncoming_automobile:` | [top](#table-of-contents) | +| [top](#travel--places) | :blue_car: | `:blue_car:` | :pickup_truck: | `:pickup_truck:` | [top](#table-of-contents) | +| [top](#travel--places) | :truck: | `:truck:` | :articulated_lorry: | `:articulated_lorry:` | [top](#table-of-contents) | +| [top](#travel--places) | :tractor: | `:tractor:` | :racing_car: | `:racing_car:` | [top](#table-of-contents) | +| [top](#travel--places) | :motorcycle: | `:motorcycle:` | :motor_scooter: | `:motor_scooter:` | [top](#table-of-contents) | +| [top](#travel--places) | :manual_wheelchair: | `:manual_wheelchair:` | :motorized_wheelchair: | `:motorized_wheelchair:` | [top](#table-of-contents) | +| [top](#travel--places) | :auto_rickshaw: | `:auto_rickshaw:` | :bike: | `:bike:` | [top](#table-of-contents) | +| [top](#travel--places) | :kick_scooter: | `:kick_scooter:` | :skateboard: | `:skateboard:` | [top](#table-of-contents) | +| [top](#travel--places) | :roller_skate: | `:roller_skate:` | :busstop: | `:busstop:` | [top](#table-of-contents) | +| [top](#travel--places) | :motorway: | `:motorway:` | :railway_track: | `:railway_track:` | [top](#table-of-contents) | +| [top](#travel--places) | :oil_drum: | `:oil_drum:` | :fuelpump: | `:fuelpump:` | [top](#table-of-contents) | +| [top](#travel--places) | :wheel: | `:wheel:` | :rotating_light: | `:rotating_light:` | [top](#table-of-contents) | +| [top](#travel--places) | :traffic_light: | `:traffic_light:` | :vertical_traffic_light: | `:vertical_traffic_light:` | [top](#table-of-contents) | +| [top](#travel--places) | :stop_sign: | `:stop_sign:` | :construction: | `:construction:` | [top](#table-of-contents) | + +### Transport Water + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :anchor: | `:anchor:` | :ring_buoy: | `:ring_buoy:` | [top](#table-of-contents) | +| [top](#travel--places) | :boat: | `:boat:` `:sailboat:` | :canoe: | `:canoe:` | [top](#table-of-contents) | +| [top](#travel--places) | :speedboat: | `:speedboat:` | :passenger_ship: | `:passenger_ship:` | [top](#table-of-contents) | +| [top](#travel--places) | :ferry: | `:ferry:` | :motor_boat: | `:motor_boat:` | [top](#table-of-contents) | +| [top](#travel--places) | :ship: | `:ship:` | | | [top](#table-of-contents) | + +### Transport Air + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :airplane: | `:airplane:` | :small_airplane: | `:small_airplane:` | [top](#table-of-contents) | +| [top](#travel--places) | :flight_departure: | `:flight_departure:` | :flight_arrival: | `:flight_arrival:` | [top](#table-of-contents) | +| [top](#travel--places) | :parachute: | `:parachute:` | :seat: | `:seat:` | [top](#table-of-contents) | +| [top](#travel--places) | :helicopter: | `:helicopter:` | :suspension_railway: | `:suspension_railway:` | [top](#table-of-contents) | +| [top](#travel--places) | :mountain_cableway: | `:mountain_cableway:` | :aerial_tramway: | `:aerial_tramway:` | [top](#table-of-contents) | +| [top](#travel--places) | :artificial_satellite: | `:artificial_satellite:` | :rocket: | `:rocket:` | [top](#table-of-contents) | +| [top](#travel--places) | :flying_saucer: | `:flying_saucer:` | | | [top](#table-of-contents) | + +### Hotel + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :bellhop_bell: | `:bellhop_bell:` | :luggage: | `:luggage:` | [top](#table-of-contents) | + +### Time + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :hourglass: | `:hourglass:` | :hourglass_flowing_sand: | `:hourglass_flowing_sand:` | [top](#table-of-contents) | +| [top](#travel--places) | :watch: | `:watch:` | :alarm_clock: | `:alarm_clock:` | [top](#table-of-contents) | +| [top](#travel--places) | :stopwatch: | `:stopwatch:` | :timer_clock: | `:timer_clock:` | [top](#table-of-contents) | +| [top](#travel--places) | :mantelpiece_clock: | `:mantelpiece_clock:` | :clock12: | `:clock12:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock1230: | `:clock1230:` | :clock1: | `:clock1:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock130: | `:clock130:` | :clock2: | `:clock2:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock230: | `:clock230:` | :clock3: | `:clock3:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock330: | `:clock330:` | :clock4: | `:clock4:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock430: | `:clock430:` | :clock5: | `:clock5:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock530: | `:clock530:` | :clock6: | `:clock6:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock630: | `:clock630:` | :clock7: | `:clock7:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock730: | `:clock730:` | :clock8: | `:clock8:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock830: | `:clock830:` | :clock9: | `:clock9:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock930: | `:clock930:` | :clock10: | `:clock10:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock1030: | `:clock1030:` | :clock11: | `:clock11:` | [top](#table-of-contents) | +| [top](#travel--places) | :clock1130: | `:clock1130:` | | | [top](#table-of-contents) | + +### Sky & Weather + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#travel--places) | :new_moon: | `:new_moon:` | :waxing_crescent_moon: | `:waxing_crescent_moon:` | [top](#table-of-contents) | +| [top](#travel--places) | :first_quarter_moon: | `:first_quarter_moon:` | :moon: | `:moon:` `:waxing_gibbous_moon:` | [top](#table-of-contents) | +| [top](#travel--places) | :full_moon: | `:full_moon:` | :waning_gibbous_moon: | `:waning_gibbous_moon:` | [top](#table-of-contents) | +| [top](#travel--places) | :last_quarter_moon: | `:last_quarter_moon:` | :waning_crescent_moon: | `:waning_crescent_moon:` | [top](#table-of-contents) | +| [top](#travel--places) | :crescent_moon: | `:crescent_moon:` | :new_moon_with_face: | `:new_moon_with_face:` | [top](#table-of-contents) | +| [top](#travel--places) | :first_quarter_moon_with_face: | `:first_quarter_moon_with_face:` | :last_quarter_moon_with_face: | `:last_quarter_moon_with_face:` | [top](#table-of-contents) | +| [top](#travel--places) | :thermometer: | `:thermometer:` | :sunny: | `:sunny:` | [top](#table-of-contents) | +| [top](#travel--places) | :full_moon_with_face: | `:full_moon_with_face:` | :sun_with_face: | `:sun_with_face:` | [top](#table-of-contents) | +| [top](#travel--places) | :ringed_planet: | `:ringed_planet:` | :star: | `:star:` | [top](#table-of-contents) | +| [top](#travel--places) | :star2: | `:star2:` | :stars: | `:stars:` | [top](#table-of-contents) | +| [top](#travel--places) | :milky_way: | `:milky_way:` | :cloud: | `:cloud:` | [top](#table-of-contents) | +| [top](#travel--places) | :partly_sunny: | `:partly_sunny:` | :cloud_with_lightning_and_rain: | `:cloud_with_lightning_and_rain:` | [top](#table-of-contents) | +| [top](#travel--places) | :sun_behind_small_cloud: | `:sun_behind_small_cloud:` | :sun_behind_large_cloud: | `:sun_behind_large_cloud:` | [top](#table-of-contents) | +| [top](#travel--places) | :sun_behind_rain_cloud: | `:sun_behind_rain_cloud:` | :cloud_with_rain: | `:cloud_with_rain:` | [top](#table-of-contents) | +| [top](#travel--places) | :cloud_with_snow: | `:cloud_with_snow:` | :cloud_with_lightning: | `:cloud_with_lightning:` | [top](#table-of-contents) | +| [top](#travel--places) | :tornado: | `:tornado:` | :fog: | `:fog:` | [top](#table-of-contents) | +| [top](#travel--places) | :wind_face: | `:wind_face:` | :cyclone: | `:cyclone:` | [top](#table-of-contents) | +| [top](#travel--places) | :rainbow: | `:rainbow:` | :closed_umbrella: | `:closed_umbrella:` | [top](#table-of-contents) | +| [top](#travel--places) | :open_umbrella: | `:open_umbrella:` | :umbrella: | `:umbrella:` | [top](#table-of-contents) | +| [top](#travel--places) | :parasol_on_ground: | `:parasol_on_ground:` | :zap: | `:zap:` | [top](#table-of-contents) | +| [top](#travel--places) | :snowflake: | `:snowflake:` | :snowman_with_snow: | `:snowman_with_snow:` | [top](#table-of-contents) | +| [top](#travel--places) | :snowman: | `:snowman:` | :comet: | `:comet:` | [top](#table-of-contents) | +| [top](#travel--places) | :fire: | `:fire:` | :droplet: | `:droplet:` | [top](#table-of-contents) | +| [top](#travel--places) | :ocean: | `:ocean:` | | | [top](#table-of-contents) | + +## Activities + +- [Event](#event) +- [Award Medal](#award-medal) +- [Sport](#sport) +- [Game](#game) +- [Arts & Crafts](#arts--crafts) + +### Event + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#activities) | :jack_o_lantern: | `:jack_o_lantern:` | :christmas_tree: | `:christmas_tree:` | [top](#table-of-contents) | +| [top](#activities) | :fireworks: | `:fireworks:` | :sparkler: | `:sparkler:` | [top](#table-of-contents) | +| [top](#activities) | :firecracker: | `:firecracker:` | :sparkles: | `:sparkles:` | [top](#table-of-contents) | +| [top](#activities) | :balloon: | `:balloon:` | :tada: | `:tada:` | [top](#table-of-contents) | +| [top](#activities) | :confetti_ball: | `:confetti_ball:` | :tanabata_tree: | `:tanabata_tree:` | [top](#table-of-contents) | +| [top](#activities) | :bamboo: | `:bamboo:` | :dolls: | `:dolls:` | [top](#table-of-contents) | +| [top](#activities) | :flags: | `:flags:` | :wind_chime: | `:wind_chime:` | [top](#table-of-contents) | +| [top](#activities) | :rice_scene: | `:rice_scene:` | :red_envelope: | `:red_envelope:` | [top](#table-of-contents) | +| [top](#activities) | :ribbon: | `:ribbon:` | :gift: | `:gift:` | [top](#table-of-contents) | +| [top](#activities) | :reminder_ribbon: | `:reminder_ribbon:` | :tickets: | `:tickets:` | [top](#table-of-contents) | +| [top](#activities) | :ticket: | `:ticket:` | | | [top](#table-of-contents) | + +### Award Medal + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#activities) | :medal_military: | `:medal_military:` | :trophy: | `:trophy:` | [top](#table-of-contents) | +| [top](#activities) | :medal_sports: | `:medal_sports:` | :1st_place_medal: | `:1st_place_medal:` | [top](#table-of-contents) | +| [top](#activities) | :2nd_place_medal: | `:2nd_place_medal:` | :3rd_place_medal: | `:3rd_place_medal:` | [top](#table-of-contents) | + +### Sport + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#activities) | :soccer: | `:soccer:` | :baseball: | `:baseball:` | [top](#table-of-contents) | +| [top](#activities) | :softball: | `:softball:` | :basketball: | `:basketball:` | [top](#table-of-contents) | +| [top](#activities) | :volleyball: | `:volleyball:` | :football: | `:football:` | [top](#table-of-contents) | +| [top](#activities) | :rugby_football: | `:rugby_football:` | :tennis: | `:tennis:` | [top](#table-of-contents) | +| [top](#activities) | :flying_disc: | `:flying_disc:` | :bowling: | `:bowling:` | [top](#table-of-contents) | +| [top](#activities) | :cricket_game: | `:cricket_game:` | :field_hockey: | `:field_hockey:` | [top](#table-of-contents) | +| [top](#activities) | :ice_hockey: | `:ice_hockey:` | :lacrosse: | `:lacrosse:` | [top](#table-of-contents) | +| [top](#activities) | :ping_pong: | `:ping_pong:` | :badminton: | `:badminton:` | [top](#table-of-contents) | +| [top](#activities) | :boxing_glove: | `:boxing_glove:` | :martial_arts_uniform: | `:martial_arts_uniform:` | [top](#table-of-contents) | +| [top](#activities) | :goal_net: | `:goal_net:` | :golf: | `:golf:` | [top](#table-of-contents) | +| [top](#activities) | :ice_skate: | `:ice_skate:` | :fishing_pole_and_fish: | `:fishing_pole_and_fish:` | [top](#table-of-contents) | +| [top](#activities) | :diving_mask: | `:diving_mask:` | :running_shirt_with_sash: | `:running_shirt_with_sash:` | [top](#table-of-contents) | +| [top](#activities) | :ski: | `:ski:` | :sled: | `:sled:` | [top](#table-of-contents) | +| [top](#activities) | :curling_stone: | `:curling_stone:` | | | [top](#table-of-contents) | + +### Game + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#activities) | :dart: | `:dart:` | :yo_yo: | `:yo_yo:` | [top](#table-of-contents) | +| [top](#activities) | :kite: | `:kite:` | :gun: | `:gun:` | [top](#table-of-contents) | +| [top](#activities) | :8ball: | `:8ball:` | :crystal_ball: | `:crystal_ball:` | [top](#table-of-contents) | +| [top](#activities) | :magic_wand: | `:magic_wand:` | :video_game: | `:video_game:` | [top](#table-of-contents) | +| [top](#activities) | :joystick: | `:joystick:` | :slot_machine: | `:slot_machine:` | [top](#table-of-contents) | +| [top](#activities) | :game_die: | `:game_die:` | :jigsaw: | `:jigsaw:` | [top](#table-of-contents) | +| [top](#activities) | :teddy_bear: | `:teddy_bear:` | :pinata: | `:pinata:` | [top](#table-of-contents) | +| [top](#activities) | :mirror_ball: | `:mirror_ball:` | :nesting_dolls: | `:nesting_dolls:` | [top](#table-of-contents) | +| [top](#activities) | :spades: | `:spades:` | :hearts: | `:hearts:` | [top](#table-of-contents) | +| [top](#activities) | :diamonds: | `:diamonds:` | :clubs: | `:clubs:` | [top](#table-of-contents) | +| [top](#activities) | :chess_pawn: | `:chess_pawn:` | :black_joker: | `:black_joker:` | [top](#table-of-contents) | +| [top](#activities) | :mahjong: | `:mahjong:` | :flower_playing_cards: | `:flower_playing_cards:` | [top](#table-of-contents) | + +### Arts & Crafts + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#activities) | :performing_arts: | `:performing_arts:` | :framed_picture: | `:framed_picture:` | [top](#table-of-contents) | +| [top](#activities) | :art: | `:art:` | :thread: | `:thread:` | [top](#table-of-contents) | +| [top](#activities) | :sewing_needle: | `:sewing_needle:` | :yarn: | `:yarn:` | [top](#table-of-contents) | +| [top](#activities) | :knot: | `:knot:` | | | [top](#table-of-contents) | + +## Objects + +- [Clothing](#clothing) +- [Sound](#sound) +- [Music](#music) +- [Musical Instrument](#musical-instrument) +- [Phone](#phone) +- [Computer](#computer) +- [Light & Video](#light--video) +- [Book Paper](#book-paper) +- [Money](#money) +- [Mail](#mail) +- [Writing](#writing) +- [Office](#office) +- [Lock](#lock) +- [Tool](#tool) +- [Science](#science) +- [Medical](#medical) +- [Household](#household) +- [Other Object](#other-object) + +### Clothing + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :eyeglasses: | `:eyeglasses:` | :dark_sunglasses: | `:dark_sunglasses:` | [top](#table-of-contents) | +| [top](#objects) | :goggles: | `:goggles:` | :lab_coat: | `:lab_coat:` | [top](#table-of-contents) | +| [top](#objects) | :safety_vest: | `:safety_vest:` | :necktie: | `:necktie:` | [top](#table-of-contents) | +| [top](#objects) | :shirt: | `:shirt:` `:tshirt:` | :jeans: | `:jeans:` | [top](#table-of-contents) | +| [top](#objects) | :scarf: | `:scarf:` | :gloves: | `:gloves:` | [top](#table-of-contents) | +| [top](#objects) | :coat: | `:coat:` | :socks: | `:socks:` | [top](#table-of-contents) | +| [top](#objects) | :dress: | `:dress:` | :kimono: | `:kimono:` | [top](#table-of-contents) | +| [top](#objects) | :sari: | `:sari:` | :one_piece_swimsuit: | `:one_piece_swimsuit:` | [top](#table-of-contents) | +| [top](#objects) | :swim_brief: | `:swim_brief:` | :shorts: | `:shorts:` | [top](#table-of-contents) | +| [top](#objects) | :bikini: | `:bikini:` | :womans_clothes: | `:womans_clothes:` | [top](#table-of-contents) | +| [top](#objects) | :folding_hand_fan: | `:folding_hand_fan:` | :purse: | `:purse:` | [top](#table-of-contents) | +| [top](#objects) | :handbag: | `:handbag:` | :pouch: | `:pouch:` | [top](#table-of-contents) | +| [top](#objects) | :shopping: | `:shopping:` | :school_satchel: | `:school_satchel:` | [top](#table-of-contents) | +| [top](#objects) | :thong_sandal: | `:thong_sandal:` | :mans_shoe: | `:mans_shoe:` `:shoe:` | [top](#table-of-contents) | +| [top](#objects) | :athletic_shoe: | `:athletic_shoe:` | :hiking_boot: | `:hiking_boot:` | [top](#table-of-contents) | +| [top](#objects) | :flat_shoe: | `:flat_shoe:` | :high_heel: | `:high_heel:` | [top](#table-of-contents) | +| [top](#objects) | :sandal: | `:sandal:` | :ballet_shoes: | `:ballet_shoes:` | [top](#table-of-contents) | +| [top](#objects) | :boot: | `:boot:` | :hair_pick: | `:hair_pick:` | [top](#table-of-contents) | +| [top](#objects) | :crown: | `:crown:` | :womans_hat: | `:womans_hat:` | [top](#table-of-contents) | +| [top](#objects) | :tophat: | `:tophat:` | :mortar_board: | `:mortar_board:` | [top](#table-of-contents) | +| [top](#objects) | :billed_cap: | `:billed_cap:` | :military_helmet: | `:military_helmet:` | [top](#table-of-contents) | +| [top](#objects) | :rescue_worker_helmet: | `:rescue_worker_helmet:` | :prayer_beads: | `:prayer_beads:` | [top](#table-of-contents) | +| [top](#objects) | :lipstick: | `:lipstick:` | :ring: | `:ring:` | [top](#table-of-contents) | +| [top](#objects) | :gem: | `:gem:` | | | [top](#table-of-contents) | + +### Sound + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :mute: | `:mute:` | :speaker: | `:speaker:` | [top](#table-of-contents) | +| [top](#objects) | :sound: | `:sound:` | :loud_sound: | `:loud_sound:` | [top](#table-of-contents) | +| [top](#objects) | :loudspeaker: | `:loudspeaker:` | :mega: | `:mega:` | [top](#table-of-contents) | +| [top](#objects) | :postal_horn: | `:postal_horn:` | :bell: | `:bell:` | [top](#table-of-contents) | +| [top](#objects) | :no_bell: | `:no_bell:` | | | [top](#table-of-contents) | + +### Music + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :musical_score: | `:musical_score:` | :musical_note: | `:musical_note:` | [top](#table-of-contents) | +| [top](#objects) | :notes: | `:notes:` | :studio_microphone: | `:studio_microphone:` | [top](#table-of-contents) | +| [top](#objects) | :level_slider: | `:level_slider:` | :control_knobs: | `:control_knobs:` | [top](#table-of-contents) | +| [top](#objects) | :microphone: | `:microphone:` | :headphones: | `:headphones:` | [top](#table-of-contents) | +| [top](#objects) | :radio: | `:radio:` | | | [top](#table-of-contents) | + +### Musical Instrument + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :saxophone: | `:saxophone:` | :accordion: | `:accordion:` | [top](#table-of-contents) | +| [top](#objects) | :guitar: | `:guitar:` | :musical_keyboard: | `:musical_keyboard:` | [top](#table-of-contents) | +| [top](#objects) | :trumpet: | `:trumpet:` | :violin: | `:violin:` | [top](#table-of-contents) | +| [top](#objects) | :banjo: | `:banjo:` | :drum: | `:drum:` | [top](#table-of-contents) | +| [top](#objects) | :long_drum: | `:long_drum:` | :maracas: | `:maracas:` | [top](#table-of-contents) | +| [top](#objects) | :flute: | `:flute:` | | | [top](#table-of-contents) | + +### Phone + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :iphone: | `:iphone:` | :calling: | `:calling:` | [top](#table-of-contents) | +| [top](#objects) | :phone: | `:phone:` `:telephone:` | :telephone_receiver: | `:telephone_receiver:` | [top](#table-of-contents) | +| [top](#objects) | :pager: | `:pager:` | :fax: | `:fax:` | [top](#table-of-contents) | + +### Computer + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :battery: | `:battery:` | :low_battery: | `:low_battery:` | [top](#table-of-contents) | +| [top](#objects) | :electric_plug: | `:electric_plug:` | :computer: | `:computer:` | [top](#table-of-contents) | +| [top](#objects) | :desktop_computer: | `:desktop_computer:` | :printer: | `:printer:` | [top](#table-of-contents) | +| [top](#objects) | :keyboard: | `:keyboard:` | :computer_mouse: | `:computer_mouse:` | [top](#table-of-contents) | +| [top](#objects) | :trackball: | `:trackball:` | :minidisc: | `:minidisc:` | [top](#table-of-contents) | +| [top](#objects) | :floppy_disk: | `:floppy_disk:` | :cd: | `:cd:` | [top](#table-of-contents) | +| [top](#objects) | :dvd: | `:dvd:` | :abacus: | `:abacus:` | [top](#table-of-contents) | + +### Light & Video + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :movie_camera: | `:movie_camera:` | :film_strip: | `:film_strip:` | [top](#table-of-contents) | +| [top](#objects) | :film_projector: | `:film_projector:` | :clapper: | `:clapper:` | [top](#table-of-contents) | +| [top](#objects) | :tv: | `:tv:` | :camera: | `:camera:` | [top](#table-of-contents) | +| [top](#objects) | :camera_flash: | `:camera_flash:` | :video_camera: | `:video_camera:` | [top](#table-of-contents) | +| [top](#objects) | :vhs: | `:vhs:` | :mag: | `:mag:` | [top](#table-of-contents) | +| [top](#objects) | :mag_right: | `:mag_right:` | :candle: | `:candle:` | [top](#table-of-contents) | +| [top](#objects) | :bulb: | `:bulb:` | :flashlight: | `:flashlight:` | [top](#table-of-contents) | +| [top](#objects) | :izakaya_lantern: | `:izakaya_lantern:` `:lantern:` | :diya_lamp: | `:diya_lamp:` | [top](#table-of-contents) | + +### Book Paper + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :notebook_with_decorative_cover: | `:notebook_with_decorative_cover:` | :closed_book: | `:closed_book:` | [top](#table-of-contents) | +| [top](#objects) | :book: | `:book:` `:open_book:` | :green_book: | `:green_book:` | [top](#table-of-contents) | +| [top](#objects) | :blue_book: | `:blue_book:` | :orange_book: | `:orange_book:` | [top](#table-of-contents) | +| [top](#objects) | :books: | `:books:` | :notebook: | `:notebook:` | [top](#table-of-contents) | +| [top](#objects) | :ledger: | `:ledger:` | :page_with_curl: | `:page_with_curl:` | [top](#table-of-contents) | +| [top](#objects) | :scroll: | `:scroll:` | :page_facing_up: | `:page_facing_up:` | [top](#table-of-contents) | +| [top](#objects) | :newspaper: | `:newspaper:` | :newspaper_roll: | `:newspaper_roll:` | [top](#table-of-contents) | +| [top](#objects) | :bookmark_tabs: | `:bookmark_tabs:` | :bookmark: | `:bookmark:` | [top](#table-of-contents) | +| [top](#objects) | :label: | `:label:` | | | [top](#table-of-contents) | + +### Money + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :moneybag: | `:moneybag:` | :coin: | `:coin:` | [top](#table-of-contents) | +| [top](#objects) | :yen: | `:yen:` | :dollar: | `:dollar:` | [top](#table-of-contents) | +| [top](#objects) | :euro: | `:euro:` | :pound: | `:pound:` | [top](#table-of-contents) | +| [top](#objects) | :money_with_wings: | `:money_with_wings:` | :credit_card: | `:credit_card:` | [top](#table-of-contents) | +| [top](#objects) | :receipt: | `:receipt:` | :chart: | `:chart:` | [top](#table-of-contents) | + +### Mail + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :envelope: | `:envelope:` | :e-mail: | `:e-mail:` `:email:` | [top](#table-of-contents) | +| [top](#objects) | :incoming_envelope: | `:incoming_envelope:` | :envelope_with_arrow: | `:envelope_with_arrow:` | [top](#table-of-contents) | +| [top](#objects) | :outbox_tray: | `:outbox_tray:` | :inbox_tray: | `:inbox_tray:` | [top](#table-of-contents) | +| [top](#objects) | :package: | `:package:` | :mailbox: | `:mailbox:` | [top](#table-of-contents) | +| [top](#objects) | :mailbox_closed: | `:mailbox_closed:` | :mailbox_with_mail: | `:mailbox_with_mail:` | [top](#table-of-contents) | +| [top](#objects) | :mailbox_with_no_mail: | `:mailbox_with_no_mail:` | :postbox: | `:postbox:` | [top](#table-of-contents) | +| [top](#objects) | :ballot_box: | `:ballot_box:` | | | [top](#table-of-contents) | + +### Writing + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :pencil2: | `:pencil2:` | :black_nib: | `:black_nib:` | [top](#table-of-contents) | +| [top](#objects) | :fountain_pen: | `:fountain_pen:` | :pen: | `:pen:` | [top](#table-of-contents) | +| [top](#objects) | :paintbrush: | `:paintbrush:` | :crayon: | `:crayon:` | [top](#table-of-contents) | +| [top](#objects) | :memo: | `:memo:` `:pencil:` | | | [top](#table-of-contents) | + +### Office + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :briefcase: | `:briefcase:` | :file_folder: | `:file_folder:` | [top](#table-of-contents) | +| [top](#objects) | :open_file_folder: | `:open_file_folder:` | :card_index_dividers: | `:card_index_dividers:` | [top](#table-of-contents) | +| [top](#objects) | :date: | `:date:` | :calendar: | `:calendar:` | [top](#table-of-contents) | +| [top](#objects) | :spiral_notepad: | `:spiral_notepad:` | :spiral_calendar: | `:spiral_calendar:` | [top](#table-of-contents) | +| [top](#objects) | :card_index: | `:card_index:` | :chart_with_upwards_trend: | `:chart_with_upwards_trend:` | [top](#table-of-contents) | +| [top](#objects) | :chart_with_downwards_trend: | `:chart_with_downwards_trend:` | :bar_chart: | `:bar_chart:` | [top](#table-of-contents) | +| [top](#objects) | :clipboard: | `:clipboard:` | :pushpin: | `:pushpin:` | [top](#table-of-contents) | +| [top](#objects) | :round_pushpin: | `:round_pushpin:` | :paperclip: | `:paperclip:` | [top](#table-of-contents) | +| [top](#objects) | :paperclips: | `:paperclips:` | :straight_ruler: | `:straight_ruler:` | [top](#table-of-contents) | +| [top](#objects) | :triangular_ruler: | `:triangular_ruler:` | :scissors: | `:scissors:` | [top](#table-of-contents) | +| [top](#objects) | :card_file_box: | `:card_file_box:` | :file_cabinet: | `:file_cabinet:` | [top](#table-of-contents) | +| [top](#objects) | :wastebasket: | `:wastebasket:` | | | [top](#table-of-contents) | + +### Lock + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :lock: | `:lock:` | :unlock: | `:unlock:` | [top](#table-of-contents) | +| [top](#objects) | :lock_with_ink_pen: | `:lock_with_ink_pen:` | :closed_lock_with_key: | `:closed_lock_with_key:` | [top](#table-of-contents) | +| [top](#objects) | :key: | `:key:` | :old_key: | `:old_key:` | [top](#table-of-contents) | + +### Tool + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :hammer: | `:hammer:` | :axe: | `:axe:` | [top](#table-of-contents) | +| [top](#objects) | :pick: | `:pick:` | :hammer_and_pick: | `:hammer_and_pick:` | [top](#table-of-contents) | +| [top](#objects) | :hammer_and_wrench: | `:hammer_and_wrench:` | :dagger: | `:dagger:` | [top](#table-of-contents) | +| [top](#objects) | :crossed_swords: | `:crossed_swords:` | :bomb: | `:bomb:` | [top](#table-of-contents) | +| [top](#objects) | :boomerang: | `:boomerang:` | :bow_and_arrow: | `:bow_and_arrow:` | [top](#table-of-contents) | +| [top](#objects) | :shield: | `:shield:` | :carpentry_saw: | `:carpentry_saw:` | [top](#table-of-contents) | +| [top](#objects) | :wrench: | `:wrench:` | :screwdriver: | `:screwdriver:` | [top](#table-of-contents) | +| [top](#objects) | :nut_and_bolt: | `:nut_and_bolt:` | :gear: | `:gear:` | [top](#table-of-contents) | +| [top](#objects) | :clamp: | `:clamp:` | :balance_scale: | `:balance_scale:` | [top](#table-of-contents) | +| [top](#objects) | :probing_cane: | `:probing_cane:` | :link: | `:link:` | [top](#table-of-contents) | +| [top](#objects) | :chains: | `:chains:` | :hook: | `:hook:` | [top](#table-of-contents) | +| [top](#objects) | :toolbox: | `:toolbox:` | :magnet: | `:magnet:` | [top](#table-of-contents) | +| [top](#objects) | :ladder: | `:ladder:` | | | [top](#table-of-contents) | + +### Science + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :alembic: | `:alembic:` | :test_tube: | `:test_tube:` | [top](#table-of-contents) | +| [top](#objects) | :petri_dish: | `:petri_dish:` | :dna: | `:dna:` | [top](#table-of-contents) | +| [top](#objects) | :microscope: | `:microscope:` | :telescope: | `:telescope:` | [top](#table-of-contents) | +| [top](#objects) | :satellite: | `:satellite:` | | | [top](#table-of-contents) | + +### Medical + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :syringe: | `:syringe:` | :drop_of_blood: | `:drop_of_blood:` | [top](#table-of-contents) | +| [top](#objects) | :pill: | `:pill:` | :adhesive_bandage: | `:adhesive_bandage:` | [top](#table-of-contents) | +| [top](#objects) | :crutch: | `:crutch:` | :stethoscope: | `:stethoscope:` | [top](#table-of-contents) | +| [top](#objects) | :x_ray: | `:x_ray:` | | | [top](#table-of-contents) | + +### Household + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :door: | `:door:` | :elevator: | `:elevator:` | [top](#table-of-contents) | +| [top](#objects) | :mirror: | `:mirror:` | :window: | `:window:` | [top](#table-of-contents) | +| [top](#objects) | :bed: | `:bed:` | :couch_and_lamp: | `:couch_and_lamp:` | [top](#table-of-contents) | +| [top](#objects) | :chair: | `:chair:` | :toilet: | `:toilet:` | [top](#table-of-contents) | +| [top](#objects) | :plunger: | `:plunger:` | :shower: | `:shower:` | [top](#table-of-contents) | +| [top](#objects) | :bathtub: | `:bathtub:` | :mouse_trap: | `:mouse_trap:` | [top](#table-of-contents) | +| [top](#objects) | :razor: | `:razor:` | :lotion_bottle: | `:lotion_bottle:` | [top](#table-of-contents) | +| [top](#objects) | :safety_pin: | `:safety_pin:` | :broom: | `:broom:` | [top](#table-of-contents) | +| [top](#objects) | :basket: | `:basket:` | :roll_of_paper: | `:roll_of_paper:` | [top](#table-of-contents) | +| [top](#objects) | :bucket: | `:bucket:` | :soap: | `:soap:` | [top](#table-of-contents) | +| [top](#objects) | :bubbles: | `:bubbles:` | :toothbrush: | `:toothbrush:` | [top](#table-of-contents) | +| [top](#objects) | :sponge: | `:sponge:` | :fire_extinguisher: | `:fire_extinguisher:` | [top](#table-of-contents) | +| [top](#objects) | :shopping_cart: | `:shopping_cart:` | | | [top](#table-of-contents) | + +### Other Object + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#objects) | :smoking: | `:smoking:` | :coffin: | `:coffin:` | [top](#table-of-contents) | +| [top](#objects) | :headstone: | `:headstone:` | :funeral_urn: | `:funeral_urn:` | [top](#table-of-contents) | +| [top](#objects) | :nazar_amulet: | `:nazar_amulet:` | :hamsa: | `:hamsa:` | [top](#table-of-contents) | +| [top](#objects) | :moyai: | `:moyai:` | :placard: | `:placard:` | [top](#table-of-contents) | +| [top](#objects) | :identification_card: | `:identification_card:` | | | [top](#table-of-contents) | + +## Symbols + +- [Transport Sign](#transport-sign) +- [Warning](#warning) +- [Arrow](#arrow) +- [Religion](#religion) +- [Zodiac](#zodiac) +- [Av Symbol](#av-symbol) +- [Gender](#gender) +- [Math](#math) +- [Punctuation](#punctuation) +- [Currency](#currency) +- [Other Symbol](#other-symbol) +- [Keycap](#keycap) +- [Alphanum](#alphanum) +- [Geometric](#geometric) + +### Transport Sign + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :atm: | `:atm:` | :put_litter_in_its_place: | `:put_litter_in_its_place:` | [top](#table-of-contents) | +| [top](#symbols) | :potable_water: | `:potable_water:` | :wheelchair: | `:wheelchair:` | [top](#table-of-contents) | +| [top](#symbols) | :mens: | `:mens:` | :womens: | `:womens:` | [top](#table-of-contents) | +| [top](#symbols) | :restroom: | `:restroom:` | :baby_symbol: | `:baby_symbol:` | [top](#table-of-contents) | +| [top](#symbols) | :wc: | `:wc:` | :passport_control: | `:passport_control:` | [top](#table-of-contents) | +| [top](#symbols) | :customs: | `:customs:` | :baggage_claim: | `:baggage_claim:` | [top](#table-of-contents) | +| [top](#symbols) | :left_luggage: | `:left_luggage:` | | | [top](#table-of-contents) | + +### Warning + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :warning: | `:warning:` | :children_crossing: | `:children_crossing:` | [top](#table-of-contents) | +| [top](#symbols) | :no_entry: | `:no_entry:` | :no_entry_sign: | `:no_entry_sign:` | [top](#table-of-contents) | +| [top](#symbols) | :no_bicycles: | `:no_bicycles:` | :no_smoking: | `:no_smoking:` | [top](#table-of-contents) | +| [top](#symbols) | :do_not_litter: | `:do_not_litter:` | :non-potable_water: | `:non-potable_water:` | [top](#table-of-contents) | +| [top](#symbols) | :no_pedestrians: | `:no_pedestrians:` | :no_mobile_phones: | `:no_mobile_phones:` | [top](#table-of-contents) | +| [top](#symbols) | :underage: | `:underage:` | :radioactive: | `:radioactive:` | [top](#table-of-contents) | +| [top](#symbols) | :biohazard: | `:biohazard:` | | | [top](#table-of-contents) | + +### Arrow + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :arrow_up: | `:arrow_up:` | :arrow_upper_right: | `:arrow_upper_right:` | [top](#table-of-contents) | +| [top](#symbols) | :arrow_right: | `:arrow_right:` | :arrow_lower_right: | `:arrow_lower_right:` | [top](#table-of-contents) | +| [top](#symbols) | :arrow_down: | `:arrow_down:` | :arrow_lower_left: | `:arrow_lower_left:` | [top](#table-of-contents) | +| [top](#symbols) | :arrow_left: | `:arrow_left:` | :arrow_upper_left: | `:arrow_upper_left:` | [top](#table-of-contents) | +| [top](#symbols) | :arrow_up_down: | `:arrow_up_down:` | :left_right_arrow: | `:left_right_arrow:` | [top](#table-of-contents) | +| [top](#symbols) | :leftwards_arrow_with_hook: | `:leftwards_arrow_with_hook:` | :arrow_right_hook: | `:arrow_right_hook:` | [top](#table-of-contents) | +| [top](#symbols) | :arrow_heading_up: | `:arrow_heading_up:` | :arrow_heading_down: | `:arrow_heading_down:` | [top](#table-of-contents) | +| [top](#symbols) | :arrows_clockwise: | `:arrows_clockwise:` | :arrows_counterclockwise: | `:arrows_counterclockwise:` | [top](#table-of-contents) | +| [top](#symbols) | :back: | `:back:` | :end: | `:end:` | [top](#table-of-contents) | +| [top](#symbols) | :on: | `:on:` | :soon: | `:soon:` | [top](#table-of-contents) | +| [top](#symbols) | :top: | `:top:` | | | [top](#table-of-contents) | + +### Religion + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :place_of_worship: | `:place_of_worship:` | :atom_symbol: | `:atom_symbol:` | [top](#table-of-contents) | +| [top](#symbols) | :om: | `:om:` | :star_of_david: | `:star_of_david:` | [top](#table-of-contents) | +| [top](#symbols) | :wheel_of_dharma: | `:wheel_of_dharma:` | :yin_yang: | `:yin_yang:` | [top](#table-of-contents) | +| [top](#symbols) | :latin_cross: | `:latin_cross:` | :orthodox_cross: | `:orthodox_cross:` | [top](#table-of-contents) | +| [top](#symbols) | :star_and_crescent: | `:star_and_crescent:` | :peace_symbol: | `:peace_symbol:` | [top](#table-of-contents) | +| [top](#symbols) | :menorah: | `:menorah:` | :six_pointed_star: | `:six_pointed_star:` | [top](#table-of-contents) | +| [top](#symbols) | :khanda: | `:khanda:` | | | [top](#table-of-contents) | + +### Zodiac + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :aries: | `:aries:` | :taurus: | `:taurus:` | [top](#table-of-contents) | +| [top](#symbols) | :gemini: | `:gemini:` | :cancer: | `:cancer:` | [top](#table-of-contents) | +| [top](#symbols) | :leo: | `:leo:` | :virgo: | `:virgo:` | [top](#table-of-contents) | +| [top](#symbols) | :libra: | `:libra:` | :scorpius: | `:scorpius:` | [top](#table-of-contents) | +| [top](#symbols) | :sagittarius: | `:sagittarius:` | :capricorn: | `:capricorn:` | [top](#table-of-contents) | +| [top](#symbols) | :aquarius: | `:aquarius:` | :pisces: | `:pisces:` | [top](#table-of-contents) | +| [top](#symbols) | :ophiuchus: | `:ophiuchus:` | | | [top](#table-of-contents) | + +### Av Symbol + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :twisted_rightwards_arrows: | `:twisted_rightwards_arrows:` | :repeat: | `:repeat:` | [top](#table-of-contents) | +| [top](#symbols) | :repeat_one: | `:repeat_one:` | :arrow_forward: | `:arrow_forward:` | [top](#table-of-contents) | +| [top](#symbols) | :fast_forward: | `:fast_forward:` | :next_track_button: | `:next_track_button:` | [top](#table-of-contents) | +| [top](#symbols) | :play_or_pause_button: | `:play_or_pause_button:` | :arrow_backward: | `:arrow_backward:` | [top](#table-of-contents) | +| [top](#symbols) | :rewind: | `:rewind:` | :previous_track_button: | `:previous_track_button:` | [top](#table-of-contents) | +| [top](#symbols) | :arrow_up_small: | `:arrow_up_small:` | :arrow_double_up: | `:arrow_double_up:` | [top](#table-of-contents) | +| [top](#symbols) | :arrow_down_small: | `:arrow_down_small:` | :arrow_double_down: | `:arrow_double_down:` | [top](#table-of-contents) | +| [top](#symbols) | :pause_button: | `:pause_button:` | :stop_button: | `:stop_button:` | [top](#table-of-contents) | +| [top](#symbols) | :record_button: | `:record_button:` | :eject_button: | `:eject_button:` | [top](#table-of-contents) | +| [top](#symbols) | :cinema: | `:cinema:` | :low_brightness: | `:low_brightness:` | [top](#table-of-contents) | +| [top](#symbols) | :high_brightness: | `:high_brightness:` | :signal_strength: | `:signal_strength:` | [top](#table-of-contents) | +| [top](#symbols) | :wireless: | `:wireless:` | :vibration_mode: | `:vibration_mode:` | [top](#table-of-contents) | +| [top](#symbols) | :mobile_phone_off: | `:mobile_phone_off:` | | | [top](#table-of-contents) | + +### Gender + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :female_sign: | `:female_sign:` | :male_sign: | `:male_sign:` | [top](#table-of-contents) | +| [top](#symbols) | :transgender_symbol: | `:transgender_symbol:` | | | [top](#table-of-contents) | + +### Math + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :heavy_multiplication_x: | `:heavy_multiplication_x:` | :heavy_plus_sign: | `:heavy_plus_sign:` | [top](#table-of-contents) | +| [top](#symbols) | :heavy_minus_sign: | `:heavy_minus_sign:` | :heavy_division_sign: | `:heavy_division_sign:` | [top](#table-of-contents) | +| [top](#symbols) | :heavy_equals_sign: | `:heavy_equals_sign:` | :infinity: | `:infinity:` | [top](#table-of-contents) | + +### Punctuation + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :bangbang: | `:bangbang:` | :interrobang: | `:interrobang:` | [top](#table-of-contents) | +| [top](#symbols) | :question: | `:question:` | :grey_question: | `:grey_question:` | [top](#table-of-contents) | +| [top](#symbols) | :grey_exclamation: | `:grey_exclamation:` | :exclamation: | `:exclamation:` `:heavy_exclamation_mark:` | [top](#table-of-contents) | +| [top](#symbols) | :wavy_dash: | `:wavy_dash:` | | | [top](#table-of-contents) | + +### Currency + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :currency_exchange: | `:currency_exchange:` | :heavy_dollar_sign: | `:heavy_dollar_sign:` | [top](#table-of-contents) | + +### Other Symbol + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :medical_symbol: | `:medical_symbol:` | :recycle: | `:recycle:` | [top](#table-of-contents) | +| [top](#symbols) | :fleur_de_lis: | `:fleur_de_lis:` | :trident: | `:trident:` | [top](#table-of-contents) | +| [top](#symbols) | :name_badge: | `:name_badge:` | :beginner: | `:beginner:` | [top](#table-of-contents) | +| [top](#symbols) | :o: | `:o:` | :white_check_mark: | `:white_check_mark:` | [top](#table-of-contents) | +| [top](#symbols) | :ballot_box_with_check: | `:ballot_box_with_check:` | :heavy_check_mark: | `:heavy_check_mark:` | [top](#table-of-contents) | +| [top](#symbols) | :x: | `:x:` | :negative_squared_cross_mark: | `:negative_squared_cross_mark:` | [top](#table-of-contents) | +| [top](#symbols) | :curly_loop: | `:curly_loop:` | :loop: | `:loop:` | [top](#table-of-contents) | +| [top](#symbols) | :part_alternation_mark: | `:part_alternation_mark:` | :eight_spoked_asterisk: | `:eight_spoked_asterisk:` | [top](#table-of-contents) | +| [top](#symbols) | :eight_pointed_black_star: | `:eight_pointed_black_star:` | :sparkle: | `:sparkle:` | [top](#table-of-contents) | +| [top](#symbols) | :copyright: | `:copyright:` | :registered: | `:registered:` | [top](#table-of-contents) | +| [top](#symbols) | :tm: | `:tm:` | | | [top](#table-of-contents) | + +### Keycap + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :hash: | `:hash:` | :asterisk: | `:asterisk:` | [top](#table-of-contents) | +| [top](#symbols) | :zero: | `:zero:` | :one: | `:one:` | [top](#table-of-contents) | +| [top](#symbols) | :two: | `:two:` | :three: | `:three:` | [top](#table-of-contents) | +| [top](#symbols) | :four: | `:four:` | :five: | `:five:` | [top](#table-of-contents) | +| [top](#symbols) | :six: | `:six:` | :seven: | `:seven:` | [top](#table-of-contents) | +| [top](#symbols) | :eight: | `:eight:` | :nine: | `:nine:` | [top](#table-of-contents) | +| [top](#symbols) | :keycap_ten: | `:keycap_ten:` | | | [top](#table-of-contents) | + +### Alphanum + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :capital_abcd: | `:capital_abcd:` | :abcd: | `:abcd:` | [top](#table-of-contents) | +| [top](#symbols) | :1234: | `:1234:` | :symbols: | `:symbols:` | [top](#table-of-contents) | +| [top](#symbols) | :abc: | `:abc:` | :a: | `:a:` | [top](#table-of-contents) | +| [top](#symbols) | :ab: | `:ab:` | :b: | `:b:` | [top](#table-of-contents) | +| [top](#symbols) | :cl: | `:cl:` | :cool: | `:cool:` | [top](#table-of-contents) | +| [top](#symbols) | :free: | `:free:` | :information_source: | `:information_source:` | [top](#table-of-contents) | +| [top](#symbols) | :id: | `:id:` | :m: | `:m:` | [top](#table-of-contents) | +| [top](#symbols) | :new: | `:new:` | :ng: | `:ng:` | [top](#table-of-contents) | +| [top](#symbols) | :o2: | `:o2:` | :ok: | `:ok:` | [top](#table-of-contents) | +| [top](#symbols) | :parking: | `:parking:` | :sos: | `:sos:` | [top](#table-of-contents) | +| [top](#symbols) | :up: | `:up:` | :vs: | `:vs:` | [top](#table-of-contents) | +| [top](#symbols) | :koko: | `:koko:` | :sa: | `:sa:` | [top](#table-of-contents) | +| [top](#symbols) | :u6708: | `:u6708:` | :u6709: | `:u6709:` | [top](#table-of-contents) | +| [top](#symbols) | :u6307: | `:u6307:` | :ideograph_advantage: | `:ideograph_advantage:` | [top](#table-of-contents) | +| [top](#symbols) | :u5272: | `:u5272:` | :u7121: | `:u7121:` | [top](#table-of-contents) | +| [top](#symbols) | :u7981: | `:u7981:` | :accept: | `:accept:` | [top](#table-of-contents) | +| [top](#symbols) | :u7533: | `:u7533:` | :u5408: | `:u5408:` | [top](#table-of-contents) | +| [top](#symbols) | :u7a7a: | `:u7a7a:` | :congratulations: | `:congratulations:` | [top](#table-of-contents) | +| [top](#symbols) | :secret: | `:secret:` | :u55b6: | `:u55b6:` | [top](#table-of-contents) | +| [top](#symbols) | :u6e80: | `:u6e80:` | | | [top](#table-of-contents) | + +### Geometric + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#symbols) | :red_circle: | `:red_circle:` | :orange_circle: | `:orange_circle:` | [top](#table-of-contents) | +| [top](#symbols) | :yellow_circle: | `:yellow_circle:` | :green_circle: | `:green_circle:` | [top](#table-of-contents) | +| [top](#symbols) | :large_blue_circle: | `:large_blue_circle:` | :purple_circle: | `:purple_circle:` | [top](#table-of-contents) | +| [top](#symbols) | :brown_circle: | `:brown_circle:` | :black_circle: | `:black_circle:` | [top](#table-of-contents) | +| [top](#symbols) | :white_circle: | `:white_circle:` | :red_square: | `:red_square:` | [top](#table-of-contents) | +| [top](#symbols) | :orange_square: | `:orange_square:` | :yellow_square: | `:yellow_square:` | [top](#table-of-contents) | +| [top](#symbols) | :green_square: | `:green_square:` | :blue_square: | `:blue_square:` | [top](#table-of-contents) | +| [top](#symbols) | :purple_square: | `:purple_square:` | :brown_square: | `:brown_square:` | [top](#table-of-contents) | +| [top](#symbols) | :black_large_square: | `:black_large_square:` | :white_large_square: | `:white_large_square:` | [top](#table-of-contents) | +| [top](#symbols) | :black_medium_square: | `:black_medium_square:` | :white_medium_square: | `:white_medium_square:` | [top](#table-of-contents) | +| [top](#symbols) | :black_medium_small_square: | `:black_medium_small_square:` | :white_medium_small_square: | `:white_medium_small_square:` | [top](#table-of-contents) | +| [top](#symbols) | :black_small_square: | `:black_small_square:` | :white_small_square: | `:white_small_square:` | [top](#table-of-contents) | +| [top](#symbols) | :large_orange_diamond: | `:large_orange_diamond:` | :large_blue_diamond: | `:large_blue_diamond:` | [top](#table-of-contents) | +| [top](#symbols) | :small_orange_diamond: | `:small_orange_diamond:` | :small_blue_diamond: | `:small_blue_diamond:` | [top](#table-of-contents) | +| [top](#symbols) | :small_red_triangle: | `:small_red_triangle:` | :small_red_triangle_down: | `:small_red_triangle_down:` | [top](#table-of-contents) | +| [top](#symbols) | :diamond_shape_with_a_dot_inside: | `:diamond_shape_with_a_dot_inside:` | :radio_button: | `:radio_button:` | [top](#table-of-contents) | +| [top](#symbols) | :white_square_button: | `:white_square_button:` | :black_square_button: | `:black_square_button:` | [top](#table-of-contents) | + +## Flags + +- [Flag](#flag) +- [Country Flag](#country-flag) +- [Subdivision Flag](#subdivision-flag) + +### Flag + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#flags) | :checkered_flag: | `:checkered_flag:` | :triangular_flag_on_post: | `:triangular_flag_on_post:` | [top](#table-of-contents) | +| [top](#flags) | :crossed_flags: | `:crossed_flags:` | :black_flag: | `:black_flag:` | [top](#table-of-contents) | +| [top](#flags) | :white_flag: | `:white_flag:` | :rainbow_flag: | `:rainbow_flag:` | [top](#table-of-contents) | +| [top](#flags) | :transgender_flag: | `:transgender_flag:` | :pirate_flag: | `:pirate_flag:` | [top](#table-of-contents) | + +### Country Flag + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#flags) | :ascension_island: | `:ascension_island:` | :andorra: | `:andorra:` | [top](#table-of-contents) | +| [top](#flags) | :united_arab_emirates: | `:united_arab_emirates:` | :afghanistan: | `:afghanistan:` | [top](#table-of-contents) | +| [top](#flags) | :antigua_barbuda: | `:antigua_barbuda:` | :anguilla: | `:anguilla:` | [top](#table-of-contents) | +| [top](#flags) | :albania: | `:albania:` | :armenia: | `:armenia:` | [top](#table-of-contents) | +| [top](#flags) | :angola: | `:angola:` | :antarctica: | `:antarctica:` | [top](#table-of-contents) | +| [top](#flags) | :argentina: | `:argentina:` | :american_samoa: | `:american_samoa:` | [top](#table-of-contents) | +| [top](#flags) | :austria: | `:austria:` | :australia: | `:australia:` | [top](#table-of-contents) | +| [top](#flags) | :aruba: | `:aruba:` | :aland_islands: | `:aland_islands:` | [top](#table-of-contents) | +| [top](#flags) | :azerbaijan: | `:azerbaijan:` | :bosnia_herzegovina: | `:bosnia_herzegovina:` | [top](#table-of-contents) | +| [top](#flags) | :barbados: | `:barbados:` | :bangladesh: | `:bangladesh:` | [top](#table-of-contents) | +| [top](#flags) | :belgium: | `:belgium:` | :burkina_faso: | `:burkina_faso:` | [top](#table-of-contents) | +| [top](#flags) | :bulgaria: | `:bulgaria:` | :bahrain: | `:bahrain:` | [top](#table-of-contents) | +| [top](#flags) | :burundi: | `:burundi:` | :benin: | `:benin:` | [top](#table-of-contents) | +| [top](#flags) | :st_barthelemy: | `:st_barthelemy:` | :bermuda: | `:bermuda:` | [top](#table-of-contents) | +| [top](#flags) | :brunei: | `:brunei:` | :bolivia: | `:bolivia:` | [top](#table-of-contents) | +| [top](#flags) | :caribbean_netherlands: | `:caribbean_netherlands:` | :brazil: | `:brazil:` | [top](#table-of-contents) | +| [top](#flags) | :bahamas: | `:bahamas:` | :bhutan: | `:bhutan:` | [top](#table-of-contents) | +| [top](#flags) | :bouvet_island: | `:bouvet_island:` | :botswana: | `:botswana:` | [top](#table-of-contents) | +| [top](#flags) | :belarus: | `:belarus:` | :belize: | `:belize:` | [top](#table-of-contents) | +| [top](#flags) | :canada: | `:canada:` | :cocos_islands: | `:cocos_islands:` | [top](#table-of-contents) | +| [top](#flags) | :congo_kinshasa: | `:congo_kinshasa:` | :central_african_republic: | `:central_african_republic:` | [top](#table-of-contents) | +| [top](#flags) | :congo_brazzaville: | `:congo_brazzaville:` | :switzerland: | `:switzerland:` | [top](#table-of-contents) | +| [top](#flags) | :cote_divoire: | `:cote_divoire:` | :cook_islands: | `:cook_islands:` | [top](#table-of-contents) | +| [top](#flags) | :chile: | `:chile:` | :cameroon: | `:cameroon:` | [top](#table-of-contents) | +| [top](#flags) | :cn: | `:cn:` | :colombia: | `:colombia:` | [top](#table-of-contents) | +| [top](#flags) | :clipperton_island: | `:clipperton_island:` | :costa_rica: | `:costa_rica:` | [top](#table-of-contents) | +| [top](#flags) | :cuba: | `:cuba:` | :cape_verde: | `:cape_verde:` | [top](#table-of-contents) | +| [top](#flags) | :curacao: | `:curacao:` | :christmas_island: | `:christmas_island:` | [top](#table-of-contents) | +| [top](#flags) | :cyprus: | `:cyprus:` | :czech_republic: | `:czech_republic:` | [top](#table-of-contents) | +| [top](#flags) | :de: | `:de:` | :diego_garcia: | `:diego_garcia:` | [top](#table-of-contents) | +| [top](#flags) | :djibouti: | `:djibouti:` | :denmark: | `:denmark:` | [top](#table-of-contents) | +| [top](#flags) | :dominica: | `:dominica:` | :dominican_republic: | `:dominican_republic:` | [top](#table-of-contents) | +| [top](#flags) | :algeria: | `:algeria:` | :ceuta_melilla: | `:ceuta_melilla:` | [top](#table-of-contents) | +| [top](#flags) | :ecuador: | `:ecuador:` | :estonia: | `:estonia:` | [top](#table-of-contents) | +| [top](#flags) | :egypt: | `:egypt:` | :western_sahara: | `:western_sahara:` | [top](#table-of-contents) | +| [top](#flags) | :eritrea: | `:eritrea:` | :es: | `:es:` | [top](#table-of-contents) | +| [top](#flags) | :ethiopia: | `:ethiopia:` | :eu: | `:eu:` `:european_union:` | [top](#table-of-contents) | +| [top](#flags) | :finland: | `:finland:` | :fiji: | `:fiji:` | [top](#table-of-contents) | +| [top](#flags) | :falkland_islands: | `:falkland_islands:` | :micronesia: | `:micronesia:` | [top](#table-of-contents) | +| [top](#flags) | :faroe_islands: | `:faroe_islands:` | :fr: | `:fr:` | [top](#table-of-contents) | +| [top](#flags) | :gabon: | `:gabon:` | :gb: | `:gb:` `:uk:` | [top](#table-of-contents) | +| [top](#flags) | :grenada: | `:grenada:` | :georgia: | `:georgia:` | [top](#table-of-contents) | +| [top](#flags) | :french_guiana: | `:french_guiana:` | :guernsey: | `:guernsey:` | [top](#table-of-contents) | +| [top](#flags) | :ghana: | `:ghana:` | :gibraltar: | `:gibraltar:` | [top](#table-of-contents) | +| [top](#flags) | :greenland: | `:greenland:` | :gambia: | `:gambia:` | [top](#table-of-contents) | +| [top](#flags) | :guinea: | `:guinea:` | :guadeloupe: | `:guadeloupe:` | [top](#table-of-contents) | +| [top](#flags) | :equatorial_guinea: | `:equatorial_guinea:` | :greece: | `:greece:` | [top](#table-of-contents) | +| [top](#flags) | :south_georgia_south_sandwich_islands: | `:south_georgia_south_sandwich_islands:` | :guatemala: | `:guatemala:` | [top](#table-of-contents) | +| [top](#flags) | :guam: | `:guam:` | :guinea_bissau: | `:guinea_bissau:` | [top](#table-of-contents) | +| [top](#flags) | :guyana: | `:guyana:` | :hong_kong: | `:hong_kong:` | [top](#table-of-contents) | +| [top](#flags) | :heard_mcdonald_islands: | `:heard_mcdonald_islands:` | :honduras: | `:honduras:` | [top](#table-of-contents) | +| [top](#flags) | :croatia: | `:croatia:` | :haiti: | `:haiti:` | [top](#table-of-contents) | +| [top](#flags) | :hungary: | `:hungary:` | :canary_islands: | `:canary_islands:` | [top](#table-of-contents) | +| [top](#flags) | :indonesia: | `:indonesia:` | :ireland: | `:ireland:` | [top](#table-of-contents) | +| [top](#flags) | :israel: | `:israel:` | :isle_of_man: | `:isle_of_man:` | [top](#table-of-contents) | +| [top](#flags) | :india: | `:india:` | :british_indian_ocean_territory: | `:british_indian_ocean_territory:` | [top](#table-of-contents) | +| [top](#flags) | :iraq: | `:iraq:` | :iran: | `:iran:` | [top](#table-of-contents) | +| [top](#flags) | :iceland: | `:iceland:` | :it: | `:it:` | [top](#table-of-contents) | +| [top](#flags) | :jersey: | `:jersey:` | :jamaica: | `:jamaica:` | [top](#table-of-contents) | +| [top](#flags) | :jordan: | `:jordan:` | :jp: | `:jp:` | [top](#table-of-contents) | +| [top](#flags) | :kenya: | `:kenya:` | :kyrgyzstan: | `:kyrgyzstan:` | [top](#table-of-contents) | +| [top](#flags) | :cambodia: | `:cambodia:` | :kiribati: | `:kiribati:` | [top](#table-of-contents) | +| [top](#flags) | :comoros: | `:comoros:` | :st_kitts_nevis: | `:st_kitts_nevis:` | [top](#table-of-contents) | +| [top](#flags) | :north_korea: | `:north_korea:` | :kr: | `:kr:` | [top](#table-of-contents) | +| [top](#flags) | :kuwait: | `:kuwait:` | :cayman_islands: | `:cayman_islands:` | [top](#table-of-contents) | +| [top](#flags) | :kazakhstan: | `:kazakhstan:` | :laos: | `:laos:` | [top](#table-of-contents) | +| [top](#flags) | :lebanon: | `:lebanon:` | :st_lucia: | `:st_lucia:` | [top](#table-of-contents) | +| [top](#flags) | :liechtenstein: | `:liechtenstein:` | :sri_lanka: | `:sri_lanka:` | [top](#table-of-contents) | +| [top](#flags) | :liberia: | `:liberia:` | :lesotho: | `:lesotho:` | [top](#table-of-contents) | +| [top](#flags) | :lithuania: | `:lithuania:` | :luxembourg: | `:luxembourg:` | [top](#table-of-contents) | +| [top](#flags) | :latvia: | `:latvia:` | :libya: | `:libya:` | [top](#table-of-contents) | +| [top](#flags) | :morocco: | `:morocco:` | :monaco: | `:monaco:` | [top](#table-of-contents) | +| [top](#flags) | :moldova: | `:moldova:` | :montenegro: | `:montenegro:` | [top](#table-of-contents) | +| [top](#flags) | :st_martin: | `:st_martin:` | :madagascar: | `:madagascar:` | [top](#table-of-contents) | +| [top](#flags) | :marshall_islands: | `:marshall_islands:` | :macedonia: | `:macedonia:` | [top](#table-of-contents) | +| [top](#flags) | :mali: | `:mali:` | :myanmar: | `:myanmar:` | [top](#table-of-contents) | +| [top](#flags) | :mongolia: | `:mongolia:` | :macau: | `:macau:` | [top](#table-of-contents) | +| [top](#flags) | :northern_mariana_islands: | `:northern_mariana_islands:` | :martinique: | `:martinique:` | [top](#table-of-contents) | +| [top](#flags) | :mauritania: | `:mauritania:` | :montserrat: | `:montserrat:` | [top](#table-of-contents) | +| [top](#flags) | :malta: | `:malta:` | :mauritius: | `:mauritius:` | [top](#table-of-contents) | +| [top](#flags) | :maldives: | `:maldives:` | :malawi: | `:malawi:` | [top](#table-of-contents) | +| [top](#flags) | :mexico: | `:mexico:` | :malaysia: | `:malaysia:` | [top](#table-of-contents) | +| [top](#flags) | :mozambique: | `:mozambique:` | :namibia: | `:namibia:` | [top](#table-of-contents) | +| [top](#flags) | :new_caledonia: | `:new_caledonia:` | :niger: | `:niger:` | [top](#table-of-contents) | +| [top](#flags) | :norfolk_island: | `:norfolk_island:` | :nigeria: | `:nigeria:` | [top](#table-of-contents) | +| [top](#flags) | :nicaragua: | `:nicaragua:` | :netherlands: | `:netherlands:` | [top](#table-of-contents) | +| [top](#flags) | :norway: | `:norway:` | :nepal: | `:nepal:` | [top](#table-of-contents) | +| [top](#flags) | :nauru: | `:nauru:` | :niue: | `:niue:` | [top](#table-of-contents) | +| [top](#flags) | :new_zealand: | `:new_zealand:` | :oman: | `:oman:` | [top](#table-of-contents) | +| [top](#flags) | :panama: | `:panama:` | :peru: | `:peru:` | [top](#table-of-contents) | +| [top](#flags) | :french_polynesia: | `:french_polynesia:` | :papua_new_guinea: | `:papua_new_guinea:` | [top](#table-of-contents) | +| [top](#flags) | :philippines: | `:philippines:` | :pakistan: | `:pakistan:` | [top](#table-of-contents) | +| [top](#flags) | :poland: | `:poland:` | :st_pierre_miquelon: | `:st_pierre_miquelon:` | [top](#table-of-contents) | +| [top](#flags) | :pitcairn_islands: | `:pitcairn_islands:` | :puerto_rico: | `:puerto_rico:` | [top](#table-of-contents) | +| [top](#flags) | :palestinian_territories: | `:palestinian_territories:` | :portugal: | `:portugal:` | [top](#table-of-contents) | +| [top](#flags) | :palau: | `:palau:` | :paraguay: | `:paraguay:` | [top](#table-of-contents) | +| [top](#flags) | :qatar: | `:qatar:` | :reunion: | `:reunion:` | [top](#table-of-contents) | +| [top](#flags) | :romania: | `:romania:` | :serbia: | `:serbia:` | [top](#table-of-contents) | +| [top](#flags) | :ru: | `:ru:` | :rwanda: | `:rwanda:` | [top](#table-of-contents) | +| [top](#flags) | :saudi_arabia: | `:saudi_arabia:` | :solomon_islands: | `:solomon_islands:` | [top](#table-of-contents) | +| [top](#flags) | :seychelles: | `:seychelles:` | :sudan: | `:sudan:` | [top](#table-of-contents) | +| [top](#flags) | :sweden: | `:sweden:` | :singapore: | `:singapore:` | [top](#table-of-contents) | +| [top](#flags) | :st_helena: | `:st_helena:` | :slovenia: | `:slovenia:` | [top](#table-of-contents) | +| [top](#flags) | :svalbard_jan_mayen: | `:svalbard_jan_mayen:` | :slovakia: | `:slovakia:` | [top](#table-of-contents) | +| [top](#flags) | :sierra_leone: | `:sierra_leone:` | :san_marino: | `:san_marino:` | [top](#table-of-contents) | +| [top](#flags) | :senegal: | `:senegal:` | :somalia: | `:somalia:` | [top](#table-of-contents) | +| [top](#flags) | :suriname: | `:suriname:` | :south_sudan: | `:south_sudan:` | [top](#table-of-contents) | +| [top](#flags) | :sao_tome_principe: | `:sao_tome_principe:` | :el_salvador: | `:el_salvador:` | [top](#table-of-contents) | +| [top](#flags) | :sint_maarten: | `:sint_maarten:` | :syria: | `:syria:` | [top](#table-of-contents) | +| [top](#flags) | :swaziland: | `:swaziland:` | :tristan_da_cunha: | `:tristan_da_cunha:` | [top](#table-of-contents) | +| [top](#flags) | :turks_caicos_islands: | `:turks_caicos_islands:` | :chad: | `:chad:` | [top](#table-of-contents) | +| [top](#flags) | :french_southern_territories: | `:french_southern_territories:` | :togo: | `:togo:` | [top](#table-of-contents) | +| [top](#flags) | :thailand: | `:thailand:` | :tajikistan: | `:tajikistan:` | [top](#table-of-contents) | +| [top](#flags) | :tokelau: | `:tokelau:` | :timor_leste: | `:timor_leste:` | [top](#table-of-contents) | +| [top](#flags) | :turkmenistan: | `:turkmenistan:` | :tunisia: | `:tunisia:` | [top](#table-of-contents) | +| [top](#flags) | :tonga: | `:tonga:` | :tr: | `:tr:` | [top](#table-of-contents) | +| [top](#flags) | :trinidad_tobago: | `:trinidad_tobago:` | :tuvalu: | `:tuvalu:` | [top](#table-of-contents) | +| [top](#flags) | :taiwan: | `:taiwan:` | :tanzania: | `:tanzania:` | [top](#table-of-contents) | +| [top](#flags) | :ukraine: | `:ukraine:` | :uganda: | `:uganda:` | [top](#table-of-contents) | +| [top](#flags) | :us_outlying_islands: | `:us_outlying_islands:` | :united_nations: | `:united_nations:` | [top](#table-of-contents) | +| [top](#flags) | :us: | `:us:` | :uruguay: | `:uruguay:` | [top](#table-of-contents) | +| [top](#flags) | :uzbekistan: | `:uzbekistan:` | :vatican_city: | `:vatican_city:` | [top](#table-of-contents) | +| [top](#flags) | :st_vincent_grenadines: | `:st_vincent_grenadines:` | :venezuela: | `:venezuela:` | [top](#table-of-contents) | +| [top](#flags) | :british_virgin_islands: | `:british_virgin_islands:` | :us_virgin_islands: | `:us_virgin_islands:` | [top](#table-of-contents) | +| [top](#flags) | :vietnam: | `:vietnam:` | :vanuatu: | `:vanuatu:` | [top](#table-of-contents) | +| [top](#flags) | :wallis_futuna: | `:wallis_futuna:` | :samoa: | `:samoa:` | [top](#table-of-contents) | +| [top](#flags) | :kosovo: | `:kosovo:` | :yemen: | `:yemen:` | [top](#table-of-contents) | +| [top](#flags) | :mayotte: | `:mayotte:` | :south_africa: | `:south_africa:` | [top](#table-of-contents) | +| [top](#flags) | :zambia: | `:zambia:` | :zimbabwe: | `:zimbabwe:` | [top](#table-of-contents) | + +### Subdivision Flag + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#flags) | :england: | `:england:` | :scotland: | `:scotland:` | [top](#table-of-contents) | +| [top](#flags) | :wales: | `:wales:` | | | [top](#table-of-contents) | + +## GitHub Custom Emoji + +| | ico | shortcode | ico | shortcode | | +| - | :-: | - | :-: | - | - | +| [top](#github-custom-emoji) | :accessibility: | `:accessibility:` | :atom: | `:atom:` | [top](#table-of-contents) | +| [top](#github-custom-emoji) | :basecamp: | `:basecamp:` | :basecampy: | `:basecampy:` | [top](#table-of-contents) | +| [top](#github-custom-emoji) | :bowtie: | `:bowtie:` | :dependabot: | `:dependabot:` | [top](#table-of-contents) | +| [top](#github-custom-emoji) | :electron: | `:electron:` | :feelsgood: | `:feelsgood:` | [top](#table-of-contents) | +| [top](#github-custom-emoji) | :finnadie: | `:finnadie:` | :fishsticks: | `:fishsticks:` | [top](#table-of-contents) | +| [top](#github-custom-emoji) | :goberserk: | `:goberserk:` | :godmode: | `:godmode:` | [top](#table-of-contents) | +| [top](#github-custom-emoji) | :hurtrealbad: | `:hurtrealbad:` | :neckbeard: | `:neckbeard:` | [top](#table-of-contents) | +| [top](#github-custom-emoji) | :octocat: | `:octocat:` | :rage1: | `:rage1:` | [top](#table-of-contents) | +| [top](#github-custom-emoji) | :rage2: | `:rage2:` | :rage3: | `:rage3:` | [top](#table-of-contents) | +| [top](#github-custom-emoji) | :rage4: | `:rage4:` | :shipit: | `:shipit:` | [top](#table-of-contents) | +| [top](#github-custom-emoji) | :suspect: | `:suspect:` | :trollface: | `:trollface:` | [top](#table-of-contents) | diff --git a/docs/content/en/quick-reference/functions.md b/docs/content/en/quick-reference/functions.md new file mode 100644 index 000000000..72235d0f3 --- /dev/null +++ b/docs/content/en/quick-reference/functions.md @@ -0,0 +1,8 @@ +--- +title: Functions +description: A quick reference guide to Hugo's functions, grouped by namespace. Aliases, if any, appear in parentheses to the right of the function name. +categories: [] +keywords: [] +--- + +{{% quick-reference section="functions" %}} diff --git a/docs/content/en/quick-reference/glossary/_index.md b/docs/content/en/quick-reference/glossary/_index.md new file mode 100644 index 000000000..42894c4da --- /dev/null +++ b/docs/content/en/quick-reference/glossary/_index.md @@ -0,0 +1,19 @@ +--- +title: Glossary +description: Terms commonly used throughout the documentation. +categories: [] +keywords: [] +build: + render: always + list: always +cascade: + build: + render: never + list: local +layout: single +params: + hide_in_this_section: true +aliases: [/getting-started/glossary/] +--- + +{{% glossary %}} diff --git a/docs/content/en/quick-reference/glossary/action.md b/docs/content/en/quick-reference/glossary/action.md new file mode 100644 index 000000000..ced877327 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/action.md @@ -0,0 +1,5 @@ +--- +title: action +--- + +See [_template action_](g). diff --git a/docs/content/en/quick-reference/glossary/archetype.md b/docs/content/en/quick-reference/glossary/archetype.md new file mode 100644 index 000000000..231089c56 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/archetype.md @@ -0,0 +1,6 @@ +--- +title: archetype +details: /content-management/archetypes +--- + +An _archetype_ is a template for new content. diff --git a/docs/content/en/quick-reference/glossary/argument.md b/docs/content/en/quick-reference/glossary/argument.md new file mode 100644 index 000000000..912951d2b --- /dev/null +++ b/docs/content/en/quick-reference/glossary/argument.md @@ -0,0 +1,5 @@ +--- +title: argument +--- + +An _argument_ is a [_scalar_](g), [_array_](g), [_slice_](g), [_map_](g), or [_object_](g) passed to a [_function_](g), [_method_](g), or [_shortcode_](g). diff --git a/docs/content/en/quick-reference/glossary/array.md b/docs/content/en/quick-reference/glossary/array.md new file mode 100644 index 000000000..0df45f212 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/array.md @@ -0,0 +1,6 @@ +--- +title: array +reference: https://go.dev/ref/spec#Array_types +--- + +An _array_ is a numbered sequence of [_elements_](g). Unlike Go's [_slice_](g) data type, an array has a fixed length. Elements within an array can be [_scalars_](g), slices, [_maps_](g), pages, or other arrays. diff --git a/docs/content/en/quick-reference/glossary/asset-pipeline.md b/docs/content/en/quick-reference/glossary/asset-pipeline.md new file mode 100644 index 000000000..5f3264a6e --- /dev/null +++ b/docs/content/en/quick-reference/glossary/asset-pipeline.md @@ -0,0 +1,5 @@ +--- +title: asset pipeline +--- + +An _asset pipeline_ is a system that automates and optimizes the handling of static assets like images, stylesheets, and JavaScript files. diff --git a/docs/content/en/quick-reference/glossary/bool.md b/docs/content/en/quick-reference/glossary/bool.md new file mode 100644 index 000000000..a4f33b5b9 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/bool.md @@ -0,0 +1,5 @@ +--- +title: bool +--- + +See [_boolean_](g). diff --git a/docs/content/en/quick-reference/glossary/boolean.md b/docs/content/en/quick-reference/glossary/boolean.md new file mode 100644 index 000000000..e727c40b0 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/boolean.md @@ -0,0 +1,5 @@ +--- +title: boolean +--- + +A _boolean_ is a data type with two possible values, either `true` or `false`. diff --git a/docs/content/en/quick-reference/glossary/branch-bundle.md b/docs/content/en/quick-reference/glossary/branch-bundle.md new file mode 100644 index 000000000..d5688ba0b --- /dev/null +++ b/docs/content/en/quick-reference/glossary/branch-bundle.md @@ -0,0 +1,6 @@ +--- +title: branch bundle +reference: /content-management/page-bundles +--- + +A _branch bundle_ is a top-level content directory or any content directory containing an `_index.md` file. Analogous to a physical branch, a branch bundle may have descendants including [_leaf bundles_](g) and other branch bundles. A branch bundle may also contain [_page resources_](g) such as images. diff --git a/docs/content/en/quick-reference/glossary/build.md b/docs/content/en/quick-reference/glossary/build.md new file mode 100644 index 000000000..79b7ec74a --- /dev/null +++ b/docs/content/en/quick-reference/glossary/build.md @@ -0,0 +1,5 @@ +--- +title: build +--- + +To _build_ a site is to generate HTML files and assets such as images, CSS files, and JavaScript files. The build process includes rendering and resource transformations. diff --git a/docs/content/en/quick-reference/glossary/bundle.md b/docs/content/en/quick-reference/glossary/bundle.md new file mode 100644 index 000000000..f30187811 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/bundle.md @@ -0,0 +1,5 @@ +--- +title: bundle +--- + +See [page bundle](g). diff --git a/docs/content/en/quick-reference/glossary/cache.md b/docs/content/en/quick-reference/glossary/cache.md new file mode 100644 index 000000000..a86068e4a --- /dev/null +++ b/docs/content/en/quick-reference/glossary/cache.md @@ -0,0 +1,5 @@ +--- +title: cache +--- + +A _cache_ is a software component that stores data so that future requests for the same data are faster. diff --git a/docs/content/en/quick-reference/glossary/chain.md b/docs/content/en/quick-reference/glossary/chain.md new file mode 100644 index 000000000..bbbc14f49 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/chain.md @@ -0,0 +1,5 @@ +--- +title: chain +--- + +To _chain_ is to connect one or more [_identifiers_](g) with a dot. An identifier can represent a [_method_](g), [_object_](g), or [_field_](g). For example, `.Site.Params.author.name` or `.Date.UTC.Hour`. diff --git a/docs/content/en/quick-reference/glossary/cicd.md b/docs/content/en/quick-reference/glossary/cicd.md new file mode 100644 index 000000000..355097b1b --- /dev/null +++ b/docs/content/en/quick-reference/glossary/cicd.md @@ -0,0 +1,7 @@ +--- +title: CI/CD +params: + reference: https://en.wikipedia.org/wiki/CI/CD +--- + +The term _CI/CD_ is an abbreviation for Continuous Integration and Continuous Delivery or Continuous Deployment depending on context. diff --git a/docs/content/en/quick-reference/glossary/cjk.md b/docs/content/en/quick-reference/glossary/cjk.md new file mode 100644 index 000000000..05a294d44 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/cjk.md @@ -0,0 +1,5 @@ +--- +title: CJK +--- + +_CJK_ is a collective term for the Chinese, Japanese, and Korean languages. diff --git a/docs/content/en/quick-reference/glossary/cli.md b/docs/content/en/quick-reference/glossary/cli.md new file mode 100644 index 000000000..8f898e364 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/cli.md @@ -0,0 +1,5 @@ +--- +title: CLI +--- + +_CLI_ stands for command-line interface, a text-based method for interacting with computer programs or operating systems. diff --git a/docs/content/en/quick-reference/glossary/collection.md b/docs/content/en/quick-reference/glossary/collection.md new file mode 100644 index 000000000..30e1ef805 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/collection.md @@ -0,0 +1,5 @@ +--- +title: collection +--- + +A _collection_ is an [_array_](g), [_slice_](g), or [_map_](g). diff --git a/docs/content/en/quick-reference/glossary/content-adapter.md b/docs/content/en/quick-reference/glossary/content-adapter.md new file mode 100644 index 000000000..974e61dca --- /dev/null +++ b/docs/content/en/quick-reference/glossary/content-adapter.md @@ -0,0 +1,6 @@ +--- +title: content adapter +reference: /content-management/content-adapters +--- + +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. diff --git a/docs/content/en/quick-reference/glossary/content-format.md b/docs/content/en/quick-reference/glossary/content-format.md new file mode 100644 index 000000000..ea459deb7 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/content-format.md @@ -0,0 +1,6 @@ +--- +title: content format +reference: /content-management/formats +--- + +A _content format_ is a markup language for creating content. Typically Markdown, but may also be HTML, AsciiDoc, Org, Pandoc, or reStructuredText. diff --git a/docs/content/en/quick-reference/glossary/content-type.md b/docs/content/en/quick-reference/glossary/content-type.md new file mode 100644 index 000000000..b7ebc5be4 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/content-type.md @@ -0,0 +1,6 @@ +--- +title: content type +reference: /content-management/types +--- + +A _content type_ is a classification of content inferred from the top-level directory name or the `type` set in [front matter](g). Pages in the root of the `content` directory, including the home page, are of type "page". Accessed via `.Page.Type` in [_templates_](g). diff --git a/docs/content/en/quick-reference/glossary/content-view.md b/docs/content/en/quick-reference/glossary/content-view.md new file mode 100644 index 000000000..009981cb5 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/content-view.md @@ -0,0 +1,6 @@ +--- +title: content view +reference: /templates/content-view +--- + +A _content view_ is a template called with the [`Render`](/methods/page/render/) method on a `Page` object. diff --git a/docs/content/en/quick-reference/glossary/context.md b/docs/content/en/quick-reference/glossary/context.md new file mode 100644 index 000000000..75afc709d --- /dev/null +++ b/docs/content/en/quick-reference/glossary/context.md @@ -0,0 +1,6 @@ +--- +title: context +reference: /templates/introduction/#context +--- + +Represented by a dot (`.`) within a [_template action_](g), _context_ is the current location in a data structure. For example, while iterating over a [_collection_](g) of pages, the context within each iteration is the page's data structure. The context received by each template depends on template type and/or how it was called. diff --git a/docs/content/en/quick-reference/glossary/default-sort-order.md b/docs/content/en/quick-reference/glossary/default-sort-order.md new file mode 100644 index 000000000..9b981a7e9 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/default-sort-order.md @@ -0,0 +1,10 @@ +--- +title: default sort order +--- + +The _default sort order_ for [_page collections_](g), used when no other criteria are set, follows this priority: + + 1. [`weight`](/content-management/front-matter/#weight) (ascending) + 1. [`date`](/content-management/front-matter/#date) (descending) + 1. [`linkTitle`](/content-management/front-matter/#linktitle) falling back to [`title`](/content-management/front-matter/#title) (ascending) + 1. [logical path](g) (ascending) diff --git a/docs/content/en/quick-reference/glossary/duration.md b/docs/content/en/quick-reference/glossary/duration.md new file mode 100644 index 000000000..21fd3c832 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/duration.md @@ -0,0 +1,5 @@ +--- +title: duration +--- + +A _duration_ is a data type that represent a length of time, expressed using units such as seconds (represented by `s`), minutes (represented by `m`), and hours (represented by `h`). For example, `42s` means 42 seconds, `6m7s` means 6 minutes and 7 seconds, and `6h7m42s` means 6 hours, 7 minutes, and 42 seconds. diff --git a/docs/content/en/quick-reference/glossary/element.md b/docs/content/en/quick-reference/glossary/element.md new file mode 100644 index 000000000..39f5df656 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/element.md @@ -0,0 +1,5 @@ +--- +title: element +--- + +An _element_ is a member of a [_slice_](g) or [_array_](g). diff --git a/docs/content/en/quick-reference/glossary/embedded-template.md b/docs/content/en/quick-reference/glossary/embedded-template.md new file mode 100644 index 000000000..3a0871690 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/embedded-template.md @@ -0,0 +1,5 @@ +--- +title: embedded template +--- + +An _embedded template_ is a built-in component within the Hugo application. This includes features like [_partials_](g), [_shortcodes_](g), and [_render hooks_](g) that provide pre-defined structures or functionalities for creating website content. diff --git a/docs/content/en/quick-reference/glossary/environment.md b/docs/content/en/quick-reference/glossary/environment.md new file mode 100644 index 000000000..ebba0ccdf --- /dev/null +++ b/docs/content/en/quick-reference/glossary/environment.md @@ -0,0 +1,9 @@ +--- +title: environment +--- + +Typically one of `development`, `staging`, or `production`, each _environment_ may exhibit different behavior depending on configuration and template logic. For example, in a production environment you might minify and fingerprint CSS, but that probably doesn't make sense in a development environment. + + When running the built-in development server with the `hugo server` command, the environment is set to `development`. When building your site with the `hugo` command, the environment is set to `production`. To override the environment value, use the `--environment` command line flag or the `HUGO_ENVIRONMENT` environment variable. + + To determine the current environment within a template, use the [`hugo.Environment`](/functions/hugo/environment/) function. diff --git a/docs/content/en/quick-reference/glossary/field.md b/docs/content/en/quick-reference/glossary/field.md new file mode 100644 index 000000000..a32eb3a6b --- /dev/null +++ b/docs/content/en/quick-reference/glossary/field.md @@ -0,0 +1,5 @@ +--- +title: field +--- + +A _field_ is a predefined key-value pair in front matter such as `date` or `title`. diff --git a/docs/content/en/quick-reference/glossary/flag.md b/docs/content/en/quick-reference/glossary/flag.md new file mode 100644 index 000000000..e7b6c5746 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/flag.md @@ -0,0 +1,6 @@ +--- +title: flag +reference: /commands/hugo +--- + +A _flag_ is an option passed to a command-line program, beginning with one or two hyphens. diff --git a/docs/content/en/quick-reference/glossary/float.md b/docs/content/en/quick-reference/glossary/float.md new file mode 100644 index 000000000..86f2c8ffb --- /dev/null +++ b/docs/content/en/quick-reference/glossary/float.md @@ -0,0 +1,6 @@ +--- +title: float +alias: true +--- + +See [floating point](g). diff --git a/docs/content/en/quick-reference/glossary/floating-point.md b/docs/content/en/quick-reference/glossary/floating-point.md new file mode 100644 index 000000000..38ba9f012 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/floating-point.md @@ -0,0 +1,5 @@ +--- +title: floating point +--- + +The term _floating point_ refers to a numeric data type with a fractional component. For example, `3.14159`. diff --git a/docs/content/en/quick-reference/glossary/fragment.md b/docs/content/en/quick-reference/glossary/fragment.md new file mode 100644 index 000000000..57ef1b4ef --- /dev/null +++ b/docs/content/en/quick-reference/glossary/fragment.md @@ -0,0 +1,5 @@ +--- +title: fragment +--- + +A _fragment_ is the final segment of a URL, beginning with a hash (`#`) mark, that references an `id` attribute of an HTML element on the page. diff --git a/docs/content/en/quick-reference/glossary/front-matter.md b/docs/content/en/quick-reference/glossary/front-matter.md new file mode 100644 index 000000000..5a3cd3040 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/front-matter.md @@ -0,0 +1,6 @@ +--- +title: front matter +reference: /content-management/front-matter +--- + +The term _front matter_ refers to the metadata at the beginning of each content page, separated from the content by format-specific delimiters. diff --git a/docs/content/en/quick-reference/glossary/function.md b/docs/content/en/quick-reference/glossary/function.md new file mode 100644 index 000000000..a7da52cd2 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/function.md @@ -0,0 +1,6 @@ +--- +title: function +reference: /functions +--- + +Used within a [_template action_](g), a _function_ takes one or more [_arguments_](g) and returns a value. Unlike [_methods_](g), functions are not associated with an [_object_](g). diff --git a/docs/content/en/quick-reference/glossary/glob.md b/docs/content/en/quick-reference/glossary/glob.md new file mode 100644 index 000000000..bb9c5a4d8 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/glob.md @@ -0,0 +1,6 @@ +--- +title: glob +reference: https://github.com/gobwas/glob?tab=readme-ov-file#example +--- + +A _glob_ is a pattern used to match file names and paths. It's a shorthand for specifying a set of files, making it easier to work with multiple files at once. diff --git a/docs/content/en/quick-reference/glossary/global-resource.md b/docs/content/en/quick-reference/glossary/global-resource.md new file mode 100644 index 000000000..a4df65f67 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/global-resource.md @@ -0,0 +1,5 @@ +--- +title: global resource +--- + +A _global resource_ is file within the `assets` directory, or within any directory mounted to the `assets` directory. diff --git a/docs/content/en/quick-reference/glossary/headless-bundle.md b/docs/content/en/quick-reference/glossary/headless-bundle.md new file mode 100644 index 000000000..ac7bf79c8 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/headless-bundle.md @@ -0,0 +1,6 @@ +--- +title: headless bundle +reference: /content-management/build-options/ +--- + +A _headless bundle_ is an unpublished [_leaf bundle_](g) or an unpublished [_branch bundle_](g) whose content and resources you can include in other pages. diff --git a/docs/content/en/quick-reference/glossary/i18n.md b/docs/content/en/quick-reference/glossary/i18n.md new file mode 100644 index 000000000..168828aa8 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/i18n.md @@ -0,0 +1,5 @@ +--- +title: i18n +--- + +See [_internationalization_](g). diff --git a/docs/content/en/quick-reference/glossary/identifier.md b/docs/content/en/quick-reference/glossary/identifier.md new file mode 100644 index 000000000..f53472fa7 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/identifier.md @@ -0,0 +1,5 @@ +--- +title: identifier +--- + +An _identifier_ is a string that represents a variable, method, object, or field. It must conform to Go's [language specification](https://go.dev/ref/spec#Identifiers), beginning with a letter or underscore, followed by zero or more letters, digits, or underscores. diff --git a/docs/content/en/quick-reference/glossary/int.md b/docs/content/en/quick-reference/glossary/int.md new file mode 100644 index 000000000..0896f1ce7 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/int.md @@ -0,0 +1,5 @@ +--- +title: int +--- + +See [_integer_](g). diff --git a/docs/content/en/quick-reference/glossary/integer.md b/docs/content/en/quick-reference/glossary/integer.md new file mode 100644 index 000000000..0af821300 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/integer.md @@ -0,0 +1,5 @@ +--- +title: integer +--- + +An _integer_ is a numeric data type without a fractional component. For example, `42`. diff --git a/docs/content/en/quick-reference/glossary/internationalization.md b/docs/content/en/quick-reference/glossary/internationalization.md new file mode 100644 index 000000000..4e8b0199c --- /dev/null +++ b/docs/content/en/quick-reference/glossary/internationalization.md @@ -0,0 +1,5 @@ +--- +title: internationalization +--- + +The term _internationalization_ refers to software design and development efforts that enable [_localization_](g). diff --git a/docs/content/en/quick-reference/glossary/interpreted-string-literal.md b/docs/content/en/quick-reference/glossary/interpreted-string-literal.md new file mode 100644 index 000000000..a5d2cd326 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/interpreted-string-literal.md @@ -0,0 +1,6 @@ +--- +title: interpreted string literal +reference: https://go.dev/ref/spec#String_literals +--- + +An _interpreted string literal_ is a character sequences between double quotes, as in "foo". Within the quotes, any character may appear except a newline and an unescaped double quote. The text between the quotes forms the value of the literal, with backslash escapes interpreted. diff --git a/docs/content/en/quick-reference/glossary/interval.md b/docs/content/en/quick-reference/glossary/interval.md new file mode 100644 index 000000000..a7ed8a6cd --- /dev/null +++ b/docs/content/en/quick-reference/glossary/interval.md @@ -0,0 +1,11 @@ +--- +title: interval +--- + +An [_interval_](https://en.wikipedia.org/wiki/Interval_(mathematics)) is a range of numbers between two endpoints: closed, open, or half-open. + + - A _closed interval_, denoted by brackets, includes its endpoints. For example, [0, 1] is the interval where `0 <= x <= 1`. + + - An _open interval_, denoted by parentheses, excludes its endpoints. For example, (0, 1) is the interval where `0 < x < 1`. + + - A _half-open interval_ includes only one of its endpoints. For example, (0, 1] is the _left-open_ interval where `0 < x <= 1`, while [0, 1) is the _right-open_ interval where `0 <= x < 1`. diff --git a/docs/content/en/quick-reference/glossary/kind.md b/docs/content/en/quick-reference/glossary/kind.md new file mode 100644 index 000000000..a214dfbf1 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/kind.md @@ -0,0 +1,5 @@ +--- +title: kind +--- + +See [_page kind_](g). diff --git a/docs/content/en/quick-reference/glossary/l10n.md b/docs/content/en/quick-reference/glossary/l10n.md new file mode 100644 index 000000000..013d0ab55 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/l10n.md @@ -0,0 +1,5 @@ +--- +title: l10n +--- + +See [_localization_](g). diff --git a/docs/content/en/quick-reference/glossary/layout.md b/docs/content/en/quick-reference/glossary/layout.md new file mode 100644 index 000000000..a4e6b33f1 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/layout.md @@ -0,0 +1,5 @@ +--- +title: layout +--- + +See [_template_](g). diff --git a/docs/content/en/quick-reference/glossary/leaf-bundle.md b/docs/content/en/quick-reference/glossary/leaf-bundle.md new file mode 100644 index 000000000..aa41384ee --- /dev/null +++ b/docs/content/en/quick-reference/glossary/leaf-bundle.md @@ -0,0 +1,6 @@ +--- +title: leaf bundle +reference: /content-management/page-bundles/ +--- + +A _leaf bundle_ is a directory that contains an `index.md` file and zero or more [_resources_](g). Analogous to a physical leaf, a leaf bundle is at the end of a [_branch bundle_](g). It has no descendants. diff --git a/docs/content/en/quick-reference/glossary/lexer.md b/docs/content/en/quick-reference/glossary/lexer.md new file mode 100644 index 000000000..a46223148 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/lexer.md @@ -0,0 +1,5 @@ +--- +title: lexer +--- + +A _lexer_ is a software component that identifies keywords, identifiers, operators, numbers, and other basic building blocks of a programming language within the input text. diff --git a/docs/content/en/quick-reference/glossary/list-page.md b/docs/content/en/quick-reference/glossary/list-page.md new file mode 100644 index 000000000..b58ee4a35 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/list-page.md @@ -0,0 +1,5 @@ +--- +title: list page +--- + +A list page is any [_page kind_](g) that receives a page [_collection_](g) in [_context_](g). This includes the home page, [section pages](g), [taxonomy pages](g), and [term pages](g). diff --git a/docs/content/en/quick-reference/glossary/list-template.md b/docs/content/en/quick-reference/glossary/list-template.md new file mode 100644 index 000000000..9a12a275f --- /dev/null +++ b/docs/content/en/quick-reference/glossary/list-template.md @@ -0,0 +1,5 @@ +--- +title: list template +--- + +A _list template_ is any [_template_](g) that renders a [_list page_](g). This includes home, [_section_](g), [_taxonomy_](g), and [_term_](g) templates. diff --git a/docs/content/en/quick-reference/glossary/localization.md b/docs/content/en/quick-reference/glossary/localization.md new file mode 100644 index 000000000..01f450635 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/localization.md @@ -0,0 +1,6 @@ +--- +title: localization +reference: /content-management/multilingual/ +--- + +The term _localization_ refers to the process of adapting a site to meet language and regional requirements. This includes translations, date formats, number formats, currency formats, and collation order. diff --git a/docs/content/en/quick-reference/glossary/logical-path.md b/docs/content/en/quick-reference/glossary/logical-path.md new file mode 100644 index 000000000..2eeee751f --- /dev/null +++ b/docs/content/en/quick-reference/glossary/logical-path.md @@ -0,0 +1,6 @@ +--- +title: logical path +reference: /methods/page/path/#examples +--- + +A _logical path_ is a page or page resource identifier derived from the file path, excluding its extension and language identifier. This value is neither a file path nor a URL. Starting with a file path relative to the `content` directory, Hugo determines the logical path by stripping the file extension and language identifier, converting to lower case, then replacing spaces with hyphens. Path segments are separated with a slash (`/`). diff --git a/docs/content/en/quick-reference/glossary/map.md b/docs/content/en/quick-reference/glossary/map.md new file mode 100644 index 000000000..b4605d20b --- /dev/null +++ b/docs/content/en/quick-reference/glossary/map.md @@ -0,0 +1,6 @@ +--- +title: map +reference: https://go.dev/ref/spec#Map_types +--- + +A _map_ is an unordered group of elements, each indexed by a unique key. diff --git a/docs/content/en/quick-reference/glossary/markdown-attribute.md b/docs/content/en/quick-reference/glossary/markdown-attribute.md new file mode 100644 index 000000000..f5c57c728 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/markdown-attribute.md @@ -0,0 +1,6 @@ +--- +title: Markdown attribute +reference: /content-management/markdown-attributes/ +--- + +A _Markdown attribute_ is a key-value pair attached to a Markdown element. These attributes are commonly used to add HTML attributes, like `class` and `id`, to the element when it's rendered into HTML. They provide a way to extend the basic Markdown syntax and add more semantic meaning or styling hooks to your content. diff --git a/docs/content/en/quick-reference/glossary/marshal.md b/docs/content/en/quick-reference/glossary/marshal.md new file mode 100644 index 000000000..3bb1623f5 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/marshal.md @@ -0,0 +1,6 @@ +--- +title: marshal +reference: /functions/transform/remarshal/ +--- + +To _marshal_ is to transform a data structure into a serialized object. For example, transforming a [_map_](g) into a JSON string. diff --git a/docs/content/en/quick-reference/glossary/media-type.md b/docs/content/en/quick-reference/glossary/media-type.md new file mode 100644 index 000000000..2994360ef --- /dev/null +++ b/docs/content/en/quick-reference/glossary/media-type.md @@ -0,0 +1,6 @@ +--- +title: media type +reference: /configuration/media-types/ +--- + +A _media type_ (formerly known as a MIME type) is a two-part identifier for file formats and transmitted content. For example, the media type for JSON data is `application/json`. diff --git a/docs/content/en/quick-reference/glossary/method.md b/docs/content/en/quick-reference/glossary/method.md new file mode 100644 index 000000000..634cd4b97 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/method.md @@ -0,0 +1,5 @@ +--- +title: method +--- + +Used within a [_template action_](g) and associated with an [_object_](g), a _method_ takes zero or more [_arguments_](g) and either returns a value or performs an action. For example, `IsHome` is a method on a `Page` object which returns `true` if the current page is the home page. See also [_function_](g). diff --git a/docs/content/en/quick-reference/glossary/module.md b/docs/content/en/quick-reference/glossary/module.md new file mode 100644 index 000000000..90c8ff80b --- /dev/null +++ b/docs/content/en/quick-reference/glossary/module.md @@ -0,0 +1,6 @@ +--- +title: module +reference: /hugo-modules/ +--- + +A _module_ is a packaged combination of [_archetypes_](g), assets, content, data, [_templates_](g), translation tables, static files, or configuration settings. A module may serve as the basis for a new site, or to augment an existing site. diff --git a/docs/content/en/quick-reference/glossary/node.md b/docs/content/en/quick-reference/glossary/node.md new file mode 100644 index 000000000..b722e07c8 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/node.md @@ -0,0 +1,5 @@ +--- +title: node +--- + +A _node_ is a class of [_page kinds_](g) including `home`, `section`, `taxonomy`, and `term`. diff --git a/docs/content/en/quick-reference/glossary/noop.md b/docs/content/en/quick-reference/glossary/noop.md new file mode 100644 index 000000000..bd159bb26 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/noop.md @@ -0,0 +1,5 @@ +--- +title: noop +--- + +An abbreviated form of "no operation", a _noop_ is a statement that does nothing. diff --git a/docs/content/en/quick-reference/glossary/object.md b/docs/content/en/quick-reference/glossary/object.md new file mode 100644 index 000000000..216609d0d --- /dev/null +++ b/docs/content/en/quick-reference/glossary/object.md @@ -0,0 +1,5 @@ +--- +title: object +--- + +An _object_ is a data structure with or without associated [_methods_](g). diff --git a/docs/content/en/quick-reference/glossary/ordered-taxonomy.md b/docs/content/en/quick-reference/glossary/ordered-taxonomy.md new file mode 100644 index 000000000..9b6c1d92c --- /dev/null +++ b/docs/content/en/quick-reference/glossary/ordered-taxonomy.md @@ -0,0 +1,5 @@ +--- +title: ordered taxonomy +--- + +Created by invoking the [`Alphabetical`](/methods/taxonomy/alphabetical/) or [`ByCount`](/methods/taxonomy/bycount/) method on a [`Taxonomy`](g) object, which is a [_map_](g), an _ordered taxonomy_ is a [_slice_](g), where each element is an object that contains the [_term_](g) and a slice of its [_weighted pages_](g). diff --git a/docs/content/en/quick-reference/glossary/output-format.md b/docs/content/en/quick-reference/glossary/output-format.md new file mode 100644 index 000000000..df042d06b --- /dev/null +++ b/docs/content/en/quick-reference/glossary/output-format.md @@ -0,0 +1,6 @@ +--- +title: output format +reference: /configuration/output-formats/ +--- + +An _output format_ is a collection of settings that defines how Hugo renders a file when building a site. For example, `html`, `json`, and `rss` are built-in output formats. You can create multiple output formats and control their generation based on [page kind](g), or by enabling one or more output formats for specific pages. diff --git a/docs/content/en/quick-reference/glossary/page-bundle.md b/docs/content/en/quick-reference/glossary/page-bundle.md new file mode 100644 index 000000000..af76da2aa --- /dev/null +++ b/docs/content/en/quick-reference/glossary/page-bundle.md @@ -0,0 +1,6 @@ +--- +title: page bundle +reference: /content-management/page-bundles/ +--- + +A _page bundle_ is a directory that encapsulates both content and associated [_resources_](g). There are two types of page bundles: [_leaf bundles_](g) and [_branch bundles_](g). diff --git a/docs/content/en/quick-reference/glossary/page-collection.md b/docs/content/en/quick-reference/glossary/page-collection.md new file mode 100644 index 000000000..f078ecf27 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/page-collection.md @@ -0,0 +1,5 @@ +--- +title: page collection +--- + +A _page collection_ is a slice of `Page` objects. diff --git a/docs/content/en/quick-reference/glossary/page-kind.md b/docs/content/en/quick-reference/glossary/page-kind.md new file mode 100644 index 000000000..ee47fe010 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/page-kind.md @@ -0,0 +1,6 @@ +--- +title: page kind +reference: /methods/page/kind/ +--- + +A _page kind_ is a classification of pages, one of `home`, `page`, `section`, `taxonomy`, or `term`. diff --git a/docs/content/en/quick-reference/glossary/page-resource.md b/docs/content/en/quick-reference/glossary/page-resource.md new file mode 100644 index 000000000..dab119eb4 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/page-resource.md @@ -0,0 +1,5 @@ +--- +title: page resource +--- + +A _page resource_ is a file within a [_page bundle_](g). diff --git a/docs/content/en/quick-reference/glossary/pager.md b/docs/content/en/quick-reference/glossary/pager.md new file mode 100644 index 000000000..f58874e4a --- /dev/null +++ b/docs/content/en/quick-reference/glossary/pager.md @@ -0,0 +1,5 @@ +--- +title: pager +--- + +Created during [_pagination_](g), a _pager_ contains a subset of a list page and navigation links to other pagers. diff --git a/docs/content/en/quick-reference/glossary/paginate.md b/docs/content/en/quick-reference/glossary/paginate.md new file mode 100644 index 000000000..d2467e098 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/paginate.md @@ -0,0 +1,5 @@ +--- +title: paginate +--- + +To _paginate_ is to split a list page into two or more subsets. diff --git a/docs/content/en/quick-reference/glossary/pagination.md b/docs/content/en/quick-reference/glossary/pagination.md new file mode 100644 index 000000000..136341dbf --- /dev/null +++ b/docs/content/en/quick-reference/glossary/pagination.md @@ -0,0 +1,6 @@ +--- +title: pagination +reference: /templates/pagination +--- + +The term _pagination_ refers to the process of [_paginating_](g) a list page. diff --git a/docs/content/en/quick-reference/glossary/paginator.md b/docs/content/en/quick-reference/glossary/paginator.md new file mode 100644 index 000000000..4d197348d --- /dev/null +++ b/docs/content/en/quick-reference/glossary/paginator.md @@ -0,0 +1,5 @@ +--- +title: paginator +--- + +A _paginator_ is a collection of [_pagers_](g). diff --git a/docs/content/en/quick-reference/glossary/parameter.md b/docs/content/en/quick-reference/glossary/parameter.md new file mode 100644 index 000000000..f1a45ea34 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/parameter.md @@ -0,0 +1,5 @@ +--- +title: parameter +--- + +A _parameter_ is typically a user-defined key-value pair at the site or page level, but may also refer to a configuration setting or an [_argument_](g). diff --git a/docs/content/en/quick-reference/glossary/partial.md b/docs/content/en/quick-reference/glossary/partial.md new file mode 100644 index 000000000..a5dd5e51a --- /dev/null +++ b/docs/content/en/quick-reference/glossary/partial.md @@ -0,0 +1,5 @@ +--- +title: partial +--- + +A _partial_ is a [_template_](g) called from any other template including [_shortcodes_](g), [render hooks](g), and other partials. A partial either renders something or returns something. A partial can also call itself, for example, to [_walk_](g) a data structure. diff --git a/docs/content/en/quick-reference/glossary/permalink.md b/docs/content/en/quick-reference/glossary/permalink.md new file mode 100644 index 000000000..45651de83 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/permalink.md @@ -0,0 +1,5 @@ +--- +title: permalink +--- + +A _permalink_ is the absolute URL of a published resource or a rendered page, including scheme and host. diff --git a/docs/content/en/quick-reference/glossary/pipe.md b/docs/content/en/quick-reference/glossary/pipe.md new file mode 100644 index 000000000..f587eeccf --- /dev/null +++ b/docs/content/en/quick-reference/glossary/pipe.md @@ -0,0 +1,5 @@ +--- +title: pipe +--- + +See [_pipeline_](g). diff --git a/docs/content/en/quick-reference/glossary/pipeline.md b/docs/content/en/quick-reference/glossary/pipeline.md new file mode 100644 index 000000000..6dab52578 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/pipeline.md @@ -0,0 +1,7 @@ +--- +title: pipeline +--- + +Within a [_template action_](g), a _pipeline_ is a possibly chained sequence of values, [_function_](g) calls, or [_method_](g) calls. Functions and methods in the pipeline may take multiple [_arguments_](g). + + A pipeline may be chained by separating a sequence of commands with pipeline characters (`|`). In a chained pipeline, the result of each command is passed as the last argument to the following command. The output of the final command in the pipeline is the value of the pipeline. diff --git a/docs/content/en/quick-reference/glossary/pretty-url.md b/docs/content/en/quick-reference/glossary/pretty-url.md new file mode 100644 index 000000000..b15ef9f0f --- /dev/null +++ b/docs/content/en/quick-reference/glossary/pretty-url.md @@ -0,0 +1,5 @@ +--- +title: pretty URL +--- + +A _pretty URL_ is a URL that does not include a file extension. diff --git a/docs/content/en/quick-reference/glossary/primary-output-format.md b/docs/content/en/quick-reference/glossary/primary-output-format.md new file mode 100644 index 000000000..c40c0176c --- /dev/null +++ b/docs/content/en/quick-reference/glossary/primary-output-format.md @@ -0,0 +1,10 @@ +--- +title: primary output format +details: /configuration/outputs/ +--- + +A _primary output format_ defines the default URL returned by the [`Permalink`] and [`RelPermalink`] methods for a given [page kind](g). It is specified as the first entry within the [outputs configuration] for that page kind. + +[`Permalink`]: /methods/page/permalink/ +[`RelPermalink`]: /methods/page/relpermalink/ +[outputs configuration]: /configuration/outputs/ diff --git a/docs/content/en/quick-reference/glossary/publish.md b/docs/content/en/quick-reference/glossary/publish.md new file mode 100644 index 000000000..743e87a3e --- /dev/null +++ b/docs/content/en/quick-reference/glossary/publish.md @@ -0,0 +1,5 @@ +--- +title: publish +--- + +See [_build_](g). diff --git a/docs/content/en/quick-reference/glossary/raw-string-literal.md b/docs/content/en/quick-reference/glossary/raw-string-literal.md new file mode 100644 index 000000000..7465c6837 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/raw-string-literal.md @@ -0,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. diff --git a/docs/content/en/quick-reference/glossary/regular-expression.md b/docs/content/en/quick-reference/glossary/regular-expression.md new file mode 100644 index 000000000..222f289d9 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/regular-expression.md @@ -0,0 +1,8 @@ +--- +title: regular expression +reference: +--- + +A _regular expression_, also known as a _regex_, is a sequence of characters that defines a search pattern. Use the [RE2 syntax] when defining regular expressions in your templates or site configuration. + + [RE2 syntax]: https://github.com/google/re2/wiki/syntax diff --git a/docs/content/en/quick-reference/glossary/regular-page.md b/docs/content/en/quick-reference/glossary/regular-page.md new file mode 100644 index 000000000..084408e57 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/regular-page.md @@ -0,0 +1,5 @@ +--- +title: regular page +--- + +A _regular page_ is a page with the "page" [_page kind_](g). See also [_section page_](g). diff --git a/docs/content/en/quick-reference/glossary/relative-permalink.md b/docs/content/en/quick-reference/glossary/relative-permalink.md new file mode 100644 index 000000000..a272133a3 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/relative-permalink.md @@ -0,0 +1,5 @@ +--- +title: relative permalink +--- + +A _relative permalink_ is the host-relative URL of a published resource or a rendered page. diff --git a/docs/content/en/quick-reference/glossary/remote-resource.md b/docs/content/en/quick-reference/glossary/remote-resource.md new file mode 100644 index 000000000..163749763 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/remote-resource.md @@ -0,0 +1,5 @@ +--- +title: remote resource +--- + +A _remote resource_ is a file on a remote server, accessible via HTTP or HTTPS. diff --git a/docs/content/en/quick-reference/glossary/render-hook.md b/docs/content/en/quick-reference/glossary/render-hook.md new file mode 100644 index 000000000..2cdb98e05 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/render-hook.md @@ -0,0 +1,6 @@ +--- +title: render hook +reference: /render-hooks +--- + +A _render hook_ is a [_template_](g) that overrides standard Markdown rendering. diff --git a/docs/content/en/quick-reference/glossary/resource-type.md b/docs/content/en/quick-reference/glossary/resource-type.md new file mode 100644 index 000000000..9a2412fb9 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/resource-type.md @@ -0,0 +1,5 @@ +--- +title: resource type +--- + +A _resource type_ is the main type of a resource's [media type](/methods/resource/mediatype/). Content files such as Markdown, HTML, AsciiDoc, Pandoc, reStructuredText, and Emacs Org Mode have resource type `page`. Other resource types include `image`, `text`, `video`, and others. Retrieve the resource type using the [`ResourceType`](/methods/resource/resourcetype/) method on a `Resource` object. diff --git a/docs/content/en/quick-reference/glossary/resource.md b/docs/content/en/quick-reference/glossary/resource.md new file mode 100644 index 000000000..0864bc43d --- /dev/null +++ b/docs/content/en/quick-reference/glossary/resource.md @@ -0,0 +1,7 @@ +--- +title: resource +--- + +A _resource_ is any file consumed by the build process to augment or generate content, structure, behavior, or presentation. For example: images, videos, content snippets, CSS, Sass, JavaScript, and data. + + Hugo supports three types of resources: [_global resources_](g), [_page resources_](g), and [_remote resources_](g). diff --git a/docs/content/en/quick-reference/glossary/scalar.md b/docs/content/en/quick-reference/glossary/scalar.md new file mode 100644 index 000000000..63ae27d3f --- /dev/null +++ b/docs/content/en/quick-reference/glossary/scalar.md @@ -0,0 +1,5 @@ +--- +title: scalar +--- + +A _scalar_ is a single value, one of [_string_](g), [_integer_](g), [floating point](g), or [_boolean_](g). diff --git a/docs/content/en/quick-reference/glossary/scope.md b/docs/content/en/quick-reference/glossary/scope.md new file mode 100644 index 000000000..5a13312a6 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/scope.md @@ -0,0 +1,5 @@ +--- +title: scope +--- + +The term _scope_ refers to the specific region of code where a [_variable_](g) or [_object_](g) is accessible. For example, a variable initialized in one [template](g) is not available within another. diff --git a/docs/content/en/quick-reference/glossary/scratch-pad.md b/docs/content/en/quick-reference/glossary/scratch-pad.md new file mode 100644 index 000000000..4792ce12e --- /dev/null +++ b/docs/content/en/quick-reference/glossary/scratch-pad.md @@ -0,0 +1,5 @@ +--- +title: scratch pad +--- + +Conceptually, a _scratch pad_ is a [_map_](g) with [_methods_](g) to set, get, update, and delete values. Attach the data structure to a `Page` or `Site` object using the [`Store`](/methods/page/store/) method, or create a locally scoped scratch pad using the [`newScratch`](/functions/collections/newscratch/) function. diff --git a/docs/content/en/quick-reference/glossary/section-page.md b/docs/content/en/quick-reference/glossary/section-page.md new file mode 100644 index 000000000..fd84ed5f2 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/section-page.md @@ -0,0 +1,5 @@ +--- +title: section page +--- + +A _section page_ is a page with the "section" [_page kind_](g). Typically a listing of [_regular pages_](g) and/or other section pages within the current [_section_](g). diff --git a/docs/content/en/quick-reference/glossary/section.md b/docs/content/en/quick-reference/glossary/section.md new file mode 100644 index 000000000..45d1203e0 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/section.md @@ -0,0 +1,5 @@ +--- +title: section +--- + +A _section_ is a top-level content directory or any content directory containing an `_index.md` file. diff --git a/docs/content/en/quick-reference/glossary/segment.md b/docs/content/en/quick-reference/glossary/segment.md new file mode 100644 index 000000000..5851a8825 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/segment.md @@ -0,0 +1,5 @@ +--- +title: segment +--- + +A _segment_ is a subset of a site, filtered by [_logical path_](g), language, [_page kind_](g), or [_output format_](g). diff --git a/docs/content/en/quick-reference/glossary/shortcode.md b/docs/content/en/quick-reference/glossary/shortcode.md new file mode 100644 index 000000000..a6503ea63 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/shortcode.md @@ -0,0 +1,6 @@ +--- +title: shortcode +reference: /content-management/shortcodes +--- + +A _shortcode_ is a [_template_](g) invoked within markup, accepting any number of [_arguments_](g). They can be used with any [_content format_](g) to insert elements such as videos, images, and social media embeds into your content. diff --git a/docs/content/en/quick-reference/glossary/slice.md b/docs/content/en/quick-reference/glossary/slice.md new file mode 100644 index 000000000..5d83bed6b --- /dev/null +++ b/docs/content/en/quick-reference/glossary/slice.md @@ -0,0 +1,6 @@ +--- +title: slice +reference: https://go.dev/ref/spec#Slice_types +--- + +A _slice_ is a numbered sequence of elements. Unlike Go's [_array_](g) data type, slices are dynamically sized. [_Elements_](g) within a slice can be [_scalars_](g), [_arrays_](g), [_maps_](g), pages, or other slices. diff --git a/docs/content/en/quick-reference/glossary/string.md b/docs/content/en/quick-reference/glossary/string.md new file mode 100644 index 000000000..54ed4c1d1 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/string.md @@ -0,0 +1,5 @@ +--- +title: string +--- + +A _string_ is a sequence of bytes. For example, `"What is 6 times 7?"`. diff --git a/docs/content/en/quick-reference/glossary/taxonomic-weight.md b/docs/content/en/quick-reference/glossary/taxonomic-weight.md new file mode 100644 index 000000000..682bc056c --- /dev/null +++ b/docs/content/en/quick-reference/glossary/taxonomic-weight.md @@ -0,0 +1,6 @@ +--- +title: taxonomic weight +reference: content-management/taxonomies/#order-taxonomies +--- + +Defined in front matter and unique to each taxonomy, a _taxonomic weight_ is a [_weight_](g) that determines the sort order of page collections contained within a [`Taxonomy`](g) object. diff --git a/docs/content/en/quick-reference/glossary/taxonomy-object.md b/docs/content/en/quick-reference/glossary/taxonomy-object.md new file mode 100644 index 000000000..590490377 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/taxonomy-object.md @@ -0,0 +1,5 @@ +--- +title: taxonomy object +--- + +A _taxonomy object_ is a [_map_](g) of [_terms_](g) and the [weighted pages](g) associated with each term. diff --git a/docs/content/en/quick-reference/glossary/taxonomy-page.md b/docs/content/en/quick-reference/glossary/taxonomy-page.md new file mode 100644 index 000000000..6b62f0912 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/taxonomy-page.md @@ -0,0 +1,5 @@ +--- +title: taxonomy page +--- + +A _taxonomy page_ is a page with the "taxonomy" [_page kind_](g). Typically a listing of [_terms_](g) within a given [_taxonomy_](g). diff --git a/docs/content/en/quick-reference/glossary/taxonomy.md b/docs/content/en/quick-reference/glossary/taxonomy.md new file mode 100644 index 000000000..ce35a634c --- /dev/null +++ b/docs/content/en/quick-reference/glossary/taxonomy.md @@ -0,0 +1,5 @@ +--- +title: taxonomy +reference: /content-management/taxonomies +--- +A _taxonomy_ is a group of related [_terms_](g) used to classify content. For example, a "colors" taxonomy might include the terms "red", "green", and "blue". diff --git a/docs/content/en/quick-reference/glossary/template-action.md b/docs/content/en/quick-reference/glossary/template-action.md new file mode 100644 index 000000000..e40c228fe --- /dev/null +++ b/docs/content/en/quick-reference/glossary/template-action.md @@ -0,0 +1,6 @@ +--- +title: template action +reference: https://pkg.go.dev/text/template#hdr-Actions +--- + +A data evaluation or control structure within a [_template_](g), delimited by `{{` and `}}`. diff --git a/docs/content/en/quick-reference/glossary/template.md b/docs/content/en/quick-reference/glossary/template.md new file mode 100644 index 000000000..d442c0a22 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/template.md @@ -0,0 +1,6 @@ +--- +title: template +reference: /templates +--- + +A _template_ is a file with [_template actions_](g), located within the `layouts` directory of a project, theme, or module. diff --git a/docs/content/en/quick-reference/glossary/term-page.md b/docs/content/en/quick-reference/glossary/term-page.md new file mode 100644 index 000000000..78eabc11f --- /dev/null +++ b/docs/content/en/quick-reference/glossary/term-page.md @@ -0,0 +1,5 @@ +--- +title: term page +--- + +A _term page_ is a page with the "term" [_page kind_](g). Typically a listing of [_regular pages_](g) and [_section pages_](g) with a given [_term_](g). diff --git a/docs/content/en/quick-reference/glossary/term.md b/docs/content/en/quick-reference/glossary/term.md new file mode 100644 index 000000000..cafd92585 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/term.md @@ -0,0 +1,6 @@ +--- +title: term +reference: /content-management/taxonomies +--- + +A _term_ is a member of a [_taxonomy_](g), used to classify content. diff --git a/docs/content/en/quick-reference/glossary/theme.md b/docs/content/en/quick-reference/glossary/theme.md new file mode 100644 index 000000000..84b9c684a --- /dev/null +++ b/docs/content/en/quick-reference/glossary/theme.md @@ -0,0 +1,5 @@ +--- +title: theme +--- + +A _theme_ is a packaged combination of [_archetypes_](g), assets, content, data, [_templates_](g), translation tables, static files, or configuration settings. A theme may serve as the basis for a new site, or to augment an existing site. diff --git a/docs/content/en/quick-reference/glossary/token.md b/docs/content/en/quick-reference/glossary/token.md new file mode 100644 index 000000000..f8c12d570 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/token.md @@ -0,0 +1,5 @@ +--- +title: token +--- + +A _token_ is an identifier within a format string, beginning with a colon and replaced with a value when rendered. For example, use tokens in format strings for both [permalinks](/content-management/urls/#permalinks) and [dates](/functions/time/format/#localization). diff --git a/docs/content/en/quick-reference/glossary/type.md b/docs/content/en/quick-reference/glossary/type.md new file mode 100644 index 000000000..dbc692e5a --- /dev/null +++ b/docs/content/en/quick-reference/glossary/type.md @@ -0,0 +1,5 @@ +--- +title: type +--- + +See [content type](g). diff --git a/docs/content/en/quick-reference/glossary/ugly-url.md b/docs/content/en/quick-reference/glossary/ugly-url.md new file mode 100644 index 000000000..4083f9378 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/ugly-url.md @@ -0,0 +1,5 @@ +--- +title: ugly URL +--- + +An _ugly URL_ is a URL that includes a file extension. diff --git a/docs/content/en/quick-reference/glossary/unmarshal.md b/docs/content/en/quick-reference/glossary/unmarshal.md new file mode 100644 index 000000000..0ed548a21 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/unmarshal.md @@ -0,0 +1,6 @@ +--- +title: unmarshal +reference: /functions/transform/unmarshal/ +--- + +To _unmarshal_ is to transform a serialized object into a data structure. For example, transforming a JSON file into a [_map_](g) that you can access within a template. diff --git a/docs/content/en/quick-reference/glossary/variable.md b/docs/content/en/quick-reference/glossary/variable.md new file mode 100644 index 000000000..f8139a41f --- /dev/null +++ b/docs/content/en/quick-reference/glossary/variable.md @@ -0,0 +1,5 @@ +--- +title: variable +--- + +A _variable_ is a user-defined [_identifier_](g) prepended with a `$` symbol, representing a value of any data type, initialized or assigned within a [_template action_](g). For example, `$foo` and `$bar` are variables. diff --git a/docs/content/en/quick-reference/glossary/walk.md b/docs/content/en/quick-reference/glossary/walk.md new file mode 100644 index 000000000..09f9ecb20 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/walk.md @@ -0,0 +1,5 @@ +--- +title: walk +--- + +To _walk_ is to recursively traverse a nested data structure. For example, rendering a multilevel menu. diff --git a/docs/content/en/quick-reference/glossary/weight.md b/docs/content/en/quick-reference/glossary/weight.md new file mode 100644 index 000000000..deb9e6dc0 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/weight.md @@ -0,0 +1,5 @@ +--- +title: weight +--- + +A _weight_ is a numeric value used to position an element within a sorted [collection](g). Assign weights using non-zero integers. Lighter items float to the top, while heavier items sink to the bottom. Unweighted or zero-weighted elements are placed at the end of the collection. Weights are typically assigned to pages, menu entries, languages, and output formats. diff --git a/docs/content/en/quick-reference/glossary/weighted-page.md b/docs/content/en/quick-reference/glossary/weighted-page.md new file mode 100644 index 000000000..e6cf8d6db --- /dev/null +++ b/docs/content/en/quick-reference/glossary/weighted-page.md @@ -0,0 +1,5 @@ +--- +title: weighted page +--- + +Contained within a [_taxonomy object_](g), a _weighted page_ is a [_map_](g) with two [_elements_](g): a `Page` object, and its [_taxonomic weight_](g) as defined in front matter. Access the elements using the `Page` and `Weight` keys. diff --git a/docs/content/en/quick-reference/glossary/zero-time.md b/docs/content/en/quick-reference/glossary/zero-time.md new file mode 100644 index 000000000..9701f3912 --- /dev/null +++ b/docs/content/en/quick-reference/glossary/zero-time.md @@ -0,0 +1,5 @@ +--- +title: zero time +--- + +The _zero time_ is January 1, 0001, 00:00:00 UTC. Formatted per [RFC3339](https://www.rfc-editor.org/rfc/rfc3339) the _zero time_ is 0001-01-01T00:00:00-00:00. diff --git a/docs/content/en/quick-reference/methods.md b/docs/content/en/quick-reference/methods.md new file mode 100644 index 000000000..524713c1f --- /dev/null +++ b/docs/content/en/quick-reference/methods.md @@ -0,0 +1,8 @@ +--- +title: Methods +description: A quick reference guide to Hugo's methods, grouped by object. +categories: [] +keywords: [] +--- + +{{% quick-reference section="methods" %}} diff --git a/docs/content/en/quick-reference/page-collections.md b/docs/content/en/quick-reference/page-collections.md new file mode 100644 index 000000000..4c2387bbe --- /dev/null +++ b/docs/content/en/quick-reference/page-collections.md @@ -0,0 +1,38 @@ +--- +title: Page collections +description: A quick reference guide to Hugo's page collections. +categories: [] +keywords: [] +--- + +## Page + +Use these `Page` methods when rendering lists on [section pages](g), [taxonomy pages](g), [term pages](g), and the home page. + +{{% list-pages-in-section path=/methods/page filter=methods_page_page_collections filterType=include titlePrefix=PAGE. %}} + +## Site + +Use these `Site` methods when rendering lists on any page. + +{{% list-pages-in-section path=/methods/site filter=methods_site_page_collections filterType=include titlePrefix=SITE. %}} + +## Filter + +Use the [`where`] function to filter page collections. + +## Sort + +{{% glossary-term "default sort order" %}} + +Use these methods to sort page collections by different criteria. + +{{% list-pages-in-section path=/methods/pages filter=methods_pages_sort filterType=include titlePrefix=. titlePrefix=PAGES. %}} + +## Group + +Use these methods to group page collections. + +{{% list-pages-in-section path=/methods/pages filter=methods_pages_group filterType=include titlePrefix=. titlePrefix=PAGES. %}} + +[`where`]: /functions/collections/where/ diff --git a/docs/content/en/quick-reference/syntax-highlighting-styles.md b/docs/content/en/quick-reference/syntax-highlighting-styles.md new file mode 100644 index 000000000..14b313cbc --- /dev/null +++ b/docs/content/en/quick-reference/syntax-highlighting-styles.md @@ -0,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 + +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 --git a/docs/content/en/render-hooks/_index.md b/docs/content/en/render-hooks/_index.md new file mode 100644 index 000000000..a5e6203ff --- /dev/null +++ b/docs/content/en/render-hooks/_index.md @@ -0,0 +1,8 @@ +--- +title: Render hooks +description: Create render hooks to override the rendering of Markdown to HTML. +categories: [] +keywords: [] +weight: 10 +aliases: [/templates/render-hooks/] +--- diff --git a/docs/content/en/render-hooks/blockquotes.md b/docs/content/en/render-hooks/blockquotes.md new file mode 100755 index 000000000..7ba282a0a --- /dev/null +++ b/docs/content/en/render-hooks/blockquotes.md @@ -0,0 +1,184 @@ +--- +title: Blockquote render hooks +linkTitle: Blockquotes +description: Create a blockquote render hook 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): + +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/_default/_markup/render-blockquote.html" copy=true} +<blockquote> + {{ .Text }} +</blockquote> +``` + +To render a blockquote as an HTML `figure` element with an optional citation and caption: + +```go-html-template {file="layouts/_default/_markup/render-blockquote.html" copy=true} +<figure> + <blockquote {{ with .Attributes.cite }}cite="{{ . }}"{{ end }}> + {{ .Text }} + </blockquote> + {{ with .Attributes.caption }} + <figcaption class="blockquote-caption"> + {{ . | safeHTML }} + </figcaption> + {{ end }} +</figure> +``` + +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/_default/_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" }} + <blockquote class="alert alert-{{ .AlertType }}"> + <p class="alert-heading"> + {{ transform.Emojify (index $emojis .AlertType) }} + {{ with .AlertTitle }} + {{ . }} + {{ else }} + {{ or (i18n .AlertType) (title .AlertType) }} + {{ end }} + </p> + {{ .Text }} + </blockquote> +{{ else }} + <blockquote> + {{ .Text }} + </blockquote> +{{ 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/ +└── _default/ + └── _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 --git a/docs/content/en/render-hooks/code-blocks.md b/docs/content/en/render-hooks/code-blocks.md new file mode 100755 index 000000000..d1a01e9b0 --- /dev/null +++ b/docs/content/en/render-hooks/code-blocks.md @@ -0,0 +1,127 @@ +--- +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. +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): + +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. + +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/_default/_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/ +└── _default/ + └── _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/_default/_markup/render-codeblock-mermaid.html" copy=true} +<pre class="mermaid"> + {{ .Inner | htmlEscape | safeHTML }} +</pre> +{{ .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/_default/baseof.html" copy=true} +{{ if .Store.Get "hasMermaid" }} + <script type="module"> + import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs'; + mermaid.initialize({ startOnLoad: true }); + </script> +{{ 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/0.31.2/#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/0.31.2/#info-string +[Mermaid]: https://mermaid.js.org/ diff --git a/docs/content/en/render-hooks/headings.md b/docs/content/en/render-hooks/headings.md new file mode 100755 index 000000000..89868d478 --- /dev/null +++ b/docs/content/en/render-hooks/headings.md @@ -0,0 +1,64 @@ +--- +title: Heading render hooks +linkTitle: Headings +description: Create a heading render hook to override the rendering of Markdown headings to HTML. +categories: [] +keywords: [] +--- + +## Context + +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/_default/_markup/render-heading.html" copy=true} +<h{{ .Level }} id="{{ .Anchor }}" {{- with .Attributes.class }} class="{{ . }}" {{- end }}> + {{- .Text -}} +</h{{ .Level }}> +``` + +To add an anchor link to the right of each heading: + +```go-html-template {file="layouts/_default/_markup/render-heading.html" copy=true} +<h{{ .Level }} id="{{ .Anchor }}" {{- with .Attributes.class }} class="{{ . }}" {{- end }}> + {{ .Text }} + <a href="#{{ .Anchor }}">#</a> +</h{{ .Level }}> +``` + +{{% include "/_common/render-hooks/pageinner.md" %}} diff --git a/docs/content/en/render-hooks/images.md b/docs/content/en/render-hooks/images.md new file mode 100755 index 000000000..a4faac672 --- /dev/null +++ b/docs/content/en/render-hooks/images.md @@ -0,0 +1,138 @@ +--- +title: Image render hooks +linkTitle: Images +description: Create an image render to hook 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 + + ------------ ------------------ --------- + 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: + +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/_default/_markup/render-image.html" copy=true} +<img src="{{ .Destination | safeURL }}" + {{- with .PlainText }} alt="{{ . }}"{{ end -}} + {{- with .Title }} title="{{ . }}"{{ end -}} +> +{{- /* chomp trailing newline */ -}} +``` + +To render standalone images within `figure` elements: + +```go-html-template {file="layouts/_default/_markup/render-image.html" copy=true} +{{- if .IsBlock -}} + <figure> + <img src="{{ .Destination | safeURL }}" + {{- with .PlainText }} alt="{{ . }}"{{ end -}} + > + {{- with .Title }}<figcaption>{{ . }}</figcaption>{{ end -}} + </figure> +{{- else -}} + <img src="{{ .Destination | safeURL }}" + {{- with .PlainText }} alt="{{ . }}"{{ end -}} + {{- with .Title }} title="{{ . }}"{{ end -}} + > +{{- end -}} +``` + +Note that the above requires the following site configuration: + +{{< code-toggle file=hugo >}} +[markup.goldmark.parser] +wrapStandAloneImageWithinParagraph = false +{{< /code-toggle >}} + +## Default + +{{< 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: + +{{< code-toggle file=hugo >}} +[markup.goldmark.renderHooks.image] +enableDefault = true +{{< /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. + +> [!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. + +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 --git a/docs/content/en/render-hooks/introduction.md b/docs/content/en/render-hooks/introduction.md new file mode 100755 index 000000000..045d25c3d --- /dev/null +++ b/docs/content/en/render-hooks/introduction.md @@ -0,0 +1,81 @@ +--- +title: Introduction +description: An introduction to Hugo's render hooks. +categories: [] +keywords: [] +weight: 10 +--- + +When rendering Markdown to HTML, render hooks override the conversion. Each render hook is a template, with one template for each supported element type: + +- [Blockquotes](/render-hooks/blockquotes) +- [Code blocks](/render-hooks/code-blocks) +- [Headings](/render-hooks/headings) +- [Images](/render-hooks/images) +- [Links](/render-hooks/links) +- [Passthrough elements](/render-hooks/passthrough) +- [Tables](/render-hooks/tables) + +> [!note] +> Hugo supports multiple [content formats] including Markdown, HTML, AsciiDoc, Emacs Org Mode, Pandoc, and reStructuredText. +> +> The render hook capability is limited to Markdown. You cannot create render hooks for the other content formats. + +For example, consider this Markdown: + +```text +[Hugo](https://gohugo.io) + + +``` + +Without link or image render hooks, the example above is rendered to: + +```html +<p><a href="https://gohugo.io">Hugo</a></p> +<p><img alt="kitten" src="kitten.jpg"></p> +``` + +By creating link and image render hooks, you can alter the conversion from Markdown to HTML. For example: + +```html +<p><a href="https://gohugo.io" rel="external">Hugo</a></p> +<p><img alt="kitten" src="kitten.jpg" width="600" height="400"></p> +``` + +Each render hook is a template, with one template for each supported element type: + +```text +layouts/ +└── _default/ + └── _markup/ + ├── render-blockquote.html + ├── render-codeblock.html + ├── render-heading.html + ├── render-image.html + ├── render-link.html + ├── render-passthrough.html + └── render-table.html +``` + +The template lookup order allows you to create different render hooks for each page [type](g), [kind](g), language, and [output format](g). For example: + +```text +layouts/ +├── _default/ +│ └── _markup/ +│ ├── render-link.html +│ └── render-link.rss.xml +├── books/ +│ └── _markup/ +│ ├── render-link.html +│ └── render-link.rss.xml +└── films/ + └── _markup/ + ├── render-link.html + └── render-link.rss.xml +``` + +The remaining pages in this section describe each type of render hook, including examples and the context received by each template. + +[content formats]: /content-management/formats/ diff --git a/docs/content/en/render-hooks/links.md b/docs/content/en/render-hooks/links.md new file mode 100755 index 000000000..23f725eb7 --- /dev/null +++ b/docs/content/en/render-hooks/links.md @@ -0,0 +1,108 @@ +--- +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: + +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/_default/_markup/render-link.html" copy=true} +<a href="{{ .Destination | safeURL }}" + {{- with .Title }} title="{{ . }}"{{ end -}} +> + {{- with .Text }}{{ . }}{{ end -}} +</a> +{{- /* chomp trailing newline */ -}} +``` + +To include a `rel` attribute set to `external` for external links: + +```go-html-template {file="layouts/_default/_markup/render-link.html" copy=true} +{{- $u := urls.Parse .Destination -}} +<a href="{{ .Destination | safeURL }}" + {{- with .Title }} title="{{ . }}"{{ end -}} + {{- if $u.IsAbs }} rel="external"{{ end -}} +> + {{- with .Text }}{{ . }}{{ end -}} +</a> +{{- /* chomp trailing newline */ -}} +``` + +## Default + +{{< 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: + +{{< code-toggle file=hugo >}} +[markup.goldmark.renderHooks.link] +enableDefault = true +{{< /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. + +> [!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. + +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 --git a/docs/content/en/render-hooks/passthrough.md b/docs/content/en/render-hooks/passthrough.md new file mode 100755 index 000000000..356a030af --- /dev/null +++ b/docs/content/en/render-hooks/passthrough.md @@ -0,0 +1,124 @@ +--- +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. +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): + +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/_default/_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/_default/baseof.html" copy=true} +<head> + {{ $noop := .WordCount }} + {{ if .Page.Store.Get "hasMath" }} + <link href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css" rel="stylesheet"> + {{ end }} +</head> +``` + +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/ +└── _default/ + └── _markup/ + ├── render-passthrough-block.html + └── render-passthrough-inline.html +``` + +{{% include "/_common/render-hooks/pageinner.md" %}} diff --git a/docs/content/en/render-hooks/tables.md b/docs/content/en/render-hooks/tables.md new file mode 100755 index 000000000..c7671aff4 --- /dev/null +++ b/docs/content/en/render-hooks/tables.md @@ -0,0 +1,100 @@ +--- +title: Table render hooks +linkTitle: Tables +description: Create a table render hook 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): + +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/_default/_markup/render-table.html" copy=true} +<table + {{- range $k, $v := .Attributes }} + {{- if $v }} + {{- printf " %s=%q" $k $v | safeHTMLAttr }} + {{- end }} + {{- end }}> + <thead> + {{- range .THead }} + <tr> + {{- range . }} + <th + {{- with .Alignment }} + {{- printf " style=%q" (printf "text-align: %s" .) | safeHTMLAttr }} + {{- end -}} + > + {{- .Text -}} + </th> + {{- end }} + </tr> + {{- end }} + </thead> + <tbody> + {{- range .TBody }} + <tr> + {{- range . }} + <td + {{- with .Alignment }} + {{- printf " style=%q" (printf "text-align: %s" .) | safeHTMLAttr }} + {{- end -}} + > + {{- .Text -}} + </td> + {{- end }} + </tr> + {{- end }} + </tbody> +</table> +``` + +{{% include "/_common/render-hooks/pageinner.md" %}} diff --git a/docs/content/en/shortcodes/_index.md b/docs/content/en/shortcodes/_index.md new file mode 100644 index 000000000..826ee5796 --- /dev/null +++ b/docs/content/en/shortcodes/_index.md @@ -0,0 +1,7 @@ +--- +title: Shortcodes +description: Insert elements such as videos, images, and social media embeds into your content using Hugo's embedded shortcodes. +categories: [] +keywords: [] +weight: 10 +--- diff --git a/docs/content/en/shortcodes/details.md b/docs/content/en/shortcodes/details.md new file mode 100755 index 000000000..94502ac1c --- /dev/null +++ b/docs/content/en/shortcodes/details.md @@ -0,0 +1,74 @@ +--- +title: Details shortcode +linkTitle: Details +description: Insert an HTML details element into your content using the details shortcode. +categories: [] +keywords: [] +--- + +{{< new-in 0.140.0 />}} + +> [!note] +> To override Hugo's embedded `details` shortcode, copy the [source code] to a file with the same name in the `layouts/shortcodes` directory. + +## Example + +With this markup: + +```text +{{</* details summary="See the details" */>}} +This is a **bold** word. +{{</* /details */>}} +``` + +Hugo renders this HTML: + +```html +<details> + <summary>See the details</summary> + <p>This is a <strong>bold</strong> word.</p> +</details> +``` + +Which looks like this in your browser: + +{{< details summary="See the details" >}} +This is a **bold** word. +{{< /details >}} + +## Arguments + +summary +: (`string`) The content of the child `summary` element rendered from Markdown to HTML. Default is `Details`. + +open +: (`bool`) Whether to initially display the content of the `details` element. Default is `false`. + +class +: (`string`) The `class` attribute of the `details` element. + +name +: (`string`) The `name` attribute of the `details` element. + +title +: (`string`) The `title` attribute of the `details` element. + +## Styling + +Use CSS to style the `details` element, the `summary` element, and the content itself. + +```css +/* target the details element */ +details { } + +/* target the summary element */ +details > summary { } + +/* target the children of the summary element */ +details > summary > * { } + +/* target the content */ +details > :not(summary) { } +``` + +[source code]: {{% eturl details %}} diff --git a/docs/content/en/shortcodes/figure.md b/docs/content/en/shortcodes/figure.md new file mode 100755 index 000000000..74af52fe7 --- /dev/null +++ b/docs/content/en/shortcodes/figure.md @@ -0,0 +1,109 @@ +--- +title: Figure shortcode +linkTitle: Figure +description: Insert an HTML figure element into your content using the figure shortcode. +categories: [] +keywords: [] +--- + +> [!note] +> To override Hugo's embedded `figure` shortcode, copy the [source code] to a file with the same name in the `layouts/shortcodes` directory. + +## Example + +With this markup: + +```text +{{</* figure + src="/images/examples/zion-national-park.jpg" + alt="A photograph of Zion National Park" + link="https://www.nps.gov/zion/index.htm" + caption="Zion National Park" + class="ma0 w-75" +*/>}} +``` + +Hugo renders this HTML: + +```html +<figure class="ma0 w-75"> + <a href="https://www.nps.gov/zion/index.htm"> + <img + src="/images/examples/zion-national-park.jpg" + alt="A photograph of Zion National Park" + > + </a> + <figcaption> + <p>Zion National Park</p> + </figcaption> +</figure> +``` + +Which looks like this in your browser: + +{{< figure + src="/images/examples/zion-national-park.jpg" + alt="A photograph of Zion National Park" + link="https://www.nps.gov/zion/index.htm" + caption="Zion National Park" + class="ma0 w-75" +>}} + +## Arguments + +src +: (`string`) The `src` attribute of the `img` element. Typically this is a [page resource](g) or a [global resource](g). + +alt +: (`string`) The `alt` attribute of the `img` element. + +width +: (`int`) The `width` attribute of the `img` element. + +height +: (`int`) The `height` attribute of the `img` element. + +loading +: (`string`) The `loading` attribute of the `img` element. + +class +: (`string`) The `class` attribute of the `figure` element. + +link +: (`string`) The `href` attribute of the anchor element that wraps the `img` element. + +target +: (`string`) The `target` attribute of the anchor element that wraps the `img` element. + +rel +: (`rel`) The `rel` attribute of the anchor element that wraps the `img` element. + +title +: (`string`) Within the `figurecaption` element, the title is at the top, wrapped within an `h4` element. + +caption +: (`string`) Within the `figurecaption` element, the caption is at the bottom and may contain plain text or markdown. + +attr +: (`string`) Within the `figurecaption` element, the attribution appears next to the caption and may contain plain text or markdown. + +attrlink +: (`string`) The `href` attribute of the anchor element that wraps the attribution. + +## Image location + +The `figure` shortcode 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 >}} + +[source code]: {{% eturl figure %}} diff --git a/docs/content/en/shortcodes/gist.md b/docs/content/en/shortcodes/gist.md new file mode 100755 index 000000000..fd2b468ab --- /dev/null +++ b/docs/content/en/shortcodes/gist.md @@ -0,0 +1,35 @@ +--- +title: Gist shortcode +linkTitle: Gist +description: Embed a GitHub Gist in your content using the gist shortcode. +categories: [] +keywords: [] +expiryDate: 2027-02-01 # deprecated 2025-02-01 in v0.143.0 +--- + +{{< deprecated-in 0.143.0 >}} +The `gist` shortcode was deprecated in version 0.143.0 and will be removed in a future release. To continue embedding GitHub Gists in your content, you'll need to create a custom shortcode: + +1. Create a new file: Create a file named `gist.html` within the `layouts/shortcodes` directory. +1. Copy the source code: Paste the [original source code]({{% eturl gist %}}) of the gist shortcode into the newly created `gist.html` file. + +This will allow you to maintain the functionality of embedding GitHub Gists in your content after the deprecation of the original shortcode. +{{< /deprecated-in >}} + +To display a GitHub gist with this URL: + +```text +https://gist.github.com/user/50a7482715eac222e230d1e64dd9a89b +``` + +Include this in your Markdown: + +```text +{{</* gist user 23932424365401ffa5e9d9810102a477 */>}} +``` + +To display a specific file within the gist: + +```text +{{</* gist user 23932424365401ffa5e9d9810102a477 list.html */>}} +``` diff --git a/docs/content/en/shortcodes/highlight.md b/docs/content/en/shortcodes/highlight.md new file mode 100755 index 000000000..371a3d46e --- /dev/null +++ b/docs/content/en/shortcodes/highlight.md @@ -0,0 +1,107 @@ +--- +title: Highlight shortcode +linkTitle: Highlight +description: Insert syntax-highlighted code into your content using the highlight shortcode. +categories: [] +keywords: [highlight] +--- + +> [!note] +> To override Hugo's embedded `highlight` shortcode, copy the [source code] to a file with the same name in the `layouts/shortcodes` directory. + +> [!note] +> With the Markdown [content format], the `highlight` shortcode is rarely needed because, by default, Hugo automatically applies syntax highlighting to fenced code blocks. +> +> The primary use case for the `highlight` shortcode in Markdown is to apply syntax highlighting to inline code snippets. + +The `highlight` shortcode calls the [`transform.Highlight`] function which uses the [Chroma] syntax highlighter, supporting over 200 languages with more than 40 [highlighting styles]. + +## Arguments + +The `highlight` shortcode takes three arguments. + +```text +{{</* highlight LANG OPTIONS */>}} +CODE +{{</* /highlight */>}} +``` + +CODE +: (`string`) The code to highlight. + +LANG +: (`string`) The language of the code to highlight. Choose from one of the [supported languages]. This value is case-insensitive. + +OPTIONS +: (`string`) Zero or more space-separated key-value pairs wrapped in quotation marks. Set default values for each option in your [site configuration]. The key names are case-insensitive. + +## Example + +```text +{{</* highlight go "linenos=inline, hl_lines=3 6-8, style=emacs" */>}} +package main + +import "fmt" + +func main() { + for i := 0; i < 3; i++ { + fmt.Println("Value of i:", i) + } +} +{{</* /highlight */>}} +``` + +Hugo renders this to: + +{{< highlight go "linenos=inline, hl_Lines=3 6-8, noClasses=true" >}} +package main + +import "fmt" + +func main() { + for i := 0; i < 3; i++ { + fmt.Println("Value of i:", i) + } +} +{{< /highlight >}} + +You can also use the `highlight` shortcode for inline code snippets: + +```text +This is some {{</* highlight go "hl_inline=true" */>}}fmt.Println("inline"){{</* /highlight */>}} code. +``` + +Hugo renders this to: + +This is some {{< highlight go "hl_inline=true, noClasses=true" >}}fmt.Println("inline"){{< /highlight >}} code. + +Given the verbosity of the example above, if you need to frequently highlight inline code snippets, create your own shortcode using a shorter name with preset options. + +```go-html-template {file="layouts/shortcodes/hl.html"} +{{ $code := .Inner | strings.TrimSpace }} +{{ $lang := or (.Get 0) "go" }} +{{ $opts := dict "hl_inline" true "noClasses" true }} +{{ transform.Highlight $code $lang $opts }} +``` + +```text +This is some {{</* hl */>}}fmt.Println("inline"){{</* /hl */>}} code. +``` + +Hugo renders this to: + +This is some {{< hl >}}fmt.Println("inline"){{< /hl >}} code. + +## Options + +Pass the options when calling the shortcode. You can set their default values in your [site configuration]. + +{{% include "_common/syntax-highlighting-options.md" %}} + +[`transform.Highlight`]: /functions/transform/highlight/ +[Chroma]: https://github.com/alecthomas/chroma +[content format]: /content-management/formats/ +[highlighting styles]: /quick-reference/syntax-highlighting-styles/ +[site configuration]: /configuration/markup/#highlight +[source code]: {{% eturl highlight %}} +[supported languages]: /content-management/syntax-highlighting/#languages diff --git a/docs/content/en/shortcodes/instagram.md b/docs/content/en/shortcodes/instagram.md new file mode 100755 index 000000000..3256790c6 --- /dev/null +++ b/docs/content/en/shortcodes/instagram.md @@ -0,0 +1,42 @@ +--- +title: Instagram shortcode +linkTitle: Instagram +description: Embed an Instagram post in your content using the instagram shortcode. +categories: [] +keywords: [] +--- + +> [!note] +> To override Hugo's embedded `instagram` shortcode, copy the [source code] to a file with the same name in the `layouts/shortcodes` directory. + +## Example + +To display an Instagram post with this URL: + +```text +https://www.instagram.com/p/CxOWiQNP2MO/ +``` + +Include this in your Markdown: + +```text +{{</* instagram CxOWiQNP2MO */>}} +``` + +Huge renders this to: + +{{< instagram CxOWiQNP2MO >}} + +## Privacy + +Adjust the relevant privacy settings in your site configuration. + +{{< code-toggle config=privacy.instagram />}} + +disable +: (`bool`) Whether to disable the shortcode. Default is `false`. + +simple +: (`bool`) Whether to enable simple mode for image card generation. If `true`, Hugo creates a static card without JavaScript. This mode only supports image cards, and the image is fetched directly from Instagram's servers. Default is `false`. + +[source code]: {{% eturl instagram %}} diff --git a/docs/content/en/shortcodes/param.md b/docs/content/en/shortcodes/param.md new file mode 100755 index 000000000..133b2322a --- /dev/null +++ b/docs/content/en/shortcodes/param.md @@ -0,0 +1,38 @@ +--- +title: Param shortcode +linkTitle: Param +description: Insert a parameter from front matter or site configuration into your content using the param shortcode. +categories: [] +keywords: [] +--- + +> [!note] +> To override Hugo's embedded `param` shortcode, copy the [source code] to a file with the same name in the `layouts/shortcodes` directory. + +The `param` shortcode renders a parameter from front matter, falling back to a site parameter of the same name. The shortcode throws an error if the parameter does not exist. + +```text {file="content/example.md"} +--- +title: Example +date: 2025-01-15T23:29:46-08:00 +params: + color: red + size: medium +--- + +We found a {{%/* param "color" */%}} shirt. +``` + +Hugo renders this to: + +```html +<p>We found a red shirt.</p> +``` + +Access nested values by [chaining](g) the [identifiers](g): + +```text +{{%/* param my.nested.param */%}} +``` + +[source code]: {{% eturl param %}} diff --git a/docs/content/en/shortcodes/qr.md b/docs/content/en/shortcodes/qr.md new file mode 100755 index 000000000..98d6cee4c --- /dev/null +++ b/docs/content/en/shortcodes/qr.md @@ -0,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 +{{</* qr text="https://gohugo.io" /*/>}} +``` + +Or insert the text between the opening and closing tags: + +```text +{{</* qr */>}} +https://gohugo.io +{{</* /qr */>}} +``` + +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" /*/>}} +``` + +{{< qr text="tel:+12065550101" class="qrcode" targetDir="images/qr" />}} + +To create a QR code containing contact information in the [vCard] format: + +```text +{{</* qr level="low" scale=2 alt="QR code of vCard for John Smith" */>}} +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 */>}} +``` + +{{< 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 diff --git a/docs/content/en/shortcodes/ref.md b/docs/content/en/shortcodes/ref.md new file mode 100755 index 000000000..2f821254c --- /dev/null +++ b/docs/content/en/shortcodes/ref.md @@ -0,0 +1,61 @@ +--- +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 the Markdown [content format], this shortcode has become largely redundant. Its functionality is now primarily handled by [link render hooks], specifically the embedded one provided by Hugo. This hook effectively addresses all the use cases previously covered by this shortcode. + +## 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 +<a href="https://example.org/en/books/book-1/">Link A</a> + +<a href="https://example.org/en/books/book-1/">Link B</a> + +<a href="https://example.org/de/books/book-1/">Link C</a> + +<a href="https://example.org/de/books/book-1/index.json">Link D</a> +``` + +## Error handling + +{{% include "_common/ref-and-relref-error-handling.md" %}} + +[content format]: /content-management/formats/ +[link render hooks]: /render-hooks/images/#default +[Markdown notation]: /content-management/shortcodes/#notation +[source code]: {{% eturl ref %}} diff --git a/docs/content/en/shortcodes/relref.md b/docs/content/en/shortcodes/relref.md new file mode 100755 index 000000000..5b413b87e --- /dev/null +++ b/docs/content/en/shortcodes/relref.md @@ -0,0 +1,61 @@ +--- +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 the Markdown [content format], this shortcode has become largely redundant. Its functionality is now primarily handled by [link render hooks], specifically the embedded one provided by Hugo. This hook effectively addresses all the use cases previously covered by this shortcode. + +## 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]({{%/* 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 +<a href="/en/books/book-1/">Link A</a> + +<a href="/en/books/book-1/">Link B</a> + +<a href="/de/books/book-1/">Link C</a> + +<a href="/de/books/book-1/index.json">Link D</a> +``` + +## Error handling + +{{% include "_common/ref-and-relref-error-handling.md" %}} + +[content format]: /content-management/formats/ +[link render hooks]: /render-hooks/links/ +[Markdown notation]: /content-management/shortcodes/#notation +[source code]: {{% eturl relref %}} diff --git a/docs/content/en/shortcodes/vimeo.md b/docs/content/en/shortcodes/vimeo.md new file mode 100755 index 000000000..c354eefe0 --- /dev/null +++ b/docs/content/en/shortcodes/vimeo.md @@ -0,0 +1,65 @@ +--- +title: Vimeo shortcode +linkTitle: Vimeo +description: Embed a Vimeo video in your content using the vimeo shortcode. +categories: [] +keywords: [] +--- + +> [!note] +> To override Hugo's embedded `vimeo` shortcode, copy the [source code] to a file with the same name in the `layouts/shortcodes` directory. + +## Example + +To display a Vimeo video with this URL: + +```text +https://vimeo.com/channels/staffpicks/55073825 +``` + +Include this in your Markdown: + +```text +{{</* vimeo 55073825 */>}} +``` + +Hugo renders this to: + +{{< vimeo 55073825 >}} + +## Arguments + +class +: (`string`) The `class` attribute of the wrapping `div` element. Adding one or more CSS classes disables inline styling. + +id +: (`string`) The `id` of the Vimeo video + +title +: (`string`) The `title` attribute of the `iframe` element. + +If you provide a `class` or `title` you must use a named parameter for the `id`. + +```text +{{</* vimeo id=55073825 class="foo bar" title="My Video" */>}} +``` + +## Privacy + +Adjust the relevant privacy settings in your site configuration. + +{{< code-toggle config=privacy.vimeo />}} + +disable +: (`bool`) Whether to disable the shortcode. Default is `false`. + +enableDNT +: (`bool`) Whether to block the Vimeo player from tracking session data and analytics. Default is `false`. + +simple +: (`bool`) Whether to enable simple mode. If `true`, the video thumbnail is fetched from Vimeo and overlaid with a play button. Clicking the thumbnail opens the video in a new Vimeo tab. Default is `false`. + +The source code for the simple version of the shortcode is available [here]. + +[here]: {{% eturl vimeo_simple %}} +[source code]: {{% eturl vimeo %}} diff --git a/docs/content/en/shortcodes/x.md b/docs/content/en/shortcodes/x.md new file mode 100755 index 000000000..f1eebdaf2 --- /dev/null +++ b/docs/content/en/shortcodes/x.md @@ -0,0 +1,54 @@ +--- +title: X shortcode +linkTitle: X +description: Embed an X post in your content using the x shortcode. +categories: [] +keywords: [] +--- + +{{< new-in 0.141.0 />}} + +> [!note] +> To override Hugo's embedded `x` shortcode, copy the [source code] to a file with the same name in the `layouts/shortcodes` directory. + +## Example + +To display an X post with this URL: + +```txt +https://x.com/SanDiegoZoo/status/1453110110599868418 +``` + +Include this in your Markdown: + +```text +{{</* x user="SanDiegoZoo" id="1453110110599868418" */>}} +``` + +Rendered: + +{{< x user="SanDiegoZoo" id="1453110110599868418" >}} + +## Privacy + +Adjust the relevant privacy settings in your site configuration. + +{{< code-toggle config=privacy.x />}} + +disable +: (`bool`) Whether to disable the shortcode. Default is `false`. + +enableDNT +: (`bool`) Whether to prevent X from using post and embedded page data for personalized suggestions and ads. Default is `false`. + +simple +: (`bool`) Whether to enable simple mode. If `true`, Hugo builds a static version of the of the post without JavaScript. Default is `false`. + +The source code for the simple version of the shortcode is available [here]. + +If you enable simple mode you may want to disable the hardcoded inline styles by setting `disableInlineCSS` to `true` in your site configuration. The default value for this setting is `false`. + +{{< code-toggle config=services.x />}} + +[here]: {{% eturl x_simple %}} +[source code]: {{% eturl x %}} diff --git a/docs/content/en/shortcodes/youtube.md b/docs/content/en/shortcodes/youtube.md new file mode 100755 index 000000000..18c5ae6c2 --- /dev/null +++ b/docs/content/en/shortcodes/youtube.md @@ -0,0 +1,91 @@ +--- +title: YouTube shortcode +linkTitle: YouTube +description: Embed a YouTube video in your content using the youtube shortcode. +categories: [] +keywords: [] +--- + +> [!note] +> To override Hugo's embedded `youtube` shortcode, copy the [source code] to a file with the same name in the `layouts/shortcodes` directory. + +## Example + +To display a YouTube video with this URL: + +```text +https://www.youtube.com/watch?v=0RKpf3rK57I +``` + +Include this in your Markdown: + +```texts +{{</* youtube 0RKpf3rK57I */>}} +``` + +Hugo renders this to: + +{{< youtube 0RKpf3rK57I >}} + +## Arguments + +id +: (`string`) The video `id`. Optional if the `id` is provided as a positional argument as shown in the example above. + +allowFullScreen +: {{< new-in 0.125.0 />}} +: (`bool`) Whether the `iframe` element can activate full screen mode. Default is `true`. + +autoplay +: {{< new-in 0.125.0 />}} +: (`bool`) Whether to automatically play the video. Forces `mute` to `true`. Default is `false`. + +class +: (`string`) The `class` attribute of the wrapping `div` element. When specified, removes the `style` attributes from the `iframe` element and its wrapping `div` element. + +controls +: {{< new-in 0.125.0 />}} +: (`bool`) Whether to display the video controls. Default is `true`. + +end +: {{< new-in 0.125.0 />}} +: (`int`) The time, measured in seconds from the start of the video, when the player should stop playing the video. + +loading +: {{< new-in 0.125.0 />}} +: (`string`) The loading attribute of the `iframe` element, either `eager` or `lazy`. Default is `eager`. + +loop +: {{< new-in 0.125.0 />}} +: (`bool`) Whether to indefinitely repeat the video. Ignores the `start` and `end` arguments after the first play. Default is `false`. + +mute +: {{< new-in 0.125.0 />}} +: (`bool`) Whether to mute the video. Always `true` when `autoplay` is `true`. Default is `false`. + +start +: {{< new-in 0.125.0 />}} +: (`int`) The time, measured in seconds from the start of the video, when the player should start playing the video. + +title +: (`string`) The `title` attribute of the `iframe` element. Defaults to "YouTube video". + +Example using some of the above: + +```text +{{</* youtube id=0RKpf3rK57I start=30 end=60 loading=lazy */>}} +``` + +## Privacy + +Adjust the relevant privacy settings in your site configuration. + +{{< code-toggle config=privacy.youTube />}} + +disable +: (`bool`) Whether to disable the shortcode. Default is `false`. + +privacyEnhanced +: (`bool`) Whether to block YouTube from storing information about visitors on your website unless the user plays the embedded video. Default is `false`. + +[source code]: {{% eturl youtube %}} diff --git a/docs/content/en/showcase/1password-support/bio.md b/docs/content/en/showcase/1password-support/bio.md new file mode 100644 index 000000000..32d299bd4 --- /dev/null +++ b/docs/content/en/showcase/1password-support/bio.md @@ -0,0 +1,3 @@ +**1Password** is a password manager that keeps you safe online. It protects your secure information behind the one password only you know. + +The [1Password Support](https://support.1password.com/) website was built from scratch with **Hugo** and enhanced with **React** and **Elasticsearch** to give us the best of both worlds: The simplicity and performance of a static site, with the richness of a hosted web app. diff --git a/docs/content/en/showcase/1password-support/featured.png b/docs/content/en/showcase/1password-support/featured.png Binary files differnew file mode 100644 index 000000000..8e46495e6 --- /dev/null +++ b/docs/content/en/showcase/1password-support/featured.png diff --git a/docs/content/en/showcase/1password-support/index.md b/docs/content/en/showcase/1password-support/index.md new file mode 100644 index 000000000..54a30f849 --- /dev/null +++ b/docs/content/en/showcase/1password-support/index.md @@ -0,0 +1,37 @@ +--- +title: 1Password Support +date: 2018-02-22 +description: 'Showcase: "Compiles 400 pages in five languages in the blink of an eye."' +siteURL: https://support.1password.com/ +byline: "[Mitch Cohen](https://github.com/mitchchn), Documentation Team Lead" +aliases: [/showcase/1password/] +--- + +At 1Password, we used to go through a different documentation platform every month: blog engines, ebooks, wikis, site generators written in Ruby and JavaScript. Each was inadequate in its own special way. Then we found **Hugo**. We made one last switch, and we're glad we did. + +### Not all static site generators are created equal + +Finding a tool that will make your customers, writers, designers, _and_ DevOps team happy is no easy task, but we managed it with Hugo: + +**Hugo is static**. We're a security company, so we swear by static sites and use them wherever possible. We feel much safer pointing customers at HTML files than at a complicated server which needs to be hardened. + +**Hugo is Go**. We love the Go programming language at 1Password, and we were delighted to learn that Hugo used the same Go template syntax that our designers and front-end developers had already mastered. + +**Hugo is FAST**. Our previous static site generator took nearly a minute to compile our (then much smaller) site. Developers might be used to this, but it wasn't cutting it for writers who wanted to see live previews of their work. Hugo did the same job in milliseconds, and to this day compiles 400 pages in five languages in the blink of an eye. + +**Hugo is flexible**. Thanks to Hugo's content and layout system, we were able to preserve our existing file and directory structure and port our entire production site in a few days. We could then create new content types that weren't possible before, like these snazzy [showcases](https://support.1password.com/explore/extension/). + +**Hugo is great for writers**. Our documentation team was already comfortable with Markdown and Git and could start creating content for Hugo with zero downtime. Once we added shortcodes, our writers were able to dress up articles with features like [platform boxes](https://support.1password.com/get-the-apps/) with just a bit of new syntax. + +**Hugo has an amazing developer community**. Hugo updates are frequent and filled to the brim with features and fixes. As we developed the multilingual version of our site, we submitted PRs for features we needed and were helped through the process by [@bep](https://github.com/bep) and others. + +**Hugo is simple to deploy**. Hugo has just the right amount of configuration options to fit into our build system without being too complicated. + +### Tech specs + +- [1Password Support](https://support.1password.com) uses Hugo with a custom theme. It shares styles and some template code with [1Password.com](https://1password.com), which we also moved to Hugo in 2016. +- Code and articles live in a private GitHub repository, which is deployed to a static content server using Git hooks. +- Writers build and preview the site on their computers and contribute content using pull requests. +- We use Hugo's [multilingual support](/content-management/multilingual/) to build the site in English, Spanish, French, Italian, German, and Russian. With the help of Hugo, 1Password Support became our very first site in multiple languages. +- Our [contact form](https://support.1password.com/contact) is a single-page React app. We were able to integrate it with Hugo seamlessly thanks to its support for static files. +- The one part of the support site which is not static is our search engine, which we developed with Elasticsearch and host on AWS. diff --git a/docs/content/en/showcase/_index.md b/docs/content/en/showcase/_index.md new file mode 100644 index 000000000..e618e8104 --- /dev/null +++ b/docs/content/en/showcase/_index.md @@ -0,0 +1,7 @@ +--- +title: Showcases +cascade: + build: + render: never + list: never +--- diff --git a/docs/content/en/showcase/_template/bio.md b/docs/content/en/showcase/_template/bio.md new file mode 100644 index 000000000..5ea389617 --- /dev/null +++ b/docs/content/en/showcase/_template/bio.md @@ -0,0 +1,6 @@ +Add some **general info** about Myshowcase here. + +The site is built by: + +- [Person 1](https://example.org) +- [Person 1](https://example.org) diff --git a/docs/content/en/showcase/_template/featured.png b/docs/content/en/showcase/_template/featured.png Binary files differnew file mode 100644 index 000000000..4f390132e --- /dev/null +++ b/docs/content/en/showcase/_template/featured.png diff --git a/docs/content/en/showcase/_template/index.md b/docs/content/en/showcase/_template/index.md new file mode 100644 index 000000000..3103903e1 --- /dev/null +++ b/docs/content/en/showcase/_template/index.md @@ -0,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 + +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 --git a/docs/content/en/showcase/alora-labs/bio.md b/docs/content/en/showcase/alora-labs/bio.md new file mode 100644 index 000000000..f14a90b75 --- /dev/null +++ b/docs/content/en/showcase/alora-labs/bio.md @@ -0,0 +1,3 @@ +**Alora Labs** is a product development consultancy headquartered in Toronto, Canada. + +We help companies build software and IoT products and were recently recognized as one of the [**top IoT development firms**](https://aloralabs.com/insights/alora-labs-receives-clutch-2021-top-iot-agency-award) in Toronto. diff --git a/docs/content/en/showcase/alora-labs/featured.png b/docs/content/en/showcase/alora-labs/featured.png Binary files differnew file mode 100644 index 000000000..b8e1f302b --- /dev/null +++ b/docs/content/en/showcase/alora-labs/featured.png diff --git a/docs/content/en/showcase/alora-labs/index.md b/docs/content/en/showcase/alora-labs/index.md new file mode 100644 index 000000000..5e676bad3 --- /dev/null +++ b/docs/content/en/showcase/alora-labs/index.md @@ -0,0 +1,18 @@ +--- +title: Alora Labs +date: 2021-05-27 +description: 'Showcase: "Making performant websites accessible for everyone."' +siteURL: https://aloralabs.com/ +siteSource: https://github.com/aloralabs/homepage +aliases: [/showcase/aloralabs/] +--- + +At Alora Labs we always have an eye open for new tools and technology that we can utilize to the benefit of our customers or internal projects like our website. + +The previous iteration of our site was built with Jekyll, which served us well at first. However as time went on, we became frustrated with the number of dependencies we had to rely on, that would often break at the most inconvenient times. + +Hugo was a breath of fresh air in this regard, a single binary that works equally well on Windows as it did on macOS or Linux. We no longer need additional tools for image optimization, Sass compilation or JavaScript bundling. Everything just works, and with a substantial performance boost too. + +Hugo has become a favorite tool in the tool belt and the foundation for many client projects. We couldn't be happier with the switch and we are optimistic about recommending Hugo for many years to come. + +Thank you to the vibrant community and talented development team for all the hard work in making Hugo a success. As excellent as Hugo is now, we cannot wait to see what the release notes have in store for us next. diff --git a/docs/content/en/showcase/ampio-help/bio.md b/docs/content/en/showcase/ampio-help/bio.md new file mode 100644 index 000000000..a08b26be7 --- /dev/null +++ b/docs/content/en/showcase/ampio-help/bio.md @@ -0,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! + +__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 --git a/docs/content/en/showcase/ampio-help/featured.png b/docs/content/en/showcase/ampio-help/featured.png Binary files differnew file mode 100644 index 000000000..07974e7f1 --- /dev/null +++ b/docs/content/en/showcase/ampio-help/featured.png diff --git a/docs/content/en/showcase/ampio-help/index.md b/docs/content/en/showcase/ampio-help/index.md new file mode 100644 index 000000000..462452cb1 --- /dev/null +++ b/docs/content/en/showcase/ampio-help/index.md @@ -0,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 + +## 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 --git a/docs/content/en/showcase/bypasscensorship/bio.md b/docs/content/en/showcase/bypasscensorship/bio.md new file mode 100644 index 000000000..a6c98f9ba --- /dev/null +++ b/docs/content/en/showcase/bypasscensorship/bio.md @@ -0,0 +1,6 @@ +Bypass Censorship find and promote tools that provide Internet access to everyone. + +The site is built by: + +- [Leyla Avsar](https://www.leylaavsar.com/) (designer) +- [Fredrik Jonsson](https://xdeb.net/) (dev) diff --git a/docs/content/en/showcase/bypasscensorship/featured.png b/docs/content/en/showcase/bypasscensorship/featured.png Binary files differnew file mode 100644 index 000000000..d6f429112 --- /dev/null +++ b/docs/content/en/showcase/bypasscensorship/featured.png diff --git a/docs/content/en/showcase/bypasscensorship/index.md b/docs/content/en/showcase/bypasscensorship/index.md new file mode 100644 index 000000000..bd1a072c0 --- /dev/null +++ b/docs/content/en/showcase/bypasscensorship/index.md @@ -0,0 +1,23 @@ +--- +title: Bypass Censorship +date: 2019-06-16 +description: 'Showcase: "Bypass Censorship find and promote tools that provide Internet access to everyone."' +siteURL: https://www.bypasscensorship.org/ +byline: "[Fredrik Jonsson](https://xdeb.net/), Web developer & Linux sysadmin" +--- + +The British Broadcasting Corporation (BBC) (UK), Deutsche Welle (DW) (Germany), France Médias Monde (FMM) (France), the U.S. Agency for Global Media (USAGM) (US) and the Open Technology Fund (OTF) (US) co-sponsor the Bypass Censorship website. + +Websites of international news agencies are often blocked in many countries. In order to connect people to these sites, Bypass Censorship feature and recommend tools in the following languages: English, French, Spanish, Arabic, Farsi, Chinese, and Russian. + +One of the tools is the Bypass Censorship Extension for Firefox and Chrome. The extension help direct people to mirrors of partners sites if they are being censored. + +The first version of the site was built in Drupal 8 but it was relaunched as a static site built with Hugo in 2019. + +Security, page load time and easy of hosting is the main reasons for switching to a static site. As the lead developer I had good experience with Hugo and was interested in exploring the multilingual features. + +It's a simply site, basically one page in seven languages. I had no problems getting Hugo to output what I wanted. Found the multilingual support straight forward and easy to work with. + +Thanks to the design by [Leyla Avsar](https://www.leylaavsar.com/) the site also looks good. I used the [Hugo Zen theme](https://github.com/frjo/hugo-theme-zen) with a few custom templates and the needed CSS. + +The editors can maintain content via [Forestry.io CMS](https://forestry.io/) or directly via Git. Forestry does unfortunately not have multilingual support. All the language versions are in one pile making it harder to find the right file to edit, but it works. diff --git a/docs/content/en/showcase/digitalgov/bio.md b/docs/content/en/showcase/digitalgov/bio.md new file mode 100644 index 000000000..70bb990b9 --- /dev/null +++ b/docs/content/en/showcase/digitalgov/bio.md @@ -0,0 +1 @@ +**Digital.gov** helps people in the U.S. government deliver better, more accessible digital services through publishing essential guidance, resources, tools, and online events that make it easier for people to design, build, and deliver essential services for the public. diff --git a/docs/content/en/showcase/digitalgov/featured.png b/docs/content/en/showcase/digitalgov/featured.png Binary files differnew file mode 100644 index 000000000..7d065dce9 --- /dev/null +++ b/docs/content/en/showcase/digitalgov/featured.png diff --git a/docs/content/en/showcase/digitalgov/index.md b/docs/content/en/showcase/digitalgov/index.md new file mode 100644 index 000000000..7f0584712 --- /dev/null +++ b/docs/content/en/showcase/digitalgov/index.md @@ -0,0 +1,64 @@ +--- +title: Digital.gov +date: 2020-05-01 +description: 'Showcase: "Guidance on building better digital services in government."' +siteURL: https://digital.gov/ +siteSource: https://github.com/gsa/digitalgov.gov +--- + +For over a decade, Digital.gov has provided guidance, training, and community support to the people who are responsible for delivering digital services in the U.S. government. Essentially, it is a place where people can find examples of problems being solved in government, and get links to the tools and resources they need. + +Through collaboration in our communities of practice, Digital.gov is a window into the people who work in technology in government and the challenges they face making digital services stronger and more effective. [Read more about our site »](https://digital.gov/2019/12/19/a-new-digitalgov/) + +Digital.gov is built using the [U.S. Web Design System](https://designsystem.digital.gov/) (USWDS) and have followed the [design principles](https://designsystem.digital.gov/maturity-model/) in building out our new site: + +- **Start with real user needs** — We used human-centered design methods to inform our product decisions (like qualitative user research), and gathered feedback from real users. We also continually test our assumptions with small experiments. +- **Earn trust** —We recognize that trust has to be earned every time. We are including all [required links and content](https://digital.gov/resources/required-web-content-and-links/) on our site, clearly identifying as a government site, building with modern best practices, and using HTTPS. +- **Embrace accessibility** — [Accessibility](https://digital.gov/resources/intro-accessibility/) affects everybody, and we built it into every decision. We're continually working to conform to Section 508 requirements, use user experience best practices, and support a wide range of devices. +- **Promote continuity** — We started from shared solutions like USWDS and [Federalist](https://federalist.18f.gov/). We designed our site to clearly identify as a government site by including USWDS's .gov banner, common colors and patterns, and built with modern best practices. +- **Listen** — We actively collect user feedback and web metrics. We use the [Digital Analytics Program](https://digital.gov/services/dap/) (DAP) and analyze the data to discover actionable insights. We make small, incremental changes to continuously improve our website by listening to readers and learning from what we hear. + +_More on the [USWDS maturity model »](https://designsystem.digital.gov/maturity-model/)_ + +## Open tools + +We didn't start from scratch. We built and designed the Digital.gov using many of the open-source tools and services that we develop for government here in the [Technology Transformation Services](https://www.gsa.gov/tts/) (TTS). + +Using services that make it possible to design, build, and iterate quickly are essential to modern web design and development, which is why [Federalist](https://federalist.18f.gov/) and the [U.S. Web Design System](https://designsystem.digital.gov/) are such a great combination. + +**Why Hugo?** Well, with around `~3,000` files _(and growing)_ and `~9,000` built pages, we needed a site generator that could handle that volume with lightning fast speed. + +Hugo was the clear option. The [Federalist](https://federalist.18f.gov/) team quickly added it to their available site generators, and we were off. + +At the moment, it takes around `32 seconds` to build close to `~10,000` pages! + +Take a look: + +```text + + | EN +-------------------+------- + Pages | 7973 + Paginator pages | 600 + Non-page files | 108 + Static files | 851 + Processed images | 0 + Aliases | 1381 + Sitemaps | 1 + Cleaned | 0 + +Built in 32.427 seconds +``` + +In addition to Hugo, we are proudly using a number of other tools and services, all built by government are free to use: + +- [Federalist](https://federalist.18f.gov/) +- [Search.gov](https://www.search.gov/) — A free, hosted search platform for federal websites. +- [Cloud.gov](https://www.cloud.gov/) — helps teams build, run, and authorize cloud-ready or legacy government systems quickly and cheaply. +- [Federal CrowdSource Mobile Testing Program](https://digital.gov/services/service_mobile-testing-program/) — Free mobile compatibility testing by feds, for feds. +- [Digital Analytics Program](https://digital.gov/services/dap/) (DAP) — A free analytics tool for measuring digital services in the federal government +- [Section508.gov](https://www.section508.gov/) and [PlainLanguage.gov](https://www.plainlanguage.gov/) resources +- [API.data.gov](https://api.data.gov/) — a free API management service for federal agencies +- [U.S. Digital Registry](https://digital.gov/services/u-s-digital-registry/) — A resource for confirming the official status of government social media accounts, mobile apps, and mobile websites. + +**Questions or feedback?** [Submit an issue](https://github.com/GSA/digitalgov.gov/issues) or send us an email to [digitalgov@gsa.gov](mailto:digitalgov@gsa.gov) :heart: diff --git a/docs/content/en/showcase/fireship/bio.md b/docs/content/en/showcase/fireship/bio.md new file mode 100644 index 000000000..2a5639aa7 --- /dev/null +++ b/docs/content/en/showcase/fireship/bio.md @@ -0,0 +1,5 @@ +**Fireship.io** is an ecosystem of detailed and practical resources for developers who want to build and ship high-quality apps. + +The site is built by: + +- [Jeff Delaney](https://fireship.io/contributors/jeff-delaney/) diff --git a/docs/content/en/showcase/fireship/featured.png b/docs/content/en/showcase/fireship/featured.png Binary files differnew file mode 100644 index 000000000..33d1a47c5 --- /dev/null +++ b/docs/content/en/showcase/fireship/featured.png diff --git a/docs/content/en/showcase/fireship/index.md b/docs/content/en/showcase/fireship/index.md new file mode 100644 index 000000000..454ee87d7 --- /dev/null +++ b/docs/content/en/showcase/fireship/index.md @@ -0,0 +1,17 @@ +--- +title: fireship.io +date: 2019-02-02 +description: 'Showcase: "Hugo helps us create complex technical content that integrates engaging web components."' +siteURL: https://fireship.io +siteSource: https://github.com/fireship-io/fireship.io +byline: "[Jeff Delaney](https://github.com/codediodeio), Fireship.io Creator" +--- + +After careful consideration of JavaScript/JSX-based static site generators, it became clear that Hugo was the only tool capable of handling our project's complex demands. Not only do we have multiple content formats and taxonomies, but we often need to customize the experience at a more granular level. The problems Hugo has solved for us include: + +- **Render speed.** We know from past experience that JavaScript-based static site generators become very slow when you have thousands of pages and images. +- **Feature-rich.** Our site has a long list of specialized needs and Hugo somehow manages to cover every single use case. +- **Composability.** Hugo's partial and shortcode systems empower us to write DRY and maintainable templates. +- **Simplicity.** Hugo is easy to learn (even without Go experience) and doesn't burden us with brittle dependencies. + +The site is able to achieve Lighthouse performance scores of 95+, despite the fact that it is a fully interactive PWA that ships Angular and Firebase in the JS bundle. This is made possible by (1) prerendering content with Hugo and (2) lazily embedding native web components directly in the HTML and Markdown. We provide a [detailed explanation](https://youtu.be/gun8OiGtlNc) of the architecture on YouTube and can't imagine development without Hugo. diff --git a/docs/content/en/showcase/forestry/bio.md b/docs/content/en/showcase/forestry/bio.md new file mode 100644 index 000000000..23951a1c6 --- /dev/null +++ b/docs/content/en/showcase/forestry/bio.md @@ -0,0 +1,3 @@ +Forestry.io is a Git-backed CMS (content management system) for websites and web products built using static site generators such as Hugo. + +Forestry bridges the gap between developers and their teams, by making development fun and easy, while providing powerful content management for their teams. diff --git a/docs/content/en/showcase/forestry/featured.png b/docs/content/en/showcase/forestry/featured.png Binary files differnew file mode 100644 index 000000000..1ee315e78 --- /dev/null +++ b/docs/content/en/showcase/forestry/featured.png diff --git a/docs/content/en/showcase/forestry/index.md b/docs/content/en/showcase/forestry/index.md new file mode 100644 index 000000000..5b8872316 --- /dev/null +++ b/docs/content/en/showcase/forestry/index.md @@ -0,0 +1,48 @@ +--- +title: Forestry.io +date: 2018-03-16 +description: 'Showcase: "Seeing Hugo in action is a whole different world of awesome."' +siteURL: https://forestry.io/ +siteSource: https://github.com/forestryio/forestry.io +--- + +It was clear from the get-go that we had to go with a static site generator. Static sites are secure, performant, and give you 100% flexibility. At [Forestry.io](https://forestry.io/) we provide Content Management Solutions for websites built with static site generators, so we might be a little biased. The only question: Which static site generator was the right choice for us? + +### Why Hugo? + +In our early research we looked at Ionic's [site](https://github.com/ionic-team/ionic) to get some inspiration. They used Jekyll to build their website. While Jekyll is a great generator, the build times for larger sites can be painfully slow. With more than 150 pages plus many custom configurations and add-ons, our website doesn't fall into the low-volume category anymore. Our developers want a smooth experience when working on the website and our content editors need the ability to preview content quickly. In short, we need our builds to be lightning fast. + +We knew Hugo was fast but we did [some additional benchmarking](https://forestry.io/blog/hugo-vs-jekyll-benchmark/) before making our decision. Seeing Hugo in action is a whole different world of awesome. Hugo takes less than one second to build our 150-page site! Take a look: + +```text + | EN ++------------------+-----+ + Pages | 141 + Paginator pages | 4 + Non-page files | 0 + Static files | 537 + Processed images | 0 + Aliases | 60 + Sitemaps | 1 + Cleaned | 0 + +Total in 739 ms +``` + +In fact, we liked Hugo so much that our wizard Chris made his workflow public and we started the open-source project [Create-Static-Site](https://github.com/forestryio/create-static-site). It's [a simple way to spin up sites](https://forestry.io/blog/up-and-running-with-hugo/) and set up a modern web development workflow with one line of code. Essentially it adds build configurations as a dependency for JS, CSS and Image Processing. + +Lastly, we want to take the opportunity to give some love to other amazing tools we used building our website. + +### What tools did we use? + +- Our Norwegian designer Nichlas is in love with [**Sketch**](https://www.sketchapp.com/). From what we hear it's a designer's dream come true. +- Some say our main graphic is [mesmerizing](https://x.com/hmncllctv/status/968907474664284160). Nichlas created it using [**3DS Max**](https://www.autodesk.com/products/3ds-max/overview). +- [**Hugo**](https://gohugo.io/) -- of course. +- Chris can't think of modern web development without [**Gulp**](https://gulpjs.com/) & [**Webpack**](https://webpack.js.org/). We used them to add additional build steps such as Browsersync, CSS, JS and SVG optimization. +- Speaking about adding steps to our build, our lives would be much harder without [**CircleCI**](https://circleci.com/) for continuous deployment and automated testing purposes. +- We can't stop raving about [**Algolia**](https://www.algolia.com/). Chris loves it and even wrote a tutorial on [how to implement Algolia](https://forestry.io/blog/search-with-algolia-in-hugo/) into static sites using Hugo's [custom output formats](/configuration/output-formats/). +- [**Cloudinary**](https://cloudinary.com/) is probably one of the easiest ways to get responsive images into your website. +- We might be a little biased on this one - We think [**Forestry.io**](https://forestry.io/) is a great way to add a content management system with a clean UI on top of your site without interrupting your experience as a developer. +- For hosting purposes we use the almighty [**AWS**](https://aws.amazon.com/). +- [**Formspree.io**](https://formspree.io/) is managing our support and enterprise requests. +- We also use browser cookies and JS to customize our user's experience and give it a more dynamic feel. diff --git a/docs/content/en/showcase/godot-tutorials/bio.md b/docs/content/en/showcase/godot-tutorials/bio.md new file mode 100644 index 000000000..fd849f844 --- /dev/null +++ b/docs/content/en/showcase/godot-tutorials/bio.md @@ -0,0 +1,7 @@ +[Godot Tutorials](https://godottutorials.com) aims to teach beginners how to get up and running with basic game programming and game development skills. + +The website is built with the **Hugo Framework** alongside aws+cloudfront+lambda. + +The site is built by: + +- [Godot Tutorials](https://godottutorials.com) diff --git a/docs/content/en/showcase/godot-tutorials/featured.png b/docs/content/en/showcase/godot-tutorials/featured.png Binary files differnew file mode 100644 index 000000000..fef13b996 --- /dev/null +++ b/docs/content/en/showcase/godot-tutorials/featured.png diff --git a/docs/content/en/showcase/godot-tutorials/index.md b/docs/content/en/showcase/godot-tutorials/index.md new file mode 100644 index 000000000..fe4f9337e --- /dev/null +++ b/docs/content/en/showcase/godot-tutorials/index.md @@ -0,0 +1,17 @@ +--- +title: Godot Tutorials +date: 2021-01-07 +description: "Teaching game development skills with love." +siteURL: https://godottutorials.com +byline: "[Godot Tutorials](https://godottutorials.com), Web Developer & Game Programmer" +--- + +[Godot Tutorials](https://godottutorials.com) started as a way to teach beginners game programming and game development. +As I created videos, I ran into a problem; if I made a mistake with a YouTube video, it was difficult to correct errors. + +I discovered that blogging episodes and having articles that teach on top of my videos is a fantastic solution to my problem. + +As I researched blogging platforms, I came across two solutions; however, I chose [Hugo](https://gohugo.io) because it's built with Markdown in mind and simplified my workflow. + +In a sense, with [Hugo](https://gohugo.io) programmed the right way, I can focus **more time on planning, creating, and editing** +my videos and **less time maintaining and fixing** my website. diff --git a/docs/content/en/showcase/hapticmedia/bio.md b/docs/content/en/showcase/hapticmedia/bio.md new file mode 100644 index 000000000..4423edb70 --- /dev/null +++ b/docs/content/en/showcase/hapticmedia/bio.md @@ -0,0 +1 @@ +**Hapticmedia** provides interactive 3D configurators for eCommerce. diff --git a/docs/content/en/showcase/hapticmedia/featured.png b/docs/content/en/showcase/hapticmedia/featured.png Binary files differnew file mode 100644 index 000000000..a47ea9c2c --- /dev/null +++ b/docs/content/en/showcase/hapticmedia/featured.png diff --git a/docs/content/en/showcase/hapticmedia/index.md b/docs/content/en/showcase/hapticmedia/index.md new file mode 100644 index 000000000..52c3337bf --- /dev/null +++ b/docs/content/en/showcase/hapticmedia/index.md @@ -0,0 +1,31 @@ +--- +title: Hapticmedia Blog +date: 2019-10-01 +description: 'Showcase: "A simple, but powerful, multilingual blog."' +siteURL: https://hapticmedia.fr/blog/en/ +byline: "[Cyril Bonnet](https://github.com/monsieurnebo), Web Developer" +--- + +Our goal was to create a simple, effective and multilingual blog on [3D technology](https://hapticmedia.fr/blog/en/3d-technology/) that could be managed by a non-technical profile. + +## Why Hugo? + +Hugo addresses all these needs, coupled with [Forestry.io](https://forestry.io/) for its administration via a "turnkey" interface. We have attached particular importance to SEO, and therefore to the creation of an advanced taxonomy system. Thus, each author and tag has a dedicated page, listing the related posts. + +## What we liked + +- The **multilingual** content support, especially simple to setup. +- The **multiple environments** support (develop, staging, test, production, ...). +- Although a hard start with the Go language, the power of the **Hugo's templating**. +- The **partial layouts**, including the `internals` (e.g. social meta tags). +- The **build time**, unbeatable ⚡️⚡️⚡️. + +## Tools & workflow + +- We used the same design as **[our website](https://hapticmedia.fr/en/)**, recreated as a Hugo HTML template. +- **[Hugo](https://gohugo.io)** for the static website generator. +- **[CircleCI](https://circleci.com)** for continuous integration & deployment. +- **[AWS](https://aws.amazon.com/)** for web hosting. +- **[Forestry.io](https://forestry.io)** for the content management. + +**All of these tools allow our editor to manage the blog's content without having to worry about its technical aspect, which is managed by the developers.** diff --git a/docs/content/en/showcase/hartwell-insurance/bio.md b/docs/content/en/showcase/hartwell-insurance/bio.md new file mode 100644 index 000000000..4cded7beb --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/bio.md @@ -0,0 +1,5 @@ +Hartwell Insurance is an insurance company set up solely to service the Broker community. + +By combining **Hugo**, **Service Worker** and **Netlify**, we were able to achieve incredible global site performance. + +The site was built by [Tomango](https://www.tomango.co.uk) diff --git a/docs/content/en/showcase/hartwell-insurance/featured.png b/docs/content/en/showcase/hartwell-insurance/featured.png Binary files differnew file mode 100644 index 000000000..ced251f98 --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/featured.png diff --git a/docs/content/en/showcase/hartwell-insurance/hartwell-columns.png b/docs/content/en/showcase/hartwell-insurance/hartwell-columns.png Binary files differnew file mode 100644 index 000000000..c9d36b67d --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/hartwell-columns.png diff --git a/docs/content/en/showcase/hartwell-insurance/hartwell-lighthouse.png b/docs/content/en/showcase/hartwell-insurance/hartwell-lighthouse.png Binary files differnew file mode 100644 index 000000000..a882f01fd --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/hartwell-lighthouse.png diff --git a/docs/content/en/showcase/hartwell-insurance/hartwell-webpagetest.png b/docs/content/en/showcase/hartwell-insurance/hartwell-webpagetest.png Binary files differnew file mode 100644 index 000000000..f60994ea1 --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/hartwell-webpagetest.png diff --git a/docs/content/en/showcase/hartwell-insurance/index.md b/docs/content/en/showcase/hartwell-insurance/index.md new file mode 100644 index 000000000..07ee6182c --- /dev/null +++ b/docs/content/en/showcase/hartwell-insurance/index.md @@ -0,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._ + +> **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 `<h1>`. No multi-wrapper or difficult-to-clear shortcodes, just clean HTML. + + + +For the ripple effects on the section headings, I used JS to prepend a `<canvas>` 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. + + + +[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. + + + +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 --git a/docs/content/en/showcase/keycdn/bio.md b/docs/content/en/showcase/keycdn/bio.md new file mode 100644 index 000000000..90f623dca --- /dev/null +++ b/docs/content/en/showcase/keycdn/bio.md @@ -0,0 +1 @@ +[KeyCDN](https://www.keycdn.com) is a high performance content delivery network (CDN) offering many powerful features, including image processing that can transform and optimize images in real time. Our network offers global coverage to speed up content delivery and is capable of delivering entire static websites, like those built with Hugo, at the edge. diff --git a/docs/content/en/showcase/keycdn/featured.png b/docs/content/en/showcase/keycdn/featured.png Binary files differnew file mode 100644 index 000000000..46018a8f9 --- /dev/null +++ b/docs/content/en/showcase/keycdn/featured.png diff --git a/docs/content/en/showcase/keycdn/index.md b/docs/content/en/showcase/keycdn/index.md new file mode 100644 index 000000000..c6972325f --- /dev/null +++ b/docs/content/en/showcase/keycdn/index.md @@ -0,0 +1,28 @@ +--- +title: KeyCDN +date: 2020-04-10 +description: 'Showcase: "Hugo has become an integral part of our stack."' +siteURL: https://www.keycdn.com +--- + +At KeyCDN one of our primary focuses is on performance. With speed being ingrained in our DNA we knew from the start that we must use a fast static website generator that could meet our requirements. When evaluating the right solution, Hugo met our requirements and we looked no further as it was the fastest and most flexible. + +## Why we chose Hugo + +Before our migration to Hugo our website was powered by a PHP-based website that had about 50 pages and a WordPress website that had over 500 posts between our blog and knowledge base. This became harder to maintain as time continued. We felt like we were losing the speed and flexibility that we require. To overcome this we knew we needed to convert our website to be static. This would allow our website to be faster and more secure as it could be delivered by all of our edge locations. + +It wasn't an easy task at the beginning, however, after evaluating Hugo and benchmarking it we knew we had found the ideal solution. Hugo was by far the fastest setup and offered an intuitive way to build our entire website exactly as needed. The Go-based templates, shortcodes, and configuration options made it easy to build a complex website. + +In the fall of 2018 we started the migration and within a couple short months we had built a custom static website with Hugo and migrated all content from our old systems. The simplicity and vast amount of functionality that Hugo offers made this process fast and left our entire team, including all of our writers and developers, happy with the migration. Since migrating to Hugo we haven't looked back. Hugo has become an integral part of our stack. We're grateful to all those who have contributed to make Hugo what it is today. + +## Technical overview + +Below is an overview of what we used with Hugo to build our website: + +- [KeyCDN](https://www.keycdn.com) uses a custom theme and is our primary hub for all style sheets and JavaScript. Our other websites, like [KeyCDN Tools](https://tools.keycdn.com), only import the required style sheets and JavaScript. +- We use [Gulp](https://gulpjs.com) in our build process for many tasks, such as combining, versioning, and compressing our style sheets as well as our JavaScript. +- Our search is powered by a custom solution that we've built. It allows our pages, blog, and knowledge base to be searched. It uses [Axios](https://github.com/axios/axios) to send a `POST` request containing the search query. An index file in JSON generated by Hugo is searched and the results are then returned. +- Our commenting system is also powered by a custom solution that we've built. It uses Axios to send a `GET` request containing the slug to pull the comment thread and a `POST` request containing the name, email address, and comment when submitting a comment. +- Our contact form is a simple HTML form, which uses Axios as well. +- Our writers use shortcodes to enhance the capability of Markdown. +- Our entire website is delivered through KeyCDN using a Pull Zone, which means all of our edge locations are delivering our website. diff --git a/docs/content/en/showcase/letsencrypt/bio.md b/docs/content/en/showcase/letsencrypt/bio.md new file mode 100644 index 000000000..62c547980 --- /dev/null +++ b/docs/content/en/showcase/letsencrypt/bio.md @@ -0,0 +1 @@ +Let's Encrypt is a free, automated, and open certificate authority (CA), run for the public's benefit. It is a service provided by the [Internet Security Research Group (ISRG)](https://www.abetterinternet.org/). diff --git a/docs/content/en/showcase/letsencrypt/featured.png b/docs/content/en/showcase/letsencrypt/featured.png Binary files differnew file mode 100644 index 000000000..9535d91bd --- /dev/null +++ b/docs/content/en/showcase/letsencrypt/featured.png diff --git a/docs/content/en/showcase/letsencrypt/index.md b/docs/content/en/showcase/letsencrypt/index.md new file mode 100644 index 000000000..8696cb7ad --- /dev/null +++ b/docs/content/en/showcase/letsencrypt/index.md @@ -0,0 +1,18 @@ +--- +title: Let's Encrypt +date: 2018-03-13 +description: 'Showcase: "Lessons learned from taking letsencrypt.org to Hugo."' +siteURL: https://letsencrypt.org/ +siteSource: https://github.com/letsencrypt/website +byline: "[bep](https://github.com/bep), Hugo Lead" +--- + +The **Let's Encrypt website** has a common set of elements: A landing page and some other static info-pages, a document section, a blog, and a documentation section. Having it moved to Hugo was mostly motivated by a _simpler administration and Hugo's [multilingual support](/content-management/multilingual/)_. They already serve HTTPS to more than 60 million domains, and having the documentation available in more languages will increase that reach.[^1] + +{{< x user="letsencrypt" id="971755920639307777" >}} + +I helped them port the site from Jekyll to Hugo. There are usually very few surprises doing this. I know Hugo very well, but working on sites with a history usually comes up with something new. + +That site is bookmarked in many browsers, so preserving the URLs was a must. Hugo's URL handling is very flexible, but there was one challenge. The website has a mix of standard and what we in Hugo call _ugly URLs_ (`https://letsencrypt.org/2017/12/07/looking-forward-to-2018.html`). In Hugo this is handled automatically, and you can turn it on globally or per language. But before Hugo `0.33` you could not configure it for parts of your site. You could set it manually for the relevant pages in front matter -- which is how it was done in Jekyll -- but that would be hard to manage, especially when you start to introduce translations. So, in Hugo 0.33 I added support for _ugly URLs_ per section and also `url` set in front matter for list pages (`https://letsencrypt.org/blog/`). + +[^1]: The work on getting the content translated is in progress. diff --git a/docs/content/en/showcase/linode/bio.md b/docs/content/en/showcase/linode/bio.md new file mode 100644 index 000000000..52c7204c1 --- /dev/null +++ b/docs/content/en/showcase/linode/bio.md @@ -0,0 +1,3 @@ +**Linode** is a cloud hosting provider that offers high performance SSD Linux servers for your infrastructure needs. + +**Hugo** offers the documentation team incredible performance as we scale and continue providing quality Linux tutorials. diff --git a/docs/content/en/showcase/linode/featured.png b/docs/content/en/showcase/linode/featured.png Binary files differnew file mode 100644 index 000000000..8e517eacb --- /dev/null +++ b/docs/content/en/showcase/linode/featured.png diff --git a/docs/content/en/showcase/linode/index.md b/docs/content/en/showcase/linode/index.md new file mode 100644 index 000000000..f91c99d50 --- /dev/null +++ b/docs/content/en/showcase/linode/index.md @@ -0,0 +1,15 @@ +--- +title: Linode Docs +date: 2018-02-12 +description: 'Showcase: "Hugo allows us to build thousands of pages in seconds."' +siteURL: https://linode.com/docs/ +siteSource: https://github.com/linode/docs +--- + +The documentation team at Linode has been writing guides since 2009, with the goal of helping new and experienced Linux users find the best tools and get the most out of their systems. + +As our library grew into thousands of guides, we needed a fast static site generator with intuitive templating and the flexibility to extend Markdown without constantly writing HTML and CSS. + +Hugo solved a lot of our growing pains with features like shortcodes, customizable URLs, LiveReload, and more. We have already brought our site build time down from minutes to just a few seconds, and we are excited to see what future developments in Hugo will bring. + +Thank you to all the [Hugo contributors](https://github.com/gohugoio/hugo/graphs/contributors) and especially [@bep](https://github.com/bep) for helping us with the adoption of Hugo. diff --git a/docs/content/en/showcase/overmindstudios/bio.md b/docs/content/en/showcase/overmindstudios/bio.md new file mode 100644 index 000000000..080de69a0 --- /dev/null +++ b/docs/content/en/showcase/overmindstudios/bio.md @@ -0,0 +1,5 @@ +**Overmind Studios** is a visual effects studio headquartered in Southern Germany. + +The site is built by: + +- [Tobias Kummer](https://www.overmind-studios.de/about/) diff --git a/docs/content/en/showcase/overmindstudios/featured.png b/docs/content/en/showcase/overmindstudios/featured.png Binary files differnew file mode 100644 index 000000000..c3eaaaf4c --- /dev/null +++ b/docs/content/en/showcase/overmindstudios/featured.png diff --git a/docs/content/en/showcase/overmindstudios/index.md b/docs/content/en/showcase/overmindstudios/index.md new file mode 100644 index 000000000..00b09c5be --- /dev/null +++ b/docs/content/en/showcase/overmindstudios/index.md @@ -0,0 +1,14 @@ +--- +title: Overmind Studios +description: "A fresh start to make things easier in the future." +siteURL: https://www.overmind-studios.de/ +byline: "[tobkum](https://github.com/tobkum), Co-Founder Overmind Studios" +--- + +After many years of running our site on WordPress, we decided to switch to Hugo. + +WordPress is a great CMS for many people, but it has some downsides, especially for those who need a fast, secure, and customizable site. Plugins can become outdated, customization can be difficult, and bloat can slow down page loading times. + +Hugo is a static site generator that addresses many of these problems. It is fast to build and iterate, does not require PHP, is highly customizable, and is easy to learn and use. It is also secure, as it does not have a backend or MySQL database that can be hacked. + +We are very happy with our switch to Hugo. It is easy to update our site with new projects, and our Lighthouse score and loading times are both excellent. We now have more time to be creative instead of troubleshooting WordPress quirks and updates. diff --git a/docs/content/en/showcase/pharmaseal/bio.md b/docs/content/en/showcase/pharmaseal/bio.md new file mode 100644 index 000000000..7477f1c32 --- /dev/null +++ b/docs/content/en/showcase/pharmaseal/bio.md @@ -0,0 +1,7 @@ +PHARMASEAL began in 2016 with the purpose of disrupting the Clinical Trials Management market through continuous validation and integration + +We've been using **Hugo + Webpack + Netlify** to provide a scalable, modular design for the website, complete with Forestry building blocks to quickly be able to generate engagement pages. + +The site is built by: + +- [Roboto Studio](https://roboto.studio) diff --git a/docs/content/en/showcase/pharmaseal/featured-pharmaseal.png b/docs/content/en/showcase/pharmaseal/featured-pharmaseal.png Binary files differnew file mode 100644 index 000000000..4a64325b7 --- /dev/null +++ b/docs/content/en/showcase/pharmaseal/featured-pharmaseal.png diff --git a/docs/content/en/showcase/pharmaseal/index.md b/docs/content/en/showcase/pharmaseal/index.md new file mode 100644 index 000000000..3a8da2377 --- /dev/null +++ b/docs/content/en/showcase/pharmaseal/index.md @@ -0,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** + +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** + +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 --git a/docs/content/en/showcase/quiply-employee-communications-app/bio.md b/docs/content/en/showcase/quiply-employee-communications-app/bio.md new file mode 100644 index 000000000..f79677a1a --- /dev/null +++ b/docs/content/en/showcase/quiply-employee-communications-app/bio.md @@ -0,0 +1,4 @@ +**Quiply** is an employee communications app enabling mobile collaboration across an entire organization. +Our customers get their own branded app enabling them to communicate fast and effectively with all employees, also non-desk and shift workers. + +As the Quiply app's build process is based on **Gulp**, we have started to build our company and product website using **Gulp + Hugo** which is super-fast and gives us exactly the flexibility we need. diff --git a/docs/content/en/showcase/quiply-employee-communications-app/featured.png b/docs/content/en/showcase/quiply-employee-communications-app/featured.png Binary files differnew file mode 100644 index 000000000..a4e9f046e --- /dev/null +++ b/docs/content/en/showcase/quiply-employee-communications-app/featured.png diff --git a/docs/content/en/showcase/quiply-employee-communications-app/index.md b/docs/content/en/showcase/quiply-employee-communications-app/index.md new file mode 100644 index 000000000..2c8854a8d --- /dev/null +++ b/docs/content/en/showcase/quiply-employee-communications-app/index.md @@ -0,0 +1,15 @@ +--- +title: Quiply Employee Communications App +date: 2018-02-13 +description: '"It became immediately clear that we would use Hugo going forward as it compiles super-fast, is intuitive to use, and offers all the features we need."' +siteURL: https://www.quiply.com +byline: "[Sebastian Schirmer](mailto:sebastian.schirmer@quiply.com), Quiply Co-Founder" +--- + +With the launch of our Employee Communications app Quiply we created a very simple and static one-page website to showcase our product. + +As our customer base and demand for marketing and communication started to grow, we needed a solution to easily grow and extend the contents of our web presence. As we do not have the need to serve dynamic content, we decided to use a static site generator. Amongst a couple of others, we tried Hugo and it became immediately clear that we'd use Hugo going forward as it compiles super-fast, is intuitive to use and offers all the features we need. + +Our website which we launched a couple of weeks ago is still growing and new content is being added constantly. By using Hugo, this can be easily done by content authors writing Markdown files without always having to touch HTML or CSS code. It is available in German only for the time being, an English version is in the works. + +Huge thanks to everyone involved in making Hugo a success. diff --git a/docs/content/en/showcase/tomango/bio.md b/docs/content/en/showcase/tomango/bio.md new file mode 100644 index 000000000..c90e48163 --- /dev/null +++ b/docs/content/en/showcase/tomango/bio.md @@ -0,0 +1,5 @@ +We help ambitious businesses grow by getting more of the customers they want. + +Our new site runs quickly, anywhere in the world, regardless of internet connectivity. + +The site was built by [Tomango](https://www.tomango.co.uk) diff --git a/docs/content/en/showcase/tomango/featured.png b/docs/content/en/showcase/tomango/featured.png Binary files differnew file mode 100644 index 000000000..d4b037e0f --- /dev/null +++ b/docs/content/en/showcase/tomango/featured.png diff --git a/docs/content/en/showcase/tomango/index.md b/docs/content/en/showcase/tomango/index.md new file mode 100644 index 000000000..d07abf92a --- /dev/null +++ b/docs/content/en/showcase/tomango/index.md @@ -0,0 +1,22 @@ +--- +title: Tomango +date: 2018-05-04 +description: 'Showcase: "Tomango site relaunch: Building our JAMstack site"' +siteURL: https://www.tomango.co.uk +siteSource: https://github.com/trys/tomango-2018 +byline: "[Trys Mudford](https://www.trysmudford.com), Lead Developer, Tomango" +--- + +Hugo is our static site generator (SSG) of choice. It's **really quick**. After using it on a number of [client projects](/showcase/hartwell-insurance/), it became clear that our new site _had_ to be built with Hugo. + +The big benefit of an SSG is how it moves all the heavy lifting to the build time. + +For example in WordPress, all the category pages are created at runtime, generating a lot of database queries. In Hugo, the paginated category pages are created at build time - so all the computational complexity is done once, and doesn't impact the user at all. + +Similarly, instead of running a live, or even a heavily cached Instagram feed that checked for new photos on page load, we used IFTTT to flip the feature to work performantly. I've [written about it](https://www.trysmudford.com/blog/making-the-static-dynamic-instagram-importer/) in detail on my blog but in essence: IFTTT sends a webhook to a Netlify Cloud Function every time a photo is uploaded. The function scrapes the photo and commits it to our GitHub repo which triggers a Hugo build on Netlify, deploying the site immediately! + +Shortcodes allow copy editors to continue using WordPress-esque features, Markdown keeps our developers happy, and our users don't have any of the database overheads. It's win-win! + +--- + +This is an extract from our [technical launch post](https://www.tomango.co.uk/thinks/tomango-progressive-web-app/). diff --git a/docs/content/en/templates/404.md b/docs/content/en/templates/404.md new file mode 100644 index 000000000..1a1a3c146 --- /dev/null +++ b/docs/content/en/templates/404.md @@ -0,0 +1,49 @@ +--- +title: Custom 404 page +linkTitle: 404 templates +description: Create a template to render a 404 error page. +categories: [] +keywords: [] +weight: 190 +--- + +To render a 404 error page in the root of your site, create a 404 template in the root of the `layouts` directory. For example: + +```go-html-template {file="layouts/404.html"} +{{ define "main" }} + <h1>404 Not Found</h1> + <p>The page you requested cannot be found.</p> + <p> + <a href="{{ .Site.Home.RelPermalink }}"> + Return to the home page + </a> + </p> +{{ end }} +``` + +For multilingual sites, add the language key to the file name: + +```text +layouts/ +├── 404.de.html +├── 404.en.html +└── 404.fr.html +``` + +Your production server redirects the browser to the 404 page when a page is not found. Capabilities and configuration vary by host. + +Host|Capabilities and configuration +:--|:-- +Amazon CloudFront|See [details](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/GeneratingCustomErrorResponses.html). +Amazon S3|See [details](https://docs.aws.amazon.com/AmazonS3/latest/userguide/CustomErrorDocSupport.html). +Apache|See [details](https://httpd.apache.org/docs/2.4/custom-error.html). +Azure Static Web Apps|See [details](https://learn.microsoft.com/en-us/azure/static-web-apps/configuration#response-overrides). +Azure Storage|See [details](https://learn.microsoft.com/en-us/azure/storage/blobs/storage-blob-static-website#setting-up-a-static-website). +Caddy|See [details](https://caddyserver.com/docs/caddyfile/directives/handle_errors). +Cloudflare Pages|See [details](https://developers.cloudflare.com/pages/configuration/serving-pages/#not-found-behavior). +DigitalOcean App Platform|See [details](https://docs.digitalocean.com/products/app-platform/how-to/manage-static-sites/#configure-a-static-site). +Firebase|See [details](https://firebase.google.com/docs/hosting/full-config#404). +GitHub Pages|Redirection to is automatic and not configurable. +GitLab Pages|See [details](https://docs.gitlab.com/ee/user/project/pages/introduction.html#custom-error-codes-pages). +NGINX|See [details](https://nginx.org/en/docs/http/ngx_http_core_module.html#error_page). +Netlify|See [details](https://docs.netlify.com/routing/redirects/redirect-options/). diff --git a/docs/content/en/templates/_index.md b/docs/content/en/templates/_index.md new file mode 100644 index 000000000..ea293e8e1 --- /dev/null +++ b/docs/content/en/templates/_index.md @@ -0,0 +1,8 @@ +--- +title: Templates +description: Create templates to render your content, resources, and data. +categories: [] +keywords: [] +weight: 10 +aliases: [/templates/overview/,/templates/content] +--- diff --git a/docs/content/en/templates/base.md b/docs/content/en/templates/base.md new file mode 100644 index 000000000..bb6a25b1e --- /dev/null +++ b/docs/content/en/templates/base.md @@ -0,0 +1,90 @@ +--- +title: Base templates +description: The base and block construct allows you to define the outer shell of your master templates (i.e., the chrome of the page). +categories: [] +keywords: [] +weight: 40 +aliases: [/templates/blocks/,/templates/base-templates-and-blocks/] +--- + +The `block` keyword allows you to define the outer shell of your pages' one or more master template(s) and then fill in or override portions as necessary. + +{{< youtube QVOMCYitLEc >}} + +## Base template lookup order + +The base template lookup order closely follows that of the template it applies to (e.g. `_default/list.html`). + +See [Template Lookup Order](/templates/lookup-order/) for details and examples. + +## Define the base template + +The following defines a simple base template at `_default/baseof.html`. As a default template, it is the shell from which all your pages will be rendered unless you specify another `*baseof.html` closer to the beginning of the lookup order. + +```go-html-template {file="layouts/_default/baseof.html"} +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>{{ block "title" . }} + <!-- Blocks may include default content. --> + {{ .Site.Title }} + {{ end }}</title> + </head> + <body> + <!-- Code that all your templates share, like a header --> + {{ block "main" . }} + <!-- The part of the page that begins to differ between templates --> + {{ end }} + {{ block "footer" . }} + <!-- More shared code, perhaps a footer but that can be overridden if need be in --> + {{ end }} + </body> +</html> +``` + +## Override the base template + +The default list template will inherit all of the code defined above and can then implement its own `"main"` block from: + +```go-html-template {file="layouts/_default/list.html"} +{{ define "main" }} + <h1>Posts</h1> + {{ range .Pages }} + <article> + <h2>{{ .Title }}</h2> + {{ .Content }} + </article> + {{ end }} +{{ end }} +``` + +This replaces the contents of our (basically empty) `main` block with something useful for the list template. In this case, we didn't define a `title` block, so the contents from our base template remain unchanged in lists. + +> [!warning] +> Only [template comments] are allowed outside a block's `define` and `end` statements. Avoid placing any other text, including HTML comments, outside these boundaries. Doing so will cause rendering issues, potentially resulting in a blank page. See the example below. + +```go-html-template {file="layouts/_default/do-not-do-this.html"} +<div>This div element broke your template.</div> +{{ define "main" }} + <h2>{{ .Title }}</h2> + {{ .Content }} +{{ end }} +<!-- An HTML comment will break your template too. --> +``` + +The following shows how you can override both the `main` and `title` block areas from the base template with code unique to your default [single template]: + +```go-html-template {file="layouts/_default/single.html"} +{{ define "title" }} + <!-- This will override the default value set in baseof.html; i.e., "{{ .Site.Title }}" in the original example--> + {{ .Title }} – {{ .Site.Title }} +{{ end }} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} +{{ end }} +``` + +[single template]: /templates/types/#single +[template comments]: /templates/introduction/#comments diff --git a/docs/content/en/templates/content-view.md b/docs/content/en/templates/content-view.md new file mode 100644 index 000000000..f001e400e --- /dev/null +++ b/docs/content/en/templates/content-view.md @@ -0,0 +1,90 @@ +--- +title: Content view templates +description: Hugo can render alternative views of your content, useful in list and summary views. +categories: [] +keywords: [] +weight: 110 +aliases: [/templates/views/] +--- + +The following are common use cases for content views: + +- You want content of every type to be shown on the home page but only with limited [summary views][summaries]. +- You only want a bulleted list of your content in a [taxonomy template]. Views make this very straightforward by delegating the rendering of each different type of content to the content itself. + +## Create a content view + +To create a new view, create a template in each of your different content type directories with the view name. The following example contains an "li" view and a "summary" view for the `posts` and `project` content types. As you can see, these sit next to the [single template], `single.html`. You can even provide a specific view for a given type and continue to use the `_default/single.html` for the primary view. + +```txt +layouts/ +├── posts/ +│ ├── li.html +│ ├── single.html +│ └── summary.html +├── project/ +│ ├── li.html +│ └── single.html +└── summary.html +``` + +## Which template will be rendered? + +The following is the lookup order for content views ordered by specificity. + +1. `/layouts/<TYPE>/<VIEW>.html` +1. `/layouts/<SECTION>/<VIEW>.html` +1. `/layouts/_default/<VIEW>.html` +1. `/themes/<THEME>/layouts/<TYPE>/<VIEW>.html` +1. `/themes/<THEME>/layouts/<SECTION>/<VIEW>.html` +1. `/themes/<THEME>/layouts/_default/<VIEW>.html` + +## Example: content view inside a list + +### list.html + +In this example, `.Render` is passed into the template to call the [render function][render]. `.Render` is a special function that instructs content to render itself with the view template provided as the first argument. In this case, the template is going to render the `summary.html` view that follows: + +```go-html-template {file="layouts/_default/list.html"} +<main id="main"> + <div> + <h1 id="title">{{ .Title }}</h1> + {{ range .Pages }} + {{ .Render "summary" }} + {{ end }} + </div> +</main> +``` + +### summary.html + +Hugo passes the `Page` object to the following `summary.html` view template. + +```go-html-template {file="layouts/_default/summary.html"} +<article class="post"> + <header> + <h2><a href="{{ .RelPermalink }}">{{ .Title }}</a></h2> + <div class="post-meta">{{ .Date.Format "Mon, Jan 2, 2006" }} - {{ .FuzzyWordCount }} Words </div> + </header> + {{ .Summary }} + <footer> + <a href='{{ .RelPermalink }}'>Read more »</a> + </footer> +</article> +``` + +### li.html + +Continuing on the previous example, we can change our render function to use a smaller `li.html` view by changing the argument in the call to the `.Render` function (i.e., `{{ .Render "li" }}`). + +```go-html-template {file="layouts/_default/li.html"} +<li> + <a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a> + <div class="meta">{{ .Date.Format "Mon, Jan 2, 2006" }}</div> +</li> +``` + +[render]: /methods/page/render/ +[single template]: /templates/types/#single +[summaries]: /content-management/summaries/ +[taxonomy template]: /templates/types/#taxonomy diff --git a/docs/content/en/templates/embedded.md b/docs/content/en/templates/embedded.md new file mode 100644 index 000000000..198136393 --- /dev/null +++ b/docs/content/en/templates/embedded.md @@ -0,0 +1,218 @@ +--- +title: Embedded templates +description: Hugo provides embedded templates for common use cases. +categories: [] +keywords: [] +weight: 170 +aliases: [/templates/internal] +--- + +## Disqus + +> [!note] +> To override Hugo's embedded Disqus template, copy the [source code]({{% eturl disqus %}}) to a file with the same name in the `layouts/partials` directory, then call it from your templates using the [`partial`] function: +> +> `{{ partial "disqus.html" . }}` + +Hugo includes an embedded template for [Disqus], a popular commenting system for both static and dynamic websites. To effectively use Disqus, secure a Disqus "shortname" by [signing up] for the free service. + +To include the embedded template: + +```go-html-template +{{ template "_internal/disqus.html" . }} +``` + +### Configuration {#configuration-disqus} + +To use Hugo's Disqus template, first set up a single configuration value: + +{{< code-toggle file=hugo >}} +[services.disqus] +shortname = 'your-disqus-shortname' +{{</ code-toggle >}} + +Hugo's Disqus template accesses this value with: + +```go-html-template +{{ .Site.Config.Services.Disqus.Shortname }} +``` + +You can also set the following in the front matter for a given piece of content: + +- `disqus_identifier` +- `disqus_title` +- `disqus_url` + +### Privacy {#privacy-disqus} + +Adjust the relevant privacy settings in your site configuration. + +{{< code-toggle config=privacy.disqus />}} + +disable +: (`bool`) Whether to disable the template. Default is `false`. + +## Google Analytics + +> [!note] +> To override Hugo's embedded Google Analytics template, copy the [source code]({{% eturl google_analytics %}}) to a file with the same name in the `layouts/partials` directory, then call it from your templates using the [`partial`] function: +> +> `{{ partial "google_analytics.html" . }}` + +Hugo includes an embedded template supporting [Google Analytics 4]. + +To include the embedded template: + +```go-html-template +{{ template "_internal/google_analytics.html" . }} +``` + +### Configuration {#configuration-google-analytics} + +Provide your tracking ID in your configuration file: + +{{< code-toggle file=hugo >}} +[services.googleAnalytics] +id = "G-MEASUREMENT_ID" +{{</ code-toggle >}} + +To use this value in your own template, access the configured ID with `{{ site.Config.Services.GoogleAnalytics.ID }}`. + +### Privacy {#privacy-google-analytics} + +Adjust the relevant privacy settings in your site configuration. + +{{< code-toggle config=privacy.googleAnalytics />}} + +disable +: (`bool`) Whether to disable the template. Default is `false`. + +respectDoNotTrack +: (`bool`) Whether to respect the browser's "do not track" setting. Default is `false`. + +## Open Graph + +> [!note] +> To override Hugo's embedded Open Graph template, copy the [source code]({{% eturl opengraph %}}) to a file with the same name in the `layouts/partials` directory, then call it from your templates using the [`partial`] function: +> +> `{{ partial "opengraph.html" . }}` + +Hugo includes an embedded template for the [Open Graph protocol](https://ogp.me/), metadata that enables a page to become a rich object in a social graph. +This format is used for Facebook and some other sites. + +To include the embedded template: + +```go-html-template +{{ template "_internal/opengraph.html" . }} +``` + +### Configuration {#configuration-open-graph} + +Hugo's Open Graph template is configured using a mix of configuration settings and [front matter](/content-management/front-matter/) on individual pages. + +{{< code-toggle file=hugo >}} +[params] + description = 'Text about my cool site' + images = ['site-feature-image.jpg'] + title = 'My cool site' + [params.social] + facebook_admin = 'jsmith' +[taxonomies] + series = 'series' +{{</ code-toggle >}} + +{{< code-toggle file=content/blog/my-post.md fm=true >}} +title = "Post title" +description = "Text about this post" +date = 2024-03-08T08:18:11-08:00 +images = ["post-cover.png"] +audio = [] +videos = [] +series = [] +tags = [] +{{</ code-toggle >}} + +Hugo uses the page title and description for the title and description metadata. +The first 6 URLs from the `images` array are used for image metadata. +If [page bundles](/content-management/page-bundles/) are used and the `images` array is empty or undefined, images with file names matching `*feature*`, `*cover*`, or `*thumbnail*` are used for image metadata. + +Various optional metadata can also be set: + +- Date, published date, and last modified data are used to set the published time metadata if specified. +- `audio` and `videos` are URL arrays like `images` for the audio and video metadata tags, respectively. +- The first 6 `tags` on the page are used for the tags metadata. +- The `series` taxonomy is used to specify related "see also" pages by placing them in the same series. + +If using YouTube this will produce a og:video tag like `<meta property="og:video" content="url">`. Use the `https://youtu.be/<id>` format with YouTube videos (example: `https://youtu.be/qtIqKaDlqXo`). + +## Schema + +> [!note] +> To override Hugo's embedded Schema template, copy the [source code]({{% eturl schema %}}) to a file with the same name in the `layouts/partials` directory, then call it from your templates using the [`partial`] function: +> +> `{{ partial "schema.html" . }}` + +Hugo includes an embedded template to render [microdata] `meta` elements within the `head` element of your templates. + +To include the embedded template: + +```go-html-template +{{ template "_internal/schema.html" . }} +``` + +## X (Twitter) Cards + +> [!note] +> To override Hugo's embedded Twitter Cards template, copy the [source code]({{% eturl twitter_cards %}}) to a file with the same name in the `layouts/partials` directory, then call it from your templates using the [`partial`] function: +> +> `{{ partial "twitter_cards.html" . }}` + +Hugo includes an embedded template for [X (Twitter) Cards](https://developer.x.com/en/docs/twitter-for-websites/cards/overview/abouts-cards), +metadata used to attach rich media to Tweets linking to your site. + +To include the embedded template: + +```go-html-template +{{ template "_internal/twitter_cards.html" . }} +``` + +### Configuration {#configuration-x-cards} + +Hugo's X (Twitter) Card template is configured using a mix of configuration settings and [front-matter](/content-management/front-matter/) values on individual pages. + +{{< code-toggle file=hugo >}} +[params] + images = ["site-feature-image.jpg"] + description = "Text about my cool site" +{{</ code-toggle >}} + +{{< code-toggle file=content/blog/my-post.md fm=true >}} +title = "Post title" +description = "Text about this post" +images = ["post-cover.png"] +{{</ code-toggle >}} + +If [page bundles](/content-management/page-bundles/) are used and the `images` array is empty or undefined, images with file names matching `*feature*`, `*cover*`, or `*thumbnail*` are used for image metadata. +If no image resources with those names are found, the images defined in the [site config](/configuration/) are used instead. +If no images are found at all, then an image-less Twitter `summary` card is used instead of `summary_large_image`. + +Hugo uses the page title and description for the card's title and description fields. The page summary is used if no description is given. + +Set the value of `twitter:site` in your site configuration: + +{{< code-toggle file=hugo >}} +[params.social] +twitter = "GoHugoIO" +{{</ code-toggle >}} + +NOTE: The `@` will be added for you + +```html +<meta name="twitter:site" content="@GoHugoIO"/> +``` + +[`partial`]: /functions/partials/include/ +[Disqus]: https://disqus.com +[Google Analytics 4]: https://support.google.com/analytics/answer/10089681 +[microdata]: https://html.spec.whatwg.org/multipage/microdata.html#microdata +[signing up]: https://disqus.com/profile/signup/ diff --git a/docs/content/en/templates/home.md b/docs/content/en/templates/home.md new file mode 100644 index 000000000..937a4a5a8 --- /dev/null +++ b/docs/content/en/templates/home.md @@ -0,0 +1,58 @@ +--- +title: Home page templates +description: The home page of a website is often formatted differently than the other pages. For this reason, Hugo makes it easy for you to define your new site's home page as a unique template. +categories: [] +keywords: [] +weight: 50 +aliases: [/layout/homepage/,/templates/homepage-template/,/templates/homepage/] +--- + +## Introduction + +A home page template is used to render your site's home page, and is the only template required for a single-page website. For example, the home page template below inherits the site's shell from the base template and renders the home page content, such as a list of other pages. + +```go-html-template {file="layouts/_default/home.html"} +{{ define "main" }} + {{ .Content }} + {{ range site.RegularPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +``` + +{{% include "/_common/filter-sort-group.md" %}} + +## Lookup order + +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. + +## Content and front matter + +The home page template uses content and front matter from an `_index.md` file located in the root of your content directory. + +{{< code-toggle file=content/_index.md fm=true >}} +--- +title: The Home Page +date: 2025-01-30T03:36:57-08:00 +draft: false +params: + subtitle: The Subtitle +--- +{{< /code-toggle >}} + +The home page template below inherits the site's shell from the base template, renders the subtitle and content as defined in the `_index.md` file, then renders of list of the site's [regular pages](g). + +```go-html-template {file="layouts/_default/home.html"} +{{ define "main" }} + <h3>{{ .Params.Subtitle }}</h3> + {{ .Content }} + {{ range site.RegularPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +``` + +[template lookup order]: /templates/lookup-order/#home-templates diff --git a/docs/content/en/templates/introduction.md b/docs/content/en/templates/introduction.md new file mode 100644 index 000000000..8898ee456 --- /dev/null +++ b/docs/content/en/templates/introduction.md @@ -0,0 +1,535 @@ +--- +title: Introduction to templating +linkTitle: Introduction +description: An introduction to Hugo's templating syntax. +categories: [] +keywords: [] +weight: 10 +--- + +{{% 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 }} +<p>The product of {{ $v1 }} and {{ $v2 }} is {{ mul $v1 $v2 }}.</p> +``` + +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. + +### Current context + +Within a template, the dot (`.`) represents the current context. + +```go-html-template {file="layouts/_default/single.html"} +<h2>{{ .Title }}</h2> +``` + +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/_default/single.html"} +<h2>{{ .Title }}</h2> + +{{ range slice "foo" "bar" }} + <p>{{ . }}</p> +{{ end }} + +{{ with "baz" }} + <p>{{ . }}</p> +{{ 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 +<h2>My Page Title</h2> +<p>foo</p> +<p>bar</p> +<p>baz</p> +``` + +### 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/_default/single.html"} +{{ with "foo" }} + <p>{{ $.Title }} - {{ . }}</p> +{{ end }} +``` + +Hugo renders this to: + +```html +<p>My Page Title - foo</p> +``` + +> [!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/_default/single.html"} +{{ $convertToLower := true }} +{{ if $convertToLower }} + <h2>{{ strings.ToLower .Title }}</h2> +{{ 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 + + + <h2>my page title</h2> + +``` + +### 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/_default/single.html"} +{{- $convertToLower := true -}} +{{- if $convertToLower -}} + <h2>{{ strings.ToLower .Title }}</h2> +{{- end -}} +``` + +Hugo renders this to: + +```html +<h2>my page title</h2> +``` + +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/_default/single.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/_default/single.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/_default/single.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 +{{ "<!-- I am an HTML comment. -->" | safeHTML }} +{{ printf "<!-- This is the %s site. -->" .Site.Title | safeHTML }} +``` + +## Include + +Use the [`template`] function to include one or more of Hugo's [embedded templates]: + +```go-html-template +{{ template "_internal/google_analytics.html" . }} +{{ template "_internal/opengraph" . }} +{{ template "_internal/pagination.html" . }} +{{ template "_internal/schema.html" . }} +{{ template "_internal/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. + +> [!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 }} + <p>{{ . }}</p> +{{ else }} + <p>The collection is empty</p> +{{ end }} +``` + +Use the [`seq`] function to loop a specified number of times: + +```go-html-template +{{ $total := 0 }} +{{ range seq 4 }} + {{ $total = add $total . }} +{{ end }} +{{ $total }} → 10 +``` + +### 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 +[`seq`]: /functions/collections/seq +[`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/partial +[templates]: /templates/ +[text/template]: https://pkg.go.dev/text/template +[variables]: #variables diff --git a/docs/content/en/templates/lookup-order.md b/docs/content/en/templates/lookup-order.md new file mode 100644 index 000000000..518900797 --- /dev/null +++ b/docs/content/en/templates/lookup-order.md @@ -0,0 +1,150 @@ +--- +title: Template lookup order +linkTitle: Lookup order +description: Hugo uses the rules below to select a template for a given page, starting from the most specific. +categories: [] +keywords: [] +weight: 20 +--- + +## Lookup rules + +Hugo takes the parameters listed below into consideration when choosing a template for a given page. The templates are ordered by specificity. This should feel natural, but look at the table below for concrete examples of the different parameter variations. + +Kind +: The page `Kind` (the home page is one). See the example tables below per kind. This also determines if it is a **single page** (i.e. a regular content page. We then look for a template in `_default/single.html` for HTML) or a **list page** (section listings, home page, taxonomy lists, taxonomy terms. We then look for a template in `_default/list.html` for HTML). + +Layout +: Can be set in front matter. + +Output Format +: See [configure output formats](/configuration/output-formats/). An output format has both a `name` (e.g. `rss`, `amp`, `html`) and a `suffix` (e.g. `xml`, `html`). We prefer matches with both (e.g. `index.amp.html`), but look for less specific templates. + +Note that if the output format's Media Type has more than one suffix defined, only the first is considered. + +Language +: We will consider a language tag in the template name. If the site language is `fr`, `index.fr.amp.html` will win over `index.amp.html`, but `index.amp.html` will be chosen before `index.fr.html`. + +Type +: Is value of `type` if set in front matter, else it is the name of the root section (e.g. "blog"). It will always have a value, so if not set, the value is "page". + +Section +: Is relevant for `section`, `taxonomy` and `term` types. + +> [!note] +> Templates can live in either the project's or the themes' `layout` directories, and the most specific templates will be chosen. Hugo will interleave the lookups listed below, finding the most specific one either in the project or themes. + +## Target a template + +You cannot change the lookup order to target a content page, but you can change a content page to target a template. Specify `type`, `layout`, or both in front matter. + +Consider this content structure: + +```text +content/ +├── about.md +└── contact.md +``` + +Files in the root of the `content` directory have a [content type](g) of `page`. To render these pages with a unique template, create a matching subdirectory: + +```text +layouts/ +└── page/ + └── single.html +``` + +But the contact page probably has a form and requires a different template. In the front matter specify `layout`: + +{{< code-toggle file=content/contact.md fm=true >}} +title = 'Contact' +layout = 'contact' +{{< /code-toggle >}} + +Then create the template for the contact page: + +```text +layouts/ +└── page/ + └── contact.html <-- renders contact.md + └── single.html <-- renders about.md +``` + +As a content type, the word `page` is vague. Perhaps `miscellaneous` would be better. Add `type` to the front matter of each page: + +{{< code-toggle file=content/about.md fm=true >}} +title = 'About' +type = 'miscellaneous' +{{< /code-toggle >}} + +{{< code-toggle file=content/contact.md fm=true >}} +title = 'Contact' +type = 'miscellaneous' +layout = 'contact' +{{< /code-toggle >}} + +Now place the layouts in the corresponding directory: + +```text +layouts/ +└── miscellaneous/ + └── contact.html <-- renders contact.md + └── single.html <-- renders about.md +``` + +## Home templates + +These template paths are sorted by specificity in descending order. The least specific path is at the bottom of each list. + +{{< datatable-filtered "output" "layouts" "Kind == home" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} + +## Single templates + +These template paths are sorted by specificity in descending order. The least specific path is at the bottom of each list. + +{{< datatable-filtered "output" "layouts" "Kind == page" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} + +## Section templates + +These template paths are sorted by specificity in descending order. The least specific path is at the bottom of each list. + +{{< datatable-filtered "output" "layouts" "Kind == section" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} + +## Taxonomy templates + +These template paths are sorted by specificity in descending order. The least specific path is at the bottom of each list. + +The examples below assume the following site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +category = 'categories' +{{< /code-toggle >}} + +{{< datatable-filtered "output" "layouts" "Kind == taxonomy" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} + +## Term templates + +These template paths are sorted by specificity in descending order. The least specific path is at the bottom of each list. + +The examples below assume the following site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +category = 'categories' +{{< /code-toggle >}} + +{{< datatable-filtered "output" "layouts" "Kind == term" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} + +## RSS templates + +These template paths are sorted by specificity in descending order. The least specific path is at the bottom of each list. + +The examples below assume the following site configuration: + +{{< code-toggle file=hugo >}} +[taxonomies] +category = 'categories' +{{< /code-toggle >}} + +{{< datatable-filtered "output" "layouts" "OutputFormat == rss" "Example" "OutputFormat" "Suffix" "Template Lookup Order" >}} diff --git a/docs/content/en/templates/menu.md b/docs/content/en/templates/menu.md new file mode 100644 index 000000000..4ff423255 --- /dev/null +++ b/docs/content/en/templates/menu.md @@ -0,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. + +```go-html-template {file="layouts/partials/menu.html" copy=true} +{{- $page := .page }} +{{- $menuID := .menuID }} + +{{- with index site.Menus $menuID }} + <nav> + <ul> + {{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }} + </ul> + </nav> +{{- 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 }} + <li> + <a + {{- range $k, $v := $attrs }} + {{- with $v }} + {{- printf " %s=%q" $k $v | safeHTMLAttr }} + {{- end }} + {{- end -}} + >{{ $name }}</a> + {{- with .Children }} + <ul> + {{- partial "inline/menu/walk.html" (dict "page" $page "menuEntries" .) }} + </ul> + {{- end }} + </li> + {{- end }} +{{- end }} +``` + +Call the partial above, passing a menu ID and the current page in context. + +```go-html-template {file="layouts/_default/single.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/_default/single.html"} +{{- range site.Menus.main }} + <a href="{{ .URL }}"> + {{ .Name }} + {{- with .Page }} + {{- with .Params.version -}} + ({{ . }}) + {{- end }} + {{- end }} + </a> +{{- 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 }} + <a {{ with .Params.class -}} class="{{ . }}" {{ end -}} href="{{ .URL }}"> + {{ .Name }} + </a> +{{- 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 --git a/docs/content/en/templates/pagination.md b/docs/content/en/templates/pagination.md new file mode 100644 index 000000000..018ec9271 --- /dev/null +++ b/docs/content/en/templates/pagination.md @@ -0,0 +1,241 @@ +--- +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 }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ template "_internal/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 }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ template "_internal/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 }} + <h2>{{ .Key }}</h2> + {{ range .Pages }} + <h3><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h3> + {{ end }} +{{ end }} + +{{ template "_internal/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 +{{ template "_internal/pagination.html" . }} +``` + +The embedded pagination template has two formats: `default` and `terse`. The above is equivalent to: + +```go-html-template +{{ template "_internal/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 +{{ template "_internal/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: + +```go-html-template +{{ range (.Paginate .Pages).Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> +{{ end }} + +{{ template "_internal/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 --git a/docs/content/en/templates/partial.md b/docs/content/en/templates/partial.md new file mode 100644 index 000000000..8493a4674 --- /dev/null +++ b/docs/content/en/templates/partial.md @@ -0,0 +1,158 @@ +--- +title: Partial templates +description: Partials are smaller, context-aware components in your list and page templates that can be used economically to keep your templating DRY. +categories: [] +keywords: [] +weight: 100 +aliases: [/templates/partials/,/layout/chrome/] +--- + +{{< youtube pjS4pOLyB7c >}} + +## Use partials in your templates + +All partials for your Hugo project are located in a single `layouts/partials` directory. For better organization, you can create multiple subdirectories within `partials` as well: + +```txt +layouts/ +└── partials/ + ├── footer/ + │ ├── scripts.html + │ └── site-footer.html + ├── head/ + │ ├── favicons.html + │ ├── metadata.html + │ └── prerender.html + └── header/ + ├── site-header.html + └── site-nav.html +``` + +All partials are called within your templates using the following pattern: + +```go-html-template +{{ partial "<PATH>/<PARTIAL>.html" . }} +``` + +> [!note] +> One of the most common mistakes with new Hugo users is failing to pass a context to the partial call. In the pattern above, note how "the dot" (`.`) is required as the second argument to give the partial context. You can read more about "the dot" in the [Hugo templating introduction](/templates/introduction/#context). + +> [!note] +> Do not include the word "baseof" when naming partial templates. The word "baseof" is reserved for base templates. + +As shown in the above example directory structure, you can nest your directories within `partials` for better source organization. You only need to call the nested partial's path relative to the `partials` directory: + +```go-html-template +{{ partial "header/site-header.html" . }} +{{ partial "footer/scripts.html" . }} +``` + +### Variable scoping + +The second argument in a partial call is the variable being passed down. The above examples are passing the `.`, which tells the template receiving the partial to apply the current [context][context]. + +This means the partial will *only* be able to access those variables. The partial is isolated and cannot access the outer scope. From within the partial, `$.Var` is equivalent to `.Var`. + +## Returning a value from a partial + +In addition to outputting markup, partials can be used to return a value of any type. In order to return a value, a partial must include a lone `return` statement *at the end of the partial*. + +### Example GetFeatured + +```go-html-template +{{/* layouts/partials/GetFeatured.html */}} +{{ return first . (where site.RegularPages "Params.featured" true) }} +``` + +```go-html-template +{{/* layouts/index.html */}} +{{ range partial "GetFeatured.html" 5 }} + [...] +{{ end }} +``` + +### Example GetImage + +```go-html-template +{{/* layouts/partials/GetImage.html */}} +{{ $image := false }} +{{ with .Params.gallery }} + {{ $image = index . 0 }} +{{ end }} +{{ with .Params.image }} + {{ $image = . }} +{{ end }} +{{ return $image }} +``` + +```go-html-template +{{/* layouts/_default/single.html */}} +{{ with partial "GetImage.html" . }} + [...] +{{ end }} +``` + +> [!note] +> Only one `return` statement is allowed per partial file. + +## Inline partials + +You can also define partials inline in the template. But remember that template namespace is global, so you need to make sure that the names are unique to avoid conflicts. + +```go-html-template +Value: {{ partial "my-inline-partial.html" . }} + +{{ define "partials/my-inline-partial.html" }} +{{ $value := 32 }} +{{ return $value }} +{{ end }} +``` + +## Cached partials + +The `partialCached` template function provides significant performance gains for complex templates that don't need to be re-rendered on every invocation. See [details][partialcached]. + +## Examples + +### `header.html` + +The following `header.html` partial template is used for [spf13.com](https://spf13.com/): + +```go-html-template {file="layouts/partials/header.html"} +<!DOCTYPE html> +<html class="no-js" lang="en-US" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#"> +<head> + <meta charset="utf-8"> + + {{ partial "meta.html" . }} + + <base href="{{ .Site.BaseURL }}"> + <title> {{ .Title }} : spf13.com </title> + <link rel="canonical" href="{{ .Permalink }}"> + {{ if .RSSLink }}<link href="{{ .RSSLink }}" rel="alternate" type="application/rss+xml" title="{{ .Title }}" />{{ end }} + + {{ partial "head_includes.html" . }} +</head> +``` + +> [!note] +> The `header.html` example partial was built before the introduction of block templates to Hugo. Read more on [base templates and blocks](/templates/base/) for defining the outer chrome or shell of your master templates (i.e., your site's head, header, and footer). You can even combine blocks and partials for added flexibility. + +### `footer.html` + +The following `footer.html` partial template is used for [spf13.com](https://spf13.com/): + +```go-html-template {file="layouts/partials/footer.html"} +<footer> + <div> + <p> + © 2013-14 Steve Francia. + <a href="https://creativecommons.org/licenses/by/3.0/" title="Creative Commons Attribution">Some rights reserved</a>; + please attribute properly and link back. + </p> + </div> +</footer> +``` + +[context]: /templates/introduction/ +[partialcached]: /functions/partials/includecached/ diff --git a/docs/content/en/templates/robots.md b/docs/content/en/templates/robots.md new file mode 100644 index 000000000..2d412d775 --- /dev/null +++ b/docs/content/en/templates/robots.md @@ -0,0 +1,53 @@ +--- +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/<THEME>/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. + +[embedded template]: {{% eturl robots %}} +[site configuration]: /configuration/ +[static]: /getting-started/directory-structure/ diff --git a/docs/content/en/templates/rss.md b/docs/content/en/templates/rss.md new file mode 100644 index 000000000..f387a71e3 --- /dev/null +++ b/docs/content/en/templates/rss.md @@ -0,0 +1,79 @@ +--- +title: RSS templates +description: Use the embedded RSS template, or create your own. +categories: [] +keywords: [] +weight: 140 +--- + +## Configuration + +By default, when you build your site, Hugo generates RSS feeds for home, section, taxonomy, and term pages. Control feed generation in your site configuration. For example, to generate feeds for home and section pages, but not for taxonomy and term pages: + +{{< code-toggle file=hugo >}} +[outputs] +home = ['html', 'rss'] +section = ['html', 'rss'] +taxonomy = ['html'] +term = ['html'] +{{< /code-toggle >}} + +To disable feed generation for all [page kinds](g): + +{{< code-toggle file=hugo >}} +disableKinds = ['rss'] +{{< /code-toggle >}} + +By default, the number of items in each feed is unlimited. Change this as needed in your site configuration: + +{{< code-toggle file=hugo >}} +[services.rss] +limit = 42 +{{< /code-toggle >}} + +Set `limit` to `-1` to generate an unlimited number of items per feed. + +The built-in RSS template will render the following values, if present, from your site configuration: + +{{< code-toggle file=hugo >}} +copyright = '© 2023 ABC Widgets, Inc.' +[params.author] +name = 'John Doe' +email = 'jdoe@example.org' +{{< /code-toggle >}} + +## Include feed reference + +To include a feed reference in the `head` element of your rendered pages, place this within the `head` element of your templates: + +```go-html-template +{{ with .OutputFormats.Get "rss" }} + {{ printf `<link rel=%q type=%q href=%q title=%q>` .Rel .MediaType.Type .Permalink site.Title | safeHTML }} +{{ end }} +``` + +Hugo will render this to: + +```html +<link rel="alternate" type="application/rss+xml" href="https://example.org/index.xml" title="ABC Widgets"> +``` + +## Custom templates + +Override Hugo's [embedded RSS template] by creating one or more of your own, following the naming conventions as shown in the [template lookup order]. + +For example, to use different templates for home, section, taxonomy, and term pages: + +```text +layouts/ +└── _default/ + ├── home.rss.xml + ├── section.rss.xml + ├── taxonomy.rss.xml + └── term.rss.xml +``` + +RSS templates receive the `.Page` and `.Site` objects in context. + +[embedded RSS template]: {{% eturl rss %}} +[template lookup order]: /templates/lookup-order/#rss-templates diff --git a/docs/content/en/templates/section.md b/docs/content/en/templates/section.md new file mode 100644 index 000000000..8bc0f9dab --- /dev/null +++ b/docs/content/en/templates/section.md @@ -0,0 +1,81 @@ +--- +title: Section templates +description: Create a section template to list its members. +categories: [] +keywords: [] +weight: 70 +aliases: [/templates/sections/,/templates/section-templates/] +--- + +## Add content and front matter to section templates + +To effectively leverage section templates, you should first understand Hugo's [content organization](/content-management/organization/) and, specifically, the purpose of `_index.md` for adding content and front matter to section and other list pages. + +## Section template lookup order + +See [Template Lookup](/templates/lookup-order/). + +## Example: creating a default section template + +```go-html-template {file="layouts/_default/section.html"} +{{ define "main" }} + <main> + {{ .Content }} + + {{ $pages := where site.RegularPages "Type" "posts" }} + {{ $paginator := .Paginate $pages }} + + {{ range $paginator.Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} + + {{ template "_internal/pagination.html" . }} + </main> +{{ end }} +``` + +### Example: using `.Site.GetPage` + +The `.Site.GetPage` example that follows assumes the following project directory structure: + +```txt +. +└── content + ├── blog + │ ├── _index.md <-- title: My Hugo Blog + │ ├── post-1.md + │ ├── post-2.md + │ └── post-3.md + └── events + ├── event-1.md + └── event-2.md +``` + +`.Site.GetPage` will return `nil` if no `_index.md` page is found. Therefore, if `content/blog/_index.md` does not exist, the template will output the section name: + +```go-html-template +<h1>{{ with .Site.GetPage "/blog" }}{{ .Title }}{{ end }}</h1> +``` + +Since `blog` has a section index page with front matter at `content/blog/_index.md`, the above code will return the following result: + +```html +<h1>My Hugo Blog</h1> +``` + +If we try the same code with the `events` section, however, Hugo will default to the section title because there is no `content/events/_index.md` from which to pull content and front matter: + +```go-html-template +<h1>{{ with .Site.GetPage "/events" }}{{ .Title }}{{ end }}</h1> +``` + +Which then returns the following: + +```html +<h1>Events</h1> +``` + +[contentorg]: /content-management/organization/ +[lookup]: /templates/lookup-order/ +[`where`]: /functions/collections/where/ +[sections]: /content-management/sections/ diff --git a/docs/content/en/templates/shortcode.md b/docs/content/en/templates/shortcode.md new file mode 100644 index 000000000..711d342cb --- /dev/null +++ b/docs/content/en/templates/shortcode.md @@ -0,0 +1,338 @@ +--- +title: Shortcode templates +description: Create custom shortcodes to simplify and standardize content creation. +categories: [] +keywords: [] +weight: 120 +aliases: [/templates/shortcode-templates/] +--- + +> [!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. + +```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 +{{</* media/audio path=/audio/podcast/episode-42.mp3 */>}} +``` + +## 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. + +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. + +{{% 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 {{</* year */>}}, 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")) -}} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="{{ $.Get "alt" }}"> + {{- end }} +{{- end -}} +``` + +Then call the shortcode from within your markup: + +```text {file="content/example/index.md"} +{{</* image path=a.jpg width=300 alt="A white kitten" */>}} +``` + +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") "" -}} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" 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"} +{{</* image path=a.jpg width=300 alt="A white kitten" */>}} +``` + +Here's how to call it with positional arguments: + +```text {file="content/example/index.md"} +{{</* image a.jpg 300 "A white kitten" */>}} +``` + +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"} +{{</* image path=a.jpg width=300 alt="A white kitten" */>}} +``` + +```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"} +{{</* image a.jpg 300 "A white kitten" */>}} +``` + +```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"} +{{</* contrived title="A Contrived Example" */>}} +This is a **bold** word, and this is an _emphasized_ word. +{{</* /contrived */>}} +``` + +```go-html-template {file="layouts/shortcodes/contrived.html"} +<div class="contrived"> + <h2>{{ .Get "title" }}</h2> + {{ .Inner | .Page.RenderString }} +</div> +``` + +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"} +<div class="{{ .Get "class" }}"> + {{ .Inner }} +</div> +``` + +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 }} + <img src="{{ $src }}" class="{{ .Get "class" }}-image"> +{{ else }} + <img src="{{ $src }}"> +{{ end }} +``` + +You can then call your shortcode in your content as follows: + +```text {file="content/example.md"} +{{</* gallery class="content-gallery" */>}} + {{</* img src="/images/one.jpg" */>}} + {{</* img src="/images/two.jpg" */>}} +{{</* /gallery */>}} +{{</* img src="/images/three.jpg" */>}} +``` + +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 +<div class="content-gallery"> + <img src="/images/one.jpg" class="content-gallery-image"> + <img src="/images/two.jpg" class="content-gallery-image"> +</div> +<img src="/images/three.jpg"> +``` + +### 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"} +{{</* audio src=/audio/test.mp3 */>}} +``` + +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/_default/baseof.html"} +<head> + ... + {{ if .HasShortcode "audio" }} + <link rel="stylesheet" src="/css/audio.css"> + {{ end }} + ... +</head> +``` + +[`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 --git a/docs/content/en/templates/single.md b/docs/content/en/templates/single.md new file mode 100644 index 000000000..6f244ef10 --- /dev/null +++ b/docs/content/en/templates/single.md @@ -0,0 +1,51 @@ +--- +title: Single templates +description: Create a single template to render a single page. +categories: [] +keywords: [] +weight: 60 +aliases: [/layout/content/,/templates/single-page-templates/] +--- + +The single template below inherits the site's shell from the [base template]. + +[base template]: /templates/types/ + +```go-html-template {file="layouts/_default/single.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} +{{ end }} +``` + +Review the [template lookup order] to select a template path that provides the desired level of specificity. + +[template lookup order]: /templates/lookup-order/#single-templates + +The single template below inherits the site's shell from the base template, and renders the page title, creation date, content, and a list of associated terms in the "tags" taxonomy. + +```go-html-template {file="layouts/_default/single.html"} +{{ define "main" }} + <section> + <h1>{{ .Title }}</h1> + {{ with .Date }} + {{ $dateMachine := . | time.Format "2006-01-02T15:04:05-07:00" }} + {{ $dateHuman := . | time.Format ":date_long" }} + <time datetime="{{ $dateMachine }}">{{ $dateHuman }}</time> + {{ end }} + <article> + {{ .Content }} + </article> + <aside> + {{ with .GetTerms "tags" }} + <div>{{ (index . 0).Parent.LinkTitle }}</div> + <ul> + {{ range . }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> + {{ end }} + </aside> + </section> +{{ end }} +``` diff --git a/docs/content/en/templates/sitemap.md b/docs/content/en/templates/sitemap.md new file mode 100644 index 000000000..bf0850eef --- /dev/null +++ b/docs/content/en/templates/sitemap.md @@ -0,0 +1,62 @@ +--- +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 +{{</ code-toggle >}} + +## Override built-in templates + +To override the built-in sitemap.xml template, create a new file in either of these locations: + +- `layouts/sitemap.xml` +- `layouts/_default/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/_default/sitemapindex.xml` + +## Disable sitemap generation + +You may disable sitemap generation in your site configuration: + +{{< code-toggle file=hugo >}} +disableKinds = ['sitemap'] +{{</ code-toggle >}} + +[`publishDir`]: /configuration/all/#publishdir +[embedded sitemap template]: {{% eturl sitemap %}} +[embedded sitemapindex template]: {{% eturl sitemapindex %}} +[sitemap protocol]: https://www.sitemaps.org/protocol.html diff --git a/docs/content/en/templates/taxonomy.md b/docs/content/en/templates/taxonomy.md new file mode 100644 index 000000000..96c93ec95 --- /dev/null +++ b/docs/content/en/templates/taxonomy.md @@ -0,0 +1,164 @@ +--- +title: Taxonomy templates +description: Create a taxonomy template to render a list of terms. +categories: [] +keywords: [] +weight: 80 +aliases: [/taxonomies/displaying/,/templates/terms/,/indexes/displaying/,/taxonomies/templates/,/indexes/ordering/, /templates/taxonomies/, /templates/taxonomy-templates/] +--- + +The [taxonomy](g) template below inherits the site's shell from the [base template], and renders a list of [terms](g) in the current taxonomy. + +[base template]: /templates/types/ + +```go-html-template {file="layouts/_default/taxonomy.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +``` + +Review the [template lookup order] to select a template path that provides the desired level of specificity. + +[template lookup order]: /templates/lookup-order/#taxonomy-templates + +In the example above, the taxonomy and term will be capitalized if their respective pages are not backed by files. You can disable this in your site configuration: + +{{< code-toggle file=hugo >}} +capitalizeListTitles = false +{{< /code-toggle >}} + +## Data object + +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 }} → tag +``` + +Plural +: (`string`) Returns the plural name of the taxonomy. + +```go-html-template +{{ .Data.Plural }} → tags +``` + +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 }} +``` + +Once we have the `Taxonomy` object, we can call any of its [methods], allowing us to sort alphabetically or by term count. + +[methods]: /methods/taxonomy/ + +## Sort alphabetically + +The taxonomy template below inherits the site's shell from the base template, and renders a list of terms in the current taxonomy. Hugo sorts the list alphabetically by term, and displays the number of pages associated with each term. + +```go-html-template {file="layouts/_default/taxonomy.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Data.Terms.Alphabetical }} + <h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> ({{ .Count }})</h2> + {{ end }} +{{ end }} +``` + +## Sort by term count + +The taxonomy template below inherits the site's shell from the base template, and renders a list of terms in the current taxonomy. Hugo sorts the list by the number of pages associated with each term, and displays the number of pages associated with each term. + +```go-html-template {file="layouts/_default/taxonomy.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Data.Terms.ByCount }} + <h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> ({{ .Count }})</h2> + {{ end }} +{{ end }} +``` + +## Include content links + +The [`Alphabetical`] and [`ByCount`] methods used in the previous examples return an [ordered taxonomy](g), so we can also list the content to which each term is assigned. + +[`Alphabetical`]: /methods/taxonomy/alphabetical/ +[`ByCount`]: /methods/taxonomy/bycount/ + +The taxonomy template below inherits the site's shell from the base template, and renders a list of terms in the current taxonomy. Hugo sorts the list by the number of pages associated with each term, displays the number of pages associated with each term, then lists the content to which each term is assigned. + +```go-html-template {file="layouts/_default/taxonomy.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Data.Terms.ByCount }} + <h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a> ({{ .Count }})</h2> + <ul> + {{ range .WeightedPages }} + <li><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></li> + {{ end }} + </ul> + {{ end }} +{{ end }} +``` + +## Display 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: + +```go-html-template {file="layouts/authors/taxonomy.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Data.Terms.Alphabetical }} + <h2><a href="{{ .Page.RelPermalink }}">{{ .Page.LinkTitle }}</a></h2> + <p>Affiliation: {{ .Page.Params.Affiliation }}</p> + {{ with .Page.Resources.Get "portrait.jpg" }} + {{ with .Fill "100x100" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="portrait"> + {{ end }} + {{ end }} + {{ end }} +{{ end }} +``` + +In the example above we list each author including their affiliation and portrait. diff --git a/docs/content/en/templates/term.md b/docs/content/en/templates/term.md new file mode 100644 index 000000000..cf1097e86 --- /dev/null +++ b/docs/content/en/templates/term.md @@ -0,0 +1,107 @@ +--- +title: Term templates +description: Create a term template to render a list of pages associated with the current term. +categories: [] +keywords: [] +weight: 90 +--- + +The [term](g) template below inherits the site's shell from the [base template], and renders a list of pages associated with the current term. + +[base template]: /templates/types/ + +```go-html-template {file="layouts/_default/term.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +``` + +Review the [template lookup order] to select a template path that provides the desired level of specificity. + +[template lookup order]: /templates/lookup-order/#taxonomy-templates + +In the example above, the term will be capitalized if its respective page is not backed by a file. You can disable this in your site configuration: + +{{< code-toggle file=hugo >}} +capitalizeListTitles = false +{{< /code-toggle >}} + +## Data object + +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 }} → tag +``` + +Plural +: (`string`) Returns the plural name of the taxonomy. + +```go-html-template +{{ .Data.Plural }} → tags +``` + +Term +: (`string`) Returns the name of the term. + +```go-html-template +{{ .Data.Term }} → fiction +``` + +## Display 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 term template specific to the "authors" taxonomy: + +```go-html-template {file="layouts/authors/term.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + <p>Affiliation: {{ .Params.affiliation }}</p> + {{ with .Resources.Get "portrait.jpg" }} + {{ with .Fill "100x100" }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="portrait"> + {{ end }} + {{ end }} + {{ .Content }} + {{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +``` + +In the example above we display the author with their affiliation and portrait, then a list of associated content. diff --git a/docs/content/en/templates/types.md b/docs/content/en/templates/types.md new file mode 100644 index 000000000..b44d3eb47 --- /dev/null +++ b/docs/content/en/templates/types.md @@ -0,0 +1,261 @@ +--- +title: Template types +description: Create templates of different types to render your content, resources, and data. +categories: [] +keywords: [] +weight: 30 +aliases: ['/templates/lists/'] +--- + +## 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/ +├── _default/ +│ ├── _markup/ +│ │ ├── render-image.html <-- render hook +│ │ └── render-link.html <-- render hook +│ ├── baseof.html +│ ├── home.html +│ ├── section.html +│ ├── single.html +│ ├── taxonomy.html +│ └── term.html +├── articles/ +│ └── card.html <-- content view +├── partials/ +│ ├── footer.html +│ └── header.html +└── shortcodes/ + ├── audio.html + └── video.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 + +Base templates reduce duplicate code by wrapping other templates within a shell. + +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 uses the [block] function to include `home`, `single`, `section`, `taxonomy`, and `term` templates within the `main` element of each page. + +```go-html-template {file="layouts/_default/baseof.html"} +<!DOCTYPE html> +<html lang="{{ or site.Language.LanguageCode }}" dir="{{ or site.Language.LanguageDirection `ltr` }}"> +<head> + {{ partial "head.html" . }} +</head> +<body> + <header> + {{ partial "header.html" . }} + </header> + <main> + {{ block "main" . }}{{ end }} + </main> + <footer> + {{ partial "footer.html" . }} + </footer> +</body> +</html> +``` + +Learn more about [base templates](/templates/base/). + +## Home + +A home page template is used to render your site's home page, and is the only template required for a single-page website. For example, the home page template below inherits the site's shell from the base template and renders the home page content, such as a list of other pages. + +```go-html-template {file="layouts/_default/home.html"} +{{ define "main" }} + {{ .Content }} + {{ range site.RegularPages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +``` + +{{% include "/_common/filter-sort-group.md" %}} + +Learn more about [home page templates](/templates/home/). + +## Single + +A single template renders a single page. + +For example, the single template below inherits the site's shell from the base template, and renders the title and content of each page. + +```go-html-template {file="layouts/_default/single.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} +{{ end }} +``` + +Learn more about [single templates](/templates/single/). + +## Section + +A section template typically renders a list of pages within a section. + +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. + +```go-html-template {file="layouts/_default/section.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +``` + +{{% include "/_common/filter-sort-group.md" %}} + +Learn more about [section templates](/templates/section/). + +## Taxonomy + +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. + +```go-html-template {file="layouts/_default/taxonomy.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +``` + +{{% include "/_common/filter-sort-group.md" %}} + +Learn more about [taxonomy templates](/templates/taxonomy/). + +## Term + +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. + +```go-html-template {file="layouts/_default/term.html"} +{{ define "main" }} + <h1>{{ .Title }}</h1> + {{ .Content }} + {{ range .Pages }} + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ end }} +{{ end }} +``` + +{{% include "/_common/filter-sort-group.md" %}} + +Learn more about [term templates](/templates/term/). + +## Partial + +A partial template is typically used to render a component of your site, though you may also create partial templates that return values. + +> [!note] +> Unlike other template types, you cannot create partial templates to target a particular page kind, content type, section, language, or output format. Partial templates do not follow Hugo's [template lookup order]. + +For example, the partial template below renders copyright information. + +```go-html-template {file="layouts/partials/footer.html"} +<p>Copyright {{ now.Year }}. All rights reserved.</p> +``` + +Learn more about [partial templates](/templates/partial/). + +## 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: + +- Automatically inherit the context of the current page +- Follow a lookup order allowing you to target a given content type or section + +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 "articles" section of your site. + +```go-html-template {file="layouts/_default/home.html"} +{{ define "main" }} + {{ .Content }} + <ul> + {{ range where site.RegularPages "Section" "articles" }} + {{ .Render "card" }} + {{ end }} + </ul> +{{ end }} +``` + +```go-html-template {file="layouts/articles/card.html"} +<div class="card"> + <h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2> + {{ .Summary }} +</div> +``` + +Learn more about [content view templates](/templates/content-view/). + +## Render hook + +A render hook template overrides the conversion of Markdown to HTML. + +For example, the render hook template below adds a `rel` attribute to external links. + +```go-html-template {file="layouts/_default/_markup/render-link.html"} +{{- $u := urls.Parse .Destination -}} +<a href="{{ .Destination | safeURL }}" + {{- with .Title }} title="{{ . }}"{{ end -}} + {{- if $u.IsAbs }} rel="external"{{ end -}} +> + {{- with .Text }}{{ . }}{{ end -}} +</a> +{{- /* chomp trailing newline */ -}} +``` + +Learn more about [render hook templates](/render-hooks/). + +## Shortcode + +A shortcode template is used to render a component of your site. Unlike partial templates, shortcode templates are called from content pages. + +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") }} + <audio controls preload="auto" src="{{ .RelPermalink }}"></audio> +{{ end }} +``` + +Then call the shortcode from within markup: + +```text {file="content/example.md"} +{{</* audio src=/audio/test.mp3 */>}} +``` + +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/) + +[`Render`]: /methods/page/render/ +[block]: /functions/go-template/block/ +[partial]: /functions/partials/include/ +[template lookup order]: /templates/lookup-order/ +[template lookup order]: /templates/lookup-order/ diff --git a/docs/content/en/tools/_index.md b/docs/content/en/tools/_index.md new file mode 100644 index 000000000..3acc287ae --- /dev/null +++ b/docs/content/en/tools/_index.md @@ -0,0 +1,7 @@ +--- +title: Developer tools +description: Third-party tools to help you create and manage sites. +categories: [] +keywords: [] +weight: 10 +--- diff --git a/docs/content/en/tools/editors.md b/docs/content/en/tools/editors.md new file mode 100644 index 000000000..c375fcba8 --- /dev/null +++ b/docs/content/en/tools/editors.md @@ -0,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 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 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). + +[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. + +## 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 --git a/docs/content/en/tools/front-ends.md b/docs/content/en/tools/front-ends.md new file mode 100644 index 000000000..0c52a4687 --- /dev/null +++ b/docs/content/en/tools/front-ends.md @@ -0,0 +1,31 @@ +--- +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. + +## 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 --git a/docs/content/en/tools/migrations.md b/docs/content/en/tools/migrations.md new file mode 100644 index 000000000..103e28b9e --- /dev/null +++ b/docs/content/en/tools/migrations.md @@ -0,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. + +## 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 --git a/docs/content/en/tools/other.md b/docs/content/en/tools/other.md new file mode 100644 index 000000000..489d78506 --- /dev/null +++ b/docs/content/en/tools/other.md @@ -0,0 +1,20 @@ +--- +title: Other community projects +linkTitle: Other projects +description: Some interesting projects developed by the Hugo community that don't quite fit into our other developer tool categories. +categories: [] +keywords: [] +weight: 50 +--- + +And for all the other community projects around Hugo: + +- [diego](https://github.com/ttybitnik/diego) - A CLI tool that integrates with Hugo to assist in importing and utilizing exported social media data from popular services on Hugo websites. +- [Emacs Easy Hugo](https://github.com/masasam/emacs-easy-hugo) - Emacs package for writing blog posts in Markdown or org-mode and building your site with Hugo. +- [Hugo SFTP Upload](https://github.com/thomasmey/HugoSftpUpload) - Sync the local build of your Hugo website with your remote web server via SFTP. +- [HugoPhotoSwipe](https://github.com/GjjvdBurg/HugoPhotoSwipe) - Make it easy to create image galleries using PhotoSwipe. +- [JAMStack Themes](https://jamstackthemes.dev/ssg/hugo/) - A collection of site themes filterable by static site generator and supported CMS to help build CMS-connected sites using Hugo (linking to Hugo-specific themes). +- [flickr-hugo-embed](https://github.com/nikhilm/flickr-hugo-embed) - Print shortcodes to embed a set of images from an album on Flickr into Hugo. +- [hugo-gallery](https://github.com/icecreammatt/hugo-gallery) - Create an image gallery for Hugo sites. +- [hugo-openapispec-shortcode](https://github.com/tenfourty/hugo-openapispec-shortcode) - A shortcode that allows you to include [Open API Spec](https://openapis.org) (formerly known as Swagger Spec) in a page. +- [plausible-hugo](https://github.com/divinerites/plausible-hugo) - Easy Hugo integration for Plausible Analytics, a simple, open-source, lightweight and privacy-friendly web analytics alternative to Google Analytics. diff --git a/docs/content/en/tools/search.md b/docs/content/en/tools/search.md new file mode 100644 index 000000000..2c392c75a --- /dev/null +++ b/docs/content/en/tools/search.md @@ -0,0 +1,53 @@ +--- +title: Search tools +linkTitle: Search +description: See some of the open-source and commercial search options for your newly created Hugo website. +categories: [] +keywords: [] +weight: 30 +--- + +A static website with a dynamic search function? Yes, Hugo provides an alternative to embeddable scripts from Google or other search engines for static websites. Hugo allows you to provide your visitors with a custom search function by indexing your content files directly. + +## Open-source + +[Pagefind](https://github.com/cloudcannon/pagefind) +: A fully static search library that aims to perform well on large sites, while using as little of your users' bandwidth as possible. + +[GitHub Gist for Hugo Workflow](https://gist.github.com/sebz/efddfc8fdcb6b480f567) +: This gist contains a simple workflow to create a search index for your static website. It uses a simple Grunt script to index all your content files and [lunr.js](https://lunrjs.com/) to serve the search results. + +[hugo-lunr](https://www.npmjs.com/package/hugo-lunr) +: A simple way to add site search to your static Hugo site using [lunr.js](https://lunrjs.com/). Hugo-lunr will create an index file of any HTML and Markdown documents in your Hugo project. + +[hugo-lunr-zh](https://www.npmjs.com/package/hugo-lunr-zh) +: A bit like Hugo-lunr, but Hugo-lunr-zh can help you separate the Chinese keywords. + +[GitHub Gist for Fuse.js integration](https://gist.github.com/eddiewebb/735feb48f50f0ddd65ae5606a1cb41ae) +: This gist demonstrates how to leverage Hugo's existing build time processing to generate a searchable JSON index used by [Fuse.js](https://fusejs.io/) on the client side. Although this gist uses Fuse.js for fuzzy matching, any client-side search tool capable of reading JSON indexes will work. Does not require npm, grunt, or other build-time tools except Hugo! + +[hugo-search-index](https://www.npmjs.com/package/hugo-search-index) +: A library containing Gulp tasks and a prebuilt browser script that implements search. Gulp generates a search index from project Markdown files. + +[hugofastsearch](https://gist.github.com/cmod/5410eae147e4318164258742dd053993) +: A usability and speed update to "GitHub Gist for Fuse.js integration" — global, keyboard-optimized search. + +[JS & Fuse.js tutorial](https://makewithhugo.com/add-search-to-a-hugo-site/) +: A simple client-side search solution, using FuseJS (does not require jQuery). + +[Hugo Lyra](https://github.com/paolomainardi/hugo-lyra) +: Hugo-Lyra is a JavaScript module to integrate [Lyra](https://github.com/LyraSearch/lyra) into a Hugo website. It contains the server-side part to generate the index and the client-side library (optional) to bootstrap the search engine easily. + +[INFINI Pizza for WebAssembly](https://github.com/infinilabs/pizza-docsearch) +: Pizza is a super-lightweight yet fully featured search engine written in Rust. You can quickly add offline search functionality to your Hugo website in just five minutes with only three lines of code. For a step-by-step guide on integrating it with Hugo, check out [this blog tutorial](https://dev.to/medcl/adding-search-functionality-to-a-hugo-static-site-based-on-infini-pizza-for-webassembly-4h5e). + +## Commercial + +[Algolia DocSearch](https://docsearch.algolia.com/) +: Algolia DocSearch is free for public technical documentation sites and easy to set up. For other use cases, [Algolia's Search API](https://www.algolia.com) makes it easy to deliver a great search experience in your apps and websites. Algolia Search provides hosted full-text, numerical, faceted, and geolocalized search. + +[Bonsai](https://www.bonsai.io) +: Bonsai is a fully-managed hosted Elasticsearch service that is fast, reliable, and simple to set up. Easily ingest your docs from Hugo into Elasticsearch following [this guide from the docs](https://bonsai.io/docs/hugo). + +[ExpertRec](https://www.expertrec.com/) +: ExpertRec is a hosted search-as-a-service solution that is fast and scalable. Set-up and integration is extremely easy and takes only a few minutes. The search settings can be modified without coding using a dashboard. diff --git a/docs/content/en/troubleshooting/_index.md b/docs/content/en/troubleshooting/_index.md new file mode 100644 index 000000000..fd51b4fc8 --- /dev/null +++ b/docs/content/en/troubleshooting/_index.md @@ -0,0 +1,8 @@ +--- +title: Troubleshooting +description: Use these techniques when troubleshooting your site. +categories: [] +keywords: [] +weight: 10 +aliases: [/templates/template-debugging/] +--- diff --git a/docs/content/en/troubleshooting/audit/index.md b/docs/content/en/troubleshooting/audit/index.md new file mode 100644 index 000000000..2efad55e3 --- /dev/null +++ b/docs/content/en/troubleshooting/audit/index.md @@ -0,0 +1,68 @@ +--- +title: Site audit +linkTitle: Audit +description: Run this audit before deploying your production site. +categories: [] +keywords: [] +--- + +There are several conditions that can produce errors in your published site which are not detected during the build. Run this audit before your final build. + +```text {copy=true} +HUGO_MINIFY_TDEWOLFF_HTML_KEEPCOMMENTS=true HUGO_ENABLEMISSINGTRANSLATIONPLACEHOLDERS=true hugo && grep -inorE "<\!-- raw HTML omitted -->|ZgotmplZ|\[i18n\]|\(<nil>\)|(<nil>)|hahahugo" public/ +``` + +_Tested with GNU Bash 5.1 and GNU grep 3.7._ + +## Example output + + + +## Explanation + +### Environment variables + +`HUGO_MINIFY_TDEWOLFF_HTML_KEEPCOMMENTS=true` +: Retain HTML comments even if minification is enabled. This takes precedence over `minify.tdewolff.html.keepComments` in the site configuration. If you minify without keeping HTML comments when performing this audit, you will not be able to detect when raw HTML has been omitted. + +`HUGO_ENABLEMISSINGTRANSLATIONPLACEHOLDERS=true` +: Show a placeholder instead of the default value or an empty string if a translation is missing. This takes precedence over `enableMissingTranslationPlaceholders` in the site configuration. + +### Grep options + +`-i, --ignore-case` +: Ignore case distinctions in patterns and input data, so that characters that differ only in case match each other. + +`-n, --line-number` +: Prefix each line of output with the 1-based line number within its input file. + +`-o, --only-matching` +: Print only the matched (non-empty) parts of a matching line, with each such part on a separate output line. + +`-r, --recursive` +: Read all files under each directory, recursively, following symbolic links only if they are on the command line. + +`-E, --extended-regexp` +: Interpret PATTERNS as extended regular expressions. + +### Patterns + +`<!-- raw HTML omitted -->` +: By default, Hugo strips raw HTML from your Markdown prior to rendering, and leaves this HTML comment in its place. + +`ZgotmplZ` +: ZgotmplZ is a special value that indicates that unsafe content reached a CSS or URL context at runtime. See [details]. + +[details]: https://pkg.go.dev/html/template + +`[i18n]` +: This is the placeholder produced instead of the default value or an empty string if a translation is missing. + +`(<nil>)` +: This string will appear in the rendered HTML when passing a nil value to the `printf` function. + +`(<nil>)` +: Same as above when the value returned from the `printf` function has not been passed through `safeHTML`. + +`HAHAHUGO` +: Under certain conditions a rendered shortcode may include all or a portion of the string HAHAHUGOSHORTCODE in either uppercase or lowercase. This is difficult to detect in all circumstances, but a case-insensitive search of the output for `HAHAHUGO` is likely to catch the majority of cases without producing false positives. diff --git a/docs/content/en/troubleshooting/audit/screen-capture.png b/docs/content/en/troubleshooting/audit/screen-capture.png Binary files differnew file mode 100644 index 000000000..221abfff0 --- /dev/null +++ b/docs/content/en/troubleshooting/audit/screen-capture.png diff --git a/docs/content/en/troubleshooting/deprecation.md b/docs/content/en/troubleshooting/deprecation.md new file mode 100644 index 000000000..f2e5259a6 --- /dev/null +++ b/docs/content/en/troubleshooting/deprecation.md @@ -0,0 +1,51 @@ +--- +title: Deprecation +description: The Hugo project follows a formal and consistent process to deprecate functions, methods, and configuration settings. +categories: [] +keywords: [] +--- + +When a project _deprecates_ something, they are telling its users: + +1. Don't use Thing One anymore. +1. Use Thing Two instead. +1. We're going to remove Thing One at some point in the future. + +[reasons for deprecation]: https://en.wikipedia.org/wiki/Deprecation + +Common [reasons for deprecation]: + +- A feature has been replaced by a more powerful alternative. +- A feature contains a design flaw. +- A feature is considered extraneous, and will be removed in the future in order to simplify the system as a whole. +- A future version of the software will make major structural changes, making it impossible or impractical to support older features. +- Standardization or increased consistency in naming. +- A feature that once was available only independently is now combined with its co-feature. + +After the project team deprecates something in code, Hugo will: + +1. Log an INFO message for 3 minor releases[^1] +1. Log a WARN message for another 12 minor releases +1. Log an ERROR message and fail the build thereafter + +The project team will: + +1. On the deprecation date, update the documentation with a note describing the deprecation and any relevant alternatives. +1. Remove the code six or more minor releases after Hugo begins logging ERROR messages and failing the build. At that point, Hugo will throw an error, but the error message will no longer mention the deprecation. +1. Remove the corresponding documentation two years after the deprecation date. + +To see the INFO messages, you must use the `--logLevel` command line flag: + +```text +hugo --logLevel info +``` + +To limit the output to deprecation notices: + +```text +hugo --logLevel info | grep deprecate +``` + +Run the above command every time you upgrade Hugo. + +[^1]: For example, v0.1.1 => v0.2.0 is a minor release. diff --git a/docs/content/en/troubleshooting/faq.md b/docs/content/en/troubleshooting/faq.md new file mode 100644 index 000000000..6992af5d3 --- /dev/null +++ b/docs/content/en/troubleshooting/faq.md @@ -0,0 +1,113 @@ +--- +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? +: <!-- do not remove preceding space --> + {{% 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? +: You may have neglected to pass the required [context](g) when calling the partial. For example: + + ```go-html-template + {{/* incorrect */}} + {{ partial "_internal/pagination.html" }} + + {{/* correct */}} + {{ partial "_internal/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\ +`{{</* shortcode */>}}` 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 Scratch or Store missing a value? +: The [`Scratch`] and [`Store`] methods on a `Page` object allow 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. + + 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/ +[`Scratch`]: /methods/page/scratch +[`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 --git a/docs/content/en/troubleshooting/inspection.md b/docs/content/en/troubleshooting/inspection.md new file mode 100644 index 000000000..dc662243a --- /dev/null +++ b/docs/content/en/troubleshooting/inspection.md @@ -0,0 +1,39 @@ +--- +title: Data inspection +linkTitle: Inspection +description: Use template functions to inspect values and data structures. +categories: [] +keywords: [] +--- + +Use the [`debug.Dump`] function to inspect a data structure: + +```go-html-template +<pre>{{ debug.Dump .Params }}</pre> +``` + +```text +{ + "date": "2023-11-10T15:10:42-08:00", + "draft": false, + "iscjklanguage": false, + "lastmod": "2023-11-10T15:10:42-08:00", + "publishdate": "2023-11-10T15:10:42-08:00", + "tags": [ + "foo", + "bar" + ], + "title": "My first post" +} +``` + +Use the [`printf`] function (render) or [`warnf`] function (log to console) to inspect simple data structures. The layout string below displays both value and data type. + +```go-html-template +{{ $value := 42 }} +{{ printf "%[1]v (%[1]T)" $value }} → 42 (int) +``` + +[`debug.Dump`]: /functions/debug/dump/ +[`printf`]: /functions/fmt/printf/ +[`warnf`]: /functions/fmt/warnf/ diff --git a/docs/content/en/troubleshooting/logging.md b/docs/content/en/troubleshooting/logging.md new file mode 100644 index 000000000..0cd25d1ae --- /dev/null +++ b/docs/content/en/troubleshooting/logging.md @@ -0,0 +1,65 @@ +--- +title: Logging +description: Enable logging to inspect events while building your site. +categories: [] +keywords: [] +--- + +## Command line + +Enable console logging with the `--logLevel` command line flag. + +Hugo has four logging levels: + +error +: Display error messages only. + + ```sh + hugo --logLevel error + ``` + +warn +: Display warning and error messages. + + ```sh + hugo --logLevel warn + ``` + +info +: Display information, warning, and error messages. + + ```sh + hugo --logLevel info + ``` + +debug +: Display debug, information, warning, and error messages. + + ```sh + hugo --logLevel debug + ``` + +> [!note] +> If you do not specify a logging level with the `--logLevel` flag, warnings and errors are always displayed. + +## Template functions + +You can also use template functions to print warnings or errors to the console. These functions are typically used to report data validation errors, missing files, etc. + +{{% list-pages-in-section path=/functions/fmt filter=functions_fmt_logging filterType=include %}} + +## LiveReload + +To log Hugo's LiveReload requests in your browser, add this query string to the URL when running Hugo's development server: + +```text +debug=LR-verbose +``` + +For example: + +```text +http://localhost:1313/?debug=LR-verbose +``` + +Then monitor the reload requests in your browser's dev tools console. Make sure the dev tools "preserve log" option is enabled. diff --git a/docs/content/en/troubleshooting/performance.md b/docs/content/en/troubleshooting/performance.md new file mode 100644 index 000000000..e366eba81 --- /dev/null +++ b/docs/content/en/troubleshooting/performance.md @@ -0,0 +1,104 @@ +--- +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/single.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 _default/list.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 _default/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 _default/_markup/render-codeblock.html + 230.490038ms 8.865001ms 177.4615ms 0 0 0 26 shortcodes/template.html + 176.921913ms 176.921913ms 176.921913ms 0 0 0 1 examples.tmpl + 163.951469ms 14.904679ms 70.267953ms 0 0 0 11 articles/list.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 _default/single.html + 146.785804ms 146.785804ms 146.785804ms 0 0 0 1 _default/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 _default/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. + +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. + +> [!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 |