Commit Graph
33 Commits
Author SHA1 Message Date
Steffen Becker d6bd53d971 fix: a header or footer the zone schema can't hold renders anyway
A hyperlink in a fixture's copyright footer threw generateHTML and
blanked the whole zone. Drop what the one-paragraph schema lacks, keep
its text. A master handing over to a successor is also the different-first-
page flag, so a title master with no zones leaves page one blank.
2026-08-10 08:54:53 +00:00
Steffen Becker e3a5594f10 fix: page geometry from the body's own master, and a TOC that breaks
The default master was the one literally named Standard, which a document
need never reference: a fixture's body runs on OOoPageStyle, so its
footer band went unreserved and every page held ~15mm too much text.

An index longer than a page has no inner document positions for a
pagination spacer, so it now breaks itself between entries.
2026-08-10 08:44:34 +00:00
Steffen Becker a70df06fc1 fix: a paragraph margin the style half-declares follows LibreOffice
LibreOffice keeps a paragraph's space above and below in one item, so a
style that declares only one of them does not inherit the other from its
parent chain — the missing half falls back to the default paragraph
style. Probed against soffice with the OPG fixture's own styles, where
it is the difference between a heading sitting flush and 4mm too low.
2026-08-09 20:43:33 +00:00
Steffen Becker 2dcf8b8a20 fix: a title-page master governs one page, not the whole document
An ODF master page whose style:next-style-name names another master applies
to a single page. Read as the section's running header, this file's full-page
title background repeated on every page and its height pushed each block onto
its own — 276 pages instead of 16.

Its zones now become the first-page variants, the successor's the running
ones, and a positioned frame in a zone is dropped as in DOCX.
2026-08-09 14:32:53 +00:00
Steffen Becker ee56a348ee feat: formulas can be inserted and edited, and survive both formats
A formula node stores only its LaTeX source; the MathML on screen, the ODF
formula object and Word's OMML are derived from it, and both importers parse
foreign markup back into that source, so an imported formula stays editable.

Word documents were losing their formulas outright: m:oMath sits beside the w:r
runs in its own namespace, past convertInline's `namespaceURI !== W` guard.
2026-08-08 21:50:36 +00:00
Steffen Becker 7d5bc5e0c9 feat: a run of tabs too wide for its line carries on the next
LibreOffice restarts the tab grid on the continuation line; Chromium
hangs the leftover tabs and starts the next line at the margin, 160mm
away in the repro. The run is walked from the pen before it — the one
thing the fix can't move, so the answer holds whether or not the break
is already in place — and a break widget goes where the line runs out.

Measuring this turned up why the two disagreed in the first place: a
file that declares no tab interval falls back to ODF's own 2cm, not to
LibreOffice's UI default of 1.25, so leaving ours implied on export
rendered every tab elsewhere. Both exports declare it now, and both
imports fall back to their format's value rather than to ours.

Only runs of two or more are walked: reading a block's geometry forces
a reflow, and doing it per tab across 48 pages slowed pagination enough
that the parity harness compared a layout still settling.
2026-08-08 15:58:40 +00:00
Steffen Becker ea39dde58b feat: a tab lands on the file's own grid, and can draw its leader
The default tab interval was fixed at 1.25cm, so a file's own
w:defaultTabStop / style:tab-stop-distance was ignored and the DOCX
export wrote 1.25 back over Word's 1.27. It is a document setting now.

A stop can also carry the character it repeats across its gap. odf-kit
has no leader option and mints one automatic style per option set, so
the leader rides style:type behind a sentinel — matching on position
and alignment alone gave every stop at 6cm the same leader, which
LibreOffice drew back plain as day.
2026-08-08 14:40:26 +00:00
Steffen Becker 6accc7268f feat: every section keeps its own header and footer
A document had one set for all of it, taken from whichever section
declared one last — so a fixture lost its letterhead entirely
and page 1 got the empty header its final section asked for.

A body block now carries `sectionBreak`, ordinal rather than indexed so
editing cannot desync it. Import resolves Word's "Link to Previous" per
reference type; export writes a set per sectPr, and on the ODF side each
section past the first gets its own master page, which the block switches
to. The layer picks a page's set from where pageBreaks reports the
sections starting, and each section's zone reaches ride
`--pb-section-reach` so a later section's letterhead makes room for
itself: page 10 of a fixture was 24.9mm out, now 1.1mm.

Editing still reaches section 1 only; the rest render read-only.
2026-08-08 14:02:36 +00:00
Steffen Becker db0fe71cdb feat: a table keeps the cell margins its file gave it
The cell padding was a constant in three places that disagreed with each
other, so a narrow column lost 0.38cm it did not have: a bibliography
marker column of 0.71cm wrapped "[2] " onto three lines and every entry
grew with it, costing a fixture a whole page.

The table now carries its own margins (w:tblCellMar, direct or from the
table style; fo:padding on the ODF cell style) and both exports write
them back. A side within a twentieth of a millimetre of the default is
the default, or Word's 108 twips would tag every table.
2026-08-08 12:18:16 +00:00
Steffen Becker be96ee626c docs: apply rules for comments 2026-08-08 08:28:55 +00:00
Steffen Becker 92d641f72f feat: honour a paragraph's own tab stops
CSS only has the fixed tab-size grid, so a tab that resolves to one of the
paragraph's stops is measured and given the exact advance as an inline margin.
A hanging indent implies a stop at the text position, as in Word.
2026-08-06 21:45:47 +00:00
Steffen Becker 1ed9f3d172 feat: table-styles 2026-08-05 19:01:25 +02:00
Steffen Becker ca4fbd422b feat: table margin edge resize 2026-07-31 17:46:26 +02:00
Steffen Becker 3dcae6f640 feat: named character styles 2026-07-30 23:34:23 +02:00
Steffen Becker d79287c10a feat: odf import/export of named paragraph styles 2026-07-29 10:53:54 +02:00
Steffen Becker d461ce09a6 fix: align styles and headings to libreoffice 2026-07-28 22:45:24 +02:00
Steffen Becker f1ba14c948 feat: add paragraph frames and background 2026-07-19 16:34:23 +02:00
Steffen Becker 2a7abed917 feat: odd/even variants for footer/header 2026-07-18 16:42:23 +02:00
Steffen Becker dce22ab3f4 fix: header and footer editor 2026-07-18 11:49:49 +02:00
Steffen Becker 40c139dd2c feat: add embedded font loading 2026-07-11 14:07:36 +02:00
Steffen Becker 1fb81c389f feat: insert date/time 2026-07-08 23:21:07 +02:00
Steffen Becker bbd84cbeed feat: new page formats A3, A5, letter, legal 2026-07-08 19:21:18 +00:00
Steffen Becker 15f7e50976 fix: import of columns 2026-07-08 19:17:42 +00:00
Steffen Becker de283adab5 feat: introduce columns 2026-07-08 19:17:16 +00:00
Steffen Becker 15b9386eb7 feat: add table frame menue 2026-07-04 00:00:44 +02:00
Steffen Becker 3cc2e65423 feat: table cells background/shading 2026-06-28 10:59:22 +02:00
Steffen Becker 20706c80cb feat: image image text wrapping 2026-06-24 21:49:59 +02:00
Steffen Becker 20eb94d7c0 docs: clean up comments 2026-06-21 12:29:25 +02:00
Steffen Becker 64ae976ecf feat: insert images 2026-06-21 12:14:10 +02:00
Steffen Becker 0a35a65c83 feat: add spell-check 2026-06-18 23:34:45 +02:00
Steffen Becker 7b67969774 feat: header/footer position 2026-06-15 15:48:15 +02:00
Steffen Becker ee217610ba feat: header/footer 2026-06-13 15:20:24 +02:00
Steffen Becker 3088da0ac9 feat: import odt 2026-06-12 21:17:29 +02:00