Skip to content
Brett Terpstra edited this page Feb 18, 2026 · 25 revisions

Syntax Reference

This page documents all syntax features available in unified mode. For mode-specific syntax, see Modes.

Basic Markdown

Headers

ATX-style headers:

# H1
## H2
### H3
#### H4
##### H5
###### H6

Setext-style headers:

H1 Alternative
==============

H2 Alternative
--------------

Multi-line setext headers (MMD 6): Setext headers can span multiple lines before the underline. This is supported in unified and MultiMarkdown modes:

This is
a multi-line
setext header
========

Another
header
with
multiple
lines
--------

Emphasis

*italic*
_italic_
**bold**
__bold__
***bold italic***
___bold italic___

Strikethrough

GFM-style strikethrough uses paired tildes:

~~strikethrough text~~

This renders as <del>strikethrough text</del> in HTML. Strikethrough is enabled by default in GFM and unified modes. In other modes, use --strikethrough to enable it, or --no-strikethrough to disable it in GFM or unified mode.

Note: When using --proofreader, ~~text~~ is converted to CriticMarkup deletion syntax ({--text--}) before strikethrough processing.

Superscript and Subscript

MultiMarkdown-style superscript and subscript syntax:

H~2~O          # H₂O (subscript - tildes within word)
m^2             # m² (superscript)
x^2 + y^2       # x² + y²
H~2~SO~4~       # H₂SO₄ (multiple subscripts within word)
~h2o~           # <u>h2o</u> (underline - tildes at word boundaries)

Syntax rules:

  • The ^ character creates superscript for the text immediately following it. The superscript stops at the first space, punctuation, or newline.
  • The ~ character creates subscript when used within a word/identifier with paired tildes (e.g., H~2~O). The subscript ends at the second tilde.
  • When tildes are at word boundaries (e.g., ~text~), they create underline instead of subscript. This prevents interference with underline/strikethrough syntax.

Examples:

Water: H~2~O           # H₂O (subscript - tildes within word)
Area: m^2              # m² (superscript)
Formula: E = mc^2      # E = mc² (superscript)
Chemical: H~2~SO~4~    # H₂SO₄ (multiple subscripts within word)
~h2o~                  # <u>h2o</u> (underline - tildes at word boundaries)

This feature is enabled by default in MultiMarkdown and unified modes. In other modes, use the --sup-sub flag to enable it. Use --no-sup-sub to disable it in unified or MultiMarkdown modes.

Lists

Unordered:

- Item 1
- Item 2
  - Nested item
  - Another nested
- Item 3

Ordered:

1. First item
2. Second item
   1. Nested item
   2. Another nested
3. Third item

Mixed Markers (Unified & MultiMarkdown modes): In unified and MultiMarkdown modes, you can mix different list marker types at the same indentation level. The list will inherit the type from the first item:

1. First numbered item
* Second item (becomes numbered)
* Third item (becomes numbered)

* First bullet item
1. Second item (becomes bullet)
2. Third item (becomes bullet)

By default, CommonMark and GFM modes create separate lists when marker types change. Use --mixed-lists to enable this behavior in other modes, or --no-mixed-lists to disable it in unified/MultiMarkdown modes.

Alpha Lists (Unified mode): In unified mode, you can use alphabetic markers for ordered lists:

a. First item
b. Second item
c. Third item

A. First item (uppercase)
B. Second item (uppercase)
C. Third item (uppercase)

Alpha lists are automatically converted to HTML with style="list-style-type: lower-alpha" or style="list-style-type: upper-alpha". This feature is enabled by default in unified mode. Use --alpha-lists to enable in other modes, or --no-alpha-lists to disable in unified mode.

Task Lists:

- [ ] Todo item
- [x] Completed item
- [ ] Another todo

Links and Images

Standard Markdown links:

[Link text](https://example.com)
[Link with title](https://example.com "Title")

Link titles with different quote styles (MMD 6): Link and image titles can use single quotes, double quotes, or parentheses. This is supported in unified and MultiMarkdown modes:

[Link with double quotes](https://example.com "Title")
[Link with single quotes](https://example.com 'Title')
[Link with parentheses](https://example.com (Title))

Images:

![Alt text](image.png)
![Alt with title](image.png "Image title")

Image captions (figure / figcaption)

In unified and MultiMarkdown modes, Apex can wrap images in semantic <figure> elements with <figcaption> when caption text is available. Caption text is chosen as follows:

  1. caption="TEXT" attribute (IAL) — If present, this is always used as the figcaption and the image is wrapped in <figure>, even when image captions are otherwise disabled (see below).
  2. Title attribute — If the image has a title (e.g. "Image title" in the link), that becomes the caption when image captions are enabled.
  3. Alt text — If there is no title, alt text is used as the caption when image captions are enabled (unless --title-captions-only is set).

If both title and alt are empty and there is no caption="" attribute, the image is left as a plain <img> tag.

Example (unified / MultiMarkdown with image captions enabled):

Input:

![Alt only](photo.png)
![With title](figure.png "Figure caption")
![](plain.png)

Output:

<figure><img src="photo.png" alt="Alt only"><figcaption>Alt only</figcaption></figure>
<figure><img src="figure.png" alt="With title" title="Figure caption"><figcaption>Figure caption</figcaption></figure>
<img src="plain.png" alt="">

Explicit caption via IAL (caption=""):

You can set the figcaption explicitly with the caption attribute in an inline attribute list. This always produces <figure><figcaption>...</figcaption></figure> for that image, regardless of the --image-captions flag. The caption attribute is not emitted on the final <img> tag (it is used only for the figcaption).

![Screenshot](screen.png){caption="App window in dark mode"}
![Logo](logo.png){#logo caption="Company logo"}

Output (even with --no-image-captions):

<figure><img src="screen.png" alt="Screenshot"><figcaption>App window in dark mode</figcaption></figure>
<figure><img id="logo" src="logo.png" alt="Logo"><figcaption>Company logo</figcaption></figure>

Caption options:

Option Effect
--image-captions Enable wrapping images with title/alt in <figure> and <figcaption> (default in unified/MMD).
--no-image-captions Disable automatic captions from title/alt. Images with caption="" in IAL still get figures.
--title-captions-only Only add captions for images that have a title attribute; ignore alt for captions. Implies --image-captions. You do not need to pass both.
--no-title-captions-only Use title or alt for captions (default).
  • CLI: e.g. --no-image-captions, --title-captions-only
  • Metadata: image-captions: true|false, title-captions-only: true|false (or snake_case title_captions_only) in YAML/MMD metadata.

Image titles with different quote styles (MMD 6):

![Image](image.png "Double quote title")
![Image](image.png 'Single quote title')
![Image](image.png (Parentheses title))

Retina / @2x images (srcset):

In unified and MultiMarkdown modes, you can add @2x to image attributes to generate a srcset for retina displays. The 2x variant is assumed to have the same path with @2x inserted before the file extension (e.g. icon.pngicon@2x.png).

Inline:

![Alt](img/icon.png @2x)
![Alt](img/icon.png "title" @2x)
![Alt](img/icon.png @2x "title")

Reference-style:

![Logo][logo]

[logo]: img/hero.png @2x

With IAL: You can also use @2x in an inline attribute list after the image:

![Alt](img/icon.png){: @2x}
![Alt](img/icon.png){: .hero-logo @2x}

Output includes both src and srcset so browsers can choose the appropriate resolution:

<img src="img/icon.png" srcset="img/icon.png 1x, img/icon@2x.png 2x" alt="Alt">

Multi-format images (WebP, AVIF, auto, video): Apex supports additional attributes for modern image formats, automatic format discovery, and video URLs. See Multi-Format Images for full documentation.

Reference-style links and images: Reference-style links and images also support all three quote styles for titles:

[Link text][ref1]
![Image][img1]

[ref1]: https://example.com "Reference title"
[ref2]: https://example.com 'Reference title'
[ref3]: https://example.com (Reference title)

[img1]: image.png "Image title"
[img2]: image.png 'Image title'
[img3]: image.png (Image title)

Image attributes on reference definitions:

In unified, MultiMarkdown, and Kramdown modes, you can put attributes (e.g. width=250 height=83 or @2x) after the URL in an image reference definition. A space after the URL separates the URL from the attributes; the URL is not encoded, so query parameters (e.g. ?size=250x83) are preserved.

![Logo][logo]

[logo]: https://example.com/badge.png?size=250x83 width=250 height=83

These attributes are applied to every image that uses that reference, including images inside fenced divs (::: ... :::) and other markdown="1" regions.

URL handling (images and links):

  • URLs that contain a protocol (e.g. http://, https://) are not URL-encoded by Apex. Query parameters and special characters (e.g. ?, &, =) in such URLs are left as-is in the output.
  • In image syntax (inline or reference definition), a space after the URL starts the attribute list. So the URL is everything before the first space that is followed by an attribute (e.g. key=value or @2x). Use this to keep query strings intact while adding width, height, or other attributes.

Autolinks:

Apex can automatically convert URLs and email addresses into clickable links. Autolinking is enabled by default in GFM, MultiMarkdown, Kramdown, and unified modes. It is disabled by default in CommonMark mode.

Angle-bracket autolinks:

<https://example.com>
<http://example.com>
<mailto:user@example.com>

Bare URL autolinks:

Visit https://example.com for more info.
Check out http://example.com too.

Email autolinks:

Contact me@example.com for details.
Send to user@example.com.

Important notes:

  • Autolinks are not processed inside code spans (`code`) or code blocks ( ```)
  • Use --autolink to enable autolinking in modes where it's disabled by default
  • Use --no-autolink to disable autolinking in modes where it's enabled by default
  • Angle-bracket autolinks (<url>) are converted to standard Markdown links during preprocessing
  • Bare URLs and email addresses are also converted to Markdown links during preprocessing

Code

Inline code:

Use `code` in text.

Fenced code blocks:

```python
def hello():
    print("Hello, World!")
```

Indented code blocks:

    def hello():
        print("Hello, World!")

Syntax highlighting:

Apex supports external syntax highlighting via the --code-highlight flag. When enabled, fenced code blocks are processed by external tools (Pygments or Skylighting) to produce colorized HTML output.

Usage:

apex document.md --code-highlight pygments
apex document.md --code-highlight skylighting

Features:

  • Language-aware highlighting based on code block language specifiers
  • Auto-detection when no language is specified
  • Line numbers support with --code-line-numbers flag
  • Automatic CSS inclusion in standalone mode (GitHub-style theme)
  • Supports both Pygments and Skylighting class names

When processed with --code-highlight pygments, the code block is sent to Pygments (pygmentize) and replaced with highlighted HTML containing syntax classes. --code-highlight skylighting uses skylighting instead.

Note: Only fenced code blocks (with triple backticks) are highlighted. Indented code blocks are not processed by external highlighters.

Blockquotes

> This is a quote.
> It can span multiple lines.
>
> > Nested quotes are supported.

Lists and definition lists in blockquotes:

Blockquotes can contain lists and definition lists:

> 1. First item
> 2. Second item
>
> - Unordered item
> - Another item
>
> Term
> : Definition

Nested blockquotes also support these features:

> > Nested quote
> > 1. List item
> > Term
> > : Definition

Horizontal Rules

---
***
___

Tables

Apex supports comprehensive table syntax including standard pipe tables, CSV/TSV tables, and advanced features. For complete table documentation, see Tables.

Quick Reference

  • Standard pipe tables with column alignment (:---, :---:, ---:)
  • Relaxed tables (no separator row required in unified/kramdown modes)
  • Headerless tables with alignment rows
  • Row header columns (first column as row header)
  • Inline CSV/TSV tables from fenced code blocks or <!--TABLE--> markers
  • Column spans using empty cells or << marker
  • Row spans using ^^ marker
  • Table footers using === separator rows
  • Individual cell alignment using colons (:Left, Center:, :Center:)
  • Table captions in multiple formats ([Caption], Table: Caption, : Caption)
  • Inline Attribute Lists (IALs) for adding IDs, classes, and custom attributes to tables

Basic Example

| Header 1 | Header 2 | Header 3 |
| -------- | :------: | -------: |
| Left     |  Center  |    Right |
| Data     |   Data   |     Data |

Column alignment: :--- (left, default), :---: (center), ---: (right).

For detailed documentation of all advanced table features including rowspan, colspan, per-cell alignment, captions, IALs, and other advanced syntax, see Tables.

Footnotes

Reference Style

Here's a footnote[^1] and another[^note].

[^1]: First footnote content.
[^note]: Second footnote with custom ID.

Inline Style (Kramdown)

This is a footnote^[inline content here].

Inline Style (MultiMarkdown)

This is a footnote[^inline content with spaces].

Definition Lists

Term
: Definition text with **Markdown** support

Apple
: A fruit
: A company

Term with multiple definitions
: First definition
: Second definition

Definition lists in blockquotes:

Definition lists work inside blockquotes, including nested blockquotes:

> Term 1
> : Definition 1
> Term 2
> : Definition 2

> > Nested blockquote
> > Term
> > : Definition

This allows you to create quoted definitions and maintain proper nesting structure.

Citations

Note: Citations are supported in MultiMarkdown and unified modes. A bibliography file must be provided via --bibliography flag or document metadata.

Pandoc Citation Syntax

Basic citation:

See [@doe99] for details.

Multiple citations:

See [@doe99; @smith2000; @smith2004] for more information.

Author in text:

@smith04 says blah.

Author suppressed:

Smith says blah [-@smith04].

With locator:

@smith04 [p. 33] says blah.

MultiMarkdown Citation Syntax

Basic citation:

This is a statement[#Doe:2006].

With locator:

This is a statement[p. 23][#Doe:2006].

Inline citation:

As per Doe.[#John Doe. *A Totally Fake Book 1*. Vanity Press, 2006.]

mmark Citation Syntax

Basic citation:

This references [@RFC2535].

Normative citation:

This references [@!RFC1034] (normative).

Multiple citations:

Multiple citations: [@RFC1034;@RFC1035].

Combined reference:

Combined reference: [@RFC1034@STD3].

Bibliography

Bibliography is automatically generated from cited entries and inserted at the <!-- REFERENCES --> marker or appended to the end of the document.

Bibliography marker:

## References

<!-- REFERENCES -->

Bibliography in metadata:

---
bibliography: references.bib
---

See [@doe99] for details.

Multiple bibliography files:

---
bibliography:
  - refs1.bib
  - refs2.bib
---

For complete documentation of citations and bibliography, see Citations.

Indices

Note: Indices are supported in MultiMarkdown and unified modes. Enabled by default in these modes.

mmark Index Syntax

Basic index entry:

This is about protocols (!Protocol).

Sub-item entry:

HTTP/1.1 (!HTTP, HTTP/1.1) is a protocol version.

Primary entry (bold in index):

This is a primary topic (!!Primary Topic, Sub Topic).

Multiple entries:

Protocols (!Protocol) and implementations (!Implementation) are important.

TextIndex Syntax

Basic syntax (indexes preceding word):

Most mechanical keyboard firmware{^} supports key combinations.

Explicit term:

This uses [key combinations]{^} for indexing.

With parameters:

Term{^param1 param2}

Leanpub Index Syntax

Leanpub (Markua) index syntax uses {i: term} to mark index entries. See the Leanpub index documentation.

Basic index entry:

Call me Ishmael{i: Ishmael}

Entries under headings (hierarchical):

Niagara{i: "Niagara!cataract"} is a waterfall.

Sort form:

Sabbath{i: "Sabbath, the"} afternoon.

Index Generation

The index is automatically generated at the end of the document or at the <!--INDEX--> marker if present:

# Document

This is about protocols (!Protocol).

<!--INDEX-->

More content after the index.

Index features:

  • Entries are sorted alphabetically
  • Can be grouped by first letter (default)
  • Sub-items are nested under main terms
  • Primary entries are marked (typically bold)
  • Each entry links back to its location in the document

Suppress index: Use --no-index to suppress index generation while still creating index markers.

Math

Inline math:

The equation $E = mc^2$ is famous.

Display math:

$$
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
$$

Math is wrapped in spans with appropriate classes for MathJax or KaTeX.

Wiki Links

Note: Wiki links are disabled by default in all modes. Use --wikilinks to enable.

Wiki links use double square brackets [[...]] to create links to other pages. They're converted to standard HTML <a> tags with URLs generated from the page name.

Syntax

[[Page Name]]                   # Link to page
[[Page Name|Display Text]]      # Custom display text
[[Page Name#Section]]           # Link to section
[[Page Name#Section|Display]]   # Custom display with section

Conversion Process

Wiki links are converted to HTML links through the following process:

  1. Page name extraction: The text between [[ and ]] is parsed
  2. Display text: If a pipe | is present, text after the pipe becomes the link text; otherwise, the page name is used
  3. Section anchor: If a hash # is present in the page name, it's extracted as a section anchor
  4. URL generation: The page name is converted to a URL based on configuration options:
    • Space handling: Spaces in page names are converted according to --wikilink-space mode (default: dash)
    • Extension: A file extension can be added via --wikilink-extension (default: none)

Space Handling Options

The --wikilink-space option controls how spaces in page names are converted:

  • dash (default): Spaces become dashes
    • [[Home Page]]href="Home-Page"
  • none: Spaces are removed
    • [[Home Page]]href="HomePage"
  • underscore: Spaces become underscores
    • [[Home Page]]href="Home_Page"
  • space: Spaces are kept (URL-encoded as %20)
    • [[Home Page]]href="Home%20Page"

File Extensions

The --wikilink-extension option adds a file extension to generated URLs:

  • --wikilink-extension htmlhref="Page.html"
  • --wikilink-extension mdhref="Page.md"
  • The dot is added automatically if not provided

Examples

Basic usage:

apex document.md --wikilinks

Input:

See [[Main Page]] for details.
Or visit [[Main Page|the main page]] with custom text.
Link to [[Main Page#Introduction]] for a specific section.

Output (default - dash mode, no extension):

<p>See <a href="Main-Page">Main Page</a> for details.</p>
<p>Or visit <a href="Main-Page">the main page</a> with custom text.</p>
<p>Link to <a href="Main-Page#Introduction">Main Page</a> for a specific section.</p>

With extension and space mode:

apex document.md --wikilinks --wikilink-space dash --wikilink-extension html

Input:

See [[Home Page]] for details.

Output:

<p>See <a href="Home-Page.html">Home Page</a> for details.</p>

With underscore mode:

apex document.md --wikilinks --wikilink-space underscore

Input:

See [[User Guide]] for help.

Output:

<p>See <a href="User_Guide">User Guide</a> for help.</p>

For complete option details, see Command Line Options.

Critic Markup

Track changes and annotations. Apex supports the standard CriticMarkup forms, and also provides a simple ++insert++ shorthand for HTML <ins> tags (see below).

{++addition++}              # Added text
{--deletion--}              # Deleted text
{~~old text~>new text~~}    # Substitution
{==highlighted==}           # Highlighted text
{>>comment text<<}         # Comment/annotation

In addition to the curly-brace CriticMarkup form for insertions, you can use a plain ++insert++ shorthand:

+insert++                   # Renders as <ins>insert</ins>
This is ++important++ text. # Inline insertion

Note: ++insert++ is a convenience syntax for <ins>…</ins> and is independent of CriticMarkup’s {++...++} form.

See Command Line Options for --accept and --reject modes.

Callouts

Bear/Obsidian/Xcode Playground syntax:

> [!NOTE] Title
> This is a note callout

> [!WARNING] Be Careful
> Warning content

> [!TIP] Pro Tip
> Helpful advice

> [!DANGER] Critical
> Dangerous operation

> [!INFO] Information
> Informational content

Collapsible callouts:

> [!NOTE]+ Expandable
> Defaults to open

> [!NOTE]- Collapsed
> Defaults to closed

File Includes

Marked syntax:

<<[file.md]      # Include and process Markdown
<<(code.py)      # Include as code block
<<{raw.html}     # Include raw HTML

MultiMarkdown transclusion:

{{file.md}}      # Include file
{{file.*}}       # Prefer file.html, file.md, file.txt, file.tex (in that order)
{{*.md}}         # Glob include (first matching .md file)
{{c?de.py}}      # ? wildcard (e.g. resolves to code.py)

{{file.*}} implements MultiMarkdown-style wildcard resolution, trying common extensions in a preferred order. Patterns containing *, ?, [], or {} are treated as glob patterns and resolved relative to the current transclude base (see metadata transclude base).

iA Writer syntax:

/image.png       # Intelligent include (detects type)
/code.py         # Auto-detects as code block
/document.md     # Auto-detects as Markdown

CSV and TSV files automatically convert to tables.

Address Syntax for File Includes

File includes support mmark-style address syntax to include specific line ranges or sections. This works with {{file}} and <<[file], <<(file), <<{file} syntaxes, but not with iA Writer /file syntax.

Line number ranges:

{{file.md}}[3,5]        # Include lines 3 to 5 (exclusive of 5)
{{file.md}}[3,]         # Include from line 3 to end of file
<<[file.md][1,10]       # Include lines 1 to 10 in Marked syntax
<<(code.py)[5,15]       # Include lines 5 to 15 in code block

Regular expression ranges:

{{file.md}}[/START/,/END/]     # Include lines between regex matches
{{file.md}}[/^## /,/^## /]     # Include between heading markers
<<[file.md][/function/,/^}/]   # Include from function to closing brace

Prefix option:

{{file.md}}[3,5;prefix="C: "]   # Prefix each line with "C: "
{{code.py}}[1,10;prefix="  "]  # Indent included lines

Combined examples:

# Include lines 10-20 with prefix
{{example.py}}[10,20;prefix="    "]

# Include from regex match to end
{{config.md}}[/^## Config/,]

# Include between patterns with prefix
{{script.sh}}[/# START/,/# END/;prefix="# "]

Notes:

  • Line numbers are 1-based
  • End line is exclusive (e.g., [3,5] includes lines 3 and 4, not 5)
  • Regex patterns use POSIX extended regular expressions
  • If start pattern is not found, empty content is returned
  • If end pattern is not found, content from start to end of file is included
  • Prefix is applied to each included line

Address Syntax for File Includes

Apex supports mmark-style address syntax for specifying line ranges and applying prefixes to included files. This works with {{file}} and <<[file] syntaxes (but not iA Writer /file syntax).

Line number ranges:

{{file.md}}[3,5]      # Include lines 3 to 5 (exclusive of 5)
{{file.md}}[3,]       # Include from line 3 to end of file
<<[file.md][1,10]     # Include lines 1 to 10
<<(code.py)[5,15]     # Include lines 5 to 15 from code file

Regular expression ranges:

{{file.md}}[/START/,/END/]           # Include lines between regex matches
{{file.md}}[/^## Section/,/^## /]     # Include from section to next section
<<[file.md][/BEGIN/,/END/]            # Include between BEGIN and END markers

Prefix option:

{{file.md}}[3,5;prefix="C: "]         # Prefix each line with "C: "
{{file.md}}[prefix="> "]              # Prefix all lines with "> "
<<(code.py)[1,10;prefix="    "]      # Prefix with 4 spaces (indentation)

Combined examples:

{{config.py}}[/def setup/,/^def /;prefix="# "]
# Includes lines from "def setup" to next "def", with "# " prefix

<<[readme.md][10,20;prefix="> "]
# Includes lines 10-20 with blockquote prefix

Notes:

  • Line numbers are 1-based
  • End line is exclusive (e.g., [3,5] includes lines 3 and 4, not 5)
  • Regex patterns use POSIX extended regular expressions
  • Prefix is applied to each included line
  • Address syntax does not apply to iA Writer syntax (/file)

Metadata

YAML Front Matter

---
title: My Document
author: John Doe
date: 2025-12-06
---

MultiMarkdown Metadata

Title: My Document
Author: John Doe
Date: 2025-12-06

Pandoc Title Block

% My Document
% John Doe
% 2025-12-06

Metadata Variables

Use [%key] to insert metadata values anywhere:

---
title: Apex Guide
version: 0.1.0
---

# [%title]

Version: [%version]

You can also transform metadata values using the [%key:transform] syntax. See Metadata Transforms for a complete guide to available transforms.

External Metadata Sources:

Metadata can also be loaded from external files or specified on the command line:

  • --meta-file FILE: Load metadata from an external file (YAML, MMD, or Pandoc format, auto-detected)
  • --meta KEY=VALUE: Set metadata from the command line (supports multiple flags and comma-separated pairs)

Metadata precedence (highest to lowest):

  1. Command-line metadata (--meta)
  2. Document metadata (in the document)
  3. File metadata (--meta-file)

Reusable Metadata Files:

You can create reusable metadata files for common settings like language and quotes language. This is especially useful for maintaining consistent settings across multiple documents.

Example metadata file (lang-fr.yml):

---
language: fr
quoteslanguage: french
---

Note: In YAML, keys with spaces must be quoted (e.g., "Quotes Language": french). Since Apex normalizes metadata keys (removes spaces, case-insensitive), you can use keys without spaces for cleaner YAML syntax. Both quoteslanguage and "Quotes Language" will work.

Example metadata file (lang-de.mmd):

Language: de
Quotes Language: german

Note: MultiMarkdown format allows spaces in keys, so Quotes Language works without quotes.

Usage:

# Use French language settings for all documents
apex document1.md --meta-file lang-fr.yml
apex document2.md --meta-file lang-fr.yml

Benefits:

  • Consistency: Ensure all documents use the same language settings
  • Reusability: Define language and quotes language once, use across many documents
  • Maintainability: Update language settings in one place
  • Automatic fallback: If Quotes Language is not specified, it automatically uses the language value

Controlling Command-Line Options via Metadata:

Most command-line options can be controlled via metadata, allowing per-document configuration. Boolean options accept true/false, yes/no, or 1/0 (case-insensitive). String options use the value directly.

Example:

---
indices: false
wikilinks: true
bibliography: references.bib
title: My Research Paper
pretty: true
standalone: true
---

This enables batch processing where each file can have its own configuration. See Command Line Options for complete documentation of metadata options and which options can be controlled via metadata.

Abbreviations

Classic MMD syntax:

*[HTML]: Hypertext Markup Language
*[CSS]: Cascading Style Sheets

HTML and CSS are essential.

MMD 6 reference syntax:

[>MMD]: MultiMarkdown

Using [>MMD] here and [>MMD] again.

MMD 6 inline syntax:

This is [>(MD) Markdown] and [>(CSS) Cascading Style Sheets].

Inline Attribute Lists (IAL)

Kramdown and Pandoc syntax for adding HTML attributes (IDs, classes, and custom key-value pairs) to Markdown elements.

Apex supports both Kramdown-style IALs ({: ...}) and Pandoc-style IALs ({#id .class}). Both formats work identically throughout the document.

Block-level IALs appear on the line immediately after the element:

# Header
{: #custom-id}

# Another Header
{#custom-id-2 .highlight}

Paragraph with class.
{: .important}

## Another Header
{: #section-2 .highlight title="Section Title" lang="en"}

Inline IALs appear immediately after the element within the paragraph:

Here's a [styled link](url){:.button} with a class.

Here's a [Pandoc-style link](url){#link-id .button} with attributes.

This has **bold text**{:.bold-style} and *italic text*{:.italic-style}.

Key-value pairs allow custom attributes:

Paragraph.
{: title="Important Note" lang="en" data-custom="value"}

[Link](url){:rel="nofollow" target="_blank"}

Attribute List Definitions (ALDs) define reusable attribute sets:

# Header 1
{:my-style}

# Header 2
{:my-style}

{:my-style: #section-title .important .highlight lang="en"}

ALD references can be combined with additional attributes in the same IAL. Additional attributes override or extend the ALD:

{:base-style: #main .class1 .class2}

# Heading 1
{:base-style}

# Heading 2
{:base-style .class3}

# Heading 3
{:base-style #override-id}

# Heading 4
{:base-style .class3 rel="nofollow"}

Behavior:

  • Classes: Additional classes are appended to the ALD classes
  • IDs: If an ID is specified in the IAL, it overrides the ALD's ID
  • Key-value attributes: If a key exists in both ALD and IAL, the IAL value overrides the ALD value

For complete documentation with examples, see Inline Attribute Lists.

Table of Contents

Multiple marker formats:

<!--TOC-->              # Basic TOC
<!--TOC max2 min1-->    # With depth control
{{TOC}}                 # MMD style
{{TOC:2-4}}            # With range
{:toc}                  # Kramdown IAL marker (uses same TOC engine)

Headings with the .no_toc class are excluded from the generated TOC:

# Contents
{:.no_toc}

{:toc}

Smart Typography

Automatic conversion:

  • "text""text" (smart quotes)
  • 'text''text' (smart apostrophes)
  • -- (en dash)
  • --- (em dash)
  • ... (ellipsis)
  • <<« (left guillemet)
  • >>» (right guillemet)

GitHub Emoji

Success! :rocket: :tada: :sparkles:
I :heart: Markdown!

Supports 350+ GitHub emoji, converted to Unicode characters.

Special Markers

Page breaks:

<!--BREAK-->            # HTML comment style
{::pagebreak /}         # Kramdown style

Autoscroll pauses:

<!--PAUSE:5-->          # Pause for 5 seconds

End-of-block marker:

- Item 1

^

- Item 2

Forces list separation.

HTML

Raw HTML is supported (when unsafe option is enabled, which is default):

<div class="custom">
  <p>This is raw HTML inside Markdown.</p>
</div>

Markdown Inside HTML Blocks

By default, Markdown inside HTML blocks is not parsed unless the HTML block contains blank lines. This follows the CommonMark specification:

  • HTML blocks without blank lines: Content is treated as raw HTML and Markdown is not parsed

    <div>**This is not bold**</div>

    Output: <div>**This is not bold**</div>

  • HTML blocks with blank lines: Content can be parsed as Markdown

    <div>
    
    **This is bold**
    
    </div>

    Output: <div><p><strong>This is bold</strong></p></div>

To explicitly enable Markdown parsing inside HTML blocks, use the markdown attribute (GFM extension):

<div markdown="1">
## This is a heading
- List item
</div>

The markdown attribute accepts:

  • markdown="1" or markdown="block" - Parse block-level Markdown
  • markdown="span" - Parse inline Markdown only

Pandoc Fenced Divs

Apex supports Pandoc's fenced divs extension, which allows you to create HTML <div> elements with attributes using a special fence syntax. This feature is available in unified mode only and is enabled by default.

Basic syntax:

::::: {#special .sidebar}
Here is a paragraph.

And another.
:::::

Opening fences:

  • Must contain at least 3 consecutive colons (:::)
  • Must have attributes (ID, classes, or custom attributes)
  • Attributes can optionally be followed by another string of consecutive colons

Closing fences:

  • Must contain at least 3 consecutive colons (:::)
  • No attributes needed
  • Number of colons doesn't need to match the opening fence

Attributes: Attributes use the same syntax as fenced code blocks:

  • {#id} - ID attribute
  • {.class} - Class attribute (can have multiple)
  • key="value" - Custom attributes with quoted values
  • key='value' - Custom attributes with single quotes
  • Single unbraced word is treated as a class name

Examples:

::: {#mydiv .container}
Content here
:::

::: sidebar
Single unbraced word becomes a class
:::

::::: {#special .warning .important key="value"}
Div with ID, multiple classes, and custom attribute
:::::

::::: {#special .sidebar} ::::
Trailing colons after attributes are allowed
::::::::::::::::::

Nested divs: Fenced divs can be nested. Opening fences must have attributes:

::: Warning ::::::
This is a warning.

::: Danger
This is a warning within a warning.
:::
::::::::::::::::::

Block types: By default, fenced divs create <div> elements. You can specify different HTML block elements using the >blocktype syntax:

::: >aside {.sidebar}
This creates an <aside> element instead of a <div>.
:::

::: >article {#post .main}
This creates an <article> element.
:::

::: >section {.container}
This creates a <section> element.
:::

Common block types:

  • >div - Default, creates a <div> element
  • >aside - Creates an <aside> element (sidebars, callouts)
  • >article - Creates an <article> element (main content)
  • >section - Creates a <section> element (document sections)
  • >details - Creates a <details> element (collapsible content)
  • >summary - Creates a <summary> element (for use inside <details>)

Nested block types: You can nest different block types:

::: >details {.warning} :::
:::: >summary
This is a summary
::::
This is the content of the details block
:::

::: >section {.outer}
Outer section content.

::: >aside {.inner}
Inner aside content.
:::

More outer content.
:::

Block type with unbraced class: The block type syntax works with unbraced class names:

::: >aside Warning :::
Warning content here
:::

This creates <aside class="Warning">...</aside>.

Note: Fenced divs should be separated by blank lines from preceding and following blocks for best results.

Control:

  • Use --divs to explicitly enable (default in unified mode)
  • Use --no-divs to disable fenced divs processing

Related

  • Modes - Which syntax is available in each mode
  • Header IDs - Automatic header ID generation
  • Command Line Options - Feature flags including --[no-]autolink, --[no-]mixed-lists, --[no-]alpha-lists, --[no-]sup-sub, and --[no-]divs

Quick Links

Clone this wiki locally