@a3s-lab/office 0.2.2 → 0.4.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 (277) hide show
  1. package/COLLABORATION_ROADMAP.md +426 -0
  2. package/README.md +649 -10
  3. package/dist/0~1403.js +1 -1
  4. package/dist/0~2805.js +1279 -0
  5. package/dist/{0~use-office-draft.js → 0~345.js} +30 -1
  6. package/dist/0~3539.js +1 -1
  7. package/dist/0~3557.js +1 -1
  8. package/dist/0~3635.js +1 -1
  9. package/dist/0~4595.js +123 -12
  10. package/dist/0~4980.js +154 -0
  11. package/dist/0~5050.js +124 -113
  12. package/dist/{0~9512.js → 0~6090.js} +540 -3
  13. package/dist/0~7048.js +92 -66
  14. package/dist/0~7614.js +2 -1
  15. package/dist/0~7754.js +5653 -0
  16. package/dist/0~9445.js +1 -1
  17. package/dist/0~document-editor.js +4992 -3323
  18. package/dist/0~markdown-editor.js +250 -44
  19. package/dist/0~pdf-viewer.js +1016 -24
  20. package/dist/0~presentation-editor.js +179 -8
  21. package/dist/0~spreadsheet-editor.js +3371 -578
  22. package/dist/0~work-docx-export.js +6801 -658
  23. package/dist/0~work-docx-import.js +1388 -795
  24. package/dist/0~work-office-diagnostics.js +524 -30
  25. package/dist/0~work-pptx-export.js +2 -1
  26. package/dist/0~work-pptx-import.js +1 -2
  27. package/dist/0~work-presentation-charts.js +1 -1
  28. package/dist/2591.js +197 -0
  29. package/dist/3818.js +1090 -0
  30. package/dist/4104.js +970 -60
  31. package/dist/432.js +171 -14
  32. package/dist/4476.js +2008 -0
  33. package/dist/4560.js +674 -0
  34. package/dist/4650.js +70 -0
  35. package/dist/{1134.js → 5184.js} +183 -1
  36. package/dist/6489.js +18 -18
  37. package/dist/7060.js +132 -0
  38. package/dist/8715.js +2 -136
  39. package/dist/8928.js +16778 -0
  40. package/dist/9787.js +209 -0
  41. package/dist/core.d.ts +29 -9
  42. package/dist/core.js +10 -2
  43. package/dist/index.js +13 -3
  44. package/dist/internal/collaboration/office-collaboration-flat-json.d.ts +13 -0
  45. package/dist/internal/collaboration/office-collaboration-json.d.ts +4 -0
  46. package/dist/internal/collaboration/office-collaboration-presence.d.ts +86 -0
  47. package/dist/internal/collaboration/office-collaboration-transport.d.ts +42 -0
  48. package/dist/internal/collaboration/office-collaboration.d.ts +85 -0
  49. package/dist/internal/collaboration/office-document-collaboration-bibliography.d.ts +7 -0
  50. package/dist/internal/collaboration/office-document-collaboration-claims.d.ts +9 -0
  51. package/dist/internal/collaboration/office-document-collaboration-comments.d.ts +7 -0
  52. package/dist/internal/collaboration/office-document-collaboration-sidecar-utils.d.ts +27 -0
  53. package/dist/internal/collaboration/office-document-collaboration-sidecars.d.ts +16 -0
  54. package/dist/internal/collaboration/office-document-collaboration.d.ts +45 -0
  55. package/dist/internal/collaboration/office-markdown-collaboration.d.ts +31 -0
  56. package/dist/internal/collaboration/office-pdf-collaboration-claims.d.ts +4 -0
  57. package/dist/internal/collaboration/office-pdf-collaboration-conflicts.d.ts +2 -0
  58. package/dist/internal/collaboration/office-pdf-collaboration-model.d.ts +26 -0
  59. package/dist/internal/collaboration/office-pdf-collaboration-records.d.ts +21 -0
  60. package/dist/internal/collaboration/office-pdf-collaboration-types.d.ts +91 -0
  61. package/dist/internal/collaboration/office-pdf-collaboration-validation.d.ts +4 -0
  62. package/dist/internal/collaboration/office-pdf-collaboration.d.ts +35 -0
  63. package/dist/internal/collaboration/office-presentation-collaboration-model.d.ts +25 -0
  64. package/dist/internal/collaboration/office-presentation-collaboration-records.d.ts +22 -0
  65. package/dist/internal/collaboration/office-presentation-collaboration-validation.d.ts +4 -0
  66. package/dist/internal/collaboration/office-presentation-collaboration.d.ts +32 -0
  67. package/dist/internal/collaboration/office-spreadsheet-collaboration-cells.d.ts +13 -0
  68. package/dist/internal/collaboration/office-spreadsheet-collaboration-claims.d.ts +4 -0
  69. package/dist/internal/collaboration/office-spreadsheet-collaboration-conflicts.d.ts +2 -0
  70. package/dist/internal/collaboration/office-spreadsheet-collaboration-flat-json.d.ts +10 -0
  71. package/dist/internal/collaboration/office-spreadsheet-collaboration-model.d.ts +31 -0
  72. package/dist/internal/collaboration/office-spreadsheet-collaboration-records.d.ts +17 -0
  73. package/dist/internal/collaboration/office-spreadsheet-collaboration-validation.d.ts +4 -0
  74. package/dist/internal/collaboration/office-spreadsheet-collaboration.d.ts +32 -0
  75. package/dist/internal/design-system/primitives/navigation/tabs.d.ts +3 -1
  76. package/dist/internal/features/work/components/work-document-page-border.d.ts +6 -0
  77. package/dist/internal/features/work/editors/document-command-catalog.d.ts +536 -0
  78. package/dist/internal/features/work/editors/document-editor-focus.d.ts +1 -1
  79. package/dist/internal/features/work/editors/document-editor-support.d.ts +7 -3
  80. package/dist/internal/features/work/editors/document-editor.d.ts +8 -2
  81. package/dist/internal/features/work/editors/document-external-content.d.ts +14 -0
  82. package/dist/internal/features/work/editors/document-format-clipboard.d.ts +6 -0
  83. package/dist/internal/features/work/editors/document-format-tools.d.ts +4 -0
  84. package/dist/internal/features/work/editors/document-layout-panel.d.ts +4 -1
  85. package/dist/internal/features/work/editors/document-page-chrome-wps-shortcuts.d.ts +2 -0
  86. package/dist/internal/features/work/editors/document-page-layout-ribbon.d.ts +14 -0
  87. package/dist/internal/features/work/editors/document-page-stack.d.ts +10 -1
  88. package/dist/internal/features/work/editors/document-page-thumbnail.d.ts +2 -0
  89. package/dist/internal/features/work/editors/document-pagination-run-coordinator.d.ts +26 -0
  90. package/dist/internal/features/work/editors/document-picture-properties-dialog-model.d.ts +20 -1
  91. package/dist/internal/features/work/editors/document-review-navigation.d.ts +9 -0
  92. package/dist/internal/features/work/editors/document-statistics-dialog.d.ts +7 -0
  93. package/dist/internal/features/work/editors/document-status-bar.d.ts +2 -1
  94. package/dist/internal/features/work/editors/document-table-properties-dialog-model.d.ts +4 -1
  95. package/dist/internal/features/work/editors/document-toolbar.d.ts +19 -42
  96. package/dist/internal/features/work/editors/document-wps-shortcuts.d.ts +12 -0
  97. package/dist/internal/features/work/editors/document-zoom.d.ts +17 -0
  98. package/dist/internal/features/work/editors/markdown-editor-focus.d.ts +1 -1
  99. package/dist/internal/features/work/editors/markdown-editor.d.ts +5 -1
  100. package/dist/internal/features/work/editors/markdown-toolbar.d.ts +2 -1
  101. package/dist/internal/features/work/editors/office-collaboration-participants.d.ts +3 -0
  102. package/dist/internal/features/work/editors/office-collaboration-presence-context.d.ts +17 -0
  103. package/dist/internal/features/work/editors/office-collaboration-presence-ui.d.ts +25 -0
  104. package/dist/internal/features/work/editors/office-editor-focus-handoff.d.ts +27 -0
  105. package/dist/internal/features/work/editors/pdf-annotation-controller.d.ts +5 -0
  106. package/dist/internal/features/work/editors/pdf-collaboration-presence.d.ts +3 -0
  107. package/dist/internal/features/work/editors/pdf-collaboration-projection.d.ts +10 -0
  108. package/dist/internal/features/work/editors/pdf-evidence-contract.d.ts +36 -0
  109. package/dist/internal/features/work/editors/pdf-evidence-overlay.d.ts +37 -0
  110. package/dist/internal/features/work/editors/pdf-toolbar.d.ts +2 -1
  111. package/dist/internal/features/work/editors/pdf-viewer-controller.d.ts +7 -1
  112. package/dist/internal/features/work/editors/pdf-viewer.d.ts +11 -1
  113. package/dist/internal/features/work/editors/presentation-collaboration-presence.d.ts +5 -0
  114. package/dist/internal/features/work/editors/presentation-editor-focus.d.ts +3 -2
  115. package/dist/internal/features/work/editors/presentation-editor-types.d.ts +3 -0
  116. package/dist/internal/features/work/editors/presentation-editor.d.ts +1 -1
  117. package/dist/internal/features/work/editors/spreadsheet-auto-filter.d.ts +9 -0
  118. package/dist/internal/features/work/editors/spreadsheet-cell-clear.d.ts +3 -0
  119. package/dist/internal/features/work/editors/spreadsheet-cell-merge.d.ts +12 -0
  120. package/dist/internal/features/work/editors/spreadsheet-clipboard-shortcuts.d.ts +3 -7
  121. package/dist/internal/features/work/editors/spreadsheet-collaboration-presence.d.ts +9 -0
  122. package/dist/internal/features/work/editors/spreadsheet-command-catalog.d.ts +464 -0
  123. package/dist/internal/features/work/editors/spreadsheet-command-controller.d.ts +45 -9
  124. package/dist/internal/features/work/editors/spreadsheet-context-menu.d.ts +2 -0
  125. package/dist/internal/features/work/editors/spreadsheet-editor-ribbon.d.ts +9 -28
  126. package/dist/internal/features/work/editors/spreadsheet-editor.d.ts +8 -2
  127. package/dist/internal/features/work/editors/spreadsheet-format-painter.d.ts +27 -0
  128. package/dist/internal/features/work/editors/spreadsheet-freeze-panes.d.ts +14 -0
  129. package/dist/internal/features/work/editors/use-document-insert-commands.d.ts +3 -2
  130. package/dist/internal/features/work/editors/use-document-pagination.d.ts +6 -1
  131. package/dist/internal/features/work/editors/use-document-review-conflicts.d.ts +28 -0
  132. package/dist/internal/features/work/editors/use-spreadsheet-auto-filter.d.ts +21 -0
  133. package/dist/internal/features/work/editors/use-spreadsheet-collaboration.d.ts +27 -0
  134. package/dist/internal/features/work/editors/use-spreadsheet-format-painter.d.ts +18 -0
  135. package/dist/internal/features/work/editors/work-office-chrome.d.ts +22 -3
  136. package/dist/internal/features/work/editors/work-office-ribbon-overflow.d.ts +2 -0
  137. package/dist/internal/features/work/work-document-bookmark-references.d.ts +37 -0
  138. package/dist/internal/features/work/work-document-bookmarks.d.ts +29 -0
  139. package/dist/internal/features/work/work-document-caption-nodes.d.ts +4 -1
  140. package/dist/internal/features/work/work-document-comments.d.ts +1 -1
  141. package/dist/internal/features/work/work-document-equations.d.ts +513 -0
  142. package/dist/internal/features/work/work-document-extensions.d.ts +1 -0
  143. package/dist/internal/features/work/work-document-field-identity.d.ts +2 -0
  144. package/dist/internal/features/work/work-document-field-node.d.ts +2 -2
  145. package/dist/internal/features/work/work-document-fields.d.ts +7 -0
  146. package/dist/internal/features/work/work-document-image-identity.d.ts +30 -0
  147. package/dist/internal/features/work/work-document-image-layout.d.ts +46 -1
  148. package/dist/internal/features/work/work-document-image-wrap-contour.d.ts +16 -0
  149. package/dist/internal/features/work/work-document-incremental-layout.d.ts +2 -2
  150. package/dist/internal/features/work/work-document-model-codec.d.ts +4 -1
  151. package/dist/internal/features/work/work-document-note-integrity.d.ts +2 -0
  152. package/dist/internal/features/work/work-document-page-borders.d.ts +25 -0
  153. package/dist/internal/features/work/work-document-page-capture.d.ts +8 -0
  154. package/dist/internal/features/work/work-document-page-frames.d.ts +15 -0
  155. package/dist/internal/features/work/work-document-page-margins.d.ts +56 -0
  156. package/dist/internal/features/work/work-document-page-size.d.ts +47 -0
  157. package/dist/internal/features/work/work-document-pagination-measurement.d.ts +1 -2
  158. package/dist/internal/features/work/work-document-pagination-types.d.ts +7 -2
  159. package/dist/internal/features/work/work-document-pagination.d.ts +2 -2
  160. package/dist/internal/features/work/work-document-paragraph-borders.d.ts +32 -0
  161. package/dist/internal/features/work/work-document-paragraph-identity.d.ts +26 -0
  162. package/dist/internal/features/work/work-document-paragraph-shading.d.ts +18 -0
  163. package/dist/internal/features/work/work-document-review-conflicts.d.ts +35 -0
  164. package/dist/internal/features/work/work-document-section.d.ts +4 -0
  165. package/dist/internal/features/work/work-document-snapshot.d.ts +19 -0
  166. package/dist/internal/features/work/work-document-source.d.ts +23 -0
  167. package/dist/internal/features/work/work-document-table-column-widths.d.ts +7 -0
  168. package/dist/internal/features/work/work-document-table-property-changes.d.ts +3 -0
  169. package/dist/internal/features/work/work-document-table-row-identity.d.ts +15 -0
  170. package/dist/internal/features/work/work-document-table-sizing.d.ts +3 -0
  171. package/dist/internal/features/work/work-document-text-layout.d.ts +3 -1
  172. package/dist/internal/features/work/work-document-word-line-metrics.d.ts +2 -0
  173. package/dist/internal/features/work/work-docx-bookmark-diagnostics.d.ts +3 -0
  174. package/dist/internal/features/work/work-docx-bookmark-import.d.ts +24 -0
  175. package/dist/internal/features/work/work-docx-bookmarks.d.ts +17 -0
  176. package/dist/internal/features/work/work-docx-comment-durable-id-preservation.d.ts +2 -0
  177. package/dist/internal/features/work/work-docx-comment-export.d.ts +3 -0
  178. package/dist/internal/features/work/work-docx-comment-metadata.d.ts +2 -0
  179. package/dist/internal/features/work/work-docx-drawing-extension-preservation.d.ts +4 -0
  180. package/dist/internal/features/work/work-docx-equation-diagnostics.d.ts +3 -0
  181. package/dist/internal/features/work/work-docx-equation-export.d.ts +14 -0
  182. package/dist/internal/features/work/work-docx-equation-import.d.ts +30 -0
  183. package/dist/internal/features/work/work-docx-equation-story.d.ts +9 -0
  184. package/dist/internal/features/work/work-docx-export-formatting.d.ts +3 -1
  185. package/dist/internal/features/work/work-docx-export-image.d.ts +5 -1
  186. package/dist/internal/features/work/work-docx-export.d.ts +1 -1
  187. package/dist/internal/features/work/work-docx-field-instructions.d.ts +8 -0
  188. package/dist/internal/features/work/work-docx-font-table-preservation.d.ts +3 -0
  189. package/dist/internal/features/work/work-docx-ignorable-extension-preservation.d.ts +15 -0
  190. package/dist/internal/features/work/work-docx-image-crop.d.ts +12 -0
  191. package/dist/internal/features/work/work-docx-image-identity.d.ts +17 -0
  192. package/dist/internal/features/work/work-docx-image-layer.d.ts +12 -0
  193. package/dist/internal/features/work/work-docx-image-layout-import.d.ts +14 -2
  194. package/dist/internal/features/work/work-docx-image-wrap.d.ts +15 -0
  195. package/dist/internal/features/work/work-docx-import.d.ts +13 -3
  196. package/dist/internal/features/work/work-docx-list-export.d.ts +18 -0
  197. package/dist/internal/features/work/work-docx-list-import.d.ts +14 -0
  198. package/dist/internal/features/work/work-docx-note-comment-content-control-block-preservation.d.ts +18 -0
  199. package/dist/internal/features/work/work-docx-note-comment-content-control-model.d.ts +47 -0
  200. package/dist/internal/features/work/work-docx-note-comment-content-control-preservation.d.ts +4 -0
  201. package/dist/internal/features/work/work-docx-note-comment-content-control-properties.d.ts +17 -0
  202. package/dist/internal/features/work/work-docx-note-comment-content-control-table-model.d.ts +17 -0
  203. package/dist/internal/features/work/work-docx-note-comment-content-control-xml.d.ts +14 -0
  204. package/dist/internal/features/work/work-docx-note-comment-extension-preservation.d.ts +2 -0
  205. package/dist/internal/features/work/work-docx-note-comment-hyperlink-content.d.ts +40 -0
  206. package/dist/internal/features/work/work-docx-note-comment-hyperlink-preservation.d.ts +5 -0
  207. package/dist/internal/features/work/work-docx-note-comment-hyperlink-relationships.d.ts +35 -0
  208. package/dist/internal/features/work/work-docx-note-comment-identity.d.ts +15 -0
  209. package/dist/internal/features/work/work-docx-note-comment-run-preservation.d.ts +4 -0
  210. package/dist/internal/features/work/work-docx-note-comment-run-properties.d.ts +2 -0
  211. package/dist/internal/features/work/work-docx-note-image-import.d.ts +12 -0
  212. package/dist/internal/features/work/work-docx-note-image-relationships.d.ts +1 -0
  213. package/dist/internal/features/work/work-docx-numbering-extension-preservation.d.ts +6 -0
  214. package/dist/internal/features/work/work-docx-numbering.d.ts +1 -0
  215. package/dist/internal/features/work/work-docx-page-borders-diagnostics.d.ts +3 -0
  216. package/dist/internal/features/work/work-docx-page-borders-import.d.ts +10 -0
  217. package/dist/internal/features/work/work-docx-page-margins-diagnostics.d.ts +3 -0
  218. package/dist/internal/features/work/work-docx-page-margins-import.d.ts +18 -0
  219. package/dist/internal/features/work/work-docx-page-size-diagnostics.d.ts +2 -0
  220. package/dist/internal/features/work/work-docx-page-size-import.d.ts +17 -0
  221. package/dist/internal/features/work/work-docx-paragraph-borders-diagnostics.d.ts +3 -0
  222. package/dist/internal/features/work/work-docx-paragraph-borders-export.d.ts +18 -0
  223. package/dist/internal/features/work/work-docx-paragraph-borders-import.d.ts +24 -0
  224. package/dist/internal/features/work/work-docx-paragraph-default-collapsed.d.ts +19 -0
  225. package/dist/internal/features/work/work-docx-paragraph-extension-preservation.d.ts +2 -0
  226. package/dist/internal/features/work/work-docx-paragraph-identity-import.d.ts +10 -0
  227. package/dist/internal/features/work/work-docx-paragraph-identity.d.ts +18 -0
  228. package/dist/internal/features/work/work-docx-paragraph-pagination-import.d.ts +6 -1
  229. package/dist/internal/features/work/work-docx-paragraph-shading-diagnostics.d.ts +3 -0
  230. package/dist/internal/features/work/work-docx-paragraph-shading-export.d.ts +5 -0
  231. package/dist/internal/features/work/work-docx-paragraph-shading-import.d.ts +18 -0
  232. package/dist/internal/features/work/work-docx-run-formatting-import.d.ts +3 -0
  233. package/dist/internal/features/work/work-docx-settings-preservation.d.ts +10 -0
  234. package/dist/internal/features/work/work-docx-settings-xml.d.ts +16 -0
  235. package/dist/internal/features/work/work-docx-style-extension-preservation.d.ts +2 -0
  236. package/dist/internal/features/work/work-docx-table-cell-export.d.ts +2 -1
  237. package/dist/internal/features/work/work-docx-table-cell-import.d.ts +3 -0
  238. package/dist/internal/features/work/work-docx-table-extension-preservation.d.ts +2 -0
  239. package/dist/internal/features/work/work-docx-table-row-import.d.ts +2 -0
  240. package/dist/internal/features/work/work-docx-table-sizing-import.d.ts +1 -0
  241. package/dist/internal/features/work/work-docx-theme-reference.d.ts +23 -0
  242. package/dist/internal/features/work/work-docx-theme.d.ts +4 -1
  243. package/dist/internal/features/work/work-docx-twips.d.ts +12 -0
  244. package/dist/internal/features/work/work-file-contract.d.ts +1 -0
  245. package/dist/internal/features/work/work-file-io.d.ts +1 -1
  246. package/dist/internal/features/work/work-markdown-extensions.d.ts +4 -1
  247. package/dist/internal/features/work/work-ooxml-package-preservation.d.ts +12 -0
  248. package/dist/internal/features/work/work-ooxml-package-security.d.ts +6 -0
  249. package/dist/internal/features/work/work-ooxml-relationship-preservation.d.ts +10 -0
  250. package/dist/internal/features/work/work-ooxml-xml.d.ts +2 -0
  251. package/dist/internal/features/work/work-pdf-export.d.ts +10 -0
  252. package/dist/internal/features/work/work-repository.d.ts +2 -0
  253. package/dist/internal/features/work/work-types.d.ts +15 -2
  254. package/dist/internal/kernel/office-kernel-client-types.d.ts +1 -0
  255. package/dist/internal/kernel/office-kernel-protocol.d.ts +7 -0
  256. package/dist/internal/kernel/office-kernel-version.d.ts +1 -1
  257. package/dist/office-kernel.wasm +0 -0
  258. package/dist/office-kernel.worker.js +93 -41
  259. package/dist/react.d.ts +18 -12
  260. package/dist/react.js +1 -1
  261. package/dist/styles.css +1367 -16
  262. package/dist/vue.d.ts +48 -5
  263. package/dist/vue.js +42 -3
  264. package/dist/web-component.d.ts +24 -2
  265. package/dist/web-component.js +101 -2
  266. package/docs/latest/en/browser-editor-architecture.md +262 -47
  267. package/package.json +29 -4
  268. package/dist/0~152.js +0 -94
  269. package/dist/0~2582.js +0 -485
  270. package/dist/0~4750.js +0 -939
  271. package/dist/0~5861.js +0 -596
  272. package/dist/0~work-document-extensions.js +0 -3045
  273. package/dist/0~work-document-model-codec.js +0 -42
  274. package/dist/0~work-docx-bibliography.js +0 -347
  275. package/dist/0~work-docx-page-color.js +0 -42
  276. package/dist/2881.js +0 -1455
  277. package/dist/8728.js +0 -723
package/dist/3818.js ADDED
@@ -0,0 +1,1090 @@
1
+ import { initializeWorkOfficeCollaborationMetadata, assertWorkOfficeCollaborationEditable, OfficeCollaborationError as WorkOfficeCollaborationError, readOfficeCollaborationMetadata as readWorkOfficeCollaborationMetadata, registerWorkOfficeCollaborationInitializer, markWorkOfficeCollaborationInitialized, assertWorkOfficeCollaborationOrigin } from "./9787.js";
2
+ import { workOfficeCollaborationJsonEqual, canonicalWorkOfficeCollaborationJson, isWorkOfficeCollaborationRecord, cloneWorkOfficeCollaborationJson } from "./4650.js";
3
+ import { patchWorkOfficeCollaborationFlatJsonMap, readWorkOfficeCollaborationFlatJsonMap } from "./7060.js";
4
+ import * as __rspack_external_yjs from "yjs";
5
+ const MAX_PDF_BYTES = 4294967296;
6
+ const MAX_PDF_PAGES = 1000000;
7
+ const MAX_PDF_RECORDS = 1000000;
8
+ function validateWorkOfficePdfCollaborationContent(content) {
9
+ const record = requiredRecord(content, 'content');
10
+ assertExactKeys(record, [
11
+ 'annotations',
12
+ 'formValues',
13
+ 'pageOperations',
14
+ 'redactionProposals',
15
+ 'reviewDecisions',
16
+ 'signaturePlacements',
17
+ 'source',
18
+ 'type'
19
+ ], 'content');
20
+ if ('pdf' !== record.type) invalid("a PDF content type of 'pdf'");
21
+ const source = validateSource(record.source);
22
+ const result = {
23
+ type: 'pdf',
24
+ source,
25
+ annotations: validateRecords(record.annotations, 'annotation', (value)=>validateAnnotation(value, source)),
26
+ formValues: validateRecords(record.formValues, 'form value', validateFormValue),
27
+ signaturePlacements: validateRecords(record.signaturePlacements, 'signature placement', (value)=>validateSignaturePlacement(value, source)),
28
+ redactionProposals: validateRecords(record.redactionProposals, 'redaction proposal', (value)=>validateRedactionProposal(value, source)),
29
+ pageOperations: validateRecords(record.pageOperations, 'page operation', (value)=>validatePageOperation(value, source)),
30
+ reviewDecisions: validateRecords(record.reviewDecisions, 'review decision', validateReviewDecision)
31
+ };
32
+ assertReferences(result);
33
+ return result;
34
+ }
35
+ function validateSharedWorkOfficePdfCollaborationContent(content) {
36
+ try {
37
+ return validateWorkOfficePdfCollaborationContent(content);
38
+ } catch (error) {
39
+ if (error instanceof WorkOfficeCollaborationError) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `The shared PDF collaboration content is invalid: ${error.message}`);
40
+ throw error;
41
+ }
42
+ }
43
+ function invalidWorkOfficePdfShared(label) {
44
+ throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `The shared PDF collaboration ${label} is invalid.`);
45
+ }
46
+ function validateSource(value) {
47
+ const source = requiredRecord(value, 'source');
48
+ assertExactKeys(source, [
49
+ 'byteLength',
50
+ 'pageCount',
51
+ 'sha256'
52
+ ], 'source');
53
+ const sha256 = requiredString(source.sha256, 'source SHA-256');
54
+ if (!/^[0-9a-f]{64}$/.test(sha256)) invalid('a lowercase SHA-256 source');
55
+ return {
56
+ sha256,
57
+ byteLength: requiredInteger(source.byteLength, 1, MAX_PDF_BYTES, 'source byte length'),
58
+ pageCount: requiredInteger(source.pageCount, 1, MAX_PDF_PAGES, 'source page count')
59
+ };
60
+ }
61
+ function validateAnnotation(value, source) {
62
+ const record = requiredRecord(value, 'annotation');
63
+ assertAllowedKeys(record, [
64
+ 'annotation',
65
+ 'deleted',
66
+ 'id',
67
+ 'pageIndex',
68
+ 'source'
69
+ ], 'annotation');
70
+ const id = requiredIdentifier(record.id, 'annotation');
71
+ const pageIndex = requiredPageIndex(record.pageIndex, source, 'annotation');
72
+ if ('base' !== record.source && 'created' !== record.source) invalid("an annotation source of 'base' or 'created'");
73
+ const annotation = validateJsonRecord(record.annotation, 'annotation value');
74
+ if (annotation.id !== id || annotation.pageIndex !== pageIndex) invalid('annotation value identity matching its record');
75
+ const result = {
76
+ id,
77
+ pageIndex,
78
+ source: record.source,
79
+ annotation
80
+ };
81
+ if (void 0 !== record.deleted) {
82
+ if (true !== record.deleted) invalid('an annotation tombstone of true');
83
+ result.deleted = true;
84
+ }
85
+ return result;
86
+ }
87
+ function validateFormValue(value) {
88
+ const record = requiredRecord(value, 'form value');
89
+ assertExactKeys(record, [
90
+ 'id',
91
+ 'value'
92
+ ], 'form value');
93
+ return {
94
+ id: requiredIdentifier(record.id, 'form field'),
95
+ value: requiredString(record.value, 'form field value')
96
+ };
97
+ }
98
+ function validateSignaturePlacement(value, source) {
99
+ const record = requiredRecord(value, 'signature placement');
100
+ assertExactKeys(record, [
101
+ 'actorId',
102
+ 'annotationId',
103
+ 'appearance',
104
+ 'createdAt',
105
+ 'id',
106
+ 'kind',
107
+ 'pageIndex'
108
+ ], 'signature placement');
109
+ if ('signature' !== record.kind && 'initials' !== record.kind) invalid("a signature placement kind of 'signature' or 'initials'");
110
+ const appearance = requiredRecord(record.appearance, 'signature appearance');
111
+ assertExactKeys(appearance, [
112
+ 'assetId',
113
+ 'byteLength',
114
+ 'mimeType',
115
+ 'sha256'
116
+ ], 'signature appearance');
117
+ const sha256 = requiredString(appearance.sha256, 'signature SHA-256');
118
+ if (!/^[0-9a-f]{64}$/.test(sha256)) invalid('a lowercase SHA-256 signature appearance');
119
+ return {
120
+ id: requiredIdentifier(record.id, 'signature placement'),
121
+ annotationId: requiredIdentifier(record.annotationId, 'signature annotation'),
122
+ pageIndex: requiredPageIndex(record.pageIndex, source, 'signature placement'),
123
+ kind: record.kind,
124
+ actorId: requiredIdentifier(record.actorId, 'signature actor'),
125
+ createdAt: requiredTimestamp(record.createdAt, 'signature creation'),
126
+ appearance: {
127
+ assetId: requiredIdentifier(appearance.assetId, 'signature asset'),
128
+ sha256,
129
+ byteLength: requiredInteger(appearance.byteLength, 1, MAX_PDF_BYTES, 'signature byte length'),
130
+ mimeType: requiredString(appearance.mimeType, 'signature MIME type')
131
+ }
132
+ };
133
+ }
134
+ function validateRedactionProposal(value, source) {
135
+ const record = requiredRecord(value, 'redaction proposal');
136
+ assertAllowedKeys(record, [
137
+ 'id',
138
+ 'pageIndex',
139
+ 'proposedAt',
140
+ 'proposedBy',
141
+ 'reason',
142
+ 'rects',
143
+ 'text'
144
+ ], 'redaction proposal');
145
+ const rects = requiredArray(record.rects, 'redaction rectangles');
146
+ if (0 === rects.length || rects.length > 10000) invalid('between 1 and 10,000 redaction rectangles');
147
+ const result = {
148
+ id: requiredIdentifier(record.id, 'redaction proposal'),
149
+ pageIndex: requiredPageIndex(record.pageIndex, source, 'redaction'),
150
+ rects: rects.map((rect)=>{
151
+ const item = requiredRecord(rect, 'redaction rectangle');
152
+ assertExactKeys(item, [
153
+ 'bottom',
154
+ 'left',
155
+ 'right',
156
+ 'top'
157
+ ], 'redaction rectangle');
158
+ const value = {
159
+ left: requiredFiniteNumber(item.left, 'redaction left'),
160
+ top: requiredFiniteNumber(item.top, 'redaction top'),
161
+ right: requiredFiniteNumber(item.right, 'redaction right'),
162
+ bottom: requiredFiniteNumber(item.bottom, 'redaction bottom')
163
+ };
164
+ if (value.right <= value.left || value.bottom <= value.top) invalid('a positive redaction rectangle');
165
+ return value;
166
+ }),
167
+ proposedBy: requiredIdentifier(record.proposedBy, 'redaction proposer'),
168
+ proposedAt: requiredTimestamp(record.proposedAt, 'redaction proposal')
169
+ };
170
+ if (void 0 !== record.reason) result.reason = requiredString(record.reason, 'redaction reason');
171
+ if (void 0 !== record.text) result.text = requiredString(record.text, 'redaction text');
172
+ return result;
173
+ }
174
+ function validatePageOperation(value, source) {
175
+ const record = requiredRecord(value, 'page operation');
176
+ const base = {
177
+ id: requiredIdentifier(record.id, 'page operation'),
178
+ proposedBy: requiredIdentifier(record.proposedBy, 'page operation proposer'),
179
+ proposedAt: requiredTimestamp(record.proposedAt, 'page operation proposal')
180
+ };
181
+ if ('rotate' === record.kind) {
182
+ assertExactKeys(record, [
183
+ 'degrees',
184
+ 'id',
185
+ 'kind',
186
+ 'pageIndices',
187
+ 'proposedAt',
188
+ 'proposedBy'
189
+ ], 'rotate page operation');
190
+ if (90 !== record.degrees && 180 !== record.degrees && 270 !== record.degrees) invalid('a page rotation of 90, 180, or 270 degrees');
191
+ return {
192
+ ...base,
193
+ kind: 'rotate',
194
+ pageIndices: requiredPageIndices(record.pageIndices, source, false),
195
+ degrees: record.degrees
196
+ };
197
+ }
198
+ if ('delete' === record.kind) {
199
+ assertExactKeys(record, [
200
+ 'id',
201
+ 'kind',
202
+ 'pageIndices',
203
+ 'proposedAt',
204
+ 'proposedBy'
205
+ ], 'delete page operation');
206
+ const pageIndices = requiredPageIndices(record.pageIndices, source, false);
207
+ if (pageIndices.length >= source.pageCount) invalid('a page deletion that retains at least one source page');
208
+ return {
209
+ ...base,
210
+ kind: 'delete',
211
+ pageIndices
212
+ };
213
+ }
214
+ if ('reorder' === record.kind) {
215
+ assertExactKeys(record, [
216
+ 'id',
217
+ 'kind',
218
+ 'pageOrder',
219
+ 'proposedAt',
220
+ 'proposedBy'
221
+ ], 'reorder page operation');
222
+ const pageOrder = requiredPageIndices(record.pageOrder, source, true);
223
+ return {
224
+ ...base,
225
+ kind: 'reorder',
226
+ pageOrder
227
+ };
228
+ }
229
+ invalid('a supported PDF page operation kind');
230
+ }
231
+ function validateReviewDecision(value) {
232
+ const record = requiredRecord(value, 'review decision');
233
+ assertExactKeys(record, [
234
+ 'actorId',
235
+ 'createdAt',
236
+ 'decision',
237
+ 'id',
238
+ 'targetId',
239
+ 'targetKind'
240
+ ], 'review decision');
241
+ if ('redaction' !== record.targetKind && 'page-operation' !== record.targetKind) invalid('a supported review target kind');
242
+ if ('approve' !== record.decision && 'reject' !== record.decision) invalid("a review decision of 'approve' or 'reject'");
243
+ return {
244
+ id: requiredIdentifier(record.id, 'review decision'),
245
+ targetKind: record.targetKind,
246
+ targetId: requiredIdentifier(record.targetId, 'review target'),
247
+ decision: record.decision,
248
+ actorId: requiredIdentifier(record.actorId, 'review actor'),
249
+ createdAt: requiredTimestamp(record.createdAt, 'review decision')
250
+ };
251
+ }
252
+ function assertReferences(content) {
253
+ const annotations = new Map(content.annotations.map((value)=>[
254
+ value.id,
255
+ value
256
+ ]));
257
+ for (const placement of content.signaturePlacements){
258
+ const annotation = annotations.get(placement.annotationId);
259
+ if (!annotation || annotation.deleted || 'created' !== annotation.source || annotation.pageIndex !== placement.pageIndex) invalid(`signature placement '${placement.id}' to reference a live created annotation on the same page`);
260
+ }
261
+ const redactions = new Set(content.redactionProposals.map(({ id })=>id));
262
+ const pageOperations = new Set(content.pageOperations.map(({ id })=>id));
263
+ const decidedTargets = new Set();
264
+ for (const decision of content.reviewDecisions){
265
+ const targets = 'redaction' === decision.targetKind ? redactions : pageOperations;
266
+ if (!targets.has(decision.targetId)) invalid(`review decision '${decision.id}' to reference an existing ${decision.targetKind}`);
267
+ const target = `${decision.targetKind}:${decision.targetId}`;
268
+ if (decidedTargets.has(target)) invalid(`at most one final review decision for '${target}'`);
269
+ decidedTargets.add(target);
270
+ }
271
+ }
272
+ function validateRecords(value, label, validate) {
273
+ const records = requiredArray(value, `${label}s`);
274
+ if (records.length > MAX_PDF_RECORDS) invalid(`at most ${MAX_PDF_RECORDS} ${label}s`);
275
+ const ids = new Set();
276
+ return records.map((item)=>{
277
+ const record = validate(item);
278
+ if (ids.has(record.id)) invalid(`a unique ${label} ID; '${record.id}' is repeated`);
279
+ ids.add(record.id);
280
+ return record;
281
+ });
282
+ }
283
+ function requiredPageIndices(value, source, complete) {
284
+ const pages = requiredArray(value, complete ? 'page order' : 'page indices');
285
+ if (complete && pages.length !== source.pageCount || !complete && 0 === pages.length) invalid(complete ? 'a complete source-page permutation' : 'at least one page index');
286
+ const result = pages.map((page)=>requiredPageIndex(page, source, 'page operation'));
287
+ if (new Set(result).size !== result.length) invalid('unique page indices');
288
+ return result;
289
+ }
290
+ function validateJsonRecord(value, label) {
291
+ const record = requiredRecord(value, label);
292
+ try {
293
+ return clonePdfJsonValue(record);
294
+ } catch (error) {
295
+ throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `PDF collaboration requires a JSON-compatible ${label}: ${error instanceof Error ? error.message : String(error)}`);
296
+ }
297
+ }
298
+ function clonePdfJsonValue(value, seen = new WeakSet()) {
299
+ if (value instanceof Date) {
300
+ if (!Number.isFinite(value.getTime())) invalid('valid annotation dates');
301
+ return value.toISOString();
302
+ }
303
+ if (Array.isArray(value)) {
304
+ if (seen.has(value)) invalid('acyclic annotation values');
305
+ seen.add(value);
306
+ const result = value.map((item)=>clonePdfJsonValue(item, seen));
307
+ seen.delete(value);
308
+ return result;
309
+ }
310
+ if (!isWorkOfficeCollaborationRecord(value)) return cloneWorkOfficeCollaborationJson(value);
311
+ if (seen.has(value)) invalid('acyclic annotation values');
312
+ seen.add(value);
313
+ const result = {};
314
+ for (const [key, item] of Object.entries(value))if (void 0 !== item) Object.defineProperty(result, key, {
315
+ configurable: true,
316
+ enumerable: true,
317
+ value: clonePdfJsonValue(item, seen),
318
+ writable: true
319
+ });
320
+ seen.delete(value);
321
+ return result;
322
+ }
323
+ function requiredPageIndex(value, source, label) {
324
+ return requiredInteger(value, 0, source.pageCount - 1, `${label} page index`);
325
+ }
326
+ function requiredTimestamp(value, label) {
327
+ const timestamp = requiredString(value, `${label} timestamp`);
328
+ if (!Number.isFinite(Date.parse(timestamp))) invalid(`an ISO-compatible ${label} timestamp`);
329
+ return timestamp;
330
+ }
331
+ function requiredIdentifier(value, label) {
332
+ const result = requiredString(value, `${label} ID`);
333
+ if (!result || result !== result.trim() || result.length > 512) invalid(`a ${label} ID containing 1 to 512 characters`);
334
+ return result;
335
+ }
336
+ function requiredString(value, label) {
337
+ if ('string' != typeof value) invalid(`a string ${label}`);
338
+ return value;
339
+ }
340
+ function requiredFiniteNumber(value, label) {
341
+ if ('number' != typeof value || !Number.isFinite(value)) invalid(`a finite number for ${label}`);
342
+ return value;
343
+ }
344
+ function requiredInteger(value, minimum, maximum, label) {
345
+ if (!Number.isSafeInteger(value) || value < minimum || value > maximum) invalid(`an integer ${label} between ${minimum} and ${maximum}`);
346
+ return value;
347
+ }
348
+ function requiredRecord(value, label) {
349
+ if (!isWorkOfficeCollaborationRecord(value)) invalid(`a valid ${label} record`);
350
+ return value;
351
+ }
352
+ function requiredArray(value, label) {
353
+ if (!Array.isArray(value)) invalid(`an array of ${label}`);
354
+ return value;
355
+ }
356
+ function assertExactKeys(record, keys, label) {
357
+ assertAllowedKeys(record, keys, label);
358
+ if (keys.some((key)=>!Object.hasOwn(record, key))) invalid(`a complete ${label} record`);
359
+ }
360
+ function assertAllowedKeys(record, keys, label) {
361
+ const allowed = new Set(keys);
362
+ if (Object.keys(record).some((key)=>!allowed.has(key))) invalid(`a ${label} record without unknown fields`);
363
+ }
364
+ function invalid(expected) {
365
+ throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `PDF collaboration requires ${expected}.`);
366
+ }
367
+ function appendWorkOfficePdfRecordClaims(claims, previous, next) {
368
+ appendClaims(claims, 'annotation', previous?.annotations ?? [], next.annotations, annotationFingerprint);
369
+ appendClaims(claims, 'signature-placement', previous?.signaturePlacements ?? [], next.signaturePlacements);
370
+ appendClaims(claims, 'redaction', previous?.redactionProposals ?? [], next.redactionProposals);
371
+ appendClaims(claims, 'page-operation', previous?.pageOperations ?? [], next.pageOperations);
372
+ appendClaims(claims, 'review-decision', previous?.reviewDecisions ?? [], next.reviewDecisions);
373
+ }
374
+ function assertWorkOfficePdfRecordClaims(claims, content) {
375
+ const fingerprints = new Map();
376
+ for (const raw of claims.toArray()){
377
+ const claim = parsedClaim(raw);
378
+ const identity = claimIdentity(claim.kind, claim.id);
379
+ const existing = fingerprints.get(identity);
380
+ if (void 0 !== existing && existing !== claim.fingerprint) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `The PDF ${claim.kind} ID '${claim.id}' was concurrently assigned to different records.`);
381
+ fingerprints.set(identity, claim.fingerprint);
382
+ }
383
+ assertClaims(fingerprints, 'annotation', content.annotations);
384
+ assertAnnotationClaimIdentities(fingerprints, content.annotations);
385
+ assertClaims(fingerprints, 'signature-placement', content.signaturePlacements);
386
+ assertClaims(fingerprints, 'redaction', content.redactionProposals);
387
+ assertClaims(fingerprints, 'page-operation', content.pageOperations);
388
+ assertClaims(fingerprints, 'review-decision', content.reviewDecisions);
389
+ }
390
+ function assertAnnotationClaimIdentities(claims, annotations) {
391
+ for (const annotation of annotations){
392
+ const fingerprint = claims.get(claimIdentity('annotation', annotation.id));
393
+ if (void 0 === fingerprint) continue;
394
+ let claimed;
395
+ try {
396
+ claimed = JSON.parse(fingerprint);
397
+ } catch {
398
+ invalidWorkOfficePdfShared('annotation record claim');
399
+ }
400
+ if (!isWorkOfficeCollaborationRecord(claimed) || claimed.id !== annotation.id || claimed.pageIndex !== annotation.pageIndex || claimed.source !== annotation.source) invalidWorkOfficePdfShared('annotation immutable identity claim');
401
+ const claimedAnnotation = isWorkOfficeCollaborationRecord(claimed.annotation) ? claimed.annotation : void 0;
402
+ const claimedType = claimed.type ?? claimedAnnotation?.type;
403
+ if ('created' === annotation.source && void 0 === claimedType || void 0 !== claimedType && claimedType !== annotation.annotation.type) invalidWorkOfficePdfShared('annotation immutable identity claim');
404
+ }
405
+ }
406
+ function appendClaims(claims, kind, previous, next, fingerprint = (value)=>value) {
407
+ const previousIds = new Set(previous.map(({ id })=>id));
408
+ for (const value of next){
409
+ if (previousIds.has(value.id)) continue;
410
+ const serialized = canonicalWorkOfficeCollaborationJson({
411
+ fingerprint: canonicalWorkOfficeCollaborationJson(fingerprint(value)),
412
+ id: value.id,
413
+ kind
414
+ });
415
+ if (!claims.toArray().includes(serialized)) claims.push([
416
+ serialized
417
+ ]);
418
+ }
419
+ }
420
+ function annotationFingerprint(value) {
421
+ return 'base' === value.source ? {
422
+ id: value.id,
423
+ pageIndex: value.pageIndex,
424
+ source: value.source,
425
+ type: value.annotation.type
426
+ } : value;
427
+ }
428
+ function assertClaims(claims, kind, values) {
429
+ for (const { id } of values)if (!claims.has(claimIdentity(kind, id))) invalidWorkOfficePdfShared(`${kind} record claim`);
430
+ }
431
+ function parsedClaim(raw) {
432
+ if ('string' != typeof raw) invalidWorkOfficePdfShared('record claim');
433
+ let value;
434
+ try {
435
+ value = JSON.parse(raw);
436
+ } catch {
437
+ invalidWorkOfficePdfShared('record claim');
438
+ }
439
+ if (!isWorkOfficeCollaborationRecord(value) || canonicalWorkOfficeCollaborationJson(value) !== raw) invalidWorkOfficePdfShared('record claim');
440
+ if (Object.keys(value).some((key)=>'fingerprint' !== key && 'id' !== key && 'kind' !== key)) invalidWorkOfficePdfShared('record claim');
441
+ const kind = requiredClaimKind(value.kind);
442
+ const id = requiredClaimString(value.id, 'record claim ID');
443
+ const fingerprint = requiredClaimString(value.fingerprint, 'record claim fingerprint');
444
+ if (!id.trim() || id.length > 512) invalidWorkOfficePdfShared('record claim ID');
445
+ try {
446
+ if (canonicalWorkOfficeCollaborationJson(JSON.parse(fingerprint)) !== fingerprint) invalidWorkOfficePdfShared('record claim fingerprint');
447
+ } catch {
448
+ invalidWorkOfficePdfShared('record claim fingerprint');
449
+ }
450
+ return {
451
+ fingerprint,
452
+ id,
453
+ kind
454
+ };
455
+ }
456
+ function requiredClaimKind(value) {
457
+ if ('annotation' === value || 'page-operation' === value || 'redaction' === value || 'review-decision' === value || 'signature-placement' === value) return value;
458
+ invalidWorkOfficePdfShared('record claim kind');
459
+ }
460
+ function requiredClaimString(value, label) {
461
+ if ('string' != typeof value) invalidWorkOfficePdfShared(label);
462
+ return value;
463
+ }
464
+ function claimIdentity(kind, id) {
465
+ return canonicalWorkOfficeCollaborationJson([
466
+ kind,
467
+ id
468
+ ]);
469
+ }
470
+ function assertWorkOfficePdfPatchSafe(previous, next, shared) {
471
+ if (!workOfficeCollaborationJsonEqual(previous.source, next.source)) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', 'The immutable PDF source identity cannot be changed by a collaboration update.');
472
+ if (!workOfficeCollaborationJsonEqual(previous.source, shared.source)) conflict('immutable PDF source identity');
473
+ assertAnnotationCollection(previous.annotations, next.annotations, shared.annotations);
474
+ assertMutableRecordCollection(previous.formValues, next.formValues, shared.formValues, 'PDF form value');
475
+ assertAppendOnlyCollection(previous.signaturePlacements, next.signaturePlacements, shared.signaturePlacements, 'PDF signature placement');
476
+ assertAppendOnlyCollection(previous.redactionProposals, next.redactionProposals, shared.redactionProposals, 'PDF redaction proposal');
477
+ assertAppendOnlyCollection(previous.pageOperations, next.pageOperations, shared.pageOperations, 'PDF page operation');
478
+ assertAppendOnlyCollection(previous.reviewDecisions, next.reviewDecisions, shared.reviewDecisions, 'PDF review decision');
479
+ }
480
+ function assertAnnotationCollection(previous, next, shared) {
481
+ const nextById = new Map(next.map((value)=>[
482
+ value.id,
483
+ value
484
+ ]));
485
+ const sharedById = new Map(shared.map((value)=>[
486
+ value.id,
487
+ value
488
+ ]));
489
+ const previousIds = new Set(previous.map(({ id })=>id));
490
+ for (const before of previous){
491
+ const after = nextById.get(before.id);
492
+ const current = sharedById.get(before.id);
493
+ if (!after) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `PDF annotation '${before.id}' must be retained with deleted: true instead of removing its durable record.`);
494
+ if (after.source !== before.source) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `PDF annotation '${before.id}' cannot change its source identity.`);
495
+ if (after.pageIndex !== before.pageIndex) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `PDF annotation '${before.id}' cannot change its page identity.`);
496
+ if (after.annotation.type !== before.annotation.type) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `PDF annotation '${before.id}' cannot change its type identity.`);
497
+ if (before.deleted && !after.deleted) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `PDF annotation '${before.id}' has a durable deletion tombstone that cannot be cleared.`);
498
+ if (!workOfficeCollaborationJsonEqual(before, after)) {
499
+ if (!current) removedConflict(`PDF annotation '${before.id}'`);
500
+ if (current.source !== before.source) conflict(`PDF annotation '${before.id}' source`);
501
+ if (current.pageIndex !== before.pageIndex) conflict(`PDF annotation '${before.id}' page identity`);
502
+ if (current.annotation.type !== before.annotation.type) conflict(`PDF annotation '${before.id}' type identity`);
503
+ assertCompatibleValue(before, after, current, `PDF annotation '${before.id}'`);
504
+ }
505
+ }
506
+ for (const after of next){
507
+ if (previousIds.has(after.id)) continue;
508
+ const current = sharedById.get(after.id);
509
+ if (current) {
510
+ if (after.source !== current.source) conflict(`PDF annotation '${after.id}' source`);
511
+ assertCompatibleValue({}, after, current, `PDF annotation '${after.id}'`);
512
+ }
513
+ }
514
+ }
515
+ function assertMutableRecordCollection(previous, next, shared, label) {
516
+ const nextById = new Map(next.map((value)=>[
517
+ value.id,
518
+ value
519
+ ]));
520
+ const sharedById = new Map(shared.map((value)=>[
521
+ value.id,
522
+ value
523
+ ]));
524
+ const previousIds = new Set(previous.map(({ id })=>id));
525
+ for (const before of previous){
526
+ const after = nextById.get(before.id);
527
+ const current = sharedById.get(before.id);
528
+ if (!after) {
529
+ if (current && !workOfficeCollaborationJsonEqual(before, current)) conflict(`${label} '${before.id}'`);
530
+ continue;
531
+ }
532
+ if (!workOfficeCollaborationJsonEqual(before, after)) {
533
+ if (!current) removedConflict(`${label} '${before.id}'`);
534
+ assertCompatibleValue(before, after, current, `${label} '${before.id}'`);
535
+ }
536
+ }
537
+ for (const after of next){
538
+ if (previousIds.has(after.id)) continue;
539
+ const current = sharedById.get(after.id);
540
+ if (current) assertCompatibleValue({}, after, current, `${label} '${after.id}'`);
541
+ }
542
+ }
543
+ function assertAppendOnlyCollection(previous, next, shared, label) {
544
+ if (previous.some((value, index)=>next[index]?.id !== value.id)) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `${label} records are append-only and cannot be reordered or inserted before an existing record.`);
545
+ const nextById = new Map(next.map((value)=>[
546
+ value.id,
547
+ value
548
+ ]));
549
+ const sharedById = new Map(shared.map((value)=>[
550
+ value.id,
551
+ value
552
+ ]));
553
+ const previousIds = new Set(previous.map(({ id })=>id));
554
+ for (const before of previous){
555
+ const after = nextById.get(before.id);
556
+ if (!after || !workOfficeCollaborationJsonEqual(before, after)) throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `${label} '${before.id}' is an append-only audit record and cannot be changed or removed.`);
557
+ }
558
+ for (const after of next){
559
+ if (previousIds.has(after.id)) continue;
560
+ const current = sharedById.get(after.id);
561
+ if (current && !workOfficeCollaborationJsonEqual(after, current)) conflict(`${label} '${after.id}'`);
562
+ }
563
+ }
564
+ function assertCompatibleValue(previous, next, shared, label) {
565
+ if (workOfficeCollaborationJsonEqual(previous, next)) return;
566
+ if (isWorkOfficeCollaborationRecord(previous) && isWorkOfficeCollaborationRecord(next) && isWorkOfficeCollaborationRecord(shared)) {
567
+ const keys = new Set([
568
+ ...Object.keys(previous),
569
+ ...Object.keys(next)
570
+ ]);
571
+ for (const key of keys){
572
+ const hadPrevious = Object.hasOwn(previous, key);
573
+ const hasNext = Object.hasOwn(next, key);
574
+ const hasShared = Object.hasOwn(shared, key);
575
+ const fieldLabel = `${label} field '${key}'`;
576
+ if (!hasNext) {
577
+ if (hadPrevious && hasShared && !workOfficeCollaborationJsonEqual(previous[key], shared[key])) conflict(fieldLabel);
578
+ continue;
579
+ }
580
+ if (!hadPrevious) {
581
+ if (hasShared && !workOfficeCollaborationJsonEqual(next[key], shared[key])) conflict(fieldLabel);
582
+ continue;
583
+ }
584
+ if (!workOfficeCollaborationJsonEqual(previous[key], next[key])) {
585
+ if (!hasShared) removedConflict(fieldLabel);
586
+ assertCompatibleValue(previous[key], next[key], shared[key], fieldLabel);
587
+ }
588
+ }
589
+ return;
590
+ }
591
+ if (!workOfficeCollaborationJsonEqual(previous, shared) && !workOfficeCollaborationJsonEqual(next, shared)) conflict(label);
592
+ }
593
+ function removedConflict(label) {
594
+ throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `The ${label} was removed before this change could be applied. Refresh the shared snapshot before retrying.`);
595
+ }
596
+ function conflict(label) {
597
+ throw new WorkOfficeCollaborationError('office.collaboration.content_invalid', `The ${label} changed concurrently. Refresh the shared snapshot before retrying.`);
598
+ }
599
+ function workOfficePdfRecordCollectionRoots(document, rootName, name) {
600
+ return {
601
+ presence: document.getMap(rootName(`pdf.${name}.presence`)),
602
+ fields: document.getMap(rootName(`pdf.${name}.fields`)),
603
+ order: document.getArray(rootName(`pdf.${name}.order`))
604
+ };
605
+ }
606
+ function patchWorkOfficePdfRecords(roots, previous, next, label) {
607
+ const beforeById = new Map(previous.map((value)=>[
608
+ value.id,
609
+ value
610
+ ]));
611
+ const afterById = new Map(next.map((value)=>[
612
+ value.id,
613
+ value
614
+ ]));
615
+ for (const before of previous){
616
+ if (afterById.has(before.id)) continue;
617
+ const presence = roots.presence.get(before.id);
618
+ if (void 0 === presence) {
619
+ removeAll(roots.order, before.id);
620
+ continue;
621
+ }
622
+ if (true !== presence) invalidWorkOfficePdfShared(`${label} record presence`);
623
+ roots.presence.delete(before.id);
624
+ patchWorkOfficeCollaborationFlatJsonMap(new PdfRecordFlatJsonMap(roots.fields, before.id, label), before, void 0, `${label} '${before.id}'`);
625
+ removeAll(roots.order, before.id);
626
+ }
627
+ for (const after of next){
628
+ const before = beforeById.get(after.id);
629
+ if (!(before && workOfficeCollaborationJsonEqual(before, after))) {
630
+ roots.presence.set(after.id, true);
631
+ patchWorkOfficeCollaborationFlatJsonMap(new PdfRecordFlatJsonMap(roots.fields, after.id, label), before, after, `${label} '${after.id}'`);
632
+ }
633
+ }
634
+ patchWorkOfficePdfOrder(roots.order, previous.map(({ id })=>id), next.map(({ id })=>id));
635
+ }
636
+ function readWorkOfficePdfRecords(roots, label) {
637
+ const ids = validatedPdfOrder(roots.order, roots.presence, label);
638
+ const fieldsById = pdfFieldsById(roots, label);
639
+ return ids.map((id)=>{
640
+ const value = readWorkOfficeCollaborationFlatJsonMap(fieldsById.get(id) ?? new Map(), `${label} '${id}'`, invalidWorkOfficePdfShared);
641
+ if (value.id !== id) invalidWorkOfficePdfShared(`${label} identity`);
642
+ return value;
643
+ });
644
+ }
645
+ function assertWorkOfficePdfRecordCollectionEmpty(roots) {
646
+ return 0 === roots.presence.size && 0 === roots.fields.size && 0 === roots.order.length;
647
+ }
648
+ function workOfficePdfRecordCollectionUndoScope(roots) {
649
+ return [
650
+ roots.presence,
651
+ roots.fields,
652
+ roots.order
653
+ ];
654
+ }
655
+ function workOfficePdfRecordFieldChanged(transaction, roots, path) {
656
+ const changedKeys = transaction.changed.get(roots.fields);
657
+ if (!changedKeys) return false;
658
+ const encodedField = JSON.stringify([
659
+ 'value',
660
+ ...path
661
+ ]);
662
+ for (const key of changedKeys){
663
+ if (null === key) return true;
664
+ const identity = tryDecodeRecordFieldIdentity(key);
665
+ if (identity?.[1] === encodedField) return true;
666
+ }
667
+ return false;
668
+ }
669
+ function validatedPdfOrder(order, presence, label) {
670
+ const seen = new Set();
671
+ const result = [];
672
+ for (const id of order.toArray()){
673
+ if ('string' != typeof id || !id.trim()) invalidWorkOfficePdfShared(`${label} order`);
674
+ if (!seen.has(id)) {
675
+ seen.add(id);
676
+ result.push(id);
677
+ }
678
+ }
679
+ for (const [id, value] of presence.entries())if (true !== value || !id.trim() || !seen.has(id)) invalidWorkOfficePdfShared(`${label} order and record set`);
680
+ if (seen.size !== presence.size) invalidWorkOfficePdfShared(`${label} order and record set`);
681
+ return result;
682
+ }
683
+ function pdfFieldsById(roots, label) {
684
+ const result = new Map();
685
+ for (const [encoded, value] of roots.fields.entries()){
686
+ const [id, field] = decodedRecordFieldIdentity(encoded, label);
687
+ if (true !== roots.presence.get(id)) invalidWorkOfficePdfShared(`${label} orphan field`);
688
+ let fields = result.get(id);
689
+ if (!fields) {
690
+ fields = new Map();
691
+ result.set(id, fields);
692
+ }
693
+ fields.set(field, value);
694
+ }
695
+ return result;
696
+ }
697
+ function patchWorkOfficePdfOrder(order, previous, next) {
698
+ if (workOfficeCollaborationJsonEqual(previous, next)) return;
699
+ const nextIds = new Set(next);
700
+ for (const id of previous)if (!nextIds.has(id)) removeAll(order, id);
701
+ const previousIds = new Set(previous);
702
+ for (const id of next)if (!(previousIds.has(id) || order.toArray().includes(id))) insertRelative(order, next, id);
703
+ if (!sameRelativeOrder(previous, next)) {
704
+ for (const id of next.filter((id)=>previousIds.has(id)))removeAll(order, id);
705
+ for (const id of next)if (!order.toArray().includes(id)) insertRelative(order, next, id);
706
+ }
707
+ }
708
+ class PdfRecordFlatJsonMap {
709
+ fields;
710
+ id;
711
+ label;
712
+ constructor(fields, id, label){
713
+ this.fields = fields;
714
+ this.id = id;
715
+ this.label = label;
716
+ }
717
+ delete(key) {
718
+ const encoded = encodedRecordFieldIdentity(this.id, key);
719
+ const hadValue = this.fields.has(encoded);
720
+ this.fields.delete(encoded);
721
+ return hadValue;
722
+ }
723
+ *entries() {
724
+ for (const [encoded, value] of this.fields.entries()){
725
+ const [id, field] = decodedRecordFieldIdentity(encoded, this.label);
726
+ if (id === this.id) yield [
727
+ field,
728
+ value
729
+ ];
730
+ }
731
+ }
732
+ get(key) {
733
+ return this.fields.get(encodedRecordFieldIdentity(this.id, key));
734
+ }
735
+ set(key, value) {
736
+ this.fields.set(encodedRecordFieldIdentity(this.id, key), value);
737
+ return this.fields;
738
+ }
739
+ }
740
+ function encodedRecordFieldIdentity(id, field) {
741
+ return JSON.stringify([
742
+ id,
743
+ field
744
+ ]);
745
+ }
746
+ function decodedRecordFieldIdentity(encoded, label) {
747
+ const identity = tryDecodeRecordFieldIdentity(encoded);
748
+ if (!identity?.[0].trim()) invalidWorkOfficePdfShared(`${label} field identity`);
749
+ if (encodedRecordFieldIdentity(identity[0], identity[1]) !== encoded) invalidWorkOfficePdfShared(`${label} field identity`);
750
+ return identity;
751
+ }
752
+ function tryDecodeRecordFieldIdentity(encoded) {
753
+ let identity;
754
+ try {
755
+ identity = JSON.parse(encoded);
756
+ } catch {
757
+ return;
758
+ }
759
+ if (!Array.isArray(identity) || 2 !== identity.length || identity.some((value)=>'string' != typeof value)) return;
760
+ return identity;
761
+ }
762
+ function insertRelative(order, desired, id) {
763
+ const desiredIndex = desired.indexOf(id);
764
+ for(let index = desiredIndex - 1; index >= 0; index -= 1){
765
+ const currentIndex = order.toArray().indexOf(desired[index]);
766
+ if (currentIndex >= 0) return void order.insert(currentIndex + 1, [
767
+ id
768
+ ]);
769
+ }
770
+ for(let index = desiredIndex + 1; index < desired.length; index += 1){
771
+ const currentIndex = order.toArray().indexOf(desired[index]);
772
+ if (currentIndex >= 0) return void order.insert(currentIndex, [
773
+ id
774
+ ]);
775
+ }
776
+ order.push([
777
+ id
778
+ ]);
779
+ }
780
+ function sameRelativeOrder(previous, next) {
781
+ const nextIds = new Set(next);
782
+ const previousIds = new Set(previous);
783
+ return workOfficeCollaborationJsonEqual(previous.filter((id)=>nextIds.has(id)), next.filter((id)=>previousIds.has(id)));
784
+ }
785
+ function removeAll(order, id) {
786
+ for(let index = order.length - 1; index >= 0; index -= 1)if (order.get(index) === id) order.delete(index, 1);
787
+ }
788
+ const PDF_SOURCE_ROOT = 'pdf.source';
789
+ const PDF_SOURCE_IDENTITIES_ROOT = 'pdf.source-identities';
790
+ const PDF_RECORD_CLAIMS_ROOT = 'pdf.record-claims';
791
+ function workOfficePdfRoots(document, rootName) {
792
+ return {
793
+ source: document.getMap(rootName(PDF_SOURCE_ROOT)),
794
+ sourceIdentities: document.getArray(rootName(PDF_SOURCE_IDENTITIES_ROOT)),
795
+ annotations: workOfficePdfRecordCollectionRoots(document, rootName, 'annotations'),
796
+ formValues: workOfficePdfRecordCollectionRoots(document, rootName, 'form-values'),
797
+ signaturePlacements: workOfficePdfRecordCollectionRoots(document, rootName, 'signature-placements'),
798
+ redactionProposals: workOfficePdfRecordCollectionRoots(document, rootName, 'redaction-proposals'),
799
+ pageOperations: workOfficePdfRecordCollectionRoots(document, rootName, 'page-operations'),
800
+ reviewDecisions: workOfficePdfRecordCollectionRoots(document, rootName, 'review-decisions'),
801
+ recordClaims: document.getArray(rootName(PDF_RECORD_CLAIMS_ROOT))
802
+ };
803
+ }
804
+ function initializeWorkOfficePdfRoots(roots, content) {
805
+ patchSource(roots.source, content.source);
806
+ roots.sourceIdentities.push([
807
+ canonicalWorkOfficeCollaborationJson(content.source)
808
+ ]);
809
+ appendWorkOfficePdfRecordClaims(roots.recordClaims, void 0, content);
810
+ patchCollections(roots, void 0, content);
811
+ }
812
+ function readWorkOfficePdfRoots(roots) {
813
+ const content = {
814
+ type: 'pdf',
815
+ source: readSource(roots.source),
816
+ annotations: readWorkOfficePdfRecords(roots.annotations, 'annotation'),
817
+ formValues: readWorkOfficePdfRecords(roots.formValues, 'form value'),
818
+ signaturePlacements: readWorkOfficePdfRecords(roots.signaturePlacements, 'signature placement'),
819
+ redactionProposals: readWorkOfficePdfRecords(roots.redactionProposals, 'redaction proposal'),
820
+ pageOperations: readWorkOfficePdfRecords(roots.pageOperations, 'page operation'),
821
+ reviewDecisions: readWorkOfficePdfRecords(roots.reviewDecisions, 'review decision')
822
+ };
823
+ const validated = validateSharedWorkOfficePdfCollaborationContent(content);
824
+ assertSourceIdentity(roots.sourceIdentities, validated.source);
825
+ assertWorkOfficePdfRecordClaims(roots.recordClaims, validated);
826
+ return validated;
827
+ }
828
+ function patchWorkOfficePdfRoots(roots, previous, next) {
829
+ const shared = readWorkOfficePdfRoots(roots);
830
+ assertWorkOfficePdfPatchSafe(previous, next, shared);
831
+ appendWorkOfficePdfRecordClaims(roots.recordClaims, previous, next);
832
+ patchCollections(roots, previous, next);
833
+ }
834
+ function assertWorkOfficePdfRootsEmpty(roots) {
835
+ if (roots.source.size > 0 || roots.sourceIdentities.length > 0 || !assertWorkOfficePdfRecordCollectionEmpty(roots.annotations) || !assertWorkOfficePdfRecordCollectionEmpty(roots.formValues) || !assertWorkOfficePdfRecordCollectionEmpty(roots.signaturePlacements) || !assertWorkOfficePdfRecordCollectionEmpty(roots.redactionProposals) || !assertWorkOfficePdfRecordCollectionEmpty(roots.pageOperations) || !assertWorkOfficePdfRecordCollectionEmpty(roots.reviewDecisions) || roots.recordClaims.length > 0) throw new WorkOfficeCollaborationError('office.collaboration.bootstrap_ambiguous', 'The PDF collaboration roots contain data without initialized metadata.');
836
+ }
837
+ function workOfficePdfUndoScope(roots) {
838
+ return [
839
+ ...workOfficePdfRecordCollectionUndoScope(roots.annotations),
840
+ ...workOfficePdfRecordCollectionUndoScope(roots.formValues)
841
+ ];
842
+ }
843
+ function workOfficePdfIrreversibleScope(roots) {
844
+ return [
845
+ ...workOfficePdfRecordCollectionUndoScope(roots.signaturePlacements),
846
+ ...workOfficePdfRecordCollectionUndoScope(roots.redactionProposals),
847
+ ...workOfficePdfRecordCollectionUndoScope(roots.pageOperations),
848
+ ...workOfficePdfRecordCollectionUndoScope(roots.reviewDecisions)
849
+ ];
850
+ }
851
+ function workOfficePdfIrreversibleChange(roots, transaction) {
852
+ const changedParents = transaction.changedParentTypes;
853
+ return workOfficePdfRecordFieldChanged(transaction, roots.annotations, [
854
+ 'deleted'
855
+ ]) || workOfficePdfIrreversibleScope(roots).some((root)=>changedParents.has(root));
856
+ }
857
+ function patchCollections(roots, previous, next) {
858
+ patchWorkOfficePdfRecords(roots.annotations, previous?.annotations ?? [], next.annotations, 'annotation');
859
+ patchWorkOfficePdfRecords(roots.formValues, previous?.formValues ?? [], next.formValues, 'form value');
860
+ patchWorkOfficePdfRecords(roots.signaturePlacements, previous?.signaturePlacements ?? [], next.signaturePlacements, 'signature placement');
861
+ patchWorkOfficePdfRecords(roots.redactionProposals, previous?.redactionProposals ?? [], next.redactionProposals, 'redaction proposal');
862
+ patchWorkOfficePdfRecords(roots.pageOperations, previous?.pageOperations ?? [], next.pageOperations, 'page operation');
863
+ patchWorkOfficePdfRecords(roots.reviewDecisions, previous?.reviewDecisions ?? [], next.reviewDecisions, 'review decision');
864
+ }
865
+ function patchSource(target, source) {
866
+ target.set('sha256', source.sha256);
867
+ target.set('byteLength', source.byteLength);
868
+ target.set('pageCount', source.pageCount);
869
+ }
870
+ function readSource(target) {
871
+ const sha256 = target.get('sha256');
872
+ const byteLength = target.get('byteLength');
873
+ const pageCount = target.get('pageCount');
874
+ if (3 !== target.size || 'string' != typeof sha256 || 'number' != typeof byteLength || 'number' != typeof pageCount) invalidWorkOfficePdfShared('source identity');
875
+ return {
876
+ sha256,
877
+ byteLength,
878
+ pageCount
879
+ };
880
+ }
881
+ function assertSourceIdentity(identities, source) {
882
+ if (0 === identities.length) return;
883
+ if (1 !== identities.length || identities.get(0) !== canonicalWorkOfficeCollaborationJson(source)) invalidWorkOfficePdfShared('immutable source identity');
884
+ }
885
+ function initializeWorkOfficePdfCollaboration(session, content) {
886
+ assertPdfSession(session);
887
+ assertWorkOfficeCollaborationEditable(session);
888
+ const prepared = validateWorkOfficePdfCollaborationContent(content);
889
+ const existing = readWorkOfficeCollaborationMetadata(session);
890
+ if (existing?.initialized) {
891
+ const current = readWorkOfficePdfCollaboration(session);
892
+ if (!workOfficeCollaborationJsonEqual(current.source, prepared.source)) throw new WorkOfficeCollaborationError('office.collaboration.artifact_mismatch', `The PDF source does not match collaboration artifact '${session.artifactId}'.`);
893
+ return {
894
+ initialized: false,
895
+ content: current
896
+ };
897
+ }
898
+ const roots = pdfRoots(session);
899
+ assertWorkOfficePdfRootsEmpty(roots);
900
+ const origin = session.createOrigin('bootstrap');
901
+ session.transact(()=>{
902
+ const metadata = initializeWorkOfficeCollaborationMetadata(session);
903
+ if (metadata.initialized) return;
904
+ registerWorkOfficeCollaborationInitializer(session);
905
+ initializeWorkOfficePdfRoots(roots, prepared);
906
+ markWorkOfficeCollaborationInitialized(session);
907
+ }, origin);
908
+ return {
909
+ initialized: true,
910
+ content: readWorkOfficePdfCollaboration(session)
911
+ };
912
+ }
913
+ function readWorkOfficePdfCollaboration(session) {
914
+ assertInitializedPdfSession(session);
915
+ return readWorkOfficePdfRoots(pdfRoots(session));
916
+ }
917
+ function assertWorkOfficePdfCollaborationSource(session, source) {
918
+ const expected = readWorkOfficePdfCollaboration(session).source;
919
+ if (workOfficeCollaborationJsonEqual(expected, source)) return;
920
+ throw new WorkOfficeCollaborationError('office.collaboration.artifact_mismatch', `The PDF source does not match collaboration artifact '${session.artifactId}'.`);
921
+ }
922
+ function readWorkOfficePdfCollaborationSource(session) {
923
+ return readWorkOfficePdfCollaboration(session).source;
924
+ }
925
+ function replaceWorkOfficePdfCollaboration(session, previous, next, origin = session.localOrigin) {
926
+ assertInitializedPdfSession(session);
927
+ assertWorkOfficeCollaborationEditable(session);
928
+ const before = validateWorkOfficePdfCollaborationContent(previous);
929
+ const after = validateWorkOfficePdfCollaborationContent(next);
930
+ if (workOfficeCollaborationJsonEqual(before, after)) return false;
931
+ session.transact(()=>{
932
+ patchWorkOfficePdfRoots(pdfRoots(session), before, after);
933
+ }, origin);
934
+ return true;
935
+ }
936
+ function createWorkOfficePdfCollaborationBinding(session, options = {}) {
937
+ assertInitializedPdfSession(session);
938
+ return new WorkOfficePdfCollaborationBindingImpl(session, options);
939
+ }
940
+ class WorkOfficePdfCollaborationBindingImpl {
941
+ origin;
942
+ #session;
943
+ #undoManager;
944
+ #roots;
945
+ #undoScope;
946
+ #irreversibleScope;
947
+ #changeScope;
948
+ #listeners = new Set();
949
+ #errorListeners = new Set();
950
+ #historyListeners = new Set();
951
+ #destroyed = false;
952
+ #pendingChange = false;
953
+ #pendingLocal = true;
954
+ #pendingOrigin;
955
+ constructor(session, options){
956
+ this.#session = session;
957
+ this.#roots = pdfRoots(session);
958
+ this.origin = options.origin ?? session.createOrigin(session.localOrigin.kind);
959
+ assertWorkOfficeCollaborationOrigin(this.origin);
960
+ this.#undoScope = workOfficePdfUndoScope(this.#roots);
961
+ this.#irreversibleScope = workOfficePdfIrreversibleScope(this.#roots);
962
+ this.#changeScope = [
963
+ this.#roots.source,
964
+ this.#roots.sourceIdentities,
965
+ this.#roots.recordClaims,
966
+ ...this.#undoScope,
967
+ ...this.#irreversibleScope
968
+ ];
969
+ this.#undoManager = new __rspack_external_yjs.UndoManager(this.#undoScope, {
970
+ captureTimeout: options.captureTimeoutMs ?? 500,
971
+ trackedOrigins: new Set([
972
+ this.origin
973
+ ])
974
+ });
975
+ session.document.on('afterTransaction', this.#onTransaction);
976
+ this.#undoManager.on('stack-item-added', this.#onHistoryChange);
977
+ this.#undoManager.on('stack-item-popped', this.#onHistoryChange);
978
+ this.#undoManager.on('stack-item-updated', this.#onHistoryChange);
979
+ this.#undoManager.on('stack-cleared', this.#onHistoryChange);
980
+ }
981
+ content() {
982
+ this.ensureActive();
983
+ return readWorkOfficePdfRoots(this.#roots);
984
+ }
985
+ replace(previous, next) {
986
+ this.ensureActive();
987
+ return replaceWorkOfficePdfCollaboration(this.#session, previous, next, this.origin);
988
+ }
989
+ canUndo() {
990
+ this.ensureActive();
991
+ return this.#undoManager.canUndo();
992
+ }
993
+ canRedo() {
994
+ this.ensureActive();
995
+ return this.#undoManager.canRedo();
996
+ }
997
+ undo() {
998
+ this.ensureActive();
999
+ assertWorkOfficeCollaborationEditable(this.#session);
1000
+ return null !== this.#undoManager.undo();
1001
+ }
1002
+ redo() {
1003
+ this.ensureActive();
1004
+ assertWorkOfficeCollaborationEditable(this.#session);
1005
+ return null !== this.#undoManager.redo();
1006
+ }
1007
+ stopCapturing() {
1008
+ this.ensureActive();
1009
+ this.#undoManager.stopCapturing();
1010
+ }
1011
+ subscribe(listener) {
1012
+ this.ensureActive();
1013
+ this.#listeners.add(listener);
1014
+ return ()=>this.#listeners.delete(listener);
1015
+ }
1016
+ subscribeError(listener) {
1017
+ this.ensureActive();
1018
+ this.#errorListeners.add(listener);
1019
+ return ()=>this.#errorListeners.delete(listener);
1020
+ }
1021
+ subscribeHistory(listener) {
1022
+ this.ensureActive();
1023
+ this.#historyListeners.add(listener);
1024
+ return ()=>this.#historyListeners.delete(listener);
1025
+ }
1026
+ destroy() {
1027
+ if (this.#destroyed) return;
1028
+ this.#destroyed = true;
1029
+ this.#pendingChange = false;
1030
+ this.#session.document.off('afterTransaction', this.#onTransaction);
1031
+ this.#undoManager.off('stack-item-added', this.#onHistoryChange);
1032
+ this.#undoManager.off('stack-item-popped', this.#onHistoryChange);
1033
+ this.#undoManager.off('stack-item-updated', this.#onHistoryChange);
1034
+ this.#undoManager.off('stack-cleared', this.#onHistoryChange);
1035
+ this.#undoManager.destroy();
1036
+ this.#listeners.clear();
1037
+ this.#errorListeners.clear();
1038
+ this.#historyListeners.clear();
1039
+ }
1040
+ #onTransaction = (transaction)=>{
1041
+ const changedParents = new Set(transaction.changedParentTypes.keys());
1042
+ if (workOfficePdfIrreversibleChange(this.#roots, transaction)) this.#undoManager.clear();
1043
+ if (this.#destroyed || !this.#changeScope.some((root)=>changedParents.has(root))) return;
1044
+ const local = transaction.origin === this.origin || transaction.origin === this.#undoManager;
1045
+ this.#pendingLocal = this.#pendingChange ? this.#pendingLocal && local : local;
1046
+ this.#pendingOrigin = transaction.origin;
1047
+ if (this.#pendingChange) return;
1048
+ this.#pendingChange = true;
1049
+ queueMicrotask(this.#flushChange);
1050
+ };
1051
+ #flushChange = ()=>{
1052
+ if (this.#destroyed || !this.#pendingChange) return;
1053
+ const local = this.#pendingLocal;
1054
+ const origin = this.#pendingOrigin;
1055
+ this.#pendingChange = false;
1056
+ this.#pendingLocal = true;
1057
+ this.#pendingOrigin = void 0;
1058
+ try {
1059
+ const change = {
1060
+ content: this.content(),
1061
+ local,
1062
+ origin
1063
+ };
1064
+ for (const listener of this.#listeners)listener(change);
1065
+ } catch (error) {
1066
+ for (const listener of this.#errorListeners)listener(error);
1067
+ }
1068
+ };
1069
+ #onHistoryChange = ()=>{
1070
+ for (const listener of this.#historyListeners)listener();
1071
+ };
1072
+ ensureActive() {
1073
+ if (!this.#destroyed) return;
1074
+ throw new WorkOfficeCollaborationError('office.collaboration.binding_destroyed', 'The PDF collaboration binding has been destroyed.');
1075
+ }
1076
+ }
1077
+ function pdfRoots(session) {
1078
+ return workOfficePdfRoots(session.document, session.rootName.bind(session));
1079
+ }
1080
+ function assertPdfSession(session) {
1081
+ if ('pdf' === session.kind) return;
1082
+ throw new WorkOfficeCollaborationError('office.collaboration.kind_mismatch', `A PDF collaboration binding cannot use a '${session.kind}' session.`);
1083
+ }
1084
+ function assertInitializedPdfSession(session) {
1085
+ assertPdfSession(session);
1086
+ const metadata = readWorkOfficeCollaborationMetadata(session);
1087
+ if (metadata?.initialized) return;
1088
+ throw new WorkOfficeCollaborationError('office.collaboration.not_initialized', 'The PDF collaboration session has not been initialized.');
1089
+ }
1090
+ export { assertWorkOfficePdfCollaborationSource as assertPdfCollaborationSource, createWorkOfficePdfCollaborationBinding as createOfficePdfCollaborationBinding, initializeWorkOfficePdfCollaboration as initializeOfficePdfCollaboration, readWorkOfficePdfCollaboration as readOfficePdfCollaboration, readWorkOfficePdfCollaborationSource as readOfficePdfCollaborationSource, replaceWorkOfficePdfCollaboration as replaceOfficePdfCollaboration };