develop
π Features
New features and additions
- β¨ Javascript helpers extension. (fix #881) 0f3ecb4
- π« Add function object support.1 (Auto-detection: records with only operator() overloads and special, Explicit: @functionobject or @functor doc commands on the variable or on, Closes #564.) 93a5032
- π Support corpus-mutation extensions in Lua and JavaScript.2 (reflection:
mrdocs.setdispatches on the normalized C++ member name,) ef2d2a0 - β¨ Make the reflection consumers public.3 e749144
- π« Uniform attribute extraction. (fix #1233) 8fe79f8
- π Declare output generators from extension scripts.4 (object:
ctx.corpusandctx.configfor a transform, and additionally) 2ea48a6 - β¨ Support HTML table tags in doc comments.5 (issue: issue #1146.) 9c7a140
- π« Data-drive generator inheritance. 9904239
- π Support script-driven generators.6 ff8bb85
- β¨ Per-generator options. 3ab3a90
- π« Add MRDOCS_DESCRIBE_KINDS for class hierarchies.7 bbbe336
- π Move template specializations and deduction guides off parent scope page.8 (issue: issue #1154.) 0d693e2
- β¨ Multi-generator workflow.9 25f4f75
- π« Support data-driven Handlebars generators.10 47db0f5
- π @implementationdefined and @seebelow as commands. 313f10e
- β¨ Expose per-extension parameters as ctx.params.11 197e765
- π« Add $meta.type and $meta.bases to all DOM objects.12 (issue: issue #1148.) c4dd89a
- π Mark and strikethrough inline markup. 78899e2
- extensions:
- lib:
- π handlebars: Support Lua scripts as Handlebars helpers.14 7a8f32c
- β¨ compilation-db: Cmake-build-dir option. (fix #762) 7f2a311
- π« support: MRDOCS_TRY_BIND for structured bindings. 1232a91
π Fixes
Bug fixes and error corrections
- Hide anchor links when wrapper is not included. d90eae6
- Replace the XML generator with a reflection-based one.15 d4a64ef
- Extract and fix some special member function helpers.16 0a69301
- Rendering of Markdown inline formatting and bullet lists (#1156).17 f35ebcd
- Don't pass sanitizer to dependency builds for UBSan/TSan.18 44c9f43
- Inherit base members from dependent template specializations.19 (issue: issue #1176.) 74bf1a3
- Symlink-tolerant path inclusion filter. (fix #1227) 3d254b6
- Nested types missing from tagfile. (fix #1232) b014649
- Separate Types and Type Aliases tables. (fix #1226) 9521a70
- Remove duplicate ellipsis in parameter pack expansion.20 c85be75
- Missing dependent array bounds in the output.21 4ae305b
- Honour CMAKE_ROOT when cmake is also in PATH. 4f51471
- Prevent infinite recursion when extracting non-regular base class (#1132).22 4e7ef04
- Empty argument list stripped from template rendering.23 (issue: issue #1184.) 966e652
- Stop auto-brief extraction at headings.24 (issue: issue #1162.) 8556f23
- Line number anchor in source links.25 (in #1034.) 7e73057
- Fall back to system compilers when database compiler is unavailable.26 ba86eae
- Destroy C++ locals before raising a Lua error.27 ce432e6
- A JavaScript function value weakly references its interpreter.28 570fd0c
- Remove all special name re-mappings for Handlebars.29 58bf524
- Empty-corpus check ignores global namespace.30 116e980
- HTML code blocks not wrapped in
...
. (commit: g was introduced with commit #51e2b655af43f36bc2fd3e9c369dbd48046d2de6.) 2a75692 - Clang resource directory missing from release packages. 1fc8a77
- Jerry_port_context_free wrong signature causes silent corruption.31 68cc299
- Error-on-empty-corpus option. (fix #1222) 0d7f8b3
- BottomUpTraverse() skips ListBlock items.32 1ebff32
- Avoid ranges::sort/unique on pointers to described types.33 fed854d
- Marshal Undefined and SafeString DOM values in Lua.34 9a42f36
- POSIX-normalize absolute path-glob. 2d0a1e0
- Missing @return command in doc comment. 7b118b1
- Use if/else instead of or helper for array bounds rendering.35 1fc06a0
- Don't treat EOF as a failure in getFileText.36 37b33c1
- Dom::Object field lookup returns the key instead of the value.37 42a0867
- ast:
- ci:
β»οΈ Refactor
Code refactoring and restructuring
- Unify partials via data-level abstraction.42 e75cdff
- Replace most per-type tag_invoke overloads with a single generic template.43 1ed76ad
- Replace per-type operator==() and operator<=>() with a single generic template.44 0246935
- Auto-merge symbol fields via Boost.Describe.45 (approach: mergeReflected() iterates all Boost.Describe'd base classes) 9a12737
- Migrate all reflection consumers to MrDocs.Describe.46 (Removes #include <lib/Support/Reflection/Reflection.hpp> from all .cpp) eb68494
- Add custom reflection facilities (MrDocs.Describe).47 6ce961f
- Algorithm function-object disclaimer. 0df52ce
- Replace per-type merge() one-liners with a single generic template.48 (unused: up unused #include <mrdocs/Platform.hpp> from several .cpp files) 8f5391b
- Drive visit() switches from existing X-macro .inc files.49 ec99c4a
- Build generators from data (don't use subclasses).50 9bbbefa
- metadata: Integrate Boost.Describe to remove manual mapping boilerplate.51 d490880
- generators: Single build() entry point. 9e66c2f
- support: Path helpers. 8e3391a
- handlebars: Add a data-driven escape map.52 (mechanism: it accommodates tokens like Markdown's
**versus a literal) 7cd6618 - extensions: Register scripts through a
mrdocsobject, not free functions.53 de70580 - test: Defer generator lookup until the per-test settings load.54 25d6c78
π Documentation
Documentation updates and improvements
- Restructure, generated registry, and live snippets.55 (fix #676) e9f847d
- Document scripting extensions.56 baf81eb
- Merge generators into the extensions page.57 d109ef9
- Add a runnable script-driven generator example.58 2f27b2e
- Document script-driven generators. ab0062a
- Document data-driven Handlebars generators. 224c795
- examples: Reuse common symbol template.59 b28ba4b
π¦οΈ Build
Build system and configuration changes
π§ͺ Tests
Test cases and testing-related changes
- golden-tests:
- Reproducible runs from a suite-root marker. 6a010a1
- Add unit tests for script-driven generators.63 3243b87
- Distinct anchors for member and friend operator>>.64 (fix #919) 707d860
- SFINAE record with two control parameters.65 (fix #823) ae70a15
- Cover additional paths in DocCommentFinalizer.cpp.66 9146125
- Regression for the extract-all crash (issue #1195).67 (
warn-if-undocumented: trueand includes a documented record., issue: issue #1195.) 18818c9 - Add golden tests for a partial class template specialization on an array type.68 (issue: issue #1172.) 72fba40
- AsciiDoc list mixing monospace across lines.69 (fix #845) 7833057
- Cover register_generator declaration and lookup. f483a3d
- Add an end-to-end fixture for a data-driven generator.70 (
addons-supplemental: a one-line layout that emits the symbol name,) 02657fe - Implementation-defined anonymous entities.71 (fix #1054) 741208f
- config: Out-of-tree base-url source link guard.72 (fix #1084) 2921b28
π¦ Continuous Integration
Changes related to continuous integration
- Dependency steps use bootstrap script.73 9b4fafb
- Modularize CI workflow. 5ca01a2
- Scope-aware build matrix. 9b193a5
- Increase test coverage for the new XML generator.74 a5f160b
- Use clang for coverage (#1144).75 5426a0a
- PR-aggregate size warning and log-scaled description floor.76 0abae84
- Merge-queue support and a leaner pipeline.77 f942a24
- Feature-without-docs warning in danger.js. 87ef94a
- Single-pass demo generation. e98b594
- Align llvm-sanitizer-config with archive basename. 8b2c3e9
- Add codecov configuration. ed6b3bc
- Skip long tests to speed up CI.78 471951d
- Detect and report demo generation failures.79 637011f
- Update actions to v1.9.1. 36a3b51
- Pull request template.80 ab5f412
- Match matrix.coverage as truthy. def9fcd
- Exclude Reflection.hpp from coverage. (Reason: See the new code comment in codecov.yml.) b1fc43c
- Revert coverage changes from b103cba (#1136). (Fixes #1135) 3462996
- Skip remote documentation generation on PRs.81 9a5bd3c
- Increase CTest timeout for MSan jobs. 7b2103a
- Speed up release demos on PRs.82 084322d
- Bump codecov-action to v7.83 6816f53
- Increase the ctest timeout to 9000. (Reason: Avoiding timeouts in the Clang 21 + MSan tests.) 086becc
- Accept any g++-14 version (#1159).84 a1f9a82
- Build on push to any branch.85 64cfdbd
- danger:
- Align report table and add top-files summary. 5429b2e
- Better markdown format. 57e191e
- PR-template section check. f330a98
- Map root files into explicit scopes. 71845c8
- Split PR target ci workflows. 240921d
- Adjust large commit threshold. 2cfd081
- "examples" scope in PR size report. 314970b
- Ignore test check for refactor-only PRs. 17b0a57
- Simplify CI naming. 6481fd3
- Correct file delta calculation in reports. 08c46b6
- Omit empty sections from report. fd7d248
- Categorize util/bootstrap as build scope. 7502961
- website: Preserve roadmap directory during deployment. c136a46
ποΈ Chores
Routine tasks, maintenance, and housekeeping
- Assign categories to regression tests. 681b0cd
- Gitignore entries for Python coverage artifacts. 8fc08d5
- danger: Drop experimental notice from PR comments.86 efdce8a
π Revert
Reverted changes to previous versions
- ci: Remove premature roadmap report step. 4763d86
π¬ Other
Other changes not covered by specific categories
- Use system libs by default (#1077).87 (Co-authored-by: Agustin Berge agustinberge@gmail.com) 6cee4af
-
When MrDocs encounters a variable that is a "function object" (its typeis a record whose only public non-special members are operator()overloads), it now synthesizes free-function entries named after thevariable. The type is marked implementation-defined and hidden from theoutput. Multi-overload function objects are naturally grouped byOverloadsFinalizer.For example:struct abs_fn { double operator()(double x) const noexcept;};constexpr abs_fn abs = {};is documented as if abs were a free function:double abs(double x) noexcept.Detection:member functions (constructors, destructor, assignment operators).Controlled by the auto-function-objects config option (default: true).the type, e.g. For types that have extra public members. Template types:auto-detected only when the type lives in the same scope or an innerscope (e.g. Detail::) relative to the variable. This avoids falsepositives from unrelated types like std::hash.What's generated:Each operator() overload becomes a synthetic FunctionSymbol with thevariable's name, parented under the variable's parent scope. Forvariable templates, the synthetic function inherits the variable'stemplate parameters. A "NOTE: This function object does not participatein ADL..." disclaimer is appended to each synthetic function's doc.FunctionSymbol::FunctionObjectImpl back-references the implementationtype.An example of this feature is added to the landing page (the abs exampleabove). β©
-
Run user-provided scripts under /extensions/.{lua,js}between corpus finalization and the first generator invocation. Eachscript may define a global
transform_corpus(corpus); the host calls itonce with a read view of the corpus (the same DOM the generators see)and the script applies changes through amrdocs.set(id, field, value)API.The write surface is a narrow, allowlist-gated setter driven byso the script-facing fields track the C++ model without a hand-writtenbinding table. It understands strings, booleans, described enums,Optional<T>,vector<T>, described structs, andPolymorphic<T>(thekind:selector picks a derived class registered withMRDOCS_DESCRIBE_KINDS). The allowlist (name,extraction,isCopyFromInherited,loc,doc,returnType) is generated at buildtime from src/lib/Extensions/AllowedFields.json, so the runtime gate andthe rendered reference table share one source of truth.The extension stack is split across small translation units:AddonDiscovery (collect scripts across addon roots), SetMember (thewrite surface and the corpus DOM), LuaBinding and JsBinding (theper-language adapters), and RunExtensions (the orchestrator).CorpusImplinvokesrunExtensionsafter finalization. The sharedaddonRoots helper used by both the Handlebars layer and the extensionlayer moved to src/lib/Support/AddonRoots.hpp; thedom::Arraymetatable in src/lib/Support/Lua.cpp is now a Lua-convention 1-indexedsequence so corpus.symbols iterates with ipairs.Golden fixtures under test-files/golden-tests/extensions/ exerciserename, brief rewrite, clearing an optional, aPolymorphic<Type>return-type write, script ordering across addon roots, and the silentskipping of a script that defines no transform_corpus. A unit testcovers themrdocs.seterror paths. β© -
The five private headers from src/lib/Support/Reflection/ areconsolidated into a single public include/mrdocs/Support/Reflection.hpp.Shared type traits (is_optional, is_vector) move to the existingSupport/TypeTraits.hpp.The tag_invoke overloads from the centralized Reflection.cpp aredistributed into per-type .cpp files.The src/lib/Support/Reflection/ directory is deleted entirely. β©
-
An extension script now defines an output generator with
register_generator(id, fn), alongside anyregister_transformitdeclares, rather than a generator directory shipping amrdocs-generator.yml that names a script. Both hooks receive onectx``ctx.outputfor a generator. This replaces the positionalgenerate(corpus, output, config, params)entry point and the separatemanifest-script discovery pass.A registered generator is adom::Functionthe corpus owns, because thegenerator registry is a process-global that is never cleared. The buildpopulates the corpus with the registered generators while extensionsrun;GenerateActionthen resolves the requested generator from thecorpus before falling back to the registry. A single language-agnosticrunner invokes the function, so the two per-language generator runnerscollapse into one path.The manifest now carries only the data-driven generator fields, itsescape rules and the parent it extends; thescriptandparamskeysare gone. The search-index example moves under addons/extensions anddeclares its generator withregister_generator. β© -
Previously, an HTML table in a doc comment triggered: warning: HTML
tag not followed by pure textand then a fatal error: the existing HTML start-tag handler could onlygather pure text between a tag and its matching end tag. The doc-commentextractor now recognizes<table>/<tr>/<th>/<td>and populatesthe existingTableBlock/TableRow/TableCellmetadata.The HTML and Adoc generators each gain a doc/block/table partial. TheAdoc output uses the[%header]table attribute when the first row is aheader; the HTML output emits plain<table>/<tr>/<th>/<td>. TheXML generator already serialized the metadata generically.Not (yet?) supported:- HTML attributes on<table>/<tr>/<th>/<td>(align,colspan,rowspan,class,style, ...). Column alignment is therefore never populated (TableBlock::Alignmentsis always empty) and cells cannot span rows or columns.-<caption>,<col>, and<colgroup>.- Block-level content inside cells (paragraphs, lists, code blocks). Cells currently hold only inline content. β© -
This adds a generator flavor backed by a user script. A directory under/generator// whose mrdocs-generator.yml names a scriptinstalls a generator that hands the whole emit to a Lua or JavaScript
generate(corpus, output)function: the script walks the corpus andwrites files through the output object, so it can produce output shapesa per-page generator cannot, such as a single artifact aggregated acrossevery symbol.The manifest parser moves into a sharedGeneratorManifest, so thedata-driven and script-driven discovery passes read the same file. Amanifest that names a script is skipped by the data-driven pass andinstalled by the script pass.The output object exposes a single write method, resolved under theoutput directory and forbidden from escaping it. Both languages receiveit as the second argument to generate; on the Lua side it is also boundas a global and passed from there, because the Lua bridge cannot carry acallable as a plain value. β© -
Add a
MRDOCS_DESCRIBE_KINDSmacro that registers the closed set ofmost derived classes ("kinds") of a polymorphic base, and apply it toevery polymorphic base in MrDocs. Generic code can then dispatch overthe closed set (describe::for_each(describe::describe_kinds<Base>{},...)) without the per-base X-macro boilerplate every consumer wouldotherwise need.The macro and its supporting machinery live in a dedicatedDescribeKinds.hppheader, so consumers that only needMRDOCS_DESCRIBE_STRUCT,MRDOCS_DESCRIBE_CLASS, andMRDOCS_DESCRIBE_ENUMkeep a slimmer include. Each per-baseregistration lives in a small private include under src/lib/Metadata/fed by the existing *Nodes.inc X-macro files, so the registered set hasone source of truth; the kind information is a compile-timeconsumer-side concern, so no public header exposes it.docs/mrdocs.yml excludes the reflection helpers from the generatedreference. β© -
Class template specializations, function template specializations, anddeduction guides used to share the enclosing scope's listing with theirprimary template. Users have repeatedly reported this as confusing:
AandA<int>appearing side by side in the namespace index reads as ifthey were independent siblings, and a primary's variants were nowhere onits own page.Specializations now appear in a dedicated "Specializations" section onthe primary's documentation page, and deduction guides in a "DeductionGuides" section on the deduced class's page. The parent scope's listingcarries only the primary itself. An orphan specialization (one whoseprimary has been excluded from extraction) stays in the parent's listingso the index can still reach it.The relationship is stored in the corpus: each primary record orfunction template carries the IDs of its specializations (and, for classtemplates, of its deduction guides), and each specialization carries anIsListedOnPrimaryflag. The lists are populated by a finalizer passand exposed via reflection, so the XML output gains matching<specializations>,<deduction-guides>, and<is-listed-on-primary>elements and the DOM/Handlebars layer renders the new sections throughplain field access. β© -
The
generatoroption now accepts a single id, a YAML sequence, or acomma-separated string, and the tool runs each generator in turn, so thecorpus is extracted once and rendered by every requested generator. A new built-innoopgenerator runs extraction and reports diagnostics without writing any output, which is useful for checking that extraction succeeds and surfacing warnings. β© -
An /generator// directory that ships anmrdocs-generator.yml file is now installed as an additional
HandlebarsGeneratorat config-resolve time. The manifest's merepresence is the explicit opt-in; its content is read for escape rules.An empty file is valid.This way, a generator can be added without writing any C++. β© -
A script extension can now receive its own parameters as
ctx.params,keyed by the id it registered under, or an empty object when none isset.For generators, this is thegenerator-options.<id>map (which alreadyexisted for per-generator settings) from mrdocs.yml. For transforms, itis a newtransform-options.<id>map; to key it,register_transformnow takes a mandatory id -register_transform(id, fn)- matchingregister_generator(id, fn). β© -
This enables the Handlebars templates to identify object types and baseclasses at runtime. The '$' prefix follows the JSON Schema conventionsfor system metadata. β©
-
This replaces the reserved-name
transform_corpus(corpus)entry pointwith an explicitregister_transform(fn)call. A script may registerany number of transforms; each runs once, in registration order, againsta navigable DOM view of the corpus it can read and mutate in place.The function is captured as adom::Functionon both languages. Luaanchors it inLUA_REGISTRYINDEXvia the newlua::makeCallable, not astorage global, so no new ownerless global state is introduced. A scriptthat registers nothing warns and is otherwise a no-op, so an emptyscript is tolerated. β© -
This mirrors the existing JS helpers for Lua. *.lua files placed in anaddon's generator/{common|}/helpers/ directory are auto-registeredas Handlebars helpers; files whose name starts with '_' run first asutility scripts. Two golden fixtures (lua-helper/, lua-helper-layering/)mirror their JS counterparts and cover the
addons-supplementaloverride.Incidental fixes to issues uncovered by this patch:- Added a qualification toMRDOCS_TRY/MRDOCS_CHECK_*/MRDOCS_CHECK_OR_*/MRDOCS_CHECK_OR_CONTINUEto make them work with nested namespaces nameddetail.- Dropped onelua.c and ltests.c from the Lua build patch, because the former definesmain, which conflicted with ourmain, and the latter is test scaffolding which shouldn't ship in a library build.- Addedextern "C"around the Lua includes. β© -
This fixes the XML generator, which was out of sync with our metadata,by replacing it with a reflection-based implementation. The XML outputstructure changes completely, but contains equivalent information. β©
-
This moves isSpecialMemberFunction() out of FunctionObjectFinalizer'sunnamed namespace into Function.hpp/cpp as a shared API, and introducesindividual helpers (isDefaultConstructor(), isCopyConstructor(),isMoveConstructor(), isCopyAssignment(),isMoveAssignment())---isSpecialMemberFunction() becomes a composition ofthese individual helpers.Contextually, this fixes three bugs in the existing detection logic inDocComment/Function.hpp:- Default constructors with all-default parameters were not recognized (only empty parameter lists were handled).- Default constructors with parameter packs were not recognized.- By-value copy assignment operator=(X) was not recognized. β©
-
Markdown inline formatting (bold,
code), bullet lists using "- "markers, and nested lists, were not rendered correctly. β© -
Only ASan and MSan require instrumented dependencies (libc++).UBSan and TSan instrumentation is added at compile time to theproject itself, not to its dependencies. Passing the sanitizerto LLVM builds for UBSan caused unnecessary 2+ hour rebuildsand cache key mismatches.Also simplify the stamp hash: only include compiler path andflags when the sanitizer actually changes how deps are built.This lets builds with different compilers share the same cachedLLVM when no sanitizer instrumentation is needed. β©
-
When the base is a dependent template specialization (e.g.,
base<T>intemplate<T> class derived : public base<T>),BaseMembersFinalizerunconditionally readSpecializationName::specializationID, which isonly set for concreteClassTemplateSpecializationDecls. For dependentbases, it stays invalid, so theMRDOCS_CHECK_OR_CONTINUE(baseID)guardsilently skipped the base and no members were inherited.The fix falls back to the primary template's ID (Name::id) whenspecializationIDis invalid, so a class template derived from adependent specialization now picks up the primary's members. Concretecases likederived : public base<int>still inherit from the implicitspecialization as before. β© -
Only set IsPackExpansion on the outermost Result type in TypeBuilder's terminal builder functions. β©
-
This fixes the rendering of e.g.:template<typename T, std::size_t N>voidf(T(&)[N]);which was previously rendered without the bound
Nin all the outputformats. For Adoc and HTML, the fix is just to fall back to the writtenexpression when the numeric value is absent. For XML, the fix is addingExprInfo handling in writeElement, and this adds several missingelements in the XML output (e.g. Initializers and requires clauses), notjust array bounds. β© -
A non-regular base class can have a member class which is abase class of the former.This fix prevents infinite recursion in this case. β©
-
T<>, a class template specialization with an empty argument list, wasincorrectly rendered asT. β© -
When a symbol's documentation begins with a
@par Titleblock (with nofront matter text before it), parsing emits aHeadingBlockfor thetitle followed by aParagraphBlockfor the body. The auto-brief passwalked past the heading looking for the first paragraph, promoted the@parbody to the brief, and left the title rendered as a section withno content.The fix is to stop iterating at the first HeadingBlock: content under aheading is the body of that section, not the symbol's introductoryprose. This is tightly scoped---HeadingBlockis only emitted from@partoday---and preserves the existing behavior when a front matteris present.The commit adds a regression test covering both shapes (no front matter,and explicit brief paragraph before the@parsection). β© -
The source link in the Synopsis section of each symbol page contained
#Lundefinedanchors. That's because the corresponding Handlebarstemplate used the wrong field name (dcl.lineinstead ofdcl.lineNumber).Note that the separate concern of these links pointing at a movingbranch rather than at a permalink for the documented commit is tracked. β© -
When use-system-stdlib is enabled and the compiler specified in thecompilation database cannot be found (e.g. Synthetic databases thatreference "clang" on systems with only GCC), try common fallbackcompilers (g++, gcc, clang++, clang, c++) to discover system includepaths. This prevents fatal "stddef.h not found" errors when runningmrdocs on systems where the database compiler isn't installed. β©
-
luaL_errorandlua_errorreport a failure by longjmp-ing to theenclosinglua_pcall. The jump runs no C++ destructors on the framesit unwinds, so any local with a non-trivial destructor still alive atthe point of the raise is leaked, and the unwind itself is undefined.Two of the Lua binding functions raised while such a local was live.The one invoked when a script assigns to adom::Objectfield heldthe value being assigned and raised from inside acatch. The oneinvoked when a script calls adom::Functionheld the argumentdom::Array, the call result, and the function being invoked.Stage the outcome on the Lua stack first - push the result value, orbuild a location-prefixed message withluaL_whereandlua_concat-then close the scope so every C++ local is destroyed, and only thenraise. Lua copies a pushed string, so the message outlives thedestructors. β© -
js::Context::~Contexttore the JerryScript interpreter down on thefirstContextdestruction, breaking the reference cycle between theImpland the native holders that each keep ashared_ptrto it. Adom::Functionobtained from a JavaScript value holds only thatshared_ptr, so once the originatingContextwas gone the functionreferred to a freed interpreter and calling it crashed.So, count only the livejs::Contextinstances that share aninterpreter and tear it down when the last one goes away. A functionvalue converted to adom::Functionholds a weak reference and locksit on each call: once the interpreter is gone the call returns anerror instead of touching freed memory. Code that needs such afunction to outlive theContextthat produced it keeps aContextalive separately.Single-context use is unchanged: the count drops to zero on thatContext's destruction and cleanup runs as before. Handlebars helperswritten in JavaScript are unaffected; they hold the value directlyrather than through the function-value conversion. β© -
We renamed some members into different Handlebars key names. But there'sno particular reason to do that. So we switch to use the canonical nameseverywhere. β©
-
The error-on-empty-corpus option compared the corpus against empty(), but the global namespace is always extracted and protected from pruning, so the corpus is never truly empty after a successful build, and the option never triggered. β©
-
Jerry_port_context_free was declared with the wrong signature(void*, jerry_size_t) instead of JerryScript's actual API (void).When jerry_cleanup() called it with no arguments, the functionread garbage from registers as the pointer to free. Also removeda redundant explicit call after jerry_cleanup() that was adouble-free.Silent on most compilers but GCC 15 on aarch64 put differentvalues in those registers, making the corruption visible. β©
-
This was a pre-existing bug that affected all content inside list items(not just our new Markdown lists, but also existing
@liones). β© -
Libstdc++-15 implements ranges::less via __not_overloaded_spaceship,which probes operator<=> via ADL on the element type. For SmallVector<Symbol*, 16>, ADL on Symbol* finds the generic mrdocs::operator<=> template. Clang 19 substitutes T = Symbol* into that template and hard-errors on the resulting non-member operator<=> with no class/enum parameter, instead of SFINAE'ing the candidate out -- a regression present in 19 but not in 18 or >=20. β©
-
domValue_pushhandledNull,Boolean,Integer,String,Array,andObject, and aborted viaMRDOCS_UNREACHABLEfor any other kind.Reading a field whose value isUndefinedorSafeStringthereforecrashed a Lua script.This mapsUndefinedtonil, asNullalready is, and aSafeStringthe way aStringis, which matches what happens in JavaScript. β© -
The Handlebars
orhelper returns the booleanfalsewhen botharguments are falsy, which renders as the literal text "false" insidearray brackets (e.g.int arr[false]). Replace{{or boundsValue boundsExpr}}with an explicit{{#if}}/{{else}}sothat empty bounds render as[]. β© -
The function was failing on
!file.good()which includes theeof()case, so an empty file caused a failure. Test for "fail() but not justbecause we hit EOF", instead. β© -
The
__indexmetamethod indomObject_push_metatable()retrieved thevalue correctly viaObject::get(key), then calledlua_replace(L, 1)to move the result into the userdata's slot.lua_replacealso pops thetop, so, on return, the key string was at the top of the stack and Luapicked it up as the metamethod's single return value, making every fieldaccess on adom::Objectuserdata silently return the key it was askedfor.This was latent until now because no Lua script in the test suitepreviously read fields off adom::Objectuserdata. Surfaced whilewiring corpus extensions: a script doingcorpus.symbols[i]saw"symbols"(the key) instead of the array. β© -
Canonicalize friend targets to avoid recursion. β©
-
Parent-based include-symbol propagation walked up to the translation unit, causing global symbols to be extracted even when include-symbols were restricted to namespaces. β©
-
The install page (https://www.mrdocs.com/docs/mrdocs/install.html)reads the rolling-release assets via the GitHub API and picks one perplatform by filename suffix. Because each develop push named itspackages with the current project version (e.g.MrDocs-0.8.0-Linux.tar.gz), a version bump produced a new filename andleft the previous version's files behind as stale assets on thedevelop-release and master-release rolling releases. The first-matchlookup then happily returned the wrong (older) asset.Thus, for non-tag publishes, rename each package from MrDocs--.to MrDocs--.right before the upload step. Subsequent pushes to the same branch nowproduce identical filenames, which action-gh-release overwrites inplace. Tag releases, which are immutable per version, keep theirversioned filenames unchanged.The upload glob is relaxed from
MrDocs-*.*.*-*.*toMrDocs-*-*.*toaccommodate the branch-named form.A one-time manual cleanup of legacy versioned assets on the existingdevelop-release and master-release rolling releases is still required;subsequent CI runs will keep the state clean on their own. β© -
Recent PR runs exceeded GitHub Actions cache limits, causing LLVM to be recompiled on every workflow run. This led to hours-long turnaround times to verify changes. As a workaround, the fork workflow was being used to test the PR.This commit simplifies the cache key structure to reduce redundant cache entries:- Add
llvm-os-keyusing container name or runs-on for OS versioning- Makellvm-archive-basenameconditional based on MSan only- Transform cache keys to replace ":" with "-" for safety- Only build instrumented libc++ for MSan where it's requiredMSan requires all code, including libc++ to be instrumented to track initialization state correctly. ASan and UBSan can effectively catch errors without instrumenting dependencies, making custom libc++ builds low-ROI for these sanitizers.Resulting cache key structure:- MSan builds: include compiler, version, and sanitizer type (e.g., llvm-dc4cef8-release-ubuntu-24.04-clang-21-MSan)- All other builds: omit compiler info since ABI is compatible (e.g., llvm-dc4cef8-release-ubuntu-24.04)Non-sanitizer builds, ASan builds, and UBSan builds across gcc/clang versions on the same OS now share a single cache entry, as they produce ABI-compatible LLVM binaries. β© -
Make tables render from data.
markup/tabletakesheaders,items,andcolumns. Cells use themarkup/cellpartial. With this, we move the symbol page out of the per-format adoc and html templatesand into a singlecommon/partials/symbol.hbs.This makes generators impossible to drift at the symbol level and data-driven generators much easier to write because they don't have to redefine the symbol template. β© -
Replace the old pattern of one tag_invoke overload per type with asingle generic template that handles any type described with the newMrDocs.Describe.The generic template dispatches through the reflection metadata: itwalks base classes, maps each described member via mapMember(), and adds$meta (type name + base class list). Types that need computed DOMproperties (Symbol, BaseInfo, RecordSymbol, etc.) keep slim customoverloads that call mapReflectedType() and add only the extras.Some DOM properties changed name because they are nowreflection-produced.The XML schema (mrdocs.rnc) is updated for newly serialized elements:template params/args, member-pointer children, IdentifierName,symbol/tparam/targ kind, and targ base fields.The XML golden test fixtures gain , , and elements that were previously silently skipped.We give up on the idea of having all reflection consumers in a singleReflection.hpp file to break circular dependencies (also, having smallincludes is better). β©
-
Add a reflection-based operator==() and operator<=>() template pair thatcompare bases then members using the MRDOCS_DESCRIBE metadata.This removes almost all per-type overloads. β©
-
This replaces hand-written per-field merge logic with a reflection-basedand members, applying a default type-based strategy via mergeByType().The strategies are tried in order: bool |=, SymbolID take-if-invalid,ADL merge() dispatch (for types with custom semantics),Polymorphic take-if-placeholder, Polymorphictake-if-identifier-empty, .Implicit types take-if-implicit, Optionaltake-or-recursive-merge, enum take-if-zero, string take-if-empty,vector dedup-append (when T has operator==), and vectortake-if-empty fallback.Every merge function now reduces to mergeReflected(I, Other). Types thatneed custom merge semantics define their own merge() overload, found viaADL:- merge(ExtractionMode) β leastSpecific()- merge(vector) β element-wise merge + append extras- merge(vector) β dedup by symbol ID- merge(Name) β auto-merge id and IdentifierThis refactor also fixed some bugs:- Symbol::Parent was merged backwards (took Other when I was valid)- RecordTranche::Usings was silently not merged- FunctionSymbol::IsRecordMethod was never merged- VariableSymbol::IsRecordField was never merged- FunctionSymbol::Attributes was never merged, unlike VariableSymbol::Attributes which was correctly dedup-mergedThe is_optional and is_vector traits are extracted into a sharedReflectionTypeTraits.hpp to avoid duplication betweenMapReflectedType.hpp and MergeReflectedType.hpp. β©
-
Switches toString(Enum), mapReflectedType, mergeReflectedType, andXMLWriter from Boost.Describe/Boost.Mp11 to the custom MrDocs.Describefacility introduced in the previous commit.files that depended on it for BOOST_DESCRIBE macros (now superseded byper-header MRDOCS_DESCRIBE_* calls). Updates Reflection.cpp with directincludes and moves the Optional tag_invoke there.Deletes the now-unreferenced Reflection.hpp registry. β©
-
Introduces include/mrdocs/Support/Describe.hpp β a minimal, C++23-onlyreplacement for Boost.Describe and Boost.Mp11. ProvidesMRDOCS_DESCRIBE_STRUCT and MRDOCS_DESCRIBE_ENUM macros with compile-timemember/base/enum descriptors and a fold-expression-based for_each.Adds MRDOCS_DESCRIBE_* calls next to every type definition. This movesreflection metadata from the private Reflection.hpp registry into thepublic headers, enabling future single-template operations (e.g. Merge)that eliminate per-type boilerplate.Both descriptor systems coexist in this commit β no consumers arechanged yet. β©
-
Adds a constrained merge(T&, T&&) template in MergeReflectedType.hppthat works for any type with MRDOCS_DESCRIBE_STRUCT. Non-templateoverloads (DocComment, SourceInfo, TemplateInfo, ExtractionMode, etc.)are still preferred by overload resolution.This eliminates a bunch of merge() functions that did nothing butforward to mergeReflected(), along with their MRDOCS_DECL declarationsin public headers. Three .cpp files that existed solely for thoseone-liners are deleted entirely (Enum.cpp, EnumConstant.cpp,NamespaceAlias.cpp).that only needed it for MRDOCS_ASSERT in the deleted functions. β©
-
The hand-coded
visit()switches in Type.hpp, TArg.hpp, and TParam.hppwere duplicating the type list already enumerated by their respective*Nodes.inc X-macro files. This rewrites each to consume the .inc file,instead, matching the pattern Symbol.hpp, Name.hpp, Block.hpp,Inline.hpp already use, so the .inc is the single source of truth. β© -
This moves
id,fileExtension, anddisplayNamefrom per-subclassvirtual overrides to base-class members set through the constructor.That's a prerequisite for letting users add a Handlebars-based generatorwithout writing C++. β© -
This introduces Boost.Describe and Boost.Mp11 and applies them acrossmetadata types (symbols, enums, inline elements) to replace hand-writtenio.map() calls with reflection-based code. This improves maintainabilitywithout altering the public API or user-facing features.Boost.Describe and Boost.Mp11 are private dependencies, i.e. They arenot used in any public Mr. Docs include. β©
-
This introduces
EscapeMap, a pattern-replacement table used to escaperendered output values. Single-byte sources live in a 256-entry arrayindexed byunsigned char; multi-byte sources go into a secondary arrayof buckets keyed by first byte, so the walk pays nothing extra for themulti-byte machinery in the common case (most buckets are empty). When abucket is non-empty, the longest match wins, so a**rule takesprecedence over a*rule at the same position. The defaultHandlebarsGenerator::escape()walks the map. This is the pathdata-driven Handlebars generators use: each format's rules come fromdata (loaded later frommrdocs-generator.yml), rather than beinghardcoded in a C++ subclass.The built-inadocandhtmlgenerators keep their existinghand-writtenescape()overrides, because the table lookup is slightlyslower than the compiled switch they had and those generators sit on thehot path.HandlebarsGenerator::escape()is therefore left virtual sothe built-ins can override it.Multi-byte support is what makes the map workable as a general escape*, RST'sliteralversus*emphasis*, and UTF-8 codepointspast ASCII that want to be replaced as a unit instead of byte by byte.The pre-existing publicHTMLEscapehelper is refactored to read fromthe same shared character-to-entity table (htmlEscapeEntities), so thetable can be used both there and by anEscapeMapfor any data-drivenHTML-like generator. β© -
register_transformandregister_generatorwere bare globals in theextension environment. This moves them onto amrdocsglobal object,the wayconsoleis already provided, so a script writesmrdocs.register_transform(fn)/mrdocs.register_generator(id, fn).Among Lua-embedding applications that expose a "register an extension"call, a host namespace object is the prevailing convention - darktableusesdt.register_*, Aegisubaegisub.register_*, Redisredis.register_function- while bare globals are the exception.Note that the per-invocationctx(ctx.corpus,ctx.output,ctx.config) is unchanged: only load-time declarations go throughmrdocs. β© -
Generator lookup happened once at
TestRunnerconstruction. Withdata-driven Handlebars generators now possible, a generatorcontributed via a test'saddons-supplementalwas unreachable from thetest binary: the lookup ran before that test's mrdocs.yml had beenloaded, so the generator wasn't yet registered.The runner now defers the lookup. The built-in generators are notaffected. β© -
The Antora docs are reorganized to be more complete and goal-oriented: each topic lives in its own directory with more detailed pages; the reference content (commands and options) is generated from a single source of truth that the implementation reads; and all examples and the reference include live-tested examples. β©
-
Add end-to-end documentation for the Lua and JavaScript scriptingsurface.extensions.adoc documents the corpus-mutation model: a worked example(synthesizing briefs from a naming convention), the file layout, the
transform_corpushook, thecorpusargument, themrdocs.setAPI andits allowlist (the table is generated from AllowedFields.json), thelifecycle, an "Invariants and operations" section spelling out thecorpus invariants and what scripts can and cannot do today, a"Stability" section stating the extensibility contract, and a "Designrationale" section comparing the alternatives considered for the writesurface.addons.adoc is a new shared page for the addon concept (lookup paths,addonsvsaddons-supplemental, override vs layering) used by boththe helper and the extension layers. Generators.adoc gains a[#custom-helpers]section covering the JS and Lua Handlebars helpersand the layering model. Nav.adoc lists the new addons page. β© -
The corpus-extensions page and the script-driven-generators pagedocumented two halves of one feature: scripts under addons/extensionsthat declare transforms and generators through the
register_*hooks.This folds the generator material into the extensions page, which nowcovers both hooks and the sharedctxobject, and removes the separatepage. β© -
This adds a self-contained search-index generator that the docs pageincludes and CI runs.The extensions/script-driven-generators.adoc example section nowincludes the manifest and the generate.lua from this fixture, so thedocumented example is exactly the one the test runs. β©
-
The symbol page now lives in a single common template, so thedata-driven examples no longer need their own
symbol.<id>.hbs.Each example is just a handful of format-specific markup primitives(table, section, admonition, list items, paragraph, heading, brief)plus the layout wrappers. Everything else comes from common and html. β© -
The sanitizer prompt rejected empty input on retry attempts becausevalidation only checked for empty/none on the first prompt, not afterreprompt. Also, "none" was shown as a valid option but wasn't accepted. β©
-
Simplify llvm build and build llvm on cache miss instead of website download.- Remove website download/publish steps for LLVM; cache misses now fetch sources and build locally before caching.- Simplifies CI by relying solely on GitHub Actions cache for LLVM artifacts and dropping the external website dependency.- Developers don't need help to update download binaries anymore. The local build became reasonable with the slim llvm build. β©
-
Each golden test now runs once, with the generator(s) it declares in its own config, instead of being run three times (xml, adoc, html). β©
-
This covers discovery (a script manifest installs a
ScriptGenerator),the output writer (writes under the root, rejects absolute and escapingpaths), and both runners against a synthetic corpus, asserting the filethey emit. A regression test reads a symbol with no name field,exercising theUndefined-to-nilmarshaling. β© -
A member operator>> and a friend/free operator>> in a class template used to get the same AsciiDoctor anchor id, colliding. The test pins distinct anchors for the two. β©
-
Golden test for a class template whose partial specializations each constrain a different SFINAE control parameter (En1 in one, En2 in the other), using the exact snippet from the issue. This used to crash during extraction; the test pins the no-crash behavior.The harness stub <type_traits> only had a partial set of traits, so it gained is_same/is_same_v to let the test use the issue's exact std::is_same code. β©
-
Exercise empty-paragraph, admonition, and styled-continuation branchesin Markdown list conversion to meet the 90% patch coverage target. β©
-
checkUndocumentedused to callundocumented_.erase(it)without firstcheckingit != end(). Underextract-all: false,undocumented_never gets populated, so for any documented symbolfind()returnedend()and the unguarded erase was undefined behavior. A user reportedthis as a crash in v0.8.0. B103cbac6 fixed this as part of an unrelatedrestructuring, but the existing fixture in this directory disabledwarn-if-undocumentedand so never reached the crashy block. The newfixture combinesextract-all: falsewith the default. β© -
Since it existed in earlier MrDocs versions, it is probably worth to adda test case for it. β©
-
A
\liitem that spans multiple source lines and mixes backtick monospace used to render as broken AsciiDoc. The test pins the correct rendering (one bullet per item, monospace preserved). β© -
This adds a fixture under test-files/template-only-generators/mock-mdthat ships its own mock "Markdown-like" generator via an addon-localplus a single escape rule mapping
_to\_. β© -
Golden test for marking an anonymous entity implementation-defined via the @implementationdefined doc command, covering the exact case from the issue (an unnamed
extern structdeclared with a variable). β© -
Symbols inherited from a base declared outside source-root must not get a source-code link (the file is not in the tree), while in-tree symbols do. The test pins both halves of that guard. β©
-
CI uses the bootstrap script to install all dependencies insteadof doing it inline. The script writes dependency paths and compiler flags to an env file that the build step picks up. β©
-
This adds support for all five admonition types, with correspondingtests, plus tests for type-based friend declarations and pointers tomembers. β©
-
Replace GCC debug-info coverage report with clang AST based reports.These are more accurate and don't suffer from disruptions from optimizations.This also makes it so coverage only applies to unit tests, excluding self-test from coverage because that's incidental coverage.This has a workaround to avoid a clang coverage bug.Link to upstream issue: llvm/llvm-project#179316. β©
-
Adds an aggregate source-churn warning (5000 lines) so large PRs areflagged even when individual commits stay under the per-commit limit,and replaces the fixed 40-character description floor with a log-scaledthreshold (~80 * log2(churn)) so descriptions are expected to grow withthe size of the change. Template scaffolding (HTML comments, Markdownheaders, standalone italic placeholders, and
- **Label**: _placeholder_bullets) is stripped from the body before measurement so an unfilledtemplate cannot inflate the length count or mask the testing-mentioncheck via the## Testingheader. β© -
With golden fixtures no longer drifting across three formats on everychange, the pipeline can run the full test set on every build and arebasing merge queue becomes practical: the queue can rebase a PR ontothe current tip and re-test it without the expected outputs churning.All actions are also bumped to their latest releases (cpp-actions tov1.9.5 and the GitHub-maintained actions to their node24 versions) sothe runner no longer warns about the deprecated node20 runtime. β©
-
This adds an
is-bottleneckmatrix flag for the followingconfigurations:- Any compiler with MSan- Apple Clang + ASan- Apple Clang + UBSanand, for these entries, skips the AsciiDoc/HTML golden tests andself-doc test while still running all the other tests.This reduces the wall-clock time of the overall CI run by removing theheaviest tests. β© -
Demo generation previously swallowed failures silently due to theabsence of
set -e. Each demo now checks its exit code: failures removepartial output, and the full list with reproduction commands is reportedat the end of the step. β© -
Prompts contributors to describe the change, enumerate per-areaimpacts, document testing (including any workflow updates), and notedocumentation changes. Placeholders are visible italic text so anysection a contributor forgets to replace stands out in the rendered PR. β©
-
The remote documentation step fetches and builds develop, master, andall tags. This content is unrelated to the PR and is only needed forwebsite publishing.The local documentation step (which builds only HEAD) still runs andvalidates that the PR does not break doc generation. β©
-
On pull_request, only generate the AsciiDoc format (the one that goes tothe website after Asciidoctor rendering). The XML and HTML formats areskipped because they are never published from a PR. β©
-
Upstream context: codecov/codecov-action#1956. β©
-
For the clang pipelines, where libstdc++14 is used, adjust thedependency so its satisfied by any g++-14 version.This fixes a recent breakage where this version is not availale anymore. β©
-
The push trigger filtered branches with '*', which does not match a'/' in a branch name, so slashed branches like feat/x never built onpush. Use '**' so any branch builds on push. β©
-
The banner was added when the rules were brand new; nothing has come backabout false positives since, so warnings can stand on their own like anyother check. β©
-
This change makes mrdocs use the system includes by default instead ofthe bundled ones.This helps mrdocs build projects which rely on differences betweenstandard library implementations, since now mrdocs sees the source codecloser to what the original compiler did, with only potential differences in thecompilers themselves and some minor command line manipulations remaining.It also stops bundling the clang resource directory, relying on the oneinstalled with libclang. This makes it so installing both to the sameprefix be necessary, which is the same as all the other libclang based tools.---------. β©