mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-25 10:57:14 -06:00
* LaTeX (.tex) import and export (#7) Open and save LaTeX source as a document format, next to Markdown and HTML. Export writes a standalone article (fontenc, ulem, xcolor, multirow, amsmath, hyperref, loaded only when used): unnumbered sections, itemize/enumerate, quote, center/flushright, verbatim, tabular with the document's column widths and merged cells, equations as $..$ / \[..\], character formatting, colours and links; metadata goes to \hypersetup. Import reads the everyday subset: preamble \title/\author, sectioning (\part/\chapter shift levels), paragraphs, lists with labels, quote, alignment environments, verbatim-like environments, tabular with \multicolumn/\multirow/\cellcolor and p{} widths, inline and display math, formatting commands and declarations, colours, links, refs, citations, footnotes, accents, TeX ligatures and special characters. Unknown commands keep their arguments' text; layout and definition commands are dropped with their arguments. Nesting is depth-limited and input is capped, so hostile files can't overflow the stack. The flow model gains an Equation inline so equations survive LaTeX round trips; the other text formats write their linear text as before. Wired into open/save dispatch, the file dialog filter, Backstage Export, the web app, CLI/MCP help, docs and the Linux desktop entry. Fixes #7. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019FczntrDNYd6DupyBdpbL5 * #7: bound LaTeX column specs and equation export (review) - spec_widths: `*{n}{…}` repeats recurse with a depth argument and stop at MAX_NEST, so a deeply nested column spec no longer overflows the stack or exhausts memory. Column counts saturate and widths stop at MAX_COLS. - Column specs read from the source are capped at MAX_SPEC (4096) chars. - balanced() looks groups up in a table of closers built in one stack pass, so linear_to_latex no longer rescans to the end of the string for every unmatched `(` (quadratic: 50k took seconds). spec_widths uses it too. - env_name restores the position when `\begin{` / `\end{` has no `}` within 64 chars, so the `{` is no longer lost. - Regression tests: the 100k-deep `*{1}{` spec and a 200k-`(` equation in deep_nesting_is_bounded; unclosed_begin_keeps_its_brace and spec_widths_repeats_are_bounded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LyVbT6Vv4BwWZ4hY8973qD * #7: linear-time labels, brackets and \begin{; no commands from the document in exports Applies @HaringIbon's review suggestions: 1. Parser::anchor keeps at most MAX_ANCHOR_RUN (64) bookmarks in a row with no text between them; text() looked back past every one, so a file of labels imported in quadratic time. Labels separated by text are all kept. 2. linear_to_latex_at checks for the `/` of a fraction before copying the group out, so deeply nested matched brackets export in linear time. 3. env_name searches only the next 65 bytes for `}`, so a run of unclosed `\begin{` imports in linear time. 4. An equation's `\name` is written as a command only when it is a known symbol, function or font/spacing command (MATH_COMMANDS); anything else becomes `\backslash name`. Two carets are never written side by side in equations or anchor names, since TeX reads `^^5c` as a backslash. Compiling an export can no longer `\input` files or `\write18` named by the document. Regression tests: three cases added to deep_nesting_is_bounded, plus latex_export_carries_no_commands_from_the_document and latex_labels_in_a_row_are_read_in_linear_time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LyVbT6Vv4BwWZ4hY8973qD * Merge follow-ups: FTable.borderless (from #102) in the LaTeX importer; rustfmt 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>
1.6 KiB
1.6 KiB
MCP server
WordCraft speaks the Model Context Protocol over stdio, so Claude and other agents can write and edit documents.
wordcraft-cli mcp # headless session (no window)
wordcraft --control 7981 & # or: drive the running app…
wordcraft-cli mcp --connect 127.0.0.1:7981 # …including clicks, keys and screenshots
Claude Code: claude mcp add wordcraft -- wordcraft-cli mcp.
With --connect, the bridge sends the app's control key, which it reads from
WORDCRAFT_CONTROL_KEY or from the key file the app writes at start. It sends the key only to
loopback addresses; see Keys.
Tools
| Tool | What it does |
|---|---|
list_commands |
every command (filter with query) — over 270 of them |
execute |
run one command: {command: "insert.table", params: {rows: 3, cols: 4}} |
batch |
run several commands in order |
new_document |
blank, sample, letter, resume, report |
open_document / save_document |
docx, odt, rtf, html, md, tex, txt, json; save also pdf, png |
type_text |
type at the caret (paragraphs: true splits lines into paragraphs) |
select_text |
select the n-th occurrence of some text |
get_text / inspect_document |
read the document back (verify without screenshots) |
render_page |
a page as PNG |
parity |
feature coverage |
screenshot, click, key, ui_inspect |
app only (--connect) |
Resources: wordcraft://document (inspect) and wordcraft://commands.
The acceptance test crates/mcp/src/tests.rs writes a formatted document using MCP only.