Extensions
Extensions let you transform the corpus of extracted symbols before any generator runs. A typical use case is rewriting metadata across many symbols at once: backfilling briefs from a naming convention, tagging symbols by group, or marking generated code as "see below" in the output.
Extensions are user-supplied scripts written in JavaScript or Lua. They run between extraction (turning C++ source into a corpus of symbols) and rendering (turning the corpus into output files), so any change they make is visible to every generator.
File layout
Drop a script into the extensions/ subdirectory of an addon root and Mr.Docs picks it up automatically:
<addons>/extensions/*.js
<addons>/extensions/*.lua
The same addons and addons-supplemental configuration options that govern templates apply here too: scripts under every existing addon root are discovered.
Scripts are loaded in alphabetical order by full path, with the two languages interleaved. This means renaming a script changes the order in which it runs, but switching the language does not.
The transform_corpus hook
A script extends Mr.Docs by exposing a function named transform_corpus(corpus).
Mr.Docs calls it once with a flat read-only view of the corpus.
The script inspects symbols and calls mutation functions on the pre-registered mrdocs object to apply changes.
A script that does not define transform_corpus is silently ignored, so an extension file can be empty during development without breaking the build.
// <addons>/extensions/rebrief.js
function transform_corpus(corpus) {
for (var i = 0; i < corpus.symbols.length; ++i) {
var sym = corpus.symbols[i];
if (sym.kind === "function") {
mrdocs.set_brief(sym.id, "Rewritten: " + sym.name);
}
}
}
-- <addons>/extensions/rebrief.lua
function transform_corpus(corpus)
local i = 0
while true do
local sym = corpus.symbols[i]
if sym == nil then break end
if sym.kind == "function" then
mrdocs.set_brief(
sym.id,
"Rewritten: " .. sym.name)
end
i = i + 1
end
end
The corpus argument
The corpus argument is a read-only object with a single field, symbols, which is an array of every symbol Mr.Docs extracted.
Each entry in corpus.symbols exposes the following fields:
| Field | Type | Description |
|---|---|---|
|
string |
Stable opaque identifier. Pass this back to a mutation function to identify which symbol to act on. |
|
string |
The symbol kind, in lowercase kebab-case. For example: |
|
string |
The unqualified symbol name. Empty for the global namespace. |
|
string |
The fully qualified name (for example, |
|
string |
The current brief as plain text, or the empty string if the symbol has no brief. |
In JavaScript, iterate with corpus.symbols.length and corpus.symbols[i], or with for (var s of corpus.symbols).
In Lua, iterate by integer index starting at 0; corpus.symbols[i] returns nil once you go past the last symbol, so a simple while loop terminates correctly.
The mrdocs API
Mutations go through the pre-registered mrdocs global.
The current set is intentionally narrow; new entries land as concrete use cases surface.
mrdocs.set_brief(symbol_id, text)
Replace the symbol’s brief with a single-paragraph plain-text block.
-
symbol_id: theidvalue read from a symbol incorpus.symbols. -
text: the new brief text. The argument is treated as plain text; no markdown parsing is performed.
Each setter validates its arguments and raises an error on misuse. An uncaught error inside an extension aborts the build with the script’s path and the error message.
Lifecycle
Extensions run between corpus finalization and the first generator invocation. The order is:
-
Mr.Docs walks the source files and extracts a corpus of symbols.
-
Built-in finalizers post-process the corpus (for example, sorting members and resolving inheritance).
-
Extensions run, in alphabetical order by full path.
-
The selected generator renders the (possibly mutated) corpus.
Because step 3 happens before step 4, an extension that mutates a symbol’s brief is visible to every output format, not just one.