feat: support addon-defined Handlebars generators#1197
Conversation
This is a prerequisite for letting users add a Handlebars-based generator (e.g. a Markdown one) by dropping a template folder in an addon, without writing C++.
This moves `id`, `fileExtension`, and `displayName` from per-subclass virtual overrides to base-class members set through the constructor. That's a prerequisite for letting users add a Handlebars-based generator without writing C++.
The function was failing on `!file.good()` which includes the `eof()` case, so an empty file caused a failure. Test for "fail() but not just because we hit EOF", instead.
An <addon>/generator/<name>/ directory that ships at least one *.<name>.hbs layout is now installed as an additional `HandlebarsGenerator` at config-resolve time. An optional mrdocs-generator.yml next to the layouts supplies escape rules. This way, a generator can be added without writing any C++.
Generator lookup happened once at `TestRunner` construction. With addon-defined Handlebars generators now possible, a generator contributed via a test's `addons-supplemental` was unreachable from the test binary: the lookup ran before that test's mrdocs.yml had been loaded, so the generator wasn't yet registered. The runner now defers the lookup. The built-in generators are not affected.
|
| Scope | Lines Δ% | Lines Δ | Lines + | Lines - | Files Δ | Files + | Files ~ | Files ↔ | Files - |
|---|---|---|---|---|---|---|---|---|---|
| 🛠️ Source | 61% | 755 | 537 | 218 | 17 | 2 | 13 | - | 2 |
| 🧪 Unit Tests | 35% | 434 | 411 | 23 | 11 | 7 | 4 | - | - |
| 🏗️ Build | 3% | 38 | 38 | - | 1 | - | 1 | - | - |
| 📄 Docs | 1% | 10 | 3 | 7 | 1 | - | 1 | - | - |
| 🧰 Tooling | <1% | 1 | - | 1 | 1 | - | 1 | - | - |
| Total | 100% | 1238 | 989 | 249 | 31 | 9 | 20 | - | 2 |
Legend: Files + (added), Files ~ (modified), Files ↔ (renamed), Files - (removed)
🔝 Top Files
- src/test/lib/Gen/hbs/AddonGenerators.cpp (Unit Tests): 290 lines Δ (+290 / -0)
- src/lib/Gen/hbs/AddonGenerators.cpp (Source): 222 lines Δ (+222 / -0)
- src/lib/Gen/adoc/AdocEscape.cpp (Source): 100 lines Δ (+0 / -100)
97fc42c to
1d5651d
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #1197 +/- ##
========================================
Coverage 82.12% 82.12%
========================================
Files 33 33
Lines 3149 3149
Branches 734 734
========================================
Hits 2586 2586
Misses 387 387
Partials 176 176
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
An automated preview of the documentation is available at https://1197.mrdocs.prtest2.cppalliance.org/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-05-08 14:43:52 UTC |
This adds a fixture under test-files/template-only-generators/mock-md that ships its own mock "Markdown-like" generator via an addon-local `addons-supplemental`: a one-line layout that emits the symbol name, plus a single escape rule mapping `_` to `\_`.
1d5651d to
b08c8a0
Compare
|
Add a brief note about how this change was tested (or why tests are not needed). :) |
This adds support for Handlebars-based generators that don't involve any C++ code. <addon>/generator/<name>/ directories are picked up at config-resolve time and installed as additional generators; escape rules can be provided via <name>/mrdocs-generator.yml.
Adds support for addon-defined Handlebars generators: any
<addon>/generator/<name>/directory is picked up at config-resolve time and installed as a generator, with escape rules and other per-generator options described in<name>/mrdocs-generator.yml. New output formats can now be added entirely from configuration and template files, without touching the C++ generator infrastructure.To make this work cleanly the generator subsystem is made data-driven. Escape rules previously lived in a dedicated
AdocEscapesubclass; they now come from data, and the file is removed. Each output format used to have its ownHandlebarsGenerator/AdocGenerator/HTMLGeneratorsubclass; those classes are collapsed into thin wrappers over a shared data-driven implementation. The test runner was rearranged to match: generator lookup is deferred until the per-test settings load, since addon-defined generators now register dynamically rather than at static init.A small bug fix rides along:
getFileTextno longer fails on empty files.Changes
src/lib/Gen/hbs/AddonGenerators.{cpp,hpp}discovers and registers addon-defined generators at config-resolve time, wired intosrc/tool/GenerateAction.cpp.src/lib/Gen/adoc/AdocEscape.{cpp,hpp}removed; escape rules now come from data consumed by the existing generators.AdocGenerator,HTMLGenerator, andHandlebarsGeneratorreworked to read their options from data; the per-format subclass headers shrink correspondingly.src/lib/Support/Handlebars.cppand the publicinclude/mrdocs/Support/Handlebars.hppgain a small surface for the new flow.src/lib/ConfigOptions.jsonanddocs/mrdocs.schema.jsonupdated for the new config keys.src/lib/Support/Path.cppfix forgetFileTexton empty files.src/test/lib/Gen/hbs/AddonGenerators.cppunit test covers generator discovery and registration (290 lines).src/test/Support/TestLayout.{cpp,hpp}andsrc/test/TestRunner.{cpp,hpp}reworked to defer generator lookup until per-test settings load, so dynamically registered generators are visible to the runner. New end-to-end fixture undertest-files/template-only-generators/mock-md/ships a complete addon (addons/generator/mock-md/withmrdocs-generator.ymland Handlebars layouts) and asimple.mock-mdexpected output.CMakeLists.txtupdated to install the new sources and pick up the new test fixture (+38 lines).util/generate-config-info.pyafter a config-option rename.AdocGenerator,HTMLGenerator,HandlebarsGenerator) and the removedAdocEscapeare internal — downstream code that included those headers directly will need to use the shared data-driven entry points. TheConfigOptions.json/mrdocs.schema.jsonschema gains keys but removes none.Testing
src/test/lib/Gen/hbs/AddonGenerators.cppis the unit-level coverage for the new discovery/registration logic.test-files/template-only-generators/mock-md/is the end-to-end fixture: a complete addon-defined generator (template-only, no C++) wired together with anmrdocs-generator.ymland asimple.cppinput that producessimple.mock-md. Any regression in discovery or in the data-driven generator pipeline fails this fixture.src/test/andtest-files/jobs already run both the unit test and the end-to-end fixture on every build.Documentation
docs/mrdocs.schema.jsonupdated to reflect the newmrdocs-generator.ymlkeys.docs/modules/ROOT/pages/, since the feature now exists but the how-to docs that would help a contributor build their own generator are not in this PR.