# 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.