########################## Serialization and export ########################## One parsed tree fans out into several output forms. The same arena tree serializes back to conformant HTML, folds into minified HTML, or walks into Markdown, plain text, and annotated text. The purple source is the tree; every green node is one rendering of it. .. mermaid:: flowchart LR tree([parsed tree]) tree --> html["html / serialize / encode"] tree --> minify["Minify"] tree --> md["to_markdown"] tree --> text["text"] tree --> annotated["to_annotated_text"] classDef src fill:#ede7f6,stroke:#4527a0,color:#311b92 classDef out fill:#e8f5e9,stroke:#2e7d32,color:#1b5e20 class tree src class html,minify,md,text,annotated out ******************************** Serialization modes and minify ******************************** A :class:`~turbohtml.Minify` is a serialization mode on that same conformant tree, and its design rule is that the minified bytes must reparse to the same tree: the hard part, a spec-correct parse, is already done, so minifying is only allowed to drop or fold what the parser reconstructs on the way back in. That gives a single correctness gate: ``minify(parse(minify(parse(src))))`` equals ``minify(parse(src))``, checked across the html5lib-tests corpus and real pages. Whitespace folds to one space rather than disappearing (a single space reparses in place, so the fold is idempotent); optional tags are omitted only away from open formatting elements, because the adoption agency would otherwise reconstruct one across the gap and shift the tree; and a value is unquoted only when no character could end or re-open it. The transforms that would *not* round-trip (deleting whitespace between block elements, or omitting a tag whose reparse changes nesting) are exactly the ones turbohtml declines to make. *************************** HTML vs XML serialization *************************** The WHATWG DOM standard defines two ways to turn a node tree into markup: *HTML fragment serialization* and *XML serialization*. They are different algorithms, not two escaping levels of one, and the same tree lands in both. The ``xml`` field on :class:`~turbohtml.Html` selects the XML one -- lxml's ``method="xml"``, libxml2's serializer, and the ``XMLSerializer`` a browser exposes all target the same form. turbohtml keeps a single tree walk and branches on a flag at the four points the algorithms diverge, so the HTML fast path is untouched. The first divergence is empty elements. HTML has a closed list of *void* elements (``br``, ``img``, ``input``, ...) that take a start tag and never an end tag, and every other empty element still writes ``
``. XML has no such list: any element with no children self-closes as ```` and a childless ``