Commit Graph
13 Commits
Author SHA1 Message Date
Steffen Becker 889f11cffc test: a committed corpus CI can read
Ten documents the docx lib authors directly, plus the ODT twin
LibreOffice converts each into, now live in tests/corpus/ instead of the
gitignored fixtures dir. corpus.test.ts asserts both formats of a
document read the same and that each survives our export and import
either way. The heading styles gained the outline level Word writes —
without it LibreOffice converts a heading to a paragraph that merely
carries the style, and the two formats disagreed.
2026-08-15 11:54:36 +02:00
Steffen Becker 0da75ed456 refactor: the project is called edentext
Renames the product in the docs, the page title and the DOCX creator, and moves
the whole storage namespace from odf-editor- to edentext-. The prefix is a
per-origin namespace, so it stays the product name rather than a generic one.
2026-08-13 21:43:12 +02:00
Steffen Becker 1a1505071c fix: the parity reference stops depending on which duplicate font it picks
A second copy of a family LibreOffice bundles makes its render
non-deterministic: it resolves the same family to either file per run — the PDF
names them Carlito and Carlito-Regular — and their vertical metrics differ, so a
page led by a large-font heading lands 1.85mm lower on some runs. Measured 5/5
identical once the duplicates were gone, against a 2-of-4 flip before, and one
fixture's count swinging 21↔62 with no code change. README now says to install
only what the local LibreOffice does not already ship.

Also skips the `~$name` lock file a word processor leaves beside a fixture it
has open, which the corpus was picking up as a document.
2026-08-13 18:07:57 +02:00
Steffen Becker f9eeeb25f0 fix: the parity harness reads a word broken mid-word as two words
getClientRects()[0] gave a token that wraps — one wider than its line, or one
carrying a hyphen or a slash — its whole text at its first fragment's position,
where pdftotext reads the two fragments as separate words on separate lines. So
every such break reported a lineBreak the two engines did not actually disagree
on, and hid the case where they break at different characters. Split by the line
each character lands on; the per-character walk only runs on a word with more
than one rect.

Corpus 900 → 849, no page count moved.
2026-08-13 17:21:41 +02:00
Steffen Becker 3301aba30e fix: the parity harness finds Chromium on any platform
playwright-core resolves its own installed browser, so the hand-rolled
~/.cache/ms-playwright scan and its chrome-linux/chrome path can go — that
directory and binary name are Linux-only, and the harness threw before
rendering anything anywhere else. PARITY_CHROME still overrides.
2026-08-13 17:06:50 +02:00
Steffen Becker f055fc4850 docs: every comment back inside the three-line rule
A sweep of the whole tree: 27 blocks ran to four lines or more. Trimmed
to what the code can't say, with two of them split back onto the
function each was really about.
2026-08-11 21:22:13 +00:00
Steffen Becker 860e25d8c8 fix: saving keeps a section's own page margins
Both exports wrote one geometry for the whole document, so a title page's
margins survived import and were lost on the next save. Each ODF section master
now names a page layout of its own — the document's, shifted by the section's
difference, so what the header/footer pass folded into it survives — and every
w:sectPr carries its section's w:pgMar. DOCX import takes the document pair from
the first section, the one .tiptap's padding draws.

The parity harness spread a 458-page document's word list into Math.max and blew
the stack; the longest fixture was never measured.
2026-08-11 19:35:55 +00:00
Steffen Becker ab83ad3c58 test: the parity runner compares a leader as one token, and polls
How many dots fill a tab or index leader is the fill's own business —
both engines end it at the same stop. The settle predicate now polls on a
timer: walking every spacer and index row each frame starved the layout
it was waiting for, and half the runs timed out.
2026-08-10 11:32:40 +00:00
Steffen Becker c26aac1bee fix: the index's leader fills its own gap, at LibreOffice's indents
Every row carried 200 dots — clipped on screen, but the clipboard, the
PDF and any measurement got all of them. Cut each to what its gap holds,
and step the levels by 0.5cm, which is what LibreOffice's Contents styles
use. The parity runner now waits for the page numbers to settle too.
2026-08-10 09:32:49 +00:00
Steffen Becker 4ad743dc28 test: the parity runner waits for the import, not just for a blank page
A 3.5MB fixture takes seconds to parse; until then the editor holds the
empty document, whose layout is stable enough to pass the settle window.
2026-08-10 08:17:40 +00:00
Steffen Becker 2e70e47912 test: the parity runner can reuse a dev server already listening
PARITY_PORT points it at an existing npm run dev instead of starting a
second one on 5199.
2026-08-10 07:38:31 +00:00
Steffen Becker e4b679ad8b test: find whichever Chromium build is installed
The parity runner pinned one build number, so a fresh
`playwright-core install chromium` left it pointing at a directory that
is not there. PARITY_CHROME still overrides.
2026-08-08 12:17:51 +00:00
Steffen Becker 361b14dc17 test: compare the rendered page against LibreOffice
Everything else in tests/ compares documents at the model level; nothing checked
what a page actually looks like. run.mjs renders the same file through soffice
and through the real app in Chromium, reads both back as word boxes, and diffs
page count, line count, line text and line position.

The corpus stays out of the repo: make-fixtures.mjs authors the baseline .docx
files, and real-world documents are whatever you drop into the gitignored
fixtures/ yourself.
2026-08-08 08:35:34 +00:00