Words that CSS held apart stay apart

A row like 39 words · 1 heading · 1 table is usually built as separate elements with the space between them coming from the layout rather than from the markup — so it converted as 39words1heading1table. The extension now reads the page with its layout in hand and puts those spaces back before converting. Stat rows, tag lists and breadcrumbs come out as sentences again.

Open a page's markup and look at the row of counts under an article heading. Very often there is not a single space character in it: <span>39</span><span>words</span>, and the gap you see on screen is a gap property on a flex container. The space is in the stylesheet, not in the document.

Every converter that comes after that sees the string and not the page — ours included — so the words arrive glued together. It is not an exotic shape either. A row of stats, a tag list, a breadcrumb trail and a pagination strip all look like this in any current framework.

Why this can only be fixed inside the page

The one place that can tell whether two elements are laid out side by side is the page itself, while getComputedStyle still exists. By the time HTML has been copied out to be converted, the layout is gone with the stylesheet and no amount of guessing recovers it: nothing in <span>39</span><span>words</span> says whether a space belongs there or not.

So the extension clones the document, walks the clone beside the living one, and wherever the real element lays its children out as flex or grid items, the copy gets a space after each of them. The copy is what gets converted. Your page is not touched, and this runs only in the moment you press the button — there is no content script sitting in your tabs.

A file you drop on the site gets none of this, because there is no layout to read. That is the difference between converting a page and converting a copy of its markup, and it is most of the reason the extension exists.

What it does not cover

Flex and grid, and nothing else. Space made by a margin on an inline-block, by absolute positioning, or by generated content in a ::before is still invisible in the markup, and still comes out closed up.

Converting a selection is also untouched: a selected range is cloned straight out of the document, so a stat row lifted as a selection can still arrive as 39words. Press the button without selecting anything and the whole-page path gives you the spaces.

Related: saving a web page as Markdown, and Turndown and the HTML-to-Markdown libraries.