# The skeleton reduction Two correct org→HTML renderers disagree on almost everything at the byte level. org wraps every section in `outline-container` divs keyed by generated ids; syntect emits one `` per code token; every backend picks its own class names and id scheme. Comparing raw HTML across implementations measures none of the things that matter. The **skeleton** throws that away and keeps what two renderers can meaningfully agree or disagree about: the ordered sequence of element opens, element closes, and text runs. A conformant implementation ports this reduction and asserts that `skeleton(its_html) == the checked-in .skeleton file`. ## The reduction, exactly Given an HTML fragment, walk it left to right and emit one line per event: 1. **Element open** → `` where `name` is lowercased. Keep only the attributes `href` and `src`, in that fixed order, each rendered as ` href="value"` / ` src="value"` with entities in the value decoded. Drop every other attribute (`id`, `class`, `style`, `datetime`, …). A self-closing `/` is stripped from the name. 2. **Element close** → ``, lowercased. 3. **Text run** → the text, with entities decoded and whitespace collapsed (any run of whitespace becomes a single space, leading/trailing trimmed), then emitted as a **Rust debug-quoted string** — i.e. wrapped in double quotes with `"` and `\` backslash-escaped. Empty runs (nothing but whitespace) emit nothing. Special rules: - **Ignored elements: `div` and `span`.** Neither emits an open or a close line. `div` is pure layout. `span` matters more than it looks: a syntax highlighter emits one span per token, and keeping them would turn one source block into ~60 lines of noise. - **Text merges across ignored tags.** Text is flushed to the output *only when a non-ignored tag is emitted*. So the text on either side of a `` joins into one run — which is exactly why a highlighted source block compares as the single string of code it is, not as a token-by-token sequence that has to line up. - **Void elements never emit a close:** `br hr img input meta link col area base source wbr`. A `` in the input is ignored. - **Comments and doctypes** (``, ``) carry nothing and are skipped. ## Entity decoding Decode the named entities `& < > " '  ` and numeric entities (` `, ` `). A non-breaking space (`\u{a0}`) is treated as a plain space for comparison. Anything that is not a recognizable entity — a bare `&` — is left as-is. Only consider a `&…;` an entity if the `;` is within 12 characters of the `&`. ## Worked example Input HTML: ```html

TODO Write the parser

``` Skeleton: ```

"TODO Write the" "parser"

``` The `id` is dropped, both `span`s vanish but their text `TODO` survives and merges with ` Write the ` into one collapsed run, and `` (not ignored) splits the run and emits its own open/close. ## Reference implementation The canonical implementation is `skeleton()` in orgo's `src/skeleton.rs` (Rust). A port is correct when, for every case in `cases/`, feeding orgo's own `.html` back through the port reproduces `.skeleton` byte for byte. That is the first test any port should run — it isolates a skeleton bug from a renderer bug.