Skip to content

Commit 9c52013

Browse files
committed
docs: merge generators into the extensions page
The corpus-extensions page and the script-driven-generators page documented two halves of one feature: scripts under addons/extensions that declare transforms and generators through the `register_*` hooks. This folds the generator material into the extensions page, which now covers both hooks and the shared `ctx` object, and removes the separate page.
1 parent c331b3d commit 9c52013

4 files changed

Lines changed: 60 additions & 88 deletions

File tree

docs/modules/ROOT/nav.adoc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@
2323
** xref:generators/adoc.adoc[AsciiDoc]
2424
** xref:generators/xml.adoc[XML]
2525
* Extensions
26-
** xref:extensions/corpus-extensions.adoc[Corpus Extensions]
26+
** xref:extensions/corpus-extensions.adoc[Extensions]
2727
** xref:extensions/handlebars-extensions.adoc[Handlebars Extensions]
2828
** xref:extensions/data-driven-generators.adoc[Data-Driven Generators]
29-
** xref:extensions/script-driven-generators.adoc[Script-Driven Generators]
3029
** xref:extensions/antora.adoc[Antora Extensions]
3130
** xref:extensions/as-library.adoc[Mr.Docs as a Library]
3231
** xref:extensions/dom-reference.adoc[DOM Reference]

docs/modules/ROOT/pages/extensions/corpus-extensions.adoc

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1-
= Corpus Extensions
1+
= Extensions
22

3-
Use an extension to rewrite metadata across many symbols at once: backfill briefs from a naming convention, tag symbols by group, mark generated code as "see below" in the output. Extensions run between extraction and rendering, so every generator sees the change.
3+
An extension is a Lua or JavaScript script that runs as part of a Mr.Docs build and shapes the documentation in a way templates alone cannot. There are two kinds, and a single script may declare either or both:
4+
5+
* A *corpus transform* rewrites metadata across many symbols at once: backfill briefs from a naming convention, tag symbols by group, mark generated code as "see below" in the output. Transforms run between extraction and rendering, so every generator sees the change.
6+
* A *generator* owns the whole emit: instead of rendering one page per symbol, it traverses the corpus and writes whatever files it wants. That lets it produce shapes the per-page generators cannot, such as a single artifact aggregated across every symbol.
7+
8+
A script declares a transform with `register_transform(fn)` and a generator with `register_generator(id, fn)`. Either way the registered function receives a single context object, `ctx`.
49

510
== Languages and addon locations
611

@@ -14,9 +19,21 @@ Both scripting languages reach the same `mrdocs` API. The choice is a trade-off,
1419
* *Lua* is the language designed to be embedded. Mr.Docs links it whole, so scripts have access to the entire Lua standard library (`string`, `table`, `math`, `io`, `os`) and can do filesystem work or text munging without leaving the script. The cost is that fewer people read Lua at a glance than read JavaScript. If you're already familiar with Lua, it is the more powerful choice.
1520
====
1621

17-
== Accessing the corpus
22+
== The context object
23+
24+
Every registered function receives one argument, `ctx`:
25+
26+
* `ctx.corpus` is the corpus. Its `symbols` field is a flat array of every extracted symbol; what a script can do with those symbols depends on the kind of extension, described in the sections below.
27+
* `ctx.config` is the resolved configuration: the same object the templates receive, holding every value from the config file and the command line. See xref:configuration/reference.adoc[the configuration reference] for the available keys.
28+
29+
A generator's `ctx` carries one more field, `ctx.output`, covered under <<generators>>.
1830

19-
A script extends Mr.Docs by calling `register_transform(fn)` with a function that takes the corpus. Mr.Docs invokes each registered function once, in registration order, with a flat view of the corpus. A script can register several transforms, or none at all; if it registers nothing, Mr.Docs warns that the script had no effect and moves on.
31+
A script can register any number of transforms and generators, or none at all. If it registers nothing, Mr.Docs warns that the script had no effect and moves on.
32+
33+
[#corpus-transforms]
34+
== Corpus transforms
35+
36+
A transform is a function passed to `register_transform`. Mr.Docs invokes each registered function once, in registration order, with the `ctx` object. A flat view of the corpus reaches the script through `ctx.corpus`.
2037

2138
[tabs]
2239
======
@@ -37,7 +54,7 @@ include::example$snippets/extensions/entry-point/addons/extensions/noop.lua[]
3754
----
3855
======
3956

40-
The `corpus` object provides functions that expose the symbol graph. The `corpus.symbols` field is a flat array containing every extracted symbol. Scripts that need queries like "all members of `X`" simply walk the array and filter.
57+
The `ctx.corpus` object provides functions that expose the symbol graph. The `ctx.corpus.symbols` field is a flat array containing every extracted symbol. Scripts that need queries like "all members of `X`" simply walk the array and filter.
4158

4259
For instance, the following scripts count the symbols of each kind and report the totals at the end of the run:
4360

@@ -48,10 +65,10 @@ JavaScript::
4865
.`addons/extensions/count_by_kind.js`
4966
[source,javascript]
5067
----
51-
register_transform(function(corpus) {
68+
register_transform(function(ctx) {
5269
var counts = {};
53-
for (var i = 0; i < corpus.symbols.length; ++i) {
54-
var k = corpus.symbols[i].kind;
70+
for (var i = 0; i < ctx.corpus.symbols.length; ++i) {
71+
var k = ctx.corpus.symbols[i].kind;
5572
counts[k] = (counts[k] || 0) + 1;
5673
}
5774
for (var k in counts) {
@@ -65,9 +82,9 @@ Lua::
6582
.`addons/extensions/count_by_kind.lua`
6683
[source,lua]
6784
----
68-
register_transform(function(corpus)
85+
register_transform(function(ctx)
6986
local counts = {}
70-
for _, sym in ipairs(corpus.symbols) do
87+
for _, sym in ipairs(ctx.corpus.symbols) do
7188
counts[sym.kind] = (counts[sym.kind] or 0) + 1
7289
end
7390
for k, v in pairs(counts) do
@@ -77,12 +94,12 @@ end)
7794
----
7895
======
7996

80-
Each entry in `corpus.symbols` is a proxy for a live Mr.Docs symbol. The fields of each object are at xref:extensions/dom-reference.adoc[the DOM reference].
97+
Each entry in `ctx.corpus.symbols` is a proxy for a live Mr.Docs symbol. The fields of each object are at xref:extensions/dom-reference.adoc[the DOM reference].
8198

8299
When a script knows a symbol's id and needs to act on that one symbol:
83100

84-
* `corpus.get(id)` returns the proxy for it or `null` if the id is unknown
85-
* `corpus.lookup(name)` does a global-namespace name lookup and returns the proxy (or `null`)
101+
* `ctx.corpus.get(id)` returns the proxy for it or `null` if the id is unknown
102+
* `ctx.corpus.lookup(name)` does a global-namespace name lookup and returns the proxy (or `null`)
86103

87104
.`subclass-tree.cpp`
88105
[source,cpp]
@@ -122,7 +139,7 @@ Shape
122139
----
123140

124141
[[modifying-the-corpus]]
125-
== Modifying the corpus
142+
=== Modifying the corpus
126143

127144
Scripts modify the corpus by assigning to fields on a symbol proxy. Each assignment lands directly in the underlying Mr.Docs symbol. The runtime validates each assignment and raises an exception on an invalid value. An uncaught error in an extension aborts the build and includes the script's path and the error message.
128145

@@ -160,7 +177,7 @@ Every `is_foo_bar` function then ships with "Returns true if foo bar." Authors o
160177
include::example$snippets/extensions/brief-from-name/brief-from-name.adoc[tags=!footer]
161178
========
162179

163-
== Cross-linking Symbols
180+
=== Cross-linking Symbols
164181

165182
When the value being written needs to reference another symbol, the second symbol's `id` is what makes the link clickable in the rendered output rather than a plain string.
166183

@@ -203,3 +220,29 @@ The two-pass shape (index, then look up) is the idiom whenever a write needs to
203220
Notice in this example that `s.doc.sees` receives a list of polymorphic types that represent a paragraph in `s.doc.sees.children`. These polymorphic objects accept an object with a `kind:` selector that names the concrete derived class to construct.
204221
====
205222

223+
[[generators]]
224+
== Generators
225+
226+
The built-in generators render one page per symbol. When you need a different output structure, e.g. one file per namespace, or a single artifact aggregated across every symbol such as a search index, that page-per-symbol shape cannot express it. A generator hands the whole emit to the script instead: it traverses the corpus and writes whatever files it wants. No C++ and no templates are involved.
227+
228+
A script declares a generator with `register_generator(id, fn)`. The `id` is the name you select on the command line with `--generator=<id>`; a registered generator takes precedence over a built-in of the same name. Selecting a generator is a request for output, so its function does the work directly, the page-per-symbol fallback the built-ins provide does not apply.
229+
230+
The function receives the same `ctx` a transform does, plus `ctx.output`:
231+
232+
* `ctx.corpus.symbols` is the array of every symbol. Each carries the same fields the template and helper layers see, plus a flat `_id` string suitable as a stable per-symbol URL fragment. A generator reads the corpus rather than mutating it.
233+
* `ctx.config` is the resolved configuration, as above.
234+
* `ctx.output.write(relativePath, contents)` writes one file under the configured output directory, which is the path specified with `--output` on the command line, or with the `output` key in the config file; that's the same location the built-in generators write to. The path is resolved relative to that directory and may not escape it; an absolute path or one that climbs above the output directory is rejected. Parent directories are created as needed.
235+
236+
Because the script owns the output, it also owns what a per-page generator would otherwise do for it: the URLs it emits, and any escaping of the content it writes. Mr.Docs does not apply an escape map to a generator's output.
237+
238+
=== Example: a search index
239+
240+
A complete, runnable example lives at `examples/generators/script-driven/search-index/`. The extension declares a `search-index` generator that emits a single search-index.json aggregating every symbol, an artifact no per-page generator can produce:
241+
242+
.`addons/extensions/search_index.lua`
243+
[source,lua]
244+
----
245+
include::example$script-driven-generators/search-index/addons/extensions/search_index.lua[]
246+
----
247+
248+
Select it with `--generator=search-index`; it writes search-index.json into the output directory.

docs/modules/ROOT/pages/extensions/data-driven-generators.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,6 @@ include::example$data-driven-generators/tex/simple.tex[]
246246
----
247247
======
248248

249-
To build the output structure yourself, e.g. one file per namespace or a single aggregated artifact like a search index, hand the whole emit to a script instead of rendering one page per symbol. See xref:extensions/script-driven-generators.adoc[Script-driven generators].
249+
To build the output structure yourself, e.g. one file per namespace or a single aggregated artifact like a search index, hand the whole emit to a script instead of rendering one page per symbol. See the xref:extensions/corpus-extensions.adoc#generators[generators] section of the extensions page.
250250

251251

docs/modules/ROOT/pages/extensions/script-driven-generators.adoc

Lines changed: 0 additions & 70 deletions
This file was deleted.

0 commit comments

Comments
 (0)