The style emulation visitor used to visit the DOM tree nodes and transform them if necessary. The algorithm transforms a DOM tree by:
- removing redundant stylistic elements and/or anti-elements
- if stylistic elements break any containment rules they should be recursively pushed into their children until the containment rules aren't broken or the stylistic element is illegal or not required.
- pulling anti-elements up to the same level as their open counterpart element and then removing the anti-element.
- removing stylistic elements from indivisible elements that don't permit them as direct children (once again the stylistic elements are pushed down into the indivisible element's children).
- merging mergeable elements such as font when one contains another (care should be taken not to push a mergeable element through another mergeable element since the lower one takes precendence over the higher one in the tree).
- ensuring that stylistic elements may be pushed through anti-elements if and only if the anti-element is not a its counterpart (e.g. b cannot be pushed through anti-b, but can be pushed through anti-u)
- mulitply nested style elements are all pushed down of an element that should not contain it (e.g. table contain b which contains i which contains font should result in b, i, font all pushed down).
The algorithm always favours pushing stylistic elements down into the tree as deep as possible. In certain circumstances anti-elements may also be promoted up recursively (whilst ensuring the promotion itself doesn't split indivisible elements along the way). Stylistic elements are always tracked (open and close) using a tracker to ensure that redundant styles may be discarded (bold within a bold, etc.). If a stylistic element contains an element it shouldn't it is pushed down to all its children.
General algorithm:
- If the element being visited is an indivisible element:
- process the indivisible element (this should catch most elements)
- If the element being visited is a stylistic element:
- process the stylistic element (b, u, i, etc.)
- If the element being visited is an anti-element:
- process the anti-element (anti-b, anti-u, anti-i, etc.)
- else do nothing (all elements should already be processed)
Example of containment rule enforcement
We need to ensure that the containment rules are not broken whilst processing elements. This is done by testing to see if the current element is contained by a style element that shouldn't contain this other element.
If no such element exists we should continue processing otherwise we need to push any elements that shouldn't contain me, down into me.
For example.
p p | / \ b b (p) / \ | / \ t1 (p) -> t1 b b / \ | | t2 u t2 u | | t3 t3 where (p) is the current element being processed and b shouldn't contain p. b would be pushed down into p.
@see StyleEmulationTransformer