Commit Graph
17 Commits
Author SHA1 Message Date
Martin BallandClaude Sonnet 5.5 28c5cbf139 #6005: escape file-derived errors where they become a Failure, not where they print
main() prints Failure::Error raw again, so the CLI's own multi-line messages (usage
after "missing argument" / "unknown command") keep their line breaks. A new
engine_error helper escapes control, bidi and invisible characters in text that
comes from the engine or a file, and every such conversion goes through it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8G9hbs6XYZFsgjbL
2026-11-08 16:08:46 +00:00
Martin BallandClaude Sonnet 5.5 00bbb147a1 #6005: escape every CLI error message, widen invisible-character escaping, cap picture names
main() prints Failure::Error through escape_text (control, bidi and invisible
characters; backslashes kept, since errors quote paths), so engine errors that
carry file text (run --cmd with strict:true) can't forge or spoof a line.
escape_peer and the JSON report line also escape soft hyphen, zero-width, word
joiner, BOM and tag characters (surrogate pairs above U+FFFF). A picture's part and
story are capped at 1024 characters in MissingPictures::push.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8G9hbs6XYZFsgjbL
2026-11-08 15:25:10 +00:00
Martin BallandClaude Sonnet 5.5 2600e22c8c #6005: keep pictures dropped inside altChunk DOCX, escape report lines
A DOCX altChunk's own dropped pictures are merged into the parent through
MissingPictures::push, named "<chunk part> > <story>". The strict report's human
lines go through escape_peer, and the JSON line escapes C1, line separator and bidi
characters (serde leaves them raw), so a crafted picture target can't forge or
spoof a terminal line.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8G9hbs6XYZFsgjbL
2026-11-08 14:56:09 +00:00
Martin BallandClaude Sonnet 5.5 3f38d0b8aa #6008: wordcraft-cli render --strict
render --strict passes strict to file.exportPng and, on refusal, prints the
report for the same page (human lines, then the JSON line) on stderr, exits 3,
and prints nothing on stdout. convert and render share one refusal helper.
Adds the engine guard that file.exportPng with strict off is byte-identical.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8G9hbs6XYZFsgjbL
2026-11-08 14:26:25 +00:00
Martin BallandClaude Sonnet 5.5 e3baa26815 #6005: strict export for PDF and PNG, wordcraft-cli convert --strict
Engine: StrictReport (missing glyphs + missing pictures, schema-1 JSON), pure
file.strictReport, and strict: true on file.save/saveAs/exportPdf/exportPng that
refuses with "strict: ..." before any write. PDF strict lays out once through
wordcraft_pdf::export_layout; PdfOptions now owns the display/layout options the
exporter and the check share. CLI: --strict, exit 3, report plus JSON line on
stderr; a non-pdf/png output is rejected before the input is read.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FypgCX8G9hbs6XYZFsgjbL
2026-11-08 13:24:00 +00:00
MexandMartin Ball ea8c45a4ca CLI: preserve non-Unicode input paths after options (#5611)
* M14: keep native CLI input names after options

* docs(M14): clarify native CLI path option exceptions

Qualify the roadmap summary and history: text option values need Unicode, while run --file and run --script retain native paths. Addresses review4485129728. Documentation only; no CLI behavior changes.

* docs(M14): qualify Unicode values in format parity notes

Exclude the existing run --file and run --script native path operands from the text option Unicode requirement. Addresses review4485129728; documentation only.

* docs(M14): qualify Unicode values in CLI gap notes

Document the existing native path exceptions for run --file and run --script. Completes the three-file wording correction requested in review4485129728, without changing readiness estimates or CLI behavior.

---------

Co-authored-by: Martin Ball <martin.ball@ucscaregroup.co.uk>
2026-11-08 02:52:08 +01:00
aiongg 00856d7178 Merge remote-tracking branch 'upstream/main' into w6
# Conflicts:
#	ROADMAP.md
#	crates/engine/src/session.rs
#	crates/ui-egui/Cargo.toml
#	crates/ui-egui/src/control.rs
#	crates/ui-egui/src/i18n/bg.tsv
#	crates/ui-egui/src/i18n/cs.tsv
#	crates/ui-egui/src/i18n/da.tsv
#	crates/ui-egui/src/i18n/de.tsv
#	crates/ui-egui/src/i18n/es.tsv
#	crates/ui-egui/src/i18n/et.tsv
#	crates/ui-egui/src/i18n/fr.tsv
#	crates/ui-egui/src/i18n/hr.tsv
#	crates/ui-egui/src/i18n/hu.tsv
#	crates/ui-egui/src/i18n/it.tsv
#	crates/ui-egui/src/i18n/ja.tsv
#	crates/ui-egui/src/i18n/ko.tsv
#	crates/ui-egui/src/i18n/nl.tsv
#	crates/ui-egui/src/i18n/pl.tsv
#	crates/ui-egui/src/i18n/pt-br.tsv
#	crates/ui-egui/src/i18n/ro.tsv
#	crates/ui-egui/src/i18n/ru.tsv
#	crates/ui-egui/src/i18n/sl.tsv
#	crates/ui-egui/src/i18n/sr-latn.tsv
#	crates/ui-egui/src/i18n/sr.tsv
#	crates/ui-egui/src/i18n/sv.tsv
#	crates/ui-egui/src/i18n/tr.tsv
#	crates/ui-egui/src/i18n/uk.tsv
#	crates/ui-egui/src/i18n/vi.tsv
#	crates/ui-egui/src/i18n/zh-hans.tsv
#	crates/ui-egui/src/i18n/zh-hant.tsv
#	crates/ui-egui/src/lib.rs
#	docs/gaps.md
#	docs/parity-checklist.md
#	docs/ui-parity.md
2026-10-24 03:53:36 +00:00
aiongg c795e3cd41 CI: one test binary per crate, nextest, line tables only (#4025)
* CI: line-table debug info for dev builds, none for dependencies

* CI: one integration-test binary per crate

* CI: nextest with doctests, test build without examples, one wasm check

* CI: the interface audit reports missing catalog entries instead of failing

* Docs: the interface audit, not CI as a whole, passes with missing catalog entries
2026-10-23 14:24:37 -04:00
aiongg a2ca57ca3f W1: MCP, control channel and CLI address an open document by id
- MCP: execute, batch, type_text, select_text, get_text, inspect_document,
  render_page and save_document take an optional doc (an open document's
  id); the headless server runs them through Session::with_document and
  the bridge passes doc to the app. New list_documents tool; new_document
  replies with the new document's id. Tool descriptions and the server
  instructions say that file.new and file.open open another document.
- Control channel: engine.execute, document.inspect and ui.render take
  doc and work on that document while the window keeps the active one;
  file.close on an addressed document refuses unsaved changes unless
  forced; ui.* commands need the document on screen. ui.inspect reports
  document and documents. Unknown or malformed ids are errors.
- CLI run starts with one open document; help and docs describe how
  file.new, file.open and view.switchWindows work in a run.
- docs/mcp.md and docs/control-protocol.md describe document ids and doc.
2026-10-22 14:53:21 +00:00
NaxvogandClaude Opus 5.5 fec27d66d1 CLI: run without --file uses the region's paper, like convert (#3152)
A bare `run` built its document with Document::new() (Letter) and never went
through file.new, so it skipped the system region's paper. It now runs
file.new, as `run --template` already did.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:54:41 +02:00
Fin WarmanandBrandon Thomas 81098c52f6 CLI: allow explicit field updates during conversion (#2014)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-18 03:45:57 -04:00
5f83a4727a get_text and CLI text omit tracked deletions (#866) (#944)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 00:21:06 -04:00
3cc0c16302 A file name that isn't valid Unicode no longer crashes wordcraft-cli or the app (#1440) (#1444)
* A file name that isn't valid Unicode no longer crashes wordcraft-cli or the app (#1440)

Both binaries read std::env::args(), which panics on a non-Unicode
argument such as a Latin-1 file name. The CLI now reads args_os(): the
file a command opens keeps its real name and opens (convert, info, text,
inspect, render, zotero, run --file), and any other such argument is an
error naming it, exit 1. The app leaves such a file out with a warning,
as it does a file that fails to open, since file.open takes its path as
text; a --control port that isn't valid Unicode exits 2.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* The app opens a file whose name isn't valid Unicode too (#1440)

file.open takes its path as text but also accepts the file's bytes
under a name, as dropped files use. The app reads such a file, opens
its bytes under the lossy name and keeps the real path on the session,
so Save writes back to it. A unit test covers the open and the save.

The CLI test now checks that every command in OPENS_FILE reaches its
open with the file, and no longer pins `pos` counting a `--page` value.
ROADMAP says which saves go back to the file.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #1440: skip non-UTF-8 file name tests on macOS

APFS refuses file names that aren't valid UTF-8, so the fixtures fail
with "Illegal byte sequence" there, and the app-start test keeps running
because macOS opens a window without a display variable. The unit test
for the CLI's argument checks and the control-port test still run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-14 19:32:48 -04:00
81b5602bf0 insert.picture and insert.icon leave the caret after the picture (#965) (#1437)
* contributors: add Nael-Nathanael

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* insert.picture and insert.icon leave the caret after the picture (#965)

A script that typed right after inserting a picture replaced it, so the
picture was missing from the saved file. Commands now leave the caret
after the new picture; Picture Format commands still act on it. The app
still selects a picture the user inserts, as in Word.

Fixes #965

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Select a pasted picture again, keep pictures inserted in a row (#965)

Desktop paste inserts through execute, so after the caret change it
left a pasted picture unselected. WordApp::select_inserted_picture
selects the picture just before the caret; run and the paste path call
it, paste once after the last picture so a multi-file paste keeps them
all. Tests for paste selection and for two inserts in a row.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-14 19:31:55 -04:00
1c2f0fe65e --help and -h print the usage for the app and every CLI command (#968) (#977)
* --help and -h print the usage for the app and every CLI command (#968)

wordcraft --help / -h printed nothing useful: the app tried to open a
file named --help and started. wordcraft-cli <command> --help failed with
"unknown option --help" for every command, and -h was taken as a file
name or ignored.

The app now prints its options and returns before the window opens.
The CLI checks for --help / -h after any known command before options
are validated or files and folders opened, and prints the shared usage.
Tests run both binaries for each command and flag; the app's test runs
without a display, so a regression fails instead of opening a window.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* #968: test bare --help and -h on wordcraft-cli

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-14 15:08:15 -04:00
bf2bd69470 HTML import: bold header cells, cell alignment and the region paper (#1381) (#1494)
* #1381: WIP

* #1381: HTML import: bold <th>, cell text-align, region paper for HTML/MD/TXT

Header cells are bold unless their own CSS says otherwise. text-align on a
td/th, or inherited from its tr/row group/table, aligns the cell's
paragraphs; a paragraph's own alignment wins, and a table's align attribute
(which places the table) no longer counts. Files that give no page size
(HTML, Markdown, plain text) open on the region's paper, as a new blank
document does: file.open uses the session's region, wordcraft-cli reads the
system region the way the app does (Region::from_locale_vars, shared with
ui-egui). Tables size to that page.

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

* #1381: the CLI uses the system region everywhere; help mentions WORDCRAFT_REGION

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

---------

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-14 13:58:14 -04:00
e5c55c0fc5 CLI: a closed stdout ends quietly instead of panicking (#508) (#510)
`println!` panics when stdout is a closed pipe, so `wordcraft-cli commands
--json | head` aborted with exit 101. Every stdout write now goes through a
locked handle with `writeln!` and propagates `io::Error`; a BrokenPipe becomes
`Failure::StdoutClosed`, which `main` treats as a normal exit 0. The MCP stdio
server's BrokenPipe takes the same path, so a client that hangs up ends the
server cleanly. Real errors still go to stderr with exit 1.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-11 11:13:01 -04:00