* engine: filter note_refs in nextFootnote to skip endnotes
* Collapse the nested if (clippy collapsible_if)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The strip kept File, the active tab and contextual tabs however narrow the window got, so
they were drawn under the buttons on the right. The strip is now planned first: the buttons
keep their room and the tabs give way in order (tab padding, Comments and Editing labels,
Share label, plain tabs into », active and contextual labels cut with …, last the active tab
into »). File always stays. A regression test checks widths 300-1280 in en, pl and de.
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
With text selected, Layout > Columns used to change the whole section. As in
Word (observed black-box), a continuous section break now goes where the
selection starts and one where it ends, splitting a paragraph there, unless that
end already meets a section boundary (the document's start or end, or an
existing break); the columns go on the section between, in one undo step.
`layout.columns` gains `apply: "selection"`, its default when text is selected
in the main text. More Columns... offers "Selected text" and picks it then.
Co-authored-by: Brandon Thomas <echelon@gmail.com>
The legacy run properties w:outline, w:shadow, w:emboss and w:imprint were
read, resolved and saved but never drawn. Layout now turns them into text
effects (hollow outlined letters; a sharp grey copy down-right for shadow
and emboss, up-left for imprint, as Word's PDFs show them) and draws them
through the existing WordArt path, so screen and PDF both get them and the
PDF keeps the text. WordArt w14 effects on the same run take precedence.
Text drawn from outlines keeps synthetic bold (a widened outline, or one
in a solid fill's colour and transparency). Colour glyphs (emoji, no
outlines) and top-to-bottom runs with upright characters are drawn as
plain glyphs, and tracked insertions and deletions keep their legacy
effects.
Co-authored-by: Naxvog <4963183+naxvog@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
With Different First Page on, page 1 shows the first-page header, but
Insert > Header/Footer/Page Number always wrote the default one (which
page 1 no longer shows), Edit Header without a page went to the default
too, and a double-click in page 1's header area was ignored while
another header was being edited (the usual case: edit the header, tick
Different First Page, double-click page 1). Now hf_part and edit_hf use
the slot of the caret's page, and a double-click in a header/footer
zone switches to the one that page shows even from another header.
Fixes#2826Fixes#2811
Claude-Session: https://claude.ai/code/session_013kKPnx8r1vcYumjyL3kcuz
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
LibreOffice puts a paragraph indented on both sides on the clipboard as
<blockquote>, its margins in the page's stylesheet. Paste mapped it to the
centred, italic Quote style. On paste only, it now becomes a Normal
paragraph indented by the blockquote's stylesheet margins (else 0.5 in each
side). Opening .html files still maps blockquote to Quote.
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Shapes: preserve DrawingML outline dashes
* Shapes: scale dashes to effective path width (#380)
* Keep the outline dash with noFill; cap the raster dashed stroke width at 200 pt
Addresses the two CodeRabbit review notes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Use clamp for the dashed stroke width (clippy)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
A copy or cut of one equation on its own now also puts its MathML in the
platform's MathML clipboard formats, beside the HTML (with MathML, #816) and
the linear text: "MathML" and "MathML Presentation" (UTF-16LE) on Windows,
public.mathml.presentation and public.mathml on macOS. These are the names
W3C MathML 3 section 6.2.4 registers, and Microsoft's "MathML Support in
Microsoft 365" doc says Office checks them first when it pastes math. No
public clipboard format carries OMML. A copy with text around the equation
doesn't offer them, so Word keeps the text.
Not yet verified in Word: the parity docs say MathML clipboard formats, not
an editable paste.
Claude-Session: https://claude.ai/code/session_01P8veLveuUsJJm6UEcQPEuW
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
alt_numpad_code_types_its_character_without_keytips always expected é, but on
Windows the app (rightly) reads 0233 in the system locale's ANSI code page, so
a Russian system (1251) types й and the test failed. The test now works out the
expected character the same way, as its Alt+233 half already did.
split_row already keeps widow/orphan control in each cell paragraph.
When that moves all of a cell's lines on although its first line would
fit, the other cells stayed on the page and the row was split beside
an empty cell. Word moves the whole row on instead. Observed with
synthetic documents (exact 14 pt lines, a one-line cell next to a
longer one near the bottom of the page):
long cell | room for | Word | before | now
4 lines | 2 | 2 + 2 | 2 + 2 | 2 + 2
3 lines | 2 | row moves | short cell kept | row moves
3 lines | 1 | row moves | short cell kept | row moves
4 lines | 1 | row moves | short cell kept | row moves
5 lines | 3 | 3 + 2 | 3 + 2 | 3 + 2
3, control off | 2 | 2 + 1 | 2 + 1 | 2 + 1
Co-authored-by: Daniele Mori <Dinasty@hotmail.it>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* Automatic text in a styled text box takes the shape style's font colour
A text box shape whose style has a:fontRef with a colour (Word's
default shape style uses lt1, white on the accent fill) shows its
automatic-colour text in that colour. WordCraft drew it black. Word,
observed with a synthetic document: only text whose resolved colour is
automatic takes the fontRef colour; a run's own colour, a paragraph or
character style colour and a colour from the document defaults all win
over it. A box without a fontRef keeps black.
- wordcraft-doc: TextBody gets `auto_color`.
- wordcraft-docx: read from wps:style/a:fontRef (theme colours resolved
as for SmartArt).
- wordcraft-layout: lines in a text box story resolve automatic colour
to it.
Saving does not write a shape style yet, so the colour is not kept
through a save; the reader and layout parts stand on their own.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Remove stray doc-comment lines from the new test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Daniele Mori <Dinasty@hotmail.it>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Some generators write a placeholder Heading 1 and then their own,
under the same w:styleId. The reader kept the first definition and
skipped the rest, so headings came out in the placeholder's font,
size and colour. Word uses the last definition, whole: a synthetic
document with an italic red 20 pt first definition and a bold blue
12 pt second one shows bold blue 12 pt, with nothing of the first
(no italic, no centring), for a custom style and for Heading 1 alike.
The reader now replaces an earlier definition in place instead of
skipping the later one.
Co-authored-by: Daniele Mori <Dinasty@hotmail.it>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Tab already follows reading order (next logical cell) and right-to-left
tables (w:bidiVisual) already lay the first cell out at the right. The
bug was that insert.table ignored the caret paragraph's direction, so a
table made while writing RTL text was a left-to-right table and Tab went
rightwards. Like Word, insert.table now makes a right-to-left table when
the caret's paragraph reads right to left.
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Found while testing crates/doc/src/table.rs:129 (Table::delete_row), called from crates/engine/src/cmd/table.rs:526 (del_row)
Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Found while testing crates/docx/src/write/story.rs:512-530 (InlineObject::NoteRef, the `current_note == Some(..)` branch)
Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Indonesian spelling reads the installed Hunspell id_ID dictionary at runtime
(Debian/Ubuntu hunspell-id, LibreOffice dict-id, the Dictionaries folder or
WORDCRAFT_DICTIONARIES), like Czech, Polish and Portuguese: nothing is bundled,
and without a dictionary Indonesian text gets no spelling marks.
- ProofLang::Id for id, id-ID, ind and the legacy in tag
- suggestions reuse the dictionary-driven Czech ranking (MAP/REP/TRY/KEY of
the loaded dictionary), nothing Indonesian hard-coded
- hyphenated reduplication accepted whole or by parts (kupu-kupu, anak-anak);
hyphenated clitics after capitals/abbreviations (KTP-nya, se-Indonesia)
- generic grammar only: repeated word (offers anak-anak first), space before
punctuation, double space, with Indonesian messages
- Review > Language, status bar, Set Proofing Language, File > Options >
Proofing list Indonesian; name translated in every catalog
- tests use a hand-written synthetic dictionary; engine end-to-end test
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Found while testing crates/formats/src/markdown.rs:253 (join_lines); also the trim_start() calls at lines 229, 311, 426 and 432, against escape_line_start at line 1077
Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
PDFW: Migrate WordCraft PDF export to the shared writer while preserving application layout and export policy.
Refresh includes current main through fd0bb2fb. The exact merged tree passed all six local CI gates, 2,769 native tests, 39 PDF tests, 16 WASM package checks, and 104 paired exports / 117 pages on native and executed Node/WASM. Fresh Ubuntu, Windows and macOS Printing checks passed at df28b78.
PR #1558. Preserve the qualified branch history and immutable shared dependency revision.
On macOS, Cmd+Left/Right were bound to Word Left/Right (same as Option+arrows).
Bind them to Line Start/End there, as in Word for Mac and every Mac text field;
Option+arrows still move by word. Windows/Linux keys are unchanged.
Co-authored-by: justinjohn0306 <babyjjbabyjj549@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* fix(ui): draw Arabic and other non-Latin comment text in balloons
Comment balloons and the Comments pane draw comment text and author
names with the interface faces (Inter, Source Sans, CJK), which have no
Arabic, Hebrew, Thai and so on: every such letter was a box. The app now
borrows a document fallback face that covers the comments, as the window
caption does (#840), checked once per document revision.
egui also lays bidi runs and words out left to right, so a right-to-left
comment read backwards. Read-only balloons now wrap the text by word
widths, put each row in display order (Unicode bidi runs, words of a
right-to-left run reversed, brackets mirrored) and set right-to-left
paragraphs against the right edge. Text without right-to-left letters is
laid out exactly as before. The editable fields (the selected balloon and
the Comments pane) keep logical order.
Also adds my contributor entry (sync_github_name).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* One contributor entry each
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Mohamed Youssef <ms.rightsteps@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Tables: formulas with cell references, functions, number formats and F9
Table Layout › Data › Formula was a fixed set of string checks: any
unknown function was silently summed, cell references weren't read, and
Update Field never recalculated a formula field.
Formulas are now parsed and evaluated (crates/engine/src/cmd/table_formula.rs):
- cell references and ranges by grid column (=B2+B3, =SUM(B2:C3)),
+ - * / ^, parentheses and the comparisons = <> < <= > >=
- SUM, AVERAGE, COUNT, MAX, MIN, PRODUCT, ABS, INT, SIGN, ROUND, MOD,
IF (only the branch taken is worked out), AND, OR, NOT, TRUE, FALSE,
DEFINED
- ABOVE/LEFT/RIGHT/BELOW sum the first run of numbers next to the cell,
as observed in Word; `=SUM()` is a syntax error, as in Word; a bare
`=SUM` takes ABOVE or LEFT from the cell
- the \# numeric picture (`#,##0.00`, `0%`, `;` sections)
- an unknown function or a syntax error is an error and inserts nothing;
input is bounded (formula length, nesting depth)
Update Field (F9) re-evaluates formula fields from the cells they read.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Review fixes for #907: clamp formula ranges to the table, cell budget, depth for ^ and unary +
- A range reads only the rows and grid columns the table has, so SUM(A1:BK32767) over a small
table no longer walks two million grid positions.
- One evaluation reads at most 100,000 cells; past it the formula fails with "Formula too
complex" (F9 shows !Formula too complex) instead of hanging on a hostile document.
- Each ^ in a chain and each unary + counts toward the nesting limit of 32, like unary -.
- Regression tests for all three.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* M2.1: locale-aware number parsing and formatting in table formulas
* contributors: credit rbr48
* Merge main; rustfmt; one contributor entry for rbr48 (#906 had added one)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Drop a stray merge marker from ROADMAP
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: rbr48 <rajbrur48@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
part that inherits its lines sends it, and the picker only shows No Border checked for it.
- CellProps::valign is Option<VAlign>: a cell's own Top (Align Top, w:vAlign="top") beats a
table style part's vertical alignment, and round-trips through .docx.
- tableStyle edit rejects Part fields at the top level without "part".
- "font": null or "" makes a part's font inherited; clearing the dialog's font box sends it.
- Document ui.dialog's optional "part" in docs/control-protocol.md.
Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>