Skip to content

Indices

Brett Terpstra edited this page Feb 2, 2026 · 3 revisions

Indices

Apex supports automatic index generation from index markers in your Markdown documents. Indices enable you to mark terms and concepts in your text and automatically generate a comprehensive index at the end of your document.

Overview

Supported modes: MultiMarkdown and unified (enabled by default)

Default behavior: Indices are automatically enabled in MultiMarkdown and unified modes. In other modes, use the --indices flag to enable them.

Index features:

  • Three syntaxes supported: mmark, TextIndex, and Leanpub
  • Automatic alphabetical sorting
  • Optional grouping by first letter
  • Hierarchical sub-items
  • Primary entries (bold entries in the index)
  • Automatic index generation at document end or custom marker

Syntax

Apex supports two index syntax formats:

mmark Index Syntax

The mmark syntax uses parentheses with exclamation marks to create index entries.

Basic index entry:

This is about protocols (!Protocol).

Sub-item entry:

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

The first term is the main entry, and the second term (after the comma) is the sub-item. Sub-items appear nested under their main entries in the generated index.

Primary entry (bold in index):

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

Using !! instead of ! marks the entry as a primary entry. Primary entries are typically rendered in bold in the generated index.

Multiple entries:

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

You can have multiple index entries in the same paragraph or sentence.

Examples:

The Hypertext Transfer Protocol (!HTTP) is widely used.

There are multiple versions (!HTTP, HTTP/1.0) and (!HTTP, HTTP/1.1).

Security protocols (!Protocol, Security) like TLS (!TLS) are essential.

TextIndex Syntax

TextIndex syntax uses curly braces with a caret ({^}) to mark index entries.

Basic syntax (indexes preceding word):

Most mechanical keyboard firmware{^} supports key combinations.

The {^} marks the word immediately before it for indexing. In this case, "firmware" will be indexed.

Explicit term:

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

Square brackets allow you to specify the exact term to index, which may differ from the visible text.

With parameters:

Term{^param1 param2}

Parameters can be included after the caret, though they are typically handled by the index generation system.

Examples:

Python{^} is a programming language.

We use [machine learning]{^ML} techniques.

The API{^Application Programming Interface} provides access.

Leanpub Index Syntax

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

Basic index entry:

Call me Ishmael{i: Ishmael}

Entries under headings (hierarchical):

Were Niagara{i: "Niagara!cataract"} but a cataract of sand{i: "Niagara!*sand*"}.

The Main!sub format places the sub-item under the main heading in the generated index. Formatting like *italics* and **bold** within the entry is stripped for the index display.

Sort form (for "Lastname, Firstname" or "something, the"):

Circumambulate the city of a dreamy Sabbath{i: "Sabbath, the"} afternoon.

Examples:

Call me Ishmael{i: Ishmael}

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

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

Index Generation

The index is automatically generated and placed in your document based on the following rules:

Automatic Placement

By default, the index is generated at the end of the document after all content.

Custom Placement

You can control where the index appears using the <!--INDEX--> marker or Leanpub's {index} marker:

# Document

This is about protocols (!Protocol).

<!--INDEX-->

More content after the index.

When the <!--INDEX--> marker is present, the index is inserted at that location instead of the end of the document.

Leanpub compatibility: Apex also accepts {index} as a placement marker (as used in Leanpub/Markua). The literal {index} is replaced with <!--INDEX--> during preprocessing, so it is always removed from the output—either replaced by the generated index or left as an invisible HTML comment when the index is suppressed. This matches Leanpub’s behavior where the index is placed at the marker (Leanpub moves it to the very end of the book regardless; in Apex the index appears at the marker position).

Command-Line Options

--indices

Enable index processing with both mmark and TextIndex syntax support.

Default: Enabled in MultiMarkdown and unified modes

Behavior:

  • Enables mmark syntax ((!item), (!item, subitem), (!!item, subitem)), TextIndex syntax ({^}, [term]{^}), and Leanpub syntax ({i: term}, {i: "Main!sub"})
  • Index entries are collected during parsing
  • Index is automatically generated at the end of the document or at <!--INDEX--> marker
  • Entries are sorted alphabetically and can be grouped by first letter

Example:

apex document.md --indices

When to use:

  • Enable indices in modes where they're disabled by default (commonmark, gfm, kramdown)
  • Explicitly enable indices when using unified or MultiMarkdown modes (optional, since enabled by default)

--no-indices

Disable index processing entirely.

Example:

apex document.md --no-indices

Behavior:

  • Index syntax is treated as plain text
  • No index markers are created in the document
  • No index section is generated
  • Useful when you want to preserve index syntax in the source but not process it

Note: When disabled, index syntax like (!item) and {^} will appear literally in your output.

--no-index

Suppress index generation while still creating index markers in the document.

Example:

apex document.md --no-index

Behavior:

  • Index markers (<span class="index" id="idxref:N">) are still created in the document
  • Index section is not generated at the end
  • Useful when you want to mark terms but generate the index separately or later

Use cases:

  • Marking terms for future index generation
  • Generating index separately with different options
  • Using external tools to build the index from the markers

Configuration

Metadata Options

Index behavior can be controlled via document metadata or a configuration file.

Enable/disable indices:

---
indices: true  # or false
---

Suppress index generation:

---
suppress-index: true  # Generate markers but not the index section
---

Group by letter:

---
group-index-by-letter: true  # Group entries alphabetically by first letter
---

When group-index-by-letter is enabled, the index groups entries under letter headings (A, B, C, etc.), making it easier to navigate longer indices.

Complete example:

---
indices: true
group-index-by-letter: true
---

Configuration File

You can also set these options in your global config.yml file:

---
indices: true
group-index-by-letter: true
---

This applies the settings to all documents unless overridden by document metadata or command-line flags.

Examples

Basic Index Example

Input:

# Network Protocols

The Hypertext Transfer Protocol (!HTTP) is the foundation of the web.

There are several versions including (!HTTP, HTTP/1.0) and (!HTTP, HTTP/1.1).

Secure communication uses (!TLS) for encryption.

Output with --indices:

<h1>Network Protocols</h1>
<p>The Hypertext Transfer Protocol <span class="index" id="idxref:0"></span> is the foundation of the web.</p>
<p>There are several versions including <span class="index" id="idxref:1"></span> and <span class="index" id="idxref:2"></span>.</p>
<p>Secure communication uses <span class="index" id="idxref:3"></span> for encryption.</p>

<h1 id="index-section">Index</h1>
<div class="index">
<ul>
<li>HTTP
  <ul>
  <li>HTTP/1.0</li>
  <li>HTTP/1.1</li>
  </ul>
</li>
<li>TLS</li>
</ul>
</div>

TextIndex Example

Input:

Python{^} is a versatile language.

We use [machine learning]{^ML} for data analysis.

The API{^Application Programming Interface} allows programmatic access.

Output: The index will include entries for "Python", "machine learning" (or "ML" if using parameters), and "API" (or "Application Programming Interface" based on the syntax used).

Index with Custom Placement

Input:

# Introduction

This document covers networking (!Networking).

# Main Content

More content about protocols (!Protocol).

<!--INDEX-->

# Appendix

Additional information goes here.

Output: The index appears between the main content and the appendix section, not at the very end of the document.

Primary Entries Example

Input:

The main topic is (!!Networking).

Subtopics include (!Networking, TCP) and (!Networking, UDP).

Output: The index entry "Networking" will be marked as primary (typically bold), with "TCP" and "UDP" as sub-items.

Output Format

Index entries in the document are marked with <span class="index" id="idxref:N"> elements. These markers:

  • Are invisible in the rendered output
  • Link back from the index entries to their locations in the text
  • Use sequential IDs (idxref:0, idxref:1, etc.)

The generated index section includes:

  • A heading (<h1 id="index-section">Index</h1>)
  • A <div class="index"> container
  • A nested <ul> structure for main entries and sub-items
  • Links from each index entry back to its location in the document

When group-index-by-letter is enabled, entries are organized under letter headings for easier navigation.

Tips and Best Practices

  1. Consistency: Use the same term consistently for similar concepts (e.g., always use (!HTTP) rather than mixing (!HTTP) and (!Hypertext Transfer Protocol)).

  2. Hierarchy: Use sub-items to create logical hierarchies (e.g., (!Protocol, HTTP) groups HTTP under Protocol).

  3. Primary entries: Use !! for main topics or key concepts that should stand out in the index.

  4. Placement: Use <!--INDEX--> to place the index where it makes sense for your document structure (e.g., before appendices but after main content).

  5. Testing: Use --no-index when developing to see where markers are placed without generating the full index each time.

Related

Quick Links

Clone this wiki locally