Why indenting HTML is harder than it looks
HTML has thirteen void elements — img, br, input, hr, meta, link and the rest — that never take a closing tag. A formatter that treats every opening tag as something to indent inside pushes each one onto its nesting stack and waits for a close that will never arrive.
The result is drift. Everything after the first img sits one level deeper, the next one pushes it deeper still, and by the bottom of a real page body you are forty columns from the margin with no structure left to read. The other common failure is a formatter that invents a closing tag, which is invalid markup.
This one carries the void list, so those tags are emitted and the stack moves on. It also accepts XHTML-style trailing slashes and the genuinely self-closing tags you find in inline SVG — path, circle, use — without treating them as containers. Nesting depth reflects the document you actually wrote.
Where whitespace is content
Inside a pre element every space and newline is rendered exactly as written. Indent a pre that sits four levels deep using four spaces and every line of the code sample inside it gains sixteen leading spaces. The sample still works; it just looks wrong, and nobody connects it to a formatter run three commits ago.
A textarea is worse, because its content is the field's value. Add a newline and eight spaces for tidiness and the form loads with whitespace already in the box, the placeholder never shows, and a required check passes on nine characters of nothing. Users then submit an address that begins with a blank line.
pre and textarea are copied across byte for byte, because their whitespace is content. script and style are handled differently: their bodies hold JavaScript and CSS, so they are formatted with the JavaScript and CSS printers rather than as markup. That keeps template literals and multi-line strings intact, and it does mean the contents of a script block come back tidied rather than identical.
What formatting will not do
Formatting and checking are separate here, and the panels are separate too. A genuinely mismatched tag — a span closed by a div — stops the format and is reported with its position, rather than being repaired into something you did not write. Where HTML's own rules already imply a closing tag, such as a p ended by a following div, the formatter writes it out and says how many it added.
Attribute order, comments, the doctype and every entity survive exactly. Quoting is normalised — class=card becomes class='card' with quotes added — so the diff is not always whitespace alone, and the diff view marks when it is. After every format the output is compared against your input: if the element sequence or the visible text has changed, the tool says so rather than presenting the result as a tidy-up.
There is no model here and no guesswork. Formatting is Prettier's HTML printer, and the health check and structure view read your source directly — deliberately not the browser's parser, which silently repairs markup and would therefore report that your unclosed tags do not exist. The same input produces the same output every time, and it keeps working with the network off once the page has loaded.