Spike: experimental transclusion/fragment extension (parsed args via host resolver)#201
Spike: experimental transclusion/fragment extension (parsed args via host resolver)#201dereuromark wants to merge 2 commits into
Conversation
Proof of concept for mapping template/fragment invocations with parsed
arguments onto Djot, exploring the parsed-vs-unparsed argument problem
discussed upstream in jgm/djot discussion 366.
Adds an opt-in TransclusionExtension that parses {{name|positional|key=value}}
into a Transclusion node whose arguments are TransclusionArgument nodes holding
PARSED inline children (so a markup-bearing argument becomes real AST, not a
flat attribute string). A host-supplied resolver expands the node into normal
AST before render; unresolved calls fall back to a visible placeholder span.
This reuses only existing infrastructure (custom inline pattern API, mutable
AST, beforeRender hook) and adds nothing to the parser core. The pipe-based
surface syntax is deliberately throwaway; the point is the AST model: multiple
named/positional parsed argument slots, expansion delegated to the host.
Marked experimental and not part of the official Djot spec.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #201 +/- ##
============================================
+ Coverage 91.78% 91.79% +0.01%
- Complexity 3441 3467 +26
============================================
Files 104 107 +3
Lines 9753 9816 +63
============================================
+ Hits 8952 9011 +59
- Misses 801 805 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces an opt-in, experimental “transclusion” extension that parses {{name|args}} inline invocations into dedicated AST nodes, then optionally expands them via a host-provided resolver in a beforeRender hook, with documentation and tests to demonstrate parsed (markup-bearing) arguments.
Changes:
- Added
TransclusionandTransclusionArgumentinline AST nodes to represent invocations and their parsed argument values. - Added
TransclusionExtensionto parse{{...}}calls into those nodes and replace them pre-render via a resolver (or an unresolved fallback span). - Added PHPUnit coverage and documentation for the experimental extension and resolver contract.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/TestCase/Extension/TransclusionExtensionTest.php | Adds tests for positional/named args, parsed inline argument content, and unresolved fallbacks. |
| src/Node/Inline/TransclusionArgument.php | Introduces an inline node type representing a positional or named transclusion argument with parsed children. |
| src/Node/Inline/Transclusion.php | Introduces an inline node type representing a transclusion invocation name plus argument children. |
| src/Extension/TransclusionExtension.php | Implements parsing for `{{name |
| docs/extensions/index.md | Documents the experimental extension, syntax limits, resolver contract, and fallback behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
What
A spike (opt-in, experimental) that maps template/fragment invocations with parsed arguments onto Djot, using only the existing extension/AST infrastructure.
This is the djot-php-side experiment for the upstream discussion on documenting Djot extensions and mapping wikitext-style templates onto Djot: jgm/djot#366
Why
Djot attributes are flat strings, so a markup-bearing template argument (a title containing emphasis, a link, or even another template) cannot live in an attribute. The discussion converges on a core question: there is good syntax for unparsed args (attributes), but no good mechanism for parsed args. This spike demonstrates one answer: a dedicated node whose arguments carry parsed child nodes, expanded by a host resolver before render, leaving the Djot core ignorant of template semantics.
What it adds
Djot\Node\Inline\Transclusion- node holding the invocationname.Djot\Node\Inline\TransclusionArgument- one argument; named or positional, value held as parsed inline children.Djot\Extension\TransclusionExtension- parses{{name|positional|key=value}}via the existing custom inline-pattern API, builds the node with parsed argument children, and onbeforeRendercalls a host-supplied resolver:transclusion-unresolvedspan containing the literal{{name}}.docs/extensions/index.md(table row + section with a resolver contract), marked experimental.So
{{cite|title=_Important_ book}}yields an emphasis node in thetitleslot, not a flat string - that is the whole point.Design notes
beforeRenderhook. No parser-core changes, no renderer changes (the resolver expands the node before the renderer ever sees it).Transclusionnode.Spike limitations (intentional)
{{...}}with[^{}]inner, so nested braces / literal braces inside arguments are not supported, and a literal|inside an argument is not supported (pipe always splits).Status
Draft / spike for discussion. Not intended to merge as-is; opening it to make the AST-model argument concrete with running code.