@docx-editor.dev/core 2.8.0 → 2.9.1

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 (114) hide show
  1. package/dist/automation.cjs +1 -1
  2. package/dist/automation.d.cts +5 -6
  3. package/dist/automation.d.ts +5 -6
  4. package/dist/automation.js +1 -1
  5. package/dist/binding.cjs +1 -1
  6. package/dist/binding.d.cts +11 -12
  7. package/dist/binding.d.ts +11 -12
  8. package/dist/binding.js +1 -1
  9. package/dist/chunk-5VC5HGJA.js +2 -0
  10. package/dist/chunk-A2JIBG75.js +1 -0
  11. package/dist/chunk-DKMKH77K.cjs +5 -0
  12. package/dist/chunk-FWUI7EXG.cjs +15 -0
  13. package/dist/chunk-GZWMLQJO.js +18 -0
  14. package/dist/chunk-IEXDXWTA.cjs +1 -0
  15. package/dist/chunk-IMMAG4QP.cjs +10 -0
  16. package/dist/chunk-JTSNJQFO.js +15 -0
  17. package/dist/chunk-KBCC66CI.js +5 -0
  18. package/dist/chunk-LJ6BY6IU.cjs +18 -0
  19. package/dist/chunk-QDBAXFIK.js +2 -0
  20. package/dist/chunk-RD266XSK.cjs +2 -0
  21. package/dist/chunk-VUJGPCPU.js +10 -0
  22. package/dist/chunk-XMHWBL3K.cjs +2 -0
  23. package/dist/contracts/editor.d.cts +9 -9
  24. package/dist/contracts/editor.d.ts +9 -9
  25. package/dist/contracts/interaction.d.cts +9 -9
  26. package/dist/contracts/interaction.d.ts +9 -9
  27. package/dist/contracts/modules.d.cts +5 -5
  28. package/dist/contracts/modules.d.ts +5 -5
  29. package/dist/{custom-node-writes-BdVl-LAC.d.ts → custom-node-writes-7ERv0f_X.d.cts} +9 -10
  30. package/dist/{custom-node-writes-Bu8JIqfA.d.cts → custom-node-writes-QyVZdTUA.d.ts} +9 -10
  31. package/dist/{editor-CWlj33GH.d.cts → editor-CojjwMmF.d.cts} +4 -4
  32. package/dist/{editor-D52SD4jG.d.ts → editor-PUlv5Pp7.d.ts} +4 -4
  33. package/dist/editor.cjs +1 -1
  34. package/dist/editor.css +129 -14
  35. package/dist/editor.d.cts +25 -25
  36. package/dist/editor.d.ts +25 -25
  37. package/dist/editor.js +1 -1
  38. package/dist/{hf-references-BdjsQNE_.d.ts → hf-references-Dvk6De4Q.d.cts} +1 -2
  39. package/dist/{hf-references-CgEOSw3i.d.cts → hf-references-z5Y4N1ab.d.ts} +1 -2
  40. package/dist/{image-resources-BveffuKp.d.cts → image-resources-DQOiwOuE.d.cts} +2 -2
  41. package/dist/{image-resources-D63k8w5f.d.ts → image-resources-eZqD_-vC.d.ts} +2 -2
  42. package/dist/{index-39yzaZO_.d.cts → index-DGPSeLI0.d.cts} +66 -13
  43. package/dist/{index-ZuqIj0b9.d.ts → index-oN-v8DQ5.d.ts} +66 -13
  44. package/dist/index.cjs +1 -1
  45. package/dist/index.d.cts +18 -18
  46. package/dist/index.d.ts +18 -18
  47. package/dist/index.js +1 -1
  48. package/dist/layout.cjs +1 -1
  49. package/dist/layout.d.cts +353 -272
  50. package/dist/layout.d.ts +353 -272
  51. package/dist/layout.js +1 -1
  52. package/dist/{note-nodes-BPSTVDMr.d.ts → note-nodes-BNCANoGN.d.ts} +1 -1
  53. package/dist/{note-nodes-C6DLxlvj.d.cts → note-nodes-DL-Au22P.d.cts} +1 -1
  54. package/dist/note-properties-CQlxjic_.d.cts +67 -0
  55. package/dist/note-properties-jvnw_DGG.d.ts +67 -0
  56. package/dist/omml-equation-BD-LsmWE.d.cts +84 -0
  57. package/dist/omml-equation-Dd3mBep-.d.ts +84 -0
  58. package/dist/{ooxml-tree-BU0e3DVi.d.cts → ooxml-package-CdEy9ufK.d.cts} +352 -1
  59. package/dist/{ooxml-tree-BU0e3DVi.d.ts → ooxml-package-CdEy9ufK.d.ts} +352 -1
  60. package/dist/output.cjs +1 -1
  61. package/dist/output.d.cts +8 -8
  62. package/dist/output.d.ts +8 -8
  63. package/dist/output.js +1 -1
  64. package/dist/{protocol-CD7slqvl.d.cts → protocol-C7ahrdUx.d.ts} +28 -4
  65. package/dist/{protocol-DsbfgBwA.d.ts → protocol-UuZOcOp7.d.cts} +28 -4
  66. package/dist/{review-support--I4ChuzF.d.ts → review-items-D5SPFtsO.d.ts} +49 -102
  67. package/dist/{review-support-CG7aVSPh.d.cts → review-items-DpsqTHio.d.cts} +49 -102
  68. package/dist/review-reads-B2Ji3fVU.d.ts +176 -0
  69. package/dist/review-reads-CP106AHp.d.cts +176 -0
  70. package/dist/{revision-projection-UKqvPa4-.d.ts → revision-projection-CILpvv4M.d.ts} +1 -1
  71. package/dist/{revision-projection-WzlQGBJx.d.cts → revision-projection-Cc4wz30g.d.cts} +1 -1
  72. package/dist/{semantic-cell-selection-I-uAmi0q.d.ts → semantic-cell-selection-BWhVAk5B.d.ts} +4 -4
  73. package/dist/{semantic-cell-selection-C45Gn4K-.d.cts → semantic-cell-selection-DJPjBWzf.d.cts} +4 -4
  74. package/dist/{semantic-interaction-DVUqu_47.d.cts → semantic-interaction-BjOcDB06.d.cts} +1 -1
  75. package/dist/{semantic-interaction-Bu_3IPaV.d.ts → semantic-interaction-Cca1-X_a.d.ts} +1 -1
  76. package/dist/{semantic-paint-BKiiDJol.d.ts → semantic-paint-CufpIQFw.d.ts} +7 -7
  77. package/dist/{semantic-paint-COQY0Lnq.d.cts → semantic-paint-Ur7pAINj.d.cts} +7 -7
  78. package/dist/{semantic-records-rAKWaD-1.d.cts → semantic-records-C3Z76KeN.d.cts} +59 -5
  79. package/dist/{semantic-records-DHcMZM2-.d.ts → semantic-records-Cc1MJrhM.d.ts} +59 -5
  80. package/dist/{shaped-measurer-Cw45Nu5R.d.ts → shaped-measurer-CYSK20E2.d.cts} +2 -4
  81. package/dist/{shaped-measurer-BRL__nm2.d.cts → shaped-measurer-CwlTPDJO.d.ts} +2 -4
  82. package/dist/store.cjs +1 -1
  83. package/dist/store.d.cts +78 -18
  84. package/dist/store.d.ts +78 -18
  85. package/dist/store.js +1 -1
  86. package/dist/{tree-op-types-A-SLSKzK.d.cts → tree-op-types-B0-sCtw-.d.cts} +27 -3
  87. package/dist/{tree-op-types-BbzrA-kg.d.ts → tree-op-types-XMVsJSpe.d.ts} +27 -3
  88. package/dist/{tree-session-C2NsEgfW.d.cts → tree-session-D945D43B.d.cts} +9 -18
  89. package/dist/{tree-session-DeNJa86l.d.ts → tree-session-DBJgmdmc.d.ts} +9 -18
  90. package/dist/{tree-store-CKswbQl3.d.ts → tree-store-C6vc8E_2.d.cts} +2 -3
  91. package/dist/{tree-store-Dob9Us6Y.d.cts → tree-store-ClA-qng4.d.ts} +2 -3
  92. package/package.json +2 -2
  93. package/dist/chunk-2WIXJ7CW.js +0 -10
  94. package/dist/chunk-42PRWWVE.js +0 -2
  95. package/dist/chunk-5XKD3VFP.js +0 -18
  96. package/dist/chunk-HCSWWXS2.cjs +0 -2
  97. package/dist/chunk-HTJLSGBH.cjs +0 -18
  98. package/dist/chunk-JEHWQPXS.cjs +0 -1
  99. package/dist/chunk-KCJLRAKT.js +0 -5
  100. package/dist/chunk-KTL3UMPK.js +0 -2
  101. package/dist/chunk-M6ZIVJUA.cjs +0 -2
  102. package/dist/chunk-NU57YOQE.js +0 -15
  103. package/dist/chunk-RUS2YBWU.cjs +0 -10
  104. package/dist/chunk-TJEWP7MX.cjs +0 -15
  105. package/dist/chunk-UGUPVZDY.cjs +0 -5
  106. package/dist/chunk-XJRMFS6O.js +0 -1
  107. package/dist/chunk-XN634HAC.js +0 -2
  108. package/dist/chunk-XRDTD4X3.cjs +0 -2
  109. package/dist/content-control-walk-CbTqHq6O.d.cts +0 -56
  110. package/dist/content-control-walk-D06GijR0.d.ts +0 -56
  111. package/dist/ooxml-package-CR5us6ad.d.cts +0 -354
  112. package/dist/ooxml-package-D_CtywTW.d.ts +0 -354
  113. package/dist/review-reads-B_pXe43J.d.ts +0 -432
  114. package/dist/review-reads-Bn7aZU4u.d.cts +0 -432
@@ -1,5 +1,5 @@
1
- import { e as OoxmlPart, a as OoxmlElement } from './ooxml-tree-BU0e3DVi.js';
2
- import { R as RevisionAddress } from './tree-op-types-BbzrA-kg.js';
1
+ import { b as OoxmlElement, O as OoxmlPart, c as OoxmlPackage } from './ooxml-package-CdEy9ufK.js';
2
+ import { R as RevisionAddress } from './tree-op-types-XMVsJSpe.js';
3
3
 
4
4
  /** The `w15` namespace: `commentsExtended.xml` — thread parent and resolved state. */
5
5
  declare const W15_NAMESPACE_URI = "http://schemas.microsoft.com/office/word/2012/wordml";
@@ -32,7 +32,7 @@ interface CommentRecord {
32
32
  readonly date?: string;
33
33
  /** Body paragraphs, as tree nodes, so the surface renders measured text rather than a string. */
34
34
  readonly blocks: readonly OoxmlElement[];
35
- /** `w14:paraId` of the first body paragraph — the key thread state is stored under. */
35
+ /** `w14:paraId` of the last body paragraph — the key thread state is stored under. */
36
36
  readonly paraId?: string;
37
37
  /** `@w16cid:parentId` — the `w:id` of the comment this replies to, when the file names it. */
38
38
  readonly parentCommentId?: string;
@@ -43,6 +43,41 @@ interface CommentThreadState {
43
43
  readonly parentParaId?: string;
44
44
  readonly done: boolean;
45
45
  }
46
+ /**
47
+ * Every comment anchor in one story, in document order.
48
+ *
49
+ * Overlapping and nested ranges are supported because each anchor is resolved independently —
50
+ * Word produces both, and a model that assumed ranges nest cleanly would mis-anchor them.
51
+ *
52
+ * A start with no matching end anchors to the end of its own paragraph and is reported orphaned
53
+ * rather than guessed at: extending it to the next end marker would attach a reviewer's remark
54
+ * to text they never saw.
55
+ */
56
+ declare function commentAnchorsOfStory(part: OoxmlPart): CommentAnchor[];
57
+ /**
58
+ * The comments in `word/comments.xml`, in authored order.
59
+ *
60
+ * Every value here comes from a file an attacker fully controls, so nothing is interpreted:
61
+ * author, initials and date are carried verbatim for a surface that will set them as TEXT.
62
+ */
63
+ declare function commentsOfPart(part: OoxmlPart): CommentRecord[];
64
+ /**
65
+ * Thread state by `w14:paraId`, from `commentsExtended.xml`.
66
+ *
67
+ * The part being PRESENT is not evidence of threading. `issue-68-large-comments-suggestions.docx`
68
+ * ships it with 212 entries carrying `@w15:done` and not one `@w15:paraIdParent`, so it records
69
+ * resolved state for a flat list. Absent parent means top-level, and that is a fact about the
70
+ * file rather than a default this code chose.
71
+ */
72
+ declare function threadStateOfPart(part: OoxmlPart): Map<string, CommentThreadState>;
73
+ /**
74
+ * Whether the package holds any `w:comment` record — the cheap gate before a reap.
75
+ *
76
+ * Overflow cannot prove the package is comment-free, so it returns true and the reap still
77
+ * runs rather than skipping cleanup.
78
+ */
79
+ declare function hasAnyComment(pkg: OoxmlPackage): boolean;
80
+
46
81
  /** A position in the model offset space of one story. */
47
82
  interface ReviewPosition {
48
83
  readonly paragraphId: string;
@@ -136,8 +171,8 @@ interface ReviewRevisionItem {
136
171
  /**
137
172
  * True when the engine cannot resolve this kind, so accept and reject must not be offered.
138
173
  *
139
- * Derived by the MODULE rather than from a caller-supplied predicate: the refusal list is
140
- * internal, and a surface asked to compute it would have to guess. A card that offers a
174
+ * Derived by the DERIVATION rather than from a caller-supplied predicate: the refusal list
175
+ * is internal, and a surface asked to compute it would have to guess. A card that offers a
141
176
  * button the engine will refuse is worse than one that explains why it cannot.
142
177
  */
143
178
  readonly readOnly: boolean;
@@ -227,6 +262,9 @@ interface ReviewCustomItem {
227
262
  /**
228
263
  * One pending decision in the review queue: a tracked change, a comment thread, or a pro
229
264
  * custom-node card. Discriminate on `kind`.
265
+ *
266
+ * The store's own derivation (`collectReviewItems`) only ever produces the first two; the
267
+ * `kind: 'custom'` card is contributed by the pro review module, which recognizes the node.
230
268
  */
231
269
  type ReviewItem = ReviewRevisionItem | ReviewCommentItem | ReviewCustomItem;
232
270
  /** What the review queue derivation reads: one story part plus its comment parts. */
@@ -251,6 +289,11 @@ interface ReviewModelInput {
251
289
  * `kind: 'custom'` cards for definitions that opted in.
252
290
  */
253
291
  readonly customNodes?: readonly unknown[] | undefined;
292
+ /**
293
+ * Where a capability package reports a node it could not read. Supplied per editor, so a page
294
+ * with two of them keeps their diagnostics apart.
295
+ */
296
+ readonly reportCustomNodeDiagnostic?: ((diagnostic: unknown) => void) | undefined;
254
297
  /**
255
298
  * The payload each of the story's controls binds to, keyed by the control's node id.
256
299
  *
@@ -259,11 +302,6 @@ interface ReviewModelInput {
259
302
  * input on both members; a capability package validates it against whatever shape it
260
303
  * declared before handing it to a host.
261
304
  */
262
- /**
263
- * Where a capability package reports a node it could not read. Supplied per editor, so a page
264
- * with two of them keeps their diagnostics apart.
265
- */
266
- readonly reportCustomNodeDiagnostic?: ((diagnostic: unknown) => void) | undefined;
267
305
  readonly customNodePayloads?: ReadonlyMap<string, {
268
306
  readonly nodeId: string;
269
307
  readonly label: string;
@@ -272,11 +310,6 @@ interface ReviewModelInput {
272
310
  }
273
311
  /** The stable key a surface uses for the active item and for a React list. */
274
312
  declare function reviewItemKey(item: ReviewItem): string;
275
- /** Plain text of a comment's body, so a card never re-implements the run walk. */
276
- declare function commentBodyText(comment: CommentRecord): string;
277
- /** Author initials for an avatar, from `@w:initials` or the name. */
278
- declare function commentInitials(comment: CommentRecord): string;
279
-
280
313
  /** Every range a decision touches. One card can cover several, in different paragraphs. */
281
314
  declare function reviewItemRanges(item: ReviewItem): readonly ReviewRange[];
282
315
  /** The first range of an item, in authored order, or null when it has none. */
@@ -324,91 +357,5 @@ declare function activeReviewItem(items: readonly ReviewItem[], position: Review
324
357
  * moment a reply could answer a revision, which outranks it outright.
325
358
  */
326
359
  declare function reviewThreadRootOf(items: readonly ReviewItem[], comment: ReviewCommentItem): ReviewItem;
327
- /** Where one paragraph sits, resolved once so a card is an O(1) lookup. */
328
- interface ReviewParagraphAnchor {
329
- readonly pageIndex: number;
330
- /** Sheet-absolute y of the page's content box. */
331
- readonly contentY: number;
332
- /** The fragment's own y, measured from that content box. */
333
- readonly fragmentY: number;
334
- readonly lines?: readonly {
335
- readonly range: {
336
- readonly end: number;
337
- };
338
- readonly box: {
339
- readonly y: number;
340
- };
341
- /**
342
- * Present on a real line. A merged fragment's join line carries spans from two
343
- * paragraphs, and its `range` can only name one of them, so the OTHER paragraph's extent
344
- * on that line is readable here and nowhere else.
345
- */
346
- readonly spans?: readonly {
347
- readonly range: {
348
- readonly paragraphId: string;
349
- readonly end: number;
350
- };
351
- }[];
352
- }[];
353
- }
354
- /**
355
- * The y of the line a position sits on, measured from the anchor's own origin.
356
- *
357
- * An ordinary line answers from its own range, exactly as it always did. On a merged
358
- * fragment's join line the range names one of the two paragraphs, so an offset compared
359
- * against it either overshot — putting a card in the absorbed half beside the wrong line —
360
- * or matched the first line every time.
361
- */
362
- declare function anchorLineY(anchor: ReviewParagraphAnchor, paragraphId: string, offset: number): number;
363
- /**
364
- * Paragraph id to its place on the page, in ONE pass over the layout.
365
- *
366
- * Built once per layout and reused by every card. The straightforward version — scan the
367
- * pages until the paragraph turns up, per card — is a full-document walk per card, and a
368
- * contract with two hundred comments walked the document two hundred times every time the
369
- * caret moved. Toggling the pane was visibly slow for exactly that reason.
370
- */
371
- declare function reviewAnchorIndex<TPage extends {
372
- readonly index: number;
373
- readonly contentBox: {
374
- readonly y: number;
375
- };
376
- }>(layout: {
377
- readonly pages: readonly TPage[];
378
- }, paragraphFragments: (page: TPage) => readonly {
379
- readonly paragraphId: string;
380
- readonly box: {
381
- readonly y: number;
382
- };
383
- readonly lines?: readonly {
384
- readonly range: {
385
- readonly end: number;
386
- };
387
- readonly box: {
388
- readonly y: number;
389
- };
390
- /** Present on a real line; a merged one carries spans from more than one paragraph. */
391
- readonly spans?: readonly {
392
- readonly range: {
393
- readonly paragraphId: string;
394
- readonly end: number;
395
- };
396
- }[];
397
- }[];
398
- }[]): Map<string, ReviewParagraphAnchor>;
399
- /**
400
- * Where a card belongs beside the page, from LAYOUT RECORDS.
401
- *
402
- * The one question the tree cannot answer, and the one a surface must not answer for itself:
403
- * measuring painted DOM puts the sidebar a repaint behind the document and breaks outright
404
- * while pagination is in flight.
405
- *
406
- * Returns null when the item has no resolvable range, or when its paragraph is not in this
407
- * layout — a comment anchored in a header belongs to a story the body layout never saw.
408
- */
409
- declare function reviewItemGeometry(item: ReviewItem, index: ReadonlyMap<string, ReviewParagraphAnchor>): {
410
- readonly pageIndex: number;
411
- readonly y: number;
412
- } | null;
413
360
 
414
- export { type CommentRecord as C, type ReviewModelInput as R, W15_NAMESPACE_URI as W, type ReviewItem as a, type ReviewRevisionItem as b, type ReviewCommentItem as c, type ReviewCustomItem as d, type ReviewPosition as e, type ReviewRange as f, type ReviewRevisionKind as g, type CommentAnchor as h, type CommentPosition as i, type CommentThreadState as j, type ReviewParagraphAnchor as k, activeReviewItem as l, anchorLineY as m, commentBodyText as n, commentInitials as o, firstReviewRange as p, reviewItemGeometry as q, reviewAnchorIndex as r, reviewItemKey as s, reviewItemPositionRank as t, reviewItemRanges as u, reviewItemsAt as v, reviewThreadRootOf as w };
361
+ export { type CommentRecord as C, type ReviewModelInput as R, W15_NAMESPACE_URI as W, type ReviewItem as a, type ReviewRevisionItem as b, type ReviewCommentItem as c, type ReviewCustomItem as d, type ReviewPosition as e, type ReviewRange as f, type ReviewRevisionKind as g, type CommentThreadState as h, type CommentAnchor as i, type CommentPosition as j, activeReviewItem as k, firstReviewRange as l, reviewItemPositionRank as m, reviewItemRanges as n, reviewItemsAt as o, reviewThreadRootOf as p, commentAnchorsOfStory as q, reviewItemKey as r, commentsOfPart as s, hasAnyComment as t, threadStateOfPart as u };
@@ -1,5 +1,5 @@
1
- import { e as OoxmlPart, a as OoxmlElement } from './ooxml-tree-BU0e3DVi.cjs';
2
- import { R as RevisionAddress } from './tree-op-types-A-SLSKzK.cjs';
1
+ import { b as OoxmlElement, O as OoxmlPart, c as OoxmlPackage } from './ooxml-package-CdEy9ufK.cjs';
2
+ import { R as RevisionAddress } from './tree-op-types-B0-sCtw-.cjs';
3
3
 
4
4
  /** The `w15` namespace: `commentsExtended.xml` — thread parent and resolved state. */
5
5
  declare const W15_NAMESPACE_URI = "http://schemas.microsoft.com/office/word/2012/wordml";
@@ -32,7 +32,7 @@ interface CommentRecord {
32
32
  readonly date?: string;
33
33
  /** Body paragraphs, as tree nodes, so the surface renders measured text rather than a string. */
34
34
  readonly blocks: readonly OoxmlElement[];
35
- /** `w14:paraId` of the first body paragraph — the key thread state is stored under. */
35
+ /** `w14:paraId` of the last body paragraph — the key thread state is stored under. */
36
36
  readonly paraId?: string;
37
37
  /** `@w16cid:parentId` — the `w:id` of the comment this replies to, when the file names it. */
38
38
  readonly parentCommentId?: string;
@@ -43,6 +43,41 @@ interface CommentThreadState {
43
43
  readonly parentParaId?: string;
44
44
  readonly done: boolean;
45
45
  }
46
+ /**
47
+ * Every comment anchor in one story, in document order.
48
+ *
49
+ * Overlapping and nested ranges are supported because each anchor is resolved independently —
50
+ * Word produces both, and a model that assumed ranges nest cleanly would mis-anchor them.
51
+ *
52
+ * A start with no matching end anchors to the end of its own paragraph and is reported orphaned
53
+ * rather than guessed at: extending it to the next end marker would attach a reviewer's remark
54
+ * to text they never saw.
55
+ */
56
+ declare function commentAnchorsOfStory(part: OoxmlPart): CommentAnchor[];
57
+ /**
58
+ * The comments in `word/comments.xml`, in authored order.
59
+ *
60
+ * Every value here comes from a file an attacker fully controls, so nothing is interpreted:
61
+ * author, initials and date are carried verbatim for a surface that will set them as TEXT.
62
+ */
63
+ declare function commentsOfPart(part: OoxmlPart): CommentRecord[];
64
+ /**
65
+ * Thread state by `w14:paraId`, from `commentsExtended.xml`.
66
+ *
67
+ * The part being PRESENT is not evidence of threading. `issue-68-large-comments-suggestions.docx`
68
+ * ships it with 212 entries carrying `@w15:done` and not one `@w15:paraIdParent`, so it records
69
+ * resolved state for a flat list. Absent parent means top-level, and that is a fact about the
70
+ * file rather than a default this code chose.
71
+ */
72
+ declare function threadStateOfPart(part: OoxmlPart): Map<string, CommentThreadState>;
73
+ /**
74
+ * Whether the package holds any `w:comment` record — the cheap gate before a reap.
75
+ *
76
+ * Overflow cannot prove the package is comment-free, so it returns true and the reap still
77
+ * runs rather than skipping cleanup.
78
+ */
79
+ declare function hasAnyComment(pkg: OoxmlPackage): boolean;
80
+
46
81
  /** A position in the model offset space of one story. */
47
82
  interface ReviewPosition {
48
83
  readonly paragraphId: string;
@@ -136,8 +171,8 @@ interface ReviewRevisionItem {
136
171
  /**
137
172
  * True when the engine cannot resolve this kind, so accept and reject must not be offered.
138
173
  *
139
- * Derived by the MODULE rather than from a caller-supplied predicate: the refusal list is
140
- * internal, and a surface asked to compute it would have to guess. A card that offers a
174
+ * Derived by the DERIVATION rather than from a caller-supplied predicate: the refusal list
175
+ * is internal, and a surface asked to compute it would have to guess. A card that offers a
141
176
  * button the engine will refuse is worse than one that explains why it cannot.
142
177
  */
143
178
  readonly readOnly: boolean;
@@ -227,6 +262,9 @@ interface ReviewCustomItem {
227
262
  /**
228
263
  * One pending decision in the review queue: a tracked change, a comment thread, or a pro
229
264
  * custom-node card. Discriminate on `kind`.
265
+ *
266
+ * The store's own derivation (`collectReviewItems`) only ever produces the first two; the
267
+ * `kind: 'custom'` card is contributed by the pro review module, which recognizes the node.
230
268
  */
231
269
  type ReviewItem = ReviewRevisionItem | ReviewCommentItem | ReviewCustomItem;
232
270
  /** What the review queue derivation reads: one story part plus its comment parts. */
@@ -251,6 +289,11 @@ interface ReviewModelInput {
251
289
  * `kind: 'custom'` cards for definitions that opted in.
252
290
  */
253
291
  readonly customNodes?: readonly unknown[] | undefined;
292
+ /**
293
+ * Where a capability package reports a node it could not read. Supplied per editor, so a page
294
+ * with two of them keeps their diagnostics apart.
295
+ */
296
+ readonly reportCustomNodeDiagnostic?: ((diagnostic: unknown) => void) | undefined;
254
297
  /**
255
298
  * The payload each of the story's controls binds to, keyed by the control's node id.
256
299
  *
@@ -259,11 +302,6 @@ interface ReviewModelInput {
259
302
  * input on both members; a capability package validates it against whatever shape it
260
303
  * declared before handing it to a host.
261
304
  */
262
- /**
263
- * Where a capability package reports a node it could not read. Supplied per editor, so a page
264
- * with two of them keeps their diagnostics apart.
265
- */
266
- readonly reportCustomNodeDiagnostic?: ((diagnostic: unknown) => void) | undefined;
267
305
  readonly customNodePayloads?: ReadonlyMap<string, {
268
306
  readonly nodeId: string;
269
307
  readonly label: string;
@@ -272,11 +310,6 @@ interface ReviewModelInput {
272
310
  }
273
311
  /** The stable key a surface uses for the active item and for a React list. */
274
312
  declare function reviewItemKey(item: ReviewItem): string;
275
- /** Plain text of a comment's body, so a card never re-implements the run walk. */
276
- declare function commentBodyText(comment: CommentRecord): string;
277
- /** Author initials for an avatar, from `@w:initials` or the name. */
278
- declare function commentInitials(comment: CommentRecord): string;
279
-
280
313
  /** Every range a decision touches. One card can cover several, in different paragraphs. */
281
314
  declare function reviewItemRanges(item: ReviewItem): readonly ReviewRange[];
282
315
  /** The first range of an item, in authored order, or null when it has none. */
@@ -324,91 +357,5 @@ declare function activeReviewItem(items: readonly ReviewItem[], position: Review
324
357
  * moment a reply could answer a revision, which outranks it outright.
325
358
  */
326
359
  declare function reviewThreadRootOf(items: readonly ReviewItem[], comment: ReviewCommentItem): ReviewItem;
327
- /** Where one paragraph sits, resolved once so a card is an O(1) lookup. */
328
- interface ReviewParagraphAnchor {
329
- readonly pageIndex: number;
330
- /** Sheet-absolute y of the page's content box. */
331
- readonly contentY: number;
332
- /** The fragment's own y, measured from that content box. */
333
- readonly fragmentY: number;
334
- readonly lines?: readonly {
335
- readonly range: {
336
- readonly end: number;
337
- };
338
- readonly box: {
339
- readonly y: number;
340
- };
341
- /**
342
- * Present on a real line. A merged fragment's join line carries spans from two
343
- * paragraphs, and its `range` can only name one of them, so the OTHER paragraph's extent
344
- * on that line is readable here and nowhere else.
345
- */
346
- readonly spans?: readonly {
347
- readonly range: {
348
- readonly paragraphId: string;
349
- readonly end: number;
350
- };
351
- }[];
352
- }[];
353
- }
354
- /**
355
- * The y of the line a position sits on, measured from the anchor's own origin.
356
- *
357
- * An ordinary line answers from its own range, exactly as it always did. On a merged
358
- * fragment's join line the range names one of the two paragraphs, so an offset compared
359
- * against it either overshot — putting a card in the absorbed half beside the wrong line —
360
- * or matched the first line every time.
361
- */
362
- declare function anchorLineY(anchor: ReviewParagraphAnchor, paragraphId: string, offset: number): number;
363
- /**
364
- * Paragraph id to its place on the page, in ONE pass over the layout.
365
- *
366
- * Built once per layout and reused by every card. The straightforward version — scan the
367
- * pages until the paragraph turns up, per card — is a full-document walk per card, and a
368
- * contract with two hundred comments walked the document two hundred times every time the
369
- * caret moved. Toggling the pane was visibly slow for exactly that reason.
370
- */
371
- declare function reviewAnchorIndex<TPage extends {
372
- readonly index: number;
373
- readonly contentBox: {
374
- readonly y: number;
375
- };
376
- }>(layout: {
377
- readonly pages: readonly TPage[];
378
- }, paragraphFragments: (page: TPage) => readonly {
379
- readonly paragraphId: string;
380
- readonly box: {
381
- readonly y: number;
382
- };
383
- readonly lines?: readonly {
384
- readonly range: {
385
- readonly end: number;
386
- };
387
- readonly box: {
388
- readonly y: number;
389
- };
390
- /** Present on a real line; a merged one carries spans from more than one paragraph. */
391
- readonly spans?: readonly {
392
- readonly range: {
393
- readonly paragraphId: string;
394
- readonly end: number;
395
- };
396
- }[];
397
- }[];
398
- }[]): Map<string, ReviewParagraphAnchor>;
399
- /**
400
- * Where a card belongs beside the page, from LAYOUT RECORDS.
401
- *
402
- * The one question the tree cannot answer, and the one a surface must not answer for itself:
403
- * measuring painted DOM puts the sidebar a repaint behind the document and breaks outright
404
- * while pagination is in flight.
405
- *
406
- * Returns null when the item has no resolvable range, or when its paragraph is not in this
407
- * layout — a comment anchored in a header belongs to a story the body layout never saw.
408
- */
409
- declare function reviewItemGeometry(item: ReviewItem, index: ReadonlyMap<string, ReviewParagraphAnchor>): {
410
- readonly pageIndex: number;
411
- readonly y: number;
412
- } | null;
413
360
 
414
- export { type CommentRecord as C, type ReviewModelInput as R, W15_NAMESPACE_URI as W, type ReviewItem as a, type ReviewRevisionItem as b, type ReviewCommentItem as c, type ReviewCustomItem as d, type ReviewPosition as e, type ReviewRange as f, type ReviewRevisionKind as g, type CommentAnchor as h, type CommentPosition as i, type CommentThreadState as j, type ReviewParagraphAnchor as k, activeReviewItem as l, anchorLineY as m, commentBodyText as n, commentInitials as o, firstReviewRange as p, reviewItemGeometry as q, reviewAnchorIndex as r, reviewItemKey as s, reviewItemPositionRank as t, reviewItemRanges as u, reviewItemsAt as v, reviewThreadRootOf as w };
361
+ export { type CommentRecord as C, type ReviewModelInput as R, W15_NAMESPACE_URI as W, type ReviewItem as a, type ReviewRevisionItem as b, type ReviewCommentItem as c, type ReviewCustomItem as d, type ReviewPosition as e, type ReviewRange as f, type ReviewRevisionKind as g, type CommentThreadState as h, type CommentAnchor as i, type CommentPosition as j, activeReviewItem as k, firstReviewRange as l, reviewItemPositionRank as m, reviewItemRanges as n, reviewItemsAt as o, reviewThreadRootOf as p, commentAnchorsOfStory as q, reviewItemKey as r, commentsOfPart as s, hasAnyComment as t, threadStateOfPart as u };
@@ -0,0 +1,176 @@
1
+ import { a as OoxmlNode, b as OoxmlElement, p as OoxmlContentControlNode, m as OoxmlGenericElementNode, q as OoxmlContentControlContentNode, O as OoxmlPart } from './ooxml-package-CdEy9ufK.js';
2
+ import { C as CommentRecord, f as ReviewRange, R as ReviewModelInput, a as ReviewItem, e as ReviewPosition, h as CommentThreadState, c as ReviewCommentItem, b as ReviewRevisionItem } from './review-items-D5SPFtsO.js';
3
+
4
+ /** Nested content-control wrappers deeper than this stop flattening; content stays preserved. */
5
+ declare const MAX_CONTENT_CONTROL_NESTING = 32;
6
+ type ContentControlLike = OoxmlContentControlNode | OoxmlGenericElementNode;
7
+ type ContentControlContentLike = OoxmlContentControlContentNode | OoxmlGenericElementNode;
8
+ /**
9
+ * Block or inline structured-document-tag wrapper — typed or generic during migration.
10
+ *
11
+ * Generic fallback requires the WordprocessingML namespace so foreign-namespace
12
+ * `<x:sdt>` elements stay opaque wrappers and are never treated as Word controls.
13
+ */
14
+ declare function isContentControl(node: OoxmlNode): node is ContentControlLike;
15
+ /**
16
+ * True when `node` is the control's content container (`w:sdtContent`).
17
+ *
18
+ * Generic `sdtContent` requires the WML namespace — same foreign-namespace rule as
19
+ * {@link isContentControl}.
20
+ */
21
+ declare function isContentControlContent(node: OoxmlNode): node is ContentControlContentLike;
22
+ /** Children of the first `w:sdtContent` under a control, or null when absent or not a control. */
23
+ declare function contentControlContentOf(node: OoxmlNode): readonly OoxmlNode[] | null;
24
+ /**
25
+ * Children of every `w:sdtContent` under a control, in document order.
26
+ *
27
+ * Does not recurse into nested controls — callers that flatten blocks or inline runs do that
28
+ * with their own depth counter against {@link MAX_CONTENT_CONTROL_NESTING}.
29
+ */
30
+ declare function contentControlContentChildren(control: OoxmlNode): readonly OoxmlNode[];
31
+ /**
32
+ * Collect paragraph and table blocks from a sibling list, flattening through content-control
33
+ * wrappers up to {@link MAX_CONTENT_CONTROL_NESTING}.
34
+ *
35
+ * `accept` filters which typed blocks are kept (e.g. skip revision-removed paragraphs). When
36
+ * nesting exceeds the bound the wrapper is skipped entirely — same fail-closed rule as the
37
+ * historical `storyBlocks` walk.
38
+ */
39
+ declare function collectFlowBlocks(children: readonly OoxmlNode[], depth?: number, accept?: (block: OoxmlElement) => boolean): OoxmlElement[];
40
+ /**
41
+ * Story blocks in document order, flattening block-level content controls — same shape as
42
+ * layout's `storyBlocks` and store `bodyBlocks`.
43
+ */
44
+ declare function walkStoryBlocks(children: readonly OoxmlNode[], depth: number, visit: (block: OoxmlElement) => void): void;
45
+ /**
46
+ * Every story paragraph in reading order — body, table cells, and flattened block controls.
47
+ */
48
+ declare function walkAllStoryParagraphs(children: readonly OoxmlNode[], sdtDepth: number, visit: (paragraph: OoxmlElement) => void): void;
49
+ /**
50
+ * Paragraph-level inline sequence — runs, hyperlinks, and inline content controls in order.
51
+ *
52
+ * `visit` receives each direct `w:r` and any other inline node the caller treats as opaque
53
+ * (bookmarks, drawings, …). Hyperlinks and content controls are descended transparently.
54
+ */
55
+ declare function walkParagraphInline(children: readonly OoxmlNode[], depth: number, visit: (child: OoxmlNode) => void): void;
56
+
57
+ /** Plain text of a comment's body, so a card never re-implements the run walk. */
58
+ declare function commentBodyText(comment: CommentRecord): string;
59
+ /** Author initials for an avatar, from `@w:initials` or the name. */
60
+ declare function commentInitials(comment: CommentRecord): string;
61
+ /**
62
+ * Every revision in one story, one card per DECISION.
63
+ *
64
+ * Sites sharing an `(id, author, date)` triple are ONE revision — a tracked row insertion is
65
+ * `w:trPr/w:ins` plus `w:cellIns` on every cell — so they coalesce into one card listing every
66
+ * range it touches. Keying per site would show the reviewer four decisions where there is one,
67
+ * and accepting any of them would make the other three vanish.
68
+ *
69
+ * Memoized per part root like the indexes it reads, and for the same reason: a heavily
70
+ * tracked document produces tens of thousands of cards, and rebuilding them per read cost
71
+ * more than everything the memos above saved. The paragraph-scoped view the local review
72
+ * patch derives (`revisionItemsOfParagraph`'s synthetic paragraph-root part) is NOT cached:
73
+ * each keystroke would insert a fresh root and churn the bounded ring. The instance is
74
+ * SHARED, so the return type is readonly.
75
+ */
76
+ declare function revisionItemsOf(part: OoxmlPart): readonly ReviewRevisionItem[];
77
+ /**
78
+ * Comment cards, threaded however the file says so and flat when nothing says so.
79
+ *
80
+ * ECMA-376 §17.13.4.2 gives `CT_Comment` no parent pointer, so threading is never something
81
+ * the standard states outright. Three sources, strongest first: `@w15:paraIdParent`, then
82
+ * `@w16cid:parentId` — both in namespaces outside Part 1 — and finally a COINCIDENT anchor, a
83
+ * comment whose `w:commentRangeStart`/`End` cover exactly the characters an earlier comment's
84
+ * cover. The ranges are Part 1's own vocabulary and the only part of a thread that survives a
85
+ * producer dropping the extension parts. Coincidence is the last resort and never overrides a
86
+ * stated link.
87
+ *
88
+ * Deliberately not containment. A remark on one word inside another remark's sentence nests
89
+ * without being a reply, and reading that as a thread would bury an independent comment inside
90
+ * someone else's.
91
+ */
92
+ declare function commentItemsOf(comments: readonly CommentRecord[], anchors: readonly {
93
+ commentId: string;
94
+ partName: string;
95
+ start: ReviewPosition;
96
+ end: ReviewPosition;
97
+ orphaned: boolean;
98
+ }[], threadState: ReadonlyMap<string, CommentThreadState>): ReviewCommentItem[];
99
+ /**
100
+ * Everything the review surface lists, in document order.
101
+ *
102
+ * Order is by paragraph position within the story, then by offset. A comment and the revision
103
+ * it covers therefore arrive together, which is what lets a surface group them. Furniture
104
+ * stories rank after the body in one merged order — their geometry (the page they first paint
105
+ * on) is a layout question the queue deliberately does not answer.
106
+ */
107
+ declare function collectReviewItems(input: ReviewModelInput): ReviewItem[];
108
+ /**
109
+ * The shape {@link linkRevisionReplies} needs, stated STRUCTURALLY.
110
+ *
111
+ * The store's queue is revisions and comments; the layout lane's adds a third kind for custom
112
+ * nodes, and neither union is assignable to the other. Both lanes have to run this pass — the
113
+ * store on the full derivation, the session on the locally patched list — so the pass is
114
+ * written against the fields it actually reads rather than against either union, and hands
115
+ * back the caller's own item type.
116
+ */
117
+ interface LinkableReviewItem {
118
+ readonly kind: string;
119
+ readonly id: string;
120
+ readonly ranges?: readonly ReviewRange[];
121
+ readonly range?: ReviewRange | null;
122
+ readonly parentId?: string;
123
+ readonly parentRevisionId?: string;
124
+ readonly replyIds?: readonly string[];
125
+ readonly orphaned?: boolean;
126
+ /** How deeply a revision is nested; absent on the kinds that cannot nest. */
127
+ readonly nesting?: number;
128
+ }
129
+ /**
130
+ * Attach each comment that answers a tracked change to the change it answers.
131
+ *
132
+ * The evidence is the RANGE, exactly as it is for a coincident comment thread: replying to a
133
+ * revision writes a comment over that revision's own characters, because OOXML gives `w:ins`
134
+ * and `w:del` nowhere else to put the text. Without this the reply came back as an independent
135
+ * card in the rail, sitting beside the change rather than inside it, and the reader had no way
136
+ * to see which change their answer belonged to.
137
+ *
138
+ * Three things keep it from over-claiming. A ZERO-WIDTH range is evidence of nothing — the same
139
+ * rule the comment threading uses, and a format or paragraph-mark revision decorates no
140
+ * characters at all. A comment already stated to be a REPLY to another comment is not claimed
141
+ * directly, because a stated link always beats an inferred one. And the FIRST revision on a span
142
+ * wins, so a card cannot claim a reply another card already holds.
143
+ *
144
+ * The WHOLE conversation moves, not its head. A change's card renders `replyIds` as a flat list,
145
+ * so linking only the top comment of a thread left every answer to that answer rendered by
146
+ * nobody: reply twice to one change and the second reply existed in `comments.xml` and appeared
147
+ * nowhere on screen. Descendants ride along, in the order they were authored.
148
+ *
149
+ * IDEMPOTENT, and that is load-bearing. The session re-runs this over a list whose comments are
150
+ * ALREADY linked, so a pass that only ever added links left a stale `parentRevisionId` behind
151
+ * when a keystroke shifted the revision's offsets out from under it — the rail filters such a
152
+ * comment out of its roots, and with no revision claiming it any more the card vanished until
153
+ * the next full re-derivation. Every link is rebuilt from the ranges on every pass.
154
+ */
155
+ declare function linkRevisionReplies<T extends LinkableReviewItem>(items: readonly T[]): T[];
156
+ /**
157
+ * Paragraph node id → document position, from the TREE rather than from a layout.
158
+ *
159
+ * Memoized on the immutable root: one full derivation pass asks this question three times
160
+ * (replacement pairing, the queue's merged order, the session's cached order), and each
161
+ * answer was a fresh full-tree walk. The instance is SHARED, so the return type is
162
+ * ReadonlyMap: a caller mutating it would poison every later reader of this root.
163
+ */
164
+ declare function paragraphOrderOfPart(part: OoxmlPart): ReadonlyMap<string, number>;
165
+ /**
166
+ * Like {@link paragraphOrderOfPart}, but descends INTO paragraphs, so paragraphs nested
167
+ * in a run's content — a textbox's `w:txbxContent` — rank right after their host.
168
+ *
169
+ * A separate function on purpose: the shallow order feeds the review queue's card
170
+ * ordering, and re-ranking nested paragraphs there would move cards. This one exists for
171
+ * position containment tests ("is the caret inside this range"), where a paragraph the
172
+ * shallow order cannot see is a position that can never match.
173
+ */
174
+ declare function deepParagraphOrderOfPart(part: OoxmlPart): ReadonlyMap<string, number>;
175
+
176
+ export { type LinkableReviewItem as L, MAX_CONTENT_CONTROL_NESTING as M, commentBodyText as a, commentInitials as b, collectFlowBlocks as c, contentControlContentChildren as d, isContentControlContent as e, collectReviewItems as f, commentItemsOf as g, contentControlContentOf as h, isContentControl as i, deepParagraphOrderOfPart as j, walkParagraphInline as k, linkRevisionReplies as l, walkStoryBlocks as m, paragraphOrderOfPart as p, revisionItemsOf as r, walkAllStoryParagraphs as w };