Repository navigation
Fix inline nodes stored outside getChildren() not being transformed - #1441
Merged
Merged
Conversation
Member
Author
|
@linawolf this is my attempt to fix #1425. The amount of code I needed is much more, but I think this gives a cleaner way of allowing extensions to extend the fields of nodes they want to replace. Your extension can find a subnode to be added by creating a new provider. This will instruct the compiler to also access that method. |
jaapio
force-pushed
the
bugfix/compile-sub-nodes
branch
from
October 28, 2026 19:20
5c8fd8d to
3a8fc22
Compare
Nodes such as definition-list terms and classifiers, code-block captions, admonition titles, figure images, confval options and Bootstrap card parts keep other nodes in properties instead of returning them from getChildren(). The shadow tree never saw those nodes, so transformers (variable substitution, roles, references) were never applied to them. A `|substitution|` in a caption or a definition-list term was therefore rendered without its replacement. Introduce a compiler-owned registry of "node fields" so these nodes become part of the shadow tree without changing the node classes: - NodeField describes one edge type: items(), replaceAt() and removeAt(). Every modification returns the new owner, because nodes are immutable. - ChildrenField is the default field for the ordinary children of a CompoundNode, using the existing replaceNode()/removeNode(). - InlineField (plus InlineListField and InlineMapField) is registered with a getter and a setter per property. Several fields can be registered for one node class, and nodes whose property may be removed are marked nullable. - AttachedNodeRegistry collects InlineFields from tagged AttachedNodeProviders. Core, reStructuredText and Bootstrap each provide their own. TreeNode now remembers the field and key a child came from, and replaces or removes it through that field. The new owner is then written back to its own parent, so immutable owners nested at any depth are handled by one code path. TreeNode::getTraversalChildren() returns registered-field nodes followed by ordinary children, and DocumentNodeTraverser iterates that. The registry is injected into DocumentNodeTraverser by Compiler, which now builds (and releases) the shadow tree itself. To write fields back, add immutable with*() methods to DefinitionListItemNode, AdmonitionNode, FigureNode, GeneralDirectiveNode, SidebarNode, ConfvalNode, CardNode and AccordionItemNode, and make the affected properties non-readonly. Add integration fixtures for variables in captions and tables, unit tests for the registry and for replacing/removing nodes through fields.
jaapio
force-pushed
the
bugfix/compile-sub-nodes
branch
from
October 28, 2026 20:12
3a8fc22 to
6aff0ba
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Nodes such as definition-list terms and classifiers, code-block captions, admonition titles, figure images, confval options and Bootstrap card parts keep other nodes in properties instead of returning them from getChildren(). The shadow tree never saw those nodes, so transformers (variable substitution, roles, references) were never applied to them. A
|substitution|in a caption or a definition-list term was therefore rendered without its replacement.Introduce a compiler-owned registry of "node fields" so these nodes become part of the shadow tree without changing the node classes:
TreeNode now remembers the field and key a child came from, and replaces or removes it through that field. The new owner is then written back to its own parent, so immutable owners nested at any depth are handled by one code path. TreeNode::getTraversalChildren() returns registered-field nodes followed by ordinary children, and DocumentNodeTraverser iterates that.
The registry is injected into DocumentNodeTraverser by Compiler, which now builds (and releases) the shadow tree itself.
To write fields back, add immutable with*() methods to DefinitionListItemNode, AdmonitionNode, FigureNode, GeneralDirectiveNode, SidebarNode, ConfvalNode, CardNode and AccordionItemNode, and make the affected properties non-readonly.
Add integration fixtures for variables in captions and tables, unit tests for the registry and for replacing/removing nodes through fields.
refs #1426
Resolves #1425