How it works
What happens to your document between dropping it in and getting it back.
Same detector, very different inputs. A Word file describes intent; a PDF describes the marks on a page. That single difference explains everything below.
| DOCX | ||
|---|---|---|
| Font per run of text | Named exactly | Often subset-mangled |
| Paragraph styles | Available, with inheritance | Do not exist |
| Indentation | Stored as a value | Must be reconstructed from coordinates |
| Reading order | Explicit | Inferred from position |
| Where the text is | One XML part | Scattered across drawing operations |
| Detection reliability | Near-exact when code is formatted | Good in one column, variable otherwise |
A .docx file is a ZIP archive containing XML. The main document part records, for
every run of text, which font it uses and which paragraph style it belongs to.
When somebody pastes code into Word, one of three things almost always happens:
Word applies a monospaced font, the author picks one, or the paste lands in a
style such as HTML Preformatted.
Any one of the three is strong enough on its own to settle the question before a
single heuristic is consulted. The stylesheet is read too, and basedOn
chains are resolved, so a custom style that inherits its font from a code style is
still recognised.
This is the reason the DOCX reader is written from scratch rather than delegated to an existing converter. General-purpose libraries are built to extract semantic content and deliberately discard run-level font information as presentational noise. For this tool that discarded metadata is the single most valuable signal available — so the thing most libraries throw away is the thing worth keeping.
No ZIP library is involved. The platform's own DecompressionStream
handles the deflate streams, the central directory is walked directly, and the XML
is scanned with a small tag reader rather than a DOM parser — which is what
lets the same reader run unchanged whether it is given a file in a browser or on a
server. The result is that a Word file is parsed with no
third-party code at all.
A PDF does not contain paragraphs. It contains instructions to place glyphs at coordinates. There is no concept of a line, let alone an indent, and often no reliable concept of which text came first.
Text fragments are grouped by baseline, with a tolerance of half a line height, then sorted left to right. This works well for body text and code alike, and is the standard approach.
Leading whitespace is recovered by measuring the distance from the page's leftmost text to the start of the line, then dividing by the median character width across the page. Gaps inside a line are converted back to spaces the same way, which preserves column alignment.
For monospaced code this is accurate, because the divisor is exactly the character cell. For code set in a proportional font it is approximate and an indent level can land one space out. Since Python's meaning depends on indentation, this is the single most consequential PDF limitation.
PDF font names are frequently subsetted into something like
ABCDEF+Consolas, and some producers emit no usable name at all. The
subset prefix is stripped and the remainder matched against the same name list used
for Word files. Where the name is unusable, the run's declared font family is used
as a fallback.
Because lines are ordered by vertical position, a two-column page can produce lines that alternate between columns. A code block that crosses a column break may come back out of order. Single-column documents — which is most technical documentation — are unaffected.
Both formats are offered whichever one you started from, but they are not the same operation, and the difference matters.
| You upload | You download | What happens |
|---|---|---|
| .docx | .docx | Edits your file. Non-code paragraphs are never rewritten. |
| Edits your file. Code regions are painted over; the rest of the page is the original. | ||
| .docx | Rebuilds, carrying the formatting across. | |
| .docx | Rebuilds, carrying the formatting across. |
A rebuild is not a plain-text dump. Both parsers keep the formatting they can see, and the generators reproduce it:
So a conversion of a text-and-code document lands very close to the original. A document built around images, tables or a heavily branded template will not. Use the matching format when fidelity has to be exact — the tool states which of the two you are about to get before you press the button.
The exported Word file is the original archive with a single part modified. Every other entry — styles, numbering, relationships, content types, embedded images — is copied across still compressed, reusing its original checksum. Those bytes are never decoded, so they cannot be altered.
Inside word/document.xml, only the exact character ranges of the
paragraphs detected as code are replaced. Prose paragraphs are not regenerated, not
re-serialised, not normalised — the new XML is spliced in around them. So the
font, size, spacing, indentation, colour and style of your ordinary text survive
because they are literally the same characters as before, not because the tool
reproduced them accurately.
Each listing is rebuilt as ordinary shaded paragraphs, filled
#1E2433, with one coloured run per token. The characters are unchanged;
only colour, font and shading are added.
Paragraphs, deliberately, and not a table. A table would give an unbroken background for free, but it makes the listing structurally a table: you cannot edit it as ordinary text, and stripping the highlight leaves the cell shading behind. The pale stripes that shaded paragraphs are prone to — where a paragraph's fill stops at its own text box and the page shows through the leading — are a line-height problem, not a reason to reach for a table. Pinning an exact line rule makes consecutive shaded boxes meet.
Line numbers are optional. With the Line numbers switch off they are not written at all, so selecting the block gives you clean code; with it on they are part of the line. The block carries a little padding at the top, bottom and left, and sits flush at the right.
A PDF cannot be edited the same way. Its text is a sequence of drawing instructions, not a document tree, so there is no "paragraph" to swap out. Instead the original pages are loaded and left entirely intact, and new drawing operations are appended: an opaque Dark+ panel over the area each code block occupies, then the same lines redrawn on top in colour.
Everything else on the page — prose, headings, tables, images, page size, margins, metadata — is the original object, untouched.
The panel spans the page's whole text column rather than only the width the listing occupied, so a block that was indented on the page still reads as a deliberate pane instead of a stub floating mid-page. It also stretches to cover any line that ran past the margin in the original, because a panel sized to the column would leave the tail of that line visible beside it.
Type is fitted to the column. The code face is whichever font you picked, embedded into the file so it travels with it; where that is not possible it falls back to Courier, which is wider than most faces a document will have used. Either way the size is reduced until the longest line fits, using the font's own measured character width rather than an assumed one — Courier advances 0.60 em per glyph and Consolas 0.55, and guessing puts the line numbers in the wrong place. Anything still too wide at the minimum readable size is clipped at the panel edge rather than allowed to run off the page.
One honest caveat. Because this paints over rather than replaces,
the original code text is still present in the file's text layer underneath the
panel, even though it is no longer visible. If you need the old text genuinely gone
rather than merely hidden, export the .docx instead, where the runs are
actually replaced.
The DOCX reader is a few kilobytes and always present. The PDF engine is substantially larger and is only fetched when you actually open a PDF — opening the site, or using it on Word files, never downloads it. That keeps the landing page fast for everyone regardless of which format they came for.
What happens to your document between dropping it in and getting it back.
Every failure mode found so far in both formats.