@stll/folio-core 0.36.0 → 0.37.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 (200) hide show
  1. package/README.md +59 -1
  2. package/dist/ai-edits/apply.js +545 -296
  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 +45 -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 +169 -567
  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 +6 -4
  55. package/dist/document-operations.js +77 -12
  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 +155 -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 +190 -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,4 +1,8 @@
1
- import { expectCharacterStyleMarkAttrs, expectParagraphAttrs } from "../attrs/index.js";
1
+ import { mergeTextFormatting } from "../../utils/textFormattingMerge.js";
2
+ import { expectCharacterStyleMarkAttrs } from "../attrs/index.js";
3
+ import { getDocumentStyleResolver } from "../plugins/documentStyles.js";
4
+ import { readAuthoredRunFormatting, reconcileRunFormattingMarks } from "../runFormattingReconciliation.js";
5
+ import { paragraphFormattingForRun, paragraphRunStyleContext, paragraphRunStyleContextAt, resolveEffectiveRunStyleFormatting } from "../runStyleFormatting.js";
2
6
  //#region src/prosemirror/commands/formatPainter.ts
3
7
  /**
4
8
  * Character-formatting marks the painter copies. Structural marks — comments,
@@ -61,76 +65,288 @@ function sanitizeOverrideMark(mark) {
61
65
  }
62
66
  kept[key] = value;
63
67
  }
68
+ for (const provenanceKey of ["_authoredOn", "_authoredOff"]) {
69
+ const properties = kept[provenanceKey];
70
+ if (!Array.isArray(properties)) continue;
71
+ const paintableProperties = properties.filter((property) => typeof property === "string" && !NON_PAINTABLE_FORMATS.has(property));
72
+ if (paintableProperties.length !== properties.length) {
73
+ kept[provenanceKey] = paintableProperties;
74
+ removedExcluded = true;
75
+ }
76
+ }
64
77
  if (!removedExcluded) return mark;
65
78
  if (Object.keys(kept).length === 0) return null;
66
79
  return mark.type.create(kept);
67
80
  }
68
- const PAINTABLE_STYLE_TOGGLE_MARKS = [
69
- ["allCaps", "allCaps"],
70
- ["bold", "bold"],
71
- ["emboss", "emboss"],
72
- ["imprint", "imprint"],
73
- ["italic", "italic"],
74
- ["outline", "textOutline"],
75
- ["shadow", "textShadow"],
76
- ["smallCaps", "smallCaps"],
77
- ["strike", "strike"]
78
- ];
79
- const PAINTABLE_COMPLEX_SCRIPT_TOGGLES = ["boldCs", "italicCs"];
80
- function materializeStyleToggleNegatives({ inheritedFormatting, marks }) {
81
- const characterStyle = marks.find((mark) => mark.type.name === "characterStyle");
82
- if (!characterStyle) return [...marks];
83
- const styleRPr = expectCharacterStyleMarkAttrs(characterStyle)._styleRPr;
84
- if (!styleRPr) return [...marks];
85
- const negativeAttrs = {};
86
- for (const [key, markName] of PAINTABLE_STYLE_TOGGLE_MARKS) if (styleRPr[key] === true && !marks.some((mark) => mark.type.name === markName)) negativeAttrs[key] = false;
87
- for (const key of PAINTABLE_COMPLEX_SCRIPT_TOGGLES) {
88
- if (styleRPr[key] === void 0) continue;
89
- const inheritedValue = inheritedFormatting?.[key] ?? false;
90
- if (!(styleRPr[key] === true ? !inheritedValue : false)) negativeAttrs[key] = false;
81
+ /**
82
+ * Every effective property represented by a paintable mark has one target-context
83
+ * policy. Adding a new paintable formatting field therefore requires an explicit
84
+ * decision: an OOXML off sentinel, a neutral scalar, or a source value that cannot
85
+ * be synthesized without flattening document defaults.
86
+ */
87
+ const TARGET_RELATIVE_FORMATTING_POLICIES = {
88
+ allCaps: {
89
+ type: "boolean",
90
+ override: "allCaps"
91
+ },
92
+ bold: {
93
+ type: "boolean",
94
+ override: "bold"
95
+ },
96
+ boldCs: {
97
+ type: "boolean",
98
+ override: "boldCs",
99
+ fallback: "bold"
100
+ },
101
+ color: {
102
+ type: "sentinel",
103
+ override: "color",
104
+ inactive: "auto",
105
+ cancellation: { auto: true }
106
+ },
107
+ cs: {
108
+ type: "boolean",
109
+ override: "cs"
110
+ },
111
+ doubleStrike: {
112
+ type: "boolean",
113
+ override: "doubleStrike"
114
+ },
115
+ effect: {
116
+ type: "sentinel",
117
+ override: "effect",
118
+ inactive: "none",
119
+ cancellation: "none"
120
+ },
121
+ emboss: {
122
+ type: "boolean",
123
+ override: "emboss"
124
+ },
125
+ emphasisMark: {
126
+ type: "sentinel",
127
+ override: "emphasisMark",
128
+ inactive: "none",
129
+ cancellation: "none"
130
+ },
131
+ fontFamily: { type: "source-value-required" },
132
+ fontSize: { type: "source-value-required" },
133
+ fontSizeCs: {
134
+ type: "source-value-required",
135
+ fallback: "fontSize"
136
+ },
137
+ highlight: {
138
+ type: "sentinel",
139
+ override: "highlight",
140
+ inactive: "none",
141
+ cancellation: "none"
142
+ },
143
+ imprint: {
144
+ type: "boolean",
145
+ override: "imprint"
146
+ },
147
+ italic: {
148
+ type: "boolean",
149
+ override: "italic"
150
+ },
151
+ italicCs: {
152
+ type: "boolean",
153
+ override: "italicCs",
154
+ fallback: "italic"
155
+ },
156
+ kerning: {
157
+ type: "sentinel",
158
+ override: "kerning",
159
+ inactive: 0,
160
+ cancellation: 0
161
+ },
162
+ outline: {
163
+ type: "boolean",
164
+ override: "outline"
165
+ },
166
+ position: {
167
+ type: "sentinel",
168
+ override: "position",
169
+ inactive: 0,
170
+ cancellation: 0
171
+ },
172
+ scale: {
173
+ type: "sentinel",
174
+ override: "scale",
175
+ inactive: 100,
176
+ cancellation: 100
177
+ },
178
+ shading: {
179
+ type: "sentinel",
180
+ override: "shading",
181
+ inactive: "nil",
182
+ cancellation: { pattern: "nil" },
183
+ projection: "shading"
184
+ },
185
+ shadow: {
186
+ type: "boolean",
187
+ override: "shadow"
188
+ },
189
+ smallCaps: {
190
+ type: "boolean",
191
+ override: "smallCaps"
192
+ },
193
+ spacing: {
194
+ type: "sentinel",
195
+ override: "spacing",
196
+ inactive: 0,
197
+ cancellation: 0
198
+ },
199
+ strike: {
200
+ type: "boolean",
201
+ override: "strike"
202
+ },
203
+ underline: {
204
+ type: "sentinel",
205
+ override: "underline",
206
+ inactive: "none",
207
+ cancellation: { style: "none" },
208
+ projection: "style"
209
+ },
210
+ vertAlign: {
211
+ type: "sentinel",
212
+ override: "vertAlign",
213
+ inactive: "baseline",
214
+ cancellation: "baseline"
215
+ }
216
+ };
217
+ const PAINTABLE_FORMATTING_KEYS = Object.keys(TARGET_RELATIVE_FORMATTING_POLICIES);
218
+ const targetRelativeFormattingPolicy = (key) => TARGET_RELATIVE_FORMATTING_POLICIES[key];
219
+ function pickPaintableFormatting(formatting) {
220
+ const result = {};
221
+ if (!formatting) return result;
222
+ for (const key of PAINTABLE_FORMATTING_KEYS) {
223
+ const value = formatting[key];
224
+ if (value !== void 0) Reflect.set(result, key, value);
91
225
  }
92
- if (Object.keys(negativeAttrs).length === 0) return [...marks];
93
- const existingOverride = marks.find((mark) => mark.type.name === "runFormattingOverride");
94
- const overrideType = existingOverride?.type ?? characterStyle.type.schema.marks["runFormattingOverride"];
95
- if (!overrideType) return [...marks];
96
- const override = overrideType.create({
97
- ...negativeAttrs,
98
- ...existingOverride?.attrs
226
+ return result;
227
+ }
228
+ function resolveEffectiveFormatting({ context, marks, styleResolver }) {
229
+ const authoredFormatting = readAuthoredRunFormatting({
230
+ context,
231
+ marks,
232
+ styleResolver
99
233
  });
100
- return existingOverride ? marks.map((mark) => mark === existingOverride ? override : mark) : [...marks, override];
234
+ const effectiveFormatting = mergeTextFormatting(resolveEffectiveRunStyleFormatting({
235
+ marks,
236
+ paragraphFormatting: paragraphFormattingForRun({
237
+ context,
238
+ directFormatting: authoredFormatting,
239
+ marks
240
+ }),
241
+ styleResolver
242
+ }), authoredFormatting) ?? {};
243
+ if (authoredFormatting.shading?.pattern === "nil") effectiveFormatting.shading = authoredFormatting.shading;
244
+ if (authoredFormatting.underline?.style === "none") effectiveFormatting.underline = authoredFormatting.underline;
245
+ return pickPaintableFormatting(effectiveFormatting);
101
246
  }
102
- /**
103
- * Marks of the first text node inside [from, to). A word processor's format
104
- * brush copies from the start of the source selection, so a mixed selection
105
- * yields the formatting of its leading run.
106
- */
107
- function firstTextMarks(state, from, to) {
108
- let marks = null;
109
- state.doc.nodesBetween(from, to, (node) => {
110
- if (marks) return false;
247
+ function resolveCopiedStyleFormatting({ context, marks, styleResolver }) {
248
+ if (marks.some((mark) => mark.type.name === "characterStyle") && !styleResolver) return null;
249
+ return pickPaintableFormatting(resolveEffectiveRunStyleFormatting({
250
+ marks,
251
+ paragraphFormatting: paragraphFormattingForRun({
252
+ context,
253
+ marks
254
+ }),
255
+ styleResolver
256
+ }));
257
+ }
258
+ function sameFormattingValue(left, right) {
259
+ if (Object.is(left, right)) return true;
260
+ if (left === null || right === null || typeof left !== "object" || typeof right !== "object") return false;
261
+ if (Array.isArray(left) || Array.isArray(right)) return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((value, index) => sameFormattingValue(value, right.at(index)));
262
+ const leftEntries = Object.entries(left);
263
+ const rightKeys = Object.keys(right);
264
+ return leftEntries.length === rightKeys.length && leftEntries.every(([property, value]) => Object.hasOwn(right, property) && sameFormattingValue(value, Reflect.get(right, property)));
265
+ }
266
+ function policyValue(formatting, key, policy) {
267
+ const own = formatting[key];
268
+ const value = own ?? (policy.type !== "sentinel" ? formatting[policy.fallback ?? key] : own);
269
+ if (policy.type !== "sentinel") return value;
270
+ if (policy.projection === "style") return typeof value === "object" && value !== null ? Reflect.get(value, "style") : void 0;
271
+ if (policy.projection === "shading") {
272
+ if (typeof value !== "object" || value === null) return;
273
+ return Reflect.get(value, "pattern") === "nil" ? "nil" : value;
274
+ }
275
+ if (key === "color") return typeof value === "object" && value !== null && Reflect.get(value, "auto") === true ? "auto" : value;
276
+ return value;
277
+ }
278
+ function materializeTargetRelativeMarks({ captured, context, node, styleResolver }) {
279
+ const targetStyleFormatting = resolveCopiedStyleFormatting({
280
+ context,
281
+ marks: captured.marks,
282
+ styleResolver
283
+ });
284
+ if (!targetStyleFormatting) return null;
285
+ const targetRelativeFormatting = {};
286
+ for (const key of PAINTABLE_FORMATTING_KEYS) {
287
+ const policy = targetRelativeFormattingPolicy(key);
288
+ const sourceValue = policyValue(captured.effectiveFormatting, key, policy);
289
+ const targetValue = policyValue(targetStyleFormatting, key, policy);
290
+ if ((key === "boldCs" || key === "italicCs" || key === "fontSizeCs") && captured.effectiveFormatting[key] === void 0 && targetStyleFormatting[key] === void 0) continue;
291
+ if (policy.type === "source-value-required") {
292
+ if (sourceValue === void 0 && targetValue !== void 0) return null;
293
+ if (sourceValue !== void 0 && !sameFormattingValue(sourceValue, targetValue)) Reflect.set(targetRelativeFormatting, key, sourceValue);
294
+ continue;
295
+ }
296
+ if (policy.type === "boolean") {
297
+ const sourceIsOn = sourceValue === true;
298
+ if (sourceIsOn !== (targetValue === true)) Reflect.set(targetRelativeFormatting, policy.override, sourceIsOn);
299
+ continue;
300
+ }
301
+ const sourceIsInactive = sourceValue === void 0 || sourceValue === policy.inactive;
302
+ const targetIsInactive = targetValue === void 0 || targetValue === policy.inactive;
303
+ if (sourceIsInactive) {
304
+ if (!targetIsInactive) Reflect.set(targetRelativeFormatting, policy.override, captured.effectiveFormatting[key] ?? policy.cancellation);
305
+ continue;
306
+ }
307
+ if (!sameFormattingValue(sourceValue, targetValue)) {
308
+ const formattingValue = captured.effectiveFormatting[key];
309
+ if (formattingValue === void 0) return null;
310
+ Reflect.set(targetRelativeFormatting, policy.override, formattingValue);
311
+ }
312
+ }
313
+ const characterStyle = captured.marks.find((mark) => mark.type.name === "characterStyle");
314
+ const characterStyleId = characterStyle ? expectCharacterStyleMarkAttrs(characterStyle).styleId : void 0;
315
+ return reconcileRunFormattingMarks({
316
+ authoredFormatting: {
317
+ ...targetRelativeFormatting,
318
+ ...characterStyleId !== void 0 ? { styleId: characterStyleId } : {}
319
+ },
320
+ context,
321
+ node,
322
+ styleResolver
323
+ }).filter(isPaintableMark);
324
+ }
325
+ function firstTextFormatting(state, from, to) {
326
+ let formatting = null;
327
+ state.doc.nodesBetween(from, to, (node, position) => {
328
+ if (formatting) return false;
111
329
  if (node.isText) {
112
- marks = node.marks;
330
+ formatting = {
331
+ marks: node.marks,
332
+ position: state.doc.resolve(position)
333
+ };
113
334
  return false;
114
335
  }
115
336
  return true;
116
337
  });
117
- return marks ?? [];
118
- }
119
- function paragraphDefaultTextFormatting(position) {
120
- for (let depth = position.depth; depth >= 0; depth -= 1) {
121
- const ancestor = position.node(depth);
122
- if (ancestor.type.name === "paragraph") return expectParagraphAttrs(ancestor).defaultTextFormatting;
123
- }
338
+ return formatting;
124
339
  }
125
340
  /**
126
- * Capture the paintable character marks active over the current selection.
127
- * Returns the marks (with their attrs) to hand to `applyFormatMarks`. An empty
128
- * selection reads the stored/insertion marks; a range reads its leading run.
129
- * Returns an empty array when the source carries no direct character formatting.
341
+ * Capture the paintable character formatting active over the current selection.
342
+ * An empty selection reads the stored/insertion marks; a range reads its leading
343
+ * run. The discriminated result deliberately represents an effectively plain run:
344
+ * `null` belongs to the host's “nothing captured” state, not this command.
130
345
  */
131
346
  function captureFormatMarks(state) {
132
347
  const { empty, $from, from, to } = state.selection;
133
- const source = empty ? state.storedMarks ?? $from.marks() : firstTextMarks(state, from, to);
348
+ const firstText = empty ? null : firstTextFormatting(state, from, to);
349
+ const source = empty ? state.storedMarks ?? $from.marks() : firstText?.marks ?? [];
134
350
  const captured = [];
135
351
  for (const mark of source) {
136
352
  if (!isPaintableMark(mark)) continue;
@@ -141,31 +357,71 @@ function captureFormatMarks(state) {
141
357
  }
142
358
  captured.push(mark);
143
359
  }
144
- return materializeStyleToggleNegatives({
145
- inheritedFormatting: paragraphDefaultTextFormatting($from),
146
- marks: captured
360
+ const styleResolver = getDocumentStyleResolver(state);
361
+ return {
362
+ effectiveFormatting: resolveEffectiveFormatting({
363
+ context: paragraphRunStyleContextAt({
364
+ doc: state.doc,
365
+ pos: (firstText?.position ?? $from).pos,
366
+ styleResolver
367
+ }),
368
+ marks: captured,
369
+ styleResolver
370
+ }),
371
+ marks: captured,
372
+ type: "capturedTextFormatting"
373
+ };
374
+ }
375
+ function targetParagraphSegments(state, from, to, styleResolver) {
376
+ const segments = [];
377
+ state.doc.nodesBetween(from, to, (node, position) => {
378
+ if (node.type.name !== "paragraph") return true;
379
+ const contentFrom = position + 1;
380
+ const segmentFrom = Math.max(from, contentFrom);
381
+ const segmentTo = Math.min(to, contentFrom + node.content.size);
382
+ if (segmentTo > segmentFrom) segments.push({
383
+ context: paragraphRunStyleContext(node, styleResolver),
384
+ from: segmentFrom,
385
+ to: segmentTo
386
+ });
387
+ return false;
147
388
  });
389
+ return segments;
148
390
  }
149
391
  /**
150
392
  * Apply captured marks onto the current selection's range: clear every paintable
151
393
  * mark type first (replace, not merge — so painting Georgia-12-bold onto
152
394
  * Arial-10 leaves only Georgia-12-bold), then lay down the captured marks.
153
395
  *
154
- * Best-effort: a collapsed selection or an empty capture is a no-op (returns
155
- * false so a keymap binding stays unclaimed and the keystroke passes through).
156
- * Never throws.
396
+ * Best-effort: a collapsed selection, no capture, or a target-relative delta
397
+ * that cannot be represented without guessing document defaults is a no-op.
398
+ * Returns false so a keymap binding stays unclaimed; never partially mutates.
157
399
  */
158
- function applyFormatMarks(marks) {
400
+ function applyFormatMarks(captured) {
159
401
  return (state, dispatch) => {
160
402
  const { from, to, empty } = state.selection;
161
- if (empty || marks.length === 0) return false;
403
+ if (empty || captured?.type !== "capturedTextFormatting") return false;
404
+ const styleResolver = getDocumentStyleResolver(state);
405
+ const segments = targetParagraphSegments(state, from, to, styleResolver);
406
+ const node = state.schema.text("format-painter");
407
+ const targetMarks = segments.map((segment) => materializeTargetRelativeMarks({
408
+ captured,
409
+ context: segment.context,
410
+ node,
411
+ styleResolver
412
+ }));
413
+ if (segments.length === 0 || targetMarks.some((marks) => marks === null)) return false;
162
414
  if (!dispatch) return true;
163
415
  let tr = state.tr;
164
416
  for (const name of PAINTABLE_MARK_NAMES) {
165
417
  const markType = state.schema.marks[name];
166
418
  if (markType) tr = tr.removeMark(from, to, markType);
167
419
  }
168
- for (const mark of marks) tr = tr.addMark(from, to, mark);
420
+ for (const [index, segment] of segments.entries()) {
421
+ const marks = targetMarks[index];
422
+ if (!marks) continue;
423
+ for (const mark of marks) tr = tr.addMark(segment.from, segment.to, mark);
424
+ }
169
425
  dispatch(tr.scrollIntoView());
170
426
  return true;
171
427
  };
@@ -1,7 +1,7 @@
1
1
  import { ResolvedStyleAttrs, getParagraphAlignment, getParagraphBidi, getStyleId } from "../extensions/core/ParagraphExtension.js";
2
2
  import { BorderPreset, TableBorderPreset, TableContextInfo, getTableContext, isInTable as isInTableCell } from "../extensions/nodes/TableExtension.js";
3
3
  import { AcceptSuggestionOptions, FolioSuggestion, SuggestionAppliedAs, SuggestionKind, acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addCommentMark, findAIEditRevisionRange, findNextChange, findPreviousChange, findSuggestionRange, getSuggestions, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark } from "./comments.js";
4
- import { PAINTABLE_MARK_NAMES, applyFormatMarks, captureFormatMarks } from "./formatPainter.js";
4
+ import { CapturedTextFormatting, PAINTABLE_MARK_NAMES, applyFormatMarks, captureFormatMarks } from "./formatPainter.js";
5
5
  import { clearFormatting, createRemoveMarkCommand, createSetMarkCommand, getMarkAttr, isMarkActive } from "../extensions/marks/markUtils.js";
6
6
  import { getHyperlinkAttrs, getSelectedText, isHyperlinkActive } from "../extensions/marks/HyperlinkExtension.js";
7
7
  import { clearFontFamily, clearFontSize, clearHighlight, clearTextColor, insertHyperlink, removeHyperlink, setFontFamily, setFontSize, setHighlight, setHyperlink, setTextColor, setUnderlineStyle, toggleBold, toggleItalic, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline } from "./formatting.js";
@@ -10,4 +10,4 @@ import { addTabStop, alignCenter, alignJustify, alignLeft, alignRight, applyStyl
10
10
  import { addColumnLeft, addColumnRight, addRowAbove, addRowBelow, applyTableStyle, autoFitContents, deleteColumn, deleteRow, deleteTable, distributeColumns, insertTable, mergeCells, removeTableBorders, selectColumn, selectRow, selectTable, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setInsideTableBorders, setOutsideTableBorders, setRowHeight, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, splitCell, toggleHeaderRow, toggleNoWrap } from "./table.js";
11
11
  import { insertPageBreak } from "./pageBreak.js";
12
12
  import { CLIPBOARD_READ_ERROR_EVENT, buildPlainTextSlice, pasteWithoutFormatting } from "./pastePlainText.js";
13
- export { type AcceptSuggestionOptions, type BorderPreset, CLIPBOARD_READ_ERROR_EVENT, type FolioSuggestion, PAINTABLE_MARK_NAMES, type ResolvedStyleAttrs, type SuggestionAppliedAs, type SuggestionKind, type TableBorderPreset, type TableContextInfo, acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addColumnLeft, addColumnRight, addCommentMark, addRowAbove, addRowBelow, addTabStop, alignCenter, alignJustify, alignLeft, alignRight, applyFormatMarks, applyStyle, applyTableStyle, autoFitContents, buildPlainTextSlice, captureFormatMarks, clearFontFamily, clearFontSize, clearFormatting, clearHighlight, clearStyle, clearTextColor, createRemoveMarkCommand, createSetMarkCommand, decreaseIndent, decreaseListLevel, deleteColumn, deleteRow, deleteTable, distributeColumns, doubleSpacing, findAIEditRevisionRange, findNextChange, findPreviousChange, findSuggestionRange, generateTOC, getHyperlinkAttrs, getListInfo, getMarkAttr, getParagraphAlignment, getParagraphBidi, getSelectedText, getStyleId, getSuggestions, getTableContext, increaseIndent, increaseListLevel, insertHyperlink, insertPageBreak, insertTable, isHyperlinkActive, isInList, isInTableCell as isInTable, isMarkActive, mergeCells, oneAndHalfSpacing, pasteWithoutFormatting, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark, removeHyperlink, removeList, removeTabStop, removeTableBorders, selectColumn, selectRow, selectTable, setAlignment, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setFontFamily, setFontSize, setHighlight, setHyperlink, setIndentFirstLine, setIndentLeft, setIndentRight, setInsideTableBorders, setLineSpacing, setLtr, setOutsideTableBorders, setRowHeight, setRtl, setSpaceAfter, setSpaceBefore, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, setTextColor, setUnderlineStyle, singleSpacing, splitCell, toggleBidi, toggleBold, toggleBulletList, toggleHeaderRow, toggleItalic, toggleNoWrap, toggleNumberedList, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline };
13
+ export { type AcceptSuggestionOptions, type BorderPreset, CLIPBOARD_READ_ERROR_EVENT, type CapturedTextFormatting, type FolioSuggestion, PAINTABLE_MARK_NAMES, type ResolvedStyleAttrs, type SuggestionAppliedAs, type SuggestionKind, type TableBorderPreset, type TableContextInfo, acceptAIEditRevision, acceptAllChanges, acceptAllSuggestions, acceptChange, acceptSuggestion, addColumnLeft, addColumnRight, addCommentMark, addRowAbove, addRowBelow, addTabStop, alignCenter, alignJustify, alignLeft, alignRight, applyFormatMarks, applyStyle, applyTableStyle, autoFitContents, buildPlainTextSlice, captureFormatMarks, clearFontFamily, clearFontSize, clearFormatting, clearHighlight, clearStyle, clearTextColor, createRemoveMarkCommand, createSetMarkCommand, decreaseIndent, decreaseListLevel, deleteColumn, deleteRow, deleteTable, distributeColumns, doubleSpacing, findAIEditRevisionRange, findNextChange, findPreviousChange, findSuggestionRange, generateTOC, getHyperlinkAttrs, getListInfo, getMarkAttr, getParagraphAlignment, getParagraphBidi, getSelectedText, getStyleId, getSuggestions, getTableContext, increaseIndent, increaseListLevel, insertHyperlink, insertPageBreak, insertTable, isHyperlinkActive, isInList, isInTableCell as isInTable, isMarkActive, mergeCells, oneAndHalfSpacing, pasteWithoutFormatting, rejectAIEditRevision, rejectAllChanges, rejectAllSuggestions, rejectChange, rejectSuggestion, removeCommentMark, removeHyperlink, removeList, removeTabStop, removeTableBorders, selectColumn, selectRow, selectTable, setAlignment, setAllTableBorders, setCellBorder, setCellFillColor, setCellMargins, setCellTextDirection, setCellVerticalAlign, setFontFamily, setFontSize, setHighlight, setHyperlink, setIndentFirstLine, setIndentLeft, setIndentRight, setInsideTableBorders, setLineSpacing, setLtr, setOutsideTableBorders, setRowHeight, setRtl, setSpaceAfter, setSpaceBefore, setTableBorderColor, setTableBorderPreset, setTableBorderWidth, setTableBorders, setTableProperties, setTextColor, setUnderlineStyle, singleSpacing, splitCell, toggleBidi, toggleBold, toggleBulletList, toggleHeaderRow, toggleItalic, toggleNoWrap, toggleNumberedList, toggleStrike, toggleSubscript, toggleSuperscript, toggleUnderline };
@@ -1,8 +1,11 @@
1
1
  import { Command } from "prosemirror-state";
2
2
  //#region src/prosemirror/commands/pageBreak.d.ts
3
3
  /**
4
- * Insert a page break at the current cursor position.
5
- * Always ensures a paragraph follows the page break and places the cursor there.
4
+ * Insert a page-break run at the current text cursor.
5
+ *
6
+ * Keeping the atom inline preserves its authored run, revision marks, and exact
7
+ * position among neighbouring run content. Block-level `pageBreak` remains a
8
+ * legacy input boundary and is never emitted by this command.
6
9
  */
7
10
  declare const insertPageBreak: Command;
8
11
  //#endregion
@@ -1,45 +1,27 @@
1
- import { TextSelection } from "prosemirror-state";
2
- import { Fragment } from "prosemirror-model";
1
+ import { pageBreakRunParagraphProjectionDisposition } from "../pageBreakRunProjection.js";
3
2
  //#region src/prosemirror/commands/pageBreak.ts
3
+ const UNSUPPORTED_PAGE_BREAK_RUN_ANCESTORS = /* @__PURE__ */ new Set([
4
+ "tableCell",
5
+ "tableHeader",
6
+ "textBox"
7
+ ]);
4
8
  /**
5
- * Page Break Commands
6
- */
7
- /**
8
- * Insert a page break at the current cursor position.
9
- * Always ensures a paragraph follows the page break and places the cursor there.
9
+ * Insert a page-break run at the current text cursor.
10
+ *
11
+ * Keeping the atom inline preserves its authored run, revision marks, and exact
12
+ * position among neighbouring run content. Block-level `pageBreak` remains a
13
+ * legacy input boundary and is never emitted by this command.
10
14
  */
11
15
  const insertPageBreak = (state, dispatch) => {
12
16
  const { schema } = state;
13
- const pageBreakType = schema.nodes["pageBreak"];
14
- const paragraphType = schema.nodes["paragraph"];
15
- if (!pageBreakType || !paragraphType) return false;
17
+ const pageBreakRunType = schema.nodes["pageBreakRun"];
18
+ const { $from } = state.selection;
19
+ if (!pageBreakRunType || !state.selection.empty || !$from.parent.isTextblock) return false;
20
+ for (let depth = $from.depth; depth >= 0; depth--) if (UNSUPPORTED_PAGE_BREAK_RUN_ANCESTORS.has($from.node(depth).type.name)) return false;
21
+ if ($from.parent.type.name !== "paragraph" || pageBreakRunParagraphProjectionDisposition($from.parent).status === "unsupported") return false;
16
22
  if (dispatch) {
17
- const { $from } = state.selection;
18
- const tr = state.tr;
19
- const pbNode = pageBreakType.create();
20
- const pbSize = pbNode.nodeSize;
21
- let cursorPos;
22
- if ($from.parent.isTextblock) if ($from.parentOffset > 0 && $from.parentOffset < $from.parent.content.size) {
23
- tr.split($from.pos);
24
- const mappedPos = tr.mapping.map($from.pos);
25
- tr.insert(mappedPos, Fragment.from([pbNode, paragraphType.create()]));
26
- cursorPos = mappedPos + pbSize + 1;
27
- } else if ($from.parentOffset === $from.parent.content.size) {
28
- const after = $from.after();
29
- tr.insert(after, Fragment.from([pbNode, paragraphType.create()]));
30
- cursorPos = after + pbSize + 1;
31
- } else {
32
- const before = $from.before();
33
- tr.insert(before, pbNode);
34
- cursorPos = before + pbSize + 1;
35
- }
36
- else {
37
- const pos = $from.pos;
38
- tr.insert(pos, Fragment.from([pbNode, paragraphType.create()]));
39
- cursorPos = pos + pbSize + 1;
40
- }
41
- tr.setSelection(TextSelection.create(tr.doc, cursorPos));
42
- dispatch(tr.scrollIntoView());
23
+ const pageBreak = pageBreakRunType.create();
24
+ dispatch(state.tr.replaceSelectionWith(pageBreak).scrollIntoView());
43
25
  }
44
26
  return true;
45
27
  };
@@ -1,7 +1,9 @@
1
1
  import { document_d_exports } from "../../types/document.js";
2
- import { ParagraphAttrs, ParagraphPropertyChangeAttrs } from "../schema/nodes.js";
2
+ import { ParagraphPropertyChangeAttrs } from "../schema/nodes.js";
3
3
  import { Node } from "prosemirror-model";
4
4
  //#region src/prosemirror/commands/propertyChangeScope.d.ts
5
+ /** Editor-only suggestions are rebased away before save; every other entry emits `w:pPrChange`. */
6
+ declare const hasSerializableParagraphPropertyChange: (changes: readonly ParagraphPropertyChangeAttrs[] | null | undefined) => boolean;
5
7
  type AttrPatch = Record<string, unknown>;
6
8
  type ParagraphPropertySnapshot = NonNullable<ParagraphPropertyChangeAttrs["previousFormatting"]>;
7
9
  type ParagraphPropertyChangeRemoval = {
@@ -38,8 +40,8 @@ declare const removeParagraphPropertyChanges: (changes: readonly ParagraphProper
38
40
  * `runInWithNext` (`w:specVanish` lives in that rPr)
39
41
  * - load-time style/numbering bookkeeping the command layer cannot recompute
40
42
  * without a style resolver: `numPrFromStyle`, the `list*` rendering attrs,
41
- * `alignmentFromStyle`, `spacingFromDocDefaults`,
42
- * `spacingFromImplicitDefaultStyle`
43
+ * `alignmentFromStyle`, `spacingFromDocDefaults`, and resolved style-spacing
44
+ * provenance in `spacingFromImplicitDefaultStyle`
43
45
  */
44
46
  declare const PPR_CHANGE_SCOPED_ATTR_KEYS: readonly ["styleId", "numPr", "alignment", "spaceBefore", "spaceAfter", "lineSpacing", "lineSpacingRule", "lineSpacingExplicit", "snapToGrid", "spacingExplicit", "indentLeft", "indentRight", "indentFirstLine", "hangingIndent", "borders", "shading", "tabs", "pageBreakBefore", "keepNext", "keepLines", "widowControl", "contextualSpacing", "outlineLevel", "direction", "_autospacingBase"];
45
47
  /** The in-scope paragraph properties as they stand, for a `w:pPrChange` record. */
@@ -51,7 +53,7 @@ declare const paragraphPropertiesSnapshot: (node: Node) => ParagraphPropertySnap
51
53
  * the scoped set (editor-created list suggestions snapshot list-rendering
52
54
  * bookkeeping attrs) merge through 1:1 so their pre-change values restore too.
53
55
  */
54
- declare function paragraphRejectAttrPatch(previousFormatting: ParagraphPropertySnapshot | null | undefined, alignmentFromStyle?: ParagraphAttrs["alignmentFromStyle"]): AttrPatch;
56
+ declare function paragraphRejectAttrPatch(previousFormatting: ParagraphPropertySnapshot | null | undefined, inheritedFormatting?: document_d_exports.ParagraphFormatting): AttrPatch;
55
57
  /**
56
58
  * Rebuild the paragraph's `_originalFormatting` (the serializer's pPr source)
57
59
  * after a reject: the stored old pPr wholesale within CT_PPrBase scope, with
@@ -88,4 +90,4 @@ declare function tableRowRejectAttrPatch(previousFormatting: document_d_exports.
88
90
  */
89
91
  declare function tableCellRejectAttrPatch(previousFormatting: document_d_exports.TableCellFormatting | undefined, liveOriginalFormatting: document_d_exports.TableCellFormatting | null | undefined): AttrPatch;
90
92
  //#endregion
91
- export { PPR_CHANGE_SCOPED_ATTR_KEYS, ParagraphPropertyChangeRemoval, paragraphPropertiesSnapshot, paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, removeParagraphPropertyChanges, sectionRejectProperties, tableCellRejectAttrPatch, tableRejectAttrPatch, tableRowRejectAttrPatch };
93
+ export { PPR_CHANGE_SCOPED_ATTR_KEYS, ParagraphPropertyChangeRemoval, hasSerializableParagraphPropertyChange, paragraphPropertiesSnapshot, paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, removeParagraphPropertyChanges, sectionRejectProperties, tableCellRejectAttrPatch, tableRejectAttrPatch, tableRowRejectAttrPatch };