Commit Graph
236 Commits
Author SHA1 Message Date
Steffen Becker 3344d20481 fix: apply a table style's paragraph spacing to its cells
Word's Table Grid — the style nearly every real table names — sets space
after 0 and single line spacing in its own w:pPr, which is why a table's rows
are line-tight. The cell paragraphs were taking the document default instead.

An explicit single spacing is now written out as well: it only used to be
dropped as redundant, but the block's own style may set another one.
2026-08-08 08:30:04 +00:00
Steffen Becker 9f6736d5a8 fix: honour w:contextualSpacing on import
Word's List Paragraph carries it, so consecutive list points sit line-tight.
Without it every one of them took the document default's 8pt after, and a
document that is mostly bullets drifted more than a page.
2026-08-08 08:30:04 +00:00
Steffen Becker 821688c2cb fix: carry the theme font into an imported paragraph style
A run with no font already fell back to the document's theme; the style did
not, so the registry held Standard and the headings without a family. Single
line spacing is measured against that family, so it resolved to the wrong one.
2026-08-08 08:30:04 +00:00
Steffen Becker 869556e531 feat: render Calibri Light with the bundled Carlito
Word's default theme heading font, so every Word file with a Title or a
heading references it. Without a face it dropped to the browser's serif —
a serif heading at the wrong width.
2026-08-08 08:30:04 +00:00
Steffen Becker 3a71491b58 fix: scale a named style's line spacing by the font's natural line height
A proportional line spacing multiplies the font's own single line height in
Word and LibreOffice, CSS multiplies the font size. The node attr already
scaled by Liberation Serif's 1.15; a style's line-height went out raw, so an
imported 1.08 rendered ~20% tighter than the file asks for and the drift
accumulated down the page.
2026-08-08 08:30:04 +00:00
Steffen Becker be96ee626c docs: apply rules for comments 2026-08-08 08:28:55 +00:00
Steffen Becker cd1da67586 fix: carry a character style through a list item on ODF export
odf-kit's list builder reads a run's marks itself and knows nothing about
charStyle, and applyRuns — which handles the style on every other path — never
sees a list paragraph, so a character-styled list item exported as plain text.

A pre-pass now does both of applyRuns' jobs: bake the resolved props into direct
marks (the run's own marks staying on top), which is what gets the run a span at
all, and prefix the CST sentinel so applyCharacterStyles re-points that span at
the named style. Formatting and name both round-trip.
2026-08-07 20:27:31 +00:00
Steffen Becker a8a4a4c32f feat: let a character style on the item's first portion reach the marker
The charStyle mark carries only a name, so resolving it needs the registry: the
plugin takes it as a `sheet` option (like ParagraphStyle), the exporters read
their own exportSheet. The style is the base, the portion's own marks stay on
top. The decoration pass now also re-runs on FORCE_PAGE_RECALC, so editing a
style repaints the markers.

The ODF marker style moves to styles.xml as a named style — LibreOffice ignores
a level's text:style-name when it resolves to an automatic style, which made the
whole ODF leg a no-op (probed both ways).
2026-08-07 20:27:07 +00:00
Steffen Becker 943a885754 feat: carry the item's formatting into its list marker
The marker took only the weight of the item's first text portion. It now takes
the family, slant, size and color too — as custom properties on every item,
since they inherit and a nested item must not take its parent's.

A named paragraph style reaches it a second way: the marker inherits the list
item's own font, and the document stylesheet only styled the item's paragraph,
so an imported document whose Standard style is Arial drew its numbers in the
editor's serif default. styleCss now emits the style's text half for the item
too (li:has(> …)).

Both file formats carry marker formatting per level, so a level definition is
written only for a list whose items agree: ODF mints a character style the level
points at, DOCX the level's w:rPr. A mixed list gets none on purpose, so
LibreOffice keeps applying its own first-portion rule.
2026-08-07 20:26:44 +00:00
Steffen Becker 0b54f6cc44 feat: render a list marker bold when the item starts bold
A bold mark sits inside the item's paragraph and never reaches ::marker, so the
roman numerals of a numbered heading stayed light while their text was bold.
A plugin tags such items and editor.css weights the marker. The trigger is the
first text portion, which is the rule LibreOffice numbering itself uses.
2026-08-07 17:41:09 +00:00
Steffen Becker 0d4ed9e591 fix: honour the paragraph mark's font size on every line
Its size is the block's line-height floor, not just an empty line's height:
10pt text in an 11pt style kept the taller strut and every line came out 0.4mm
high. Both importers now carry it as the blockFontSize attr whenever it differs
from what the block renders at, and the ODF export emits the FSZ sentinel for a
filled block too.
2026-08-07 17:33:23 +00:00
Steffen Becker 8b9ba74a48 fix: import a list indented less than the level base
A list's own indent is the offset from the level's 1.27cm base, and the
importers dropped it when the file put the list left of that (w:ind w:left="360"
is a common one), so every item rendered 6.3mm too far right. The offset is
signed now, floored at the base so the list stays inside the text column.
2026-08-07 17:32:59 +00:00
Steffen Becker 38e852190d fix: keep a header/footer's own font on DOCX import
blockDefaults(baseRun) made the Header/Footer style's own font the yardstick,
so a run matching it imported without marks. The zone carries no styleName and
no style CSS reaches it, so it then rendered in the editor default instead —
an Arial footer came back as Liberation Serif, 2.3mm narrow per line.
2026-08-07 17:32:24 +00:00
Steffen Becker 67e2a00bf0 feat: add a right paragraph indent
The mirror of the left indent (fo:margin-right, w:ind w:right) with its own
marker on the ruler. ODF export rides the PBX sentinel: odf-kit has a paragraph
option for the left indent but none for the right one.

Clearing direct formatting now resets the first-line and right indents as well —
no named style governs either, so both are always direct formatting.
2026-08-07 16:34:42 +00:00
Steffen Becker 7c09727cda docs: remove word as placeholder for general text editor 2026-08-07 18:08:20 +02:00
Steffen Becker ad38994c65 feat: add ruler for tab stops and indents
Click the strip to place a stop of the selected type, drag to move it, drag it
off to drop it; the two triangles set the paragraph's first-line and left
indent. Sticky inside the scroll area, so it clears the toolbar island and
stays aligned with the page as it scrolls or zooms.
2026-08-07 17:47:30 +02: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 7d4a0b256e fix: indent list levels by the step both exporters write
Lists were padded 1.5rem per level on screen while the DOCX and ODT
exports place item text at LIST_LEFT_STEP_CM (1.27cm) per level, so the
editor disagreed with its own output and with Word and LibreOffice by
6.4mm on the first level, doubling with each nesting level.
2026-08-06 20:01:23 +00:00
Steffen Becker c014a73da2 feat: support first-line and hanging indents
Only the block's left margin was read, so w:firstLine, w:hanging and
fo:text-indent were dropped: every hanging-indent paragraph rendered with
its first line flush with the rest instead of outdented.

Stored as the signed indentFirst attr in cm (negative = hanging) and
rendered as CSS text-indent. Word splits it into two exclusive
attributes by sign, ODF keeps one signed value.
2026-08-06 19:58:33 +00:00
Steffen Becker 3a68a144cb fix: read OOXML toggles as ST_OnOff, not as element presence
w:evenAndOddHeaders, w:titlePg and w:pageBreakBefore were treated as on
whenever the element existed, but w:val="false"/"0"/"off" turns them off
and both Word and the docx lib write that explicit form.

A file with <w:evenAndOddHeaders w:val="false"/> therefore took the
even-page header variant on every second page, which is empty — the
header and footer vanished from page 2 onwards.
2026-08-06 19:53:47 +00:00
Steffen Becker f48e5508a8 feat: honour the document's widow-orphan setting
Widow-orphan control was hardcoded on. It is a per-paragraph property in
both formats, so a file that turns it off paginated differently from
Word and LibreOffice.

Stored as the widowControl attr next to breakBefore. DOCX resolves
w:widowControl direct-then-style-chain-then-docDefaults; ODF reads
fo:widows/fo:orphans, where only an explicit 0 means off (absent is the
XSL-FO default of 2). Export rides the existing PBX sentinel rather than
adding a pass.
2026-08-06 19:45:08 +00:00
Steffen Becker 275a77564e fix: use Word's asymmetric cell padding for tables
Cells padded 0.1cm on all sides; Word and LibreOffice use 0.19cm left and
right and none top or bottom. Text sat 0.7mm too far left and every row
was 2mm too tall, so the offset accumulated down a table.

odf-kit only writes the fo:padding shorthand, which ODF defines as a
single length — LibreOffice drops a two-value form — so the export
expands it per side.
2026-08-06 19:26:56 +00:00
Steffen Becker 52cf5ac702 fix: derive single line spacing from the font, not a fixed 1.15
Single spacing is the font's natural line height. The hardcoded 1.15 is
Liberation Serif's (and Liberation Sans' and Caladea's), but Carlito
needs 1.2208 and Liberation Mono 1.1333 — measured against LibreOffice
at 12pt. A Calibri body ran 6% too tight, drifting a line per page.

Emitted next to font-family, so an explicit line spacing still wins.
2026-08-06 19:19:06 +00:00
Steffen Becker b1c515fd2f fix: adopt the DOCX document default font into the Standard style
Body paragraphs carry no w:pStyle, so the default style never reached
usedStyles and Standard kept the editor's Liberation Serif 12pt. Run
suppression meanwhile resolves against w:docDefaults, so the file's body
font was dropped with no run mark left to render it: a Calibri 11pt Word
document rendered as Liberation Serif 12pt.
2026-08-06 19:18:58 +00:00
Steffen Becker 328aff97dd fix: add widow-orphan control to prevent single paragraph lines 2026-08-06 20:59:33 +02:00
Steffen Becker 6c256c6533 fix: add pre-wrap for line-end space 2026-08-06 20:46:17 +02:00
Steffen Becker d608771105 feat: add table options 2026-08-06 20:01:44 +02:00
Steffen Becker 1ed9f3d172 feat: table-styles 2026-08-05 19:01:25 +02:00
Steffen Becker 82699e653b feat: add table header column 2026-08-03 22:47:44 +02:00
Steffen Becker 359915d6b2 fix: toolbar issues 2026-08-03 22:38:04 +02:00
Steffen Becker 308a80867c feat: add increase/decrease text size buttons 2026-08-03 16:41:17 +02:00
Steffen Becker 5b11cdf3f6 fix: styles manager 2026-08-03 09:42:07 +02:00
Steffen Becker 51584a98ea fix: color picker in style manager 2026-08-03 08:55:13 +02:00
Steffen Becker 24621b1450 feat: add rgb and hsl to colorpicker 2026-08-03 00:00:27 +02:00
Steffen Becker 8cdd487172 feat: right-click context-menu 2026-08-02 23:06:18 +02:00
Steffen Becker 9483d598fc feat: keyboard shortcuts 2026-07-31 20:43:48 +02:00
Steffen Becker 445d1c505f feat: editable font field 2026-07-31 18:59:38 +02:00
Steffen Becker 7cc9a36d18 feat: touchpad and keyboard scale document instad of browser ui 2026-07-31 18:37:17 +02:00
Steffen Becker ca4fbd422b feat: table margin edge resize 2026-07-31 17:46:26 +02:00
Steffen Becker f7c0e1ed1e fix: scroll bounce 2026-07-31 00:00:00 +02:00
Steffen Becker ec0cfb76fd feat: add character style editor 2026-07-30 23:34:36 +02:00
Steffen Becker 3dcae6f640 feat: named character styles 2026-07-30 23:34:23 +02:00
Steffen Becker 603f4df905 feat: paragraph style manager ui 2026-07-30 19:58:47 +02:00
Steffen Becker ebb76a5104 feat: docx import/export of named paragraph styles 2026-07-29 11:35:07 +02:00
Steffen Becker d79287c10a feat: odf import/export of named paragraph styles 2026-07-29 10:53:54 +02:00
Steffen Becker ac9d6cdcff feat: named paragraph styles with inheritance 2026-07-28 23:53:00 +02:00
Steffen Becker d461ce09a6 fix: align styles and headings to libreoffice 2026-07-28 22:45:24 +02:00
Steffen Becker f4973caade test: add unit test for display of font size 2026-07-27 20:38:13 +02:00
Steffen Becker 56f884a412 feat: dropdown for text styles 2026-07-27 20:35:55 +02:00
Steffen Becker 18a8609926 fix: resetHistory after loading new document 2026-07-27 18:55:50 +02:00