Class: Markbridge::Normalizer::Walker
- Inherits:
-
Object
- Object
- Markbridge::Normalizer::Walker
- Defined in:
- lib/markbridge/normalizer/walker.rb
Overview
The parent-aware tree-rewriting engine. One Walker is built per #normalize call (holding that call's RuleSet and Report; no state is kept on the Normalizer). It changes the tree in place via AST::Element#replace_children, touching only elements whose children actually changed.
The main rule is resolve-before-descend: a child's strategy is resolved against its current ancestor stack first, and a moved subtree (hoist or unwrap) is then walked against the ancestor stack it will have in its new place. So a node that leaves a link does not see the link while its own inside is normalized. That keeps a legally nested quote-in-quote or image-in-quote intact, and it means a second normalize reports nothing.
Hoisting: a node taken out of an inline container is moved up, tagged
with its boundary (the outermost matching ancestor, compared by
identity), and placed right after that boundary, at the boundary's
parent. A wrapper left empty by a hoist or drop is removed (see
PRUNE_WHEN_EMPTY), so no empty ** ** markers stay.
For speed, the ancestor stack is one shared array that is pushed and popped, and an element's children list is copied only when a child first changes (copy-on-write). A subtree with no violations allocates nothing and is left as it was, so the pass can run by default.
Constant Summary collapse
- EMPTY =
[].freeze
- PRUNE_WHEN_EMPTY =
Wrappers that mean nothing once they are empty, so an empty one is removed instead of kept.
AST::Urlis not here on purpose: an empty link still renders as a bare URL, so a hoist that empties a link keeps the link. [ AST::Bold, AST::Italic, AST::Underline, AST::Strikethrough, AST::Superscript, AST::Subscript, AST::Color, AST::Size, AST::Align, AST::Email, ].freeze
Instance Method Summary collapse
-
#call(document) ⇒ Object
Normalize +document+'s subtree in place.
-
#initialize(rule_set, report) ⇒ Walker
constructor
A new instance of Walker.
Constructor Details
#initialize(rule_set, report) ⇒ Walker
Returns a new instance of Walker.
50 51 52 53 |
# File 'lib/markbridge/normalizer/walker.rb', line 50 def initialize(rule_set, report) @rules = rule_set @report = report end |
Instance Method Details
#call(document) ⇒ Object
Normalize +document+'s subtree in place.
57 58 59 60 61 62 63 |
# File 'lib/markbridge/normalizer/walker.rb', line 57 def call(document) _element, bubble = normalize_element(document, []) # Defensive: anything that never reached its boundary becomes a # trailing sibling rather than being lost. Well-formed rule tables # do not get here. bubble.each { |node, _boundary| document << node } end |