mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-27 20:07:19 -06:00
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CX1hMKX28764Lrx5moxs1o
96 lines
5.5 KiB
Markdown
96 lines
5.5 KiB
Markdown
# Zotero
|
||
|
||
WordCraft works with the [Zotero](https://www.zotero.org) desktop app the way Word does: Zotero's
|
||
own citation dialog, all of its citation styles, automatic bibliography and refresh. Nothing to
|
||
install in Zotero; it only has to be running. The **Zotero** tab in the ribbon has the buttons:
|
||
Add/Edit Citation, Add Note, Add/Edit Bibliography, Refresh, Document Preferences and Unlink
|
||
Citations (each runs one of the commands below).
|
||
|
||
## Commands
|
||
|
||
| Command | What it does |
|
||
|---|---|
|
||
| `ui.zotero.addEditCitation` | Add a citation at the caret, or edit the one the caret is in |
|
||
| `ui.zotero.addEditBibliography` | Add the bibliography at the caret, or edit it |
|
||
| `ui.zotero.refresh` | Update every citation and the bibliography |
|
||
| `ui.zotero.setDocPrefs` | Citation style, language, footnotes or in-text |
|
||
| `ui.zotero.removeCodes` | Unlink citations: keep the text, drop Zotero's codes |
|
||
| `ui.zotero.addNote` | Insert a Zotero note |
|
||
| `ui.zotero.status` | `{busy, waitingForAnswer, last}` |
|
||
| `ui.zotero.answer` | `{"button": n}`: answer a question Zotero is asking (OK/Yes 1, No/Cancel 0; with Yes/No/Cancel: Yes 2, No 1, Cancel 0) |
|
||
|
||
They run in the app (and through the control channel and MCP bridged to the app). A command
|
||
returns at once with `{"started": …}`; Zotero then works in its own window and WordCraft answers
|
||
it in the background. All changes from one command are one undo step. If New or Open replaces
|
||
the document while a command is running, Zotero's remaining calls for it get an error and the
|
||
new document is left as it is.
|
||
|
||
From a terminal, against a file:
|
||
|
||
```
|
||
wordcraft-cli zotero refresh paper.docx --save paper.docx [--trace]
|
||
```
|
||
|
||
Two engine commands work with Zotero's fields without Zotero running:
|
||
|
||
- `caret.pastCitation` (Zotero › Move Past Citation) moves the caret to just after the citation
|
||
it is in or before. Adjacent citations count as one. If there is none, it moves past the next
|
||
citation.
|
||
- Read Aloud (`review.readAloud`, Review › Speech, Mod+Alt+Space) skips citations and the
|
||
bibliography by default. This covers Zotero, Mendeley, EndNote and Word's own citation
|
||
fields. The player window has previous/next sentence, pause, stop and speed (0.5–3×).
|
||
Its commands are `readAloud.playPause`, `.next`, `.previous`, `.stop`, `.speed {"value"}`,
|
||
`.skipCitations {"value"}` and `.status`. Set `WORDCRAFT_SPEECH=off` to keep it silent.
|
||
|
||
Switching between an in-text style and a note style in Document Preferences moves the citations:
|
||
into new footnotes (or endnotes) at the same place, and back into the text where the note marks
|
||
were; a note that held only the citation is removed.
|
||
|
||
## Word compatibility
|
||
|
||
Citations are stored as Word's Zotero plugin stores them — fields with the code
|
||
`ADDIN ZOTERO_ITEM CSL_CITATION {…}`, the bibliography as `ADDIN ZOTERO_BIBL … CSL_BIBLIOGRAPHY`,
|
||
document preferences in the custom properties `ZOTERO_PREF_1…n` — so one document can be edited
|
||
in Word and WordCraft in turn, with Zotero working in both. (Zotero talks to WordCraft over the
|
||
protocol it uses for LibreOffice and calls the field type "Reference Mark" there; WordCraft keeps
|
||
Word's "Field" in the file.)
|
||
|
||
## Limits
|
||
|
||
- Zotero's "Bookmarks" field type isn't supported; keep the default.
|
||
- Zotero's document transfer (Export/Import Document) isn't needed and isn't supported.
|
||
- The web version can't reach Zotero (browsers can't open the socket).
|
||
|
||
## Who can drive the document
|
||
|
||
Zotero's protocol has no handshake that proves the program on port 23116 is Zotero, and that
|
||
program can read the citations and edit the open document. WordCraft limits who that can be.
|
||
In short: **every system** gets the loopback rule; **only Linux** also checks that the listener
|
||
isn't another user's. On Windows and macOS (and the BSDs) the loopback rule is the only check.
|
||
|
||
- Every system: it only connects to this computer (a loopback address such as `127.0.0.1`);
|
||
any other address is refused before connecting.
|
||
- Linux only: it checks, in the kernel's socket table (`/proc/net/tcp`, `/proc/net/tcp6`), that the
|
||
program listening on the port runs as the same user as WordCraft, before sending anything. If
|
||
another account on a shared machine took the port while Zotero wasn't running, WordCraft
|
||
refuses with an error and the document isn't touched. When the table doesn't show the
|
||
listener (WSL2 mirrored networking with Zotero running on Windows, a local proxy, a sandbox)
|
||
or can't be read, its owner is unknown and only the loopback rule applies, as below.
|
||
- Windows, macOS and the BSDs: **no same-user check.** They have no such table to read
|
||
without OS calls WordCraft doesn't make (it uses no `unsafe` code), so only the loopback rule
|
||
applies there (and on Linux when the listener isn't in the table). Remaining risk: on a
|
||
computer shared with other accounts, a program another user leaves on port 23116 while
|
||
Zotero is closed would be taken for Zotero. An owner check for these systems is tracked in
|
||
#3831. A program running as you is trusted on every system; it could change your documents
|
||
anyway.
|
||
- `wordcraft-cli zotero` prints Zotero's messages (and `--trace` lines) with control
|
||
characters, line breaks and backslashes shown as escapes (`\n`, `\u{1b}`, `\\`), so a peer
|
||
can't forge other output or drive the terminal.
|
||
|
||
## How it works
|
||
|
||
`crates/zotero` implements Zotero's published word-processor wire protocol (port 23116):
|
||
`client` runs a session, `Bridge` answers Zotero's `Document_*` / `Field_*` calls against the
|
||
session. The app (`crates/ui-egui/src/zotero.rs`) runs the socket on a thread and answers on the
|
||
UI thread.
|