@stll/folio-core 0.54.2 → 0.55.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 (199) hide show
  1. package/dist/ai-edits/apply.js +22 -1
  2. package/dist/ai-edits/headless.js +1 -0
  3. package/dist/compare/content-types.d.ts +3 -15
  4. package/dist/controller/canonicalComposition.d.ts +36 -0
  5. package/dist/controller/canonicalComposition.js +168 -0
  6. package/dist/controller/canonicalInput.d.ts +45 -0
  7. package/dist/controller/canonicalInput.js +338 -0
  8. package/dist/controller/canonicalOperations.d.ts +22 -0
  9. package/dist/controller/canonicalOperations.js +85 -0
  10. package/dist/controller/canonicalReview.d.ts +12 -0
  11. package/dist/controller/canonicalReview.js +19 -0
  12. package/dist/controller/canonicalSession.d.ts +149 -0
  13. package/dist/controller/canonicalSession.js +1038 -0
  14. package/dist/controller/canonicalStoryEditor.d.ts +34 -0
  15. package/dist/controller/canonicalStoryEditor.js +82 -0
  16. package/dist/controller/canonicalStructure.d.ts +16 -0
  17. package/dist/controller/canonicalStructure.js +269 -0
  18. package/dist/controller/folioEditor.d.ts +1 -1
  19. package/dist/controller/folioEditor.js +9 -0
  20. package/dist/controller/headerFooterEditorManager.d.ts +4 -0
  21. package/dist/controller/headerFooterEditorManager.js +71 -3
  22. package/dist/controller/hiddenEditorApi.d.ts +35 -0
  23. package/dist/controller/hiddenEditorApi.js +25 -8
  24. package/dist/controller/hiddenEditorManager.d.ts +11 -2
  25. package/dist/controller/hiddenEditorManager.js +456 -30
  26. package/dist/controller/layoutPipeline.d.ts +1 -1
  27. package/dist/controller/layoutPipeline.js +2 -0
  28. package/dist/controller/noteEditorManager.d.ts +4 -0
  29. package/dist/controller/noteEditorManager.js +113 -15
  30. package/dist/docx/attributeRemainder.js +1 -0
  31. package/dist/docx/canonicalSessionInput.d.ts +11 -0
  32. package/dist/docx/canonicalSessionInput.js +27 -0
  33. package/dist/docx/canonicalStoryRepack.d.ts +10 -0
  34. package/dist/docx/canonicalStoryRepack.js +41 -0
  35. package/dist/docx/contentTypeRegistry.d.ts +8 -0
  36. package/dist/docx/contentTypeRegistry.js +64 -0
  37. package/dist/docx/ensureParaIds.d.ts +7 -1
  38. package/dist/docx/ensureParaIds.js +163 -211
  39. package/dist/docx/foldedListNumberFields.d.ts +85 -0
  40. package/dist/docx/foldedListNumberFields.js +267 -0
  41. package/dist/docx/headerFooterVerbatim.d.ts +14 -1
  42. package/dist/docx/headerFooterVerbatim.js +95 -2
  43. package/dist/docx/noteIds.d.ts +5 -0
  44. package/dist/docx/noteIds.js +6 -2
  45. package/dist/docx/noteReferenceMark.d.ts +3 -1
  46. package/dist/docx/noteReferenceMark.js +15 -14
  47. package/dist/docx/numberingParser.d.ts +3 -1
  48. package/dist/docx/numberingParser.js +17 -3
  49. package/dist/docx/packageParts.d.ts +3 -1
  50. package/dist/docx/packageParts.js +65 -16
  51. package/dist/docx/paragraphMarkPropertyPresence.d.ts +9 -0
  52. package/dist/docx/paragraphMarkPropertyPresence.js +21 -0
  53. package/dist/docx/paragraphParser.js +101 -53
  54. package/dist/docx/paragraphPropertySource.d.ts +15 -1
  55. package/dist/docx/paragraphPropertySource.js +76 -22
  56. package/dist/docx/parser.js +2 -1
  57. package/dist/docx/reviewHistoryNamespace.d.ts +4 -0
  58. package/dist/docx/reviewHistoryNamespace.js +4 -0
  59. package/dist/docx/reviewResolutionProvenance.d.ts +25 -0
  60. package/dist/docx/reviewResolutionProvenance.js +153 -0
  61. package/dist/docx/rezip.d.ts +7 -3
  62. package/dist/docx/rezip.js +107 -45
  63. package/dist/docx/runConsolidator.d.ts +2 -58
  64. package/dist/docx/runConsolidator.js +3 -175
  65. package/dist/docx/runParser.d.ts +2 -1
  66. package/dist/docx/runParser.js +156 -116
  67. package/dist/docx/saveDiagnostics.d.ts +11 -0
  68. package/dist/docx/saveDiagnostics.js +0 -0
  69. package/dist/docx/selectiveSave.d.ts +2 -1
  70. package/dist/docx/selectiveSave.js +4 -1
  71. package/dist/docx/selectiveXmlPatch.d.ts +16 -8
  72. package/dist/docx/selectiveXmlPatch.js +74 -2
  73. package/dist/docx/serializer/headerFooterSerializer.d.ts +5 -1
  74. package/dist/docx/serializer/headerFooterSerializer.js +19 -11
  75. package/dist/docx/serializer/noteSerializer.d.ts +2 -2
  76. package/dist/docx/serializer/noteSerializer.js +24 -8
  77. package/dist/docx/serializer/paragraphSerializer.js +41 -4
  78. package/dist/docx/serializer/partNamespaces.js +2 -1
  79. package/dist/docx/serializer/runSerializer.js +3 -1
  80. package/dist/docx/settingsHeaderFooterUpdate.d.ts +5 -0
  81. package/dist/docx/settingsHeaderFooterUpdate.js +90 -0
  82. package/dist/docx/settingsParser.d.ts +1 -2
  83. package/dist/docx/settingsParser.js +5 -6
  84. package/dist/docx/storyBlockReplay.d.ts +11 -0
  85. package/dist/docx/storyBlockReplay.js +367 -0
  86. package/dist/docx/streamingXmlParser.d.ts +22 -1
  87. package/dist/docx/streamingXmlParser.js +49 -3
  88. package/dist/docx/structuralXmlPatch.js +8 -1
  89. package/dist/docx/verbatimCapture.d.ts +3 -1
  90. package/dist/docx/verbatimCapture.js +49 -6
  91. package/dist/i18n/messages/ar.gen.d.ts +5 -0
  92. package/dist/i18n/messages/ar.gen.js +656 -0
  93. package/dist/i18n/messages/cs.gen.d.ts +5 -0
  94. package/dist/i18n/messages/cs.gen.js +656 -0
  95. package/dist/i18n/messages/de.gen.d.ts +5 -0
  96. package/dist/i18n/messages/de.gen.js +656 -0
  97. package/dist/i18n/messages/en.gen.d.ts +5 -0
  98. package/dist/i18n/messages/en.gen.js +656 -0
  99. package/dist/i18n/messages/es.gen.d.ts +5 -0
  100. package/dist/i18n/messages/es.gen.js +656 -0
  101. package/dist/i18n/messages/et.gen.d.ts +5 -0
  102. package/dist/i18n/messages/et.gen.js +656 -0
  103. package/dist/i18n/messages/fr.gen.d.ts +5 -0
  104. package/dist/i18n/messages/fr.gen.js +656 -0
  105. package/dist/i18n/messages/he.gen.d.ts +5 -0
  106. package/dist/i18n/messages/he.gen.js +656 -0
  107. package/dist/i18n/messages/hi.gen.d.ts +5 -0
  108. package/dist/i18n/messages/hi.gen.js +656 -0
  109. package/dist/i18n/messages/hu.gen.d.ts +5 -0
  110. package/dist/i18n/messages/hu.gen.js +656 -0
  111. package/dist/i18n/messages/locales.d.ts +5 -0
  112. package/dist/i18n/messages/locales.js +22 -0
  113. package/dist/i18n/messages/lt.gen.d.ts +5 -0
  114. package/dist/i18n/messages/lt.gen.js +656 -0
  115. package/dist/i18n/messages/lv.gen.d.ts +5 -0
  116. package/dist/i18n/messages/lv.gen.js +656 -0
  117. package/dist/i18n/messages/pl.gen.d.ts +5 -0
  118. package/dist/i18n/messages/pl.gen.js +656 -0
  119. package/dist/i18n/messages/pt-BR.gen.d.ts +5 -0
  120. package/dist/i18n/messages/pt-BR.gen.js +656 -0
  121. package/dist/i18n/messages/sk.gen.d.ts +5 -0
  122. package/dist/i18n/messages/sk.gen.js +656 -0
  123. package/dist/i18n/messages/tr.gen.d.ts +5 -0
  124. package/dist/i18n/messages/tr.gen.js +656 -0
  125. package/dist/i18n/messages/zh-CN.gen.d.ts +5 -0
  126. package/dist/i18n/messages/zh-CN.gen.js +656 -0
  127. package/dist/i18n/messages.d.ts +2 -3
  128. package/dist/i18n/messages.js +1 -19
  129. package/dist/internal/noteMarkerAttrs.d.ts +8 -0
  130. package/dist/internal/noteMarkerAttrs.js +16 -0
  131. package/dist/internal/pageBreakRunSourceDescendantIndex.js +1 -0
  132. package/dist/internal/prosemirrorAttrBoundary.d.ts +21 -0
  133. package/dist/internal/prosemirrorAttrBoundary.js +50 -0
  134. package/dist/layout-bridge/convert/footnoteLayout.d.ts +1 -0
  135. package/dist/layout-bridge/convert/footnoteLayout.js +3 -3
  136. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +1 -0
  137. package/dist/layout-bridge/convert/headerFooterLayout.js +1 -0
  138. package/dist/layout-bridge/convert/noteReferences.d.ts +1 -3
  139. package/dist/layout-bridge/convert/noteReferences.js +1 -6
  140. package/dist/layout-bridge/convert/paragraphRuns.js +2 -4
  141. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +2 -2
  142. package/dist/layout-bridge/convert/toFlowBlocks.js +2 -2
  143. package/dist/managers/DocumentLoaderManager.d.ts +1 -0
  144. package/dist/managers/DocumentLoaderManager.js +8 -1
  145. package/dist/markdown/renderBlock.js +15 -1
  146. package/dist/markdown/renderParagraph.js +9 -13
  147. package/dist/markdown/renderRuns.js +3 -2
  148. package/dist/markdown/renderTable.js +2 -0
  149. package/dist/markdown/types.d.ts +3 -9
  150. package/dist/prosemirror/attrs/index.d.ts +2 -12
  151. package/dist/prosemirror/attrs/index.js +22 -48
  152. package/dist/prosemirror/bookmarkBoundaryAttrs.d.ts +2 -1
  153. package/dist/prosemirror/canonicalCommands.d.ts +97 -0
  154. package/dist/prosemirror/canonicalCommands.js +28 -0
  155. package/dist/prosemirror/commands/pageBreak.js +15 -1
  156. package/dist/prosemirror/commentReferenceAttrs.d.ts +2 -1
  157. package/dist/prosemirror/conversion/fromProseDoc.js +91 -19
  158. package/dist/prosemirror/conversion/listRenderingDefinition.d.ts +6 -0
  159. package/dist/prosemirror/conversion/listRenderingDefinition.js +97 -0
  160. package/dist/prosemirror/conversion/toProseDoc.d.ts +4 -3
  161. package/dist/prosemirror/conversion/toProseDoc.js +51 -11
  162. package/dist/prosemirror/executeEditorCommand.d.ts +11 -0
  163. package/dist/prosemirror/executeEditorCommand.js +26 -0
  164. package/dist/prosemirror/extensions/StarterKit.js +2 -0
  165. package/dist/prosemirror/extensions/core/ParagraphExtension.js +50 -19
  166. package/dist/prosemirror/extensions/features/ListExtension.js +18 -5
  167. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +5 -2
  168. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +13 -1
  169. package/dist/prosemirror/extensions/marks/TextColorExtension.js +3 -2
  170. package/dist/prosemirror/extensions/marks/TrackedChangeExtensions.js +2 -0
  171. package/dist/prosemirror/extensions/marks/markUtils.js +70 -8
  172. package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.d.ts +6 -0
  173. package/dist/prosemirror/extensions/nodes/NoteMarkerExtension.js +36 -0
  174. package/dist/prosemirror/extensions/nodes/PreservedXmlExtension.js +4 -2
  175. package/dist/prosemirror/listMarker.d.ts +1 -0
  176. package/dist/prosemirror/listMarker.js +16 -7
  177. package/dist/prosemirror/listNumbering.js +26 -5
  178. package/dist/prosemirror/listRenderingAttrs.d.ts +1 -0
  179. package/dist/prosemirror/listRenderingAttrs.js +3 -0
  180. package/dist/prosemirror/markupViewNotes.js +3 -2
  181. package/dist/prosemirror/moveRangeBoundaryAttrs.d.ts +2 -1
  182. package/dist/prosemirror/noteReferenceReview.js +5 -3
  183. package/dist/prosemirror/plugins/suggestionMode.js +50 -2
  184. package/dist/prosemirror/rangeAnchorAttrs.d.ts +2 -1
  185. package/dist/prosemirror/runFormattingFromMarks.d.ts +4 -1
  186. package/dist/prosemirror/runFormattingFromMarks.js +15 -1
  187. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +2 -1
  188. package/dist/prosemirror/runFormattingInlineCarriers.js +4 -1
  189. package/dist/prosemirror/schema/marks.d.ts +2 -0
  190. package/dist/prosemirror/schema/nodes.d.ts +10 -2
  191. package/dist/prosemirror/textBoxAnchorAttrs.d.ts +2 -1
  192. package/dist/prosemirror/textInput.js +5 -1
  193. package/dist/prosemirror/trackedRevisionPath.js +2 -1
  194. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +1 -0
  195. package/dist/prosemirror/trackedRunInlineAtoms.js +1 -0
  196. package/dist/prosemirror/validation.js +4 -0
  197. package/dist/types/content.d.ts +2 -2
  198. package/dist/utils/createDocument.js +2 -2
  199. package/package.json +14 -2
@@ -2,6 +2,7 @@ import { FONT_THEME_VALUES } from "../../../types/documentEnumValues.js";
2
2
  import { mergeFontFamily } from "../../../utils/fontFamilyMerge.js";
3
3
  import { normalizeHorizontalScalePercent } from "../../../utils/horizontalScale.js";
4
4
  import { expectCharacterSpacingMarkAttrs, expectCharacterStyleMarkAttrs, expectEmphasisMarkAttrs, expectFontFamilyMarkAttrs, expectRunFormattingOverrideMarkAttrs, expectRunShadingMarkAttrs, expectStrikeMarkAttrs, expectTextEffectMarkAttrs } from "../../attrs/index.js";
5
+ import { canonicalRunFormatting, withCanonicalCommand } from "../../canonicalCommands.js";
5
6
  import { runShadingAttrsToShading, shadingToRunShadingAttrs } from "../../conversion/runShadingMark.js";
6
7
  import { documentMarkType } from "../../documentSchema.js";
7
8
  import { selectRunFormattingCarrierRepresentations } from "../../runFormattingInlineCarriers.js";
@@ -12,6 +13,12 @@ import { applyRunFormattingOverrideMark, buildRunFormattingOverrideAttrs } from
12
13
  import { readThemeColor } from "@stll/docx-core/model";
13
14
  import { toggleMark } from "prosemirror-commands";
14
15
  //#region src/prosemirror/extensions/marks/markUtils.ts
16
+ /**
17
+ * Shared mark utility functions
18
+ *
19
+ * setMark, removeMark, isMarkActive, getMarkAttr, marksToTextFormatting,
20
+ * textFormattingToMarks, clearFormatting
21
+ */
15
22
  const isFontTheme = (value) => value !== void 0 && FONT_THEME_VALUES.some((theme) => theme === value);
16
23
  const fontFamilyAttrsToFormatting = ({ ascii, hAnsi, eastAsia, cs, hint, asciiTheme, hAnsiTheme, eastAsiaTheme, csTheme }) => ({
17
24
  ...ascii !== void 0 ? { ascii } : {},
@@ -179,8 +186,23 @@ function createMarkWithMergedAttrs(markType, currentMark, nextAttrs) {
179
186
  if (!markRequiresAttrMerge(markType)) return markType.create(nextAttrs);
180
187
  return markType.create(mergeMarkAttrs(markType, currentMark, nextAttrs));
181
188
  }
189
+ const canonicalSetMarkFormatting = ({ state, type, attrs }) => {
190
+ const markType = documentMarkType(state, type);
191
+ const { from, to, empty } = state.selection;
192
+ if (empty) return canonicalRunFormatting(state, marksToTextFormatting([createMarkWithMergedAttrs(markType, markType.isInSet(state.storedMarks ?? state.selection.$from.marks()), attrs)]));
193
+ return selectRunFormattingCarrierRepresentations({
194
+ doc: state.doc,
195
+ from,
196
+ to
197
+ }).map((representation) => ({
198
+ type: "formatRun",
199
+ from: representation.from,
200
+ to: representation.to,
201
+ patch: marksToTextFormatting([createMarkWithMergedAttrs(markType, markType.isInSet(representation.node.marks), attrs)])
202
+ }));
203
+ };
182
204
  function setMark(type, attrs) {
183
- return (state, dispatch) => {
205
+ const command = (state, dispatch) => {
184
206
  const markType = documentMarkType(state, type);
185
207
  const { from, to, empty } = state.selection;
186
208
  if (empty) {
@@ -211,6 +233,12 @@ function setMark(type, attrs) {
211
233
  }
212
234
  return true;
213
235
  };
236
+ if (!RUN_FORMATTING_MARK_NAMES.has(type.name)) return command;
237
+ return withCanonicalCommand(command, (state) => canonicalSetMarkFormatting({
238
+ state,
239
+ type,
240
+ attrs
241
+ }));
214
242
  }
215
243
  const DIRECT_FONT_PROPERTIES = [
216
244
  "color",
@@ -287,17 +315,42 @@ const withRunFormattingOverride = (command, update) => (state, dispatch) => comm
287
315
  dispatch(updateRunFormattingOverride(state, tr, update));
288
316
  } : void 0);
289
317
  /** `toggleMark` for the document's own counterpart of `type`. */
290
- const toggleDocumentMark = (type) => (state, dispatch, view) => toggleMark(documentMarkType(state, type))(state, dispatch, view);
318
+ const toggleDocumentMark = (type) => {
319
+ const command = (state, dispatch, view) => toggleMark(documentMarkType(state, type))(state, dispatch, view);
320
+ if (!RUN_FORMATTING_MARK_NAMES.has(type.name)) return command;
321
+ return withCanonicalCommand(command, (state) => {
322
+ const markType = documentMarkType(state, type);
323
+ const formatting = marksToTextFormatting([markType.create()]);
324
+ if (!isMarkActive(state, markType)) return canonicalRunFormatting(state, formatting);
325
+ const keys = markType.name === "strike" ? ["strike", "doubleStrike"] : Object.keys(formatting);
326
+ return canonicalRunFormatting(state, Object.fromEntries(keys.map((key) => [key, null])));
327
+ });
328
+ };
291
329
  /** UI toggle whose direct-formatting contract explicitly targets both script families. */
292
- const toggleMarkForAllScripts = (type, property) => (state, dispatch) => {
330
+ const toggleMarkForAllScripts = (type, property) => withCanonicalCommand((state, dispatch) => {
293
331
  const markType = documentMarkType(state, type);
294
332
  const enabled = !isMarkActive(state, markType);
295
333
  return withRunFormattingOverride(toggleMark(markType), (attrs) => updatePairedToggleAttrs(attrs, property, enabled))(state, dispatch);
296
- };
334
+ }, (state) => {
335
+ const enabled = !isMarkActive(state, documentMarkType(state, type));
336
+ return canonicalRunFormatting(state, property === "bold" ? {
337
+ bold: enabled,
338
+ boldCs: enabled
339
+ } : {
340
+ italic: enabled,
341
+ italicCs: enabled
342
+ });
343
+ });
297
344
  /** UI size command whose direct-formatting contract explicitly targets both script families. */
298
- const setFontSizeForAllScripts = (markType, size) => withRunFormattingOverride(setMark(markType, { size }), (attrs) => updateFontSizeCompanionAttrs(attrs, size));
345
+ const setFontSizeForAllScripts = (markType, size) => withCanonicalCommand(withRunFormattingOverride(setMark(markType, { size }), (attrs) => updateFontSizeCompanionAttrs(attrs, size)), (state) => canonicalRunFormatting(state, {
346
+ fontSize: size,
347
+ fontSizeCs: size
348
+ }));
299
349
  /** Clears both ordinary and complex-script direct size through the UI command boundary. */
300
- const clearFontSizeForAllScripts = (markType) => withRunFormattingOverride(removeMark(markType), (attrs) => updateFontSizeCompanionAttrs(attrs, void 0));
350
+ const clearFontSizeForAllScripts = (markType) => withCanonicalCommand(withRunFormattingOverride(removeMark(markType), (attrs) => updateFontSizeCompanionAttrs(attrs, void 0)), (state) => canonicalRunFormatting(state, {
351
+ fontSize: null,
352
+ fontSizeCs: null
353
+ }));
301
354
  function selectionHasVisibleUnderline(state, markType) {
302
355
  const { from, to, empty, $from } = state.selection;
303
356
  if (empty) {
@@ -317,10 +370,14 @@ function selectionHasVisibleUnderline(state, markType) {
317
370
  return hasVisibleUnderline;
318
371
  }
319
372
  function toggleUnderlineMark(markType) {
320
- return (state, dispatch) => setMark(markType, { style: selectionHasVisibleUnderline(state, documentMarkType(state, markType)) ? "none" : "single" })(state, dispatch);
373
+ return withCanonicalCommand((state, dispatch) => setMark(markType, { style: selectionHasVisibleUnderline(state, documentMarkType(state, markType)) ? "none" : "single" })(state, dispatch), (state) => canonicalSetMarkFormatting({
374
+ state,
375
+ type: markType,
376
+ attrs: { style: selectionHasVisibleUnderline(state, documentMarkType(state, markType)) ? "none" : "single" }
377
+ }));
321
378
  }
322
379
  function removeMark(type) {
323
- return (state, dispatch) => {
380
+ const command = (state, dispatch) => {
324
381
  const markType = documentMarkType(state, type);
325
382
  const { from, to, empty } = state.selection;
326
383
  if (empty) {
@@ -330,6 +387,11 @@ function removeMark(type) {
330
387
  if (dispatch) dispatch(state.tr.removeMark(from, to, markType).scrollIntoView());
331
388
  return true;
332
389
  };
390
+ if (!RUN_FORMATTING_MARK_NAMES.has(type.name)) return command;
391
+ return withCanonicalCommand(command, (state) => {
392
+ const formatting = marksToTextFormatting([documentMarkType(state, type).create()]);
393
+ return canonicalRunFormatting(state, Object.fromEntries(Object.keys(formatting).map((key) => [key, null])));
394
+ });
333
395
  }
334
396
  /**
335
397
  * Check if a mark is active in the current selection
@@ -0,0 +1,6 @@
1
+ import { NodeExtension } from "../types.js";
2
+ //#region src/prosemirror/extensions/nodes/NoteMarkerExtension.d.ts
3
+ declare const NOTE_MARKER_NODE_NAME = "noteMarker";
4
+ declare const NoteMarkerExtension: (options?: Partial<Record<string, unknown>> | undefined) => NodeExtension;
5
+ //#endregion
6
+ export { NOTE_MARKER_NODE_NAME, NoteMarkerExtension };
@@ -0,0 +1,36 @@
1
+ import { expectNoteMarkerAttrs } from "../../../internal/noteMarkerAttrs.js";
2
+ import { createNodeExtension } from "../create.js";
3
+ //#region src/prosemirror/extensions/nodes/NoteMarkerExtension.ts
4
+ /** An authored automatic note mark: invisible, but retained through PM JSON and edits. */
5
+ const NOTE_MARKER_NODE_NAME = "noteMarker";
6
+ const NoteMarkerExtension = createNodeExtension({
7
+ name: NOTE_MARKER_NODE_NAME,
8
+ schemaNodeName: NOTE_MARKER_NODE_NAME,
9
+ nodeSpec: {
10
+ inline: true,
11
+ group: "inline",
12
+ atom: true,
13
+ marks: "_",
14
+ selectable: false,
15
+ attrs: { kind: {} },
16
+ parseDOM: [{
17
+ tag: "span[data-docx-note-marker]",
18
+ getAttrs(node) {
19
+ if (!(node instanceof HTMLElement)) return false;
20
+ const kind = node.dataset["docxNoteMarker"];
21
+ return kind === "footnote" || kind === "endnote" ? { kind } : false;
22
+ }
23
+ }],
24
+ toDOM(node) {
25
+ const { kind } = expectNoteMarkerAttrs(node);
26
+ return ["span", {
27
+ "data-docx-note-marker": kind,
28
+ "aria-hidden": "true",
29
+ contenteditable: "false",
30
+ style: "display: none;"
31
+ }];
32
+ }
33
+ }
34
+ });
35
+ //#endregion
36
+ export { NOTE_MARKER_NODE_NAME, NoteMarkerExtension };
@@ -25,7 +25,8 @@ const PreservedXmlExtension = createNodeExtension({
25
25
  attrs: {
26
26
  xml: {},
27
27
  text: { default: "" },
28
- level: { default: PRESERVED_XML_LEVELS.run }
28
+ level: { default: PRESERVED_XML_LEVELS.run },
29
+ foldedListNumber: { default: void 0 }
29
30
  },
30
31
  parseDOM: [{
31
32
  tag: "span[data-docx-preserved-xml]",
@@ -42,7 +43,8 @@ const PreservedXmlExtension = createNodeExtension({
42
43
  }
43
44
  }],
44
45
  toDOM(node) {
45
- const { xml, text, level } = expectPreservedXmlAttrs(node);
46
+ const { xml, text, level, foldedListNumber } = expectPreservedXmlAttrs(node);
47
+ if (foldedListNumber) return ["span", { contenteditable: "false" }];
46
48
  return [
47
49
  "span",
48
50
  {
@@ -55,6 +55,7 @@ declare const CLEARED_LIST_RENDERING_ATTRS: Readonly<{
55
55
  listMarkerSuffix: null;
56
56
  listMarkerAllCaps: null;
57
57
  listImplicitChildLevelAdvances: null;
58
+ listFoldedMarkerSuffix: null;
58
59
  listMarkerSecondSlotOffsetTwips: null;
59
60
  listLevelNumFmts: null;
60
61
  listLevelStarts: null;
@@ -17,6 +17,7 @@ const CLEARED_LIST_RENDERING_ATTRS = Object.freeze({
17
17
  listMarkerSuffix: null,
18
18
  listMarkerAllCaps: null,
19
19
  listImplicitChildLevelAdvances: null,
20
+ listFoldedMarkerSuffix: null,
20
21
  listMarkerSecondSlotOffsetTwips: null,
21
22
  listLevelNumFmts: null,
22
23
  listLevelStarts: null,
@@ -76,6 +77,7 @@ function previousListAttrs(attrs) {
76
77
  ...previous.listNumFmt !== void 0 ? { listNumFmt: previous.listNumFmt } : {},
77
78
  ...previous.listMarker !== void 0 ? { listMarker: previous.listMarker } : {},
78
79
  ...previous.listMarkerTemplate !== void 0 ? { listMarkerTemplate: previous.listMarkerTemplate } : {},
80
+ ...previous.listFoldedMarkerSuffix !== void 0 ? { listFoldedMarkerSuffix: previous.listFoldedMarkerSuffix } : {},
79
81
  ...previous.listMarkerHidden !== void 0 ? { listMarkerHidden: previous.listMarkerHidden } : {},
80
82
  ...previous.listMarkerFormatting !== void 0 ? { listMarkerFormatting: previous.listMarkerFormatting } : {},
81
83
  ...previous.listMarkerAlignment !== void 0 ? { listMarkerAlignment: previous.listMarkerAlignment } : {},
@@ -178,6 +180,7 @@ function formatNumberedMarker(counters, level) {
178
180
  }
179
181
  function advanceListMarker(attrs, state) {
180
182
  const markerTemplate = attrs.listMarkerTemplate ?? attrs.listMarker;
183
+ const foldedMarkerSuffix = attrs.listFoldedMarkerSuffix ?? void 0;
181
184
  const level = paragraphNumberingLevel(attrs.numPr) ?? 0;
182
185
  if (!Number.isInteger(level) || level < 0 || level > 8) return null;
183
186
  const numId = paragraphNumberingReferenceId(attrs.numPr);
@@ -205,7 +208,9 @@ function advanceListMarker(attrs, state) {
205
208
  fromStyle: false,
206
209
  numId: null
207
210
  };
208
- return convertBulletToUnicode(attrs.listMarker ?? markerTemplate ?? "", bulletMarkerFontName(attrs.listMarkerFormatting));
211
+ if (foldedMarkerSuffix !== void 0 && attrs.listMarkerTemplate == null) return attrs.listMarker ?? null;
212
+ const marker = convertBulletToUnicode(attrs.listMarkerTemplate ?? attrs.listMarker ?? "", bulletMarkerFontName(attrs.listMarkerFormatting));
213
+ return foldedMarkerSuffix === void 0 ? marker : `${marker}\t${foldedMarkerSuffix}`;
209
214
  }
210
215
  const firstInstanceEncounter = !state.counters.has(numId);
211
216
  let counters = state.counters.get(numId) ?? Array.from({ length: 9 }, () => NaN);
@@ -250,12 +255,16 @@ function advanceListMarker(attrs, state) {
250
255
  numId
251
256
  };
252
257
  const levelFormats = attrs.listLevelNumFmts ?? (attrs.listNumFmt ? [attrs.listNumFmt] : void 0);
253
- if (markerTemplate?.includes("%")) return resolveListTemplate({
254
- template: markerTemplate,
255
- counters,
256
- levelFormats,
257
- forceDecimal: attrs.listIsLegal
258
- });
258
+ if (markerTemplate?.includes("%") && (foldedMarkerSuffix === void 0 || attrs.listMarkerTemplate != null)) {
259
+ const marker = resolveListTemplate({
260
+ template: markerTemplate,
261
+ counters,
262
+ levelFormats,
263
+ forceDecimal: attrs.listIsLegal
264
+ });
265
+ return foldedMarkerSuffix === void 0 ? marker : `${marker}\t${foldedMarkerSuffix}`;
266
+ }
267
+ if (foldedMarkerSuffix !== void 0 && attrs.listMarkerTemplate != null) return `${attrs.listMarkerTemplate}\t${foldedMarkerSuffix}`;
259
268
  if (attrs.listMarker) return attrs.listMarker;
260
269
  if ((levelFormats?.[level] ?? attrs.listNumFmt) === "none" || attrs.listMarker === "") return null;
261
270
  return formatNumberedMarker(counters, level);
@@ -2,6 +2,7 @@ import { mintListInstance, restartListInstance } from "../docx/listNumberingInst
2
2
  import { createNumberingMap, isBulletLevel } from "../docx/numberingParser.js";
3
3
  import { paragraphNumberingLevel, paragraphNumberingReferenceId } from "../docx/numberingReference.js";
4
4
  import { expectParagraphAttrs } from "./attrs/index.js";
5
+ import { withCanonicalCommand } from "./canonicalCommands.js";
5
6
  import { paragraphPropertiesSnapshot } from "./commands/propertyChangeScope.js";
6
7
  import { listRenderingFor, recordsListRendering } from "./listRendering.js";
7
8
  import { LIST_RENDERING_ATTR_KEYS } from "./listRenderingAttrs.js";
@@ -11,6 +12,22 @@ import { getDocumentStyleResolver } from "./plugins/documentStyleState.js";
11
12
  import { SUGGESTION_META, makeRevisionInfo } from "./plugins/suggestionMode.js";
12
13
  import { listAttrsFromNumbering, listLevelIndentAttrPatch } from "./styles/resolvedStyleAttrs.js";
13
14
  //#region src/prosemirror/listNumbering.ts
15
+ /**
16
+ * Which numbering instance a list command puts a paragraph in, and the
17
+ * *Restart Numbering*, *Continue Numbering* and *Set Numbering Value* commands.
18
+ *
19
+ * A paragraph made into a list item continues the list directly above or below
20
+ * it when that list is of the requested kind (and, for a typed marker, has the
21
+ * typed format). Otherwise it starts a new list: a new `w:num`, defined on the
22
+ * paragraphs it numbers (see `docx/listNumberingInstances.ts`). A list that a
23
+ * paragraph style supplies (a heading's numbering from `styles.xml`) is never
24
+ * joined implicitly; it belongs to the style, not to the body text around it.
25
+ *
26
+ * Every change made while suggesting is recorded as one `w:pPrChange` per
27
+ * paragraph. A paragraph that already carries one keeps a single record whose
28
+ * previous state is the paragraph's original, so rejecting it restores what the
29
+ * paragraph was before any of the tracked changes.
30
+ */
14
31
  const PARAGRAPH_NODE = "paragraph";
15
32
  /**
16
33
  * The paragraph's properties as a `w:pPrChange` records them before a list
@@ -187,6 +204,7 @@ const listItemAttrs = (attrs, { numId, ilvl }, numbering) => ({
187
204
  ilvl
188
205
  }, numbering),
189
206
  listImplicitChildLevelAdvances: attrs["listImplicitChildLevelAdvances"] ?? null,
207
+ listFoldedMarkerSuffix: attrs["listFoldedMarkerSuffix"] ?? void 0,
190
208
  listMarkerSecondSlotOffsetTwips: attrs["listMarkerSecondSlotOffsetTwips"] ?? null
191
209
  });
192
210
  /**
@@ -260,7 +278,7 @@ const moveItems = ({ state, items, numId, numbering }) => {
260
278
  * its list move to a new instance of the same definition, whose
261
279
  * `w:startOverride` at the item's level is `value`.
262
280
  */
263
- const setNumberingValue = (value) => (state, dispatch) => {
281
+ const setNumberingValue = (value) => withCanonicalCommand((state, dispatch) => {
264
282
  if (!Number.isSafeInteger(value) || value < 0) return false;
265
283
  const selected = selectedListParagraph(state);
266
284
  const numbering = getDocumentNumbering(state);
@@ -279,9 +297,12 @@ const setNumberingValue = (value) => (state, dispatch) => {
279
297
  numbering: createNumberingMap(restarted.definitions)
280
298
  }));
281
299
  return true;
282
- };
300
+ }, () => [{
301
+ type: "restartNumbering",
302
+ start: value
303
+ }]);
283
304
  /** *Restart at 1*: the selected item starts its list over at one. */
284
- const restartNumbering = (state, dispatch) => setNumberingValue(1)(state, dispatch);
305
+ const restartNumbering = withCanonicalCommand((state, dispatch) => setNumberingValue(1)(state, dispatch), () => [{ type: "restartNumbering" }]);
285
306
  /** The nearest list before `beforePos` of the kind `membership` has, other than its own. */
286
307
  const previousListOfKind = (state, beforePos, membership) => {
287
308
  const numbering = getDocumentNumbering(state);
@@ -301,7 +322,7 @@ const previousListOfKind = (state, beforePos, membership) => {
301
322
  * join the nearest earlier list of the same kind, so their numbers carry on
302
323
  * from it. Not applicable when no such list precedes the item.
303
324
  */
304
- const continueNumbering = (state, dispatch) => {
325
+ const continueNumbering = withCanonicalCommand((state, dispatch) => {
305
326
  const selected = selectedListParagraph(state);
306
327
  const numbering = getDocumentNumbering(state);
307
328
  if (!selected || !numbering) return false;
@@ -315,7 +336,7 @@ const continueNumbering = (state, dispatch) => {
315
336
  numbering
316
337
  }));
317
338
  return true;
318
- };
339
+ }, () => [{ type: "continueNumbering" }]);
319
340
  const NO_LIST_NUMBERING_MENU = { type: "none" };
320
341
  /**
321
342
  * Whether the selection is in a list item whose numbering can be restarted
@@ -6,6 +6,7 @@ type ListRenderingAttrField = Exclude<keyof document_d_exports.ListRendering, "l
6
6
  declare const LIST_RENDERING_ATTR_BY_FIELD: {
7
7
  readonly marker: "listMarker";
8
8
  readonly markerTemplate: "listMarkerTemplate";
9
+ readonly foldedMarkerSuffix: "listFoldedMarkerSuffix";
9
10
  readonly isBullet: "listIsBullet";
10
11
  readonly isLegal: "listIsLegal";
11
12
  readonly numFmt: "listNumFmt";
@@ -12,6 +12,7 @@ import { paragraphNumberingLevel } from "@stll/docx-core/model";
12
12
  const LIST_RENDERING_ATTR_BY_FIELD = {
13
13
  marker: "listMarker",
14
14
  markerTemplate: "listMarkerTemplate",
15
+ foldedMarkerSuffix: "listFoldedMarkerSuffix",
15
16
  isBullet: "listIsBullet",
16
17
  isLegal: "listIsLegal",
17
18
  numFmt: "listNumFmt",
@@ -41,6 +42,7 @@ const listRenderingAttrPatch = (rendering) => {
41
42
  const patch = {
42
43
  listMarker: rendering.marker || void 0,
43
44
  listMarkerTemplate: rendering.markerTemplate || void 0,
45
+ listFoldedMarkerSuffix: rendering.foldedMarkerSuffix,
44
46
  listIsBullet: rendering.isBullet || void 0,
45
47
  listIsLegal: rendering.isLegal || void 0,
46
48
  listNumFmt: rendering.numFmt || void 0,
@@ -73,6 +75,7 @@ const hasListRendering = (attrs) => attrs.listMarker != null || attrs.listIsBull
73
75
  const listRenderingFromAttrs = ({ attrs, numId }) => {
74
76
  const optional = {
75
77
  markerTemplate: attrs.listMarkerTemplate ?? void 0,
78
+ foldedMarkerSuffix: attrs.listFoldedMarkerSuffix ?? void 0,
76
79
  isLegal: attrs.listIsLegal ?? void 0,
77
80
  numFmt: attrs.listNumFmt ?? void 0,
78
81
  markerHidden: attrs.listMarkerHidden ?? void 0,
@@ -10,10 +10,11 @@ const resolvedNote = (note, mode, state, document) => {
10
10
  const styleResolver = getDocumentStyleResolver(state);
11
11
  const cached = resolvedNotes.get(note)?.get(mode);
12
12
  if (cached?.styleResolver === styleResolver) return cached.note;
13
- const { styles, theme } = document.package;
13
+ const { styles, theme, numbering } = document.package;
14
14
  const doc = footnoteToProseDoc(note.content, {
15
15
  ...styles !== void 0 && { styles },
16
- ...theme !== void 0 && { theme }
16
+ ...theme !== void 0 && { theme },
17
+ ...numbering !== void 0 && { numbering }
17
18
  });
18
19
  const result = resolveWholeStory({
19
20
  doc,
@@ -1,5 +1,6 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
- import { ReadProseMirrorAttrsResult } from "./attrs/index.js";
2
+ import { ReadProseMirrorAttrsResult } from "../internal/prosemirrorAttrBoundary.js";
3
+ import "./attrs/index.js";
3
4
  import { Node } from "prosemirror-model";
4
5
  //#region src/prosemirror/moveRangeBoundaryAttrs.d.ts
5
6
  type MoveRangeMarker = Extract<document_d_exports.ParagraphContent, {
@@ -64,7 +64,8 @@ const restoredNote = (note, document, reference) => {
64
64
  const { styles, theme, numbering } = document.package;
65
65
  const doc = footnoteToProseDoc(note.content, {
66
66
  ...styles !== void 0 && { styles },
67
- ...theme !== void 0 && { theme }
67
+ ...theme !== void 0 && { theme },
68
+ ...numbering !== void 0 && { numbering }
68
69
  });
69
70
  const revisions = noteDeletionRevisions(doc, reference);
70
71
  if (revisions.length === 0) return note;
@@ -164,10 +165,11 @@ const deleteNoteWithReference = (transform, reference) => {
164
165
  * deleted too, by the reference's author at the reference's date.
165
166
  */
166
167
  const deletedNote = (note, document, reference) => {
167
- const { styles, theme } = document.package;
168
+ const { styles, theme, numbering } = document.package;
168
169
  const doc = footnoteToProseDoc(note.content, {
169
170
  ...styles !== void 0 && { styles },
170
- ...theme !== void 0 && { theme }
171
+ ...theme !== void 0 && { theme },
172
+ ...numbering !== void 0 && { numbering }
171
173
  });
172
174
  const transform = deleteNoteWithReference(new Transform(doc), reference);
173
175
  if (!transform.docChanged) return note;
@@ -527,7 +527,9 @@ function applySuggestionInsert(view, from, to, text, pluginState) {
527
527
  const tr = view.state.tr;
528
528
  tr.setMeta(SUGGESTION_META, true);
529
529
  tr.setMeta(SUGGESTED_TEXT_INPUT_META, text);
530
- const selectsAll = view.state.selection instanceof AllSelection;
530
+ const { selection } = view.state;
531
+ const typesOverSelection = !selection.empty && selection.from === from && selection.to === to;
532
+ const selectsAll = selection instanceof AllSelection;
531
533
  if (selectsAll) {
532
534
  from = Math.max(from, Selection.atStart(view.state.doc).from);
533
535
  to = Math.min(to, Selection.atEnd(view.state.doc).to);
@@ -548,7 +550,7 @@ function applySuggestionInsert(view, from, to, text, pluginState) {
548
550
  for (const mark of replacedFormatting) tr.addMark(insertAt, insertAt + text.length, mark);
549
551
  }
550
552
  separateSplitStretch(tr, insertAt, insertAt + text.length, insertAttrs.revisionId);
551
- if (view.state.selection instanceof AllSelection) tr.setSelection(TextSelection.create(tr.doc, insertAt + text.length));
553
+ if (typesOverSelection) tr.setSelection(TextSelection.create(tr.doc, insertAt + text.length));
552
554
  view.dispatch(tr.scrollIntoView());
553
555
  return true;
554
556
  }
@@ -895,6 +897,38 @@ function recordSplitParagraph(tr, before, step, insertedFrom, insertedTo, attrs)
895
897
  });
896
898
  }
897
899
  /**
900
+ * The inline content a step removed from within one textblock, and where it
901
+ * started: the node a node selection held (an image, a field, a note
902
+ * reference) or a range of runs. Null for a step that removed nothing, or removed paragraph or table
903
+ * structure the catch-all cannot put back.
904
+ */
905
+ function replacedInline(before, step) {
906
+ if (!(step instanceof ReplaceStep) || !before || step.from === step.to) return null;
907
+ const $from = before.resolve(step.from);
908
+ if (!$from.parent.inlineContent || !$from.sameParent(before.resolve(step.to))) return null;
909
+ return {
910
+ from: step.from,
911
+ content: $from.parent.content.cut($from.parentOffset, step.to - $from.start())
912
+ };
913
+ }
914
+ /**
915
+ * A transaction the plugin did not build (a command, a default paste, a
916
+ * keymap) replaced inline content directly. Put it back in front of what
917
+ * replaced it as a tracked deletion, as typing over a selection does, so
918
+ * rejecting restores it and accepting removes it. The author's own
919
+ * insertions are retracted instead.
920
+ */
921
+ function restoreReplacedInline({ tr, replaced, insertionType, deletionType, pluginState }) {
922
+ for (const { at, content } of replaced) {
923
+ const pos = tr.mapping.map(at, -1);
924
+ const $pos = tr.doc.resolve(pos);
925
+ const index = $pos.index();
926
+ if (!$pos.parent.canReplace(index, index, content)) continue;
927
+ tr.insert(pos, content);
928
+ markRangeAsDeleted(tr, tr.doc, pos, pos + content.size, insertionType, deletionType, pluginState);
929
+ }
930
+ }
931
+ /**
898
932
  * Create the suggestion mode plugin.
899
933
  * When active, text edits become tracked changes.
900
934
  */
@@ -1039,9 +1073,16 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
1039
1073
  tr.setMeta(SUGGESTION_META, true);
1040
1074
  const deletionType = newState.schema.marks["deletion"];
1041
1075
  const laterMaps = transactions.slice(transactions.indexOf(userTr) + 1).flatMap((transaction) => transaction.mapping.maps);
1076
+ const restoresReplaced = userTr.getMeta("appendedTransaction") === void 0;
1077
+ const replaced = [];
1042
1078
  for (const [stepIndex, step] of userTr.steps.entries()) {
1043
1079
  const stepMap = step.getMap();
1044
1080
  const following = new Mapping([...userTr.mapping.maps.slice(stepIndex + 1), ...laterMaps]);
1081
+ const removed = restoresReplaced ? replacedInline(userTr.docs[stepIndex], step) : null;
1082
+ if (removed) replaced.push({
1083
+ at: following.map(removed.from, -1),
1084
+ content: removed.content
1085
+ });
1045
1086
  stepMap.forEach((_oldFrom, _oldTo, stepFrom, stepTo) => {
1046
1087
  const newFrom = following.map(stepFrom, -1);
1047
1088
  const newTo = following.map(stepTo, 1);
@@ -1057,6 +1098,13 @@ function createSuggestionModePlugin(initialActive = false, author = "User") {
1057
1098
  }
1058
1099
  });
1059
1100
  }
1101
+ if (deletionType) restoreReplacedInline({
1102
+ tr,
1103
+ replaced,
1104
+ insertionType,
1105
+ deletionType,
1106
+ pluginState
1107
+ });
1060
1108
  return tr.steps.length > 0 ? tr : null;
1061
1109
  }
1062
1110
  });
@@ -1,4 +1,5 @@
1
- import { ReadProseMirrorAttrsResult } from "./attrs/index.js";
1
+ import { ReadProseMirrorAttrsResult } from "../internal/prosemirrorAttrBoundary.js";
2
+ import "./attrs/index.js";
2
3
  import { RangeAnchorAttrs } from "./emptyRangeAnchor.js";
3
4
  import { Node } from "prosemirror-model";
4
5
  //#region src/prosemirror/rangeAnchorAttrs.d.ts
@@ -1,6 +1,7 @@
1
1
  import { document_d_exports } from "../types/document.js";
2
2
  import { RunStyleResolver } from "./runStyleFormatting.js";
3
3
  import { Mark } from "prosemirror-model";
4
+ import { RunPropsPatch } from "@stll/docx-core/ops";
4
5
  //#region src/prosemirror/runFormattingFromMarks.d.ts
5
6
  /**
6
7
  * Convert ProseMirror marks to TextFormatting
@@ -12,7 +13,9 @@ type MarksToTextFormattingOptions = {
12
13
  paragraphMarkPrecedesStyle?: boolean | undefined;
13
14
  styleResolver?: RunStyleResolver | null | undefined;
14
15
  };
16
+ /** Overlay only changed visual marks; private authored properties stay with the run. */
17
+ declare const runFormattingPatchFromMarks: (beforeMarks: readonly Mark[], afterMarks: readonly Mark[]) => RunPropsPatch;
15
18
  declare const sameFormattingValue: (left: unknown, right: unknown) => boolean;
16
19
  declare function marksToTextFormatting(marks: readonly Mark[], options?: MarksToTextFormattingOptions): document_d_exports.TextFormatting;
17
20
  //#endregion
18
- export { MarksToTextFormattingOptions, marksToTextFormatting, sameFormattingValue };
21
+ export { MarksToTextFormattingOptions, marksToTextFormatting, runFormattingPatchFromMarks, sameFormattingValue };
@@ -203,6 +203,20 @@ const changedVisualFormattingGroups = (observedFormatting, expectedFormatting) =
203
203
  }
204
204
  return changed;
205
205
  };
206
+ /** Overlay only changed visual marks; private authored properties stay with the run. */
207
+ const runFormattingPatchFromMarks = (beforeMarks, afterMarks) => {
208
+ const observedMarks = (marks) => marks.filter(({ type }) => type.name !== "runFormattingOverride");
209
+ const before = marksToTextFormatting(observedMarks(beforeMarks));
210
+ const after = marksToTextFormatting(observedMarks(afterMarks));
211
+ const changed = changedVisualFormattingGroups(after, before);
212
+ const patch = before.styleId === after.styleId ? {} : { styleId: after.styleId ?? null };
213
+ const isFormattingKey = (key) => Object.hasOwn(RUN_FORMATTING_VISUAL_GROUPS, key);
214
+ for (const [key, group] of Object.entries(RUN_FORMATTING_VISUAL_GROUPS)) {
215
+ if (!isFormattingKey(key) || group === null || !changed.has(group)) continue;
216
+ Reflect.set(patch, key, after[key] ?? null);
217
+ }
218
+ return patch;
219
+ };
206
220
  const VISUAL_BOOLEAN_FORMATTING_PROPERTIES = /* @__PURE__ */ new Set([
207
221
  "allCaps",
208
222
  "bold",
@@ -564,4 +578,4 @@ function marksToTextFormatting(marks, options) {
564
578
  };
565
579
  }
566
580
  //#endregion
567
- export { marksToTextFormatting, sameFormattingValue };
581
+ export { marksToTextFormatting, runFormattingPatchFromMarks, sameFormattingValue };
@@ -1,7 +1,7 @@
1
1
  import { Mark, Node } from "prosemirror-model";
2
2
  import { Transaction } from "prosemirror-state";
3
3
  //#region src/prosemirror/runFormattingInlineCarriers.d.ts
4
- type RunFormattingInlineAtomDisposition = "break-run" | "field-run" | "not-a-run" | "page-break-carrier" | "preserved-xml-run" | "structured-field" | "symbol-run" | "tab-run" | "text-run";
4
+ type RunFormattingInlineAtomDisposition = "break-run" | "field-run" | "not-a-run" | "note-marker-run" | "page-break-carrier" | "preserved-xml-run" | "structured-field" | "symbol-run" | "tab-run" | "text-run";
5
5
  /**
6
6
  * How every inline atom maps to a serialized run-formatting carrier.
7
7
  *
@@ -18,6 +18,7 @@ declare const RUN_FORMATTING_INLINE_ATOM_DISPOSITIONS: Readonly<{
18
18
  readonly image: "not-a-run";
19
19
  readonly math: "not-a-run";
20
20
  readonly moveRangeBoundary: "not-a-run";
21
+ readonly noteMarker: "note-marker-run";
21
22
  readonly pageBreakRun: "page-break-carrier";
22
23
  readonly preservedXml: "preserved-xml-run";
23
24
  readonly rangeAnchor: "not-a-run";
@@ -20,6 +20,7 @@ const RUN_FORMATTING_INLINE_ATOM_DISPOSITIONS = Object.freeze({
20
20
  image: "not-a-run",
21
21
  math: "not-a-run",
22
22
  moveRangeBoundary: "not-a-run",
23
+ noteMarker: "note-marker-run",
23
24
  pageBreakRun: "page-break-carrier",
24
25
  preservedXml: "preserved-xml-run",
25
26
  rangeAnchor: "not-a-run",
@@ -52,6 +53,7 @@ const CONTROL_CHARACTER_BY_DISPOSITION = Object.freeze({
52
53
  "break-run": "\n",
53
54
  "field-run": null,
54
55
  "not-a-run": null,
56
+ "note-marker-run": null,
55
57
  "page-break-carrier": null,
56
58
  "preserved-xml-run": null,
57
59
  "structured-field": null,
@@ -179,7 +181,8 @@ const runFormattingCarrierReviewText = (carrier) => {
179
181
  case "tab-run":
180
182
  case "break-run": return CONTROL_CHARACTER_BY_DISPOSITION[carrier.disposition];
181
183
  case "text-run": return carrier.node.text ?? "";
182
- case "page-break-carrier": return "";
184
+ case "page-break-carrier":
185
+ case "note-marker-run": return "";
183
186
  case "symbol-run": {
184
187
  const { char } = expectSymbolAttrs(carrier.node);
185
188
  return decodeOoxmlSymbolCharacter(char) ?? "�";
@@ -107,6 +107,7 @@ type TrackedRevisionAncestor = {
107
107
  utcDate?: string;
108
108
  initials?: string;
109
109
  outerWrapperCount: number;
110
+ resolutionJoins?: document_d_exports.Insertion["resolutionJoins"];
110
111
  };
111
112
  type TrackedChangeMarkAttrs = {
112
113
  revisionId: number;
@@ -119,6 +120,7 @@ type TrackedChangeMarkAttrs = {
119
120
  moveKind?: "moveTo" | "moveFrom";
120
121
  /** Number of inline-wrapper layers authored outside this revision. */
121
122
  _docxOuterWrapperCount?: number;
123
+ _docxResolutionJoins?: document_d_exports.Insertion["resolutionJoins"];
122
124
  /** Outer revisions, in authored order, that ProseMirror cannot hold as nested marks. */
123
125
  _docxRevisionAncestors?: readonly TrackedRevisionAncestor[];
124
126
  /** Defaults to `"user"`; `"suggested"` for AI-proposed, non-serialized edits. */