@stll/folio-core 0.3.1 → 0.5.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 (120) hide show
  1. package/dist/ai-edits/apply.d.ts +3 -9
  2. package/dist/ai-edits/apply.js +94 -14
  3. package/dist/ai-edits/blockRange.d.ts +33 -0
  4. package/dist/ai-edits/blockRange.js +58 -0
  5. package/dist/ai-edits/headless.d.ts +35 -5
  6. package/dist/ai-edits/headless.js +92 -22
  7. package/dist/ai-edits/index.d.ts +5 -3
  8. package/dist/ai-edits/index.js +3 -2
  9. package/dist/ai-edits/snapshot.d.ts +14 -2
  10. package/dist/ai-edits/snapshot.js +12 -1
  11. package/dist/ai-edits/types.d.ts +42 -3
  12. package/dist/compat/eigenpal.d.ts +3 -2
  13. package/dist/compat/eigenpal.js +6 -5
  14. package/dist/controller/layoutPipeline.d.ts +1 -0
  15. package/dist/controller/layoutPipeline.js +35 -115
  16. package/dist/controller/layoutScheduler.d.ts +2 -1
  17. package/dist/controller/layoutScheduler.js +6 -0
  18. package/dist/document-operations.d.ts +122 -0
  19. package/dist/document-operations.js +575 -0
  20. package/dist/docx/blockContentParser.js +17 -7
  21. package/dist/docx/encryption/agileDecryption.d.ts +6 -0
  22. package/dist/docx/encryption/agileDecryption.js +209 -0
  23. package/dist/docx/encryption/compoundFile.d.ts +20 -0
  24. package/dist/docx/encryption/compoundFile.js +251 -0
  25. package/dist/docx/encryption/containerFormat.d.ts +15 -0
  26. package/dist/docx/encryption/containerFormat.js +40 -0
  27. package/dist/docx/encryption/cryptoBytes.d.ts +11 -0
  28. package/dist/docx/encryption/cryptoBytes.js +55 -0
  29. package/dist/docx/encryption/encryptionInfo.d.ts +32 -0
  30. package/dist/docx/encryption/encryptionInfo.js +128 -0
  31. package/dist/docx/encryption/errors.d.ts +18 -0
  32. package/dist/docx/encryption/errors.js +13 -0
  33. package/dist/docx/encryption/index.d.ts +4 -0
  34. package/dist/docx/encryption/index.js +4 -0
  35. package/dist/docx/encryption/openEncryptedDocx.d.ts +28 -0
  36. package/dist/docx/encryption/openEncryptedDocx.js +65 -0
  37. package/dist/docx/footnoteParser.d.ts +1 -17
  38. package/dist/docx/footnoteParser.js +1 -27
  39. package/dist/docx/groupDrawingParser.d.ts +8 -0
  40. package/dist/docx/groupDrawingParser.js +131 -0
  41. package/dist/docx/index.d.ts +3 -1
  42. package/dist/docx/index.js +3 -1
  43. package/dist/docx/numberingParser.d.ts +3 -1
  44. package/dist/docx/numberingParser.js +8 -2
  45. package/dist/docx/paragraphParser.js +9 -3
  46. package/dist/docx/parser.d.ts +4 -5
  47. package/dist/docx/parser.js +8 -2
  48. package/dist/docx/runParser.js +8 -1
  49. package/dist/docx/selectiveXmlPatch.js +4 -10
  50. package/dist/docx/serializer/numberingSerializer.js +3 -1
  51. package/dist/docx/settingsParser.d.ts +6 -3
  52. package/dist/docx/settingsParser.js +2 -0
  53. package/dist/docx/unzip.d.ts +7 -5
  54. package/dist/docx/unzip.js +8 -2
  55. package/dist/docx/xmlParser.js +11 -4
  56. package/dist/index.d.ts +3 -2
  57. package/dist/index.js +6 -5
  58. package/dist/layout-bridge/convert/footnoteLayout.d.ts +37 -1
  59. package/dist/layout-bridge/convert/footnoteLayout.js +138 -14
  60. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +6 -8
  61. package/dist/layout-bridge/convert/headerFooterLayout.js +21 -13
  62. package/dist/layout-bridge/convert/toFlowBlocks.js +58 -19
  63. package/dist/layout-engine/index.d.ts +6 -5
  64. package/dist/layout-engine/index.js +116 -27
  65. package/dist/layout-engine/keep-together.d.ts +13 -8
  66. package/dist/layout-engine/keep-together.js +40 -25
  67. package/dist/layout-engine/layoutInstrumentation.d.ts +11 -1
  68. package/dist/layout-engine/layoutInstrumentation.js +10 -1
  69. package/dist/layout-engine/measure/measureBlocks.js +43 -19
  70. package/dist/layout-engine/measure/measureParagraph.js +91 -14
  71. package/dist/layout-engine/paginator.d.ts +2 -1
  72. package/dist/layout-engine/paginator.js +9 -3
  73. package/dist/layout-engine/textBoxGroup.d.ts +7 -0
  74. package/dist/layout-engine/textBoxGroup.js +8 -0
  75. package/dist/layout-engine/types.d.ts +33 -9
  76. package/dist/layout-engine/types.js +20 -2
  77. package/dist/layout-painter/renderPage.d.ts +15 -1
  78. package/dist/layout-painter/renderPage.js +29 -12
  79. package/dist/layout-painter/renderParagraph.js +44 -9
  80. package/dist/layout-painter/renderTable.js +27 -7
  81. package/dist/managers/DocumentLoaderManager.d.ts +3 -1
  82. package/dist/managers/DocumentLoaderManager.js +13 -5
  83. package/dist/managers/TableSelectionManager.js +1 -1
  84. package/dist/model.js +1 -1
  85. package/dist/paged-layout/pageText.d.ts +14 -0
  86. package/dist/paged-layout/pageText.js +21 -0
  87. package/dist/prosemirror/attrs/index.js +3 -0
  88. package/dist/prosemirror/commands/comments.js +75 -5
  89. package/dist/prosemirror/commands/hyperlink.js +4 -2
  90. package/dist/prosemirror/commands/image.js +2 -1
  91. package/dist/prosemirror/commands/index.js +1 -1
  92. package/dist/prosemirror/commands/propertyChangeScope.d.ts +68 -0
  93. package/dist/prosemirror/commands/propertyChangeScope.js +242 -0
  94. package/dist/prosemirror/conversion/fromProseDoc.js +21 -5
  95. package/dist/prosemirror/conversion/toProseDoc.js +43 -15
  96. package/dist/prosemirror/extensions/core/ParagraphExtension.js +3 -0
  97. package/dist/prosemirror/extensions/features/ListExtension.js +6 -0
  98. package/dist/prosemirror/extensions/nodes/TableExtension.js +12 -11
  99. package/dist/prosemirror/findReplaceSelection.js +2 -1
  100. package/dist/prosemirror/index.js +1 -1
  101. package/dist/prosemirror/insertOperations.js +1 -1
  102. package/dist/prosemirror/schema/nodes.d.ts +14 -7
  103. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  104. package/dist/prosemirror/utils/tabCalculator.js +4 -2
  105. package/dist/redline.d.ts +20 -0
  106. package/dist/redline.js +127 -0
  107. package/dist/server.d.ts +7 -3
  108. package/dist/server.js +6 -2
  109. package/dist/symbols.d.ts +35 -0
  110. package/dist/symbols.js +512 -0
  111. package/dist/utils/clipboard.js +3 -3
  112. package/dist/utils/fontLoader.js +3 -0
  113. package/dist/utils/fontResolver.js +65 -1
  114. package/dist/utils/zoom.d.ts +21 -0
  115. package/dist/utils/zoom.js +21 -0
  116. package/dist/version-comparison.d.ts +92 -0
  117. package/dist/version-comparison.js +436 -0
  118. package/package.json +7 -3
  119. package/dist/paged-layout/headerFooterMargins.d.ts +0 -73
  120. package/dist/paged-layout/headerFooterMargins.js +0 -120
@@ -0,0 +1,68 @@
1
+ import { document_d_exports } from "../../types/document.js";
2
+
3
+ //#region src/prosemirror/commands/propertyChangeScope.d.ts
4
+ type AttrPatch = Record<string, unknown>;
5
+ /**
6
+ * Paragraph attrs governed by a `w:pPrChange` — the attrs
7
+ * `paragraphFormattingToAttrs` (conversion/toProseDoc.ts) can produce from a
8
+ * parsed `CT_PPrBase` (ECMA-376 §17.13.5.29). Rejecting a pPrChange restores
9
+ * the stored old pPr wholesale for exactly these keys: a key absent from the
10
+ * stored record resets to the schema default (`null`).
11
+ *
12
+ * Deliberately OUT of scope (preserved across a reject):
13
+ * - identity/structure: `paraId`, `textId`, `sectionBreakType`,
14
+ * `_sectionProperties`, `_propertyChanges`, `pPrMark`, `bookmarks`,
15
+ * `_emptyHyperlinks`, `renderedPageBreakBefore`
16
+ * - paragraph-mark run properties — `pPr/rPr` is CT_PPr-only, not part of the
17
+ * CT_PPrBase payload a pPrChange stores: `defaultTextFormatting`,
18
+ * `runInWithNext` (`w:specVanish` lives in that rPr)
19
+ * - load-time style/numbering bookkeeping the command layer cannot recompute
20
+ * without a style resolver: `numPrFromStyle`, the `list*` rendering attrs,
21
+ * `spacingFromDocDefaults`
22
+ */
23
+ declare const PPR_CHANGE_SCOPED_ATTR_KEYS: readonly ["styleId", "numPr", "alignment", "spaceBefore", "spaceAfter", "lineSpacing", "lineSpacingRule", "spacingExplicit", "indentLeft", "indentRight", "indentFirstLine", "hangingIndent", "borders", "shading", "tabs", "pageBreakBefore", "keepNext", "keepLines", "widowControl", "contextualSpacing", "outlineLevel", "direction", "_autospacingBase"];
24
+ /**
25
+ * Build the attr patch that rejecting one pPrChange applies to a paragraph:
26
+ * every in-scope key set to the stored previous value, or reset to `null`
27
+ * when the stored old pPr does not carry it. Keys the record captured beyond
28
+ * the scoped set (editor-created list suggestions snapshot list-rendering
29
+ * bookkeeping attrs) merge through 1:1 so their pre-change values restore too.
30
+ */
31
+ declare function paragraphRejectAttrPatch(previousFormatting: Record<string, unknown> | null | undefined): AttrPatch;
32
+ /**
33
+ * Rebuild the paragraph's `_originalFormatting` (the serializer's pPr source)
34
+ * after a reject: the stored old pPr wholesale within CT_PPrBase scope, with
35
+ * the paragraph-mark rPr fields (`runProperties`, `runInWithNext`) preserved
36
+ * from the live original — a pPrChange cannot store them, so a reject must
37
+ * not drop them.
38
+ */
39
+ declare function paragraphRejectOriginalFormatting(previousFormatting: Record<string, unknown> | null | undefined, liveOriginal: unknown): document_d_exports.ParagraphFormatting | null;
40
+ /**
41
+ * Rejected section properties: the stored old sectPr wholesale, preserving
42
+ * the live header/footer references — `EG_HdrFtrReferences` is not part of
43
+ * the `CT_SectPrBase` payload a `w:sectPrChange` stores (ECMA-376
44
+ * §17.13.5.32), so those children survive a reject. The caller re-attaches
45
+ * whatever `propertyChanges` remain unresolved.
46
+ */
47
+ declare function sectionRejectProperties(live: document_d_exports.SectionProperties, previousProperties: document_d_exports.SectionProperties | undefined): document_d_exports.SectionProperties;
48
+ /**
49
+ * Attr patch for rejecting a `w:tblPrChange`: the stored old tblPr wholesale
50
+ * (`w:tblPrChange` stores the complete previous tblPr, so every tblPr-derived
51
+ * attr resets when absent). `columnWidths` comes from `w:tblGrid`, not tblPr,
52
+ * and is untouched.
53
+ */
54
+ declare function tableRejectAttrPatch(previousFormatting: document_d_exports.TableFormatting | undefined): AttrPatch;
55
+ /** Attr patch for rejecting a `w:trPrChange`: the stored old trPr wholesale. */
56
+ declare function tableRowRejectAttrPatch(previousFormatting: document_d_exports.TableRowFormatting | undefined): AttrPatch;
57
+ /**
58
+ * Attr patch for rejecting a `w:tcPrChange`: the stored old tcPr wholesale
59
+ * for the non-structural attrs. `gridSpan` / `vMerge` are structural in
60
+ * ProseMirror (`colspan` / `rowspan` shape the table grid); restoring them
61
+ * from the record would desync the grid without a full table restructure, so
62
+ * the live structure is kept and the rebuilt `_originalFormatting` inherits
63
+ * the live original's `gridSpan` / `vMerge` to stay consistent with it.
64
+ * (Word would also restore tracked merges; folio deliberately does not.)
65
+ */
66
+ declare function tableCellRejectAttrPatch(previousFormatting: document_d_exports.TableCellFormatting | undefined, liveOriginalFormatting: document_d_exports.TableCellFormatting | null | undefined): AttrPatch;
67
+ //#endregion
68
+ export { PPR_CHANGE_SCOPED_ATTR_KEYS, paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, sectionRejectProperties, tableCellRejectAttrPatch, tableRejectAttrPatch, tableRowRejectAttrPatch };
@@ -0,0 +1,242 @@
1
+ import { directionFromBidi } from "../paragraphDirection.js";
2
+ import { setAutospacingBaseValue } from "../autospacingBase.js";
3
+ //#region src/prosemirror/commands/propertyChangeScope.ts
4
+ /**
5
+ * Paragraph attrs governed by a `w:pPrChange` — the attrs
6
+ * `paragraphFormattingToAttrs` (conversion/toProseDoc.ts) can produce from a
7
+ * parsed `CT_PPrBase` (ECMA-376 §17.13.5.29). Rejecting a pPrChange restores
8
+ * the stored old pPr wholesale for exactly these keys: a key absent from the
9
+ * stored record resets to the schema default (`null`).
10
+ *
11
+ * Deliberately OUT of scope (preserved across a reject):
12
+ * - identity/structure: `paraId`, `textId`, `sectionBreakType`,
13
+ * `_sectionProperties`, `_propertyChanges`, `pPrMark`, `bookmarks`,
14
+ * `_emptyHyperlinks`, `renderedPageBreakBefore`
15
+ * - paragraph-mark run properties — `pPr/rPr` is CT_PPr-only, not part of the
16
+ * CT_PPrBase payload a pPrChange stores: `defaultTextFormatting`,
17
+ * `runInWithNext` (`w:specVanish` lives in that rPr)
18
+ * - load-time style/numbering bookkeeping the command layer cannot recompute
19
+ * without a style resolver: `numPrFromStyle`, the `list*` rendering attrs,
20
+ * `spacingFromDocDefaults`
21
+ */
22
+ const PPR_CHANGE_SCOPED_ATTR_KEYS = [
23
+ "styleId",
24
+ "numPr",
25
+ "alignment",
26
+ "spaceBefore",
27
+ "spaceAfter",
28
+ "lineSpacing",
29
+ "lineSpacingRule",
30
+ "spacingExplicit",
31
+ "indentLeft",
32
+ "indentRight",
33
+ "indentFirstLine",
34
+ "hangingIndent",
35
+ "borders",
36
+ "shading",
37
+ "tabs",
38
+ "pageBreakBefore",
39
+ "keepNext",
40
+ "keepLines",
41
+ "widowControl",
42
+ "contextualSpacing",
43
+ "outlineLevel",
44
+ "direction",
45
+ "_autospacingBase"
46
+ ];
47
+ const PPR_CHANGE_SCOPED_ATTR_KEY_SET = new Set(PPR_CHANGE_SCOPED_ATTR_KEYS);
48
+ /**
49
+ * Parser-shaped `ParagraphFormatting` keys that must NOT merge through to
50
+ * attrs verbatim: they either normalize to a differently named attr
51
+ * (`bidi` → `direction`, autospacing flags → `_autospacingBase`), have no
52
+ * attr representation and round-trip via `_originalFormatting` only
53
+ * (`frame`, `suppressLineNumbers`, `suppressAutoHyphens`), or sit outside
54
+ * the CT_PPrBase scope entirely (`runProperties`, `runInWithNext` — the
55
+ * paragraph-mark rPr) and so must never overwrite the live value on reject.
56
+ */
57
+ const PPR_PARSER_ONLY_KEYS = /* @__PURE__ */ new Set([
58
+ "bidi",
59
+ "beforeAutospacing",
60
+ "afterAutospacing",
61
+ "runProperties",
62
+ "runInWithNext",
63
+ "frame",
64
+ "suppressLineNumbers",
65
+ "suppressAutoHyphens",
66
+ "numPrFromStyle"
67
+ ]);
68
+ /**
69
+ * `ParagraphFormatting` keys inside the CT_PPrBase scope, used to rebuild
70
+ * `_originalFormatting` after a reject (old pPr wholesale within scope,
71
+ * paragraph-mark rPr fields preserved from the live original).
72
+ */
73
+ const PPR_CHANGE_SCOPED_FORMATTING_KEYS = [
74
+ "styleId",
75
+ "numPr",
76
+ "alignment",
77
+ "bidi",
78
+ "spaceBefore",
79
+ "spaceAfter",
80
+ "lineSpacing",
81
+ "lineSpacingRule",
82
+ "beforeAutospacing",
83
+ "afterAutospacing",
84
+ "spacingExplicit",
85
+ "indentLeft",
86
+ "indentRight",
87
+ "indentFirstLine",
88
+ "hangingIndent",
89
+ "borders",
90
+ "shading",
91
+ "tabs",
92
+ "pageBreakBefore",
93
+ "keepNext",
94
+ "keepLines",
95
+ "widowControl",
96
+ "contextualSpacing",
97
+ "outlineLevel",
98
+ "frame",
99
+ "suppressLineNumbers",
100
+ "suppressAutoHyphens"
101
+ ];
102
+ /**
103
+ * Build the attr patch that rejecting one pPrChange applies to a paragraph:
104
+ * every in-scope key set to the stored previous value, or reset to `null`
105
+ * when the stored old pPr does not carry it. Keys the record captured beyond
106
+ * the scoped set (editor-created list suggestions snapshot list-rendering
107
+ * bookkeeping attrs) merge through 1:1 so their pre-change values restore too.
108
+ */
109
+ function paragraphRejectAttrPatch(previousFormatting) {
110
+ const prev = previousFormatting ?? {};
111
+ const patch = {};
112
+ for (const key of PPR_CHANGE_SCOPED_ATTR_KEYS) patch[key] = Object.hasOwn(prev, key) ? prev[key] ?? null : null;
113
+ if (!Object.hasOwn(prev, "direction")) patch["direction"] = directionFromBidi(prev["bidi"]);
114
+ if (!Object.hasOwn(prev, "_autospacingBase")) patch["_autospacingBase"] = autospacingBaseFromFormatting(prev);
115
+ for (const [key, value] of Object.entries(prev)) {
116
+ if (PPR_CHANGE_SCOPED_ATTR_KEY_SET.has(key) || PPR_PARSER_ONLY_KEYS.has(key)) continue;
117
+ patch[key] = value ?? null;
118
+ }
119
+ return patch;
120
+ }
121
+ /**
122
+ * Rebuild the paragraph's `_originalFormatting` (the serializer's pPr source)
123
+ * after a reject: the stored old pPr wholesale within CT_PPrBase scope, with
124
+ * the paragraph-mark rPr fields (`runProperties`, `runInWithNext`) preserved
125
+ * from the live original — a pPrChange cannot store them, so a reject must
126
+ * not drop them.
127
+ */
128
+ function paragraphRejectOriginalFormatting(previousFormatting, liveOriginal) {
129
+ const prev = previousFormatting ?? {};
130
+ const result = {};
131
+ for (const key of PPR_CHANGE_SCOPED_FORMATTING_KEYS) {
132
+ const value = Object.hasOwn(prev, key) ? prev[key] : void 0;
133
+ if (value != null) result[key] = value;
134
+ }
135
+ const live = isRecord(liveOriginal) ? liveOriginal : {};
136
+ if (live["runProperties"] != null) result["runProperties"] = live["runProperties"];
137
+ if (live["runInWithNext"] != null) result["runInWithNext"] = live["runInWithNext"];
138
+ if (Object.keys(result).length === 0) return null;
139
+ return result;
140
+ }
141
+ function autospacingBaseFromFormatting(prev) {
142
+ const before = prev["beforeAutospacing"] === true;
143
+ const after = prev["afterAutospacing"] === true;
144
+ if (!before && !after) return null;
145
+ const base = {};
146
+ if (before) setAutospacingBaseValue(base, "before", prev["spaceBefore"]);
147
+ if (after) setAutospacingBaseValue(base, "after", prev["spaceAfter"]);
148
+ return base;
149
+ }
150
+ /**
151
+ * Rejected section properties: the stored old sectPr wholesale, preserving
152
+ * the live header/footer references — `EG_HdrFtrReferences` is not part of
153
+ * the `CT_SectPrBase` payload a `w:sectPrChange` stores (ECMA-376
154
+ * §17.13.5.32), so those children survive a reject. The caller re-attaches
155
+ * whatever `propertyChanges` remain unresolved.
156
+ */
157
+ function sectionRejectProperties(live, previousProperties) {
158
+ const restored = { ...previousProperties };
159
+ delete restored.propertyChanges;
160
+ if (live.headerReferences) restored.headerReferences = live.headerReferences;
161
+ else delete restored.headerReferences;
162
+ if (live.footerReferences) restored.footerReferences = live.footerReferences;
163
+ else delete restored.footerReferences;
164
+ return restored;
165
+ }
166
+ /**
167
+ * Attr patch for rejecting a `w:tblPrChange`: the stored old tblPr wholesale
168
+ * (`w:tblPrChange` stores the complete previous tblPr, so every tblPr-derived
169
+ * attr resets when absent). `columnWidths` comes from `w:tblGrid`, not tblPr,
170
+ * and is untouched.
171
+ */
172
+ function tableRejectAttrPatch(previousFormatting) {
173
+ return {
174
+ styleId: previousFormatting?.styleId ?? null,
175
+ width: previousFormatting?.width?.value ?? null,
176
+ widthType: previousFormatting?.width?.type ?? null,
177
+ justification: previousFormatting?.justification ?? null,
178
+ floating: previousFormatting?.floating ?? null,
179
+ cellMargins: previousFormatting?.cellMargins ? cellMarginsToAttr(previousFormatting.cellMargins) : null,
180
+ look: previousFormatting?.look ?? null,
181
+ borders: previousFormatting?.borders ?? null,
182
+ _originalFormatting: previousFormatting ?? null
183
+ };
184
+ }
185
+ /** Attr patch for rejecting a `w:trPrChange`: the stored old trPr wholesale. */
186
+ function tableRowRejectAttrPatch(previousFormatting) {
187
+ return {
188
+ height: previousFormatting?.height?.value ?? null,
189
+ heightRule: previousFormatting?.heightRule ?? null,
190
+ isHeader: previousFormatting?.header ?? false,
191
+ hidden: previousFormatting?.hidden ?? null,
192
+ _originalFormatting: previousFormatting ?? null
193
+ };
194
+ }
195
+ /**
196
+ * Attr patch for rejecting a `w:tcPrChange`: the stored old tcPr wholesale
197
+ * for the non-structural attrs. `gridSpan` / `vMerge` are structural in
198
+ * ProseMirror (`colspan` / `rowspan` shape the table grid); restoring them
199
+ * from the record would desync the grid without a full table restructure, so
200
+ * the live structure is kept and the rebuilt `_originalFormatting` inherits
201
+ * the live original's `gridSpan` / `vMerge` to stay consistent with it.
202
+ * (Word would also restore tracked merges; folio deliberately does not.)
203
+ */
204
+ function tableCellRejectAttrPatch(previousFormatting, liveOriginalFormatting) {
205
+ const restoredOriginal = { ...previousFormatting };
206
+ delete restoredOriginal.gridSpan;
207
+ delete restoredOriginal.vMerge;
208
+ if (liveOriginalFormatting?.gridSpan !== void 0) restoredOriginal.gridSpan = liveOriginalFormatting.gridSpan;
209
+ if (liveOriginalFormatting?.vMerge !== void 0) restoredOriginal.vMerge = liveOriginalFormatting.vMerge;
210
+ return {
211
+ width: previousFormatting?.width?.value ?? null,
212
+ widthType: previousFormatting?.width?.type ?? null,
213
+ verticalAlign: previousFormatting?.verticalAlign ?? null,
214
+ backgroundColor: previousFormatting?.shading?.fill?.rgb ?? null,
215
+ textDirection: previousFormatting?.textDirection ?? null,
216
+ noWrap: previousFormatting?.noWrap ?? null,
217
+ borders: previousFormatting?.borders ? cellBordersToAttr(previousFormatting.borders) : null,
218
+ margins: previousFormatting?.margins ? cellMarginsToAttr(previousFormatting.margins) : null,
219
+ _originalFormatting: Object.keys(restoredOriginal).length > 0 ? restoredOriginal : null
220
+ };
221
+ }
222
+ function cellMarginsToAttr(margins) {
223
+ const result = {};
224
+ if (margins.top?.value !== void 0) result.top = margins.top.value;
225
+ if (margins.bottom?.value !== void 0) result.bottom = margins.bottom.value;
226
+ if (margins.left?.value !== void 0) result.left = margins.left.value;
227
+ if (margins.right?.value !== void 0) result.right = margins.right.value;
228
+ return result;
229
+ }
230
+ function cellBordersToAttr(borders) {
231
+ const result = {};
232
+ if (borders.top) result.top = borders.top;
233
+ if (borders.bottom) result.bottom = borders.bottom;
234
+ if (borders.left) result.left = borders.left;
235
+ if (borders.right) result.right = borders.right;
236
+ return result;
237
+ }
238
+ function isRecord(value) {
239
+ return typeof value === "object" && value !== null && !Array.isArray(value);
240
+ }
241
+ //#endregion
242
+ export { PPR_CHANGE_SCOPED_ATTR_KEYS, paragraphRejectAttrPatch, paragraphRejectOriginalFormatting, sectionRejectProperties, tableCellRejectAttrPatch, tableRejectAttrPatch, tableRowRejectAttrPatch };
@@ -341,6 +341,7 @@ function paragraphAttrsToFormatting(attrs) {
341
341
  if (attrs.styleId !== (orig.styleId ?? void 0)) if (attrs.styleId) result.styleId = attrs.styleId;
342
342
  else delete result.styleId;
343
343
  assignBooleanToggle(result, attrs, orig, "pageBreakBefore");
344
+ assignBooleanToggle(result, attrs, orig, "widowControl");
344
345
  if (attrs.spacingExplicit !== orig.spacingExplicit) if (attrs.spacingExplicit) result.spacingExplicit = attrs.spacingExplicit;
345
346
  else delete result.spacingExplicit;
346
347
  const bidi = directionToBidi(attrs.direction);
@@ -350,7 +351,7 @@ function paragraphAttrsToFormatting(attrs) {
350
351
  }
351
352
  const outlineLevel = Reflect.get(attrs, "outlineLevel");
352
353
  const bidi = directionToBidi(attrs.direction);
353
- if (!(attrs.alignment || shouldSerializeSpaceBefore || shouldSerializeSpaceAfter || beforeAutospacingEdited || afterAutospacingEdited || attrs.lineSpacing || attrs.indentLeft || attrs.indentRight || attrs.indentFirstLine || attrs.numPr || attrs.styleId || attrs.borders || attrs.shading || attrs.tabs || typeof outlineLevel === "number" || attrs.contextualSpacing || attrs.spacingExplicit || bidi != null || attrs.pageBreakBefore != null)) return;
354
+ if (!(attrs.alignment || shouldSerializeSpaceBefore || shouldSerializeSpaceAfter || beforeAutospacingEdited || afterAutospacingEdited || attrs.lineSpacing || attrs.indentLeft || attrs.indentRight || attrs.indentFirstLine || attrs.numPr || attrs.styleId || attrs.borders || attrs.shading || attrs.tabs || typeof outlineLevel === "number" || attrs.contextualSpacing || attrs.spacingExplicit || bidi != null || attrs.pageBreakBefore != null || attrs.widowControl != null)) return;
354
355
  const f = {};
355
356
  if (attrs.alignment) f.alignment = attrs.alignment;
356
357
  if (shouldSerializeSpaceBefore) f.spaceBefore = spaceBefore;
@@ -373,6 +374,7 @@ function paragraphAttrsToFormatting(attrs) {
373
374
  if (attrs.contextualSpacing) f.contextualSpacing = attrs.contextualSpacing;
374
375
  if (bidi != null) f.bidi = bidi;
375
376
  if (attrs.pageBreakBefore != null) f.pageBreakBefore = attrs.pageBreakBefore;
377
+ if (attrs.widowControl != null) f.widowControl = attrs.widowControl;
376
378
  return f;
377
379
  }
378
380
  /**
@@ -491,13 +493,12 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks) {
491
493
  }
492
494
  if (linkMark) {
493
495
  const linkKey = getLinkKey(linkMark);
494
- if (currentHyperlink && currentHyperlinkKey === linkKey) addNodeToHyperlink(currentHyperlink, node);
495
- else {
496
+ if (currentHyperlink && currentHyperlinkKey === linkKey) {} else {
496
497
  flushCurrentInline();
497
498
  currentHyperlink = createHyperlink(linkMark);
498
499
  currentHyperlinkKey = linkKey;
499
- addNodeToHyperlink(currentHyperlink, node);
500
500
  }
501
+ addNodeToHyperlink(currentHyperlink, node);
501
502
  return;
502
503
  }
503
504
  if (currentHyperlink) flushCurrentInline();
@@ -1234,6 +1235,7 @@ function convertPMTable(node, documentCounts) {
1234
1235
  rows
1235
1236
  };
1236
1237
  if (attrs.columnWidths) minTable.columnWidths = attrs.columnWidths;
1238
+ restoreTablePropertyChanges(minTable, attrs);
1237
1239
  return minTable;
1238
1240
  }
1239
1241
  }
@@ -1243,8 +1245,17 @@ function convertPMTable(node, documentCounts) {
1243
1245
  };
1244
1246
  if (attrs.columnWidths) table.columnWidths = attrs.columnWidths;
1245
1247
  if (formatting) table.formatting = formatting;
1248
+ restoreTablePropertyChanges(table, attrs);
1246
1249
  return table;
1247
1250
  }
1251
+ /**
1252
+ * Restore `w:tblPrChange` entries that PM carried opaquely on the table attrs
1253
+ * (same rationale as the paragraph `_propertyChanges` attr): they must survive
1254
+ * an edit so the saved DOCX keeps the tracked property-change history.
1255
+ */
1256
+ function restoreTablePropertyChanges(table, attrs) {
1257
+ if (Array.isArray(attrs.tblPrChange) && attrs.tblPrChange.length > 0) table.propertyChanges = [...attrs.tblPrChange];
1258
+ }
1248
1259
  function convertPMTableRows(node, documentCounts) {
1249
1260
  const rows = [];
1250
1261
  const activeVerticalMerges = /* @__PURE__ */ new Map();
@@ -1367,6 +1378,7 @@ function convertPMTableRow(node, documentCounts, activeVerticalMerges) {
1367
1378
  };
1368
1379
  const rowFormatting = tableRowAttrsToFormatting(attrs);
1369
1380
  if (rowFormatting) row.formatting = rowFormatting;
1381
+ if (Array.isArray(attrs.trPrChange) && attrs.trPrChange.length > 0) row.propertyChanges = [...attrs.trPrChange];
1370
1382
  return row;
1371
1383
  }
1372
1384
  function createVerticalMergeContinuationCell(colspan) {
@@ -1397,9 +1409,11 @@ function tableRowAttrsToFormatting(attrs) {
1397
1409
  else delete result.heightRule;
1398
1410
  if (attrs.isHeader !== (orig.header ?? void 0)) if (attrs.isHeader) result.header = attrs.isHeader;
1399
1411
  else delete result.header;
1412
+ if (attrs.hidden !== (orig.hidden ?? void 0)) if (attrs.hidden) result.hidden = attrs.hidden;
1413
+ else delete result.hidden;
1400
1414
  return result;
1401
1415
  }
1402
- if (!(attrs.height || attrs.isHeader)) return;
1416
+ if (!(attrs.height || attrs.isHeader || attrs.hidden)) return;
1403
1417
  const f = {};
1404
1418
  if (attrs.height) f.height = {
1405
1419
  value: attrs.height,
@@ -1407,6 +1421,7 @@ function tableRowAttrsToFormatting(attrs) {
1407
1421
  };
1408
1422
  if (attrs.heightRule) f.heightRule = attrs.heightRule;
1409
1423
  if (attrs.isHeader) f.header = attrs.isHeader;
1424
+ if (attrs.hidden) f.hidden = attrs.hidden;
1410
1425
  return f;
1411
1426
  }
1412
1427
  /**
@@ -1425,6 +1440,7 @@ function convertPMTableCell(node, documentCounts) {
1425
1440
  };
1426
1441
  const cellFormatting = tableCellAttrsToFormatting(attrs);
1427
1442
  if (cellFormatting) cell.formatting = cellFormatting;
1443
+ if (Array.isArray(attrs.tcPrChange) && attrs.tcPrChange.length > 0) cell.propertyChanges = [...attrs.tcPrChange];
1428
1444
  return cell;
1429
1445
  }
1430
1446
  /**
@@ -11,6 +11,7 @@ import { createStyleEngine } from "../../style-engine/styleEngine.js";
11
11
  import { buildRunFormattingOverrideAttrs } from "../extensions/marks/RunFormattingOverrideExtension.js";
12
12
  import { schema } from "../schema/index.js";
13
13
  //#region src/prosemirror/conversion/toProseDoc.ts
14
+ const TOC_STYLE_ID = /^TOC\d*$/iu;
14
15
  /**
15
16
  * Convert a Document to a ProseMirror document
16
17
  *
@@ -80,6 +81,7 @@ function convertBlockSdt(blockSdt, convertBlocks) {
80
81
  */
81
82
  function convertParagraph(paragraph, styleResolver, activeCommentIds, extraRunFormatting, tableParagraphOverlay) {
82
83
  const attrs = paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOverlay);
84
+ const isTocParagraph = TOC_STYLE_ID.test(paragraph.formatting?.styleId ?? "");
83
85
  const inlineNodes = [];
84
86
  let inlineOffset = 0;
85
87
  let bookmarksArr;
@@ -98,13 +100,16 @@ function convertParagraph(paragraph, styleResolver, activeCommentIds, extraRunFo
98
100
  };
99
101
  let styleRunFormatting;
100
102
  if (styleResolver) styleRunFormatting = styleResolver.resolveParagraphStyle(paragraph.formatting?.styleId).runFormatting;
101
- const paragraphRunFormatting = paragraph.formatting?.runProperties ? resolveTextFormatting(paragraph.formatting.runProperties, styleResolver) : void 0;
102
- const inheritableParagraphRunFormatting = paragraphRunFormatting ? stripParagraphMarkOnlyFormatting(paragraphRunFormatting) : void 0;
103
+ const paragraphRunFormatting = resolveParagraphMarkRunFormatting(paragraph.formatting?.runProperties, styleResolver);
104
+ let inheritableParagraphRunFormatting;
105
+ if (paragraphRunFormatting && !isTocParagraph) inheritableParagraphRunFormatting = stripParagraphMarkOnlyFormatting(paragraphRunFormatting);
103
106
  const baseRunFormatting = mergeTextFormatting(styleRunFormatting, extraRunFormatting);
104
- const defaultRunFormatting = mergeTextFormatting(baseRunFormatting, inheritableParagraphRunFormatting);
105
- const getInheritedRunFormatting = (formatting) => {
107
+ const paragraphMarkPrecedesStyle = paragraph.formatting?.styleId !== void 0;
108
+ const defaultRunFormatting = paragraphMarkPrecedesStyle ? mergeTextFormatting(inheritableParagraphRunFormatting, baseRunFormatting) : mergeTextFormatting(baseRunFormatting, inheritableParagraphRunFormatting);
109
+ const getInheritedRunFormatting = (formatting, fieldType) => {
110
+ if (fieldType === "TOC") return hasDirectRunFormatting(formatting) ? suppressParagraphMarkFormatting(baseRunFormatting, void 0, formatting) : baseRunFormatting;
106
111
  if (!hasDirectRunFormatting(formatting)) return defaultRunFormatting;
107
- return suppressParagraphMarkFormatting(baseRunFormatting, inheritableParagraphRunFormatting, formatting);
112
+ return suppressParagraphMarkFormatting(baseRunFormatting, inheritableParagraphRunFormatting, formatting, paragraphMarkPrecedesStyle);
108
113
  };
109
114
  const emitTrackedChange = (change, markType, moveKind) => {
110
115
  emitInlineNodes(convertTrackedChange(change, markType, getInheritedRunFormatting, styleResolver, moveKind));
@@ -224,6 +229,10 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
224
229
  if (paragraph.listRendering?.implicitChildLevelAdvances !== void 0) attrs.listImplicitChildLevelAdvances = paragraph.listRendering.implicitChildLevelAdvances;
225
230
  if (paragraph.listRendering?.markerSecondSlotOffsetTwips !== void 0) attrs.listMarkerSecondSlotOffsetTwips = paragraph.listRendering.markerSecondSlotOffsetTwips;
226
231
  if (paragraph.listRendering?.levelNumFmts) attrs.listLevelNumFmts = paragraph.listRendering.levelNumFmts;
232
+ if (paragraph.listRendering && "levelStarts" in paragraph.listRendering) {
233
+ const { levelStarts } = paragraph.listRendering;
234
+ if (Array.isArray(levelStarts) && levelStarts.every((value) => typeof value === "number")) attrs.listLevelStarts = levelStarts;
235
+ }
227
236
  if (paragraph.listRendering?.abstractNumId !== void 0) attrs.listAbstractNumId = paragraph.listRendering.abstractNumId;
228
237
  if (paragraph.listRendering?.startOverride !== void 0) attrs.listStartOverride = paragraph.listRendering.startOverride;
229
238
  if (formatting) attrs._originalFormatting = formatting;
@@ -241,6 +250,12 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
241
250
  set("lineSpacing", formatting?.lineSpacing ?? stylePpr?.lineSpacing);
242
251
  set("lineSpacingRule", formatting?.lineSpacingRule ?? stylePpr?.lineSpacingRule);
243
252
  set("spacingExplicit", formatting?.spacingExplicit);
253
+ const paragraphStyle = styleId ? styleResolver.getStyle(styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
254
+ const docDefaultSpacing = styleResolver.getDocDefaults()?.pPr;
255
+ const spacingFromDocDefaults = {};
256
+ if (formatting?.spaceBefore === void 0 && tableParagraphOverlay?.spaceBefore === void 0 && paragraphStyle?.pPr?.spaceBefore === void 0 && docDefaultSpacing?.spaceBefore !== void 0) spacingFromDocDefaults.before = true;
257
+ if (formatting?.spaceAfter === void 0 && tableParagraphOverlay?.spaceAfter === void 0 && paragraphStyle?.pPr?.spaceAfter === void 0 && docDefaultSpacing?.spaceAfter !== void 0) spacingFromDocDefaults.after = true;
258
+ if (spacingFromDocDefaults.before || spacingFromDocDefaults.after) attrs.spacingFromDocDefaults = spacingFromDocDefaults;
244
259
  set("indentLeft", formatting?.indentLeft ?? stylePpr?.indentLeft);
245
260
  set("indentRight", formatting?.indentRight ?? stylePpr?.indentRight);
246
261
  const styleFirstLine = formatting?.numPr?.numId === 0 && stylePpr?.numPr !== void 0 && stylePpr.numPr.numId !== 0 ? void 0 : stylePpr;
@@ -252,11 +267,12 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
252
267
  set("pageBreakBefore", formatting?.pageBreakBefore ?? stylePpr?.pageBreakBefore);
253
268
  set("keepNext", formatting?.keepNext ?? stylePpr?.keepNext);
254
269
  set("keepLines", formatting?.keepLines ?? stylePpr?.keepLines);
270
+ set("widowControl", formatting?.widowControl ?? stylePpr?.widowControl);
255
271
  set("contextualSpacing", formatting?.contextualSpacing ?? stylePpr?.contextualSpacing);
256
272
  set("runInWithNext", formatting?.runInWithNext ?? stylePpr?.runInWithNext);
257
273
  set("outlineLevel", formatting?.outlineLevel ?? stylePpr?.outlineLevel);
258
274
  set("direction", directionFromBidi(formatting?.bidi ?? stylePpr?.bidi));
259
- set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver));
275
+ set("defaultTextFormatting", resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, { includeParagraphMarkRunProperties: !TOC_STYLE_ID.test(styleId ?? "") }));
260
276
  if (!formatting?.numPr && stylePpr?.numPr && stylePpr.numPr.numId !== 0) {
261
277
  attrs.numPr = stylePpr.numPr;
262
278
  attrs.numPrFromStyle = stylePpr.numPr;
@@ -278,6 +294,7 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
278
294
  set("pageBreakBefore", formatting?.pageBreakBefore);
279
295
  set("keepNext", formatting?.keepNext);
280
296
  set("keepLines", formatting?.keepLines);
297
+ set("widowControl", formatting?.widowControl);
281
298
  set("runInWithNext", formatting?.runInWithNext);
282
299
  set("outlineLevel", formatting?.outlineLevel);
283
300
  set("direction", directionFromBidi(formatting?.bidi));
@@ -381,12 +398,12 @@ function hasDirectRunFormatting(formatting) {
381
398
  return Object.entries(formatting).some(([key, value]) => key !== "styleId" && value !== void 0);
382
399
  }
383
400
  function stripParagraphMarkOnlyFormatting(formatting) {
384
- const { highlight: _h, shading: _s, ...rest } = formatting;
401
+ const { allCaps: _ac, highlight: _h, shading: _s, smallCaps: _sc, ...rest } = formatting;
385
402
  return Object.keys(rest).length > 0 ? rest : void 0;
386
403
  }
387
- function suppressParagraphMarkFormatting(base, paragraphMark, direct) {
404
+ function suppressParagraphMarkFormatting(base, paragraphMark, direct, paragraphMarkPrecedesStyle = false) {
388
405
  if (!paragraphMark) return base;
389
- const result = { ...base };
406
+ const result = (paragraphMarkPrecedesStyle ? mergeTextFormatting(paragraphMark, base) : mergeTextFormatting(base, paragraphMark)) ?? {};
390
407
  suppressBooleanParagraphMark(result, paragraphMark, direct, "bold");
391
408
  suppressBooleanParagraphMark(result, paragraphMark, direct, "italic");
392
409
  suppressBooleanParagraphMark(result, paragraphMark, direct, "strike");
@@ -399,7 +416,10 @@ function suppressParagraphMarkFormatting(base, paragraphMark, direct) {
399
416
  suppressBooleanParagraphMark(result, paragraphMark, direct, "shadow");
400
417
  suppressBooleanParagraphMark(result, paragraphMark, direct, "outline");
401
418
  suppressBooleanParagraphMark(result, paragraphMark, direct, "rtl");
419
+ if (paragraphMark.fontSize !== void 0 && direct?.fontSize === void 0 && base?.fontSize !== void 0) result.fontSize = base.fontSize;
420
+ if (paragraphMark.fontSizeCs !== void 0 && direct?.fontSizeCs === void 0 && base?.fontSizeCs !== void 0) result.fontSizeCs = base.fontSizeCs;
402
421
  if (paragraphMark.underline !== void 0 && direct?.underline === void 0) result.underline = { style: "none" };
422
+ if (paragraphMark.spacing !== void 0 && direct?.spacing === void 0) result.spacing = 0;
403
423
  return Object.keys(result).length > 0 ? result : void 0;
404
424
  }
405
425
  function suppressBooleanParagraphMark(result, paragraphMark, direct, key) {
@@ -411,13 +431,17 @@ function resolveTextFormatting(formatting, styleResolver) {
411
431
  if (!styleResolver) return formatting;
412
432
  return mergeTextFormatting(styleResolver.resolveRunStyle(formatting.styleId), formatting);
413
433
  }
414
- function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver) {
434
+ function resolveParagraphMarkRunFormatting(formatting, styleResolver) {
435
+ if (!formatting || !styleResolver) return formatting;
436
+ return mergeTextFormatting(formatting.styleId ? styleResolver.getRunStyleOwnProperties(formatting.styleId) : void 0, formatting);
437
+ }
438
+ function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, options = {}) {
415
439
  const style = styleId ? styleResolver.getStyle(styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
416
440
  const paragraphStyleRpr = style?.type === "paragraph" ? style.rPr : void 0;
417
- const rawParagraphMarkRpr = formatting?.runProperties;
418
- const characterStyleRpr = rawParagraphMarkRpr?.styleId !== void 0 ? styleResolver.getRunStyleOwnProperties(rawParagraphMarkRpr.styleId) : void 0;
419
- const paragraphRunProperties = rawParagraphMarkRpr ? stripParagraphMarkOnlyFormatting(mergeTextFormatting(characterStyleRpr, rawParagraphMarkRpr) ?? {}) : void 0;
420
- return mergeTextFormatting(mergeTextFormatting(mergeTextFormatting(styleResolver.getDocDefaults()?.rPr, styleResolver.getDefaultCharacterStyle()?.rPr), paragraphStyleRpr), paragraphRunProperties);
441
+ const rawParagraphMarkRpr = options.includeParagraphMarkRunProperties === false ? void 0 : formatting?.runProperties;
442
+ const paragraphRunProperties = rawParagraphMarkRpr ? stripParagraphMarkOnlyFormatting(resolveParagraphMarkRunFormatting(rawParagraphMarkRpr, styleResolver) ?? {}) : void 0;
443
+ const bodyRunDefaults = mergeTextFormatting(mergeTextFormatting(styleResolver.getDocDefaults()?.rPr, styleResolver.getDefaultCharacterStyle()?.rPr), paragraphStyleRpr);
444
+ return styleId === void 0 ? mergeTextFormatting(bodyRunDefaults, paragraphRunProperties) : mergeTextFormatting(paragraphRunProperties, bodyRunDefaults);
421
445
  }
422
446
  function calculateRowSpans(table) {
423
447
  const result = /* @__PURE__ */ new Map();
@@ -543,6 +567,7 @@ function convertTable(table, styleResolver, theme) {
543
567
  if (table.formatting?.look) attrs.look = table.formatting.look;
544
568
  if (table.formatting?.borders) attrs.borders = table.formatting.borders;
545
569
  if (table.formatting) attrs._originalFormatting = table.formatting;
570
+ if (table.propertyChanges && table.propertyChanges.length > 0) attrs.tblPrChange = [...table.propertyChanges];
546
571
  const conditionalStyles = {};
547
572
  const setCS = (key, type) => {
548
573
  const val = resolveTableStyleConditional(styleResolver, conditionalTableStyleId, type);
@@ -599,7 +624,9 @@ function convertTableRow(row, styleResolver, isHeaderRow, columnWidths, totalWid
599
624
  const attrs = { isHeader: !!row.formatting?.header };
600
625
  if (row.formatting?.height?.value !== void 0) attrs.height = row.formatting.height.value;
601
626
  if (row.formatting?.heightRule) attrs.heightRule = row.formatting.heightRule;
627
+ if (row.formatting?.hidden) attrs.hidden = true;
602
628
  if (row.formatting) attrs._originalFormatting = row.formatting;
629
+ if (row.propertyChanges && row.propertyChanges.length > 0) attrs.trPrChange = [...row.propertyChanges];
603
630
  const numCells = row.cells.length;
604
631
  const isFirstRow = rowIndex === 0;
605
632
  const isLastRow = rowIndex === (totalRows ?? 1) - 1;
@@ -745,6 +772,7 @@ function convertTableCell(cell, styleResolver, isHeader, gridWidthPercent, condi
745
772
  else if (conditionalStyle?.tcPr?.margins) attrs.margins = buildMarginsAttr(conditionalStyle.tcPr.margins);
746
773
  else if (defaultCellMargins) attrs.margins = defaultCellMargins;
747
774
  if (formatting) attrs._originalFormatting = formatting;
775
+ if (cell.propertyChanges && cell.propertyChanges.length > 0) attrs.tcPrChange = [...cell.propertyChanges];
748
776
  if (preserveVMergeRestart) attrs._preserveVMergeRestart = true;
749
777
  if (vMergeContinuationCells && vMergeContinuationCells.length > 0) attrs._docxVMergeContinuationCells = vMergeContinuationCells;
750
778
  const contentNodes = [];
@@ -769,7 +797,7 @@ function convertField(field, getInheritedRunFormatting, styleResolver) {
769
797
  if (!fieldFormatting && r.formatting) fieldFormatting = r.formatting;
770
798
  }
771
799
  if (!fieldFormatting && field.type === "complexField" && field.fieldResult.length === 0) fieldFormatting = field.formatting;
772
- const inheritedFormatting = getInheritedRunFormatting(fieldFormatting);
800
+ const inheritedFormatting = getInheritedRunFormatting(fieldFormatting, field.fieldType);
773
801
  const { marks } = buildRunMarks(fieldFormatting, inheritedFormatting, styleResolver);
774
802
  return schema.node("field", {
775
803
  fieldType: field.fieldType,
@@ -185,6 +185,7 @@ const paragraphNodeSpec = {
185
185
  lineSpacing: { default: null },
186
186
  lineSpacingRule: { default: null },
187
187
  spacingExplicit: { default: null },
188
+ spacingFromDocDefaults: { default: null },
188
189
  indentLeft: { default: null },
189
190
  indentRight: { default: null },
190
191
  indentFirstLine: { default: null },
@@ -203,6 +204,7 @@ const paragraphNodeSpec = {
203
204
  listImplicitChildLevelAdvances: { default: null },
204
205
  listMarkerSecondSlotOffsetTwips: { default: null },
205
206
  listLevelNumFmts: { default: null },
207
+ listLevelStarts: { default: null },
206
208
  listAbstractNumId: { default: null },
207
209
  listStartOverride: { default: null },
208
210
  styleId: { default: null },
@@ -213,6 +215,7 @@ const paragraphNodeSpec = {
213
215
  renderedPageBreakBefore: { default: null },
214
216
  keepNext: { default: null },
215
217
  keepLines: { default: null },
218
+ widowControl: { default: null },
216
219
  contextualSpacing: { default: null },
217
220
  runInWithNext: { default: null },
218
221
  defaultTextFormatting: { default: null },
@@ -1,3 +1,4 @@
1
+ import { PPR_CHANGE_SCOPED_ATTR_KEYS } from "../../commands/propertyChangeScope.js";
1
2
  import { Priority } from "../types.js";
2
3
  import { createExtension } from "../create.js";
3
4
  import { SUGGESTION_META, makeRevisionInfo } from "../../plugins/suggestionMode.js";
@@ -35,11 +36,16 @@ const LIST_FORMATTING_ATTRS = [
35
36
  "listMarkerFontSize",
36
37
  "listMarkerSuffix",
37
38
  "listLevelNumFmts",
39
+ "listLevelStarts",
38
40
  "listAbstractNumId",
39
41
  "listStartOverride"
40
42
  ];
41
43
  function getPreviousListFormatting(attrs) {
42
44
  const previousFormatting = {};
45
+ for (const key of PPR_CHANGE_SCOPED_ATTR_KEYS) {
46
+ const value = attrs[key];
47
+ if (value != null) previousFormatting[key] = value;
48
+ }
43
49
  for (const key of LIST_FORMATTING_ATTRS) previousFormatting[key] = attrs[key] ?? null;
44
50
  return previousFormatting;
45
51
  }