m.css already turns Doxygen's XML into far nicer HTML than Doxygen's own output, with a great live search. Poxy sits in front of both: it drives Doxygen with a locked-down configuration, repairs and normalises the XML, then post-processes the HTML. The result is more consistent across Doxygen versions and has a number of features neither tool provides alone.
- Configuration
- Version-proofing the XML
- Appearance and HTML
- Authoring conveniences
- Cross-referencing
- Extras
Poxy is configured with a poxy.toml instead of a Doxyfile.
- Most of Doxygen's knobs are set by poxy and not exposed. This is deliberate: Doxygen tends to break between releases, so keeping it locked down limits the damage and keeps debugging on the python side.
- The config file is self-contained (no Doxyfile-style
@INCLUDEhierarchy). - All relative input paths are resolved relative to the config file, not the working directory.
- Output always goes to
<cwd>/htmland<cwd>/xml. You choose the location by choosing where you run poxy, not through the config. - C++ feature-test macros (the
__cpp_*family) are defined automatically for the target language version, so conditional code documents correctly without a hand-maintained macro list. - Source, image and example directories can be recursive or shallow on a per-directory basis.
A core goal of poxy is to be a man-in-the-middle between Doxygen and m.css, ironing out the differences between Doxygen versions so the same input produces the same output. Poxy reformats the XML consistently from one release to the next, and applies a set of targeted fixes:
- removes
dir_*.xmlentries for directories that contain no input files - removes empty
file_*.xmlentries that exist only to describe a documentation-only file (e.g. a.doxfile). The file's content still appears in the docs; only the useless "Files" listing goes away. - strips local filesystem paths out of generated tagfiles (they serve no purpose and leak directory layout)
- removes duplicate
<memberdef>tags that some Doxygen versions emit when using groups - merges class-member
@namegroups that share a name, so you do not have to rearrange code to make Doxygen behave - sorts
@namegroups,<memberdef>tags, and inner class / namespace / group references alphabetically. Non-static data members are left in declaration order. - adds the missing
inline="yes"attribute to namespaces listed ininline_namespaces - stops Doxygen folding non-type keywords such as
friendandstaticinto a function's return type - repairs the many cases where Doxygen mangles trailing return types (
auto f() -> T) - folds a markdown list's first item back into the list when it shared a line with a block command
(e.g.
@see - @ref afollowed by more items), which Doxygen otherwise leaves stranded as loose text - normalises section titles and C++20 concept definitions so m.css renders them correctly
It can also merge the documentation of private "implementation" headers into their public counterpart;
see implementation_headers.
- A switchable light theme in addition to m.css's dark one.
- Better C++ syntax highlighting in code blocks: poxy re-highlights with Pygments and additionally colours types, namespaces, macros and other tokens that the base highlighter misses.
- Function signatures render qualifiers such as
constexpr,noexceptandvirtualas distinct labels. - Support for C++20 concepts.
- A top-level page listing every
#define, so macros are discoverable without hunting through file docs. - Undocumented parents of documented symbols (and the values of documented enums) are kept rather than pruned, so the tree stays navigable.
- SVGs are inlined, so they can take advantage of
currentColorand follow the active theme. - Fonts are self-hosted, so a built site makes no external font requests.
- Configured
#includeprefixes can be stripped from the include line shown on each page. - Tabbed content blocks for showing, for example, one snippet in several languages.
- Images in page content open full-size in an overlay when clicked; see
lightbox. - Video embeds via
@youtube, sized and lazily loaded. - Embedded iframe pages for hosting an external report (coverage, benchmarks, hand-written HTML) inside the docs without leaving them.
- A set of extra Doxygen @alias commands: language code-block shortcuts, coloured note boxes, field decorators, link helpers and more.
- Square-bracket tags for reliable inline control of the generated HTML (CSS classes, wrappers, ids, entities, emoji) where Doxygen's raw HTML support falls short.
- Emoji by name, via
[emoji name].
- The cppreference.com tagfile is bundled and integrated automatically, so references to the standard library link to cppreference without any setup.
autolinksadds your own regex-to-URL hotlinking on top of what Doxygen and tagfiles resolve.- Markdown headings get stable anchors derived from their text and namespaced per page. Doxygen
otherwise numbers them
autotoc_md<N>from a counter global to the whole run, so adding one page silently renumbers the anchors on every other page and breaks every deep link into them. An explicit{#label}on a heading is always honoured as written. - Explicit link requests to documented macros (
#SOME_MACRO) resolve everywhere, including markdown pages. Doxygen can only resolve a macro reference from inside a file scope, so from a page every spelling fails; poxy repairs these in the XML so they link like any other reference. - Poxy can emit a tagfile of your own project for others to link against; see
generate_tagfile.
- A blog can be built alongside the API documentation: markdown posts with TOML front matter,
a dated index, tags, drafts, per-post media, an RSS feed and a sitemap. Posts can
@refyour C++ symbols, which is most of the reason to keep the blog in the docs at all. - A git-tag-based semver version switcher can be added to the generated HTML (
--git-tags). - Built-in
navbar,badgesand sponsor / social links. --bug-reportcaptures all output in a zip file to make issues easier to report.