Doxygen XML to Markdown converter. Doxygen's parser is solid; its HTML output looks like 1998. Every tool that tried to replace the parser (Standardese, hdoc, DoxyPress) stalled. The other option is a four-tool Breathe + Exhale + Sphinx pipeline. Moxygen takes a simpler approach: parse the XML, emit clean Markdown, let your docs tool handle the rest.
Used as the C++ documentation engine in Sourcey.
- Multi-language - C++ and Java supported out of the box
- Multi-page output - single file, per-group, per-class, or per-page
- Internal linking - anchors in comments and function definitions
- Markdown comments - Markdown in Doxygen comments is rendered
- Doxygen groups - grouping support for organised docs
- Grouped and ungrouped codebases - works with explicit grouped compounds and normal namespace/class output
- Structured landing pages - namespace and group pages separate nested namespaces, types, and enums
- Custom templates - modify the Handlebars templates to suit your needs
- Optional index - optionally render a top-level index
npm install moxygen -g
Requires Node.js 20+.
- Add
GENERATE_XML=YESto yourDoxyfile(see Icey's Doxyfile for a real-world example) - Run
doxygento generate the XML documentation - Run
moxygenpointing to the XML output directory
moxygen [options] <doxygen XML directory>
Options:
-V, --version output the version number
-o, --output <file> output file, must contain "%s" when using groups or classes
-g, --groups output doxygen groups into separate files
-c, --classes output doxygen classes into separate files
-p, --pages output doxygen pages into separate files
-n, --noindex disable generation of the index
-a, --anchors add anchors to internal links
-H, --html-anchors add HTML anchors to internal links
-l, --language <lang> programming language (default: cpp)
-t, --templates <dir> custom templates directory
-s, --source-root <dir>
source root used to resolve file-level group membership
when Doxygen group XML is sparse
-f, --frontmatter prepend YAML frontmatter to output files
-L, --logfile [file] output log messages to file (default: moxygen.log)
-q, --quiet quiet mode
-h, --help display help
Moxygen supports both of the common Doxygen documentation styles:
- Explicit grouped compounds.
@defgroup,@ingroup, and related tags produce normal Doxygen group XML.- Moxygen renders those groups directly.
- File-level grouped code.
- Some codebases group files with
@addtogroup/@ingroup, but Doxygen emits sparse group XML and leaves the real compound ownership in file XML. - Moxygen can recover those grouped classes, namespaces, and members when you pass
--source-root. - Shared umbrella namespaces across multiple groups are preserved without dropping group-owned root classes, and cross-page refs are resolved correctly for both markdown mirrors and generated multi-page output.
- Some codebases group files with
Use --source-root when your Doxygen XML is generated outside the source tree or when grouped output depends on file-level grouping comments:
moxygen --groups \
--source-root /path/to/project/src \
--output api-%s.md \
/path/to/doxygen/xml
If your XML already contains fully populated groups, --source-root is optional.
Single file output:
moxygen --anchors /path/to/doxygen/xml
Multi-file grouped output:
moxygen --anchors --groups --output api-%s.md /path/to/doxygen/xml
Grouped output recovered from file-level grouping comments:
moxygen --anchors --groups --source-root /path/to/project/src \
--output api-%s.md /path/to/doxygen/xml
Per-class files:
moxygen --classes --output api-%s.md /path/to/doxygen/xml
Java project:
moxygen --language java --anchors /path/to/doxygen/xml
Moxygen uses Handlebars templates for output. The default modern templates produce clean Markdown with code-block signatures and parameter tables.
To use the classic (pre-1.0) template style:
moxygen --templates ./templates/classic /path/to/xml
To create your own templates, copy the templates/cpp/ directory and modify. Templates receive the full parsed compound data including structured parameter info, inheritance, and more.
Two entry points: run() writes Markdown files to disk, generate() returns structured page objects for library consumers.
import { run, generate } from 'moxygen';
// Write files to disk (CLI equivalent)
await run({
directory: '/path/to/doxygen/xml',
output: 'api.md',
anchors: true,
});
await run({
directory: '/path/to/doxygen/xml',
output: 'api-%s.md',
groups: true,
sourceRoot: '/path/to/project/src',
});
// Library API - returns GeneratedPage[] (no disk I/O)
// This is what Sourcey uses internally
const pages = await generate({
directory: '/path/to/doxygen/xml',
language: 'cpp',
});
for (const page of pages) {
console.log(page.slug, page.title, page.kind);
console.log(page.markdown); // rendered markdown body
}npm install
npm run build
npm testTo test against the example:
npm run exampleFor more details, visit 0state.com/moxygen.
MIT