GFM vs CommonMark vs Pandoc Markdown: Syntax Compared

Know which Markdown features travel safely

Page content

Markdown looks like one language until the same file renders differently on GitHub, Hugo, Obsidian, or Pandoc. And the problem is not that Markdown is unreliable.

It is that “Markdown” describes a family of related syntaxes, parsers, and platform features rather than a single universal document format. CommonMark defines a precise portable core, GitHub Flavored Markdown adds features useful for software collaboration, and Pandoc Markdown expands the language into a serious document-authoring format.

Markdown dialects comparison

Choosing between them depends on where the document must render. A README file, a Hugo blog post, and an academic paper each have different requirements. This comparison is part of the broader documentation tooling picture and covers the formal dialects, platform-specific extensions, and practical portability rules so you can pick the right syntax for your target environment. For a quick syntax reference, the Markdown cheatsheet covers the essential formatting elements.

Markdown Is Not One Language

The original Markdown syntax was intentionally small and loosely specified. That made it easy to read and implement, but different parsers began interpreting ambiguous input differently.

CommonMark was created to define consistent parsing rules for the fundamental Markdown structures. GitHub Flavored Markdown, usually called GFM, builds on that foundation with several widely used extensions.

Pandoc Markdown takes a different approach. Instead of remaining a small web-oriented syntax, it adds document features such as citations, metadata, footnotes, definition lists, attributes, and mathematical notation.

A simplified relationship looks like this:

flowchart TD M[Markdown family] --> C[CommonMark core] C --> G[GitHub Flavored Markdown] C --> X[Other CommonMark-based renderers] M --> P[Pandoc Markdown] G --> GH[GitHub platform features] X --> H[Hugo with Goldmark] X --> GL[GitLab Flavored Markdown] P --> PDF[PDF and academic workflows] P --> DOCX[DOCX and publishing workflows]

This hierarchy is useful, but it is not exact inheritance in every implementation. Each renderer can enable, disable, or add syntax independently.

The Short Answer

Use CommonMark-compatible syntax when portability matters most.

Use GFM when writing README files, pull requests, issue templates, and technical documentation intended primarily for GitHub-compatible platforms.

Use Pandoc Markdown when the source document must become PDF, DOCX, EPUB, LaTeX, slides, or an academic paper with citations and metadata.

For a Hugo technical blog, use the CommonMark core plus the Goldmark extensions that your site explicitly enables. Do not assume every feature visible on GitHub will work merely because Hugo is described as GFM-compatible.

Opinionated take: if you only remember one rule for a Hugo technical blog, treat CommonMark plus GFM-style tables and task lists as the default, and treat everything else — footnotes, math, callouts, header attributes — as an explicit, tested extension rather than an assumed default. That single habit prevents most of the portability failures described below.

CommonMark: The Portable Core

CommonMark is a formal specification for the basic Markdown language. Its main contribution is not a large collection of features, but consistent parsing.

It defines how parsers should interpret:

  • Paragraphs
  • ATX and Setext headings
  • Block quotes
  • Ordered and unordered lists
  • Fenced and indented code blocks
  • Emphasis and strong emphasis
  • Links and images
  • Reference-style links
  • Inline code
  • Thematic breaks
  • Raw HTML blocks
  • Hard and soft line breaks

A CommonMark document can still behave differently at the presentation layer. CSS, syntax highlighting, heading anchors, HTML sanitization, and link policies are outside the core parsing rules.

CommonMark should therefore be treated as a reliable structural baseline, not a promise that every renderer will produce an identical page.

A Portable CommonMark Example

# Service Deployment

The service exposes a small HTTP API.

## Requirements

- Linux
- Docker
- 8 GB of memory

## Start the service

```bash
docker compose up -d
```

See the [configuration guide](configuration.md) for details.

This type of document works across almost every modern Markdown environment. It uses headings, paragraphs, lists, fenced code, and ordinary links without relying on dialect-specific extensions.

GitHub Flavored Markdown: CommonMark for Software Projects

GitHub Flavored Markdown is a formal dialect based on CommonMark. It preserves the CommonMark parsing model and adds features commonly needed in repository documentation and collaboration.

The formal GFM specification adds:

  • Pipe tables
  • Task list items
  • Strikethrough
  • Extended autolinks
  • Restrictions around some raw HTML tags

These extensions are now so common that many users think they are part of standard Markdown. They are not part of the CommonMark core.

GFM Tables

| Backend | Best use |
|---|---|
| Ollama | Local experiments |
| vLLM | Shared inference |
| SGLang | Structured workloads |

A strict CommonMark parser is allowed to treat this as ordinary paragraph text. A GFM-compatible parser recognizes it as a table. For a deeper look at table syntax and alignment options, see Tables in Markdown.

GFM Task Lists

- [x] Install Docker
- [x] Download the model
- [ ] Add monitoring

Task list syntax is useful in issues, pull requests, and project documentation. Outside a supporting renderer, it may appear as an ordinary list containing literal square brackets.

GFM Strikethrough

Use the ~~old endpoint~~ new endpoint.

Strikethrough is widely supported, but it is still an extension rather than portable CommonMark syntax.

GFM recognizes more URL-like and email-like text without requiring angle brackets or explicit link syntax.

Visit https://example.com/docs for details.

In strict CommonMark, explicit autolinks use angle brackets:

<https://example.com/docs>

The explicit form is safer when a document must travel through unknown Markdown processors.

GitHub.com Supports More Than Formal GFM

A frequent source of confusion is the assumption that every Markdown feature visible on GitHub belongs to the GFM specification.

It does not.

GitHub.com adds platform-level processing and features around the GFM parser. Depending on the context, GitHub can support:

  • Mathematical expressions
  • Mermaid diagrams
  • Alerts
  • Issue and pull request references
  • User and team mentions
  • Commit references
  • Emoji shortcodes
  • Collapsible HTML sections
  • Color previews
  • Repository-relative links
  • Automatic heading anchors

Some of these features are syntax extensions. Others are post-processing behavior or integrations with GitHub data.

This distinction matters because another renderer may accurately claim GFM compatibility without implementing GitHub’s math renderer, Mermaid integration, issue references, or alert styling.

GitHub Mermaid Diagrams

GitHub renders a fenced code block marked mermaid as a diagram:

```mermaid
flowchart LR
    A[Markdown] --> B[Rendered diagram]
```

A generic GFM renderer may display the same block as highlighted source code. The Markdown remains valid, but the enhanced rendering is platform-specific. For a practical introduction to Mermaid syntax, see the Mermaid Diagrams Quickstart.

GitHub Mathematical Expressions

GitHub supports inline and block mathematical expressions using dollar delimiters and additional escaping forms.

The cache size is approximately $2nlhd$ bytes.
$$
C = 2nlhd
$$

Math is not part of formal GFM. Moving this content to another renderer requires a compatible math extension such as KaTeX, MathJax, or Pandoc math support.

GitHub Alerts

GitHub supports alert-style block quotes such as:

> [!WARNING]
> Changing this setting clears the cache.

On GitHub, this can appear as a styled warning. On a plain CommonMark renderer, it usually appears as an ordinary block quote containing [!WARNING].

That fallback is readable, which makes GitHub alerts less dangerous than extensions that disappear completely. They are still not portable presentation elements.

Pandoc Markdown: Markdown as a Document Language

Pandoc Markdown is designed for document conversion rather than one particular website. It uses Markdown as the source syntax for producing HTML, PDF, DOCX, EPUB, LaTeX, presentations, and other formats.

Its default Markdown reader includes a large extension set. Important capabilities include:

  • YAML metadata blocks
  • Footnotes
  • Citations
  • Multiple table formats
  • Definition lists
  • Mathematical notation
  • Header identifiers and attributes
  • Code block attributes
  • Fenced divisions
  • Bracketed spans
  • Superscript and subscript
  • Strikeout
  • Line blocks
  • Numbered example lists
  • Raw LaTeX
  • Raw HTML
  • Automatic section numbering
  • Bibliography processing

Pandoc Markdown is much more expressive than CommonMark or formal GFM. That expressiveness makes it powerful for publishing, but less safe as an interchange format.

Pandoc Footnotes

Markdown has several incompatible dialects.[^dialects]

[^dialects]: CommonMark, GFM, and Pandoc Markdown are three
    important examples.

Footnote syntax is supported by many modern tools, but it is not part of CommonMark or formal GFM.

GitHub currently renders footnotes in several content contexts, but that is a GitHub platform feature rather than a formal GFM guarantee. A renderer claiming only CommonMark or GFM compatibility may not support them.

Pandoc Citations

PagedAttention improves KV cache memory management
[@kwon2023pagedattention].

With a bibliography file and citation style, Pandoc can resolve this into a formatted academic citation and bibliography.

pandoc article.md \
  --citeproc \
  --bibliography references.bib \
  --csl ieee.csl \
  -o article.pdf

The citation syntax remains readable in an unsupported renderer, but it will not become a formatted reference without Pandoc or another compatible citation processor. Pandoc’s reader-side flexibility also underpins conversion workflows in the other direction — see converting Word documents to Markdown for a practical example of using Pandoc’s extended dialect as an intermediate format.

Pandoc Definition Lists

CommonMark
: A precise specification for core Markdown.

GFM
: A CommonMark-based dialect with software-oriented extensions.

Pandoc Markdown
: An extended authoring format for document conversion.

Definition lists are useful in manuals, glossaries, and technical books. They normally degrade poorly in renderers that do not support them because the colon lines remain visible as plain text.

Pandoc Header Attributes

## Cache Configuration {#cache-config .deployment}

Pandoc interprets the braces as an explicit identifier and class list. Many other Markdown renderers show the attribute text directly in the heading.

This is one of the clearest examples of useful syntax that should not be placed in a document expected to render everywhere.

Pandoc Fenced Divisions

::: warning
Changing this option restarts the server.

Pandoc converts this into a structural division with a class. Templates, CSS, filters, or output writers can decide how that structure should appear.

Most CommonMark and GFM renderers do not recognize the fence. They display the colons and content as ordinary text.

CommonMark vs GFM vs Pandoc Markdown

The following matrix describes the formal dialects, not every feature added by GitHub.com, Hugo, Obsidian, GitLab, or another platform.

Feature CommonMark Formal GFM Pandoc Markdown
Headings Yes Yes Yes
Emphasis Yes Yes Yes
Links and images Yes Yes Yes
Block quotes Yes Yes Yes
Ordered and unordered lists Yes Yes Yes
Fenced code blocks Yes Yes Yes
Raw HTML syntax Yes Restricted in some contexts Yes
Pipe tables No Yes Yes
Task lists No Yes Yes
Strikethrough No Yes Yes
Extended autolinks No Yes Configurable
Footnotes No No Yes
Citations No No Yes
YAML metadata No No Yes
Definition lists No No Yes
Mathematical notation No No Yes
Header attributes No No Yes
Fenced divisions No No Yes
Raw LaTeX No No Yes
Bibliography processing No No Yes

The word “No” does not mean a platform can never support the feature. It means the feature is not guaranteed by that dialect’s formal specification.

Which Syntax Works on GitHub?

For README files, issues, pull requests, discussions, and wikis, GFM is the natural baseline.

You can generally use:

  • CommonMark syntax
  • Tables
  • Task lists
  • Strikethrough
  • Extended autolinks
  • Syntax-highlighted code fences
  • GitHub-specific references
  • GitHub-supported math
  • GitHub-supported diagrams
  • GitHub alerts
  • Footnotes where supported by the content surface

The portability risk begins when GitHub performs additional rendering beyond formal GFM. Mermaid diagrams, mathematical notation, issue references, and alert presentation may not survive outside GitHub.

For repository files that are also published elsewhere, test the source in the second renderer rather than treating GitHub preview as authoritative.

Which Syntax Works in Hugo?

Hugo uses Goldmark as its default Markdown renderer. Goldmark conforms to CommonMark and provides extensions compatible with important parts of GFM.

In a typical Hugo configuration, the following work well:

  • CommonMark structure
  • Fenced code blocks
  • Pipe tables
  • Strikethrough
  • Task lists
  • Automatic heading IDs
  • Syntax highlighting
  • Footnotes when the extension is enabled
  • Definition lists when enabled
  • Typographic substitutions when enabled

Hugo also adds features outside Markdown through:

  • Front matter
  • Shortcodes
  • Render hooks
  • Page resources
  • Internal reference functions
  • Template processing
  • Site configuration

These Hugo features do not travel with the Markdown file. For a practical example of Hugo deployment, see Deploy Hugo to AWS S3.

Hugo Front Matter Is Not Markdown Content

A Hugo page commonly starts with YAML, TOML, or JSON metadata:

---
title: "Markdown Compatibility"
description: "Compare Markdown dialects and renderers."
date: 2026-07-31
tags:
  - Markdown
  - documentation
---

Pandoc can also recognize YAML metadata blocks, but it interprets fields according to its own templates and writers. GitHub normally displays the block as a YAML-like section or treats it as repository metadata only in specific systems.

The same syntax can therefore be recognized in more than one tool without having the same semantics.

Raw HTML in Hugo

Goldmark does not render potentially unsafe raw HTML by default in a standard Hugo configuration.

A block such as:

<div class="notice">
  Restart the service after changing this value.
</div>

may be omitted unless raw HTML rendering is enabled or the content is implemented through a shortcode or render hook.

For a controlled technical blog, enabling raw HTML can be reasonable. It still makes the source less portable and should be a deliberate site-level decision.

Mermaid in Hugo

A fenced mermaid block is still just a code block unless the Hugo theme, render hook, shortcode, or JavaScript pipeline transforms it into a diagram.

GitHub and Hugo may therefore accept identical Mermaid source while using completely different rendering mechanisms.

Which Syntax Works in Pandoc?

Pandoc can read several Markdown dialects explicitly:

pandoc --from=markdown input.md
pandoc --from=commonmark input.md
pandoc --from=gfm input.md
pandoc --from=commonmark_x input.md

This is one of Pandoc’s most useful portability features. The operator can tell Pandoc which dialect the source claims to use instead of relying on a vague .md file extension.

Pandoc also lets you enable or disable individual extensions:

pandoc \
  --from=markdown-footnotes-pipe_tables \
  input.md \
  -o output.html

Or start from a narrower format and add one feature:

pandoc \
  --from=commonmark+footnotes \
  input.md \
  -o output.html

You can inspect available extensions with:

pandoc --list-extensions=markdown
pandoc --list-extensions=commonmark
pandoc --list-extensions=gfm

This extension model is powerful, but it means “Pandoc Markdown” is not always one fixed configuration. Build commands and defaults files are part of the document specification.

Which Syntax Works in Obsidian?

Obsidian stores notes as Markdown files, but its authoring model includes several application-specific features.

Common examples include:

  • Wiki links
  • Embedded notes
  • Embedded files
  • Callouts
  • Block references
  • Tags
  • Properties
  • Highlighting
  • Comments
  • Dataview queries from plugins
  • Application-specific URI links

A wiki link such as:

[[Markdown Compatibility]]

is meaningful inside an Obsidian vault. GitHub, CommonMark, and a default Pandoc reader normally display it as literal bracketed text.

An embed is even more application-specific:

![[compatibility-table]]

The referenced content is not present in the file itself. Exporting or publishing the note therefore requires an expansion step that resolves the embed.

Obsidian is a good example of why storage in .md files does not guarantee Markdown portability. For a practical look at Obsidian as a knowledge management tool, see Obsidian for Personal Knowledge Management.

Which Syntax Works in GitLab?

GitLab Flavored Markdown uses CommonMark as its core and includes GFM features such as tables and task lists. It then adds GitLab-specific behavior including cross-references, mathematical notation, diagrams, and other collaboration features.

A README written in conservative GFM usually moves between GitHub and GitLab without major damage.

Platform integrations do not travel as reliably. Issue references, user mentions, diagrams, math handling, and special block syntax can behave differently even when the basic Markdown remains readable.

Platform Support Matrix

This matrix describes common default behavior. Themes, plugins, extensions, and configuration can change individual cells.

Feature GitHub Hugo Goldmark Pandoc Obsidian GitLab
CommonMark core Yes Yes Yes Mostly Yes
Pipe tables Yes Yes Yes Yes Yes
Task lists Yes Yes Yes Yes Yes
Strikethrough Yes Yes Yes Yes Yes
Footnotes Yes Configurable Yes Yes Yes
YAML metadata Context-dependent Front matter Yes Properties Context-dependent
Math Yes Requires setup Yes Yes Yes
Mermaid Yes Requires setup Output-dependent Yes Yes
Citations No native bibliography Requires tooling Yes Plugin-dependent No native bibliography
Definition lists No Configurable Yes Limited Limited
Header attributes Limited Renderer-dependent Yes Limited Limited
Wiki links No No by default No by default Yes Wiki-dependent
Callouts or alerts GitHub syntax Theme or shortcode Template-dependent Obsidian syntax GitLab syntax
Raw HTML Sanitized or restricted Disabled by default Yes Context-dependent Sanitized or restricted

“Yes” still does not guarantee identical HTML or visual presentation. It means the environment recognizes the general feature.

Syntax That Is Usually Safe Everywhere

The safest portable subset includes:

  • ATX headings using #
  • Ordinary paragraphs
  • Blank lines between blocks
  • - for unordered lists
  • 1. for ordered lists
  • Fenced code blocks using backticks
  • Inline code using backticks
  • Emphasis using *text*
  • Strong emphasis using **text**
  • Ordinary links
  • Ordinary images
  • Block quotes
  • Thematic breaks
  • Explicit angle-bracket autolinks

An intentionally conservative document might look like this:

# Deployment Guide

This guide explains how to deploy the service.

## Requirements

- Docker
- Linux
- A supported GPU

## Configuration

Create a file named `compose.yaml`.

```yaml
services:
  application:
    image: example/application:1.0
```

For more information, see the [configuration reference](config.md).

> Back up existing data before upgrading.

This syntax travels well because it does not depend on tables, footnotes, attributes, callouts, or platform processing.

Syntax That Commonly Breaks

Portability problems tend to cluster around a small number of features.

Pipe Tables

Pipe tables are well supported by GFM-oriented tools, but not by strict CommonMark.

A table can degrade into unreadable text when passed through a parser that does not recognize it. For highly portable documents, consider short lists or semantic HTML generated during a build step.

Footnotes

Footnote syntax has become common, but it remains an extension.

Different tools may:

  • Support only one footnote format
  • Place footnotes differently
  • Generate different identifiers
  • Reject multi-paragraph footnotes
  • Render the source literally

Use footnotes when the publishing pipeline is known. Avoid depending on them in README files that must render across arbitrary systems.

Heading IDs and Attributes

This Pandoc syntax is not portable:

## Installation {#installation .procedure}

Use an ordinary heading and let the renderer generate its own anchor when portability matters.

Also avoid hard-coding links to auto-generated heading IDs unless every target uses the same slugification rules.

Callouts and Alerts

GitHub, Obsidian, GitLab, MkDocs, Docusaurus, and Hugo themes can all support callout-like blocks, but they often use different syntax.

A portable fallback is an ordinary block quote:

> Warning: Back up the database before upgrading.

It is less visually impressive, but it preserves meaning everywhere.

Wiki links are concise inside knowledge-management tools:

[[KV Cache]]

They are poor interchange syntax because the target path, file name, heading rules, and resolution behavior belong to the application.

Use standard Markdown links in content intended for publication:

[KV cache](kv-cache.md)

Raw HTML

Raw HTML is the usual escape hatch when Markdown cannot express a layout. It is also a common portability and security failure.

A renderer may:

  • Remove the HTML
  • Escape it
  • Sanitize selected elements
  • Allow blocks but not inline elements
  • Refuse Markdown parsing inside HTML
  • Pass it unchanged only in trusted mode

Use raw HTML only when the publishing target is controlled.

Mathematical Notation

Dollar-delimited math is popular but not universally interpreted.

The source:

The complexity is $O(n^2)$.

may become:

  • Rendered mathematics
  • Ordinary text with dollar signs
  • Incorrect emphasis
  • Input to a different math parser

Choose one math pipeline and test it in every target environment.

Mermaid and Other Diagram Blocks

A Mermaid code fence is syntactically safe because unsupported renderers normally display it as code.

The semantic result is still different. Readers may see a rendered architecture diagram on GitHub and raw Mermaid source in another environment.

This is graceful degradation, not true compatibility.

The Three Layers of Markdown Compatibility

It helps to separate compatibility into three layers.

Layer 1: Parsing Compatibility

Does the parser recognize the structure?

Examples include headings, tables, footnotes, and fenced divisions.

Layer 2: Transformation Compatibility

Does the platform apply additional processing?

Examples include:

  • Rendering Mermaid
  • Resolving citations
  • Expanding wiki links
  • Linking issue numbers
  • Processing shortcodes
  • Generating a table of contents

Layer 3: Presentation Compatibility

Does the result look and behave appropriately?

Examples include:

  • Table styling
  • Syntax highlighting
  • Alert colors
  • Heading anchors
  • Responsive images
  • Footnote placement
  • Math fonts

Two platforms can parse identical syntax while producing substantially different presentation.

A Better Portability Model

Instead of asking whether a file is “valid Markdown,” ask four narrower questions:

  1. Which dialect is the source written in?
  2. Which parser reads it?
  3. Which extensions are enabled?
  4. Which platform transformations run afterward?

For example:

Dialect: CommonMark plus GFM tables
Parser: Goldmark
Extensions: tables, strikethrough, task lists, footnotes
Platform: Hugo
Additional processing: render hooks and Mermaid JavaScript

That description is much more useful than saying “the site uses Markdown.”

Choosing a Dialect by Use Case

README Files

Use GFM.

README files benefit from:

  • Tables
  • Task lists
  • Fenced code
  • Autolinks
  • Strikethrough
  • GitHub references

Avoid excessive dependence on GitHub-only features when the repository is mirrored to GitLab, rendered on a package registry, or included in generated documentation.

Hugo Technical Articles

Use CommonMark-compatible Markdown with a documented Goldmark extension set.

Tables, code fences, footnotes, and Mermaid can be reasonable because you control the build pipeline. Prefer Hugo shortcodes or render hooks over embedding large amounts of raw HTML.

Keep Hugo-specific syntax isolated and easy to find.

Academic Documents

Use Pandoc Markdown.

Citations, bibliography processing, footnotes, metadata, mathematical notation, cross-references, and conversion to PDF or DOCX justify the reduced portability.

Store the Pandoc command, defaults file, filters, bibliography, and templates beside the source. The source file alone does not fully describe the build.

Books and Long-Form Documentation

Pandoc Markdown is usually the strongest of the three options when multiple output formats matter.

Definition lists, citations, attributes, metadata, and structured transformations become more important as document complexity grows.

For web-only documentation hosted in a Git repository, GFM or a CommonMark-based documentation generator may remain simpler.

Notes and Personal Knowledge Bases

Use the native syntax of the selected notes application when application features provide real value.

Obsidian wiki links, embeds, and callouts are useful inside a vault. Treat export as a compilation process rather than assuming the raw files are already portable publications.

Shared Documentation Across Unknown Systems

Use a conservative CommonMark subset.

Avoid:

  • Wiki links
  • Platform alerts
  • Header attributes
  • Citations
  • Raw HTML
  • Custom containers
  • Application embeds
  • Shortcodes

Portability usually requires giving up convenience features.

Practical Rules for Portable Markdown

Start with CommonMark Structure

Use CommonMark for the document skeleton:

  • Headings
  • Paragraphs
  • Lists
  • Links
  • Images
  • Block quotes
  • Code blocks

This ensures that the main meaning survives even when optional extensions fail.

Add GFM Features Deliberately

Tables and task lists are reasonable when all important targets support them.

Do not assume “most tools support GFM” without testing the exact target. Some claim GFM compatibility while enabling only selected extensions.

Isolate Platform Extensions

Keep platform-specific syntax in clearly identifiable blocks.

For example, centralize Hugo shortcodes, Pandoc citations, or Obsidian embeds rather than scattering them through every paragraph.

Isolation makes later conversion easier.

Prefer Graceful Degradation

A Mermaid block degrades into readable source code. A GitHub alert degrades into a block quote.

A wiki embed may degrade into an unexplained file name, while a Pandoc fenced division may expose punctuation around the content.

Choose extensions whose fallback remains understandable.

Do Not Depend on Auto-Generated Heading IDs

Heading anchor algorithms differ between GitHub, Hugo, Pandoc, and documentation generators.

For cross-document links, use renderer-supported explicit IDs only when the target pipeline is controlled. Otherwise, link to the document rather than a generated fragment.

Keep Build Configuration with the Content

Pandoc extensions, Hugo settings, plugins, filters, and JavaScript integrations determine how Markdown behaves.

Commit relevant configuration files with the source:

content/
  article.md
pandoc.yaml
references.bib
config/
  _default/
    markup.yaml
layouts/
  _default/
    _markup/

A .md extension alone does not capture the publishing environment. For a structured approach to documenting these decisions, see Decision Records for AI-Driven Development.

Test Markdown Against Every Important Target

Visual preview in one editor is not enough. The editor may support a richer dialect than the production renderer.

For Pandoc, test explicit input formats:

pandoc --from=commonmark article.md -o commonmark.html
pandoc --from=gfm article.md -o gfm.html
pandoc --from=markdown article.md -o pandoc.html

Warnings and visible source punctuation reveal which features are dialect-specific.

For Hugo, build the production site:

hugo --gc --minify

Then inspect the generated HTML rather than relying only on an editor preview.

For repositories, view the committed file on the actual hosting platform. Local Markdown extensions in VS Code may not match GitHub or GitLab.

Troubleshooting Common Rendering Mismatches

When a file that worked on one platform breaks on another, the failure usually falls into one of a handful of repeatable patterns. The table below lists the symptom as you would actually see it, the most likely cause, and a concrete command or check to confirm and fix it.

Symptom Likely cause Confirm and fix
A pipe table renders as one long paragraph with visible | characters Renderer is strict CommonMark without a tables extension Run pandoc --from=commonmark file.md -o test.html and inspect the output; either enable the tables extension or export with --from=gfm
[^note] stays inline as literal text instead of becoming a superscript footnote marker The footnote Goldmark extension is not enabled In Hugo, check for footnote under markup.goldmark.extensions in hugo.yaml, rebuild with hugo --gc --minify, and look for <sup> in the generated HTML
A ```mermaid fence shows as plain grey source code instead of a diagram The platform performs no post-processing on the fenced block GitHub renders it natively; Hugo needs a render hook, shortcode, or JS pipeline — check the built HTML for <pre><code class="language-mermaid"> versus an <svg>
## Heading {#id} shows the literal curly braces in the rendered heading text Header attribute syntax is Pandoc-specific, not CommonMark or GFM Remove the attribute syntax for portable output, or pre-convert with pandoc --from=markdown --to=gfm file.md -o out.md
[[Note Name]] displays as literal double square brackets Wiki link syntax is application-specific to tools like Obsidian Replace with a standard Markdown link, [Note Name](note-name.md), before exporting outside the vault
[@kwon2023pagedattention] stays as plain bracketed text instead of a formatted citation No bibliography or citeproc pass was applied Re-run with pandoc --citeproc --bibliography=refs.bib input.md -o output.pdf and confirm the CSL style is specified
> [!WARNING] renders as an ordinary quoted paragraph instead of a styled alert Alert styling is a GitHub.com platform feature, not part of formal GFM Expected outside GitHub; keep the wording readable as a plain block quote rather than depending on the color styling

This is the fastest first pass before assuming a Markdown “bug” — most of these mismatches are a missing extension or a platform-only feature, not broken syntax. For code-fence-specific issues such as missing syntax highlighting or unsupported language identifiers, see the dedicated guide on Markdown code blocks.

Lint the Portable Subset

A Markdown linter cannot guarantee renderer compatibility, but it can remove avoidable ambiguity.

Useful rules include:

  • Use consistent heading styles
  • Add blank lines around lists and code blocks
  • Use fenced rather than indented code
  • Specify code fence languages
  • Avoid skipped heading levels
  • Use consistent list markers
  • Avoid ambiguous emphasis around punctuation
  • Keep line endings consistent
  • Validate links and images

For multi-target publishing, add a build test for each important renderer rather than relying only on syntax linting.

Converting Between Dialects with Pandoc

Pandoc can normalize documents from one dialect to another:

pandoc \
  --from=markdown \
  --to=gfm \
  article.md \
  -o article-gfm.md

Or convert GFM into Pandoc Markdown:

pandoc \
  --from=gfm \
  --to=markdown \
  README.md \
  -o document.md

This is useful, but conversion is not guaranteed to preserve every feature.

Potential losses include:

  • Platform-specific references
  • Callout styling
  • Complex tables
  • Embedded application objects
  • Custom attributes
  • Raw HTML behavior
  • Plugin syntax
  • Diagram rendering
  • Exact whitespace and formatting

Pandoc preserves document structure better than original source formatting. Treat conversion as a build step, not a reversible text formatter.

For a Hugo technical blog, the most practical policy is:

  1. Use CommonMark for core prose and structure.
  2. Enable a small documented set of Goldmark extensions.
  3. Use GFM-style tables and task lists where they improve readability.
  4. Implement Mermaid through one consistent render hook or shortcode.
  5. Handle math through one documented KaTeX or MathJax pipeline.
  6. Use Hugo front matter only at the start of content files.
  7. Prefer render hooks and shortcodes over raw HTML.
  8. Keep source links as standard Markdown links where possible.
  9. Test migrated or externally sourced documents through Hugo.
  10. Document any syntax that will not render correctly on GitHub.

This approach accepts that Hugo content is not universally portable while keeping the portability boundary visible.

The worst approach is accidental dialect mixing: GitHub alerts, Obsidian embeds, Pandoc attributes, and Hugo shortcodes placed in the same document without a defined build pipeline.

Decision Table

Use case Recommended syntax Reason
Portable plain-text document CommonMark Smallest reliable baseline
GitHub README GFM Tables, tasks, and repository workflows
GitHub issue template GFM plus GitHub features Platform is the intended target
Hugo blog post CommonMark plus configured Goldmark extensions Controlled publishing pipeline
Academic paper Pandoc Markdown Citations, math, metadata, PDF output
Multi-format book Pandoc Markdown Structured conversion to many outputs
Obsidian vault Obsidian Markdown Backlinks, embeds, and knowledge workflows
GitHub and GitLab mirror Conservative GFM Strong shared feature set
Unknown renderer CommonMark subset Lowest compatibility risk

Conclusion

CommonMark, GitHub Flavored Markdown, and Pandoc Markdown are not competing versions of the same product. They solve different problems.

CommonMark provides a dependable parsing foundation. GFM adds practical features for software collaboration, while Pandoc Markdown turns Markdown into a rich source language for publishing and conversion.

The safest rule is simple: write the smallest dialect that satisfies the real destination. Use CommonMark when content must travel, GFM when GitHub-style collaboration is the target, and Pandoc Markdown when document structure and output formats matter more than universal rendering.

Markdown portability is not achieved by avoiding every extension. It is achieved by knowing which extensions are part of the source contract and testing them in every renderer that matters.

References

Subscribe

Get new posts on AI systems, Infrastructure, and AI engineering.