- Wire craft-wordmodel, craft-docx, craft-rtf (doc), and craft-doc-binary into workspace
- Delete ~26,300 lines of app-owned DOCX parser/serializer in crates/docx
- Implement zero-copy media transfer and FitState custom XML round-trip via craft_wordmodel bridge
- Delete ~5,400 lines of app-owned RTF parser/serializer in crates/formats/src/rtf
- Delegate RTF import, export, parse, and esc to craft-rtf
- Add cfb_guard DIFAT validation and float sanitization on model bridge
- Net reduction: 31,697 deletions, 818 insertions (-30,879 LOC)
#6537 declared a test change but committed 50 text files with CRLF, which
`cargo fmt --check` does not catch. Restore the bytes from c37baf76: no text
file carries CRLF, and the tree is identical to that commit again.
Refs #6537, #6539.
The #5858 early return kept page anchoring for any object that does not
move with text, which includes a body frame that came from an .odt with
text:anchor-type="page". Moving it then skipped the paragraph placement
and the save wrote the page anchor and number back, contradicting #5705's
an_odt_frame_moved_from_its_page_loses_the_page_number.
Only header/footer objects (and drops on a page with no anchoring text)
keep page anchoring now, which is what #5812 needed. The body test that
pinned the opposite is updated to the #5705 rule.
- Recognize a marked Fit One Page custom XML store across package and document
relationships, skipping passthrough only after loading successfully.
- Reserve the Fit One Page part path in EmbedWriter taken paths to prevent collisions.
- Track typography provenance per formatting location rather than sorted multisets.
- Validate stepPt parameter and reject non-positive or non-finite values.
- Report "already fits on one page" before an exhausted cumulative budget.
* docx: ignore w:lnNumType without w:countBy (#6209)
* DOCX: record the w:lnNumType rule in the parity docs (#6209)
A row for `w:lnNumType` (§17.6.8), its status line and a revision entry in
`docs/file-format-parity.md`, the progress-log bullet in `ROADMAP.md`, a comment in
the reader saying why a missing `w:countBy` leaves numbering off, and a save check in
the zero-interval test.
- Record original and reduced font sizes, line spacings and paragraph
spacings as multisets, so restoring neighbouring sizes clears the
exhausted budget, and paragraph spacing keeps the budget when line
spacing rounds back to its original.
- Resolve font and spacing budgets independently, letting the remaining
component be used instead of refusing the whole command.
- Persist FitState in a namespaced DOCX custom XML part and restore it on
read; add a DOCX round-trip regression.
Pass LayoutOptions::hides_deleted per story into the explicit-break scan and
the font floor, so hide_marked, revisions in balloons and moved-from text are
seen exactly as Print layout sees them. This keeps the guards from counting
deletions the page no longer contains.
- Anchor cumulative budget provenance to the original sizes and spacings
recorded before the first fit, instead of matching every current value
against every recorded value. Restoring body and heading sizes now resets
the budget.
- Build the initial and trial layouts from the session's hide_marked,
deletions_in_balloons and resolved numeral settings, so hidden or
ballooned deletions and numeral shaping paginate as in Session::layout.
- Add regressions for mixed body/heading sizes, mixed line spacings, and
Session::layout parity under non-default visibility and numeral settings.
The gate's Clippy flags needless_range_loop in the borderless/bordered table
fixtures. Iterate the rows and cells mutably instead; no behaviour change.
Resolve each cell's conditional table-style character formatting before
checking whether a page break is hidden, matching min_blocks_font_size and
layout's region selection. A first-row or banded hidden override now agrees
with Print layout. Add a regression with a hidden first-row override.
- Round paragraph spacing up to hundredths, so a very small value is never
reduced by more than the requested factor.
- Ignore page-break characters in hidden or tracked-deleted runs, matching
Print layout visibility, so a hidden break cannot force a refusal.
- Scale paragraph spacing without rounding a small value to zero or
compressing past the requested factor.
- Detect resolved page_break_before and nested table paragraphs as explicit
breaks, and refuse before evaluating candidates.
- Count non-text body items in the final-page volume limit.
- Give the ribbon button an accessible label and test it through the
rendered Layout ribbon in both themes.
* View: editable Markdown source view for .md files (#5826)
Co-authored-by: oldgranola <marken.john206@gmail.com>
* Address review feedback on Markdown source view
- Fix view.markdownSourceText purity and input validation
- Single-pass block line mapping in markdown parser
- Reuse parsed documents and block line ranges on apply and leave
- Bound memory usage with MAX_SOURCE_BYTES and clamp caret byte offsets
- Isolate temp directories in tests and test caret validation
- Preserve dirty state while markdown text edits are pending
- Flush pending markdown text edits in swap_doc
* Address CodeRabbit review feedback on Markdown source view
- Exempt view.markdownSourceText in command refusal
- Preserve original source line mapping when filtering link definitions
- Map between egui char indices and byte-offset caret in history and undo
* Remap block line numbers in a single linear pass
* Refuse over-limit Markdown Source edits to prevent document truncation
* Keep a Markdown file's own text when it is opened from handed-over bytes
`file.open` kept a Markdown file's exact text only for path-backed opens, so a
platform that hands the bytes over (data) lost front matter, comments and the
author's line endings on the first save, and the rewritten flag could not say
so. The kept text now comes from the same bytes `read_document` decodes, still
bounded by MAX_SOURCE_BYTES through FileText::from_bytes; the path read stays
for opens without data.
---------
Co-authored-by: oldgranola <marken.john206@gmail.com>
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
Add layout.fitOnePage, a speculative typography search that removes one
page from the document while preserving relative font hierarchy.
Every size receives the same half-point-rounded reduction; line spacing
never falls below 0.94 of its original and body text never below 8.5 pt.
The command refuses on explicit page breaks, excessive final-page content,
formatting protection, tracked formatting and the cumulative 1 pt budget,
and leaves the document unchanged when it refuses.
Add the Layout ribbon button, KeyTip and a code-drawn icon, cover the
command with 41 tests, and regenerate the parity checklist.
system_clipboard::fill recomputed privateClipboard whenever the host could report ownership, overwriting the value the Paste Special dialog captured when it opened. Only compute it when the caller supplied none, so the dialog's format list and the paste agree while ribbon and agent calls keep reading ownership from the clipboard.
Paste selected WordCraft's own fragment whenever the system clipboard text matched, even when the host reported that another program owned the clipboard, so a plain-text copy made elsewhere could paste the earlier bold fragment back. Read privateClipboard in paste_content and in the Formatted Text source, using the session fragment only when ownership is true or the caller omits the flag (agents and the CLI keep working). Carry the flag through the Paste Special request and dialog so its format list matches.
- Recognize the XDG document portal mount inside a Flatpak sandbox
(`/run/flatpak/doc/`), so a changed extension reopens the dialog for the
overwrite confirmation like the host mount does.
- Give the portal SaveFile request a real cancellation path: the CancelToken is
armed before the waiting thread starts and cancelled when the system dialog is
given up (File > Open > Browse in WordCraft...). The request closes and the
answer reads as a cancel, so a portal that stops answering cannot keep Save As
stuck; a late cancel after the answer is ignored.
- Map the cancellation error to a cancelled dialog instead of the rfd fallback.
- Regression tests for the Flatpak mount, the CancelHandle arm/cancel/disarm,
and the UI calling the host's cancel hook when the dialog is given up.
Co-authored-by: CommandCodeBot <noreply@commandcode.ai>