Commit Graph
770 Commits
Author SHA1 Message Date
Martin BallandClaude Opus 5.5 7aab0b202c FU.3: language packs — the status bar's pack lookup is cached by index generation, not copied every frame
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 01:52:21 +00:00
Martin BallandClaude Opus 5.5 d393e99879 FU.1: language packs — a user's cancel isn't an error; Install right after Cancel starts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 01:52:21 +00:00
Martin BallandClaude Opus 5.5 34525f1cb1 CP4.3: review — regression test: a same-length index refresh still changes index_generation, so the missing-pack bar works it out again (CodeRabbit)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 01:04:00 +00:00
Martin BallandClaude Opus 5.5 03c50f8af2 CP4.3: restack on #5205 — craft-proof #485 bdd434bc and font store #486 83c2e7b from storytold/craft-libs, craft-i18n 059cbf9; SCOWL notice in About; no "(no dictionary)" or bar for a language with no pack; Swiss German and Portugal's Portuguese keep their names
- craft-proof now names ja, zh and th in missing_dictionary: packs::missing_dictionary hides it
  for a pack language when no pack for it is listed (status bar and Options).
- de-CH and pt-PT are pack languages in craft-proof (de-ch, pt-pt): names, hyphenation and
  grammar stay German and Portuguese (tests); pack names fall back to the region-aware name.
- About › Language data shows craft_proof::scowl::notice() when SCOWL is embedded (test).
- Flatpak manifest's craft-i18n commit follows craft-i18n.rev.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 01:04:00 +00:00
Martin BallandClaude Opus 5.5 1146691b90 CP4.3: review — craft-libs at #485 f88bd48 / #486 83c2e7b; test-source warning in proof.packs, the CLI and the bar; About › Language data a fixed-height list; Cancel reaches a stalled download
- proof.packs reports index_override; the CLI prints the test source; the bar's Install tooltip
  says it turns on downloading of fonts and Language packs, and names a test source.
- Docs: Install works once language-packs-1 is published (until then only a test index); with a
  test index the sha256 only catches a broken download.
- About › Language data keeps its size: a fixed-height scrolling list, licence texts read again
  only when the dictionaries change.
- The engine's Cancel is the font store's own flag (no snapshot), so a cancel stops a fetch or a
  stalled download too.
- Index text shown without control, bidi or format characters; long names cut; the bar works out
  what to offer again when the list changes (index generation, not its length).
- ui_shot's store is a temporary folder (or storeDir); tests reset the backend even on panic; a
  fixture pack proves per-run proofing and hyphenation from a pack.
- The default-build check follows craft-proof's carry-over (de, pl, pt, it, ru embedded until packs
  ship; CRAFT_PROOF_EMBED=en is English only); the Polish hyphenation check runs again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 01:04:00 +00:00
Martin BallandClaude Opus 5.5 c1490c5ba9 CP4.3: review — a click from the control channel never turns on downloading; installs and refreshes run in the background in the app; parked documents proof again after a pack change
- Install, Show available languages and Refresh turn on the font store's downloading only on the
  person's own click (input_from_control, as in #959); a faked click says why instead.
- proof.installPack and proof.packs {refresh} run on the engine's thread in the app ("started"),
  with progress, results and errors in proof.packs; the CLI and headless MCP stay synchronous.
- A session's layout is keyed on the dictionaries' generation, so parked documents proof again.
- proof.removePack refuses while that pack installs; pack commands that need a locale are left out
  of Search; options text names Refresh; licence tooltip says Source; errors go through tl!;
  the bar rescans at most once a second while typing; English names for every pack language and
  sr-latn; About has one Close button; xtask doc comment back on cmd_i18n_report.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 01:04:00 +00:00
Martin BallandClaude Opus 5.5 efb7d8ef20 CP4.3: craft-proof pinned to storytold/craft-libs#485's rebased head (6e8eb65), font store to #486 (d342a50); Pack languages report their tag
- `review.issues` and `file.options` report a run's language with `ProofLang::tag()`, so a
  Pack language reports its locale, not "".
- The test-source warning reads craft-font-store's `language_pack_index_overridden()`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 01:04:00 +00:00
Martin BallandClaude Opus 5.5 2ef046bad9 CP4.3: craft-libs pinned to Lane 4's pushed heads; test-source warning, upstream source links, code-drawn bar close button
- craft-proof (benandez/craft-libs 6ae4f03, storytold/craft-libs#485) and craft-font-store /
  craft-font-catalog (630e42f, #486) by git rev instead of local paths.
- ProofLang::Pack: the bar offers every language with a pack (zxx/und never).
- Options › Language warns when CRAFT_LANGUAGE_PACK_INDEX supplies a test index.
- Pack `source` (upstream link) when the index gives it, else the archive.
- The bar's close button is the code-drawn close icon: "✕" had no glyph in the interface fonts
  and egui panicked drawing it.
- `cargo xtask language` allows our own ru-extra, which stays embedded.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 01:03:59 +00:00
Martin BallandClaude Opus 5.5 e5d46bb242 CP4.3: Language packs: proof.packs, proof.installPack, proof.removePack; Options › Language list, missing-pack bar, About › Language data
- engine `packs`: the packs Backend (the font store on the desktop and CLI, a fixed list in tests
  and ui_shot), the pinned index, installs and removals through craft-font-store's
  `language-pack` kind, craft-proof reading the store's `language-packs/` folder at once.
  Commands open nothing and never turn downloading on (only an Install click in the app does);
  confined automation can't write the packs folder outside its write root.
- ui-egui `language_packs`: File › Options › Language › Language packs (name, size, licence,
  source, Install/Remove, progress, errors), the missing-pack bar (dismissible per document,
  never for a language without a pack), About › Language data (full licence texts).
- CP4.4: `cargo xtask language` (in `ci`): the default build embeds only en-* Language data.
- CP4.5: docs (help, MCP, control protocol, gaps #8, localization parity, roadmap).
- Path deps to Lane 4's worktrees while developing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 01:03:59 +00:00
Martin BallandClaude Opus 5.5 09e9522a35 CP2.3: English spelling reads SCOWL 2026; regression tests for #40, #520, #1281, #1045
craft-proof moves to storytold/craft-libs#483's head (e6e948f, on #482's
9e5862a): each English checks against its own SCOWL rel-2026.02.25 dictionary
through the affix engine (ordinals via COMPOUNDRULE), with en-variants.txt as
the dialect policy. Lookup order: dictionaries folder, [English pack], SCOWL,
system Hunspell, the built-in Moby list; Moby stays for hyphenation.
craft-i18n.rev and the Flatpak source move to storytold/craft-i18n#109's merge
commit (efb1127), which adds the SCOWL files.

Typed-text tests pin British spellings in en-GB (#40), modern words (#520),
Canadian/Australian/NZ/Indian English (#1281, #1045) and ordinals; they skip
without the Language data, as the other data tests do. Docs: typing-parity,
localization-parity, ROADMAP progress log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 00:31:38 +00:00
Martin BallandClaude Opus 5.5 b7dad64d94 CP1.3: review — no-data proofing described right, NOTICE names craft-i18n's hyphenation.pat files, Flatpak dictionaries folder, printing checkout without credentials, data gate asks the variant table too
CodeRabbit on #5202:
- AGENTS.md, ATTRIBUTION.md, README.md, docs/architecture.md: without
  CRAFT_I18N_DIR English spelling falls back to an installed Hunspell English
  or craft-proof's built-in Moby list, and only pattern hyphenation is off
  (Bulgarian, Turkish and Russian hyphenate by rule); they said English
  wasn't spell-checked. (CLAUDE.md carries the same sentence; left for the
  maintainer, as agents don't edit it.)
- NOTICE: craft-i18n's patterns are language-data/<lang>/hyphenation.pat,
  not en-us.pat, pl.pat, pt.pat, de.pat, it.pat.
- docs/spelling-dictionaries.md: the Flatpak's dictionaries folder is
  ~/.var/app/ai.storyteller.wordcraft/data/wordcraft/dictionaries; the host's
  folders are outside its sandbox.
- printing.yml: the repository checkout doesn't persist credentials.
- tests.rs no_language_data: also probes the American/British variant table,
  so a craft-i18n checkout missing some files skips the dialect tests
  instead of failing them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-02 00:31:32 +00:00
Martin BallandClaude Opus 5.5 36400f69eb CP1.3: review — no_language_data says what it probes (the embedded en-us list, present exactly when CRAFT_I18N_DIR's data is)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-01 20:13:12 +00:00
Martin BallandClaude Opus 5.5 9d5b98eb18 CP1.3: review — six engine tests run again without the Language data now that craft-proof's built-in English is the Moby list
Polish/Portuguese/Czech review commands, the custom dictionary file and the two typing squiggle
tests pass without CRAFT_I18N_DIR at 48ed6f8. English dialects, regions' English and Hyphenation
Options still need the variant table and patterns, so they keep the skip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-01 20:13:12 +00:00
Martin BallandClaude Opus 5.5 8c3a792b49 CP1.3: review — engine tests that need the Language data skip with a note naming CRAFT_I18N_DIR when none is embedded, as craft-proof's do
cargo test -p wordcraft-engine now passes without CRAFT_I18N_DIR (10 tests return early) and
still runs them all with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-01 20:13:12 +00:00
Martin BallandClaude Opus 5.5 3110dcf02b CP1.3: proofing comes from craft-proof (craft-libs), its data from craft-i18n
- wordcraft-proof is now `package = "craft-proof"` from craft-libs (local
  path for now; TODO in Cargo.toml for the git+rev pin after the craft-libs
  PR merges). `wordcraft_proof::` paths are unchanged.
- crates/proof and assets/{spelling,hyphenation} deleted with their
  ATTRIBUTION.md rows; one row now points at craft-i18n's Language data;
  NOTICE paths updated.
- craft-i18n.rev (and the flatpak source) moved to the craft-i18n commit that
  adds language-data/ (CI sets CRAFT_I18N_REQUIRED=1, so the pin must have it).
- xtask layers: proof removed. Engine tests carry their own copy of the
  synthetic Czech fixture (they reached into crates/proof/src).
- Docs: architecture.md, CLAUDE.md/AGENTS.md layer table, README build note
  (CRAFT_I18N_DIR), localization-tr path, ROADMAP progress log.

Before/after wordcraft-cli on a 17-language proofing document: issues,
suggestions, manual hyphenation, PDF text and PDF bytes identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8LsYYE8fsj4byBm2
2026-11-01 20:13:03 +00:00
aiongg 9c72ddf56a Merge pull request #5000 from benandez/integration/batch-proof
Integration batch proof: 2 approved proofing PRs (merge commit, please)
2026-11-01 10:46:45 -05:00
.CooCoo e868e2a83f Tests: border lines, tab indents and wide spaces before a word (#4235)
Tests and notes for rules that #4129, #4113, #4109 and #4101 added and
left uncovered:

- A border line at the top of a story with formatting left out of the
  Track Changes markup is not a formatting change, and Reject All keeps
  it.
- The author's own earlier formatting change on that paragraph stays the
  one change.
- Reject All keeps the table of a "+---+" line.
- A border line that a content control's lock stops Backspace from
  deleting stays as it is, and Enter is refused, untracked too.
- With tab indents on, Tab in a table cell moves to the next cell; with
  them off, Backspace before an indented paragraph joins it.
- AutoCorrect and the spelling check's web and e-mail addresses after a
  narrow no-break space and a figure space.

docs/typing-parity.md describes each, and lists a no-break space typed
after a word, which does not finish the word for AutoCorrect, as a
known gap.
2026-11-01 10:46:25 -05:00
401c6c0dc2 References: a table of contents writes its page numbers as PAGEREF fields, as Word does (#5097)
A hyperlinked TOC wrote each entry's page number as plain text inside the
link. Word writes it as a PAGEREF _Toc… \h field, so Update Field in Word
moves the number with its heading; with plain text the numbers stay what
they were when the file was saved.

Entries that link to a bookmark now end with that field (result: the page
number). Entries without a link and \n levels are unchanged. The DOCX span
test looks for the TOC's own end, the last one, since PAGEREF fields now end
inside it.

Co-authored-by: dfgodvan <180286157+dfgodvan@users.noreply.github.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-31 11:53:56 -04:00
6dae5a1d17 Detect CSV separator from the first non-blank line (#5042)
Found while testing crates/engine/src/cmd/mailings/recipients.rs:6-18 (csv_separator)

Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-31 10:50:10 -04:00
a2f387567d Printing: the print job's PDF leaves out link annotations, so documents with links print (#4734) (#4817)
* #4734: the print job's PDF leaves out link annotations

craft-print refuses to fit a page with annotations to the paper ("flatten page annotations
before using shrink-to-fit"), and the desktop app always prints with ShrinkToFit, so any
document with a hyperlink or a TOC (its entries are links) failed to print. Links print
nothing; `PdfOptions::links` (default on) lets the print job leave them out. Exported PDFs
keep them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* #4734: review — the print note is in every desktop column; gaps and progress log

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* #4734: doc wording: the print PDF omits link annotations; hardware still to validate

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* #4734: only the printer's PDF drops links; Save these pages as PDF keeps them

Session::print_job_pdf is what ui.printSubmit sends to the spooler, without
link annotations; Session::print_pdf (file.printPdf) keeps them again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-31 10:26:28 -04:00
socrabs151andBrandon Thomas 028d413ad6 #3676: page parameters saturate instead of wrapping to page one (#4289)
* fix(engine): saturate page parameters on 32-bit and wasm (#3676)

The file.exportPng and edit.goto paths cast a u64 page to usize and subtracted one. On 32-bit and wasm, page 2^32 truncated to 0 and the subtraction wrapped to page 1 (a debug panic).

Add p::page_index, which saturates instead of wrapping, and use it in both engine paths. The MCP render path already has the same guard on main; the new tests also pin that behavior.

Regression tests cover the helper, Go To, PNG export and the MCP render path.

* fix(engine): guard caret.set page cast too (#3676)

caret.set takes a 0-based page; pg as usize truncated on 32-bit and wasm and could select page 0. Use the same checked conversion and add a regression test.

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-31 10:08:13 -04:00
Martin Ball 2424bf8caf Merge #4191 2026-10-30 21:16:12 +00:00
ReesandBrandon Thomas a4b1682b41 Index laid-out objects during connector rerouting (#3631) (#4622)
* #3631: index laid-out objects during connector rerouting

* docs: keep the gaps.md note in the status line and revision table

* docs: drop a stray blank line

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-30 00:13:32 -04:00
9632646c5e Bibliography: keep a source's corporate author (#4848) (#4898)
* #4848: corporate authors in bibliographies

A Word source whose author is an organisation (Create Source › Corporate Author)
stores it as `b:Corporate`, which the reader ignored: the source opened with no
author, citations fell back to the title and bibliography entries started with
the year. A bare name typed into Author was split into "Organization, W. H.".

- Source gains `corporate`, read from and written as `b:Corporate` (in place of a
  name list: a role holds one or the other, ECMA-376 CT_NameOrCorporateType).
- Citations and bibliography entries write it as it is in every style; it gives
  the source's tag and its place in an author-sorted list, and untagged sources
  are matched by it.
- APA puts its full stop after a group author ("World Health Organization.
  (2021).") instead of relying on the initials for it.
- Create Source has a Corporate Author box under Author; Edit Source opens with
  it checked when the source has one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LvG6DxS4tKmWSLCiDPvb4G

* Match untagged sources by corporate author before personal author

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-30 00:12:17 -04:00
ReesandBrandon Thomas 18ae8b2150 DOCX: preserve custom-property bookmark links (#4767) (#4771)
* M12: preserve custom-property bookmark links (#4767)

* M12: preserve bookmark links across property renames (#4767)

* M12: align custom-property preservation status dates (#4767)

* docs: keep the gaps.md note in the status line and revision table

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-30 00:11:27 -04:00
9a172e2241 Table Properties: row, column and cell settings follow the selection (#4857) (#4896)
Row, column and cell settings applied to the caret's row, column and cell only, so
selecting the whole table and unticking "Allow row to break across pages" changed
one row and the others still split across pages.

- table.properties applies row height and rule, allow break and header row to every
  selected row, the column width to every selected column, and the cell width and
  vertical alignment to every selected cell (the caret's with nothing selected), in
  one undo step.
- The dialog shows "Allow row to break" and "Repeat as header row" as mixed when the
  selected rows differ; left alone they change nothing, clicked they set every row.
- The row-height rule box is named by "Specify height" for screen readers.


Claude-Session: https://claude.ai/code/session_01LvG6DxS4tKmWSLCiDPvb4G

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-30 00:10:33 -04:00
ReesandBrandon Thomas db2b3cab99 Home › Font: step each selected run from its own size (#4903) (#4910)
* M2 #4903: step each selected run from its own font size

* docs: keep the gaps.md note in the status line and revision table

* docs: drop a stray blank line

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-30 00:09:39 -04:00
665ded2800 Cross-reference: captions in a style based on Caption (#4411) (#4881)
* #4411: captions in a style based on Caption are cross-reference targets

Cross-reference and Table of Figures found captions only by the exact
Caption style, so a caption restyled with a style based on Caption (a
label's own "Caption Table") was left out: of five tableX captions,
only the two still in Caption were offered. A caption is now a
paragraph whose style is Caption or based on it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* #4411: test captions two styles from Caption and the Table type

Covers a style based on a style based on Caption, a Table caption in
such a style offered under the built-in Table type, and a caption
label used only in a style not based on Caption staying out of the
cross-reference types.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-30 00:09:01 -04:00
Yasas SriandBrandon Thomas d40e0eeb47 #4086: highlighting at a caret leaves the word alone (#4701)
* #4086: highlighting at a caret leaves the word alone

* #4086: the highlight toggle reads pending caret formatting; word formatting updates it

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-30 00:08:31 -04:00
Harrison BoothandBrandon Thomas 2e790d549c Backspace after a floating shape's anchor keeps the shape (#4592) (#4641)
* Backspace after a floating shape's anchor joins paragraphs and keeps the shape (#4592)

* wc-upkeep-6: protect Backspace joins and markers

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-30 00:07:53 -04:00
ReesandBrandon Thomas 74b2cbb5c9 Backspace: keep Arabic base letters when removing marks (#4757) (#4761)
* 4757: keep Arabic base letters when removing marks

* docs: keep the gaps.md note in the status line and revision table

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-29 23:53:06 -04:00
22e99fc2b7 Tables can be copied and cut: whole tables, rows and cells (#1744) (#1784)
* #1744: WIP

* #1744: Select Table copies and cuts the whole table

Copy of a whole-table selection used to keep only the cells' paragraphs
(copy_blocks flattened a cross-cell range), and Cut only cleared the text.
Now Copy puts the table on the clipboard and Cut removes the table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* #1744: selected table rows and cells copy as a table; Cut clears their text

Copy of whole rows, cells of a row or a block of cells puts a table of just
those cells on the clipboard (Table::slice). Cut of rows or cells clears their
text and keeps the rows and cells, as in Word (Word check A).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* #1744: review fixes

Table::slice widens every row to a merged cell partly selected (no ragged
copy); an empty selected table or cell copies and cuts; a text selection over
exactly a nested table copies it; one selected_table per Cut; tests for
slice merges/widths/controls, tracked and locked cuts, and the text route.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* #1744: Cut clears every cell Copy takes; Spike stays off for empty cell selections

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* #1744: a copied part of a percentage-width table keeps a point width

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ROADMAP: tidy merged header

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ROADMAP: keep only the #1744 rows over main's version

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* ROADMAP: remove conflict markers; keep only the #1744 rows over main's version

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* #1744: rename the range Cut helper clear_range_cells (main added clear_cells)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Remove conflict markers from ROADMAP.md; leave main's header line alone

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* cargo fmt

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* Import Path in table structure after merging main

---------

Co-authored-by: Dmitrii Khlapov <19991457+dkhlapov@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-29 21:47:27 -04:00
VoiceLessQ 0d41b18301 Engine tests: the dictionaries-folder test checks each reported file again
The shared dictionary slot reports no file while a dictionary given
with install_dictionary is in use, so this test had accepted null
alongside the folder's file, for installs from tests running at the
same time. That also let it pass if file.options stopped reporting the
folder's file at all. The tests' install helpers and this test now take
turns on one lock, and each language must report the folder's file
again. An install from before the test doesn't matter: changing the
folder reloads every slot.
2026-10-29 15:38:01 -02:00
OPUZZLES 01a1bf3921 M9: assert unused recipient labels are empty (#4880) 2026-10-29 18:14:46 +01:00
VoiceLessQ 744addabf2 Merge origin/main
main split Czech's suggest_in into one helper per round for the
cognitive_complexity limit (#4501). On this branch that code is the
shared affix_suggest::suggest_in (36 of 30), so cs/suggest.rs stays the
thin wrapper and the shared function gets the same split. The candidates
are offered in the same order; a dump of 13,081 calls over every
language's test dictionary matches the old engine except one: the typo
round counts the lower-cased letters, so "İ" (two letters lower case)
now gets "I" in Polish, where the old count stopped one letter short.
2026-10-29 14:55:30 -02:00
OPUZZLES 5a9e414d1e M9: generate all recipient label sheets (#4880) 2026-10-29 17:49:08 +01:00
Dylan M. Taylor ab91e9f96c Deflake the IME epoch test 2026-10-28 01:06:49 +00:00
Dylan M. Taylor a2435388e5 Refactor engine for strict Clippy checks 2026-10-28 01:06:48 +00:00
VoiceLessQ 62948a2c31 Merge remote-tracking branch 'upstream/main' into fix/proof-shared-language-engine
# Conflicts:
#	crates/proof/src/es/mod.rs
#	crates/proof/src/tr/mod.rs
2026-10-27 15:36:17 -02:00
NetterSilverandClaude Opus 5.5 8cdc172171 Lay out the paragraph after a kept heading once
A paragraph with keep with next measures the paragraph after it before it is
placed (next_first_line). That measurement called layout_para directly, so
every paragraph following a heading was laid out twice in each layout pass:
once to measure it and once, through the cache, when it was placed.

The measurement now goes through the layout cache under the key
para_labelled uses (Ctx::para_ahead) when its inputs are the same: no
proofing, no typed word, not inside a text box, no inline text boxes that
resize, the body's tracked-deletion view. Otherwise it is laid out on its
own as before. It counts nothing (list labels, equation numbers and the
page-total flag are restored), so pagination is unchanged.

Adds crates/engine/examples/export_bench.rs, which saves a long generated
document (the sample document 200 times, 259 pages) through io::save_bytes
and prints wall times:

  cargo run --release -p wordcraft-engine --example export_bench -- pdf 200 9

PDF export on that document, interleaved with main (Ryzen, 16 threads):
median 286 ms -> 256 ms (-10.6 %). The PDF bytes are identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 13:39:09 +01:00
aiongg 0404b4199a test: file_access scan stops only at inline test modules 2026-10-26 22:10:26 +00:00
aiongg 835704f870 refactor(engine): move session::ime_state to the crate root as ime 2026-10-26 21:16:49 +00:00
aiongg 39336fe844 refactor(engine): move session::snapshot_types to the crate root as snapshot 2026-10-26 21:16:49 +00:00
aiongg 5a311f4615 refactor(engine): move session::prefs to the crate root as prefs 2026-10-26 21:16:49 +00:00
aiongg 8f1f3c6132 refactor(engine): move session::view to the crate root as view 2026-10-26 21:16:49 +00:00
aiongg e027a4244b refactor(engine): move session::doc_state to the crate root as doc_state 2026-10-26 21:16:49 +00:00
aiongg 3c4d7adc87 refactor(engine): move session::locale to the crate root as locale 2026-10-26 21:16:49 +00:00
aiongg cfa90220d9 refactor(engine): split session.rs into session/ 2026-10-26 21:16:49 +00:00
aiongg 8f10bd1b9f refactor(engine): split cmd/table.rs into table/ 2026-10-26 21:16:49 +00:00
aiongg a82063e50a refactor(engine): split cmd/insert.rs into insert/ 2026-10-26 21:16:49 +00:00