@stll/folio-core 0.4.0 → 0.6.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 (98) 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 +37 -4
  6. package/dist/ai-edits/headless.js +134 -16
  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 -137
  16. package/dist/controller/layoutScheduler.d.ts +2 -1
  17. package/dist/controller/layoutScheduler.js +6 -0
  18. package/dist/document-operations.d.ts +139 -0
  19. package/dist/document-operations.js +578 -0
  20. package/dist/docx/blockContentParser.js +17 -7
  21. package/dist/docx/encryption/agileDecryption.js +2 -1
  22. package/dist/docx/encryption/compoundFile.js +4 -2
  23. package/dist/docx/footnoteParser.d.ts +1 -17
  24. package/dist/docx/footnoteParser.js +1 -27
  25. package/dist/docx/groupDrawingParser.d.ts +8 -0
  26. package/dist/docx/groupDrawingParser.js +131 -0
  27. package/dist/docx/numberingParser.d.ts +3 -1
  28. package/dist/docx/numberingParser.js +8 -2
  29. package/dist/docx/paragraphParser.js +9 -3
  30. package/dist/docx/runParser.js +8 -1
  31. package/dist/docx/selectiveXmlPatch.js +4 -10
  32. package/dist/docx/serializer/numberingSerializer.js +3 -1
  33. package/dist/docx/settingsParser.d.ts +6 -3
  34. package/dist/docx/settingsParser.js +2 -0
  35. package/dist/docx/xmlParser.js +11 -4
  36. package/dist/i18n/messages/catalogs.gen.d.ts +1054 -34
  37. package/dist/i18n/messages/catalogs.gen.js +1122 -68
  38. package/dist/i18n/messages/messages.gen.d.ts +62 -2
  39. package/dist/index.d.ts +3 -2
  40. package/dist/index.js +6 -5
  41. package/dist/layout-bridge/convert/footnoteLayout.d.ts +37 -1
  42. package/dist/layout-bridge/convert/footnoteLayout.js +138 -14
  43. package/dist/layout-bridge/convert/headerFooterLayout.d.ts +5 -7
  44. package/dist/layout-bridge/convert/headerFooterLayout.js +5 -7
  45. package/dist/layout-bridge/convert/toFlowBlocks.js +56 -19
  46. package/dist/layout-engine/index.d.ts +6 -5
  47. package/dist/layout-engine/index.js +143 -30
  48. package/dist/layout-engine/keep-together.d.ts +13 -8
  49. package/dist/layout-engine/keep-together.js +40 -25
  50. package/dist/layout-engine/layoutInstrumentation.d.ts +11 -1
  51. package/dist/layout-engine/layoutInstrumentation.js +10 -1
  52. package/dist/layout-engine/measure/measureBlocks.js +50 -18
  53. package/dist/layout-engine/measure/measureParagraph.js +61 -15
  54. package/dist/layout-engine/paginator.d.ts +2 -1
  55. package/dist/layout-engine/paginator.js +9 -3
  56. package/dist/layout-engine/textBoxGroup.d.ts +7 -0
  57. package/dist/layout-engine/textBoxGroup.js +8 -0
  58. package/dist/layout-engine/types.d.ts +30 -9
  59. package/dist/layout-engine/types.js +20 -2
  60. package/dist/layout-painter/renderPage.d.ts +15 -1
  61. package/dist/layout-painter/renderPage.js +27 -11
  62. package/dist/layout-painter/renderParagraph.js +18 -8
  63. package/dist/layout-painter/renderTable.js +10 -7
  64. package/dist/managers/DocumentLoaderManager.js +12 -5
  65. package/dist/model.js +1 -1
  66. package/dist/paged-layout/pageText.d.ts +14 -0
  67. package/dist/paged-layout/pageText.js +21 -0
  68. package/dist/prosemirror/attrs/index.js +2 -0
  69. package/dist/prosemirror/commands/comments.js +75 -5
  70. package/dist/prosemirror/commands/hyperlink.js +4 -2
  71. package/dist/prosemirror/commands/image.js +2 -1
  72. package/dist/prosemirror/commands/propertyChangeScope.d.ts +68 -0
  73. package/dist/prosemirror/commands/propertyChangeScope.js +242 -0
  74. package/dist/prosemirror/conversion/fromProseDoc.js +14 -3
  75. package/dist/prosemirror/conversion/toProseDoc.js +29 -8
  76. package/dist/prosemirror/extensions/core/ParagraphExtension.js +2 -0
  77. package/dist/prosemirror/extensions/features/ListExtension.js +6 -0
  78. package/dist/prosemirror/extensions/nodes/TableExtension.js +10 -11
  79. package/dist/prosemirror/findReplaceSelection.js +2 -1
  80. package/dist/prosemirror/schema/nodes.d.ts +10 -5
  81. package/dist/prosemirror/styles/resolvedStyleAttrs.js +1 -0
  82. package/dist/prosemirror/utils/tabCalculator.js +4 -2
  83. package/dist/redline.d.ts +20 -0
  84. package/dist/redline.js +127 -0
  85. package/dist/server.d.ts +7 -3
  86. package/dist/server.js +6 -2
  87. package/dist/symbols.d.ts +35 -0
  88. package/dist/symbols.js +512 -0
  89. package/dist/utils/clipboard.js +3 -3
  90. package/dist/utils/fontLoader.js +3 -0
  91. package/dist/utils/fontResolver.js +48 -1
  92. package/dist/utils/zoom.d.ts +21 -0
  93. package/dist/utils/zoom.js +21 -0
  94. package/dist/version-comparison.d.ts +92 -0
  95. package/dist/version-comparison.js +436 -0
  96. package/package.json +3 -3
  97. package/dist/paged-layout/headerFooterMargins.d.ts +0 -75
  98. package/dist/paged-layout/headerFooterMargins.js +0 -122
@@ -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 };
@@ -493,13 +493,12 @@ function extractParagraphContent(paragraph, _documentCounts, emptyHyperlinks) {
493
493
  }
494
494
  if (linkMark) {
495
495
  const linkKey = getLinkKey(linkMark);
496
- if (currentHyperlink && currentHyperlinkKey === linkKey) addNodeToHyperlink(currentHyperlink, node);
497
- else {
496
+ if (currentHyperlink && currentHyperlinkKey === linkKey) {} else {
498
497
  flushCurrentInline();
499
498
  currentHyperlink = createHyperlink(linkMark);
500
499
  currentHyperlinkKey = linkKey;
501
- addNodeToHyperlink(currentHyperlink, node);
502
500
  }
501
+ addNodeToHyperlink(currentHyperlink, node);
503
502
  return;
504
503
  }
505
504
  if (currentHyperlink) flushCurrentInline();
@@ -1236,6 +1235,7 @@ function convertPMTable(node, documentCounts) {
1236
1235
  rows
1237
1236
  };
1238
1237
  if (attrs.columnWidths) minTable.columnWidths = attrs.columnWidths;
1238
+ restoreTablePropertyChanges(minTable, attrs);
1239
1239
  return minTable;
1240
1240
  }
1241
1241
  }
@@ -1245,8 +1245,17 @@ function convertPMTable(node, documentCounts) {
1245
1245
  };
1246
1246
  if (attrs.columnWidths) table.columnWidths = attrs.columnWidths;
1247
1247
  if (formatting) table.formatting = formatting;
1248
+ restoreTablePropertyChanges(table, attrs);
1248
1249
  return table;
1249
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
+ }
1250
1259
  function convertPMTableRows(node, documentCounts) {
1251
1260
  const rows = [];
1252
1261
  const activeVerticalMerges = /* @__PURE__ */ new Map();
@@ -1369,6 +1378,7 @@ function convertPMTableRow(node, documentCounts, activeVerticalMerges) {
1369
1378
  };
1370
1379
  const rowFormatting = tableRowAttrsToFormatting(attrs);
1371
1380
  if (rowFormatting) row.formatting = rowFormatting;
1381
+ if (Array.isArray(attrs.trPrChange) && attrs.trPrChange.length > 0) row.propertyChanges = [...attrs.trPrChange];
1372
1382
  return row;
1373
1383
  }
1374
1384
  function createVerticalMergeContinuationCell(colspan) {
@@ -1430,6 +1440,7 @@ function convertPMTableCell(node, documentCounts) {
1430
1440
  };
1431
1441
  const cellFormatting = tableCellAttrsToFormatting(attrs);
1432
1442
  if (cellFormatting) cell.formatting = cellFormatting;
1443
+ if (Array.isArray(attrs.tcPrChange) && attrs.tcPrChange.length > 0) cell.propertyChanges = [...attrs.tcPrChange];
1433
1444
  return cell;
1434
1445
  }
1435
1446
  /**
@@ -100,15 +100,16 @@ function convertParagraph(paragraph, styleResolver, activeCommentIds, extraRunFo
100
100
  };
101
101
  let styleRunFormatting;
102
102
  if (styleResolver) styleRunFormatting = styleResolver.resolveParagraphStyle(paragraph.formatting?.styleId).runFormatting;
103
- const paragraphRunFormatting = paragraph.formatting?.runProperties ? resolveTextFormatting(paragraph.formatting.runProperties, styleResolver) : void 0;
103
+ const paragraphRunFormatting = resolveParagraphMarkRunFormatting(paragraph.formatting?.runProperties, styleResolver);
104
104
  let inheritableParagraphRunFormatting;
105
105
  if (paragraphRunFormatting && !isTocParagraph) inheritableParagraphRunFormatting = stripParagraphMarkOnlyFormatting(paragraphRunFormatting);
106
106
  const baseRunFormatting = mergeTextFormatting(styleRunFormatting, extraRunFormatting);
107
- const defaultRunFormatting = mergeTextFormatting(baseRunFormatting, inheritableParagraphRunFormatting);
107
+ const paragraphMarkPrecedesStyle = paragraph.formatting?.styleId !== void 0;
108
+ const defaultRunFormatting = paragraphMarkPrecedesStyle ? mergeTextFormatting(inheritableParagraphRunFormatting, baseRunFormatting) : mergeTextFormatting(baseRunFormatting, inheritableParagraphRunFormatting);
108
109
  const getInheritedRunFormatting = (formatting, fieldType) => {
109
110
  if (fieldType === "TOC") return hasDirectRunFormatting(formatting) ? suppressParagraphMarkFormatting(baseRunFormatting, void 0, formatting) : baseRunFormatting;
110
111
  if (!hasDirectRunFormatting(formatting)) return defaultRunFormatting;
111
- return suppressParagraphMarkFormatting(baseRunFormatting, inheritableParagraphRunFormatting, formatting);
112
+ return suppressParagraphMarkFormatting(baseRunFormatting, inheritableParagraphRunFormatting, formatting, paragraphMarkPrecedesStyle);
112
113
  };
113
114
  const emitTrackedChange = (change, markType, moveKind) => {
114
115
  emitInlineNodes(convertTrackedChange(change, markType, getInheritedRunFormatting, styleResolver, moveKind));
@@ -228,6 +229,10 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
228
229
  if (paragraph.listRendering?.implicitChildLevelAdvances !== void 0) attrs.listImplicitChildLevelAdvances = paragraph.listRendering.implicitChildLevelAdvances;
229
230
  if (paragraph.listRendering?.markerSecondSlotOffsetTwips !== void 0) attrs.listMarkerSecondSlotOffsetTwips = paragraph.listRendering.markerSecondSlotOffsetTwips;
230
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
+ }
231
236
  if (paragraph.listRendering?.abstractNumId !== void 0) attrs.listAbstractNumId = paragraph.listRendering.abstractNumId;
232
237
  if (paragraph.listRendering?.startOverride !== void 0) attrs.listStartOverride = paragraph.listRendering.startOverride;
233
238
  if (formatting) attrs._originalFormatting = formatting;
@@ -245,6 +250,12 @@ function paragraphFormattingToAttrs(paragraph, styleResolver, tableParagraphOver
245
250
  set("lineSpacing", formatting?.lineSpacing ?? stylePpr?.lineSpacing);
246
251
  set("lineSpacingRule", formatting?.lineSpacingRule ?? stylePpr?.lineSpacingRule);
247
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;
248
259
  set("indentLeft", formatting?.indentLeft ?? stylePpr?.indentLeft);
249
260
  set("indentRight", formatting?.indentRight ?? stylePpr?.indentRight);
250
261
  const styleFirstLine = formatting?.numPr?.numId === 0 && stylePpr?.numPr !== void 0 && stylePpr.numPr.numId !== 0 ? void 0 : stylePpr;
@@ -390,9 +401,9 @@ function stripParagraphMarkOnlyFormatting(formatting) {
390
401
  const { allCaps: _ac, highlight: _h, shading: _s, smallCaps: _sc, ...rest } = formatting;
391
402
  return Object.keys(rest).length > 0 ? rest : void 0;
392
403
  }
393
- function suppressParagraphMarkFormatting(base, paragraphMark, direct) {
404
+ function suppressParagraphMarkFormatting(base, paragraphMark, direct, paragraphMarkPrecedesStyle = false) {
394
405
  if (!paragraphMark) return base;
395
- const result = { ...base };
406
+ const result = (paragraphMarkPrecedesStyle ? mergeTextFormatting(paragraphMark, base) : mergeTextFormatting(base, paragraphMark)) ?? {};
396
407
  suppressBooleanParagraphMark(result, paragraphMark, direct, "bold");
397
408
  suppressBooleanParagraphMark(result, paragraphMark, direct, "italic");
398
409
  suppressBooleanParagraphMark(result, paragraphMark, direct, "strike");
@@ -405,7 +416,10 @@ function suppressParagraphMarkFormatting(base, paragraphMark, direct) {
405
416
  suppressBooleanParagraphMark(result, paragraphMark, direct, "shadow");
406
417
  suppressBooleanParagraphMark(result, paragraphMark, direct, "outline");
407
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;
408
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;
409
423
  return Object.keys(result).length > 0 ? result : void 0;
410
424
  }
411
425
  function suppressBooleanParagraphMark(result, paragraphMark, direct, key) {
@@ -417,13 +431,17 @@ function resolveTextFormatting(formatting, styleResolver) {
417
431
  if (!styleResolver) return formatting;
418
432
  return mergeTextFormatting(styleResolver.resolveRunStyle(formatting.styleId), formatting);
419
433
  }
434
+ function resolveParagraphMarkRunFormatting(formatting, styleResolver) {
435
+ if (!formatting || !styleResolver) return formatting;
436
+ return mergeTextFormatting(formatting.styleId ? styleResolver.getRunStyleOwnProperties(formatting.styleId) : void 0, formatting);
437
+ }
420
438
  function resolveParagraphDefaultTextFormatting(styleId, formatting, styleResolver, options = {}) {
421
439
  const style = styleId ? styleResolver.getStyle(styleId) ?? styleResolver.getDefaultParagraphStyle() : styleResolver.getDefaultParagraphStyle();
422
440
  const paragraphStyleRpr = style?.type === "paragraph" ? style.rPr : void 0;
423
441
  const rawParagraphMarkRpr = options.includeParagraphMarkRunProperties === false ? void 0 : formatting?.runProperties;
424
- const characterStyleRpr = rawParagraphMarkRpr?.styleId !== void 0 ? styleResolver.getRunStyleOwnProperties(rawParagraphMarkRpr.styleId) : void 0;
425
- const paragraphRunProperties = rawParagraphMarkRpr ? stripParagraphMarkOnlyFormatting(mergeTextFormatting(characterStyleRpr, rawParagraphMarkRpr) ?? {}) : void 0;
426
- return mergeTextFormatting(mergeTextFormatting(mergeTextFormatting(styleResolver.getDocDefaults()?.rPr, styleResolver.getDefaultCharacterStyle()?.rPr), paragraphStyleRpr), paragraphRunProperties);
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);
427
445
  }
428
446
  function calculateRowSpans(table) {
429
447
  const result = /* @__PURE__ */ new Map();
@@ -549,6 +567,7 @@ function convertTable(table, styleResolver, theme) {
549
567
  if (table.formatting?.look) attrs.look = table.formatting.look;
550
568
  if (table.formatting?.borders) attrs.borders = table.formatting.borders;
551
569
  if (table.formatting) attrs._originalFormatting = table.formatting;
570
+ if (table.propertyChanges && table.propertyChanges.length > 0) attrs.tblPrChange = [...table.propertyChanges];
552
571
  const conditionalStyles = {};
553
572
  const setCS = (key, type) => {
554
573
  const val = resolveTableStyleConditional(styleResolver, conditionalTableStyleId, type);
@@ -607,6 +626,7 @@ function convertTableRow(row, styleResolver, isHeaderRow, columnWidths, totalWid
607
626
  if (row.formatting?.heightRule) attrs.heightRule = row.formatting.heightRule;
608
627
  if (row.formatting?.hidden) attrs.hidden = true;
609
628
  if (row.formatting) attrs._originalFormatting = row.formatting;
629
+ if (row.propertyChanges && row.propertyChanges.length > 0) attrs.trPrChange = [...row.propertyChanges];
610
630
  const numCells = row.cells.length;
611
631
  const isFirstRow = rowIndex === 0;
612
632
  const isLastRow = rowIndex === (totalRows ?? 1) - 1;
@@ -752,6 +772,7 @@ function convertTableCell(cell, styleResolver, isHeader, gridWidthPercent, condi
752
772
  else if (conditionalStyle?.tcPr?.margins) attrs.margins = buildMarginsAttr(conditionalStyle.tcPr.margins);
753
773
  else if (defaultCellMargins) attrs.margins = defaultCellMargins;
754
774
  if (formatting) attrs._originalFormatting = formatting;
775
+ if (cell.propertyChanges && cell.propertyChanges.length > 0) attrs.tcPrChange = [...cell.propertyChanges];
755
776
  if (preserveVMergeRestart) attrs._preserveVMergeRestart = true;
756
777
  if (vMergeContinuationCells && vMergeContinuationCells.length > 0) attrs._docxVMergeContinuationCells = vMergeContinuationCells;
757
778
  const contentNodes = [];
@@ -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 },
@@ -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
  }
@@ -152,7 +152,8 @@ const tableSpec = {
152
152
  cellMargins: { default: null },
153
153
  look: { default: null },
154
154
  borders: { default: null },
155
- _originalFormatting: { default: null }
155
+ _originalFormatting: { default: null },
156
+ tblPrChange: { default: null }
156
157
  },
157
158
  parseDOM: [{
158
159
  tag: "table",
@@ -171,17 +172,12 @@ const tableSpec = {
171
172
  const domAttrs = { class: "docx-table" };
172
173
  if (attrs.styleId) domAttrs["data-style-id"] = attrs.styleId;
173
174
  const styles = ["border-collapse: collapse"];
174
- if (attrs.width !== void 0 && attrs.widthType === "pct") {
175
- styles.push(`width: ${attrs.width / 50}%`);
176
- styles.push("table-layout: fixed");
177
- } else if (attrs.width !== void 0 && attrs.widthType === "dxa") {
175
+ if (attrs.width !== void 0 && attrs.widthType === "pct") styles.push(`width: ${attrs.width / 50}%`);
176
+ else if (attrs.width !== void 0 && attrs.widthType === "dxa") {
178
177
  const widthPx = Math.round(attrs.width / 20 * 1.333);
179
178
  styles.push(`width: ${widthPx}px`);
180
- styles.push("table-layout: fixed");
181
- } else {
182
- styles.push("width: 100%");
183
- styles.push("table-layout: fixed");
184
- }
179
+ } else styles.push("width: 100%");
180
+ styles.push("table-layout: fixed");
185
181
  if (attrs.justification === "center") styles.push("margin-left: auto", "margin-right: auto");
186
182
  else if (attrs.justification === "right") styles.push("margin-left: auto");
187
183
  domAttrs["style"] = styles.join("; ");
@@ -200,7 +196,8 @@ const tableRowSpec = {
200
196
  heightRule: { default: null },
201
197
  isHeader: { default: false },
202
198
  hidden: { default: false },
203
- _originalFormatting: { default: null }
199
+ _originalFormatting: { default: null },
200
+ trPrChange: { default: null }
204
201
  },
205
202
  parseDOM: [{ tag: "tr" }],
206
203
  toDOM(node) {
@@ -317,6 +314,7 @@ const tableCellSpec = {
317
314
  textDirection: { default: null },
318
315
  noWrap: { default: false },
319
316
  _originalFormatting: { default: null },
317
+ tcPrChange: { default: null },
320
318
  _preserveVMergeRestart: { default: null },
321
319
  _docxVMergeContinuationCells: { default: null }
322
320
  },
@@ -369,6 +367,7 @@ const tableHeaderSpec = {
369
367
  textDirection: { default: null },
370
368
  noWrap: { default: false },
371
369
  _originalFormatting: { default: null },
370
+ tcPrChange: { default: null },
372
371
  _preserveVMergeRestart: { default: null },
373
372
  _docxVMergeContinuationCells: { default: null }
374
373
  },
@@ -44,7 +44,8 @@ function resolveFindMatchRange(doc, match) {
44
44
  cellOffset += cell.nodeSize;
45
45
  continue;
46
46
  }
47
- if (!walkBlocks(cell, rowPos + 1 + cellOffset + 1)) return false;
47
+ const cellPos = rowPos + 1 + cellOffset;
48
+ if (!walkBlocks(cell, cellPos + 1)) return false;
48
49
  cellOffset += cell.nodeSize;
49
50
  }
50
51
  rowOffset += row.nodeSize;
@@ -18,7 +18,8 @@ type ParagraphAttrs = {
18
18
  spaceAfter?: number;
19
19
  lineSpacing?: number;
20
20
  lineSpacingRule?: document_d_exports.LineSpacingRule;
21
- spacingExplicit?: SpacingExplicit;
21
+ spacingExplicit?: SpacingExplicit; /** Layout provenance: document defaults survive on empty paragraphs. */
22
+ spacingFromDocDefaults?: SpacingExplicit;
22
23
  indentLeft?: number;
23
24
  indentRight?: number;
24
25
  indentFirstLine?: number;
@@ -65,7 +66,8 @@ type ParagraphAttrs = {
65
66
  * inline LISTNUM "(a)" with the deeper level's marker column.
66
67
  */
67
68
  listMarkerSecondSlotOffsetTwips?: number; /** Number format for each level used by multi-level marker templates. */
68
- listLevelNumFmts?: document_d_exports.NumberFormat[]; /** Abstract numbering ID shared by numbering instances. */
69
+ listLevelNumFmts?: document_d_exports.NumberFormat[]; /** Initial counter for each level used by multi-level marker templates. */
70
+ listLevelStarts?: number[]; /** Abstract numbering ID shared by numbering instances. */
69
71
  listAbstractNumId?: number; /** Numbering start override for this numId/level. */
70
72
  listStartOverride?: number;
71
73
  styleId?: string;
@@ -346,7 +348,8 @@ type TableAttrs = {
346
348
  }; /** Table look flags for conditional formatting (w:tblLook) */
347
349
  look?: document_d_exports.TableLook; /** Table-level borders (w:tblBorders) — full BorderSpec per side */
348
350
  borders?: document_d_exports.TableBorders; /** Original table formatting from DOCX for lossless round-trip serialization */
349
- _originalFormatting?: document_d_exports.TableFormatting;
351
+ _originalFormatting?: document_d_exports.TableFormatting; /** Tracked table property changes (w:tblPrChange) for round-trip + accept/reject */
352
+ tblPrChange?: document_d_exports.TablePropertyChange[];
350
353
  };
351
354
  /**
352
355
  * Table row attributes
@@ -356,7 +359,8 @@ type TableRowAttrs = {
356
359
  heightRule?: NonNullable<document_d_exports.TableRowFormatting["heightRule"]>; /** Is header row */
357
360
  isHeader?: boolean; /** Whether the row is hidden (`w:hidden`) */
358
361
  hidden?: boolean; /** Original row formatting from DOCX for lossless round-trip serialization */
359
- _originalFormatting?: document_d_exports.TableRowFormatting;
362
+ _originalFormatting?: document_d_exports.TableRowFormatting; /** Tracked row property changes (w:trPrChange) for round-trip + accept/reject */
363
+ trPrChange?: document_d_exports.TableRowPropertyChange[];
360
364
  };
361
365
  /**
362
366
  * Table cell attributes
@@ -383,7 +387,8 @@ type TableCellAttrs = {
383
387
  left?: number;
384
388
  right?: number;
385
389
  }; /** Original cell formatting from DOCX for lossless round-trip serialization */
386
- _originalFormatting?: document_d_exports.TableCellFormatting; /** Preserve a DOCX vMerge restart even when PM cannot model it as a rowspan. */
390
+ _originalFormatting?: document_d_exports.TableCellFormatting; /** Tracked cell property changes (w:tcPrChange) for round-trip + accept/reject */
391
+ tcPrChange?: document_d_exports.TableCellPropertyChange[]; /** Preserve a DOCX vMerge restart even when PM cannot model it as a rowspan. */
387
392
  _preserveVMergeRestart?: boolean; /** Original DOCX vMerge continuation cells skipped into this PM rowspan. */
388
393
  _docxVMergeContinuationCells?: document_d_exports.TableCell[];
389
394
  };
@@ -91,6 +91,7 @@ function listAttrsFromResolvedStyle(resolved, numbering) {
91
91
  listImplicitChildLevelAdvances: null,
92
92
  listMarkerSecondSlotOffsetTwips: null,
93
93
  listLevelNumFmts: rendering?.levelNumFmts ?? null,
94
+ listLevelStarts: rendering?.levelStarts ?? null,
94
95
  listAbstractNumId: rendering?.abstractNumId ?? null,
95
96
  listStartOverride: rendering?.startOverride ?? null
96
97
  };