Goldmark Markdown Processing in Hugo

hugo
goldmark
markdown
syntax-highlighting
customization
Understanding Hugo’s Goldmark parser, configuration options, syntax highlighting, and custom render hooks for advanced markdown rendering
Author

Dario Airoldi

Published

January 14, 2026

Modified

March 8, 2026

Goldmark Markdown Processing in Hugo

📖 Overview

Since Hugo 0.60, Goldmark is the default markdown parser, replacing BlackFriday. Goldmark is a CommonMark-compliant parser written in Go that offers better performance, spec compliance, and extensibility than its predecessor.

Why Goldmark Matters:

  • CommonMark compliance - Consistent rendering across platforms
  • Extensible - Support for tables, task lists, strikethrough, etc.
  • Performant - Native Go implementation
  • Customizable - Extensive configuration options
  • Render hooks - Custom rendering for links, images, headings, code blocks

⚙️ Goldmark Configuration

Basic Configuration

config.toml:

[markup]
  defaultMarkdownHandler = "goldmark"
  
  [markup.goldmark]
    [markup.goldmark.renderer]
      unsafe = true              # Allow raw HTML in markdown
      hardWraps = false          # Don't convert line breaks to <br>
      xhtml = false              # Don't use XHTML-style tags
    
    [markup.goldmark.parser]
      autoHeadingID = true       # Generate heading IDs automatically
      autoHeadingIDType = "github"  # Use GitHub-style IDs
      
      [markup.goldmark.parser.attribute]
        block = true             # Allow attributes on blocks
        title = true             # Allow attributes on titles
    
    [markup.goldmark.extensions]
      definitionList = true      # Enable definition lists
      footnote = true            # Enable footnotes
      linkify = true             # Auto-link URLs
      linkifyProtocol = "https"  # Default protocol for linkify
      strikethrough = true       # Enable ~~strikethrough~~
      table = true               # Enable tables
      taskList = true            # Enable task lists
      typographer = true         # Smart quotes, dashes

Renderer Options

unsafe = true vs false:

<!-- With unsafe = true (allows raw HTML) -->
<div class="alert alert-warning">
  ⚠️ This works!
</div>

<script>alert("This also works, be careful!")</script>

<!-- With unsafe = false (HTML escaped) -->
<div class="alert">This is shown as text, not rendered</div>

When to use unsafe = true:

  • ✅ You control all content
  • ✅ Need custom HTML components
  • ✅ Trusted content sources only

When to use unsafe = false:

  • ✅ User-generated content
  • ✅ Maximum security
  • ✅ Enforce markdown-only content

Parser Options

autoHeadingID and autoHeadingIDType:

## My Heading Title

<!-- autoHeadingIDType = "github" -->
<h2 id="my-heading-title">My Heading Title</h2>

<!-- autoHeadingIDType = "github-ascii" -->
<h2 id="my-heading-title">My Heading Title</h2>

<!-- autoHeadingIDType = "blackfriday" (legacy) -->
<h2 id="my-heading-title">My Heading Title</h2>

Attribute support:

{.myclass #myid key="value"}
## Heading with Attributes

<!-- Renders as: -->
<h2 class="myclass" id="myid" key="value">Heading with Attributes</h2>

{.warning}
This is a warning paragraph.

<!-- Renders as: -->
<p class="warning">This is a warning paragraph.</p>

📝 Markdown Extensions

Tables

| Feature | Hugo/Goldmark | Quarto |
|---------|---------------|--------|
| Build Speed | ✅ Fast | 🟡 Moderate |
| Code Execution | ❌ No | ✅ Yes |
| Templates | Go templates | Pandoc |

<!-- Alignment -->
| Left | Center | Right |
|:-----|:------:|------:|
| Text | Text   | Text  |

Task Lists

- [x] Install Hugo
- [x] Create new site
- [ ] Configure theme
- [ ] Write first post
  - [x] Draft content
  - [ ] Add images
  - [ ] Publish

Renders as:

  • ☑ Install Hugo
  • ☑ Create new site
    • ☑ Draft content

Strikethrough

~~This text is crossed out~~

Price: ~~$99~~ $79 (20% off!)

Renders as: This text is crossed out

Definition Lists

Hugo
: A fast static site generator

Goldmark
: CommonMark-compliant markdown parser written in Go

Quarto
: Scientific publishing system built on Pandoc

Renders as:

Hugo
A fast static site generator
Goldmark
CommonMark-compliant markdown parser written in Go
Quarto
Scientific publishing system built on Pandoc

Footnotes

Hugo uses Goldmark[^1] for markdown processing, which replaced BlackFriday[^2].

[^1]: Goldmark is a CommonMark 0.30 compliant markdown parser.
[^2]: BlackFriday was the previous default parser before Hugo 0.60.

Renders with footnote links and auto-generated footnote section.

Typographer

<!-- Smart quotes -->
"This is a quote"
'Single quote'

<!-- Em dashes -->
This is an em-dash: ---
This is an en-dash: --

<!-- Ellipsis -->
Waiting...

<!-- Renders as -->
"This is a quote"  <!-- Curly quotes -->
'Single quote'     <!-- Curly single quotes -->
This is an em-dash: —
This is an en-dash: –
Waiting…

Auto-linking

<!-- linkify = true -->
Check out https://gohugo.io for more info.
Email me at info@example.com

<!-- Renders as -->
Check out <a href="https://gohugo.io">https://gohugo.io</a> for more info.
Email me at <a href="mailto:info@example.com">info@example.com</a>

🎨 Syntax Highlighting with Chroma

Hugo includes Chroma, a syntax highlighter supporting 100+ languages.

Configuration

config.toml:

[markup.highlight]
  anchorLineNos = false          # Add anchors to line numbers
  codeFences = true              # Enable ``` code blocks
  guessSyntax = false            # Don't guess language if not specified
  hl_Lines = ""                  # Highlight specific lines
  hl_inline = false              # Highlight inline code
  lineAnchors = ""               # Prefix for line anchors
  lineNoStart = 1                # Starting line number
  lineNos = false                # Show line numbers
  lineNumbersInTable = true      # Use table for line numbers
  noClasses = true               # Use inline styles (vs CSS classes)
  noHl = false                   # Disable highlighting
  style = "monokai"              # Color scheme
  tabWidth = 4                   # Tab width in spaces

Available Styles

# List all available styles
hugo gen chromastyles --help

# Generate CSS for a specific style
hugo gen chromastyles --style=monokai > syntax.css

Popular styles:

  • monokai - Dark theme, popular for code
  • github - GitHub-style light theme
  • dracula - Dark purple theme
  • vim - Classic vim colors
  • vs - Visual Studio light theme
  • solarized-dark / solarized-light - Solarized themes

Code Blocks

Fenced code blocks:

```go
package main

import "fmt"

func main() {
    fmt.Println("Hello, Hugo!")
}
```

With language and options:

```go {linenos=table,hl_lines=[2,"4-6"],linenostart=1}
package main

import "fmt"

func main() {
    fmt.Println("Hello, Hugo!")
}
```

Options:

  • linenos=table - Line numbers in table (for copy-paste)
  • linenos=inline - Line numbers inline
  • hl_lines=[2,5] - Highlight lines 2 and 5
  • hl_lines=["4-6"] - Highlight lines 4 through 6
  • linenostart=10 - Start line numbers at 10
  • anchorlinenos=true - Make line numbers linkable

Highlight Shortcode

Alternative to fenced code blocks with more control:

{{< highlight go "linenos=table,hl_lines=8 15-17,linenostart=1" >}}
package main

import "fmt"

func main() {
    fmt.Println("Hello, Hugo!")
}
{{< /highlight >}}

Inline Code Highlighting

config.toml:

[markup.highlight]
  hl_inline = true

Usage:

Use the `var x = 10;`{language=javascript} syntax in your code.

Practical Example: Learning Hub Code Display

Recommended configuration for technical documentation:

[markup.highlight]
  anchorLineNos = true           # Allow linking to specific lines
  codeFences = true
  guessSyntax = false            # Require explicit language
  lineNos = false                # Don't show by default
  lineNumbersInTable = true      # Better for copy-paste
  noClasses = false              # Use CSS classes (better performance)
  style = "github"               # Professional light theme
  tabWidth = 2                   # Consistent with VS Code defaults

Generate CSS:

hugo gen chromastyles --style=github > assets/css/syntax.css

Include in template:

{{ $syntax := resources.Get "css/syntax.css" | minify }}
<link rel="stylesheet" href="{{ $syntax.Permalink }}">

🎣 Render Hooks

Render hooks allow you to customize how specific markdown elements are rendered without modifying content files.

Image Render Hook

**layouts/_default/_markup/render-image.html:**

{{ $image := .Page.Resources.GetMatch .Destination }}
{{ if $image }}
  {{/* Image is a page resource */}}
  {{ $resized := $image.Resize "800x" }}
  {{ $webp := $resized.Process "webp" }}
  
  <figure>
    <picture>
      <source srcset="{{ $webp.RelPermalink }}" type="image/webp">
      <img src="{{ $resized.RelPermalink }}"
           alt="{{ .Text }}"
           width="{{ $resized.Width }}"
           height="{{ $resized.Height }}"
           loading="lazy"
           {{ with .Title }}title="{{ . }}"{{ end }}>
    </picture>
    {{ with .Title }}
      <figcaption>{{ . }}</figcaption>
    {{ end }}
  </figure>
{{ else }}
  {{/* External image or static file */}}
  <img src="{{ .Destination | safeURL }}"
       alt="{{ .Text }}"
       loading="lazy"
       {{ with .Title }}title="{{ . }}"{{ end }}>
{{ end }}

Features:

  • ✅ Auto-resize images to 800px width
  • ✅ Generate WebP versions
  • ✅ Lazy loading
  • ✅ Responsive images
  • ✅ Figure/figcaption for titles

Heading Render Hook

**layouts/_default/_markup/render-heading.html:**

<h{{ .Level }} id="{{ .Anchor | safeURL }}">
  {{ .Text }}
  <a href="#{{ .Anchor | safeURL }}" 
     class="heading-anchor" 
     aria-label="Link to {{ .Text }}">
    <svg class="icon-link" aria-hidden="true">
      <use xlink:href="#icon-link"></use>
    </svg>
  </a>
</h{{ .Level }}>

Features:

  • ✅ Linkable headings (like GitHub)
  • ✅ Accessible labels
  • ✅ Custom styling

Code Block Render Hook

**layouts/_default/_markup/render-codeblock-bash.html:**

{{ $content := .Inner }}
<div class="code-block bash-block">
  <div class="code-header">
    <span class="language">Bash</span>
    <button class="copy-button" 
            data-clipboard-text="{{ $content }}">
      Copy
    </button>
  </div>
  <pre><code class="language-bash">{{ $content }}</code></pre>
</div>

Language-specific hooks:

  • render-codeblock-bash.html
  • render-codeblock-powershell.html
  • render-codeblock-python.html
  • render-codeblock-go.html

Features:

  • ✅ Language-specific styling
  • ✅ Copy button
  • ✅ Custom headers
  • ✅ Enhanced UX

🆚 Goldmark vs Quarto/Pandoc Markdown

Feature Goldmark (Hugo) Pandoc (Quarto)
Spec Compliance CommonMark 0.30 Pandoc’s extended markdown
Tables GitHub-style Pandoc tables (more flexible)
Math KaTeX (via shortcode/JS) Built-in LaTeX rendering
Citations Manual/custom Native with CSL support
Code Execution ❌ No ✅ Yes (R, Python, Julia)
Div/Span Attributes extension Native .class {attr}
Callouts Custom shortcodes ::: {.callout} syntax
Cross-references Custom/manual [@fig:label] native
Diagrams Mermaid (JS) Native with Graphviz/Mermaid

Migration Considerations from Quarto

Quarto callouts:

:::{.callout-warning}
This is a warning
:::

Hugo equivalent (custom shortcode):

{{< callout type="warning" >}}
This is a warning
{{< /callout >}}

Quarto figure cross-reference:

See @fig:architecture for details.

![Architecture](diagram.png){#fig:architecture}

Hugo equivalent:

See [Figure 1](#fig-architecture) for details.

![Architecture](diagram.png "Figure 1: System Architecture") {#fig-architecture}

💡 Best Practices for Learning Hub

Render Hooks Strategy

  1. Implement link hook - External link handling
  2. Implement image hook - Auto-optimization
  3. Implement heading hook - Linkable headings
  4. Implement code block hooks - Copy buttons, language-specific styling

Content Guidelines

  1. Always specify language in code blocks:

    ```python  <!-- Good -->
    ```         <!-- Bad: no syntax highlighting -->
  2. Use attributes for styling:

    {.alert .alert-warning}
    Important note!
  3. Leverage footnotes for references:

    Hugo uses Goldmark[^1] for parsing.
    
    [^1]: https://github.com/yuin/goldmark
  4. Use tables for comparisons:

    | Tool | Speed | Features |
    |------|-------|----------|
    | Hugo | ✅ Fast | Good |

🎯 Key Takeaways

  1. Goldmark is CommonMark-compliant - Predictable, standard behavior
  2. Extensive configuration options - Customize to your needs
  3. Render hooks provide powerful customization - Without changing content
  4. Chroma supports 100+ languages - Comprehensive syntax highlighting
  5. Extensions enable rich content - Tables, footnotes, task lists, etc.

🔜 Next Steps

Continue to Hugo vs Quarto Comparison to learn about:

  • Detailed feature comparison
  • Performance benchmarks with Learning Hub
  • Migration complexity analysis
  • When to choose each tool
  • Hybrid approaches

📚 References