revise 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/CHANGELOG.md +962 -0
  2. package/FONT-LICENSE-HAN-EXT-B.txt +91 -0
  3. package/FONT-LICENSE-KATEX.txt +95 -0
  4. package/FONT-LICENSE-LIBERATION.txt +102 -0
  5. package/FONT-LICENSE-NOTO-MULTILINGUAL.txt +93 -0
  6. package/FONT-LICENSE-NOTO-SANS-SC.txt +93 -0
  7. package/FONT-LICENSE-NOTO.txt +94 -0
  8. package/FONT-LICENSE-SOURCE-CODE-PRO.txt +94 -0
  9. package/FONT-LICENSE-SOURCE-SERIF-4.txt +93 -0
  10. package/LICENSE +41 -21
  11. package/README.md +39 -1
  12. package/THIRD-PARTY-NOTICES.md +3376 -0
  13. package/assets/historyMaterializeWorker-CoAX9ZAi.js +3 -0
  14. package/backend.d.ts +133 -0
  15. package/backend.js +1 -0
  16. package/chunks/AgentPageRenderer-C0n4EnuW.js +1 -0
  17. package/chunks/AgentPageRenderer-DURfmiu0.js +1 -0
  18. package/chunks/AttachmentDocumentImporter-DSic_6At.js +1 -0
  19. package/chunks/AttachmentDocumentImporter-dNMtkxrv.js +1 -0
  20. package/chunks/BidiText-B4Hzrjg9.js +1 -0
  21. package/chunks/ColorParserFull-BKH72fK8.js +1 -0
  22. package/chunks/DocumentStylesheet-byN5dtC6.js +1 -0
  23. package/chunks/DocxConverter-B7P52lw7.js +11 -0
  24. package/chunks/DocxConverter-COV6CjUM.js +11 -0
  25. package/chunks/DocxConverter-Cq_zCEJC.js +11 -0
  26. package/chunks/DocxGraft-CJ12C9WP.js +1 -0
  27. package/chunks/DocxGraft-CQpvFcYb.js +1 -0
  28. package/chunks/DocxGraft-DcmFuUkd.js +1 -0
  29. package/chunks/FileImporter-DVnYOJHp.js +1 -0
  30. package/chunks/FileImporter-q9mCch0J.js +1 -0
  31. package/chunks/HorizontalRuleOrnaments-gmUZ3R7Q.js +1 -0
  32. package/chunks/HtmlConverter-JvRlkQM3.js +61 -0
  33. package/chunks/ListNumbering-Qlu6AuRZ.js +1 -0
  34. package/chunks/MarkdownConverter-B-tPY7X3.js +17 -0
  35. package/chunks/MathRenderer-B0Y1h1JU.js +33 -0
  36. package/chunks/OdtConverter-Br81BSoJ.js +1 -0
  37. package/chunks/OdtConverter-CQjh0vlo.js +1 -0
  38. package/chunks/OdtConverter-DYHnR4E8.js +1 -0
  39. package/chunks/PdfConverter-D26rXumc.js +21 -0
  40. package/chunks/PdfConverter-DGZpUSVf.js +21 -0
  41. package/chunks/PdfConverter-DZzVP0-B.js +21 -0
  42. package/chunks/PdfImportService-CBD8TL1k.js +2 -0
  43. package/chunks/PdfImportService-D6uUKGMf.js +2 -0
  44. package/chunks/RtfConverter-BQGge3K-.js +14 -0
  45. package/chunks/RtfConverter-CMfZ4olw.js +14 -0
  46. package/chunks/RtfConverter-oIwzoqCD.js +14 -0
  47. package/chunks/TableBorders-BLkZYt1k.js +1 -0
  48. package/chunks/TableGrid-DVWaRZv0.js +1 -0
  49. package/chunks/TextFileDecoder--rsVs3NR.js +2 -0
  50. package/chunks/TxtConverter-C1lp6dBS.js +11 -0
  51. package/chunks/__vite-browser-external-l0sNRNKZ.js +0 -0
  52. package/chunks/_commonjsHelpers-DaMA6jEr.js +1 -0
  53. package/chunks/_revise-sdk-lazy-harfbuzz-CDWdjF9f.js +1 -0
  54. package/chunks/_revise-sdk-lazy-harfbuzz-X8gnYTZL.js +1 -0
  55. package/chunks/ar-kgSWdrXF.js +8 -0
  56. package/chunks/backend-Cq-khfdG.js +1 -0
  57. package/chunks/base64-CfDUyGi8.js +36 -0
  58. package/chunks/browser-module-6b2Fq-5C.js +3 -0
  59. package/chunks/browser-module-CFmqfGkE.js +3 -0
  60. package/chunks/browser-module-CkO57IPL.js +3 -0
  61. package/chunks/bundle.min-DRpfgV69.js +8 -0
  62. package/chunks/capture-DU3MC7tb.js +1 -0
  63. package/chunks/carrier-WgcRSu7a.js +1 -0
  64. package/chunks/de-C2QTHrqo.js +8 -0
  65. package/chunks/es-BKboUn4q.js +8 -0
  66. package/chunks/footnoteFlatten-CW-DUcgK.js +1 -0
  67. package/chunks/graftExport-CVg7PO2A.js +2 -0
  68. package/chunks/html2canvas.esm-CntiHiYW.js +5 -0
  69. package/chunks/index-BWdRWxoH.js +24 -0
  70. package/chunks/index-CLw_BlSL.js +353 -0
  71. package/chunks/index-F-kHIwWT.js +353 -0
  72. package/chunks/index.es-CI0QPo8w.js +5 -0
  73. package/chunks/index.es-DOqegDGr.js +5 -0
  74. package/chunks/index.es-tXDO0RMv.js +5 -0
  75. package/chunks/jspdf.es.min-CzYti8jo.js +77 -0
  76. package/chunks/jspdf.es.min-DU74zN8b.js +77 -0
  77. package/chunks/jspdf.es.min-ejWOGhkJ.js +77 -0
  78. package/chunks/jszip.min-CPW0h1Kx.js +2 -0
  79. package/chunks/katex-DWj8TvwO.js +261 -0
  80. package/chunks/pdf-BLWDCiFF.js +12 -0
  81. package/chunks/persistInlineDocumentImages-DQj2iaqg.js +1 -0
  82. package/chunks/pseudoLocale-CdBtPHRi.js +1 -0
  83. package/chunks/pseudoLocale-DEVWLkGC.js +1 -0
  84. package/chunks/purify.es-BwLardii.js +2 -0
  85. package/chunks/serverDocumentSession-DZrYbdpk.js +42 -0
  86. package/chunks/tree-sitter-D6zWWUMP.js +4 -0
  87. package/chunks/wasmInline.generated-CBYFkdSM.js +1 -0
  88. package/chunks/web-tree-sitter-BXGZGnNj.js +1 -0
  89. package/full.js +1 -0
  90. package/index.d.ts +929 -0
  91. package/index.js +1 -0
  92. package/package.json +93 -26
  93. package/root.d.ts +5 -0
  94. package/root.js +2 -0
  95. package/serverToolContract.d.ts +373 -0
  96. package/serverToolInputs.generated.d.ts +229 -0
  97. package/style.css +1 -0
  98. package/.npmignore +0 -4
  99. package/.travis.yml +0 -16
  100. package/revise.js +0 -16
  101. package/t/cover +0 -18
  102. package/t/revise/comparator.t.js +0 -31
  103. package/t/revise/extractor.t.js +0 -29
  104. package/t/test +0 -20
package/CHANGELOG.md ADDED
@@ -0,0 +1,962 @@
1
+ # Changelog
2
+
3
+ ## 2.0.0
4
+
5
+ The SDK is now public: `npm i revise`. No account, token, or contact
6
+ with us is needed to install it. 2.0.0 also ships everything from the
7
+ 2.0.0-alpha releases below.
8
+
9
+ ### Changed
10
+
11
+ - **BREAKING: the package is now `revise`.** The private `@reviseio/sdk`
12
+ package is retired. Update the dependency and imports:
13
+ `@reviseio/sdk` → `revise/editor`, `@reviseio/sdk/full` →
14
+ `revise/editor/full`, `@reviseio/sdk/backend` → `revise/server`, and
15
+ `@reviseio/sdk/style.css` → `revise/style.css`. Remove the `@reviseio`
16
+ scope and token lines from `.npmrc`.
17
+ - **New license: free for evaluation, personal projects, and education.**
18
+ Production use by businesses, nonprofits, and government requires a paid
19
+ license. See `LICENSE` and [developer.revise.io](https://developer.revise.io/editor-sdk/license).
20
+ The previous 60-day evaluation terms no longer apply.
21
+ - **The editor fills its container at any size.** The 640×560px minimum is
22
+ gone, so the editor fits phone-width columns and short panels without
23
+ overflowing them. A container with no height gets a 560px fallback and a
24
+ one-time console warning instead of a collapsed editor.
25
+ - **Hosted agent defaults to production.** Without `agent.baseUrl`, the
26
+ delegated Revise agent now targets `https://agent.revise.io` instead of a
27
+ development address.
28
+
29
+ ### Added
30
+
31
+ - **A 4.5 MB package, with assets loaded on demand.** PDF export fonts were
32
+ inlined as base64 and made up three quarters of the package; they, the math
33
+ fonts and stylesheet, the pdf.js worker, and Tree-sitter grammars now load
34
+ from `https://revise.io` when first needed. **`setAssetBaseUrl(url)`**
35
+ points the SDK at a self-hosted mirror.
36
+ - **`import ReviseEditor from "revise/editor"`.** The editor entry now has a
37
+ default export. The named `ReviseEditor` export still works.
38
+ - **`revise` root entry** with `REVISE_SDK_VERSION`, `REVISE_SDK_BUILD`, and
39
+ the shared types, and no runtime weight.
40
+ - **`THIRD-PARTY-NOTICES.md`** lists every bundled open-source package with
41
+ its license.
42
+ - **Anonymous usage ping, and the `telemetry` prop to turn it off.** Once
43
+ per page load, the editor sends Revise its version; the browser adds the
44
+ site's origin. Development hosts are counted per day and version without
45
+ their origin. No cookies, user data, or document content.
46
+ `telemetry={false}` disables it.
47
+
48
+ ### Fixed
49
+
50
+ - **Math renders with its real fonts in host apps.** Equations looked for
51
+ their fonts and stylesheet at the host's own `/fonts` and `/katex.min.css`
52
+ and fell back to system fonts; the help link in the editor menu also
53
+ pointed at the host's `/help`. All now resolve to Revise's assets.
54
+ - **The SDK no longer reaches for development servers.** Revise application
55
+ endpoints (document history, preferences, uploads, failure reports) and the
56
+ sync-server addresses no longer resolve to `localhost` in an embedding
57
+ host. Document history in particular fetched from `localhost:3001` in
58
+ browsers without a `process` global.
59
+ - **No debug globals on the host's `window`.** `__getEditor`,
60
+ `__getDocLayout`, and `__aiLogs` are no longer installed.
61
+ - **DOCX math export uses Revise's own MathML → OMML converter.** Equations
62
+ export to native Word math (fractions, radicals, scripts, sums and
63
+ integrals with limits, delimiters, matrices, accents, bars, braces,
64
+ functions, boxed and text runs) with no third-party copyleft code in the
65
+ package. Re-importing them is more faithful: `\left\{ … \right.`,
66
+ `\underline`, `\overbrace`, `\boxed`, `\text{…}`, `\mathbb`, binomials,
67
+ and named functions (`\sin`, `\log`, `\lim_{…}`) now come back as the
68
+ same LaTeX instead of approximations, and symbols no longer run into the
69
+ following letter (`\alpha x`, not `\alphax`).
70
+
71
+ ## 2.0.0-alpha.7
72
+
73
+ ### Fixed
74
+
75
+ - **DOCX round trips keep every modeled mark and block.** A new
76
+ export → import matrix (every formatting mark in every text context,
77
+ every paragraph, list, table, cell, image, code, math, note, header,
78
+ footer, and page-layout attribute, plus a second-pass fixed-point
79
+ check) found and pinned a set of losses: lists inside table cells
80
+ were dropped on export; hanging indents exported as zero and
81
+ `w:hanging` was ignored on import; headings came back as Word's blue
82
+ 16pt built-ins (export now writes the editor's heading sizes with
83
+ inherited color); unscoped header/footer blocks were not exported;
84
+ hyperlinks discarded an explicit text color; links inside footnotes
85
+ were lost on import; header and footer runs used a reduced codec in
86
+ both directions and now share the body run codec, links and inline
87
+ code included; inline code and code blocks flattened to Courier text
88
+ and now travel as `CodeInline` / `CodeBlock_<language>` styles and
89
+ return as the original nodes; todo items exported as literal
90
+ `[x]` text and now use checkbox glyphs that re-import as todo lists
91
+ with their checked state; code-block line breaks doubled on
92
+ re-import; and a single run in another font restamped the whole
93
+ document (the inferred document font is now the character-weighted
94
+ majority).
95
+ - **Table borders export and re-import faithfully.** Export no longer
96
+ throws on non-hex colors such as `TRANSPARENT`, `rgba()`, or CSS
97
+ names — unresolvable values are omitted or written as `auto`. The
98
+ uniform `borderWidth`/`borderColor` pair is honored (width 0 means
99
+ no borders), width-0 spec edges export as `none` instead of a
100
+ hairline, and an explicit `w:sz="0"` imports as hidden rather than a
101
+ 1px line. Table Settings border changes now rewrite the structured
102
+ table spec and clear per-cell overrides, so hiding borders on an
103
+ imported table takes effect.
104
+ - **Byte-preserving DOCX export degrades instead of failing.** A carrier
105
+ that fails to load falls back to the regenerated package like every
106
+ other graft failure; the graft option reports its outcome (exact,
107
+ grafted, regenerated, and the fallback code) through an isolated
108
+ callback that can never break an export. Untouched imports of rich
109
+ documents now export byte-identical: note-body font inheritance,
110
+ header/footer zone ids, and legacy chrome no longer drift the
111
+ fidelity signatures; watermark and settings edits graft instead of
112
+ restoring carrier values; body grafting is invalidated when wrapper
113
+ or style sidecars change; single-quoted and non-numeric relationship
114
+ ids parse; and a changed header image is replaced even when its
115
+ media filename collides.
116
+ - **Formatting suggestions preserve footnotes.** Accepting a
117
+ `style_blocks` suggestion keeps footnote references and bodies.
118
+ - **Large documents no longer stall on batch edits.** Styling 205 blocks
119
+ in a 10,000-block document, applying 100 replacements, and large
120
+ multi-block insertions run without re-decoding the document per
121
+ action; suggestion projection latency is bounded; batch paragraph
122
+ formatting suggestions behave identically through preview,
123
+ acceptance, and rejection.
124
+ - **Semantic tool errors and inputs.** Errors distinguish Markdown find
125
+ syntax from stored plain text; metric CSS paragraph indentation
126
+ (`cm`, `mm`) is accepted; number-dot prose can be parsed as inline
127
+ text instead of a list when requested.
128
+ - **Comments render AI citations.** Structured citations persist on
129
+ replies and render in the panel; unsupported provider citation
130
+ markers are hidden, including on legacy comments.
131
+ - **Agent image rehosting.** Wikimedia thumbnail URLs are recovered by
132
+ rehosting the original image, and rate-limited rehosts surface the
133
+ backend reason and status.
134
+ - **Revision timeline never collapses to zero.** A stale or missing
135
+ server update counter no longer disables history or pins every frame
136
+ to the first update; loaded frames are authoritative.
137
+ - **Pasted images write once.** A pasted image no longer inserts a
138
+ temporary base64 placeholder that is replaced later; the final hosted
139
+ URL is written at the captured paste position when the upload
140
+ completes.
141
+
142
+ ### Changed
143
+
144
+ - **Comment margin geometry is direction-aware.** Chip, floating-stack,
145
+ and insert-chip positions are computed along an outward axis with a
146
+ single conversion to physical coordinates. The embedded document
147
+ surface itself is still laid out left-to-right: the margin chrome
148
+ stays on the page's right regardless of the host page's direction.
149
+ Mirroring the embed for right-to-left hosts is not part of this
150
+ release.
151
+
152
+ ## 2.0.0-alpha.6
153
+
154
+ ### Fixed
155
+
156
+ - **A healed seed race now recovers full fidelity — and never loses a
157
+ comment.** Three repair refinements: the winner is the seed whose
158
+ metadata survived the merge (each seed stamps a ballot in the same
159
+ transaction), so the kept content matches the surviving import
160
+ capture; a shared deterministic id keeps the WINNER's element, not an
161
+ arbitrary one; and map records under a shared key (deterministic
162
+ comment ids) are never deleted — the merge already deduplicated them,
163
+ and alpha.5's repair removed the only surviving record. A raced,
164
+ repaired room now reports "exact" and exports byte-identically.
165
+
166
+ ## 2.0.0-alpha.5
167
+
168
+ ### Fixed
169
+
170
+ - **Seed-race repair kept a duplicate footnote.** Deterministic ids that
171
+ every seed generates identically (docx footnotes) were protected from
172
+ repair as a collision safeguard, leaving one copy per seed. Repair now
173
+ keeps exactly one occurrence of a shared id. Supersedes 2.0.0-alpha.4,
174
+ which was deprecated minutes after publish.
175
+
176
+ ## 2.0.0-alpha.4
177
+
178
+ ### Fixed
179
+
180
+ - **Double-seed connect race no longer duplicates the document.** Two
181
+ peers that each found an empty room and seeded the same file before
182
+ syncing used to merge into a perfectly-synced, perfectly-duplicated
183
+ document. Every seed now records a claim in the same transaction as
184
+ its content, and any peer that sees two claims deterministically
185
+ removes the losing seed's content — idempotent, convergent, and
186
+ content added after a seed is never touched. `seedYDocFromFile` is
187
+ now genuinely safe to call on every connection: a later call also
188
+ heals an already-raced room, and every live editor session repairs
189
+ one the moment the second claim syncs in.
190
+ - **Editing no longer rewrites document properties.** A structural edit
191
+ (or a rejected tracked change) permanently dropped the imported core
192
+ properties from the live model, so every later export regenerated
193
+ `docProps/core.xml` with an "Un-named" creator, the title removed,
194
+ and the creation date reset to export time. Core properties now
195
+ survive every model rebuild, and when core.xml IS legitimately
196
+ regenerated it is a faithful merge: `cp:revision` round-trips and
197
+ fields the original never had are not invented.
198
+ - **`docProps/app.xml` passes through untouched.** It is never
199
+ regenerated (preserving Application/Company/TotalTime) and never
200
+ added to a package that did not have one.
201
+
202
+ ### Added
203
+
204
+ - **`repairSeedRace(ydoc)`** on the backend entry (with
205
+ `SeedRaceRepairResult`): detect and repair a double-seed race on
206
+ demand. Editor sessions and `seedYDocFromFile` run it for you.
207
+
208
+ ### Changed
209
+
210
+ - **New reserved top-level key in shared documents: `"seed-claims"`**
211
+ (see `RESERVED_DOCUMENT_KEYS`) — where seed claims live.
212
+
213
+ ## 2.0.0-alpha.3
214
+
215
+ ### Fixed
216
+
217
+ - **Backspace before a chip deleted the chip.** A preserved-object chip
218
+ has two caret stops — before and after — and a delete now respects
219
+ which side the caret is on, like a caret between two characters:
220
+ backspace at the before-stop targets the block BEFORE the chip (an
221
+ atomic neighbor is deleted whole, a text neighbor loses its last
222
+ character), and forward delete at the after-stop targets the block
223
+ after. Deletes pointing AT the chip still remove it.
224
+ - **Up/down arrows at a chip slid the caret to the chip's other side**
225
+ instead of changing lines. Vertical movement now leaves the chip's
226
+ line and lands on the neighboring block's stop nearest the caret's
227
+ column — arrowing through a stack of chips keeps the caret on the
228
+ same side all the way down.
229
+
230
+ ## 2.0.0-alpha.2
231
+
232
+ ### Fixed
233
+
234
+ - **Exporting .docx could crash in production builds of the host app**
235
+ ("Cannot destructure property 'default' … as it is undefined" from
236
+ the converter's zip loader). The SDK's build emitted duplicate
237
+ interop chunks for its zip dependency behind dynamic imports, and
238
+ some consumer bundlers resolved one family to `undefined` when
239
+ producing production builds — development builds were unaffected,
240
+ which is why the crash only appeared after deployment. The dependency
241
+ is now a static import inside the (still lazily loaded) converter
242
+ modules: the load profile is unchanged and the chunk graph no longer
243
+ depends on the host bundler's interop handling.
244
+ - **Backspace in an empty paragraph directly after a chip deleted the
245
+ chip** instead of the paragraph. Preserved payloads are content the
246
+ source file owns, not editor furniture: the empty paragraph dies, the
247
+ chip survives. (Page and section breaks keep their old
248
+ consume-on-backspace behavior.)
249
+ - **Chips gained real before/after caret stops.** The caret can now be
250
+ placed on either side of a chip — arrow keys walk across it, and
251
+ clicking the left or right half of the chip places the caret on the
252
+ matching side.
253
+
254
+ ## 2.0.0-alpha.1
255
+
256
+ Prerelease for evaluation. The 2.0 line's headline is DOCX source
257
+ fidelity: a document imported from .docx can now leave the editor as the
258
+ file it came from, not a reconstruction of it.
259
+
260
+ ### Added
261
+
262
+ - **DOCX source-fidelity mode (default on).** Importing a .docx keeps the
263
+ original package inside the document (the "carrier", shared documents
264
+ included, capped at 25MB). On export, content you did not touch is
265
+ emitted as the exact bytes that arrived — byte-for-byte, unannotated —
266
+ and only changed content is regenerated. A verification stage inspects
267
+ every composed package and falls back to full regeneration rather than
268
+ ship anything it cannot verify.
269
+ - **`handle.getSourceFidelity()`** (and `ydocSourceFidelity(ydoc)` /
270
+ `documentToDocx(doc, { originalDocx })` on the backend entry) reports
271
+ the honest relationship of the next export to the original file:
272
+ `"exact"` (byte-identical), `"grafted"` (original bytes plus your
273
+ edits), or `"converted"` (no usable original; the report says why).
274
+ - **Unmodeled Word formatting survives editing.** Run, paragraph, table,
275
+ row, cell, and section properties the editor does not model (vendor
276
+ effects such as `w14:glow`, revision-save ids, row heights, table
277
+ look flags, page borders, note-numbering properties…) are carried
278
+ through the model and re-emitted — so an EDITED paragraph keeps them
279
+ too, with or without the carrier.
280
+ - **Preserved objects render as labeled chips.** OLE embeds (Excel,
281
+ Visio), SmartArt without a raster fallback, and unknown OOXML
282
+ constructs import as atomic blocks labeled with their source tag
283
+ (e.g. "w:object · Excel.Sheet.12"), render as chips on canvas and in
284
+ PDF export, and re-export verbatim. In agent HTML they appear as
285
+ `<docx-raw id tag/>`: an agent can keep, move, or omit one
286
+ (omission deletes), but can never inject raw OOXML of its own.
287
+ - **Editable-region permissions preserved.** `w:permStart`/`w:permEnd`
288
+ pairs (and future paired ranges) survive import, editing, and export
289
+ with balance guaranteed by construction: typing inside extends the
290
+ region, deleting its text retires it, and unbalanced pairs in source
291
+ files are repaired at import.
292
+
293
+ ### Changed
294
+
295
+ - **BREAKING: two new reserved top-level keys in shared documents** —
296
+ `"docx-carrier"` and `"oxml-ranges"` (see
297
+ `RESERVED_DOCUMENT_KEYS`). A host-built Y.Doc already using these
298
+ names is rejected by `assertUsableSharedDocument`.
299
+ - **BREAKING: docx-sourced exports are byte-preserving by default.**
300
+ 1.x regenerated every export from the model; 2.0 reproduces original
301
+ bytes for untouched content. Hosts that depended on exports being
302
+ normalized into the generated dialect should convert explicitly.
303
+ - `ReviseDocument` block children may now include the `"docx-raw"`
304
+ node type (opaque; convert rather than inspect, as ever).
305
+ - Shared documents built from a .docx are larger by roughly the size of
306
+ the source file (the carrier). It is stored once, chunked, and synced
307
+ like any other document state.
308
+
309
+ ## 1.3.1
310
+
311
+ ### Fixed
312
+
313
+ - **Delegated page inspection now reaches the embedded editor canvas.** The
314
+ SDK connects the delegated agent's `render_document_pages` tool to the
315
+ mounted document renderer, so appearance and layout requests return the
316
+ actual pages instead of reporting that canvas inspection is unavailable.
317
+ - **Agent-tool documentation now matches the generated SDK catalog.** The
318
+ public docs use the canonical `remove_blocks` name, distinguish the
319
+ deterministic document-local tool subset from delegated-agent-only tools,
320
+ and explain where visual page inspection is available.
321
+
322
+ ## 1.3.0
323
+
324
+ ### Added
325
+
326
+ - **The built-in editor UI now localizes itself in English, Spanish, and
327
+ German.** Ribbon controls, menus, dialogs, comments, Review mode, and agent
328
+ chrome follow the browser language or the persisted Revise UI-language
329
+ preference, while English remains the fallback if a locale chunk cannot be
330
+ loaded.
331
+ - **The delegated browser agent can inspect the document's rendered pages.**
332
+ It can request bounded appearance contact sheets or layout diagnostics from
333
+ the real canvas renderer, including page geometry, tables, images, math,
334
+ headers, footers, and safe placeholders for unavailable visual assets.
335
+
336
+ ### Changed
337
+
338
+ - **Tab editing and layout now follow Word-style paragraph behavior.** Tab and
339
+ Shift+Tab at the start of a block keep indenting or outdenting, while either
340
+ key inside paragraph text inserts a tab. Long tabbed lines wrap at word
341
+ boundaries, restart their ruler on each visual line, and preserve custom,
342
+ aligned, leader, and right-to-left tab stops.
343
+
344
+ ### Fixed
345
+
346
+ - **DOCX named styles remain stable through editing and repeated round trips.**
347
+ Imported paragraph styles and document defaults now drive newly created
348
+ headings and agent-created styled blocks, survive Yjs persistence, suppress
349
+ redundant direct formatting on export, and converge without accumulating
350
+ unused generated Word styles. Explicit formatting resets, borders, spacing,
351
+ fonts, and styles inside table cells remain intact.
352
+ - **Agent document measurements reconcile pending Review changes.** Primary
353
+ totals consistently measure the final, as-if-accepted document and include
354
+ the original review projection when pending suggestions make the visible
355
+ word or character count differ.
356
+
357
+ ## 1.2.0
358
+
359
+ ### Added
360
+
361
+ - **International text support now extends across the editing and conversion
362
+ pipeline.** Unicode-aware line breaking, search, list numbering, font
363
+ fallback, and IME composition preserve multilingual text more reliably, and
364
+ text import now detects UTF-8 and UTF-16 files. HTML, DOCX, RTF, ODT, and
365
+ plain-text conversions keep the expanded script coverage intact.
366
+ - **Orange and purple join the SDK highlight palette.** The editor UI,
367
+ `find_highlights`, `style_blocks`, agent HTML, and DOCX round trips now
368
+ share the same seven canonical highlight colors.
369
+ - **Agent styling covers richer document structures.** `style_blocks` adds
370
+ span, descendant-wildcard, first-row, and named-paragraph-style selectors,
371
+ with durable mappings for image sizing and alignment, paragraph borders,
372
+ nested tables and lists, per-edge cell borders, cell fills, padding, and
373
+ table-cell text styles.
374
+
375
+ ### Fixed
376
+
377
+ - **DOCX import follows Word's effective paragraph and table styling.**
378
+ Unstyled paragraphs inherit the document's default style; exact and
379
+ at-least line rules use the resolved font size; paragraph before/after and
380
+ contextual spacing replace the editor's fallback gap; missing table borders
381
+ remain borderless; and non-uniform cell margins survive import. The imported
382
+ spacing persists through Yjs, paragraph splits and merges, HTML, DOCX, and
383
+ PDF output, keeping compact Word layouts from growing onto extra pages.
384
+ - **Unavailable Word fonts use the document's own substitution hints.** DOCX
385
+ import reads `fontTable.xml` alternate names and PANOSE/family/pitch
386
+ metadata, persists them with the document, and chooses metric-compatible
387
+ fallbacks before resorting to a generic family.
388
+ - **Multilingual PDF export embeds and shapes the scripts it needs.** Chinese,
389
+ Japanese, Korean, Indic, Southeast Asian, Tibetan, Ethiopic, Armenian,
390
+ Georgian, Syriac, Thaana, symbols, emoji, and rare Han use bundled lazy
391
+ fallback faces, while a hidden logical-text layer preserves search and text
392
+ extraction.
393
+ - **Agent edits preserve complex formatting and pending review state.** Styled
394
+ tables, nested content, list-item formatting, explicit text overrides,
395
+ comments, and edits layered over pending insertions now survive preview,
396
+ acceptance, and rejection without duplicating or flattening structure.
397
+ - **Borderless layout tables stay visually borderless while editing.** The
398
+ canvas now reveals only the specific invisible vertical edge under a resize
399
+ pointer instead of ghosting the table's entire grid on hover or focus.
400
+ - **Imported pale-yellow highlights remain highlights.** HTML clipboard import
401
+ no longer remaps Word's pale yellow to the editor's green palette entry.
402
+
403
+ ## 1.1.0
404
+
405
+ ### Added
406
+
407
+ - **First-class right-to-left editing.** The built-in toolbar can set paragraph
408
+ and list direction to automatic, LTR, or RTL. Mixed Hebrew, Arabic, and
409
+ left-to-right text now uses bidi-aware line layout, visual arrow-key
410
+ movement, stable caret and selection geometry, direction-aware alignment and
411
+ indents, mirrored list markers, and RTL tab stops. Direction survives Yjs,
412
+ clipboard and agent edits, HTML, and DOCX round trips; PDF export preserves
413
+ mixed-direction reading order and positioning.
414
+ - **Multi-column sections.** Page layout now supports one, two, or three
415
+ newspaper-style columns with a configurable gap. Continuous section breaks
416
+ balance their final columns, while page and next-page sections keep ordinary
417
+ pagination. The canvas editor and PDF export share the flow rules, DOCX and
418
+ HTML import/export preserve the settings, and `set_page_layout` exposes
419
+ `columnCount`, `columnGap`, and section-scoped updates to browser and
420
+ server agent sessions.
421
+ - **Native document-structure tools.** `insert_block` can create a live table
422
+ of contents with `<toc levels="3"></toc>`. The canonical
423
+ `remove_blocks` tool can delete a counted range, exact IDs, a saved search
424
+ result, or an explicitly authorized document tail with `through_end`.
425
+
426
+ ### Changed
427
+
428
+ - **Agent tool sessions avoid unproductive read cycles.** Sequential reads now
429
+ reject windows containing only blocks already returned in the same request
430
+ with `no_new_read_context`; `read_specific_blocks` remains available for
431
+ intentional revisits. `remove_blocks` is now the model-facing name, while
432
+ the previous `remove_block` name remains an executable compatibility alias.
433
+
434
+ ### Fixed
435
+
436
+ - **Strict-provider nulls behave like omitted optional tool fields.** Browser
437
+ and server tool execution normalize provider-materialized `null` values
438
+ from the generated schema before dispatch, without stripping required or
439
+ deliberately nullable values. Optional layout and mutation inputs therefore
440
+ no longer take invalid branches merely because a provider filled them in.
441
+ - **Agent-generated Unicode escapes become the intended text.** Literal
442
+ `\uXXXX` sequences in agent HTML and replacement paths are decoded without
443
+ disturbing escaped backslashes or code spans, preventing visible escape text
444
+ in edited documents.
445
+ - **Review decisions preserve the reader's place.** Accepting or rejecting a
446
+ tracked change no longer forces the embedded editor to scroll back to the
447
+ active suggestion.
448
+ - **SDK PDF export keeps Hebrew and Arabic text self-contained.** The package
449
+ now bundles the Noto fallback faces used by RTL export, so embedding hosts do
450
+ not need to mirror Revise's public font directory to avoid dropped glyphs.
451
+
452
+ ## 1.0.1
453
+
454
+ ### Fixed
455
+
456
+ - **Malformed model input can no longer crash a host's agent loop.** A bare
457
+ string where `search_document` expects a `queries` array — the most
458
+ common model slip — threw a raw `TypeError` out of `execute()` /
459
+ `executeDynamic()` instead of returning a structured failure. Bare
460
+ strings are now coerced to one-element arrays (also for
461
+ `read_specific_blocks`' `block_ids`), anything uncoercible fails
462
+ structurally, and both surfaces gained a safety net that converts an
463
+ unexpected handler throw into an `internal_error` result. The documented
464
+ contract — expected failures as results, only environment errors reject —
465
+ now holds for arbitrary input.
466
+ - **Invalid enum values no longer mutate the wrong target silently.** An
467
+ insert tool called with `position: "above"` placed content _after_ the
468
+ reference block while reporting success, and `set_header_footer` with a
469
+ misspelled or missing `side` edited the header. Both now return a
470
+ structured failure naming the valid values.
471
+
472
+ ## 1.0.0
473
+
474
+ One package, one tool contract. The browser and server surfaces now speak
475
+ the same canonical envelope, so host result-handling code is shared verbatim
476
+ between web and Node. That convergence is breaking on the browser side —
477
+ every change is listed below.
478
+
479
+ ### Breaking
480
+
481
+ - **`tools.execute()` returns the canonical discriminated envelope.** The
482
+ flat `{ toolCallId, name, success, error?, agentFeedback?, output?,
483
+ documentContent? }` result is gone. Both surfaces now return
484
+ `{ ok: true, value: { callId, tool, message, data, context, suggestionIds } }`
485
+ or `{ ok: false, error: { callId, tool, code, message } }`
486
+ (`ReviseToolResult`). Field mapping: `toolCallId → value.callId`,
487
+ `name → value.tool`, `agentFeedback → value.message`,
488
+ `output → value.data`, `documentContent → value.context.html`;
489
+ `view_image`'s attachment lives on `value.image`.
490
+ `ReviseEditorToolExecutionResult` no longer exists.
491
+ - **`tools.execute()` is typed and no longer routes `document_id`.**
492
+ `execute()`/`call()` take the generated per-tool input types and
493
+ cover the shared 24-tool contract; untrusted model calls — including the
494
+ browser-only `get_selection`, `view_image`, and
495
+ `revise_run_agent`, and model-facing `document_id` routing — go
496
+ through the new `executeDynamic()`, exactly as on the server.
497
+ - **Unknown tools and role denials are results, not throws.** `execute()`
498
+ returns `{ ok: false }` with `code: "unknown_tool"` or
499
+ `"role_not_permitted"` instead of throwing; the new `tools.call()`
500
+ throws a typed `ReviseToolError` for hosts that prefer exceptions.
501
+ `ReviseRoleError` is still thrown by `agent.run()` and UI
502
+ controllers.
503
+ - **ID-keyed suggestion decisions return per-ID outcomes.**
504
+ `review.acceptSuggestions`/`rejectSuggestions`,
505
+ `review.acceptCommentSuggestions`/`rejectCommentSuggestions`, and
506
+ `tools.acceptAllSuggestions`/`rejectAllSuggestions`, and the server
507
+ session's `acceptSuggestions`/`rejectSuggestions` return
508
+ `{ resolved, missing, unresolved }` (`ReviseSuggestionDecision`)
509
+ instead of a bare count. Stale IDs land in `missing`; a role that may
510
+ not resolve reports everything `unresolved`. `review.acceptAll()` /
511
+ `rejectAll()` keep their boolean UI-gesture contract.
512
+ - **Server sessions default to suggesting mode.** `createServerDocumentSession`
513
+ without `mode` now proposes tracked changes instead of applying edits
514
+ directly — the same default posture as the browser surface, and the safe
515
+ one. Pass `mode: "editing"` (or per-call `directMode: true`) for
516
+ direct application.
517
+
518
+ ### Added
519
+
520
+ - **Browser mutation results report created suggestion IDs.** Successful
521
+ mutations carry `suggestionIds` — the tracked records that call created
522
+ (empty for direct edits, `null` for read/search/measure tools) — with a
523
+ concurrent human suggestion never attributed to the tool call. Feed them
524
+ straight to `review.acceptSuggestions()`.
525
+ - **The tool contract types ship from both entries.** `ReviseToolResult`,
526
+ `ReviseToolResponse`, `ReviseToolFailure`, `ReviseToolError`,
527
+ `ReviseSuggestionDecision`, the generated `ReviseToolInputMap`, and
528
+ friends are exported by `@reviseio/sdk` and `@reviseio/sdk/backend`
529
+ alike.
530
+
531
+ - **Server mutation results report the tracked records they created.**
532
+ Successful mutation calls from `createServerDocumentSession` now carry
533
+ `suggestionIds` — the tracked suggestion records that call created (empty
534
+ for direct edits, `null` for read/search/measure tools) — so a host can
535
+ persist per-edit IDs with its review workflow instead of diffing the
536
+ document-global pending set.
537
+ - **`listSuggestions()`** returns every pending suggestion as a reviewable
538
+ record with authorship metadata (`authorType`, `agentName`,
539
+ `agentModel`, `source`, `label`, `createdAt`), so hosts can decide on
540
+ their own agent's suggestions and leave collaborators' pending work alone.
541
+ - **`acceptAllSuggestions()` / `rejectAllSuggestions()`** make the
542
+ whole-document decision an explicit, greppable call instead of the
543
+ `acceptSuggestions(getPendingSuggestionIds())` idiom.
544
+
545
+ ### Fixed
546
+
547
+ - **Server tool types now resolve for `moduleResolution: "NodeNext"`
548
+ consumers.** The packaged declarations re-exported the server tool contract
549
+ through extensionless relative specifiers, which NodeNext cannot resolve —
550
+ every tool input/output type silently degraded to `any`, and importing a
551
+ contract type by name (e.g. `ServerDocumentSession`) failed to compile.
552
+ The declarations now use explicit `.js` specifiers, which every supported
553
+ resolution mode maps to the sibling `.d.ts` files.
554
+ - **Importing a document with code blocks no longer risks crashing a Node
555
+ host.** The canvas syntax highlighter tried to fetch its tree-sitter wasm
556
+ under Node (the server DOM shims install a jsdom `window`, defeating its
557
+ browser check), failing as an unhandled promise rejection. Highlighting now
558
+ recognizes the server runtime explicitly and stays off, and a failed
559
+ highlighter init in the browser no longer poisons later attempts.
560
+ - **Table and list mutations no longer spam `Invalid access` warnings.**
561
+ Building table rows, cells, and list items called Yjs `push()` on
562
+ elements not yet integrated into a document, which logs a warning per
563
+ child. Construction now inserts children at explicit indices — dozens of
564
+ stderr lines per table insert in server logs, gone.
565
+ - **Editing mode applies server edits directly again.** A server session in
566
+ `"editing"` mode quietly recorded every mutation as a
567
+ pending tracked suggestion instead of applying it. Editing-mode calls now
568
+ run in the runtime's direct mode and settle within the call, matching the
569
+ documented behavior; an explicit per-call `directMode` still overrides in
570
+ either direction.
571
+
572
+ ## 0.9.0
573
+
574
+ ### Added
575
+
576
+ - **`review.listChanges()` now reports linked moves as moves.** A move pair
577
+ surfaces as ONE `ReviseTrackedChange` with `kind: "move"`,
578
+ `moveSourceBlockIds`/`moveDestinationBlockIds` locating each half, and
579
+ `deletedText`/`insertedText` carrying the text as it left and as it
580
+ arrived. Previously both halves were folded into a single change labeled
581
+ `"delete"`, leaving a host review panel no way to distinguish a move from
582
+ a replacement. Accept/reject semantics are unchanged: resolving the change
583
+ settles both locations atomically.
584
+
585
+ ## 0.8.0
586
+
587
+ ### Added
588
+
589
+ - **Cut and paste now creates native linked moves in Suggesting mode.** Cutting
590
+ text from supported paragraphs and pasting that same internal clipboard
591
+ payload elsewhere in the document produces one atomic “Moved from”/“Moved
592
+ here” pair. Accepting or rejecting either half resolves both locations, undo
593
+ cannot strand an orphaned half, and DOCX export/reimport preserves native
594
+ linked move markup. Copy/paste, editing mode, reused or mismatched clipboard
595
+ payloads, and unsupported structural selections continue to use ordinary
596
+ insertion/deletion behavior.
597
+
598
+ ## 0.7.0
599
+
600
+ ### Added
601
+
602
+ - **Server-side semantic tools.** `await createServerDocumentSession(ydoc,
603
+ { documentId, mode })` in `@reviseio/sdk/backend` binds the canonical
604
+ document-local agent tools — read, search, measure, mutate, layout,
605
+ footnotes, tables, comments — to a host-owned Y.Doc under plain Node.
606
+ `mode: "suggesting"` produces Word-compatible tracked changes with
607
+ accept/reject; concurrent calls are serialized; literal tool calls infer
608
+ their schema inputs and structured outputs. See the README's "Server semantic
609
+ tools" section.
610
+ - **Linked Word moves now round-trip as atomic move suggestions.** DOCX import
611
+ pairs native `w:moveFrom` and `w:moveTo` ranges across runs, paragraphs,
612
+ and table cells. Accepting either half keeps the text at its
613
+ destination; rejecting either half restores its original location; export
614
+ re-emits native paired move markup. Suggestion cards distinguish “Moved from”
615
+ and “Moved here”, and focusing either half highlights its partner even across
616
+ paragraphs.
617
+
618
+ ### Fixed
619
+
620
+ - **Node-side DOCX imports preserve tracked table-row revisions without a
621
+ browser `FileReader`.** The backend DOM shims and table-revision
622
+ postprocessor now work from `Blob.arrayBuffer()`, retaining row insertion
623
+ and deletion metadata in server integrations.
624
+ - **Word comment anchors preserve their identity and semantic range.** Safe
625
+ native numeric IDs no longer shift, cross-paragraph and table-cell ranges
626
+ emit one anchor triple instead of duplicates, and collapsed, overlapping,
627
+ threaded, and resolved comments survive repeated round trips.
628
+ - **Visible drawing text survives DOCX import when shape geometry is
629
+ flattened.** Inline and anchored DrawingML, grouped shapes, legacy VML,
630
+ headers, and standards-valid `mc:AlternateContent` Choice/Fallback content
631
+ become editable paragraphs in reading order without duplicate fallback text.
632
+ - **DOCX archives no longer inflate and large imports avoid repeated work.**
633
+ Generated packages use DEFLATE compression, parse the main document XML once,
634
+ and skip move indexing when a file has no moves, preventing the reported
635
+ multi-fold output growth and superlinear no-move scan.
636
+
637
+ ## 0.6.0
638
+
639
+ ### Added
640
+
641
+ - **Horizontal rules and ornamental dividers are now supported throughout the
642
+ editor.** Insert thin, thick, double, dashed, dotted, star, or diamond
643
+ dividers from the toolbar or context menu, or create them with text triggers
644
+ such as `---`, `===`, `-**-`, and `-<>-`. DOCX, HTML, Markdown, agent HTML,
645
+ PDF, and plain-text output preserve the divider where the format permits;
646
+ DOCX, HTML, Markdown, RTF, and ODT imports recognize their native divider or
647
+ paragraph-border representations.
648
+
649
+ ### Changed
650
+
651
+ - **Em-dash autocorrection now waits for a word boundary.** Typing `--` remains
652
+ literal until Space or Enter, allowing `---` to be used for horizontal-rule
653
+ insertion and preserving word-initial values such as `--flag`.
654
+
655
+ ### Fixed
656
+
657
+ - **Words no longer wrap in the middle at formatting or tracked-change run
658
+ boundaries.** A word split across differently styled text nodes now wraps as
659
+ one unit and keeps a stable layout when suggestions are accepted.
660
+ - **Suggestion editing produces stable runs and caret placement.** Continued
661
+ typing or backspacing merges into the existing suggestion instead of creating
662
+ one run per keystroke, replacement normalization no longer leaves the caret
663
+ inside hidden deleted text, and Enter after a pending deletion creates the
664
+ expected paragraph or list item without moving the deleted content.
665
+ - **Structural editing keeps the expected document shape and keyboard focus.**
666
+ Backspace exits or splits empty list items correctly, compatible lists rejoin
667
+ when their separating empty paragraph is removed, Enter at the start of a
668
+ leading heading or code block creates a body paragraph above it, and toolbar
669
+ commands no longer steal keyboard focus from the editor.
670
+
671
+ ## 0.5.1
672
+
673
+ ### Fixed
674
+
675
+ - **PDF table-of-contents page numbers stay accurate when a heading moves to
676
+ the next page.** Export now records a heading's destination after paragraph
677
+ pagination, so a keep-with-next or end-of-page preflight cannot leave the
678
+ TOC pointing at the page the heading would have occupied before it moved.
679
+
680
+ ## 0.5.0
681
+
682
+ ### Added
683
+
684
+ - **Comments now work on list items, including nested items.** Selecting list
685
+ text, expanding a word from the caret, and commenting on a whole item all
686
+ create item-local anchors. Returning the caret to that text activates the
687
+ thread, list-item threads survive agent-HTML round trips, and the
688
+ `leave_comment` agent tool accepts list-item IDs.
689
+
690
+ ### Changed
691
+
692
+ - **PDF export now follows the editor's layout and print semantics much more
693
+ closely.** It shares wrapping and pagination rules for tab stops and
694
+ leaders, hyphenation, keep-with-next, keep-lines, widows and orphans, code
695
+ blocks, nested tables, footnotes, page and section breaks, live TOC page
696
+ numbers, line numbers, and watermarks. Editor-only placeholders and review
697
+ chrome are not printed, and Word hidden text remains hidden in ordinary PDF
698
+ output. The SDK now carries its metric-compatible PDF fonts itself, so an
699
+ embedding host does not need to mirror Revise's public font directory.
700
+ - **Agent tool sessions reject redundant full-document read loops.** After a
701
+ session has read the complete document, another sequential `read_document`
702
+ returns `no_new_read_context`; agents can still revisit known content with
703
+ `read_specific_blocks`.
704
+
705
+ ### Fixed
706
+
707
+ - **DOCX formatting exceptions survive a complete edit and export cycle.**
708
+ Explicit run-property clears over named styles, zero paragraph indents,
709
+ paragraph border and shading clears, decimal font sizes, and mixed small-cap
710
+ and all-cap overrides now remain distinct from inherited formatting and do
711
+ not leak into adjacent text.
712
+ - **Complex Word structures no longer lose modeled content on re-export.**
713
+ Internal bookmark links stay internal; exact table widths, columns,
714
+ alignment, cell padding, and vertical alignment survive; nested tables keep
715
+ the paragraphs around them; display equations are not flattened when a file
716
+ is immediately re-exported; and multi-block footnotes and endnotes can retain
717
+ their lists and tables.
718
+ - **Accepting or rejecting a compound agent edit is atomic.** Mixed text,
719
+ formatting, and structural suggestions are resolved together, so accepting
720
+ a rewrite no longer retains deleted fragments and rejecting it restores the
721
+ original content and formatting.
722
+ - **Comment cards stay where users put them.** A previously active card no
723
+ longer drifts with the viewport, and selecting text inside a card no longer
724
+ jumps focus back to the document or clears the selection. Inline code in
725
+ comment bodies is also styled as code.
726
+ - **Package managers can no longer omit the Yjs runtime.** Every editor session
727
+ is Yjs-backed even without a collaboration provider, so `yjs` and
728
+ `y-protocols` are now required peers instead of optional peers. This makes
729
+ package managers install or validate them instead of letting bundlers
730
+ substitute empty optional-peer modules and fail the consumer build.
731
+
732
+ ## 0.4.5
733
+
734
+ ### Fixed
735
+
736
+ - **Starting a list no longer drops the font.** Typing a list trigger
737
+ (`- `, `1. `, `[] `) in a paragraph set in a non-default font produced
738
+ a list item that fell back to the default font: clearing the trigger text
739
+ left an empty item with nowhere to carry its formatting. The formatting at
740
+ the trigger's trailing edge — the font family included — is now preserved
741
+ on the empty item and applies to the next character typed.
742
+
743
+ ## 0.4.4
744
+
745
+ ### Fixed
746
+
747
+ - **Suggestion cards now hang from the suggested text.** The floating
748
+ accept/reject card anchored to the caret; it now follows the suggested
749
+ fragment (or your selection) and sits centered below its line, the same
750
+ placement the revise.io app uses, falling back to the caret only when the
751
+ fragment cannot be measured. Wide cards are clamped to the page edges
752
+ instead of a fixed margin.
753
+
754
+ ## 0.4.3
755
+
756
+ Identical in content to 0.4.2; republished.
757
+
758
+ ## 0.4.2
759
+
760
+ ### Fixed
761
+
762
+ - **Word-level diffs misplaced edits next to repeated words.** When the text
763
+ adjacent to an edit repeated a word from the edit itself (replacing
764
+ "[Berkshire County / appropriate Massachusetts county]," with "Suffolk
765
+ County, Massachusetts," just before "Massachusetts will"), the unchanged
766
+ suffix could be drawn as deleted and retyped. Unchanged repeated words now
767
+ stay anchored as unchanged, in tracked changes and the diff view alike.
768
+ - **Writing a comment no longer collapses the comments margin.** Finishing a
769
+ draft that had itself opened the margin always collapsed it — even when
770
+ submitting had just created a thread, so the pages jerked sideways in both
771
+ directions and hid the card the user just wrote. The margin now stays open
772
+ on the new thread; only an abandoned draft with no other open thread
773
+ collapses it.
774
+ - **Comment card placement around drafts and tracked changes.** A comment
775
+ draft started while hovering the card stack could pin its card — and drag
776
+ the viewport — to the top of page 1; it now anchors where the draft was
777
+ made. A caret inside a resolved thread's highlight, or inside an imported
778
+ thread's replies, activated no card at all; it now activates the right
779
+ open thread. And when a commented paragraph also contains tracked changes,
780
+ the card describes the change under the cursor instead of jumping to the
781
+ top of the paragraph.
782
+ - **The selection card no longer chases the pointer mid-drag.** While the
783
+ mouse button is down nothing pops up under the pointer; the card appears
784
+ on release, anchored below the selection the user meant.
785
+
786
+ ## 0.4.1
787
+
788
+ ### Fixed
789
+
790
+ - **Opening the export menu crashed.** An icon component in the export menu
791
+ referenced React without importing it, which the packaged build has no
792
+ global to fall back on.
793
+
794
+ ## 0.4.0
795
+
796
+ ### Changed
797
+
798
+ - **The default entry no longer ships Tree-sitter syntax highlighting or the
799
+ embedded WASM payload.** Code blocks still render as code, and every WASM
800
+ hot path has a TypeScript implementation. This keeps the normal
801
+ integration smaller and compatible with strict Content Security Policies.
802
+ Optional features now load as async chunks inside the package.
803
+
804
+ ### Added
805
+
806
+ - **`@reviseio/sdk/full`** — an opt-in entry point that keeps token-colored
807
+ code blocks and the WASM hot paths. The API and stylesheet are identical
808
+ between the two entries.
809
+
810
+ ## 0.3.4
811
+
812
+ ### Fixed
813
+
814
+ - **The SDK no longer attempts any telemetry.** Earlier builds emitted
815
+ editor health metrics toward a Revise backend that does not exist in your
816
+ deployment, which could only fail — loudly, as console CORS errors — and
817
+ represented network calls you never asked for. Telemetry is now something
818
+ only the revise.io application itself can switch on; embedded editors
819
+ send nothing anywhere: no metric POSTs, no analytics vendor code, no
820
+ beacons.
821
+
822
+ ### Added
823
+
824
+ - **`onAnalyticsEvent`** — the editor's own instrumentation, delivered to
825
+ the host instead:
826
+ `<ReviseEditor onAnalyticsEvent={(event, properties) => ...} />`.
827
+ Forward events to your own analytics service; a throwing handler never
828
+ breaks the editor. Event names and property shapes are internal and
829
+ version-unstable.
830
+
831
+ ## 0.3.3
832
+
833
+ Four suggesting-mode fixes, two of them content corruption. If your users
834
+ edit in `suggesting` mode — the mode this SDK exists for — take this
835
+ release.
836
+
837
+ ### Fixed
838
+
839
+ - **Pasting in suggesting mode corrupted the document.** The paste path
840
+ predated suggesting mode: it duplicated the rest of the paragraph and
841
+ inserted the pasted text without tracked-change marks, so the paste was
842
+ invisible to review and survived reject. Pasting is now recorded exactly
843
+ as if the pasted characters had been typed — an insertion suggestion, plus
844
+ a deletion suggestion for any replaced selection.
845
+ - **Formatting across a pending change destroyed it.** Applying bold (or any
846
+ inline format) over a range touching a pending insertion or deletion
847
+ overwrote the change's identity; resolving the format then silently turned
848
+ a pending insertion into accepted text, or resurrected deleted text.
849
+ Formatting now leaves deletion spans alone, folds into insertion spans (as
850
+ Word nests run properties inside `w:ins`), and records a reviewable
851
+ format change only on unmarked text.
852
+ - **Accepting a deletion that crossed a paragraph boundary left the
853
+ paragraphs unmerged.** The boundary is now part of the suggestion, as the
854
+ pilcrow is in Word: accepting merges the paragraphs, in any resolution
855
+ order, for any number of paragraphs in the selection.
856
+ - **Copying a selection inside your own pending insertion copied nothing.**
857
+ It now copies the selected text. Clipboard payloads are also sanitized so
858
+ tracked-change marks never travel with copied content.
859
+
860
+ ### Console
861
+
862
+ - Opening a document no longer logs to the console (previously one Yjs
863
+ warning per block plus two internal debug lines). `console.warn` and
864
+ `console.error` remain for genuinely actionable problems.
865
+
866
+ ## 0.3.2
867
+
868
+ ### Fixed
869
+
870
+ - `editor.whenReady()` was missing from the published type declarations. It
871
+ worked at runtime, but TypeScript rejected the call the documentation tells
872
+ you to make.
873
+
874
+ ## 0.3.1
875
+
876
+ ### Fixed
877
+
878
+ - Using the editor handle from `onReady` no longer throws. `onReady` fires
879
+ before any document exists, and "subscribe to everything on ready" is the
880
+ first thing a host writes — a subscription placed then now waits and
881
+ attaches when a document arrives. `selection.observe()` was affected too.
882
+ Methods that act on a document still fail loudly, and the message now names
883
+ the fix.
884
+
885
+ ### Added
886
+
887
+ - `editor.whenReady()` — resolves once a document is open and its
888
+ controllers are usable.
889
+ - `REVISE_SDK_VERSION` and `REVISE_SDK_BUILD` exports, and a `bugs` entry
890
+ in the manifest: a support ticket can name the exact build it came from.
891
+
892
+ ## 0.3.0
893
+
894
+ ### Collaboration
895
+
896
+ Multi-user editing over a Yjs transport you own. The editor builds the
897
+ document; you attach the connection:
898
+
899
+ ```ts
900
+ collaboration: {
901
+ connect: (doc, awareness) =>
902
+ new HocuspocusProvider({ url, name, document: doc, awareness }),
903
+ synced,
904
+ }
905
+ ```
906
+
907
+ Remote carets, a presence roster (`editor.collaboration`), seed-or-join
908
+ semantics, and validation of any document you supply. See the collaboration
909
+ guide.
910
+
911
+ ### Roles
912
+
913
+ `role="editor" | "suggester" | "viewer"`, editor-wide or per document, and
914
+ enforced on every surface: typing, the built-in chrome, the handle, and agent
915
+ tool calls. A suggester cannot leave suggesting mode, apply anything directly,
916
+ or accept and reject.
917
+
918
+ ### Tracked changes you can list
919
+
920
+ `review.listChanges()` and `review.getChange(id)` return each pending change
921
+ with its kind, author, timestamp, affected blocks, and text — enough to build
922
+ your own review panel. Imported Word redlines keep their original reviewers.
923
+
924
+ ### Server-side primitives
925
+
926
+ New subpath export `@reviseio/sdk/backend` (Node only): `parseDocument`,
927
+ `fileToYDoc`, `seedYDocFromFile`, `ydocToDocx`, `encodeYDoc`/`decodeYDoc`.
928
+ Your server can create a collaborative room from a .docx before any browser
929
+ connects, and export a live room without one. Requires `jsdom`.
930
+
931
+ ### Breaking
932
+
933
+ - **`yjs` and `y-protocols` are now peer dependencies** and are no longer
934
+ bundled. Install them yourself, and make sure your bundler resolves ONE copy
935
+ — Yjs identifies its own types with `instanceof`, so a second copy breaks a
936
+ shared document. Only collaboration needs them; they are optional peers.
937
+ - **`ReviseDocumentInput.docx` is now optional**, since a document joining a
938
+ collaborative room needs no source file. Inputs must supply `docx`,
939
+ `collaboration`, or both.
940
+
941
+ ### Fixed
942
+
943
+ - `search_result_id`, which the agent tool schemas advertise for bulk edits,
944
+ was unusable: tool state did not survive between `tools.execute()` calls.
945
+ - `exportDocx()` omitted TOC page numbers, which only the live layout knows.
946
+ - Exports lost imported named styles and reset core property dates in any
947
+ non-browser environment.
948
+ - `collaboration.synced` was read once at mount, so a host reporting sync
949
+ later was ignored and the document never opened.
950
+ - The margin insert-comment chip was missing from the embedded editor.
951
+ - Presence colors: an explicit `currentUser.color` was ignored whenever the
952
+ user had an id.
953
+
954
+ ## 0.2.0
955
+
956
+ Multi-document sessions, host-owned chrome, skinning props, per-embed
957
+ theming, the selection controller, and comment-thread agents.
958
+
959
+ ## 0.1.0
960
+
961
+ First release: the editor, DOCX in and out, tracked changes, comments, and
962
+ the agent tool surface.