Apex is a unified Markdown processor that combines the best features from CommonMark, GitHub Flavored Markdown (GFM), MultiMarkdown, Kramdown, and Marked. One processor to rule them all.
There are so many variations of Markdown, extending its features in all kinds of ways. But picking one flavor means giving up the features of another flavor. So I’m building Apex with the goal of making all of the most popular features of various processors available in one tool.
Callouts: Bear/Obsidian-style callouts with collapsible support (> [!NOTE], > [!WARNING], etc.)
GitHub emoji: 350+ emoji support (:rocket:, :heart:, etc.)
Document Features
Metadata blocks: YAML front matter, MultiMarkdown metadata, and Pandoc title blocks
Metadata variables: Insert metadata values with [%key] syntax
Metadata transforms: Transform metadata values with [%key:transform] syntax - supports case conversion, string manipulation, regex replacement, date formatting, and more. See Metadata Transforms for complete documentation
Metadata control of options: Control command-line options via metadata - set boolean flags (indices: false, wikilinks: true) and string options (bibliography: refs.bib, title: My Document) directly in document metadata for per-document configuration
Table of Contents: Automatic TOC generation with depth control (<!--TOC-->, ``)
File includes: Three syntaxes (Marked <<[file], MultiMarkdown ``, iA Writer /file)
CSV/TSV support: Automatic table conversion from CSV and TSV files
Custom styling: Link external CSS files in standalone mode
Pretty-print: Formatted HTML with proper indentation for readability
Header ID generation: Automatic or manual header IDs with multiple format options (GFM, MMD, Kramdown)
Header anchors: Option to generate <a> anchor tags instead of header IDs
Advanced Features
Hard breaks: Option to treat newlines as hard line breaks
Feature toggles: Granular control to enable/disable specific features (tables, footnotes, math, smart typography, etc.)
Unsafe HTML: Option to allow or block raw HTML in documents
Autolinks: Automatic URL detection and linking
Superscript/Subscript: Support for ^superscript^ and ~subscript~ syntax
Installation
Homebrew (macOS/Linux)
brew tap ttscoff/thelab
brew install ttscoff/thelab/apex
Building from Source
git clone https://github.com/ttscoff/apex.git
cd apex
git submodule update --init--recursive
make
The apex binary will be in the build/ directory.
To install the built binary and libraries system-wide:
make install
Note: The default make command runs both cmake -S . -B build (to configure the project) and cmake --build build (to compile). If you prefer to run cmake commands directly, you can use those instead.
Pre-built Binaries
Download pre-built binaries from the latest release. Binaries are available for:
macOS (Universal binary for arm64 and x86_64)
Linux (x86_64 and arm64)
Basic Usage
Command Line
# Process a markdown file
apex input.md
# Output to a file
apex input.md -o output.html
# Generate standalone HTML document
apex input.md --standalone--title"My Document"# Pretty-print HTML output
apex input.md --pretty
Processing Modes
Apex supports multiple compatibility modes:
--mode commonmark - Pure CommonMark specification
--mode gfm - GitHub Flavored Markdown
--mode mmd or --mode multimarkdown - MultiMarkdown compatibility
--mode kramdown - Kramdown compatibility
--mode unified - All features enabled (default)
# Use GFM mode
apex input.md --mode gfm
# Use Kramdown mode with relaxed tables
apex input.md --mode kramdown
Common Options
--pretty - Pretty-print HTML with indentation
--standalone - Generate complete HTML document with <html>, <head>, <body>
--style FILE - Link to CSS file in document head (requires --standalone)
--title TITLE - Document title (requires --standalone)
--relaxed-tables - Enable relaxed table parsing (default in unified/kramdown modes)
--id-format FORMAT - Header ID format: gfm, mmd, or kramdown
--no-ids - Disable automatic header ID generation
--header-anchors - Generate <a> anchor tags instead of header IDs
--bibliography FILE - Bibliography file (BibTeX, CSL JSON, or CSL YAML) - can be used multiple times
--csl FILE - Citation style file (CSL format)
--link-citations - Link citations to bibliography entries
--indices - Enable index processing (mmark and TextIndex syntax)
--no-indices - Disable index processing
--no-index - Suppress index generation (markers still created)
All Options
Apex Markdown Processor v0.1.25
One Markdown processor to rule them all
Usage: build/apex [options] [file]
Options:
--accept Accept all Critic Markup changes (apply edits)
--[no-]includes Enable file inclusion (enabled by default in unified mode)
--hardbreaks Treat newlines as hard breaks
-h, --help Show this help message
--header-anchors Generate <a> anchor tags instead of header IDs
--id-format FORMAT Header ID format: gfm (default), mmd, or kramdown
(modes auto-set format; use this to override in unified mode)
--[no-]alpha-lists Support alpha list markers (a., b., c. and A., B., C.)
--[no-]mixed-lists Allow mixed list markers at same level (inherit type from first item)
-m, --mode MODE Processor mode: commonmark, gfm, mmd, kramdown, unified (default)
--meta-file FILE Load metadata from external file (YAML, MMD, or Pandoc format)
--meta KEY=VALUE Set metadata key-value pair (can be used multiple times, supports quotes and comma-separated pairs)
--no-footnotes Disable footnote support
--no-ids Disable automatic header ID generation
--no-math Disable math support
--no-smart Disable smart typography
--no-tables Disable table support
-o, --output FILE Write output to FILE instead of stdout
--pretty Pretty-print HTML with indentation and whitespace
--[no-]autolink Enable autolinking of URLs and email addresses
--obfuscate-emails Obfuscate email links/text using HTML entities
--[no-]relaxed-tables Enable relaxed table parsing (no separator rows required)
--[no-]sup-sub Enable MultiMarkdown-style superscript (^text^) and subscript (~text~) syntax
--[no-]transforms Enable metadata variable transforms [%key:transform] (enabled by default in unified mode)
--[no-]unsafe Allow raw HTML in output (default: true for unified/mmd/kramdown, false for commonmark/gfm)
--[no-]wikilinks Enable wiki link syntax [[PageName]] (disabled by default)
--embed-images Embed local images as base64 data URLs in HTML output
--base-dir DIR Base directory for resolving relative paths (for images, includes, wiki links)
--bibliography FILE Bibliography file (BibTeX, CSL JSON, or CSL YAML) - can be used multiple times
--csl FILE Citation style file (CSL format)
--indices Enable index processing (mmark and TextIndex syntax)
--no-indices Disable index processing
--no-index Suppress index generation (markers still created)
--no-bibliography Suppress bibliography output
--link-citations Link citations to bibliography entries
--show-tooltips Show tooltips on citations
--reject Reject all Critic Markup changes (revert edits)
-s, --standalone Generate complete HTML document (with <html>, <head>, <body>)
--css FILE, --style FILE Link to CSS file in document head (requires --standalone, overrides CSS metadata)
--title TITLE Document title (requires --standalone, default: "Document")
-v, --version Show version information
If no file is specified, reads from stdin.
Per-Document Configuration via Metadata
Most command-line options can be controlled via document metadata, allowing different files to be processed with different settings when processing batches. Boolean options accept true/false, yes/no, or 1/0 (case-insensitive). String options use the value directly.
Example:
---indices:falsewikilinks:truebibliography:references.bibtitle:My Research Paperpretty:truestandalone:true---
This allows you to process multiple files with apex *.md and have each file use its own configuration. You can also use --meta-file to specify a shared configuration file that applies to all processed files.
Add citation processing with support for Pandoc, MultiMarkdown, and mmark syntaxes
Add bibliography loading from BibTeX, CSL JSON, and CSL YAML formats
Add –bibliography CLI option to specify bibliography files (can be used multiple times)
Add –csl CLI option to specify citation style file
Add –no-bibliography CLI option to suppress bibliography output
Add –link-citations CLI option to link citations to bibliography entries
Add –show-tooltips CLI option for citation tooltips
Add bibliography generation and insertion at marker
Add support for bibliography specified in document metadata
Improved
Only process citations when bibliography is actually provided for better performance
Fixed
Raw HTML tags and comments are now preserved in definition lists by default in unified mode. Previously, HTML content in definition list definitions was being replaced with “raw HTML omitted” even when using –unsafe or in unified mode.
Unified mode now explicitly sets unsafe=true by default to ensure raw HTML is allowed.
Prevent autolinking of @ symbols in citation syntax (e.g., [@key])
Handle HTML comments in autolinker to preserve citation placeholders
Add –embed-images flag to embed local images as base64 data URLs in HTML output
Add –base-dir flag to set base directory for resolving relative paths (images, includes, wiki links)
Add automatic base directory detection from input file directory when reading from file
Add base64 encoding utility for image data
Add MIME type detection from file extensions (supports jpg, png, gif, webp, svg, bmp, ico)
Add image embedding function that processes HTML and replaces local image src attributes with data URLs
Add test suite for image embedding functionality
Improved
Wiki link scanner now processes all links in a text node in a single pass instead of recursively processing one at a time, significantly improving performance for documents with multiple wiki links per text node.
Added early-exit optimization to skip wiki link AST traversal entirely when no wiki link markers are present in the document.
Improve error handling in transform execution to return original value instead of NULL on failure
Add comprehensive test coverage for all transforms including edge cases
Relative path resolution for images now uses base_directory option
Base directory is automatically set from input file location when not specified
Fixed
Fix bracket handling in regex patterns - properly match closing brackets in [%…] syntax when patterns contain brackets
Fix YAML metadata parsing to strip quotes from quoted string values
Raw HTML tags and comments are now preserved in definition lists by default in unified mode. Previously, HTML content in definition list definitions was being replaced with “raw HTML omitted” even when using –unsafe or in unified mode.
Unified mode now explicitly sets unsafe=true by default to ensure raw HTML is allowed.
Added man page generation and installation support. Man pages can be generated from Markdown source using pandoc or go-md2man, with pre-generated man pages included in the repository as fallback. CMake build system now handles man page installation, and Homebrew formula installs the man page.
Added comprehensive test suite for MMD 6 features including multi-line setext headers and link/image titles with different quote styles (single quotes, double quotes, parentheses). Tests verify these features work in both MultiMarkdown and unified modes.
Added build-test man_page_copy target for man page installation.
Added –obfuscate-emails flag to hex-encode mailto links.
IMPROVED
Superscript processing now stops at sentence terminators (. , ; : ! ?) instead of including them in the superscript content. This prevents punctuation from being incorrectly included in superscripts.
Enhanced subscript and underline detection logic. The processor now correctly differentiates between subscript (tildes within a word, e.g., H~2~O) and underline (tildes at word boundaries, e.g., ~text~) by checking if tildes are within alphanumeric words or at word boundaries.
Expanded test coverage for superscript, subscript, underline, strikethrough, and highlight features with additional edge case tests.
HTML comments now replaced with “raw HTML omitted” in CommonMark and GFM modes by default
Added enable_sup_sub flag to apex_options struct
Updated mode configurations to enable sup/sub in appropriate modes
Added sup_sub.c to CMakeLists.txt build configuration
Removed unused variables to resolve compiler warnings
Tag filter (GFM security feature) now only applies in GFM mode, not Unified mode, allowing raw HTML and autolinks in Unified mode as intended.
Autolink extension registration now respects the enable_autolink option flag.
NEW
Added MultiMarkdown-style superscript (^text^) and subscript (~text~) syntax support
Added –[no-]sup-sub command-line option to enable/disable superscript/subscript
Superscript/subscript enabled by default in unified and MultiMarkdown modes
Created sup_sub extension (sup_sub.c and sup_sub.h) for processing ^ and ~ syntax
Added –[no-]unsafe command-line option to control raw HTML handling
Added test_sup_sub() function with 13 tests covering superscript and
Added test_mixed_lists() function with 10 tests covering mixed list
Added test_unsafe_mode() function with 8 tests covering raw HTML
Added preprocessing for angle-bracket autolinks (http://...) to convert them to explicit markdown links, ensuring they work correctly with custom rendering paths.
Added –[no-]autolink CLI option to control automatic linking of URLs and email addresses. Autolinking is enabled by default in GFM, MultiMarkdown, Kramdown, and unified modes, and disabled in CommonMark mode.
Added enable_autolink field to apex_options structure to control autolink behavior programmatically.
Added underline syntax support: ~text~ now renders as text when there’s a closing ~ with no space before it.
IMPROVED
Test suite now includes 36 additional tests, increasing total test
Autolink preprocessing now skips processing inside code spans (...) and code blocks (...), preventing URLs from being converted to links when they appear in code examples.
Metadata replacement retains HTML edge-case handling and properly cleans up intermediate buffers.
FIXED
Unified mode now correctly enables mixed list markers and alpha lists by default when no –mode is specified
^ marker now properly separates lists by creating a paragraph break instead of just blank lines
Empty paragraphs created by ^ marker are now removed from final HTML output
Superscript and subscript processing now skips ^ and ~ characters
Superscript processing now skips ^ when part of footnote reference
Subscript processing now skips ~ when part of critic markup patterns
Setext headers are no longer broken when followed by highlight syntax (==text==). Highlight processing now stops at line breaks to prevent interference with header parsing.
Metadata parser no longer incorrectly treats URLs and angle-bracket autolinks as metadata. Lines containing < or URLs (http://, https://, mailto:) are now skipped during metadata extraction.
Superscript/subscript processor now correctly differentiates between ~text~ (underline), ~word (subscript), and ~~text~~ (strikethrough). Double-tilde sequences are skipped so strikethrough extension can handle them.
Subscript processing now stops at sentence terminators (. , ; : ! ?) instead of including them in the subscript content.
Metadata variable replacement now runs before autolinking so [%key] values containing URLs are turned into links when autolinking is enabled.
MMD metadata parsing no longer incorrectly rejects entries with URL values; only URL-like keys or ‘<’ characters in keys are rejected, allowing “URL: https://example.com” as valid metadata.
Headers starting with # are now correctly recognized instead of being treated as autolinks. The autolink preprocessor now skips # at the start of a line when followed by whitespace.
Math processor now validates that \(...\) sequences contain actual math content (letters, numbers, or operators) before processing them. This prevents false positives like \(%\) from being treated as math when they only contain special characters.
Core Features:
- Initial release of Apex unified Markdown processor
- Based on cmark-gfm for CommonMark + GFM support
- Support for 5 processor modes: CommonMark, GFM, MultiMarkdown, Kramdown, Unified
Metadata:
- YAML front matter parsing
- MultiMarkdown metadata format
- Pandoc title block format
- Metadata variable replacement with [%key] syntax
Build System:
- CMake build system for cross-platform support
- Builds shared library, static library, CLI binary, and macOS framework
- Clean compilation on macOS with Apple Clang
CLI Tool:
- apex command-line binary
- Support for all processor modes via --mode flag
- Stdin/stdout support for Unix pipes
- Comprehensive help and version information
Integration:
- Objective-C wrapper (NSString+Apex) for Marked integration
- macOS framework with proper exports
- Detailed integration documentation and examples
Testing:
- Automated test suite with 31 tests
- 90% pass rate across all feature areas
- Manual testing validated
Documentation:
- Comprehensive user guide
- Complete API reference
- Architecture documentation
- Integration guides
- Code examples
Known Issues
Critic Markup substitutions have edge cases with certain inputs