@stll/folio-core 0.36.0 → 0.37.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/README.md +59 -1
  2. package/dist/ai-edits/apply.js +689 -367
  3. package/dist/ai-edits/block-identity.d.ts +4 -1
  4. package/dist/ai-edits/block-identity.js +4 -1
  5. package/dist/ai-edits/blockRange.js +14 -14
  6. package/dist/ai-edits/clean-text.d.ts +40 -1
  7. package/dist/ai-edits/clean-text.js +52 -2
  8. package/dist/ai-edits/headless.d.ts +3 -1
  9. package/dist/ai-edits/headless.js +133 -71
  10. package/dist/ai-edits/index.d.ts +3 -3
  11. package/dist/ai-edits/index.js +2 -2
  12. package/dist/ai-edits/read.js +38 -20
  13. package/dist/ai-edits/snapshot.d.ts +14 -6
  14. package/dist/ai-edits/snapshot.js +99 -19
  15. package/dist/ai-edits/table-cell-mutations.js +1 -1
  16. package/dist/ai-edits/table-row-column-mutations.js +7 -0
  17. package/dist/ai-edits/table-template.d.ts +11 -1
  18. package/dist/ai-edits/table-template.js +49 -17
  19. package/dist/ai-edits/types.d.ts +60 -57
  20. package/dist/ai-suggestions/conflict.js +1 -4
  21. package/dist/ai-suggestions/text-positions.d.ts +8 -0
  22. package/dist/ai-suggestions/text-positions.js +27 -5
  23. package/dist/compare/__fixtures__/body-sequence.js +3 -4
  24. package/dist/compare/column-alignment.d.ts +13 -13
  25. package/dist/compare/column-alignment.js +78 -39
  26. package/dist/compare/compare.d.ts +4 -3
  27. package/dist/compare/compare.js +41 -5
  28. package/dist/compare/content-alignment.d.ts +95 -0
  29. package/dist/compare/content-alignment.js +1450 -0
  30. package/dist/compare/content-types.d.ts +100 -0
  31. package/dist/compare/content-types.js +0 -0
  32. package/dist/compare/content.d.ts +209 -0
  33. package/dist/compare/content.js +885 -0
  34. package/dist/compare/formatting.d.ts +5 -5
  35. package/dist/compare/formatting.js +6 -4
  36. package/dist/compare/plan.d.ts +6 -1
  37. package/dist/compare/plan.js +201 -569
  38. package/dist/compare/scenario.d.ts +2 -2
  39. package/dist/compare/types.d.ts +3 -3
  40. package/dist/compare/verification.d.ts +2 -2
  41. package/dist/compare/verification.js +25 -8
  42. package/dist/compat/eigenpal.d.ts +5 -3
  43. package/dist/compat/eigenpal.js +3 -2
  44. package/dist/controller/headerFooterEditorManager.js +14 -6
  45. package/dist/controller/hiddenEditorManager.d.ts +7 -2
  46. package/dist/controller/hiddenEditorManager.js +15 -6
  47. package/dist/controller/layoutPipeline.js +5 -3
  48. package/dist/controller/noteEditorManager.js +12 -7
  49. package/dist/display-list/build/headerFooterPrimitives.js +1 -0
  50. package/dist/display-list/build/storyPrimitives.d.ts +5 -2
  51. package/dist/display-list/build/storyPrimitives.js +60 -3
  52. package/dist/display-list/build/tablePrimitives.js +30 -0
  53. package/dist/display-list/primitives.d.ts +1 -1
  54. package/dist/document-operations.d.ts +8 -6
  55. package/dist/document-operations.js +121 -26
  56. package/dist/docx/blockContentParser.js +6 -27
  57. package/dist/docx/ensureParaIds.js +9 -4
  58. package/dist/docx/numberingParser.d.ts +3 -1
  59. package/dist/docx/numberingParser.js +4 -1
  60. package/dist/docx/paragraphParser.js +7 -6
  61. package/dist/docx/paragraphTraversal.js +30 -34
  62. package/dist/docx/rezip.d.ts +0 -8
  63. package/dist/docx/rezip.js +41 -16
  64. package/dist/docx/runParser.js +4 -2
  65. package/dist/docx/serializer/paragraphSerializer.js +2 -0
  66. package/dist/docx/serializer/runSerializer.js +5 -3
  67. package/dist/docx/serializer/trackedChangeAttributes.d.ts +3 -1
  68. package/dist/docx/serializer/trackedChangeAttributes.js +11 -1
  69. package/dist/docx/server/build.d.ts +1 -1
  70. package/dist/headless-layout.js +5 -4
  71. package/dist/index.d.ts +5 -3
  72. package/dist/index.js +3 -2
  73. package/dist/internal/headlessRevisionResolution.d.ts +23 -0
  74. package/dist/internal/headlessRevisionResolution.js +176 -0
  75. package/dist/internal/headlessRevisionResolutionGuard.d.ts +12 -0
  76. package/dist/internal/headlessRevisionResolutionGuard.js +28 -0
  77. package/dist/internal/pageBreakRunDescendantIndex.d.ts +9 -0
  78. package/dist/internal/pageBreakRunDescendantIndex.js +27 -0
  79. package/dist/internal/pageBreakRunPartition.d.ts +26 -0
  80. package/dist/internal/pageBreakRunPartition.js +35 -0
  81. package/dist/internal/pageBreakRunSourceDescendantIndex.d.ts +15 -0
  82. package/dist/internal/pageBreakRunSourceDescendantIndex.js +126 -0
  83. package/dist/internal/sectionEndpointResolution.d.ts +32 -0
  84. package/dist/internal/sectionEndpointResolution.js +38 -0
  85. package/dist/layout-bridge/convert/footnoteLayout.js +1 -0
  86. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +16 -4
  87. package/dist/layout-bridge/convert/headerFooterLayout.js +48 -5
  88. package/dist/layout-bridge/convert/toFlowBlocks.d.ts +4 -0
  89. package/dist/layout-bridge/convert/toFlowBlocks.js +379 -75
  90. package/dist/layout-bridge/dom/clickToPositionDom.d.ts +8 -1
  91. package/dist/layout-bridge/dom/clickToPositionDom.js +114 -40
  92. package/dist/layout-bridge/dom/textStreamDom.d.ts +24 -0
  93. package/dist/layout-bridge/dom/textStreamDom.js +75 -0
  94. package/dist/layout-bridge/headerFooterLayout.js +16 -30
  95. package/dist/layout-engine/index.js +12 -3
  96. package/dist/layout-engine/measure/tableFragmentBorderGeometry.d.ts +17 -0
  97. package/dist/layout-engine/measure/tableFragmentBorderGeometry.js +24 -0
  98. package/dist/layout-engine/renderedBreakReconciliation.js +1 -1
  99. package/dist/layout-engine/types.d.ts +7 -0
  100. package/dist/layout-painter/imageLayout.d.ts +1 -1
  101. package/dist/layout-painter/renderTable.js +20 -0
  102. package/dist/model.d.ts +1 -1
  103. package/dist/paged-layout/rangeProjection.js +6 -9
  104. package/dist/paged-layout/transactionDirtyRange.d.ts +3 -1
  105. package/dist/paged-layout/transactionDirtyRange.js +23 -1
  106. package/dist/prosemirror/attrs/index.d.ts +7 -3
  107. package/dist/prosemirror/attrs/index.js +113 -7
  108. package/dist/prosemirror/bookmarkBoundaryIntegrity.d.ts +9 -0
  109. package/dist/prosemirror/bookmarkBoundaryIntegrity.js +22 -0
  110. package/dist/prosemirror/commands/comments.d.ts +10 -1
  111. package/dist/prosemirror/commands/comments.js +167 -59
  112. package/dist/prosemirror/commands/formatPainter.d.ts +45 -10
  113. package/dist/prosemirror/commands/formatPainter.js +319 -63
  114. package/dist/prosemirror/commands/index.d.ts +2 -2
  115. package/dist/prosemirror/commands/pageBreak.d.ts +5 -2
  116. package/dist/prosemirror/commands/pageBreak.js +18 -36
  117. package/dist/prosemirror/commands/propertyChangeScope.d.ts +7 -5
  118. package/dist/prosemirror/commands/propertyChangeScope.js +27 -18
  119. package/dist/prosemirror/conversion/fromProseDoc.d.ts +7 -2
  120. package/dist/prosemirror/conversion/fromProseDoc.js +809 -209
  121. package/dist/prosemirror/conversion/runShadingMark.js +2 -2
  122. package/dist/prosemirror/conversion/toProseDoc.d.ts +26 -1
  123. package/dist/prosemirror/conversion/toProseDoc.js +416 -283
  124. package/dist/prosemirror/extensions/StarterKit.js +4 -0
  125. package/dist/prosemirror/extensions/core/ParagraphExtension.js +12 -8
  126. package/dist/prosemirror/extensions/features/ListExtension.js +95 -123
  127. package/dist/prosemirror/extensions/features/ParaIdAllocatorExtension.js +1 -1
  128. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.d.ts +27 -1
  129. package/dist/prosemirror/extensions/features/ParagraphChangeTrackerExtension.js +134 -30
  130. package/dist/prosemirror/extensions/features/pasteCleanup.js +9 -15
  131. package/dist/prosemirror/extensions/marks/BoldExtension.js +4 -3
  132. package/dist/prosemirror/extensions/marks/CharacterStyleExtension.d.ts +4 -7
  133. package/dist/prosemirror/extensions/marks/CharacterStyleExtension.js +5 -11
  134. package/dist/prosemirror/extensions/marks/FontSizeExtension.js +3 -3
  135. package/dist/prosemirror/extensions/marks/ItalicExtension.js +4 -3
  136. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts +13 -0
  137. package/dist/prosemirror/extensions/marks/PageBreakRunOwnerExtension.js +39 -0
  138. package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.d.ts +7 -1
  139. package/dist/prosemirror/extensions/marks/RunFormattingOverrideExtension.js +67 -21
  140. package/dist/prosemirror/extensions/marks/markUtils.d.ts +8 -1
  141. package/dist/prosemirror/extensions/marks/markUtils.js +88 -2
  142. package/dist/prosemirror/extensions/nodes/BookmarkBoundaryExtension.js +44 -3
  143. package/dist/prosemirror/extensions/nodes/FieldExtension.js +1 -1
  144. package/dist/prosemirror/extensions/nodes/HardBreakExtension.js +15 -4
  145. package/dist/prosemirror/extensions/nodes/PageBreakExtension.d.ts +6 -0
  146. package/dist/prosemirror/extensions/nodes/PageBreakExtension.js +6 -0
  147. package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.d.ts +6 -0
  148. package/dist/prosemirror/extensions/nodes/PageBreakRunExtension.js +36 -0
  149. package/dist/prosemirror/findReplaceSelection.js +8 -3
  150. package/dist/prosemirror/index.d.ts +3 -3
  151. package/dist/prosemirror/listMarker.d.ts +26 -1
  152. package/dist/prosemirror/listMarker.js +108 -14
  153. package/dist/prosemirror/pageBreakRunProjection.d.ts +28 -0
  154. package/dist/prosemirror/pageBreakRunProjection.js +47 -0
  155. package/dist/prosemirror/paraText.js +6 -0
  156. package/dist/prosemirror/paragraphSpacing.d.ts +29 -0
  157. package/dist/prosemirror/paragraphSpacing.js +125 -0
  158. package/dist/prosemirror/plugins/documentNumbering.d.ts +8 -0
  159. package/dist/prosemirror/plugins/documentNumbering.js +18 -0
  160. package/dist/prosemirror/plugins/pmTextScan.d.ts +3 -2
  161. package/dist/prosemirror/plugins/pmTextScan.js +14 -4
  162. package/dist/prosemirror/plugins/suggestionMode.js +8 -10
  163. package/dist/prosemirror/rebaseParagraphRunFormatting.d.ts +16 -0
  164. package/dist/prosemirror/rebaseParagraphRunFormatting.js +61 -0
  165. package/dist/prosemirror/runFormattingInlineCarriers.d.ts +64 -0
  166. package/dist/prosemirror/runFormattingInlineCarriers.js +121 -0
  167. package/dist/prosemirror/runFormattingProvenance.d.ts +12 -0
  168. package/dist/prosemirror/runFormattingProvenance.js +48 -0
  169. package/dist/prosemirror/runFormattingReconciliation.d.ts +25 -0
  170. package/dist/prosemirror/runFormattingReconciliation.js +54 -0
  171. package/dist/prosemirror/runPropertyChangeResolution.d.ts +18 -0
  172. package/dist/prosemirror/runPropertyChangeResolution.js +18 -0
  173. package/dist/prosemirror/runStyleFormatting.d.ts +50 -0
  174. package/dist/prosemirror/runStyleFormatting.js +105 -0
  175. package/dist/prosemirror/schema/index.d.ts +3 -3
  176. package/dist/prosemirror/schema/marks.d.ts +82 -9
  177. package/dist/prosemirror/schema/marks.js +73 -1
  178. package/dist/prosemirror/schema/nodes.d.ts +18 -5
  179. package/dist/prosemirror/styles/resolvedStyleAttrs.d.ts +14 -2
  180. package/dist/prosemirror/styles/resolvedStyleAttrs.js +44 -23
  181. package/dist/prosemirror/styles/styleResolver.d.ts +10 -13
  182. package/dist/prosemirror/styles/styleResolver.js +3 -3
  183. package/dist/prosemirror/styles/styleToggleCascade.d.ts +8 -1
  184. package/dist/prosemirror/styles/styleToggleCascade.js +24 -1
  185. package/dist/prosemirror/tableGridMutation.d.ts +20 -0
  186. package/dist/prosemirror/tableGridMutation.js +30 -0
  187. package/dist/prosemirror/trackedRunInlineAtoms.d.ts +31 -0
  188. package/dist/prosemirror/trackedRunInlineAtoms.js +39 -0
  189. package/dist/prosemirror/utils/visualLineNavigation.js +27 -31
  190. package/dist/prosemirror/validation.js +23 -4
  191. package/dist/render-dom/HeaderFooterSelectionOverlay.js +20 -20
  192. package/dist/render-dom/RenderedDomContext.js +17 -34
  193. package/dist/server.d.ts +4 -4
  194. package/dist/server.js +2 -2
  195. package/dist/style-engine/styleEngine.d.ts +1 -1
  196. package/dist/utils/clipboard.js +1 -1
  197. package/dist/utils/findReplace.js +38 -21
  198. package/dist/version-comparison.d.ts +38 -44
  199. package/dist/version-comparison.js +270 -401
  200. package/package.json +3 -2
@@ -1,27 +1,50 @@
1
+ import { canonicalJson } from "../../../utils/canonicalJson.js";
1
2
  import { createExtension } from "../create.js";
2
3
  import { AddMarkStep, AddNodeMarkStep, AttrStep, RemoveMarkStep, RemoveNodeMarkStep } from "prosemirror-transform";
3
4
  import { Plugin, PluginKey } from "prosemirror-state";
4
5
  //#region src/prosemirror/extensions/features/ParagraphChangeTrackerExtension.ts
5
- /**
6
- * Paragraph Change Tracker Extension
7
- *
8
- * Watches ProseMirror transactions and records which paragraph IDs (paraId)
9
- * were modified. Also detects structural changes (paragraphs added/deleted).
10
- * Used by the selective save system to patch only changed paragraphs in document.xml.
11
- */
12
6
  const paragraphChangeTrackerKey = new PluginKey("paragraphChangeTracker");
13
7
  const CLEAR_META = "clear";
14
8
  const IGNORE_META = "ignore";
15
9
  const STRUCTURAL_META = "structural";
16
- /**
17
- * Count paragraph nodes in a ProseMirror document
18
- */
19
- function countParagraphs(doc) {
20
- let count = 0;
21
- doc.descendants((node) => {
22
- if (node.type.name === "paragraph") count++;
23
- });
24
- return count;
10
+ const CHANGED_PARAGRAPH_RANGES_META = "folioChangedParagraphRanges";
11
+ const SECTION_ENDPOINT_REMOVAL_META = "folioSectionEndpointRemoval";
12
+ const isChangedParagraphRangesMeta = (value) => typeof value === "object" && value !== null && "type" in value && value.type === "changed-paragraph-ranges";
13
+ const isRemovedSectionReference = (value) => typeof value === "object" && value !== null && "part" in value && (value.part === "header" || value.part === "footer") && "type" in value && (value.type === "default" || value.type === "first" || value.type === "even") && "relationshipId" in value && typeof value.relationshipId === "string";
14
+ const isTrackedSectionEndpointRemoval = (value) => typeof value === "object" && value !== null && "type" in value && value.type === "tracked-section-endpoint-removal" && "sourceParagraphEndpointCount" in value && typeof value.sourceParagraphEndpointCount === "number" && Number.isSafeInteger(value.sourceParagraphEndpointCount) && "expectedParagraphEndpointCount" in value && typeof value.expectedParagraphEndpointCount === "number" && Number.isSafeInteger(value.expectedParagraphEndpointCount) && value.sourceParagraphEndpointCount > value.expectedParagraphEndpointCount && value.expectedParagraphEndpointCount >= 0 && "sourceEndpointFingerprint" in value && typeof value.sourceEndpointFingerprint === "string" && "expectedEndpointFingerprint" in value && typeof value.expectedEndpointFingerprint === "string" && "removedReferences" in value && Array.isArray(value.removedReferences) && value.removedReferences.every(isRemovedSectionReference);
15
+ const isTrackedSectionEndpointRemovalMeta = (value) => typeof value === "object" && value !== null && "type" in value && value.type === "tracked-section-endpoint-removal-meta" && "authorization" in value && isTrackedSectionEndpointRemoval(value.authorization);
16
+ /** Count the structural values the tracker compares for every transaction. */
17
+ function countDocumentStructure(doc) {
18
+ let paragraphs = 0;
19
+ let sectionEndpoints = 0;
20
+ const endpointRecords = [];
21
+ const visit = (parent, parentPath) => {
22
+ parent.forEach((node, _offset, index) => {
23
+ if (node.type.name === "paragraph") {
24
+ paragraphs++;
25
+ if (node.attrs["_sectionProperties"] != null || node.attrs["sectionBreakType"] != null) {
26
+ sectionEndpoints++;
27
+ endpointRecords.push({
28
+ path: parentPath.length === 0 ? `${index}` : `${parentPath}.${index}`,
29
+ paraId: node.attrs["paraId"] ?? null,
30
+ sectionBreakType: node.attrs["sectionBreakType"] ?? null,
31
+ sectionProperties: node.attrs["_sectionProperties"] ?? null
32
+ });
33
+ }
34
+ return;
35
+ }
36
+ if (node.childCount > 0) {
37
+ const path = parentPath.length === 0 ? `${index}` : `${parentPath}.${index}`;
38
+ visit(node, path);
39
+ }
40
+ });
41
+ };
42
+ visit(doc, "");
43
+ return {
44
+ paragraphs,
45
+ sectionEndpoints,
46
+ sectionEndpointFingerprint: canonicalJson(endpointRecords)
47
+ };
25
48
  }
26
49
  /**
27
50
  * Collect paraIds of all paragraphs that overlap with the given range
@@ -81,33 +104,82 @@ function createParagraphChangeTrackerPlugin() {
81
104
  key: paragraphChangeTrackerKey,
82
105
  state: {
83
106
  init(_config, state) {
107
+ const counts = countDocumentStructure(state.doc);
84
108
  return {
85
109
  changedParaIds: /* @__PURE__ */ new Set(),
86
110
  structuralChange: false,
87
111
  hasUntrackedChanges: false,
88
- paragraphCount: countParagraphs(state.doc)
112
+ paragraphCount: counts.paragraphs,
113
+ sectionEndpointCount: counts.sectionEndpoints,
114
+ sectionEndpointFingerprint: counts.sectionEndpointFingerprint,
115
+ sectionEndpointRemoval: null
89
116
  };
90
117
  },
91
118
  apply(tr, prevState) {
92
119
  const meta = tr.getMeta(paragraphChangeTrackerKey);
93
- if (meta === CLEAR_META) return {
94
- changedParaIds: /* @__PURE__ */ new Set(),
95
- structuralChange: false,
96
- hasUntrackedChanges: false,
97
- paragraphCount: prevState.paragraphCount
98
- };
99
- if (meta === IGNORE_META) return {
100
- ...prevState,
101
- paragraphCount: tr.docChanged ? countParagraphs(tr.doc) : prevState.paragraphCount
102
- };
120
+ const changedParagraphRangesMeta = tr.getMeta(CHANGED_PARAGRAPH_RANGES_META);
121
+ const sectionEndpointRemovalMeta = tr.getMeta(SECTION_ENDPOINT_REMOVAL_META);
122
+ if (meta === CLEAR_META) {
123
+ const counts = countDocumentStructure(tr.doc);
124
+ return {
125
+ changedParaIds: /* @__PURE__ */ new Set(),
126
+ structuralChange: false,
127
+ hasUntrackedChanges: false,
128
+ paragraphCount: counts.paragraphs,
129
+ sectionEndpointCount: counts.sectionEndpoints,
130
+ sectionEndpointFingerprint: counts.sectionEndpointFingerprint,
131
+ sectionEndpointRemoval: null
132
+ };
133
+ }
134
+ if (meta === IGNORE_META) {
135
+ const counts = tr.docChanged ? countDocumentStructure(tr.doc) : {
136
+ paragraphs: prevState.paragraphCount,
137
+ sectionEndpoints: prevState.sectionEndpointCount,
138
+ sectionEndpointFingerprint: prevState.sectionEndpointFingerprint
139
+ };
140
+ return {
141
+ ...prevState,
142
+ paragraphCount: counts.paragraphs,
143
+ sectionEndpointCount: counts.sectionEndpoints,
144
+ sectionEndpointRemoval: counts.sectionEndpointFingerprint === prevState.sectionEndpointFingerprint ? prevState.sectionEndpointRemoval : null,
145
+ sectionEndpointFingerprint: counts.sectionEndpointFingerprint
146
+ };
147
+ }
103
148
  if (!tr.docChanged) return prevState;
104
- const newCount = countParagraphs(tr.doc);
149
+ const counts = countDocumentStructure(tr.doc);
150
+ const newCount = counts.paragraphs;
151
+ let sectionEndpointRemoval = prevState.sectionEndpointRemoval;
152
+ if (counts.sectionEndpointFingerprint !== prevState.sectionEndpointFingerprint) if (isTrackedSectionEndpointRemovalMeta(sectionEndpointRemovalMeta) && sectionEndpointRemovalMeta.authorization.sourceEndpointFingerprint === prevState.sectionEndpointFingerprint && sectionEndpointRemovalMeta.authorization.expectedEndpointFingerprint === counts.sectionEndpointFingerprint && sectionEndpointRemovalMeta.authorization.sourceParagraphEndpointCount === prevState.sectionEndpointCount && sectionEndpointRemovalMeta.authorization.expectedParagraphEndpointCount === counts.sectionEndpoints && counts.sectionEndpoints < prevState.sectionEndpointCount) {
153
+ const authorization = sectionEndpointRemovalMeta.authorization;
154
+ sectionEndpointRemoval = {
155
+ type: "tracked-section-endpoint-removal",
156
+ sourceParagraphEndpointCount: prevState.sectionEndpointRemoval?.expectedParagraphEndpointCount === authorization.sourceParagraphEndpointCount ? prevState.sectionEndpointRemoval.sourceParagraphEndpointCount : authorization.sourceParagraphEndpointCount,
157
+ expectedParagraphEndpointCount: authorization.expectedParagraphEndpointCount,
158
+ sourceEndpointFingerprint: prevState.sectionEndpointRemoval?.expectedParagraphEndpointCount === authorization.sourceParagraphEndpointCount ? prevState.sectionEndpointRemoval.sourceEndpointFingerprint : authorization.sourceEndpointFingerprint,
159
+ expectedEndpointFingerprint: authorization.expectedEndpointFingerprint,
160
+ removedReferences: [...prevState.sectionEndpointRemoval?.expectedParagraphEndpointCount === authorization.sourceParagraphEndpointCount ? prevState.sectionEndpointRemoval.removedReferences : [], ...authorization.removedReferences]
161
+ };
162
+ } else sectionEndpointRemoval = null;
105
163
  const newState = {
106
164
  changedParaIds: new Set(prevState.changedParaIds),
107
165
  structuralChange: prevState.structuralChange || meta === STRUCTURAL_META,
108
166
  hasUntrackedChanges: prevState.hasUntrackedChanges,
109
- paragraphCount: newCount
167
+ paragraphCount: newCount,
168
+ sectionEndpointCount: counts.sectionEndpoints,
169
+ sectionEndpointFingerprint: counts.sectionEndpointFingerprint,
170
+ sectionEndpointRemoval
110
171
  };
172
+ if (isChangedParagraphRangesMeta(changedParagraphRangesMeta)) for (const batch of changedParagraphRangesMeta.batches) {
173
+ const remap = tr.mapping.slice(batch.mappingFrom);
174
+ for (const range of batch.ranges) {
175
+ const from = mapStepPosition(remap, range.from, 1);
176
+ const to = mapStepPosition(remap, range.to, -1);
177
+ if (to <= from) continue;
178
+ const { ids, hasUntracked } = collectAffectedParaIdsFromMarkLikeStep(tr.doc, from, to);
179
+ for (const id of ids) newState.changedParaIds.add(id);
180
+ if (hasUntracked) newState.hasUntrackedChanges = true;
181
+ }
182
+ }
111
183
  if (prevState.paragraphCount !== newCount) newState.structuralChange = true;
112
184
  for (let stepIndex = 0; stepIndex < tr.steps.length; stepIndex++) {
113
185
  const step = tr.steps[stepIndex];
@@ -169,6 +241,29 @@ function hasStructuralChanges(state) {
169
241
  function hasUntrackedChanges(state) {
170
242
  return getChangeTrackerState(state)?.hasUntrackedChanges ?? false;
171
243
  }
244
+ /** Exact section-count transition authorized by tracked paragraph-mark resolution. */
245
+ function getTrackedSectionEndpointRemoval(state) {
246
+ return getChangeTrackerState(state)?.sectionEndpointRemoval ?? null;
247
+ }
248
+ /** Record only a complete, internally consistent endpoint-removal transition. */
249
+ function markTrackedSectionEndpointRemoval(tr, { sourceDoc, removedEndpointCount, removedReferences }) {
250
+ const sourceStructure = countDocumentStructure(sourceDoc);
251
+ const sourceParagraphEndpointCount = sourceStructure.sectionEndpoints;
252
+ const expectedStructure = countDocumentStructure(tr.doc);
253
+ const expectedParagraphEndpointCount = expectedStructure.sectionEndpoints;
254
+ if (sourceParagraphEndpointCount - expectedParagraphEndpointCount !== removedEndpointCount) return tr;
255
+ return tr.setMeta(SECTION_ENDPOINT_REMOVAL_META, {
256
+ type: "tracked-section-endpoint-removal-meta",
257
+ authorization: {
258
+ type: "tracked-section-endpoint-removal",
259
+ sourceParagraphEndpointCount,
260
+ expectedParagraphEndpointCount,
261
+ sourceEndpointFingerprint: sourceStructure.sectionEndpointFingerprint,
262
+ expectedEndpointFingerprint: expectedStructure.sectionEndpointFingerprint,
263
+ removedReferences
264
+ }
265
+ });
266
+ }
172
267
  /**
173
268
  * Create a transaction that clears the change tracker
174
269
  */
@@ -181,6 +276,15 @@ function ignoreTrackedChanges(tr) {
181
276
  function markStructuralChange(tr) {
182
277
  return tr.setMeta(paragraphChangeTrackerKey, STRUCTURAL_META);
183
278
  }
279
+ /** Record mark-only paragraph changes whose replacement step has a granular map. */
280
+ function markChangedParagraphRanges(tr, batch) {
281
+ const previous = tr.getMeta(CHANGED_PARAGRAPH_RANGES_META);
282
+ const batches = isChangedParagraphRangesMeta(previous) ? [...previous.batches, batch] : [batch];
283
+ return tr.setMeta(CHANGED_PARAGRAPH_RANGES_META, {
284
+ type: "changed-paragraph-ranges",
285
+ batches
286
+ });
287
+ }
184
288
  const ParagraphChangeTrackerExtension = createExtension({
185
289
  name: "paragraphChangeTracker",
186
290
  defaultOptions: {},
@@ -189,4 +293,4 @@ const ParagraphChangeTrackerExtension = createExtension({
189
293
  }
190
294
  });
191
295
  //#endregion
192
- export { ParagraphChangeTrackerExtension, clearTrackedChanges, getChangeTrackerState, getChangedParagraphIds, hasStructuralChanges, hasUntrackedChanges, ignoreTrackedChanges, markStructuralChange, paragraphChangeTrackerKey };
296
+ export { ParagraphChangeTrackerExtension, clearTrackedChanges, getChangeTrackerState, getChangedParagraphIds, getTrackedSectionEndpointRemoval, hasStructuralChanges, hasUntrackedChanges, ignoreTrackedChanges, markChangedParagraphRanges, markStructuralChange, markTrackedSectionEndpointRemoval, paragraphChangeTrackerKey };
@@ -1,6 +1,7 @@
1
1
  import { htmlCommentEnd } from "../../../utils/htmlComments.js";
2
2
  import { stripXmlDeclarations } from "../../../utils/stripXmlDeclarations.js";
3
3
  import { readBookmarkBoundaryAttrs } from "../../bookmarkBoundaryAttrs.js";
4
+ import { findInvalidBookmarkBoundaryIds } from "../../bookmarkBoundaryIntegrity.js";
4
5
  import { Fragment, Slice } from "prosemirror-model";
5
6
  //#region src/prosemirror/extensions/features/pasteCleanup.ts
6
7
  /**
@@ -187,35 +188,28 @@ function cleanPastedHtml(html, options = {}) {
187
188
  }
188
189
  /** Remove incomplete or duplicate bookmark pairs at copied slice edges. */
189
190
  function removeUnpairedBookmarkBoundaries(slice) {
190
- const counts = /* @__PURE__ */ new Map();
191
+ const boundaries = [];
191
192
  let boundaryIndex = 0;
192
193
  slice.content.descendants((node) => {
193
194
  if (node.type.name !== "bookmarkBoundary") return true;
194
195
  const result = readBookmarkBoundaryAttrs(node);
195
196
  if (!result.ok) return false;
196
197
  const attrs = result.value;
197
- const count = counts.get(attrs.id) ?? {
198
- starts: 0,
199
- ends: 0
200
- };
201
- if (attrs.type === "start") {
202
- count.starts += 1;
203
- count.firstStart ??= boundaryIndex;
204
- } else {
205
- count.ends += 1;
206
- count.firstEnd ??= boundaryIndex;
207
- }
198
+ boundaries.push({
199
+ id: attrs.id,
200
+ type: attrs.type,
201
+ position: boundaryIndex
202
+ });
208
203
  boundaryIndex += 1;
209
- counts.set(attrs.id, count);
210
204
  return false;
211
205
  });
212
- const pairedIds = new Set([...counts].flatMap(([id, count]) => count.starts === 1 && count.ends === 1 && count.firstStart !== void 0 && count.firstEnd !== void 0 && count.firstStart < count.firstEnd ? [id] : []));
206
+ const invalidIds = findInvalidBookmarkBoundaryIds(boundaries);
213
207
  const filterFragment = (fragment) => {
214
208
  const children = [];
215
209
  fragment.forEach((node) => {
216
210
  if (node.type.name === "bookmarkBoundary") {
217
211
  const result = readBookmarkBoundaryAttrs(node);
218
- if (result.ok && pairedIds.has(result.value.id)) children.push(node);
212
+ if (result.ok && !invalidIds.has(result.value.id)) children.push(node);
219
213
  return;
220
214
  }
221
215
  children.push(node.childCount === 0 ? node : node.copy(filterFragment(node.content)));
@@ -1,6 +1,6 @@
1
1
  import { createMarkExtension } from "../create.js";
2
+ import { toggleMarkForAllScripts } from "./markUtils.js";
2
3
  import { panic } from "better-result";
3
- import { toggleMark } from "prosemirror-commands";
4
4
  //#region src/prosemirror/extensions/marks/BoldExtension.ts
5
5
  /**
6
6
  * Bold Mark Extension
@@ -31,9 +31,10 @@ const BoldExtension = createMarkExtension({
31
31
  onSchemaReady(ctx) {
32
32
  const boldType = ctx.schema.marks["bold"];
33
33
  if (!boldType) panic("Missing mark type: bold");
34
+ const toggleBold = toggleMarkForAllScripts(boldType, "bold");
34
35
  return {
35
- commands: { toggleBold: () => toggleMark(boldType) },
36
- keyboardShortcuts: { "Mod-b": toggleMark(boldType) }
36
+ commands: { toggleBold: () => toggleBold },
37
+ keyboardShortcuts: { "Mod-b": toggleBold }
37
38
  };
38
39
  }
39
40
  });
@@ -6,16 +6,13 @@ import { MarkExtension } from "../types.js";
6
6
  * Carries a run's character style reference through ProseMirror so semantic
7
7
  * styles (e.g. a house "DefinedTerm" style) survive the load → edit → save
8
8
  * round-trip. The style's resolved formatting is flattened into the regular
9
- * marks at load for rendering; this mark only preserves the reference plus a
10
- * private snapshot of the style's own run properties (`_styleRPr`) that the
11
- * serializer uses to avoid re-emitting style-provided values as direct
12
- * formatting.
9
+ * marks at load for rendering; this mark preserves only the reference. Style
10
+ * formatting resolves through the document's shared style engine so it does
11
+ * not become stale when a run moves between paragraph contexts.
13
12
  *
14
13
  * The mark renders as an unstyled span with a `data-character-style`
15
14
  * attribute. parseDOM restores the styleId (so copy/paste inside the editor
16
- * keeps the reference) but not the snapshot — pasted content then serializes
17
- * with the reference plus explicit formatting, which renders identically and
18
- * degrades gracefully.
15
+ * keeps the reference).
19
16
  */
20
17
  declare const CharacterStyleExtension: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
21
18
  //#endregion
@@ -7,25 +7,19 @@ import { createMarkExtension } from "../create.js";
7
7
  * Carries a run's character style reference through ProseMirror so semantic
8
8
  * styles (e.g. a house "DefinedTerm" style) survive the load → edit → save
9
9
  * round-trip. The style's resolved formatting is flattened into the regular
10
- * marks at load for rendering; this mark only preserves the reference plus a
11
- * private snapshot of the style's own run properties (`_styleRPr`) that the
12
- * serializer uses to avoid re-emitting style-provided values as direct
13
- * formatting.
10
+ * marks at load for rendering; this mark preserves only the reference. Style
11
+ * formatting resolves through the document's shared style engine so it does
12
+ * not become stale when a run moves between paragraph contexts.
14
13
  *
15
14
  * The mark renders as an unstyled span with a `data-character-style`
16
15
  * attribute. parseDOM restores the styleId (so copy/paste inside the editor
17
- * keeps the reference) but not the snapshot — pasted content then serializes
18
- * with the reference plus explicit formatting, which renders identically and
19
- * degrades gracefully.
16
+ * keeps the reference).
20
17
  */
21
18
  const CharacterStyleExtension = createMarkExtension({
22
19
  name: "characterStyle",
23
20
  schemaMarkName: "characterStyle",
24
21
  markSpec: {
25
- attrs: {
26
- styleId: { default: "" },
27
- _styleRPr: { default: null }
28
- },
22
+ attrs: { styleId: { default: "" } },
29
23
  parseDOM: [{
30
24
  tag: "span[data-character-style]",
31
25
  getAttrs: (dom) => {
@@ -1,6 +1,6 @@
1
1
  import { expectFontSizeMarkAttrs } from "../../attrs/index.js";
2
2
  import { createMarkExtension } from "../create.js";
3
- import { removeMark, setMark } from "./markUtils.js";
3
+ import { clearFontSizeForAllScripts, setFontSizeForAllScripts } from "./markUtils.js";
4
4
  import { panic } from "better-result";
5
5
  //#region src/prosemirror/extensions/marks/FontSizeExtension.ts
6
6
  /**
@@ -38,8 +38,8 @@ const FontSizeExtension = createMarkExtension({
38
38
  const fontSizeType = ctx.schema.marks["fontSize"];
39
39
  if (!fontSizeType) panic("Missing mark type: fontSize");
40
40
  return { commands: {
41
- setFontSize: (size) => setMark(fontSizeType, { size }),
42
- clearFontSize: () => removeMark(fontSizeType)
41
+ setFontSize: (size) => setFontSizeForAllScripts(fontSizeType, size),
42
+ clearFontSize: () => clearFontSizeForAllScripts(fontSizeType)
43
43
  } };
44
44
  }
45
45
  });
@@ -1,6 +1,6 @@
1
1
  import { createMarkExtension } from "../create.js";
2
+ import { toggleMarkForAllScripts } from "./markUtils.js";
2
3
  import { panic } from "better-result";
3
- import { toggleMark } from "prosemirror-commands";
4
4
  //#region src/prosemirror/extensions/marks/ItalicExtension.ts
5
5
  /**
6
6
  * Italic Mark Extension
@@ -24,9 +24,10 @@ const ItalicExtension = createMarkExtension({
24
24
  onSchemaReady(ctx) {
25
25
  const italicType = ctx.schema.marks["italic"];
26
26
  if (!italicType) panic("Missing mark type: italic");
27
+ const toggleItalic = toggleMarkForAllScripts(italicType, "italic");
27
28
  return {
28
- commands: { toggleItalic: () => toggleMark(italicType) },
29
- keyboardShortcuts: { "Mod-i": toggleMark(italicType) }
29
+ commands: { toggleItalic: () => toggleItalic },
30
+ keyboardShortcuts: { "Mod-i": toggleItalic }
30
31
  };
31
32
  }
32
33
  });
@@ -0,0 +1,13 @@
1
+ import { MarkExtension } from "../types.js";
2
+ //#region src/prosemirror/extensions/marks/PageBreakRunOwnerExtension.d.ts
3
+ /**
4
+ * Editor-only identity for the authored run surrounding a page-break atom.
5
+ *
6
+ * Ordinary formatting marks cannot distinguish two adjacent source runs with
7
+ * identical properties. This mark is added only to a run containing an
8
+ * explicit page break, so every sibling carrier can be rejoined exactly on
9
+ * save without changing the generic run-coalescing model.
10
+ */
11
+ declare const PageBreakRunOwnerExtension: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
12
+ //#endregion
13
+ export { PageBreakRunOwnerExtension };
@@ -0,0 +1,39 @@
1
+ import { expectPageBreakRunOwnerMarkAttrs } from "../../attrs/index.js";
2
+ import { createMarkExtension } from "../create.js";
3
+ //#region src/prosemirror/extensions/marks/PageBreakRunOwnerExtension.ts
4
+ /**
5
+ * Editor-only identity for the authored run surrounding a page-break atom.
6
+ *
7
+ * Ordinary formatting marks cannot distinguish two adjacent source runs with
8
+ * identical properties. This mark is added only to a run containing an
9
+ * explicit page break, so every sibling carrier can be rejoined exactly on
10
+ * save without changing the generic run-coalescing model.
11
+ */
12
+ const CANONICAL_OWNER_ID = /^(?:0|[1-9]\d*)$/u;
13
+ const PageBreakRunOwnerExtension = createMarkExtension({
14
+ name: "pageBreakRunOwner",
15
+ schemaMarkName: "pageBreakRunOwner",
16
+ markSpec: {
17
+ attrs: { id: {} },
18
+ inclusive: false,
19
+ parseDOM: [{
20
+ tag: "span[data-docx-page-break-run-owner]",
21
+ getAttrs(dom) {
22
+ const rawId = dom.dataset["docxPageBreakRunOwner"];
23
+ if (rawId === void 0 || !CANONICAL_OWNER_ID.test(rawId)) return false;
24
+ const id = Number(rawId);
25
+ return Number.isSafeInteger(id) ? { id } : false;
26
+ }
27
+ }],
28
+ toDOM(mark) {
29
+ const { id } = expectPageBreakRunOwnerMarkAttrs(mark);
30
+ return [
31
+ "span",
32
+ { "data-docx-page-break-run-owner": String(id) },
33
+ 0
34
+ ];
35
+ }
36
+ }
37
+ });
38
+ //#endregion
39
+ export { PageBreakRunOwnerExtension };
@@ -3,7 +3,13 @@ import { RunFormattingOverrideAttrs } from "../../schema/marks.js";
3
3
  import { MarkExtension } from "../types.js";
4
4
  import { Mark } from "prosemirror-model";
5
5
  //#region src/prosemirror/extensions/marks/RunFormattingOverrideExtension.d.ts
6
- declare function buildRunFormattingOverrideAttrs(formatting: document_d_exports.TextFormatting | undefined): RunFormattingOverrideAttrs | undefined;
6
+ type BuildRunFormattingOverrideAttrsOptions = {
7
+ type: "authored-baseline";
8
+ formatting: document_d_exports.TextFormatting | undefined;
9
+ } | {
10
+ type: "structural-only";
11
+ };
12
+ declare function buildRunFormattingOverrideAttrs(formatting: document_d_exports.TextFormatting | undefined, options?: BuildRunFormattingOverrideAttrsOptions): RunFormattingOverrideAttrs | undefined;
7
13
  declare function applyRunFormattingOverrideAttrs(formatting: document_d_exports.TextFormatting, attrs: RunFormattingOverrideAttrs): void;
8
14
  declare function applyRunFormattingOverrideMark(formatting: document_d_exports.TextFormatting, mark: Mark): void;
9
15
  declare const RunFormattingOverrideExtension: (options?: Partial<Record<string, unknown>> | undefined) => MarkExtension;
@@ -1,34 +1,60 @@
1
1
  import { expectRunFormattingOverrideMarkAttrs } from "../../attrs/index.js";
2
+ import { withAuthoredRunFormatting } from "../../runFormattingProvenance.js";
2
3
  import { createMarkExtension } from "../create.js";
3
4
  //#region src/prosemirror/extensions/marks/RunFormattingOverrideExtension.ts
4
- function buildRunFormattingOverrideAttrs(formatting) {
5
- if (!formatting) return;
5
+ function buildRunFormattingOverrideAttrs(formatting, options) {
6
6
  const attrs = {};
7
- if (formatting.bold !== void 0) attrs.bold = formatting.bold;
8
- if (formatting.italic !== void 0) attrs.italic = formatting.italic;
9
- if (formatting.underline?.style === "none") attrs.underline = "none";
10
- if (formatting.strike !== void 0) attrs.strike = formatting.strike;
11
- if (formatting.doubleStrike === false) attrs.doubleStrike = false;
12
- if (formatting.allCaps !== void 0) attrs.allCaps = formatting.allCaps;
13
- if (formatting.smallCaps !== void 0) attrs.smallCaps = formatting.smallCaps;
14
- if (formatting.hidden !== void 0) attrs.hidden = formatting.hidden;
15
- if (formatting.emboss !== void 0) attrs.emboss = formatting.emboss;
16
- if (formatting.imprint !== void 0) attrs.imprint = formatting.imprint;
17
- if (formatting.shadow !== void 0) attrs.shadow = formatting.shadow;
18
- if (formatting.outline !== void 0) attrs.outline = formatting.outline;
19
- if (formatting.rtl === false) attrs.rtl = false;
20
- if (formatting.boldCs !== void 0) attrs.boldCs = formatting.boldCs;
21
- if (formatting.italicCs !== void 0) attrs.italicCs = formatting.italicCs;
22
- if (formatting.fontSizeCs !== void 0 && formatting.fontSizeCs !== formatting.fontSize) attrs.fontSizeCs = formatting.fontSizeCs;
23
- if (formatting.cs !== void 0) attrs.cs = formatting.cs;
24
- return Object.keys(attrs).length > 0 ? attrs : void 0;
7
+ if (formatting?.bold !== void 0) attrs.bold = formatting.bold;
8
+ if (formatting?.italic !== void 0) attrs.italic = formatting.italic;
9
+ if (formatting?.underline?.style === "none") attrs.underline = "none";
10
+ if (formatting?.color?.auto === true) attrs.color = "auto";
11
+ if (formatting?.highlight === "none") attrs.highlight = "none";
12
+ if (formatting?.shading?.pattern === "nil") attrs.shading = {
13
+ ...formatting.shading,
14
+ pattern: "nil"
15
+ };
16
+ if (formatting?.strike !== void 0) attrs.strike = formatting.strike;
17
+ if (formatting?.doubleStrike === false) attrs.doubleStrike = false;
18
+ if (formatting?.vertAlign === "baseline") attrs.vertAlign = "baseline";
19
+ if (formatting?.allCaps !== void 0) attrs.allCaps = formatting.allCaps;
20
+ if (formatting?.smallCaps !== void 0) attrs.smallCaps = formatting.smallCaps;
21
+ if (formatting?.hidden !== void 0) attrs.hidden = formatting.hidden;
22
+ if (formatting?.emboss !== void 0) attrs.emboss = formatting.emboss;
23
+ if (formatting?.imprint !== void 0) attrs.imprint = formatting.imprint;
24
+ if (formatting?.shadow !== void 0) attrs.shadow = formatting.shadow;
25
+ if (formatting?.outline !== void 0) attrs.outline = formatting.outline;
26
+ if (formatting?.spacing === 0) attrs.spacing = 0;
27
+ if (formatting?.position === 0) attrs.position = 0;
28
+ if (formatting?.scale === 100) attrs.scale = 100;
29
+ if (formatting?.kerning === 0) attrs.kerning = 0;
30
+ if (formatting?.emphasisMark === "none") attrs.emphasisMark = "none";
31
+ if (formatting?.effect === "none") attrs.effect = "none";
32
+ if (formatting?.rtl === false) attrs.rtl = false;
33
+ if (formatting?.boldCs !== void 0) attrs.boldCs = formatting.boldCs;
34
+ if (formatting?.italicCs !== void 0) attrs.italicCs = formatting.italicCs;
35
+ if (formatting?.fontSizeCs !== void 0) attrs.fontSizeCs = formatting.fontSizeCs;
36
+ if (formatting?.cs !== void 0) attrs.cs = formatting.cs;
37
+ const provenance = options ?? {
38
+ type: "authored-baseline",
39
+ formatting
40
+ };
41
+ if (provenance.type === "structural-only") return Object.keys(attrs).length > 0 ? attrs : void 0;
42
+ const authoredFormatting = provenance.formatting;
43
+ const hasAuthoredFormatting = Object.entries(authoredFormatting ?? {}).some(([property, value]) => property !== "styleId" && value !== void 0);
44
+ if (Object.keys(attrs).length === 0 && !hasAuthoredFormatting) return;
45
+ const withProvenance = withAuthoredRunFormatting(attrs, authoredFormatting);
46
+ return Object.keys(withProvenance).length > 0 ? withProvenance : void 0;
25
47
  }
26
48
  function applyRunFormattingOverrideAttrs(formatting, attrs) {
27
49
  if (attrs.bold !== void 0) formatting.bold = attrs.bold;
28
50
  if (attrs.italic !== void 0) formatting.italic = attrs.italic;
29
51
  if (attrs.underline === "none") formatting.underline = { style: "none" };
52
+ if (attrs.color === "auto") formatting.color = { auto: true };
53
+ if (attrs.highlight === "none") formatting.highlight = "none";
54
+ if (attrs.shading?.pattern === "nil") formatting.shading = attrs.shading;
30
55
  if (attrs.strike !== void 0) formatting.strike = attrs.strike;
31
56
  if (attrs.doubleStrike === false) formatting.doubleStrike = false;
57
+ if (attrs.vertAlign === "baseline") formatting.vertAlign = "baseline";
32
58
  if (attrs.allCaps !== void 0) formatting.allCaps = attrs.allCaps;
33
59
  if (attrs.smallCaps !== void 0) formatting.smallCaps = attrs.smallCaps;
34
60
  if (attrs.hidden !== void 0) formatting.hidden = attrs.hidden;
@@ -36,6 +62,12 @@ function applyRunFormattingOverrideAttrs(formatting, attrs) {
36
62
  if (attrs.imprint !== void 0) formatting.imprint = attrs.imprint;
37
63
  if (attrs.shadow !== void 0) formatting.shadow = attrs.shadow;
38
64
  if (attrs.outline !== void 0) formatting.outline = attrs.outline;
65
+ if (attrs.spacing === 0) formatting.spacing = 0;
66
+ if (attrs.position === 0) formatting.position = 0;
67
+ if (attrs.scale === 100) formatting.scale = 100;
68
+ if (attrs.kerning === 0) formatting.kerning = 0;
69
+ if (attrs.emphasisMark === "none") formatting.emphasisMark = "none";
70
+ if (attrs.effect === "none") formatting.effect = "none";
39
71
  if (attrs.rtl === false) formatting.rtl = false;
40
72
  if (attrs.boldCs !== void 0) formatting.boldCs = attrs.boldCs;
41
73
  if (attrs.italicCs !== void 0) formatting.italicCs = attrs.italicCs;
@@ -50,12 +82,22 @@ const RunFormattingOverrideExtension = createMarkExtension({
50
82
  schemaMarkName: "runFormattingOverride",
51
83
  markSpec: {
52
84
  attrs: {
85
+ _authoredOn: { default: null },
86
+ _authoredOff: { default: null },
87
+ _authoredValues: { default: null },
53
88
  directFontProperties: { default: null },
89
+ complexScriptPropertyAbsences: { default: null },
90
+ color: { default: null },
54
91
  bold: { default: null },
55
92
  italic: { default: null },
56
93
  underline: { default: null },
57
94
  strike: { default: null },
58
95
  doubleStrike: { default: null },
96
+ effect: { default: null },
97
+ emphasisMark: { default: null },
98
+ highlight: { default: null },
99
+ kerning: { default: null },
100
+ position: { default: null },
59
101
  allCaps: { default: null },
60
102
  smallCaps: { default: null },
61
103
  hidden: { default: null },
@@ -64,10 +106,14 @@ const RunFormattingOverrideExtension = createMarkExtension({
64
106
  shadow: { default: null },
65
107
  outline: { default: null },
66
108
  rtl: { default: null },
109
+ scale: { default: null },
110
+ shading: { default: null },
111
+ spacing: { default: null },
67
112
  boldCs: { default: null },
68
113
  italicCs: { default: null },
69
114
  fontSizeCs: { default: null },
70
- cs: { default: null }
115
+ cs: { default: null },
116
+ vertAlign: { default: null }
71
117
  },
72
118
  toDOM(mark) {
73
119
  const attrs = expectRunFormattingOverrideMarkAttrs(mark);
@@ -4,6 +4,13 @@ import { Mark, MarkType, Schema } from "prosemirror-model";
4
4
  //#region src/prosemirror/extensions/marks/markUtils.d.ts
5
5
  type MarkAttrs = Record<string, unknown>;
6
6
  declare function setMark(markType: MarkType, attrs: MarkAttrs): Command;
7
+ type PairedToggleProperty = "bold" | "italic";
8
+ /** UI toggle whose direct-formatting contract explicitly targets both script families. */
9
+ declare const toggleMarkForAllScripts: (markType: MarkType, property: PairedToggleProperty) => Command;
10
+ /** UI size command whose direct-formatting contract explicitly targets both script families. */
11
+ declare const setFontSizeForAllScripts: (markType: MarkType, size: number) => Command;
12
+ /** Clears both ordinary and complex-script direct size through the UI command boundary. */
13
+ declare const clearFontSizeForAllScripts: (markType: MarkType) => Command;
7
14
  declare function toggleUnderlineMark(markType: MarkType): Command;
8
15
  declare function removeMark(markType: MarkType): Command;
9
16
  /**
@@ -31,4 +38,4 @@ declare function createSetMarkCommand(markType: MarkType, attrs?: Record<string,
31
38
  */
32
39
  declare function createRemoveMarkCommand(markType: MarkType): Command;
33
40
  //#endregion
34
- export { clearFormatting, createRemoveMarkCommand, createSetMarkCommand, getMarkAttr, isMarkActive, removeMark, setMark, textFormattingToMarks, toggleUnderlineMark };
41
+ export { clearFontSizeForAllScripts, clearFormatting, createRemoveMarkCommand, createSetMarkCommand, getMarkAttr, isMarkActive, removeMark, setFontSizeForAllScripts, setMark, textFormattingToMarks, toggleMarkForAllScripts, toggleUnderlineMark };