moxygen
Version:
Doxygen XML to Markdown converter
184 lines (139 loc) • 6.95 kB
Markdown
# Moxygen
[](https://github.com/sourcey/moxygen/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/moxygen)
[](https://nodejs.org)
[](https://github.com/sourcey/moxygen/blob/master/LICENCE)
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](https://github.com/sourcey/sourcey).
## Features
- **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](http://www.doxygen.nl/manual/grouping.html) support for organised docs
- **Grouped and ungrouped codebases** - works with explicit grouped compounds and normal namespace/class output
- **Modern C++ signatures** - class template parameters, default arguments, typedef aliases, friend declarations, `constexpr`/`consteval`, `[[nodiscard]]`, conditional `noexcept`, ref qualifiers, trailing returns, and `requires` clauses
- **Reference-depth sections** - source locations, examples, inherited members, all-member indexes, referenced-by links, and reimplementation relationships when present in the XML
- **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
## Install
```
npm install moxygen -g
```
Requires Node.js 20+.
## Usage
1. Add `GENERATE_XML=YES` to your `Doxyfile` (see [Icey's Doxyfile](https://github.com/nilstate/icey/blob/main/Doxyfile) for a real-world example)
2. Run `doxygen` to generate the XML documentation
3. Run `moxygen` pointing 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
```
## Grouping Modes
Moxygen supports both of the common Doxygen documentation styles:
1. Explicit grouped compounds.
- `@defgroup`, `@ingroup`, and related tags produce normal Doxygen group XML.
- Moxygen renders those groups directly.
- The root `api.md` page lists top-level groups before classes, and nested group pages list their child groups with breadcrumbs.
2. File-level grouped code.
- Some codebases group files with `@addtogroup` blocks or `@file` comments with `@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.
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.
## Examples
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 writes group files such as `api-mygroup.md` plus `api.md` for root-level globals and the top-level group/class index, unless `--noindex` is set.
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
```
Per-class output writes class files plus `api.md` for root-level globals and the class/namespace index, unless `--noindex` is set.
Java project:
```
moxygen --language java --anchors /path/to/doxygen/xml
```
## Custom Templates
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.
## Programmatic API
Two entry points: `run()` writes Markdown files to disk, `generate()` returns structured page objects for library consumers.
```typescript
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
}
```
## Development
```bash
npm install
npm run build
npm test
```
To test against the example:
```bash
npm run example
```
## More Information
For more details, visit [0state.com/moxygen](https://0state.com/moxygen).
## Licence
MIT