summaryrefslogtreecommitdiffstats
path: root/docs/content/en/render-hooks
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2024-06-21 09:41:24 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2024-06-21 09:41:24 +0200
commitaf0cb57aaf668278551454678eac60b17348b13c (patch)
treeb0fbd866cfc5e605ff789de9d6d9b162094a217b /docs/content/en/render-hooks
parentd5542ed286746e89fb13a1f821d4955ace371773 (diff)
parent8b9803425e63e1b1801f8d5d676e96368d706722 (diff)
downloadhugo-af0cb57aaf668278551454678eac60b17348b13c.tar.gz
hugo-af0cb57aaf668278551454678eac60b17348b13c.zip
Merge commit '8b9803425e63e1b1801f8d5d676e96368d706722'
Diffstat (limited to 'docs/content/en/render-hooks')
-rw-r--r--docs/content/en/render-hooks/_common/_index.md13
-rw-r--r--docs/content/en/render-hooks/_common/pageinner.md42
-rw-r--r--docs/content/en/render-hooks/_index.md17
-rwxr-xr-xdocs/content/en/render-hooks/code-blocks.md152
-rwxr-xr-xdocs/content/en/render-hooks/headings.md79
-rwxr-xr-xdocs/content/en/render-hooks/images.md163
-rwxr-xr-xdocs/content/en/render-hooks/introduction.md85
-rwxr-xr-xdocs/content/en/render-hooks/links.md133
8 files changed, 684 insertions, 0 deletions
diff --git a/docs/content/en/render-hooks/_common/_index.md b/docs/content/en/render-hooks/_common/_index.md
new file mode 100644
index 000000000..4328d4d14
--- /dev/null
+++ b/docs/content/en/render-hooks/_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/render-hooks/_common/pageinner.md b/docs/content/en/render-hooks/_common/pageinner.md
new file mode 100644
index 000000000..de1316cba
--- /dev/null
+++ b/docs/content/en/render-hooks/_common/pageinner.md
@@ -0,0 +1,42 @@
+---
+# 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] 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:
+
+{{< code file=layouts/shortcodes/include.html >}}
+{{ with site.GetPage (.Get 0) }}
+ {{ .RenderShortcodes }}
+{{ end }}
+{{< /code >}}
+
+Then call the shortcode in your Markdown:
+
+{{< code file=content/posts/p1.md >}}
+{{%/* include "/posts/p2" */%}}
+{{< /code >}}
+
+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 the `{{%/*..*/%}}` notation.
+
+[`RenderShortcodes`]: /methods/page/rendershortcodes/
+{{% /note %}}
+
+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]({{% eturl render-link %}})
+- [Embedded image render hook]({{% eturl render-image %}})
+
+[`RenderShortcodes`]: /methods/page/rendershortcodes/
+[page resources]: /getting-started/glossary/#page-resource
diff --git a/docs/content/en/render-hooks/_index.md b/docs/content/en/render-hooks/_index.md
new file mode 100644
index 000000000..8cf72c4e8
--- /dev/null
+++ b/docs/content/en/render-hooks/_index.md
@@ -0,0 +1,17 @@
+---
+title: Render hooks
+linkTitle: In this section
+description: Create render hooks to override the rendering of Markdown to HTML.
+categories: []
+keywords: []
+menu:
+ docs:
+ identifier: render-hooks-in-this-section
+ parent: render-hooks
+ weight: 10
+weight: 10
+showSectionMenu: false
+aliases: [/templates/render-hooks/]
+---
+
+Create render hooks to override the rendering of Markdown to HTML.
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..0c11c7864
--- /dev/null
+++ b/docs/content/en/render-hooks/code-blocks.md
@@ -0,0 +1,152 @@
+---
+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: [render hooks]
+keywords: []
+menu:
+ docs:
+ parent: render-hooks
+ weight: 30
+weight: 30
+toc: true
+---
+
+## Markdown
+
+This Markdown example contains a fenced code block:
+
+{{< code file=content/example.md lang=text >}}
+```bash {class="my-class" id="my-codeblock" lineNos=inline tabWidth=2}
+declare a=1
+echo "$a"
+exit
+```
+{{< /code >}}
+
+A fenced code block consists of:
+
+- A leading [code fence]
+- An optional [info string]
+- A code sample
+- A trailing code fence
+
+[code fence]: https://spec.commonmark.org/0.31.2/#code-fence
+[info string]: https://spec.commonmark.org/0.31.2/#info-string
+
+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].
+
+[Chroma]: https://github.com/alecthomas/chroma/
+[highlighting options]: /functions/transform/highlight/#options
+
+{{% note %}}
+Although `style` is a global HTML attribute, when used in an info string it is a highlighting option.
+{{% /note %}}
+
+## Context
+
+Code block render hook templates receive the following [context]:
+
+[context]: /getting-started/glossary/#context
+
+###### 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).
+
+[`RenderShortcodes`]: /methods/page/rendershortcodes
+
+###### 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:
+
+[CommonMark specification]: https://spec.commonmark.org/current/
+
+{{< code file=layouts/_default/_markup/render-codeblock.html copy=true >}}
+{{ $result := transform.HighlightCodeBlock . }}
+{{ $result.Wrapped }}
+{{< /code >}}
+
+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:
+
+[Mermaid]: https://mermaid.js.org/
+
+{{< code file=layouts/_default/_markup/render-codeblock-mermaid.html copy=true >}}
+<pre class="mermaid">
+ {{- .Inner | safeHTML }}
+</pre>
+{{ .Page.Store.Set "hasMermaid" true }}
+{{< /code >}}
+
+Then include this snippet at the bottom of the your base template:
+
+{{< code 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 }}
+{{< /code >}}
+
+See the [diagrams] page for details.
+
+[diagrams]: /content-management/diagrams/#mermaid-diagrams
+
+## Embedded
+
+Hugo includes an [embedded code block render hook] to render [GoAT diagrams].
+
+[embedded code block render hook]: {{% eturl render-codeblock-goat %}}
+[GoAT diagrams]: /content-management/diagrams/#goat-diagrams-ascii
+
+{{% include "/render-hooks/_common/pageinner.md" %}}
diff --git a/docs/content/en/render-hooks/headings.md b/docs/content/en/render-hooks/headings.md
new file mode 100755
index 000000000..c48bb11e1
--- /dev/null
+++ b/docs/content/en/render-hooks/headings.md
@@ -0,0 +1,79 @@
+---
+title: Heading render hooks
+linkTitle: Headings
+description: Create a heading render hook to override the rendering of Markdown headings to HTML.
+categories: [render hooks]
+keywords: []
+menu:
+ docs:
+ parent: render-hooks
+ weight: 40
+weight: 40
+toc: true
+---
+
+## Context
+
+Heading render hook templates receive the following [context]:
+
+[context]: /getting-started/glossary/#context
+
+###### 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).
+
+[`RenderShortcodes`]: /methods/page/rendershortcodes
+
+###### PlainText
+
+(`string`) The heading text as plain text.
+
+###### Text
+
+(`string`) The heading text.
+
+## 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/
+
+{{< code file=layouts/_default/_markup/render-heading.html copy=true >}}
+<h{{ .Level }} id="{{ .Anchor }}">
+ {{- .Text | safeHTML -}}
+</h{{ .Level }}>
+{{< /code >}}
+
+To add an anchor link to the right of each heading:
+
+{{< code file=layouts/_default/_markup/render-heading.html copy=true >}}
+<h{{ .Level }} id="{{ .Anchor }}">
+ {{ .Text | safeHTML }}
+ <a href="#{{ .Anchor }}">#</a>
+</h{{ .Level }}>
+{{< /code >}}
+
+{{% include "/render-hooks/_common/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..e68cd1b95
--- /dev/null
+++ b/docs/content/en/render-hooks/images.md
@@ -0,0 +1,163 @@
+---
+title: Image render hooks
+linkTitle: Images
+description: Create an image render to hook override the rendering of Markdown images to HTML.
+categories: [render hooks]
+keywords: []
+menu:
+ docs:
+ parent: render-hooks
+ weight: 50
+weight: 50
+toc: true
+---
+
+## Markdown
+
+A Markdown image has three components: the image description, the image destination, and optionally the image title.
+
+```text
+![white kitten](/images/kitten.jpg "A kitten!")
+ ------------ ------------------ ---------
+ description destination title
+```
+
+These components are passed into the render hook [context] as shown below.
+
+[context]: /getting-started/glossary/#context
+
+## 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`) Returns true if 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).
+
+[`RenderShortcodes`]: /methods/page/rendershortcodes
+
+###### PlainText
+
+(`string`) The image description as plain text.
+
+###### Text
+
+(`string`) 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.
+{{% /note %}}
+
+In its default configuration, Hugo renders Markdown images according to the [CommonMark specification]. To create a render hook that does the same thing:
+
+[CommonMark specification]: https://spec.commonmark.org/current/
+
+{{< code file=layouts/_default/_markup/render-image.html copy=true >}}
+<img src="{{ .Destination | safeURL }}"
+ {{- with .Text }} alt="{{ . }}"{{ end -}}
+ {{- with .Title }} title="{{ . }}"{{ end -}}
+>
+{{- /* chomp trailing newline */ -}}
+{{< /code >}}
+
+To render standalone images within `figure` elements:
+
+{{< code file=layouts/_default/_markup/render-image.html copy=true >}}
+{{- if .IsBlock -}}
+ <figure>
+ <img src="{{ .Destination | safeURL }}"
+ {{- with .Text }} alt="{{ . }}"{{ end -}}
+ >
+ <figcaption>{{ .Title }}</figcaption>
+ </figure>
+{{- else -}}
+ <img src="{{ .Destination | safeURL }}"
+ {{- with .Text }} alt="{{ . }}"{{ end -}}
+ {{- with .Title }} title="{{ . }}"{{ end -}}
+ >
+{{- end -}}
+{{< /code >}}
+
+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:
+
+[embedded image render hook]: {{% eturl render-image %}}
+
+{{< 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.
+
+[duplication of shared page resources]: /getting-started/configuration-markup/#duplicateresourcefiles
+{{% /note %}}
+
+The embedded image render hook resolves internal Markdown destinations by looking for a matching [page resource], falling back to a matching [global resource]. Remote destinations are passed through, and the render hook will not throw an error or warning if it is unable to resolve a destination.
+
+[page resource]: /getting-started/glossary/#page-resource
+[global resource]: /getting-started/glossary/#global-resource
+
+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 "/render-hooks/_common/pageinner.md" %}}
diff --git a/docs/content/en/render-hooks/introduction.md b/docs/content/en/render-hooks/introduction.md
new file mode 100755
index 000000000..ebf95c00f
--- /dev/null
+++ b/docs/content/en/render-hooks/introduction.md
@@ -0,0 +1,85 @@
+---
+title: Introduction
+description: An introduction to Hugo's render hooks.
+categories: [render hooks]
+keywords: []
+menu:
+ docs:
+ identifier: render-hooks-introduction
+ parent: render-hooks
+ weight: 20
+weight: 20
+---
+
+When rendering Markdown to HTML, render hooks override the conversion. Each render hook is a template, with one template for each supported element type:
+
+- [Code blocks](/render-hooks/code-blocks)
+- [Headings](/render-hooks/headings)
+- [Images](/render-hooks/images)
+- [Links](/render-hooks/links)
+
+{{% 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.
+
+[content formats]: /content-management/formats/
+{{% /note %}}
+
+For example, consider this Markdown:
+
+```text
+[Hugo](https://gohugo.io)
+
+![kitten](kitten.jpg)
+```
+
+Without link or image render hooks, this 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-codeblock.html
+ ├── render-heading.html
+ ├── render-image.html
+ └── render-link.html
+```
+
+The template lookup order allows you to create different render hooks for each page [type], [kind], language, and [output format]. For example:
+
+```text
+layouts/
+├── _default/
+│ └── _markup/
+│ ├── render-link.html
+│ └── render-link.text.txt
+├── books/
+│ └── _markup/
+│ ├── render-link.html
+│ └── render-link.text.txt
+└── films/
+ └── _markup/
+ ├── render-link.html
+ └── render-link.text.txt
+```
+
+[kind]: /getting-started/glossary/#page-kind
+[output format]: /getting-started/glossary/#output-format
+[type]: /getting-started/glossary/#content-type
+
+The remaining pages in this section describe each type of render hook, including examples and the context received by each template.
diff --git a/docs/content/en/render-hooks/links.md b/docs/content/en/render-hooks/links.md
new file mode 100755
index 000000000..bf0485068
--- /dev/null
+++ b/docs/content/en/render-hooks/links.md
@@ -0,0 +1,133 @@
+---
+title: Link render hooks
+linkTitle: Links
+description: Create a link render hook to override the rendering of Markdown links to HTML.
+categories: [render hooks]
+keywords: []
+menu:
+ docs:
+ parent: render-hooks
+ weight: 60
+weight: 60
+toc: true
+---
+
+## 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] as shown below.
+
+[context]: /getting-started/glossary/#context
+
+## Context
+
+Link render hook templates receive the following context:
+
+[context]: /getting-started/glossary/#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).
+
+[`RenderShortcodes`]: /methods/page/rendershortcodes
+
+###### PlainText
+
+(`string`) The link description as plain text.
+
+###### Text
+
+(`string`) 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.
+{{% /note %}}
+
+In its default configuration, Hugo renders Markdown links according to the [CommonMark specification]. To create a render hook that does the same thing:
+
+[CommonMark specification]: https://spec.commonmark.org/current/
+
+{{< code file=layouts/_default/_markup/render-link.html copy=true >}}
+<a href="{{ .Destination | safeURL }}"
+ {{- with .Title }} title="{{ . }}"{{ end -}}
+>
+ {{- with .Text | safeHTML }}{{ . }}{{ end -}}
+</a>
+{{- /* chomp trailing newline */ -}}
+{{< /code >}}
+
+To include a `rel` attribute set to `external` for external links:
+
+{{< code 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 | safeHTML }}{{ . }}{{ end -}}
+</a>
+{{- /* chomp trailing newline */ -}}
+{{< /code >}}
+
+## 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:
+
+[embedded link render hook]: {{% eturl render-link %}}
+
+{{< 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.
+
+[duplication of shared page resources]: /getting-started/configuration-markup/#duplicateresourcefiles
+{{% /note %}}
+
+The embedded link render hook resolves internal Markdown destinations by looking for a matching page, falling back to a matching [page resource], then falling back to a matching [global resource]. Remote destinations are passed through, and the render hook will not throw an error or warning if it is unable to resolve a destination.
+
+[page resource]: /getting-started/glossary/#page-resource
+[global resource]: /getting-started/glossary/#global-resource
+
+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 "/render-hooks/_common/pageinner.md" %}}