Feature Request: Content hook for post-processing HTML from external renderers (e.g., Asciidoctor)

Hi Hugo Team,

I would like to propose a new feature: a content hook that allows for post-processing the final HTML of a content page after it has been rendered by its respective engine, especially external ones like Asciidoctor.

Background and Motivation

I am currently working on adding support for Asciidoc to a community module, hugo-admonitions. This module provides beautifully styled admonitions (callouts like Note, Warning, etc.).

  • For Markdown: Our current implementation works perfectly. We use a render-blockquote-alert.html render hook to intercept a specific Markdown syntax and convert it into a custom HTML structure (e.g., <div class="admonition note">...</div>). Our CSS is written to style this specific, clean structure.

  • The Asciidoc Challenge: When adding support for Asciidoc (.adoc files), we’ve hit a limitation. Hugo passes the content to the external asciidoctor binary, which generates its own default HTML for admonitions (a <table>-based structure). This process completely bypasses Hugo’s render hook system.

This leaves us with two architectural choices:

  1. Adapt the CSS to the HTML: Our current, working solution is to add a significant amount of specific CSS to our stylesheet to target Asciidoctor’s unique table-based output.

    • Downside: This couples our module tightly to the specific HTML output of Asciidoctor, which could change. It also leads to CSS bloat, as we have to maintain two sets of structural styles for the same visual component.
  2. Transform the HTML to the CSS: A much cleaner and more robust architectural solution would be to intercept the HTML generated by Asciidoctor and transform it to match the semantic HTML structure our module already uses for Markdown. This would allow us to reuse our existing CSS, making the module more maintainable and efficient.

Unfortunately, after investigation, it appears Hugo does not currently provide a hook to post-process the .Content after it has been rendered by an external tool.

Proposed Solution

I propose the creation of a new, final-stage content hook, perhaps named post-render-content.html, located at layouts/_default/_markup/post-render-content.html.

This hook would function as follows:

  • It would receive the fully rendered .Content variable as its context.
  • It would run after the content has been processed by its renderer (Goldmark, Asciidoctor, etc.).
  • It would allow theme and module authors to perform final transformations (e.g., via replaceRE) before the content is rendered into the final page template.

A hypothetical implementation would look like this:

{{/* layouts/_default/_markup/post-render-content.html */}}

{{ $processedContent := .Content |
    replaceRE `<div class="admonitionblock (\w+)">\s*<table>(.+?)</table>\s*</div>` `<div class="admonition $1">$2</div>` |
    replaceRE `(?s)<td class="icon"><div class="title">(.+?)</div></td>` `<div class="admonition-header">$1</div>` |
    replaceRE `(?s)<td class="content">(.+?)</td>` `<div class="admonition-content">$1</div>`
    /* Note: Regex is simplified for demonstration */
}}

{{ return $processedContent | safeHTML }}

Alternatives Considered

  1. Renderer-Specific CSS: This is the workaround we are currently using. It is functional but not ideal for the reasons mentioned above (fragile and not DRY).
  2. Custom Asciidoctor Templates: One could configure Asciidoctor itself to use custom templates to generate the desired HTML. This places a very high configuration burden on the end-user and defeats the purpose of creating a simple, “plug-and-play” Hugo module.

Adding a native post-processing hook would provide a powerful, clean, and “Hugo-native” way to normalize output from various content formats. It would greatly empower module authors and theme developers to create more consistent and robust components.

Thank you for your time and for considering this request.

2 Likes

Thanks a lot for this detailed analysis and the proposal. I am struggling quite hard with Asciidoc content in Hugo (which is a hard requirement for a project I am working on) as such render hooks are not working. Aside from the mentioned admonitions plugin I’d also like to use hugo-kroki which relies on the same mechanism and isn’t working with Asciidoc source files.

It would be great if source files in different formats than Markdown would receive some love and a better support by Hugo. Thanks for your consideration!

The Kroki shortcode should work fine.