@stll/folio-core 0.54.2 → 0.56.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 (267) hide show
  1. package/dist/ai-edits/apply.js +185 -33
  2. package/dist/ai-edits/headless.js +3 -2
  3. package/dist/ai-edits/types.d.ts +7 -1
  4. package/dist/compare/compare.js +1 -0
  5. package/dist/compare/content-types.d.ts +3 -15
  6. package/dist/compare/reproducible-package.d.ts +0 -17
  7. package/dist/compare/reproducible-package.js +12 -18
  8. package/dist/controller/canonicalClipboard.d.ts +23 -0
  9. package/dist/controller/canonicalClipboard.js +476 -0
  10. package/dist/controller/canonicalClipboardResources.d.ts +21 -0
  11. package/dist/controller/canonicalClipboardResources.js +382 -0
  12. package/dist/controller/canonicalComposition.d.ts +53 -0
  13. package/dist/controller/canonicalComposition.js +296 -0
  14. package/dist/controller/canonicalInlineProjection.d.ts +113 -0
  15. package/dist/controller/canonicalInlineProjection.js +393 -0
  16. package/dist/controller/canonicalInput.d.ts +54 -0
  17. package/dist/controller/canonicalInput.js +377 -0
  18. package/dist/controller/canonicalInputTimer.d.ts +7 -0
  19. package/dist/controller/canonicalInputTimer.js +11 -0
  20. package/dist/controller/canonicalOperations.d.ts +22 -0
  21. package/dist/controller/canonicalOperations.js +85 -0
  22. package/dist/controller/canonicalPublicOperations.d.ts +48 -0
  23. package/dist/controller/canonicalPublicOperations.js +556 -0
  24. package/dist/controller/canonicalReview.d.ts +12 -0
  25. package/dist/controller/canonicalReview.js +19 -0
  26. package/dist/controller/canonicalSession.d.ts +167 -0
  27. package/dist/controller/canonicalSession.js +1186 -0
  28. package/dist/controller/canonicalStoryEditor.d.ts +36 -0
  29. package/dist/controller/canonicalStoryEditor.js +87 -0
  30. package/dist/controller/canonicalStructure.d.ts +16 -0
  31. package/dist/controller/canonicalStructure.js +322 -0
  32. package/dist/controller/canonicalTocSelection.d.ts +11 -0
  33. package/dist/controller/canonicalTocSelection.js +43 -0
  34. package/dist/controller/folioEditor.d.ts +3 -10
  35. package/dist/controller/folioEditor.js +14 -4
  36. package/dist/controller/headerFooterEditorManager.d.ts +5 -0
  37. package/dist/controller/headerFooterEditorManager.js +72 -3
  38. package/dist/controller/hiddenEditorApi.d.ts +45 -0
  39. package/dist/controller/hiddenEditorApi.js +29 -8
  40. package/dist/controller/hiddenEditorManager.d.ts +13 -2
  41. package/dist/controller/hiddenEditorManager.js +639 -31
  42. package/dist/controller/layoutPipeline.d.ts +1 -1
  43. package/dist/controller/layoutPipeline.js +2 -0
  44. package/dist/controller/noteEditorManager.d.ts +5 -0
  45. package/dist/controller/noteEditorManager.js +114 -15
  46. package/dist/document-operations.d.ts +8 -1
  47. package/dist/document-operations.js +6 -4
  48. package/dist/docx/attributeRemainder.js +1 -0
  49. package/dist/docx/blockPlainText.d.ts +1 -1
  50. package/dist/docx/blockPlainText.js +11 -3
  51. package/dist/docx/canonicalResourceSave.d.ts +16 -0
  52. package/dist/docx/canonicalResourceSave.js +27 -0
  53. package/dist/docx/canonicalSave.d.ts +29 -0
  54. package/dist/docx/canonicalSave.js +101 -0
  55. package/dist/docx/canonicalSessionInput.d.ts +11 -0
  56. package/dist/docx/canonicalSessionInput.js +27 -0
  57. package/dist/docx/canonicalStoryRepack.d.ts +10 -0
  58. package/dist/docx/canonicalStoryRepack.js +74 -0
  59. package/dist/docx/contentTypeRegistry.d.ts +8 -0
  60. package/dist/docx/contentTypeRegistry.js +64 -0
  61. package/dist/docx/documentParser.d.ts +1 -13
  62. package/dist/docx/documentParser.js +1 -47
  63. package/dist/docx/ensureParaIds.d.ts +7 -1
  64. package/dist/docx/ensureParaIds.js +173 -215
  65. package/dist/docx/foldedListNumberFields.d.ts +85 -0
  66. package/dist/docx/foldedListNumberFields.js +267 -0
  67. package/dist/docx/footnoteParser.d.ts +1 -11
  68. package/dist/docx/footnoteParser.js +1 -16
  69. package/dist/docx/headerFooterParser.d.ts +1 -9
  70. package/dist/docx/headerFooterParser.js +1 -12
  71. package/dist/docx/headerFooterVerbatim.d.ts +39 -1
  72. package/dist/docx/headerFooterVerbatim.js +173 -2
  73. package/dist/docx/imageParser.d.ts +13 -1
  74. package/dist/docx/imageParser.js +20 -11
  75. package/dist/docx/metadataPrivacy.js +6 -1
  76. package/dist/docx/noteIds.d.ts +5 -0
  77. package/dist/docx/noteIds.js +6 -2
  78. package/dist/docx/noteReferenceMark.d.ts +3 -1
  79. package/dist/docx/noteReferenceMark.js +15 -14
  80. package/dist/docx/numberingParser.d.ts +3 -1
  81. package/dist/docx/numberingParser.js +17 -3
  82. package/dist/docx/packageParts.d.ts +3 -1
  83. package/dist/docx/packageParts.js +74 -19
  84. package/dist/docx/paragraphMarkPropertyPresence.d.ts +9 -0
  85. package/dist/docx/paragraphMarkPropertyPresence.js +21 -0
  86. package/dist/docx/paragraphParser.js +101 -53
  87. package/dist/docx/paragraphPropertySource.d.ts +15 -1
  88. package/dist/docx/paragraphPropertySource.js +77 -22
  89. package/dist/docx/parser.js +3 -1
  90. package/dist/docx/removeHeaderFooterParts.js +17 -6
  91. package/dist/docx/reviewHistoryNamespace.d.ts +4 -0
  92. package/dist/docx/reviewHistoryNamespace.js +4 -0
  93. package/dist/docx/reviewResolutionProvenance.d.ts +25 -0
  94. package/dist/docx/reviewResolutionProvenance.js +153 -0
  95. package/dist/docx/rezip.d.ts +54 -6
  96. package/dist/docx/rezip.js +835 -257
  97. package/dist/docx/runConsolidator.d.ts +2 -58
  98. package/dist/docx/runConsolidator.js +3 -175
  99. package/dist/docx/runParser.d.ts +2 -1
  100. package/dist/docx/runParser.js +156 -116
  101. package/dist/docx/saveDiagnostics.d.ts +22 -0
  102. package/dist/docx/saveDiagnostics.js +0 -0
  103. package/dist/docx/selectiveSave.d.ts +3 -1
  104. package/dist/docx/selectiveSave.js +36 -4
  105. package/dist/docx/selectiveXmlPatch.d.ts +16 -8
  106. package/dist/docx/selectiveXmlPatch.js +81 -7
  107. package/dist/docx/serializer/documentSerializer.d.ts +9 -2
  108. package/dist/docx/serializer/documentSerializer.js +29 -10
  109. package/dist/docx/serializer/headerFooterSerializer.d.ts +5 -1
  110. package/dist/docx/serializer/headerFooterSerializer.js +19 -11
  111. package/dist/docx/serializer/noteSerializer.d.ts +2 -2
  112. package/dist/docx/serializer/noteSerializer.js +24 -8
  113. package/dist/docx/serializer/paragraphSerializer.js +41 -4
  114. package/dist/docx/serializer/partNamespaces.js +2 -1
  115. package/dist/docx/serializer/runSerializer.js +3 -1
  116. package/dist/docx/server/applyDocxXmlPatchProposal.js +14 -9
  117. package/dist/docx/settingsHeaderFooterUpdate.d.ts +5 -0
  118. package/dist/docx/settingsHeaderFooterUpdate.js +90 -0
  119. package/dist/docx/settingsParser.d.ts +1 -2
  120. package/dist/docx/settingsParser.js +5 -6
  121. package/dist/docx/storyBlockReplay.d.ts +31 -0
  122. package/dist/docx/storyBlockReplay.js +471 -0
  123. package/dist/docx/storyPlainText.d.ts +20 -0
  124. package/dist/docx/storyPlainText.js +23 -0
  125. package/dist/docx/streamingXmlParser.d.ts +22 -1
  126. package/dist/docx/streamingXmlParser.js +49 -3
  127. package/dist/docx/structuralXmlPatch.js +18 -23
  128. package/dist/docx/styleParser.d.ts +5 -1
  129. package/dist/docx/styleParser.js +1 -1
  130. package/dist/docx/tableParser.d.ts +1 -8
  131. package/dist/docx/tableParser.js +1 -28
  132. package/dist/docx/textBoxParser.d.ts +1 -5
  133. package/dist/docx/textBoxParser.js +1 -20
  134. package/dist/docx/unzip.js +6 -1
  135. package/dist/docx/verbatimCapture.d.ts +3 -1
  136. package/dist/docx/verbatimCapture.js +49 -6
  137. package/dist/i18n/messages/ar.gen.d.ts +5 -0
  138. package/dist/i18n/messages/ar.gen.js +656 -0
  139. package/dist/i18n/messages/cs.gen.d.ts +5 -0
  140. package/dist/i18n/messages/cs.gen.js +656 -0
  141. package/dist/i18n/messages/de.gen.d.ts +5 -0
  142. package/dist/i18n/messages/de.gen.js +656 -0
  143. package/dist/i18n/messages/en.gen.d.ts +5 -0
  144. package/dist/i18n/messages/en.gen.js +656 -0
  145. package/dist/i18n/messages/es.gen.d.ts +5 -0
  146. package/dist/i18n/messages/es.gen.js +656 -0
  147. package/dist/i18n/messages/et.gen.d.ts +5 -0
  148. package/dist/i18n/messages/et.gen.js +656 -0
  149. package/dist/i18n/messages/fr.gen.d.ts +5 -0
  150. package/dist/i18n/messages/fr.gen.js +656 -0
  151. package/dist/i18n/messages/he.gen.d.ts +5 -0
  152. package/dist/i18n/messages/he.gen.js +656 -0
  153. package/dist/i18n/messages/hi.gen.d.ts +5 -0
  154. package/dist/i18n/messages/hi.gen.js +656 -0
  155. package/dist/i18n/messages/hu.gen.d.ts +5 -0
  156. package/dist/i18n/messages/hu.gen.js +656 -0
  157. package/dist/i18n/messages/locales.d.ts +5 -0
  158. package/dist/i18n/messages/locales.js +22 -0
  159. package/dist/i18n/messages/lt.gen.d.ts +5 -0
  160. package/dist/i18n/messages/lt.gen.js +656 -0
  161. package/dist/i18n/messages/lv.gen.d.ts +5 -0
  162. package/dist/i18n/messages/lv.gen.js +656 -0
  163. package/dist/i18n/messages/pl.gen.d.ts +5 -0
  164. package/dist/i18n/messages/pl.gen.js +656 -0
  165. package/dist/i18n/messages/pt-BR.gen.d.ts +5 -0
  166. package/dist/i18n/messages/pt-BR.gen.js +656 -0
  167. package/dist/i18n/messages/sk.gen.d.ts +5 -0
  168. package/dist/i18n/messages/sk.gen.js +656 -0
  169. package/dist/i18n/messages/tr.gen.d.ts +5 -0
  170. package/dist/i18n/messages/tr.gen.js +656 -0
  171. package/dist/i18n/messages/zh-CN.gen.d.ts +5 -0
  172. package/dist/i18n/messages/zh-CN.gen.js +656 -0
  173. package/dist/i18n/messages.d.ts +2 -3
  174. package/dist/i18n/messages.js +1 -19
  175. package/dist/internal/acceptedBlockProjection.d.ts +12 -0
  176. package/dist/internal/acceptedBlockProjection.js +45 -0
  177. package/dist/internal/noteMarkerAttrs.d.ts +8 -0
  178. package/dist/internal/noteMarkerAttrs.js +16 -0
  179. package/dist/internal/pageBreakRunSourceDescendantIndex.js +1 -0
  180. package/dist/internal/prosemirrorAttrBoundary.d.ts +21 -0
  181. package/dist/internal/prosemirrorAttrBoundary.js +50 -0
  182. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  183. package/dist/layout-bridge/convert/footnoteLayout.js +3 -3
  184. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  185. package/dist/layout-bridge/convert/headerFooterLayout.js +1 -0
  186. package/dist/layout-bridge/convert/noteReferences.d.ts +1 -3
  187. package/dist/layout-bridge/convert/noteReferences.js +1 -6
  188. package/dist/layout-bridge/convert/paragraphRuns.js +2 -4
  189. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -2
  190. package/dist/layout-bridge/convert/toFlowBlocks.js +2 -2
  191. package/dist/managers/DocumentLoaderManager.d.ts +1 -0
  192. package/dist/managers/DocumentLoaderManager.js +9 -1
  193. package/dist/markdown/escape.d.ts +3 -1
  194. package/dist/markdown/escape.js +9 -2
  195. package/dist/markdown/renderBlock.js +20 -121
  196. package/dist/markdown/renderParagraph.js +13 -15
  197. package/dist/markdown/renderRuns.d.ts +7 -1
  198. package/dist/markdown/renderRuns.js +35 -15
  199. package/dist/markdown/renderTable.js +2 -0
  200. package/dist/markdown/types.d.ts +3 -9
  201. package/dist/prosemirror/attrs/index.d.ts +2 -12
  202. package/dist/prosemirror/attrs/index.js +22 -48
  203. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +2 -1
  204. package/dist/prosemirror/canonicalCommands.d.ts +121 -0
  205. package/dist/prosemirror/canonicalCommands.js +35 -0
  206. package/dist/prosemirror/canonicalSelectionRange.d.ts +9 -0
  207. package/dist/prosemirror/canonicalSelectionRange.js +15 -0
  208. package/dist/prosemirror/clipboardIntent.d.ts +7 -0
  209. package/dist/prosemirror/clipboardIntent.js +9 -0
  210. package/dist/prosemirror/commands/pageBreak.js +15 -1
  211. package/dist/prosemirror/commands/pastePlainText.js +2 -1
  212. package/dist/prosemirror/commentReferenceAttrs.d.ts +2 -1
  213. package/dist/prosemirror/conversion/fromProseDoc.js +91 -19
  214. package/dist/prosemirror/conversion/hyphenTextCarriers.d.ts +8 -0
  215. package/dist/prosemirror/conversion/hyphenTextCarriers.js +8 -0
  216. package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +6 -0
  217. package/dist/prosemirror/conversion/listRenderingDefinition.js +97 -0
  218. package/dist/prosemirror/conversion/toProseDoc.d.ts +11 -4
  219. package/dist/prosemirror/conversion/toProseDoc.js +55 -14
  220. package/dist/prosemirror/executeEditorCommand.d.ts +11 -0
  221. package/dist/prosemirror/executeEditorCommand.js +26 -0
  222. package/dist/prosemirror/extensions/StarterKit.js +2 -0
  223. package/dist/prosemirror/extensions/core/ParagraphExtension.js +88 -48
  224. package/dist/prosemirror/extensions/features/ListExtension.js +18 -5
  225. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +5 -2
  226. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +13 -1
  227. package/dist/prosemirror/extensions/marks/HyperlinkExtension.js +56 -28
  228. package/dist/prosemirror/extensions/marks/TextColorExtension.js +3 -2
  229. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
  230. package/dist/prosemirror/extensions/marks/markUtils.js +72 -8
  231. package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.d.ts +6 -0
  232. package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.js +36 -0
  233. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +4 -2
  234. package/dist/prosemirror/insertOperations.js +2 -1
  235. package/dist/prosemirror/listMarker.d.ts +1 -0
  236. package/dist/prosemirror/listMarker.js +16 -7
  237. package/dist/prosemirror/listNumbering.js +26 -5
  238. package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
  239. package/dist/prosemirror/listRenderingAttrs.js +3 -0
  240. package/dist/prosemirror/markupViewNotes.js +3 -2
  241. package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +2 -1
  242. package/dist/prosemirror/noteReferenceReview.js +5 -3
  243. package/dist/prosemirror/paragraphPropertyCarry.d.ts +7 -1
  244. package/dist/prosemirror/paragraphPropertyCarry.js +8 -3
  245. package/dist/prosemirror/plugins/suggestionMode.js +57 -7
  246. package/dist/prosemirror/rangeAnchorAttrs.d.ts +2 -1
  247. package/dist/prosemirror/runFormattingFromMarks.d.ts +4 -1
  248. package/dist/prosemirror/runFormattingFromMarks.js +15 -1
  249. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -1
  250. package/dist/prosemirror/runFormattingInlineCarriers.js +4 -1
  251. package/dist/prosemirror/schema/marks.d.ts +2 -0
  252. package/dist/prosemirror/schema/nodes.d.ts +10 -2
  253. package/dist/prosemirror/textBoxAnchorAttrs.d.ts +2 -1
  254. package/dist/prosemirror/textInput.js +5 -1
  255. package/dist/prosemirror/trackedRevisionPath.js +2 -1
  256. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -0
  257. package/dist/prosemirror/trackedRunInlineAtoms.js +1 -0
  258. package/dist/prosemirror/validation.js +4 -0
  259. package/dist/types/canonicalCapabilities.d.ts +215 -0
  260. package/dist/types/canonicalCapabilities.js +212 -0
  261. package/dist/types/canonicalSave.d.ts +11 -0
  262. package/dist/types/canonicalSave.js +0 -0
  263. package/dist/types/content.d.ts +2 -2
  264. package/dist/types/docxSerialization.d.ts +14 -0
  265. package/dist/types/docxSerialization.js +7 -0
  266. package/dist/utils/createDocument.js +2 -2
  267. package/package.json +16 -4
@@ -10,9 +10,20 @@ import { createDocumentNumberingPlugin } from "../prosemirror/plugins/documentNu
10
10
  import { createDocumentStylesPlugin } from "../prosemirror/plugins/documentStyles.js";
11
11
  import { schema } from "../prosemirror/schema/index.js";
12
12
  import { storyListNumbering } from "../prosemirror/storyListNumbering.js";
13
- import { EditorState } from "prosemirror-state";
13
+ import { CANONICAL_GAP, usesCanonicalSession } from "../types/canonicalCapabilities.js";
14
+ import { createCanonicalStoryEditor } from "./canonicalStoryEditor.js";
15
+ import { OP_STORIES } from "@stll/docx-core/ops";
16
+ import { EditorState, TextSelection } from "prosemirror-state";
14
17
  import { EditorView } from "prosemirror-view";
15
18
  //#region src/controller/headerFooterEditorManager.ts
19
+ /**
20
+ * Framework-neutral lifecycle owner for persistent header/footer EditorViews.
21
+ *
22
+ * Each distinct relationship id owns one off-screen ProseMirror view. Painted
23
+ * header/footer instances that share that relationship therefore share live
24
+ * editor state, and adapters only decide when to synchronize or destroy the
25
+ * manager.
26
+ */
16
27
  const createEditorView = (mountNode, props) => new EditorView(mountNode, props);
17
28
  const DETACHED_WATERMARK_HOST = Symbol.for("stll.detachedWatermarkHost");
18
29
  const headerFooterToProseDocWithDetachedWatermarkHost = (headerFooter, options) => {
@@ -27,6 +38,7 @@ const buildInitialState = (headerFooter, styles, theme, numbering, manager) => {
27
38
  const proseDocOptions = {};
28
39
  if (styles) proseDocOptions.styles = styles;
29
40
  if (theme !== void 0) proseDocOptions.theme = theme;
41
+ if (numbering != null) proseDocOptions.numbering = numbering;
30
42
  const document = headerFooter.watermarkBlockIndex === void 0 ? headerFooterToProseDoc(headerFooter.content, proseDocOptions) : headerFooterToProseDocWithDetachedWatermarkHost(headerFooter, proseDocOptions);
31
43
  return ensureBaseDirectionInState(ensureParaIdsInState(EditorState.create({
32
44
  doc: document,
@@ -76,7 +88,8 @@ const createHeaderFooterEditorManager = (deps) => {
76
88
  const sync = () => {
77
89
  const host = deps.getHost();
78
90
  if (!host) return;
79
- const document = deps.getDocument();
91
+ if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.secondaryStories) && !deps.getCanonicalApi?.()?.getCanonicalStoryProjection(OP_STORIES.MAIN)) return;
92
+ const document = usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.secondaryStories) ? deps.getCanonicalApi?.()?.getCanonicalDocument() ?? deps.getDocument() : deps.getDocument();
80
93
  const styles = deps.getStyles();
81
94
  const theme = deps.getTheme();
82
95
  const numbering = document?.package.numbering;
@@ -92,6 +105,30 @@ const createHeaderFooterEditorManager = (deps) => {
92
105
  const existing = mounted.get(part.rId);
93
106
  if (existing) {
94
107
  if (existing.mountNode.parentElement !== host) host.append(existing.mountNode);
108
+ if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.secondaryStories)) {
109
+ const projected = deps.getCanonicalApi?.()?.getCanonicalStoryProjection({
110
+ kind: part.kind,
111
+ rId: part.rId
112
+ });
113
+ if (projected && !existing.view.state.doc.eq(projected)) {
114
+ const transaction = existing.view.state.tr.replaceWith(0, existing.view.state.doc.content.size, projected.content);
115
+ const restored = deps.getCanonicalApi?.()?.getCanonicalStorySelection({
116
+ kind: part.kind,
117
+ rId: part.rId
118
+ });
119
+ const anchor = Math.min(existing.view.state.selection.anchor, projected.content.size);
120
+ transaction.setSelection(restored ? TextSelection.create(transaction.doc, restored.anchor, restored.head) : TextSelection.near(transaction.doc.resolve(anchor)));
121
+ transaction.setMeta("addToHistory", false);
122
+ existing.view.updateState(existing.view.state.apply(transaction));
123
+ }
124
+ existing.appliedHeaderFooter = headerFooter;
125
+ existing.appliedContent = headerFooter.content;
126
+ existing.appliedStyles = styles;
127
+ existing.appliedTheme = theme;
128
+ existing.appliedNumbering = numbering;
129
+ existing.dirty = false;
130
+ continue;
131
+ }
95
132
  const contentIsCurrent = existing.appliedHeaderFooter === headerFooter && existing.appliedContent === headerFooter.content;
96
133
  const contextIsCurrent = existing.appliedStyles === styles && existing.appliedTheme === theme && existing.appliedNumbering === numbering;
97
134
  if (contentIsCurrent && contextIsCurrent) continue;
@@ -111,9 +148,40 @@ const createHeaderFooterEditorManager = (deps) => {
111
148
  mountNode.dataset["hfRId"] = part.rId;
112
149
  mountNode.dataset["hfKind"] = part.kind;
113
150
  host.append(mountNode);
151
+ const canonical = createCanonicalStoryEditor({
152
+ story: {
153
+ kind: part.kind,
154
+ rId: part.rId
155
+ },
156
+ getView: () => view,
157
+ getApi: () => deps.getCanonicalApi?.() ?? null,
158
+ enabled: () => usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.secondaryStories),
159
+ onRefusal: deps.onSessionRefusal,
160
+ onSelectionChange: () => deps.onTransaction?.({
161
+ kind: part.kind,
162
+ rId: part.rId,
163
+ view,
164
+ docChanged: false,
165
+ selectionChanged: true
166
+ })
167
+ });
168
+ const canonicalProjection = usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.secondaryStories) ? deps.getCanonicalApi?.()?.getCanonicalStoryProjection({
169
+ kind: part.kind,
170
+ rId: part.rId
171
+ }) : null;
172
+ if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.secondaryStories) && !canonicalProjection) {
173
+ manager.destroy();
174
+ mountNode.remove();
175
+ continue;
176
+ }
114
177
  const view = (deps.createView ?? createEditorView)(mountNode, {
115
- state: buildInitialState(headerFooter, styles, theme, numbering, manager),
178
+ ...canonical.props,
179
+ state: canonicalProjection ? EditorState.create({
180
+ doc: canonicalProjection,
181
+ plugins: [createDocumentStylesPlugin(styles), createDocumentNumberingPlugin(numbering)]
182
+ }) : buildInitialState(headerFooter, styles, theme, numbering, manager),
116
183
  dispatchTransaction(transaction) {
184
+ if (canonical.dispatch(transaction)) return;
117
185
  const nextState = view.state.apply(transaction);
118
186
  view.updateState(nextState);
119
187
  const mountedPart = mounted.get(part.rId);
@@ -150,6 +218,7 @@ const createHeaderFooterEditorManager = (deps) => {
150
218
  rId
151
219
  })),
152
220
  snapshotDocument: (document) => {
221
+ if (usesCanonicalSession(deps.getExperimentalSession?.(), CANONICAL_GAP.secondaryStories)) return deps.getCanonicalApi?.()?.getCanonicalDocument() ?? document;
153
222
  let headers = document.package.headers;
154
223
  let footers = document.package.footers;
155
224
  let headersChanged = false;
@@ -1,7 +1,24 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
+ import { FolioDocumentOperationResult, FolioDocumentOperationUndoHandle, FolioDocumentOperationUndoResult } from "../document-operations.js";
3
+ import { CanonicalSaveSnapshot } from "../types/canonicalSave.js";
4
+ import { CanonicalSessionMode } from "./canonicalSession.js";
5
+ import { createCanonicalInputBoundary } from "./canonicalInput.js";
6
+ import { CanonicalPublicOperationOptions } from "./canonicalPublicOperations.js";
7
+ import { Node } from "prosemirror-model";
2
8
  import { Command, EditorState, Transaction } from "prosemirror-state";
3
9
  import { EditorView } from "prosemirror-view";
10
+ import { DocumentOp, OpStory } from "@stll/docx-core/ops";
4
11
  //#region src/controller/hiddenEditorApi.d.ts
12
+ type CanonicalStoryHistoryOptions = {
13
+ view: EditorView;
14
+ story: OpStory;
15
+ direction: "undo" | "redo";
16
+ };
17
+ type CanonicalStoryTextOptions = {
18
+ view: EditorView;
19
+ story: OpStory;
20
+ intent: Parameters<Parameters<typeof createCanonicalInputBoundary>[0]["replace"]>[0];
21
+ };
5
22
  type HiddenEditorApi = {
6
23
  /** Request the off-screen EditorView (idempotent; creates it when possible). */
7
24
  ensureView: () => void;
@@ -13,6 +30,26 @@ type HiddenEditorApi = {
13
30
  getView: () => EditorView | null;
14
31
  /** Get the current Document from PM state */
15
32
  getDocument: () => document_d_exports.Document | null;
33
+ /** Canonical snapshot, or null in the default session. */
34
+ getCanonicalDocument: () => document_d_exports.Document | null;
35
+ captureCanonicalSave: () => CanonicalSaveSnapshot | null;
36
+ /** A save cannot acknowledge newer edits or an unfinished composition. */
37
+ isCanonicalSaveCurrent: (version: number) => boolean;
38
+ /** Set the explicit mode for an active canonical session. */
39
+ setCanonicalMode: (mode: CanonicalSessionMode) => boolean;
40
+ /** Resolve canonical revisions as one batch and journal its exact inverse. */
41
+ resolveCanonicalRevisions: (revisionIds: readonly number[], resolution: "accept" | "reject") => boolean;
42
+ updateCanonicalInputLifecycle: (action: "beginComposition" | "endComposition" | "breakUndoGroup") => boolean;
43
+ applyCanonicalStoryHistory: (options: CanonicalStoryHistoryOptions) => boolean;
44
+ applyCanonicalOperations: (ops: readonly DocumentOp[]) => boolean;
45
+ getCanonicalStorySelection: (story: OpStory) => {
46
+ anchor: number;
47
+ head: number;
48
+ } | null;
49
+ getCanonicalStoryProjection: (story: OpStory) => Node | null;
50
+ replaceCanonicalStoryText: (options: CanonicalStoryTextOptions) => boolean;
51
+ applyCanonicalDocumentOperations: (options: CanonicalPublicOperationOptions) => FolioDocumentOperationResult | null;
52
+ undoCanonicalDocumentOperations: (handle: FolioDocumentOperationUndoHandle) => FolioDocumentOperationUndoResult | null;
16
53
  /** Focus the hidden editor */
17
54
  focus: () => void;
18
55
  /** Blur the hidden editor */
@@ -43,6 +80,14 @@ type HiddenEditorApi = {
43
80
  type HiddenEditorApiDeps = {
44
81
  getView: () => EditorView | null;
45
82
  getDocumentContext: () => document_d_exports.Document | null;
83
+ getCanonicalDocument?: () => document_d_exports.Document | null;
84
+ captureCanonicalSave?: HiddenEditorApi["captureCanonicalSave"];
85
+ isCanonicalSaveCurrent?: HiddenEditorApi["isCanonicalSaveCurrent"];
86
+ setCanonicalMode?: HiddenEditorApi["setCanonicalMode"];
87
+ resolveCanonicalRevisions?: HiddenEditorApi["resolveCanonicalRevisions"];
88
+ executeCanonicalCommand?: (command: Command) => boolean | undefined;
89
+ getCanonicalHistory?: () => Pick<HiddenEditorApi, "undo" | "redo" | "canUndo" | "canRedo"> | null;
90
+ canonicalOperations?: Pick<HiddenEditorApi, "updateCanonicalInputLifecycle" | "applyCanonicalOperations" | "getCanonicalStoryProjection" | "replaceCanonicalStoryText" | "applyCanonicalStoryHistory" | "getCanonicalStorySelection" | "applyCanonicalDocumentOperations" | "undoCanonicalDocumentOperations">;
46
91
  isDestroying: () => boolean;
47
92
  ensureView: () => void;
48
93
  isViewRequested: () => boolean;
@@ -1,17 +1,10 @@
1
+ import { cloneDocumentWithParagraphPropertySources } from "../docx/paragraphPropertySource.js";
1
2
  import { fromProseDoc } from "../prosemirror/conversion/fromProseDoc.js";
2
3
  import { CellSelection } from "prosemirror-tables";
3
4
  import { NodeSelection, Selection, TextSelection } from "prosemirror-state";
4
5
  import { redo, undo } from "prosemirror-history";
5
6
  //#region src/controller/hiddenEditorApi.ts
6
7
  /**
7
- * Hidden-editor imperative API
8
- *
9
- * Framework-agnostic method surface for the off-screen ProseMirror editor.
10
- * Operates on an injected view accessor plus the document context and
11
- * destruction guard, so the same imperative handle can be driven from the
12
- * React component or a headless controller without depending on React.
13
- */
14
- /**
15
8
  * Convert PM state to Document
16
9
  */
17
10
  const stateToDocument = (state, originalDoc) => {
@@ -39,11 +32,29 @@ const createHiddenEditorApi = (deps) => {
39
32
  isViewRequested: deps.isViewRequested,
40
33
  getState: () => deps.getView()?.state ?? null,
41
34
  getView: () => deps.getView() ?? null,
35
+ setCanonicalMode: (mode) => !deps.isDestroying() && (deps.setCanonicalMode?.(mode) ?? false),
36
+ resolveCanonicalRevisions: (revisionIds, resolution) => !deps.isDestroying() && (deps.resolveCanonicalRevisions?.(revisionIds, resolution) ?? false),
37
+ captureCanonicalSave: () => deps.captureCanonicalSave?.() ?? null,
38
+ isCanonicalSaveCurrent: (version) => deps.isCanonicalSaveCurrent?.(version) ?? false,
39
+ getCanonicalDocument: () => {
40
+ const canonical = deps.getCanonicalDocument?.();
41
+ return canonical ? cloneDocumentWithParagraphPropertySources(canonical) : null;
42
+ },
42
43
  getDocument: () => {
44
+ const canonical = deps.getCanonicalDocument?.();
45
+ if (canonical) return cloneDocumentWithParagraphPropertySources(canonical);
43
46
  const view = deps.getView();
44
47
  if (!view) return null;
45
48
  return stateToDocument(view.state, deps.getDocumentContext());
46
49
  },
50
+ updateCanonicalInputLifecycle: (action) => deps.canonicalOperations?.updateCanonicalInputLifecycle(action) ?? false,
51
+ applyCanonicalStoryHistory: (options) => deps.canonicalOperations?.applyCanonicalStoryHistory(options) ?? false,
52
+ applyCanonicalOperations: (ops) => deps.canonicalOperations?.applyCanonicalOperations(ops) ?? false,
53
+ getCanonicalStorySelection: (story) => deps.canonicalOperations?.getCanonicalStorySelection(story) ?? null,
54
+ getCanonicalStoryProjection: (story) => deps.canonicalOperations?.getCanonicalStoryProjection(story) ?? null,
55
+ replaceCanonicalStoryText: (options) => deps.canonicalOperations?.replaceCanonicalStoryText(options) ?? false,
56
+ applyCanonicalDocumentOperations: (options) => deps.canonicalOperations?.applyCanonicalDocumentOperations(options) ?? null,
57
+ undoCanonicalDocumentOperations: (handle) => deps.canonicalOperations?.undoCanonicalDocumentOperations(handle) ?? null,
47
58
  focus: () => {
48
59
  const view = deps.getView();
49
60
  if (!view || view.hasFocus()) return;
@@ -62,24 +73,34 @@ const createHiddenEditorApi = (deps) => {
62
73
  executeCommand: (command) => {
63
74
  const view = deps.getView();
64
75
  if (!view) return false;
76
+ const canonical = deps.executeCanonicalCommand?.(command);
77
+ if (canonical !== void 0) return canonical;
65
78
  return command(view.state, (tr) => dispatchTr(view, tr), view);
66
79
  },
67
80
  undo: () => {
81
+ const canonical = deps.getCanonicalHistory?.();
82
+ if (canonical) return canonical.undo();
68
83
  const view = deps.getView();
69
84
  if (!view) return false;
70
85
  return undo(view.state, (tr) => dispatchTr(view, tr));
71
86
  },
72
87
  redo: () => {
88
+ const canonical = deps.getCanonicalHistory?.();
89
+ if (canonical) return canonical.redo();
73
90
  const view = deps.getView();
74
91
  if (!view) return false;
75
92
  return redo(view.state, (tr) => dispatchTr(view, tr));
76
93
  },
77
94
  canUndo: () => {
95
+ const canonical = deps.getCanonicalHistory?.();
96
+ if (canonical) return canonical.canUndo();
78
97
  const view = deps.getView();
79
98
  if (!view) return false;
80
99
  return undo(view.state);
81
100
  },
82
101
  canRedo: () => {
102
+ const canonical = deps.getCanonicalHistory?.();
103
+ if (canonical) return canonical.canRedo();
83
104
  const view = deps.getView();
84
105
  if (!view) return false;
85
106
  return redo(view.state);
@@ -1,14 +1,21 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
+ import { CanonicalGap } from "../types/canonicalCapabilities.js";
3
+ import { HiddenEditorApi } from "./hiddenEditorApi.js";
2
4
  import { HiddenEditorStateReason } from "../layout-engine/layoutInstrumentation.js";
3
5
  import { ExtensionManager } from "../prosemirror/extensions/ExtensionManager.js";
4
6
  import { RemoteSelection } from "../types/remote-selection.js";
5
- import { HiddenEditorApi } from "./hiddenEditorApi.js";
7
+ import { EditorMode } from "../managers/EditorModeManager.js";
6
8
  import { EditorState, Plugin, Transaction } from "prosemirror-state";
7
9
  import { EditorView } from "prosemirror-view";
8
10
  import * as Yjs from "yjs";
9
11
  import { XmlFragment } from "yjs";
10
12
  import * as YProseMirror from "y-prosemirror";
11
13
  //#region src/controller/hiddenEditorManager.d.ts
14
+ declare const CanonicalSessionRefusalError_base: import("better-result").TaggedErrorClass<"CanonicalSessionRefusalError">;
15
+ declare class CanonicalSessionRefusalError extends CanonicalSessionRefusalError_base<{
16
+ gap: CanonicalGap;
17
+ message: string;
18
+ }> {}
12
19
  type YProseMirrorModule = typeof YProseMirror;
13
20
  type YjsModule = typeof Yjs;
14
21
  type CollaborationModules = {
@@ -55,6 +62,10 @@ type HiddenEditorManagerDeps = {
55
62
  getCollaborationModules: () => CollaborationModules | null;
56
63
  getPrecomputedInitialState: () => EditorState | null | undefined;
57
64
  getReadOnly: () => boolean;
65
+ getExperimentalSession?: () => "canonical" | undefined;
66
+ getEditingMode?: () => EditorMode;
67
+ getSuggestionAuthor?: () => string;
68
+ onSessionRefusal?: (reason: string, gap: CanonicalGap) => void;
58
69
  /**
59
70
  * Identity of the loaded document as tracked by the adapter's loader: the
60
71
  * same value across internal edits (so typing does not trigger an external
@@ -102,4 +113,4 @@ type HiddenEditorManager = {
102
113
  };
103
114
  declare const createHiddenEditorManager: (deps: HiddenEditorManagerDeps) => HiddenEditorManager;
104
115
  //#endregion
105
- export { CollaborationModules, CreateHiddenEditorStateOptions, HiddenEditorManager, HiddenEditorManagerDeps, HiddenEditorTransactionUpdate, HiddenProseMirrorCollaboration, HiddenProseMirrorRemoteSelection, collectRemoteSelections, createHiddenEditorClipboardHandlers, createHiddenEditorManager, createHiddenEditorState };
116
+ export { CanonicalSessionRefusalError, CollaborationModules, CreateHiddenEditorStateOptions, HiddenEditorManager, HiddenEditorManagerDeps, HiddenEditorTransactionUpdate, HiddenProseMirrorCollaboration, HiddenProseMirrorRemoteSelection, collectRemoteSelections, createHiddenEditorClipboardHandlers, createHiddenEditorManager, createHiddenEditorState };