@stll/folio-core 0.52.0 → 0.53.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 (307) hide show
  1. package/README.md +23 -0
  2. package/dist/ai-edits/apply.d.ts +26 -1
  3. package/dist/ai-edits/apply.js +1519 -105
  4. package/dist/ai-edits/batch-claims.d.ts +130 -0
  5. package/dist/ai-edits/batch-claims.js +244 -0
  6. package/dist/ai-edits/blockRange.js +9 -3
  7. package/dist/ai-edits/character-boundaries.d.ts +43 -0
  8. package/dist/ai-edits/character-boundaries.js +95 -0
  9. package/dist/ai-edits/clean-text.d.ts +33 -3
  10. package/dist/ai-edits/clean-text.js +52 -6
  11. package/dist/ai-edits/comment-lifecycle.d.ts +18 -0
  12. package/dist/ai-edits/comment-lifecycle.js +52 -0
  13. package/dist/ai-edits/headless.d.ts +71 -7
  14. package/dist/ai-edits/headless.js +381 -41
  15. package/dist/ai-edits/index.d.ts +2 -1
  16. package/dist/ai-edits/index.js +2 -1
  17. package/dist/ai-edits/minimal-replacement.d.ts +21 -6
  18. package/dist/ai-edits/minimal-replacement.js +134 -15
  19. package/dist/ai-edits/newListNumbering.d.ts +23 -0
  20. package/dist/ai-edits/newListNumbering.js +94 -0
  21. package/dist/ai-edits/note-references.d.ts +96 -0
  22. package/dist/ai-edits/note-references.js +139 -0
  23. package/dist/ai-edits/pending-suggestions.d.ts +79 -0
  24. package/dist/ai-edits/pending-suggestions.js +306 -0
  25. package/dist/ai-edits/read.d.ts +1 -1
  26. package/dist/ai-edits/read.js +56 -43
  27. package/dist/ai-edits/result-validation.d.ts +29 -0
  28. package/dist/ai-edits/result-validation.js +164 -0
  29. package/dist/ai-edits/snapshot.d.ts +36 -3
  30. package/dist/ai-edits/snapshot.js +177 -23
  31. package/dist/ai-edits/table-cell-mutations.d.ts +1 -1
  32. package/dist/ai-edits/table-cell-mutations.js +4 -1
  33. package/dist/ai-edits/table-geometry.d.ts +1 -1
  34. package/dist/ai-edits/table-row-column-mutations.d.ts +38 -16
  35. package/dist/ai-edits/table-row-column-mutations.js +61 -26
  36. package/dist/ai-edits/types.d.ts +155 -16
  37. package/dist/compare/compare.d.ts +1 -1
  38. package/dist/compare/compare.js +65 -16
  39. package/dist/compare/content-alignment.js +13 -2
  40. package/dist/compare/content-types.d.ts +7 -0
  41. package/dist/compare/content.d.ts +4 -1
  42. package/dist/compare/content.js +6 -1
  43. package/dist/compare/formatting.js +2 -1
  44. package/dist/compare/inline-atoms.d.ts +21 -4
  45. package/dist/compare/inline-atoms.js +138 -16
  46. package/dist/compare/plan.js +10 -5
  47. package/dist/compare/scenario.js +14 -3
  48. package/dist/compare/section-boundary-properties.js +1 -1
  49. package/dist/compare/types.d.ts +4 -2
  50. package/dist/compare/types.js +2 -1
  51. package/dist/compare/verification.d.ts +1 -1
  52. package/dist/compare/verification.js +15 -3
  53. package/dist/controller/committedLayoutDiff.d.ts +25 -0
  54. package/dist/controller/committedLayoutDiff.js +71 -0
  55. package/dist/controller/contentControlWidgetController.d.ts +1 -1
  56. package/dist/controller/folioEditor.d.ts +1 -1
  57. package/dist/controller/fontReadiness.d.ts +70 -3
  58. package/dist/controller/fontReadiness.js +100 -10
  59. package/dist/controller/headerFooterEditorManager.js +6 -1
  60. package/dist/controller/layoutPipeline.d.ts +12 -10
  61. package/dist/controller/layoutPipeline.js +62 -9
  62. package/dist/controller/layoutRunOptions.d.ts +24 -0
  63. package/dist/controller/layoutRunOptions.js +17 -0
  64. package/dist/controller/layoutScheduler.d.ts +19 -14
  65. package/dist/controller/layoutScheduler.js +15 -12
  66. package/dist/controller/layoutSession.d.ts +26 -2
  67. package/dist/controller/layoutSession.js +1 -1
  68. package/dist/controller/noteEditorManager.js +8 -3
  69. package/dist/document-operations.d.ts +11 -2
  70. package/dist/document-operations.js +230 -21
  71. package/dist/docx/altChunk.d.ts +8 -0
  72. package/dist/docx/altChunk.js +17 -0
  73. package/dist/docx/attributeRemainder.d.ts +1 -1
  74. package/dist/docx/blockContentParser.d.ts +64 -1
  75. package/dist/docx/blockContentParser.js +17 -4
  76. package/dist/docx/blockCustomXmlShell.d.ts +7 -0
  77. package/dist/docx/blockCustomXmlShell.js +14 -0
  78. package/dist/docx/blockPlainText.js +7 -0
  79. package/dist/docx/commentAnchorIndex.js +1 -1
  80. package/dist/docx/commentRangeIntegrity.js +8 -3
  81. package/dist/docx/commentReferenceNormalization.js +1 -1
  82. package/dist/docx/commentReplyMarkers.js +20 -1
  83. package/dist/docx/compatibility.d.ts +1 -1
  84. package/dist/docx/compatibility.js +34 -13
  85. package/dist/docx/containerChildren.gen.d.ts +1 -1
  86. package/dist/docx/containerChildren.gen.js +1 -0
  87. package/dist/docx/documentParser.js +12 -12
  88. package/dist/docx/drawingIdNormalization.d.ts +3 -1
  89. package/dist/docx/drawingIdNormalization.js +6 -1
  90. package/dist/docx/ensureParaIds.js +119 -97
  91. package/dist/docx/footnoteParser.js +8 -4
  92. package/dist/docx/headerFooterParser.js +3 -3
  93. package/dist/docx/headerFooterReferenceNormalization.d.ts +20 -1
  94. package/dist/docx/headerFooterReferenceNormalization.js +52 -27
  95. package/dist/docx/hyperlinkParser.d.ts +1 -1
  96. package/dist/docx/index.d.ts +1 -1
  97. package/dist/docx/listNumberingInstances.d.ts +59 -0
  98. package/dist/docx/listNumberingInstances.js +249 -0
  99. package/dist/docx/normalizeBaseDirection.js +2 -1
  100. package/dist/docx/opaqueCarrier.d.ts +7 -0
  101. package/dist/docx/opaqueCarrier.js +38 -0
  102. package/dist/docx/packageParts.js +4 -1
  103. package/dist/docx/paragraphParser.js +91 -24
  104. package/dist/docx/paragraphPropertySource.d.ts +4 -2
  105. package/dist/docx/paragraphPropertySource.js +7 -1
  106. package/dist/docx/paragraphTraversal.js +1 -0
  107. package/dist/docx/parseWarningMessage.js +4 -1
  108. package/dist/docx/parser.js +173 -20
  109. package/dist/docx/rezip.js +27 -5
  110. package/dist/docx/sdtProperties.js +1 -1
  111. package/dist/docx/sdtPropertiesPatch.js +3 -0
  112. package/dist/docx/selectiveSave.js +16 -9
  113. package/dist/docx/selectiveXmlPatch.js +106 -37
  114. package/dist/docx/serializer/blockCustomXmlSerializer.d.ts +5 -0
  115. package/dist/docx/serializer/blockCustomXmlSerializer.js +4 -0
  116. package/dist/docx/serializer/documentSerializer.js +2 -0
  117. package/dist/docx/serializer/headerFooterSerializer.js +2 -0
  118. package/dist/docx/serializer/noteSerializer.js +3 -1
  119. package/dist/docx/serializer/paragraphSerializer.js +33 -9
  120. package/dist/docx/serializer/tableSerializer.js +25 -38
  121. package/dist/docx/server/createBilingualDocument.js +3 -3
  122. package/dist/docx/tableParser.d.ts +157 -1
  123. package/dist/docx/tableParser.js +89 -10
  124. package/dist/docx/textBoxParser.js +1 -1
  125. package/dist/docx/unzip.d.ts +2 -1
  126. package/dist/docx/unzip.js +1 -1
  127. package/dist/docx/wordprocessingPrefixes.d.ts +78 -0
  128. package/dist/docx/wordprocessingPrefixes.js +286 -0
  129. package/dist/i18n/messages/catalogs.gen.d.ts +136 -0
  130. package/dist/i18n/messages/catalogs.gen.js +153 -17
  131. package/dist/i18n/messages/messages.gen.d.ts +8 -0
  132. package/dist/internal/compare/inline-presentation.d.ts +2 -1
  133. package/dist/internal/compare/inline-presentation.js +11 -10
  134. package/dist/internal/headlessRevisionResolutionGuard.d.ts +2 -8
  135. package/dist/internal/headlessRevisionResolutionGuard.js +2 -11
  136. package/dist/internal/indexedPositionMap.d.ts +11 -0
  137. package/dist/internal/indexedPositionMap.js +42 -0
  138. package/dist/internal/pageBreakRunSourceDescendantIndex.js +2 -1
  139. package/dist/internal/revisionResolutionEdits.d.ts +13 -0
  140. package/dist/internal/revisionResolutionEdits.js +19 -0
  141. package/dist/internal/revisionResolutionInline.d.ts +24 -0
  142. package/dist/internal/{headlessRevisionResolution.js → revisionResolutionInline.js} +61 -43
  143. package/dist/internal/revisionResolutionStep.d.ts +34 -0
  144. package/dist/internal/revisionResolutionStep.js +282 -0
  145. package/dist/internal/revisionResolutionTracking.d.ts +11 -0
  146. package/dist/internal/revisionResolutionTracking.js +124 -0
  147. package/dist/internal/wholeStoryRevisionResolution.d.ts +56 -0
  148. package/dist/internal/wholeStoryRevisionResolution.js +530 -0
  149. package/dist/layout-bridge/convert/markupViewFlow.d.ts +20 -0
  150. package/dist/layout-bridge/convert/markupViewFlow.js +123 -0
  151. package/dist/layout-bridge/convert/tableConversion.js +1 -1
  152. package/dist/layout-bridge/convert/toFlowBlocks.js +10 -1
  153. package/dist/layout-engine/layoutInstrumentation.d.ts +9 -1
  154. package/dist/layout-engine/layoutInstrumentation.js +4 -1
  155. package/dist/layout-engine/measure/cache.d.ts +18 -1
  156. package/dist/layout-engine/measure/cache.js +31 -1
  157. package/dist/layout-engine/measure/font-metrics.worker.js +3 -7
  158. package/dist/layout-engine/measure/measureContainer.js +7 -47
  159. package/dist/layout-engine/measure/measureHelpers.d.ts +6 -1
  160. package/dist/layout-engine/measure/measureHelpers.js +22 -2
  161. package/dist/layout-engine/measure/measureWorker.js +2 -3
  162. package/dist/layout-engine/measure/measureWorkerProtocol.d.ts +6 -7
  163. package/dist/layout-engine/measure/measureWorkerProtocol.js +1 -2
  164. package/dist/layout-engine/types.d.ts +6 -0
  165. package/dist/layout-painter/renderPage.js +1 -0
  166. package/dist/layout-painter/renderParagraph.js +1 -1
  167. package/dist/managers/ContextMenuManager.js +5 -2
  168. package/dist/managers/types.d.ts +3 -0
  169. package/dist/markdown/fromMarkdown.js +2 -1
  170. package/dist/markdown/internals.d.ts +11 -1
  171. package/dist/markdown/internals.js +24 -3
  172. package/dist/markdown/renderBlock.js +39 -9
  173. package/dist/markdown/renderParagraph.d.ts +13 -1
  174. package/dist/markdown/renderParagraph.js +85 -38
  175. package/dist/markdown/renderRuns.js +3 -10
  176. package/dist/markdown/renderTable.js +24 -12
  177. package/dist/markdown/trailers.js +2 -2
  178. package/dist/markdown/types.d.ts +29 -7
  179. package/dist/paged-layout/incrementalMeasure.d.ts +1 -2
  180. package/dist/paged-layout/incrementalMeasure.js +1 -9
  181. package/dist/paged-layout/transactionDirtyRange.d.ts +1 -3
  182. package/dist/paged-layout/transactionDirtyRange.js +29 -41
  183. package/dist/panel-layout.d.ts +83 -0
  184. package/dist/panel-layout.js +96 -0
  185. package/dist/prosemirror/anchoredTextBoxes.d.ts +37 -0
  186. package/dist/prosemirror/anchoredTextBoxes.js +156 -0
  187. package/dist/prosemirror/attrs/index.d.ts +6 -2
  188. package/dist/prosemirror/attrs/index.js +172 -1
  189. package/dist/prosemirror/commands/comments.d.ts +7 -8
  190. package/dist/prosemirror/commands/comments.js +241 -207
  191. package/dist/prosemirror/commands/contentControls.d.ts +1 -1
  192. package/dist/prosemirror/commands/formatPainter.d.ts +1 -1
  193. package/dist/prosemirror/commands/formatting.d.ts +1 -1
  194. package/dist/prosemirror/commands/index.d.ts +2 -2
  195. package/dist/prosemirror/commands/index.js +2 -2
  196. package/dist/prosemirror/commands/paragraph.d.ts +7 -1
  197. package/dist/prosemirror/commands/paragraph.js +9 -1
  198. package/dist/prosemirror/commands/paragraphBookmarkJoin.d.ts +13 -0
  199. package/dist/prosemirror/commands/paragraphBookmarkJoin.js +22 -0
  200. package/dist/prosemirror/commands/pastePlainText.d.ts +1 -1
  201. package/dist/prosemirror/commands/resolveAllTableChanges.d.ts +40 -0
  202. package/dist/prosemirror/commands/resolveAllTableChanges.js +615 -0
  203. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.d.ts +15 -0
  204. package/dist/prosemirror/commands/resolveNodePropertyChangeAttrs.js +46 -0
  205. package/dist/prosemirror/commands/resolveParagraphProperties.d.ts +16 -0
  206. package/dist/prosemirror/commands/resolveParagraphProperties.js +59 -0
  207. package/dist/prosemirror/commands/sectionBreak.js +2 -1
  208. package/dist/prosemirror/commands/tableCellMergeResolution.d.ts +8 -2
  209. package/dist/prosemirror/commands/tableCellMergeResolution.js +1 -1
  210. package/dist/prosemirror/contentControlRevisions.d.ts +1 -1
  211. package/dist/prosemirror/conversion/fromProseDoc.js +181 -31
  212. package/dist/prosemirror/conversion/toProseDoc.js +39 -4
  213. package/dist/prosemirror/emptyFieldResultRuns.d.ts +18 -0
  214. package/dist/prosemirror/emptyFieldResultRuns.js +33 -0
  215. package/dist/prosemirror/extensions/ExtensionManager.d.ts +1 -1
  216. package/dist/prosemirror/extensions/ExtensionManager.js +3 -1
  217. package/dist/prosemirror/extensions/StarterKit.js +3 -1
  218. package/dist/prosemirror/extensions/core/DocExtension.js +1 -1
  219. package/dist/prosemirror/extensions/core/ParagraphExtension.js +12 -0
  220. package/dist/prosemirror/extensions/features/BaseKeymapExtension.js +3 -0
  221. package/dist/prosemirror/extensions/features/ListExtension.js +161 -123
  222. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.d.ts +19 -2
  223. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +33 -20
  224. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +31 -2
  225. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +270 -99
  226. package/dist/prosemirror/extensions/features/PasteCleanupExtension.js +3 -2
  227. package/dist/prosemirror/extensions/features/pasteCleanup.js +2 -1
  228. package/dist/prosemirror/extensions/features/pastedHtmlLists.d.ts +12 -0
  229. package/dist/prosemirror/extensions/features/pastedHtmlLists.js +126 -0
  230. package/dist/prosemirror/extensions/marks/FootnoteRefExtension.js +21 -5
  231. package/dist/prosemirror/extensions/marks/RunIdentityExtension.d.ts +21 -18
  232. package/dist/prosemirror/extensions/marks/RunIdentityExtension.js +37 -17
  233. package/dist/prosemirror/extensions/marks/markUtils.d.ts +7 -2
  234. package/dist/prosemirror/extensions/marks/markUtils.js +8 -2
  235. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.d.ts +10 -0
  236. package/dist/prosemirror/extensions/marks/noteReferenceDeletion.js +35 -0
  237. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.d.ts +6 -0
  238. package/dist/prosemirror/extensions/nodes/BlockCustomXmlExtension.js +52 -0
  239. package/dist/prosemirror/extensions/nodes/FieldExtension.d.ts +3 -3
  240. package/dist/prosemirror/extensions/nodes/FieldExtension.js +50 -15
  241. package/dist/prosemirror/extensions/nodes/PreservedBlockExtension.js +4 -1
  242. package/dist/prosemirror/extensions/nodes/TableExtension.d.ts +1 -1
  243. package/dist/prosemirror/extensions/nodes/TableExtension.js +19 -18
  244. package/dist/prosemirror/extensions/types.d.ts +4 -1
  245. package/dist/prosemirror/findReplaceSelection.js +1 -1
  246. package/dist/prosemirror/index.d.ts +3 -2
  247. package/dist/prosemirror/index.js +3 -2
  248. package/dist/prosemirror/indexedNodeLookup.d.ts +17 -0
  249. package/dist/prosemirror/indexedNodeLookup.js +103 -0
  250. package/dist/prosemirror/listAutoformatMarkers.d.ts +19 -0
  251. package/dist/prosemirror/listAutoformatMarkers.js +98 -0
  252. package/dist/prosemirror/listInstanceReferences.d.ts +12 -0
  253. package/dist/prosemirror/listInstanceReferences.js +72 -0
  254. package/dist/prosemirror/listLabels.d.ts +24 -0
  255. package/dist/prosemirror/listLabels.js +111 -0
  256. package/dist/prosemirror/listNumbering.d.ts +110 -0
  257. package/dist/prosemirror/listNumbering.js +345 -0
  258. package/dist/prosemirror/listRenderingAttrs.d.ts +11 -2
  259. package/dist/prosemirror/listRenderingAttrs.js +8 -1
  260. package/dist/prosemirror/markupViewProjection.d.ts +95 -0
  261. package/dist/prosemirror/markupViewProjection.js +83 -0
  262. package/dist/prosemirror/numberingAttr.d.ts +9 -1
  263. package/dist/prosemirror/numberingAttr.js +9 -1
  264. package/dist/prosemirror/outlineLevelAttr.js +1 -1
  265. package/dist/prosemirror/paragraphIndentation.d.ts +10 -1
  266. package/dist/prosemirror/paragraphIndentation.js +29 -7
  267. package/dist/prosemirror/paragraphMarkJoin.d.ts +19 -0
  268. package/dist/prosemirror/paragraphMarkJoin.js +24 -0
  269. package/dist/prosemirror/plugins/createDocScanPlugin.d.ts +1 -1
  270. package/dist/prosemirror/plugins/documentNumbering.d.ts +27 -1
  271. package/dist/prosemirror/plugins/documentNumbering.js +97 -11
  272. package/dist/prosemirror/plugins/documentStyles.d.ts +10 -1
  273. package/dist/prosemirror/plugins/documentStyles.js +14 -1
  274. package/dist/prosemirror/plugins/suggestionMode.d.ts +16 -2
  275. package/dist/prosemirror/plugins/suggestionMode.js +116 -52
  276. package/dist/prosemirror/plugins/templateDirectives.d.ts +1 -1
  277. package/dist/prosemirror/plugins/transactionInvariants.d.ts +32 -0
  278. package/dist/prosemirror/plugins/transactionInvariants.js +86 -0
  279. package/dist/prosemirror/positionSweep.d.ts +24 -0
  280. package/dist/prosemirror/positionSweep.js +222 -0
  281. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +1 -1
  282. package/dist/prosemirror/rejoinRunCarriers.d.ts +1 -1
  283. package/dist/prosemirror/replacedAnnotations.d.ts +33 -1
  284. package/dist/prosemirror/replacedAnnotations.js +170 -1
  285. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +1 -1
  286. package/dist/prosemirror/schema/index.d.ts +2 -2
  287. package/dist/prosemirror/schema/index.js +3 -0
  288. package/dist/prosemirror/schema/nodes.d.ts +42 -11
  289. package/dist/prosemirror/sectionMarkEdits.d.ts +20 -0
  290. package/dist/prosemirror/sectionMarkEdits.js +59 -0
  291. package/dist/prosemirror/storyListNumbering.d.ts +17 -0
  292. package/dist/prosemirror/storyListNumbering.js +102 -0
  293. package/dist/prosemirror/tableGridMutation.d.ts +48 -2
  294. package/dist/prosemirror/tableGridMutation.js +106 -1
  295. package/dist/prosemirror/validation.js +5 -1
  296. package/dist/redline.js +93 -9
  297. package/dist/render-dom/BodySelectionOverlay.d.ts +4 -1
  298. package/dist/render-dom/BodySelectionOverlay.js +3 -2
  299. package/dist/utils/findReplace.js +2 -2
  300. package/dist/utils/mergeDocumentContent.js +1 -1
  301. package/dist/utils/noteReferenceLabels.d.ts +36 -0
  302. package/dist/utils/noteReferenceLabels.js +32 -0
  303. package/dist/utils/replaceText.js +1 -1
  304. package/dist/version-comparison.d.ts +1 -0
  305. package/dist/version-comparison.js +1 -0
  306. package/package.json +3 -2
  307. package/dist/internal/headlessRevisionResolution.d.ts +0 -23
@@ -22,6 +22,7 @@ import { expectInlineWrapperMarkAttrs, expectTrackedChangeMarkAttrs } from "../a
22
22
  import { authoredTransformAttrs } from "../authoredTransformAttrs.js";
23
23
  import { setAutospacingBaseValue } from "../autospacingBase.js";
24
24
  import { withEnclosingRevision } from "../contentControlRevisions.js";
25
+ import { emptyFieldRunPropertyChanges } from "../emptyFieldResultRuns.js";
25
26
  import { planEmptyRanges } from "../emptyRangeAnchor.js";
26
27
  import { INLINE_WRAPPER_MARK_NAME } from "../extensions/marks/InlineWrapperExtension.js";
27
28
  import { textFormattingToMarks } from "../extensions/marks/markUtils.js";
@@ -197,6 +198,7 @@ const collectPairedBookmarkIds = (blocks) => {
197
198
  }
198
199
  break;
199
200
  case "blockSdt":
201
+ case "blockCustomXml":
200
202
  visitBlocks(block.content);
201
203
  break;
202
204
  case "preservedBlock": break;
@@ -250,6 +252,9 @@ function toProseDoc(document, options) {
250
252
  case "blockSdt":
251
253
  out.push(convertBlockSdt(block, convertBodyBlocks));
252
254
  break;
255
+ case "blockCustomXml":
256
+ out.push(convertBlockCustomXml(block, convertBodyBlocks));
257
+ break;
253
258
  case "preservedBlock":
254
259
  out.push(convertPreservedBlock(block));
255
260
  break;
@@ -282,7 +287,10 @@ function toProseDoc(document, options) {
282
287
  * no index and nothing has to keep one honest as the blocks around it change.
283
288
  */
284
289
  function convertPreservedBlock(block) {
285
- return schema.node("preservedBlock", { xml: block.xml });
290
+ return schema.node("preservedBlock", {
291
+ xml: block.xml,
292
+ readerText: block.readerText ?? null
293
+ });
286
294
  }
287
295
  /**
288
296
  * Carry a bookmark marker that stands between two blocks into the editor.
@@ -354,6 +362,15 @@ function convertBlockSdt(blockSdt, convertBlocks) {
354
362
  if (children.length === 0) children.push(schema.node("paragraph", {}, []));
355
363
  return schema.node("blockSdt", attrs, children);
356
364
  }
365
+ function convertBlockCustomXml(block, convertBlocks) {
366
+ const children = convertBlocks(block.content);
367
+ if (children.length === 0) children.push(schema.node("paragraph", {}, []));
368
+ return schema.node("blockCustomXml", {
369
+ openingXml: block.openingXml,
370
+ closingXml: block.closingXml,
371
+ _originallyEmpty: block.content.length === 0
372
+ }, children);
373
+ }
357
374
  /**
358
375
  * Convert a Paragraph to a ProseMirror paragraph node
359
376
  *
@@ -1072,7 +1089,7 @@ function blockHasMeaningfulContent(block) {
1072
1089
  if (block.type === "preservedBlock") return true;
1073
1090
  if (block.type === "bookmarkStart" || block.type === "bookmarkEnd") return true;
1074
1091
  if (block.type === "table") return block.rows.some((row) => row.cells.some((cell) => tableCellHasMeaningfulContent(cell)));
1075
- if (block.type === "blockSdt") return true;
1092
+ if (block.type === "blockSdt" || block.type === "blockCustomXml") return true;
1076
1093
  return block.content.some(paragraphContentHasMeaningfulContent);
1077
1094
  }
1078
1095
  function paragraphContentHasMeaningfulContent(content) {
@@ -1132,6 +1149,7 @@ function convertTable(table, styleResolver, context) {
1132
1149
  if (table.propertyChanges && table.propertyChanges.length > 0) attrs.tblPrChange = [...table.propertyChanges];
1133
1150
  if (table.bookmarks && table.bookmarks.length > 0) attrs._bookmarks = table.bookmarks;
1134
1151
  if (hasSinkChildren(table.preserved)) attrs._preserved = table.preserved;
1152
+ if (table.carrierStack?.length) attrs.carrierStack = table.carrierStack;
1135
1153
  const conditionalStyles = {};
1136
1154
  const setCS = (key, type) => {
1137
1155
  const val = resolveTableStyleConditional(styleResolver, conditionalTableStyleId, type);
@@ -1212,6 +1230,7 @@ function convertTableRow(row, styleResolver, context, isHeaderRow, columnWidths,
1212
1230
  if (row.preservedAttributes && row.preservedAttributes.length > 0) attrsWithoutStructuralChange._preservedAttributes = row.preservedAttributes;
1213
1231
  if (row.bookmarks && row.bookmarks.length > 0) attrsWithoutStructuralChange._bookmarks = row.bookmarks;
1214
1232
  if (row.contentControls && row.contentControls.length > 0) attrsWithoutStructuralChange.contentControls = row.contentControls;
1233
+ if (row.carrierStack?.length) attrsWithoutStructuralChange.carrierStack = row.carrierStack;
1215
1234
  if (hasSinkChildren(row.preserved)) attrsWithoutStructuralChange._preserved = row.preserved;
1216
1235
  let attrs = attrsWithoutStructuralChange;
1217
1236
  const rowStructuralChange = row.structuralChange;
@@ -1394,6 +1413,7 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
1394
1413
  if (formatting) attrs._originalFormatting = formatting;
1395
1414
  if (cell.propertyChanges && cell.propertyChanges.length > 0) attrs.tcPrChange = [...cell.propertyChanges];
1396
1415
  if (cell.contentControls && cell.contentControls.length > 0) attrs.contentControls = cell.contentControls;
1416
+ if (cell.carrierStack?.length) attrs.carrierStack = cell.carrierStack;
1397
1417
  const cellStructuralChange = cell.structuralChange;
1398
1418
  if (cellStructuralChange) {
1399
1419
  const info = {
@@ -1448,6 +1468,9 @@ function convertTableCell({ cell, styleResolver, context, isHeader, gridWidthPer
1448
1468
  case "blockSdt":
1449
1469
  nodes.push(convertBlockSdt(block, convertCellBlocks));
1450
1470
  break;
1471
+ case "blockCustomXml":
1472
+ nodes.push(convertBlockCustomXml(block, convertCellBlocks));
1473
+ break;
1451
1474
  case "preservedBlock":
1452
1475
  nodes.push(convertPreservedBlock(block));
1453
1476
  break;
@@ -1548,7 +1571,10 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
1548
1571
  const hasConvertedPreservedContent = inlineNodes.some((node) => node.type.name === "preservedXml");
1549
1572
  const hasConvertedWrapperContent = inlineNodes.some((node) => node.marks.some((mark) => mark.type.name === INLINE_WRAPPER_MARK_NAME));
1550
1573
  const createStructuredField = hasConvertedPageBreakContent || hasConvertedPreservedContent || hasStructuredSourceContent && (hasConvertedHyperlinkContent || hasConvertedWrapperContent);
1551
- if (!createStructuredField && fieldPropertyChanges && fieldPropertyChanges.length > 0) marks.push(schema.mark("runPropertyChange", { changes: [...fieldPropertyChanges] }));
1574
+ const resultRuns = field.type === "simpleField" ? field.content.flatMap((content) => content.type === "run" ? [content] : []) : field.fieldResult;
1575
+ const emptyResultRuns = displayText === "" && resultRuns.length > 0 && (field.type === "complexField" || field.content.length === resultRuns.length) && resultRuns.every((run) => run.content.every((item) => item.type === "text" && item.text === "")) ? resultRuns : void 0;
1576
+ const resultPropertyChanges = emptyResultRuns ? emptyFieldRunPropertyChanges(emptyResultRuns) : fieldPropertyChanges;
1577
+ if (!createStructuredField && resultPropertyChanges && resultPropertyChanges.length > 0) marks.push(schema.mark("runPropertyChange", { changes: [...resultPropertyChanges] }));
1552
1578
  return schema.node(createStructuredField ? "structuredField" : "field", {
1553
1579
  fieldType: field.fieldType,
1554
1580
  instruction: field.instruction,
@@ -1556,7 +1582,13 @@ function convertField(field, { getInheritedRunFormatting, styleResolver, nextHyp
1556
1582
  fieldKind: field.type === "simpleField" ? "simple" : "complex",
1557
1583
  fldLock: field.fldLock ?? null,
1558
1584
  dirty: field.dirty ?? null,
1559
- fieldResultIsFallback: field.type === "complexField" ? field.fieldResultIsFallback ?? null : null
1585
+ fieldResultIsFallback: field.type === "complexField" ? field.fieldResultIsFallback ?? null : null,
1586
+ formFieldDataXml: field.type === "complexField" ? field.formFieldDataXml ?? null : null,
1587
+ _docxEmptyResultRuns: emptyResultRuns ?? null,
1588
+ _docxFieldCode: field.type === "complexField" && field.fieldCode.length > 0 ? {
1589
+ instruction: field.instruction,
1590
+ runs: field.fieldCode
1591
+ } : null
1560
1592
  }, createStructuredField ? inlineNodes : void 0, marks);
1561
1593
  }
1562
1594
  /**
@@ -2897,6 +2929,9 @@ function headerFooterToProseDoc(content, options) {
2897
2929
  case "blockSdt":
2898
2930
  out.push(convertBlockSdt(block, convertBlocks));
2899
2931
  break;
2932
+ case "blockCustomXml":
2933
+ out.push(convertBlockCustomXml(block, convertBlocks));
2934
+ break;
2900
2935
  case "preservedBlock":
2901
2936
  out.push(convertPreservedBlock(block));
2902
2937
  break;
@@ -0,0 +1,18 @@
1
+ import { document_d_exports } from "../types/document.js";
2
+ //#region src/prosemirror/emptyFieldResultRuns.d.ts
3
+ /** The single field mark lists every revision held by its invisible result runs. */
4
+ declare const emptyFieldRunPropertyChanges: (runs: readonly document_d_exports.Run[]) => document_d_exports.RunPropertyChange[];
5
+ type ResolveEmptyFieldResultRunsOptions = {
6
+ runs: readonly document_d_exports.Run[];
7
+ mode: "accept" | "reject";
8
+ revisionIds: ReadonlySet<number> | null;
9
+ };
10
+ type ResolvedEmptyFieldResultRuns = {
11
+ runs: document_d_exports.Run[];
12
+ visibleFormatting: document_d_exports.TextFormatting | undefined;
13
+ visibleFormattingChanged: boolean;
14
+ };
15
+ /** Resolve each authored run separately; a field mark carries their combined revisions. */
16
+ declare const resolveEmptyFieldResultRuns: ({ runs, mode, revisionIds }: ResolveEmptyFieldResultRunsOptions) => ResolvedEmptyFieldResultRuns | null;
17
+ //#endregion
18
+ export { emptyFieldRunPropertyChanges, resolveEmptyFieldResultRuns };
@@ -0,0 +1,33 @@
1
+ import { canonicalJson } from "../utils/canonicalJson.js";
2
+ //#region src/prosemirror/emptyFieldResultRuns.ts
3
+ /** The single field mark lists every revision held by its invisible result runs. */
4
+ const emptyFieldRunPropertyChanges = (runs) => runs.flatMap((run) => run.propertyChanges ?? []);
5
+ const visibleFormatting = (runs) => runs.find((run) => run.formatting !== void 0)?.formatting;
6
+ /** Resolve each authored run separately; a field mark carries their combined revisions. */
7
+ const resolveEmptyFieldResultRuns = ({ runs, mode, revisionIds }) => {
8
+ let changed = false;
9
+ const resolved = runs.map((run) => {
10
+ const matches = run.propertyChanges?.filter((change) => revisionIds === null || revisionIds.has(change.info.id));
11
+ if (!matches?.length) return run;
12
+ changed = true;
13
+ const remaining = run.propertyChanges?.filter((change) => revisionIds !== null && !revisionIds.has(change.info.id));
14
+ const formatting = mode === "reject" ? matches.at(0)?.previousFormatting : run.formatting;
15
+ return {
16
+ type: "run",
17
+ content: run.content,
18
+ ...formatting !== void 0 ? { formatting } : {},
19
+ ...remaining?.length ? { propertyChanges: remaining } : {},
20
+ ...run.preservedAttributes ? { preservedAttributes: run.preservedAttributes } : {}
21
+ };
22
+ });
23
+ if (!changed) return null;
24
+ const before = visibleFormatting(runs);
25
+ const after = visibleFormatting(resolved);
26
+ return {
27
+ runs: resolved,
28
+ visibleFormatting: after,
29
+ visibleFormattingChanged: canonicalJson(before) !== canonicalJson(after)
30
+ };
31
+ };
32
+ //#endregion
33
+ export { emptyFieldRunPropertyChanges, resolveEmptyFieldResultRuns };
@@ -1,6 +1,6 @@
1
1
  import { AnyExtension, CommandFactory, CommandMap, FolioCommandArguments, FolioCommandName } from "./types.js";
2
- import { Plugin } from "prosemirror-state";
3
2
  import { Schema } from "prosemirror-model";
3
+ import { Plugin } from "prosemirror-state";
4
4
  //#region src/prosemirror/extensions/ExtensionManager.d.ts
5
5
  declare class ExtensionManager {
6
6
  private readonly extensions;
@@ -1,3 +1,4 @@
1
+ import { areTransactionInvariantsEnabled, createTransactionInvariantPlugin } from "../plugins/transactionInvariants.js";
1
2
  import { createTextInputPlugin } from "../textInput.js";
2
3
  import { panic } from "better-result";
3
4
  import { Schema } from "prosemirror-model";
@@ -50,7 +51,8 @@ var ExtensionManager = class {
50
51
  this.plugins = [
51
52
  createTextInputPlugin(),
52
53
  ...allPlugins,
53
- ...allKeyboardShortcuts.map((shortcuts) => keymap(shortcuts))
54
+ ...allKeyboardShortcuts.map((shortcuts) => keymap(shortcuts)),
55
+ ...areTransactionInvariantsEnabled() ? [createTransactionInvariantPlugin()] : []
54
56
  ];
55
57
  this.commands = allCommands;
56
58
  }
@@ -19,6 +19,7 @@ import { PasteStyleInlinerExtension } from "./features/PasteStyleInlinerExtensio
19
19
  import { SelectionTrackerExtension } from "./features/SelectionTrackerExtension.js";
20
20
  import { MARK_EXTENSIONS, MARK_NESTING_ORDER } from "./markRegistry.js";
21
21
  import { BlockBookmarkBoundaryExtension } from "./nodes/BlockBookmarkBoundaryExtension.js";
22
+ import { BlockCustomXmlExtension } from "./nodes/BlockCustomXmlExtension.js";
22
23
  import { BlockSdtExtension } from "./nodes/BlockSdtExtension.js";
23
24
  import { BookmarkBoundaryExtension } from "./nodes/BookmarkBoundaryExtension.js";
24
25
  import { CommentReferenceExtension } from "./nodes/CommentReferenceExtension.js";
@@ -86,10 +87,11 @@ function createStarterKit(options = {}) {
86
87
  add("pageBreak", PageBreakExtension());
87
88
  add("pageBreakRun", PageBreakRunExtension());
88
89
  add("renderedPageBreak", RenderedPageBreakExtension());
89
- add("field", FieldExtension());
90
+ add("field", FieldExtension({ getInternalClipboardToken }));
90
91
  add("field", StructuredFieldExtension({ getInternalClipboardToken }));
91
92
  add("sdt", SdtExtension());
92
93
  add("blockSdt", BlockSdtExtension());
94
+ add("blockCustomXml", BlockCustomXmlExtension());
93
95
  add("preservedBlock", PreservedBlockExtension());
94
96
  add("math", MathExtension());
95
97
  if (!disabled.has("table")) extensions.push(...createTableExtensions());
@@ -14,7 +14,7 @@ const DocExtension = createNodeExtension({
14
14
  _adjustLineHeightInTable: { default: false },
15
15
  _doNotUseIndentAsNumberingTabStop: { default: false }
16
16
  },
17
- content: "(paragraph | horizontalRule | pageBreak | table | textBox | blockSdt | preservedBlock | blockBookmarkBoundary)+"
17
+ content: "(paragraph | horizontalRule | pageBreak | table | textBox | blockSdt | blockCustomXml | preservedBlock | blockBookmarkBoundary)+"
18
18
  }
19
19
  });
20
20
  //#endregion
@@ -213,6 +213,7 @@ const paragraphNodeSpec = {
213
213
  indentFirstLine: { default: null },
214
214
  hangingIndent: { default: false },
215
215
  numPr: { default: null },
216
+ _pastedHtmlList: { default: void 0 },
216
217
  numPrFromStyle: { default: null },
217
218
  listNumFmt: { default: null },
218
219
  listIsBullet: { default: null },
@@ -273,11 +274,22 @@ const paragraphNodeSpec = {
273
274
  const styleId = element.dataset["styleId"];
274
275
  const tableOfContentsLevel = Number(element.dataset["tableOfContentsLevel"]);
275
276
  const sectionBreakType = parseSectionBreakType(element.dataset["sectionBreak"]);
277
+ const pastedListGroup = Number(element.dataset["folioListGroup"]);
278
+ const pastedListLevel = Number(element.dataset["folioListLevel"]);
279
+ const pastedListKind = element.dataset["folioListKind"];
280
+ const pastedListStart = Number(element.dataset["folioListStart"]);
281
+ const pastedHtmlList = Number.isSafeInteger(pastedListGroup) && pastedListGroup > 0 && Number.isSafeInteger(pastedListLevel) && pastedListLevel >= 0 && pastedListLevel <= 8 && (pastedListKind === "bullet" || pastedListKind === "numbered") ? {
282
+ group: pastedListGroup,
283
+ level: pastedListLevel,
284
+ kind: pastedListKind,
285
+ ...Number.isSafeInteger(pastedListStart) && pastedListStart > 0 ? { start: pastedListStart } : {}
286
+ } : void 0;
276
287
  const attrs = {
277
288
  ...paraId ? { paraId } : {},
278
289
  ...alignment ? { alignment } : {},
279
290
  ...alignmentFromStyle ? { alignmentFromStyle } : {},
280
291
  ...styleId ? { styleId } : {},
292
+ ...pastedHtmlList ? { _pastedHtmlList: pastedHtmlList } : {},
281
293
  ...Number.isSafeInteger(tableOfContentsLevel) && tableOfContentsLevel > 0 ? { _tableOfContentsLevel: tableOfContentsLevel } : {},
282
294
  ...sectionBreakType ? { _sectionProperties: mintSectionProperties(sectionBreakType) } : {}
283
295
  };
@@ -63,6 +63,9 @@ const INHERITED_PARA_ATTRS = [
63
63
  "snapToGrid",
64
64
  "spaceAfter",
65
65
  "spaceBefore",
66
+ "spacingExplicit",
67
+ "spacingFromDocDefaults",
68
+ "spacingFromImplicitDefaultStyle",
66
69
  "contextualSpacing"
67
70
  ];
68
71
  /** Style formatting needed when the caret has no marks of its own. */
@@ -1,18 +1,18 @@
1
- import { isBulletLevel } from "../../../docx/numberingParser.js";
2
- import { NO_PARAGRAPH_NUMBERING, paragraphNumberingLevel, paragraphNumberingReference, paragraphNumberingReferenceId } from "../../../docx/numberingReference.js";
1
+ import { paragraphNumberingLevel, paragraphNumberingReferenceId } from "../../../docx/numberingReference.js";
3
2
  import { expectParagraphAttrs } from "../../attrs/index.js";
4
- import { PPR_CHANGE_SCOPED_ATTR_KEYS, hasSerializableParagraphPropertyChange } from "../../commands/propertyChangeScope.js";
3
+ import { LIST_MARKER_PATTERN, listRequestsForMarker } from "../../listAutoformatMarkers.js";
5
4
  import { CLEARED_LIST_RENDERING_ATTRS } from "../../listMarker.js";
6
- import { LIST_RENDERING_ATTR_KEYS } from "../../listRenderingAttrs.js";
5
+ import { applyParagraphUpdates, continueNumbering, listItemAttrs, resolveListTarget, restartNumbering, setNumberingValue } from "../../listNumbering.js";
7
6
  import { resolveListState } from "../../listState.js";
8
- import { paragraphNumberingAttr } from "../../numberingAttr.js";
7
+ import { removedNumberingAttr } from "../../numberingAttr.js";
9
8
  import { getDocumentNumbering } from "../../plugins/documentNumbering.js";
10
- import { SUGGESTION_META, makeRevisionInfo } from "../../plugins/suggestionMode.js";
9
+ import { SUGGESTION_META, makeRevisionInfo, suggestRangeDeletion } from "../../plugins/suggestionMode.js";
11
10
  import { listLevelAttrPatch } from "../../styles/resolvedStyleAttrs.js";
12
11
  import { createExtension } from "../create.js";
13
12
  import { goToNextCell, goToPrevCell } from "../nodes/TableExtension.js";
14
13
  import { Priority } from "../types.js";
15
14
  import { panic } from "better-result";
15
+ import { Plugin } from "prosemirror-state";
16
16
  import { InputRule, inputRules, undoInputRule } from "prosemirror-inputrules";
17
17
  //#region src/prosemirror/extensions/features/ListExtension.ts
18
18
  /**
@@ -27,113 +27,87 @@ function chainCommands(...commands) {
27
27
  return false;
28
28
  };
29
29
  }
30
- function appendParagraphPropertyChange(attrs, existing, previousFormatting, rev) {
31
- return {
32
- ...attrs,
33
- _propertyChanges: [...existing ?? [], {
34
- type: "paragraphPropertyChange",
35
- info: {
36
- id: rev.id,
37
- author: rev.author,
38
- date: rev.date
39
- },
40
- previousFormatting
41
- }]
42
- };
43
- }
44
- function getPreviousListFormatting(attrs) {
45
- const previousFormatting = {};
46
- for (const key of PPR_CHANGE_SCOPED_ATTR_KEYS) {
47
- const value = attrs[key];
48
- if (value != null) previousFormatting[key] = value;
49
- }
50
- previousFormatting["numPr"] = attrs["numPr"] ?? null;
51
- for (const key of LIST_RENDERING_ATTR_KEYS) previousFormatting[key] = attrs[key] ?? null;
52
- return previousFormatting;
53
- }
54
30
  function clearListAttrs(attrs) {
55
- const numPr = paragraphNumberingReferenceId(attrs.numPrFromStyle) === void 0 ? null : paragraphNumberingAttr(NO_PARAGRAPH_NUMBERING);
56
31
  return {
57
32
  ...attrs,
58
- numPr,
33
+ numPr: removedNumberingAttr(attrs.numPrFromStyle),
59
34
  ...CLEARED_LIST_RENDERING_ATTRS
60
35
  };
61
36
  }
62
37
  function hasActiveListNumbering(attrs) {
63
38
  return attrs.numPr?.kind === "reference";
64
39
  }
40
+ const paragraphsBetween = (doc, from, to) => {
41
+ const paragraphs = [];
42
+ doc.nodesBetween(from, to, (node, pos) => {
43
+ if (node.type.name !== "paragraph") return true;
44
+ paragraphs.push({
45
+ pos,
46
+ node
47
+ });
48
+ return false;
49
+ });
50
+ return paragraphs;
51
+ };
65
52
  /**
66
- * The numbering instances Folio mints for its own toolbar lists. They are the
67
- * ids the autoformat rules and the list buttons create; a document Folio did
68
- * not create numbers its lists however its author did, which is why nothing
69
- * reads a list's kind off its id any more.
53
+ * Make every paragraph from `from` to `to` an item of one list: the list next
54
+ * to them when it matches, else a new one (see `listNumbering.ts`). One
55
+ * target for the whole range, so a selection of plain paragraphs becomes one
56
+ * list rather than one list apiece.
70
57
  */
71
- const FOLIO_BULLET_NUM_ID = 1;
72
- const FOLIO_NUMBERED_NUM_ID = 2;
73
- const targetNumIdForIntent = (numbering, preferredNumId, ilvl, intent) => {
74
- const matchesIntent = (numId) => {
75
- const level = numbering?.getLevel(numId, ilvl) ?? null;
76
- return level !== null && (isBulletLevel(level) ? "bullet" : "numbered") === intent;
77
- };
78
- if (matchesIntent(preferredNumId)) return preferredNumId;
79
- return numbering?.definitions.nums.find(({ numId }) => matchesIntent(numId))?.numId ?? preferredNumId;
58
+ const numberParagraphs = ({ state, tr, from, to, requests }) => {
59
+ const target = resolveListTarget({
60
+ numbering: getDocumentNumbering(state),
61
+ $from: tr.doc.resolve(from),
62
+ $to: tr.doc.resolve(to),
63
+ requests
64
+ });
65
+ if (!target) return false;
66
+ applyParagraphUpdates({
67
+ tr,
68
+ state,
69
+ updates: paragraphsBetween(tr.doc, from, to).map(({ pos, node }) => ({
70
+ pos,
71
+ node,
72
+ next: listItemAttrs(node.attrs, {
73
+ numId: target.numId,
74
+ ilvl: paragraphNumberingLevel(expectParagraphAttrs(node).numPr) ?? target.ilvl
75
+ }, target.numbering)
76
+ }))
77
+ });
78
+ return true;
80
79
  };
81
- function toggleList(numId, intent) {
80
+ function toggleList(intent) {
82
81
  return (state, dispatch) => {
83
82
  const { $from, $to } = state.selection;
84
83
  const paragraph = $from.parent;
85
84
  if (paragraph.type.name !== "paragraph") return false;
86
- const numbering = getDocumentNumbering(state);
87
- const isInSameList = resolveListState(numbering, expectParagraphAttrs(paragraph).numPr).type === intent;
88
- const rev = makeRevisionInfo(state);
89
- if (rev) {
90
- let hasPendingChange = false;
91
- state.doc.nodesBetween($from.pos, $to.pos, (node) => {
92
- if (node.type.name === "paragraph" && hasSerializableParagraphPropertyChange(expectParagraphAttrs(node)._propertyChanges)) {
93
- hasPendingChange = true;
94
- return false;
95
- }
96
- });
97
- if (hasPendingChange) return false;
98
- }
99
85
  if (!dispatch) return true;
100
- let tr = state.tr;
101
- const seen = /* @__PURE__ */ new Set();
102
- state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
103
- if (node.type.name === "paragraph" && !seen.has(pos)) {
104
- seen.add(pos);
105
- let nextAttrs;
106
- if (isInSameList) nextAttrs = clearListAttrs(expectParagraphAttrs(node));
107
- else {
108
- const ilvl = paragraphNumberingLevel(expectParagraphAttrs(node).numPr) ?? 0;
109
- const targetNumId = targetNumIdForIntent(numbering, numId, ilvl, intent);
110
- const definition = numbering?.getLevel(targetNumId, ilvl) ?? null;
111
- const isBullet = definition === null ? intent === "bullet" : isBulletLevel(definition);
112
- nextAttrs = {
113
- ...node.attrs,
114
- ...CLEARED_LIST_RENDERING_ATTRS,
115
- numPr: paragraphNumberingAttr(paragraphNumberingReference({
116
- numId: targetNumId,
117
- ilvl
118
- })),
119
- listIsBullet: isBullet,
120
- listNumFmt: isBullet ? null : definition?.numFmt ?? "decimal"
121
- };
122
- }
123
- if (rev) {
124
- const existing = expectParagraphAttrs(node)._propertyChanges;
125
- nextAttrs = appendParagraphPropertyChange(nextAttrs, existing, getPreviousListFormatting(node.attrs), rev);
126
- }
127
- tr = tr.setNodeMarkup(pos, void 0, nextAttrs);
128
- }
86
+ const numbering = getDocumentNumbering(state);
87
+ const isItemOfKind = (node) => resolveListState(numbering, expectParagraphAttrs(node).numPr).type === intent;
88
+ const tr = state.tr;
89
+ if (isItemOfKind(paragraph)) applyParagraphUpdates({
90
+ tr,
91
+ state,
92
+ updates: paragraphsBetween(state.doc, $from.pos, $to.pos).filter(({ node }) => isItemOfKind(node)).map(({ pos, node }) => ({
93
+ pos,
94
+ node,
95
+ next: clearListAttrs(expectParagraphAttrs(node))
96
+ }))
97
+ });
98
+ else numberParagraphs({
99
+ state,
100
+ tr,
101
+ from: $from.pos,
102
+ to: $to.pos,
103
+ requests: [{ kind: intent }]
129
104
  });
130
- if (rev) tr.setMeta(SUGGESTION_META, true);
131
105
  dispatch(tr.scrollIntoView());
132
106
  return true;
133
107
  };
134
108
  }
135
- const toggleBulletList = (state, dispatch) => toggleList(FOLIO_BULLET_NUM_ID, "bullet")(state, dispatch);
136
- const toggleNumberedList = (state, dispatch) => toggleList(FOLIO_NUMBERED_NUM_ID, "numbered")(state, dispatch);
109
+ const toggleBulletList = (state, dispatch) => toggleList("bullet")(state, dispatch);
110
+ const toggleNumberedList = (state, dispatch) => toggleList("numbered")(state, dispatch);
137
111
  const attrsForListLevel = (state, attrs, level) => {
138
112
  if (!hasActiveListNumbering(attrs)) panic("Cannot change the level of a list without a numbering id");
139
113
  return {
@@ -215,7 +189,19 @@ function exitListOnEmptyEnter() {
215
189
  const attrs = expectParagraphAttrs(paragraph);
216
190
  if (!hasActiveListNumbering(attrs)) return false;
217
191
  if (paragraph.textContent.length > 0) return false;
218
- if (dispatch) dispatch(state.tr.setNodeMarkup($from.before(), void 0, clearListAttrs(attrs)));
192
+ if (dispatch) {
193
+ const tr = state.tr;
194
+ applyParagraphUpdates({
195
+ tr,
196
+ state,
197
+ updates: [{
198
+ pos: $from.before(),
199
+ node: paragraph,
200
+ next: clearListAttrs(attrs)
201
+ }]
202
+ });
203
+ dispatch(tr);
204
+ }
219
205
  return true;
220
206
  };
221
207
  }
@@ -229,10 +215,19 @@ function splitListItem() {
229
215
  if (dispatch) {
230
216
  const { tr } = state;
231
217
  const pos = $from.pos;
218
+ const paragraphPos = $from.before();
219
+ const revision = makeRevisionInfo(state);
232
220
  tr.split(pos, 1, [{
233
221
  type: state.schema.nodes["paragraph"],
234
222
  attrs: { ...paragraph.attrs }
235
223
  }]);
224
+ if (revision && paragraph.attrs["pPrMark"] == null) {
225
+ tr.setNodeAttribute(paragraphPos, "pPrMark", {
226
+ kind: "ins",
227
+ info: revision
228
+ });
229
+ tr.setMeta(SUGGESTION_META, true);
230
+ }
236
231
  dispatch(tr.scrollIntoView());
237
232
  }
238
233
  return true;
@@ -247,7 +242,19 @@ function backspaceExitList() {
247
242
  if (paragraph.type.name !== "paragraph") return false;
248
243
  const attrs = expectParagraphAttrs(paragraph);
249
244
  if (!hasActiveListNumbering(attrs)) return false;
250
- if (dispatch) dispatch(state.tr.setNodeMarkup($from.before(), void 0, clearListAttrs(attrs)));
245
+ if (dispatch) {
246
+ const tr = state.tr;
247
+ applyParagraphUpdates({
248
+ tr,
249
+ state,
250
+ updates: [{
251
+ pos: $from.before(),
252
+ node: paragraph,
253
+ next: clearListAttrs(attrs)
254
+ }]
255
+ });
256
+ dispatch(tr);
257
+ }
251
258
  return true;
252
259
  };
253
260
  }
@@ -314,53 +321,84 @@ function insertTab() {
314
321
  return true;
315
322
  };
316
323
  }
324
+ /** Whether a typed marker may become a list here at all. */
325
+ const acceptsListMarker = (paragraph) => paragraph.type.name === "paragraph" && paragraphNumberingReferenceId(expectParagraphAttrs(paragraph).numPr) === void 0;
317
326
  /**
318
- * Word's as-you-type markers. Each ends in the space that triggers the rule.
319
- * `1.` starts a numbered list at one, like the toolbar button; another typed
320
- * number stays text rather than being silently renumbered.
327
+ * Replace a typed marker with the list the toolbar button produces: the same
328
+ * target resolution and the same attrs, so an autoformatted list saves exactly
329
+ * like a clicked one. The marker's format and value choose the list (see
330
+ * `listAutoformatMarkers.ts`).
321
331
  */
322
- const BULLET_AUTOFORMAT = /^[-*] $/u;
323
- const NUMBERED_AUTOFORMAT = /^1\. $/u;
324
- const captureTransaction = (command, state) => {
325
- const captured = { transaction: null };
326
- command(state, (transaction) => {
327
- captured.transaction = transaction;
328
- });
329
- return captured.transaction;
330
- };
331
- /**
332
- * Replace a typed marker with the list the toolbar button produces. Running the
333
- * command itself (rather than writing `numPr` here) keeps an autoformatted list
334
- * identical to a clicked one, down to what the document saves.
335
- */
336
- const listAutoformat = (marker, toggleCommand) => new InputRule(marker, (state, _match, start, end) => {
332
+ const listAutoformatRule = () => new InputRule(LIST_MARKER_PATTERN, (state, match, start, end) => {
337
333
  const { $from } = state.selection;
338
- if ($from.parent.type.name !== "paragraph") return null;
334
+ if (!acceptsListMarker($from.parent)) return null;
339
335
  if (start !== $from.start()) return null;
340
- if (paragraphNumberingReferenceId(expectParagraphAttrs($from.parent).numPr) !== void 0) return null;
341
336
  if (makeRevisionInfo(state)) return null;
342
- const toggled = captureTransaction(toggleCommand, state);
343
- if (!toggled) return null;
337
+ const requests = listRequestsForMarker(match[0]);
338
+ if (!requests) return null;
344
339
  const tr = state.tr.delete(start, end);
345
- for (const step of toggled.steps) {
346
- const mapped = step.map(tr.mapping);
347
- if (mapped) tr.step(mapped);
348
- }
349
- return tr;
340
+ return numberParagraphs({
341
+ state,
342
+ tr,
343
+ from: start,
344
+ to: start,
345
+ requests
346
+ }) ? tr : null;
350
347
  });
351
- const listAutoformatRules = () => inputRules({ rules: [listAutoformat(BULLET_AUTOFORMAT, toggleBulletList), listAutoformat(NUMBERED_AUTOFORMAT, toggleNumberedList)] });
348
+ /**
349
+ * List autoformat while suggesting. The suggestion plugin has already
350
+ * recorded the typed space as a tracked insertion; this follows it with the
351
+ * marker's removal (a retraction of the author's own typing, or a tracked
352
+ * deletion of text that was there before) and the list as a tracked
353
+ * paragraph-property change. The follow-up is appended to the typing
354
+ * transaction, so one undo reverts both, and it is stored as the input rule's
355
+ * last conversion, so Backspace puts the marker back as it does while editing.
356
+ */
357
+ const suggestedListAutoformat = (autoformat) => new Plugin({ appendTransaction(transactions, _oldState, state) {
358
+ if (!transactions.some((tr) => tr.getMeta("suggestionModeTextInput") === " ")) return null;
359
+ const { $head, empty } = state.selection;
360
+ if (!empty || !makeRevisionInfo(state) || !acceptsListMarker($head.parent)) return null;
361
+ const requests = listRequestsForMarker($head.parent.textBetween(0, $head.parentOffset, null, ""));
362
+ if (!requests) return null;
363
+ const start = $head.start();
364
+ const tr = state.tr;
365
+ if (!suggestRangeDeletion(state, tr, start, $head.pos)) return null;
366
+ const from = tr.mapping.map(start);
367
+ if (!numberParagraphs({
368
+ state,
369
+ tr,
370
+ from,
371
+ to: from,
372
+ requests
373
+ })) return null;
374
+ const caret = tr.mapping.map($head.pos);
375
+ tr.setMeta(autoformat, {
376
+ transform: tr,
377
+ from: caret,
378
+ to: caret,
379
+ text: ""
380
+ });
381
+ return tr;
382
+ } });
383
+ const listAutoformatPlugins = () => {
384
+ const autoformat = inputRules({ rules: [listAutoformatRule()] });
385
+ return [autoformat, suggestedListAutoformat(autoformat)];
386
+ };
352
387
  const ListExtension = createExtension({
353
388
  name: "list",
354
389
  priority: Priority.High,
355
390
  onSchemaReady() {
356
391
  return {
357
- plugins: [listAutoformatRules()],
392
+ plugins: listAutoformatPlugins(),
358
393
  commands: {
359
394
  toggleBulletList: () => toggleBulletList,
360
395
  toggleNumberedList: () => toggleNumberedList,
361
396
  increaseListLevel: () => increaseListLevel,
362
397
  decreaseListLevel: () => decreaseListLevel,
363
- removeList: () => removeList
398
+ removeList: () => removeList,
399
+ restartNumbering: () => restartNumbering,
400
+ continueNumbering: () => continueNumbering,
401
+ setNumberingValue: (value) => setNumberingValue(value)
364
402
  },
365
403
  keyboardShortcuts: {
366
404
  Tab: chainCommands(goToNextCell(), increaseListIndent(), insertTab()),