@beyondwork/docx-react-component 1.0.37 → 1.0.39

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 (116) hide show
  1. package/package.json +41 -31
  2. package/src/api/public-types.ts +496 -1
  3. package/src/core/commands/section-layout-commands.ts +58 -0
  4. package/src/core/commands/table-grid.ts +431 -0
  5. package/src/core/commands/table-structure-commands.ts +845 -56
  6. package/src/core/commands/text-commands.ts +122 -2
  7. package/src/io/docx-session.ts +1 -0
  8. package/src/io/export/serialize-main-document.ts +2 -11
  9. package/src/io/export/serialize-numbering.ts +43 -10
  10. package/src/io/export/serialize-paragraph-formatting.ts +152 -0
  11. package/src/io/export/serialize-run-formatting.ts +90 -0
  12. package/src/io/export/serialize-styles.ts +212 -0
  13. package/src/io/export/serialize-tables.ts +74 -0
  14. package/src/io/export/table-properties-xml.ts +139 -4
  15. package/src/io/normalize/normalize-text.ts +15 -0
  16. package/src/io/ooxml/parse-fields.ts +10 -3
  17. package/src/io/ooxml/parse-footnotes.ts +60 -0
  18. package/src/io/ooxml/parse-headers-footers.ts +60 -0
  19. package/src/io/ooxml/parse-main-document.ts +137 -0
  20. package/src/io/ooxml/parse-numbering.ts +41 -1
  21. package/src/io/ooxml/parse-paragraph-formatting.ts +188 -0
  22. package/src/io/ooxml/parse-run-formatting.ts +129 -0
  23. package/src/io/ooxml/parse-styles.ts +31 -0
  24. package/src/io/ooxml/parse-tables.ts +249 -0
  25. package/src/io/ooxml/xml-attr-helpers.ts +60 -0
  26. package/src/io/ooxml/xml-element.ts +19 -0
  27. package/src/model/canonical-document.ts +117 -3
  28. package/src/runtime/collab/event-types.ts +165 -0
  29. package/src/runtime/collab/index.ts +22 -0
  30. package/src/runtime/collab/remote-cursor-awareness.ts +93 -0
  31. package/src/runtime/collab/runtime-collab-sync.ts +273 -0
  32. package/src/runtime/document-layout.ts +4 -2
  33. package/src/runtime/document-navigation.ts +1 -1
  34. package/src/runtime/document-runtime.ts +248 -18
  35. package/src/runtime/layout/default-page-format.ts +96 -0
  36. package/src/runtime/layout/index.ts +47 -0
  37. package/src/runtime/layout/inert-layout-facet.ts +16 -0
  38. package/src/runtime/layout/layout-engine-instance.ts +100 -23
  39. package/src/runtime/layout/layout-invalidation.ts +14 -5
  40. package/src/runtime/layout/margin-preset-catalog.ts +178 -0
  41. package/src/runtime/layout/page-format-catalog.ts +233 -0
  42. package/src/runtime/layout/page-graph.ts +55 -0
  43. package/src/runtime/layout/paginate-paragraph-lines.ts +128 -0
  44. package/src/runtime/layout/paginated-layout-engine.ts +484 -37
  45. package/src/runtime/layout/project-block-fragments.ts +225 -0
  46. package/src/runtime/layout/public-facet.ts +748 -16
  47. package/src/runtime/layout/resolve-page-fields.ts +70 -0
  48. package/src/runtime/layout/resolve-page-previews.ts +185 -0
  49. package/src/runtime/layout/resolved-formatting-state.ts +30 -26
  50. package/src/runtime/layout/table-render-plan.ts +249 -0
  51. package/src/runtime/numbering-prefix.ts +5 -0
  52. package/src/runtime/paragraph-style-resolver.ts +194 -0
  53. package/src/runtime/render/block-fragment-projection.ts +35 -0
  54. package/src/runtime/render/decoration-resolver.ts +189 -0
  55. package/src/runtime/render/index.ts +57 -0
  56. package/src/runtime/render/pending-op-delta-reader.ts +129 -0
  57. package/src/runtime/render/render-frame-types.ts +317 -0
  58. package/src/runtime/render/render-kernel.ts +759 -0
  59. package/src/runtime/resolved-numbering-geometry.ts +9 -1
  60. package/src/runtime/surface-projection.ts +129 -9
  61. package/src/runtime/table-schema.ts +11 -0
  62. package/src/runtime/view-state.ts +67 -0
  63. package/src/runtime/workflow-markup.ts +1 -5
  64. package/src/runtime/workflow-rail-segments.ts +280 -0
  65. package/src/ui/WordReviewEditor.tsx +368 -19
  66. package/src/ui/editor-command-bag.ts +4 -0
  67. package/src/ui/editor-runtime-boundary.ts +16 -0
  68. package/src/ui/editor-shell-view.tsx +10 -0
  69. package/src/ui/editor-surface-controller.tsx +9 -1
  70. package/src/ui/headless/chrome-registry.ts +310 -15
  71. package/src/ui/headless/scoped-chrome-policy.ts +49 -1
  72. package/src/ui/headless/selection-tool-types.ts +10 -0
  73. package/src/ui-tailwind/chrome/chrome-preset-model.ts +23 -2
  74. package/src/ui-tailwind/chrome/review-queue-bar.tsx +2 -14
  75. package/src/ui-tailwind/chrome/role-action-sets.ts +80 -0
  76. package/src/ui-tailwind/chrome/tw-detach-handle.tsx +147 -0
  77. package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +160 -0
  78. package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +68 -92
  79. package/src/ui-tailwind/chrome/tw-selection-tool-placement.ts +149 -0
  80. package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +11 -0
  81. package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +15 -4
  82. package/src/ui-tailwind/chrome/tw-table-border-picker.tsx +245 -0
  83. package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +356 -140
  84. package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +284 -0
  85. package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +94 -0
  86. package/src/ui-tailwind/chrome-overlay/index.ts +16 -0
  87. package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +96 -0
  88. package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +178 -0
  89. package/src/ui-tailwind/editor-surface/fast-text-edit-lane.ts +4 -0
  90. package/src/ui-tailwind/editor-surface/local-edit-session-state.ts +11 -0
  91. package/src/ui-tailwind/editor-surface/page-slice-util.ts +15 -0
  92. package/src/ui-tailwind/editor-surface/perf-probe.ts +7 -1
  93. package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +40 -4
  94. package/src/ui-tailwind/editor-surface/pm-decorations.ts +22 -12
  95. package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +389 -0
  96. package/src/ui-tailwind/editor-surface/pm-schema.ts +40 -2
  97. package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +144 -62
  98. package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +179 -0
  99. package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +559 -0
  100. package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +224 -75
  101. package/src/ui-tailwind/editor-surface/tw-table-bands.css +61 -0
  102. package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +19 -0
  103. package/src/ui-tailwind/index.ts +29 -0
  104. package/src/ui-tailwind/review/tw-comment-sidebar.tsx +2 -2
  105. package/src/ui-tailwind/review/tw-rail-card.tsx +150 -0
  106. package/src/ui-tailwind/review/tw-review-rail-footer.tsx +52 -0
  107. package/src/ui-tailwind/review/tw-review-rail.tsx +166 -11
  108. package/src/ui-tailwind/review/tw-workflow-tab.tsx +108 -0
  109. package/src/ui-tailwind/theme/editor-theme.css +498 -163
  110. package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +680 -0
  111. package/src/ui-tailwind/toolbar/tw-scope-posture-menu.tsx +182 -0
  112. package/src/ui-tailwind/toolbar/tw-shell-header.tsx +162 -0
  113. package/src/ui-tailwind/toolbar/tw-toolbar.tsx +104 -2
  114. package/src/ui-tailwind/tw-review-workspace.tsx +234 -21
  115. package/src/runtime/collab-review-sync.ts +0 -254
  116. package/src/ui-tailwind/editor-surface/pm-collab-plugins.ts +0 -40
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Read `<w:pPr>` (paragraph properties) into a `CanonicalParagraphFormatting` value.
3
+ *
4
+ * Returns `undefined` when the input is `undefined` or when the pPr is empty (no recognized
5
+ * child produces a field). Delegates the paragraph-mark `<w:rPr>` to `readRunProperties`
6
+ * so every rPr in the project is parsed through one code path.
7
+ */
8
+
9
+ import type {
10
+ CanonicalParagraphFormatting,
11
+ ParagraphBorders,
12
+ ParagraphIndentation,
13
+ ParagraphShading,
14
+ ParagraphSpacing,
15
+ TabStop,
16
+ } from "../../model/canonical-document.ts";
17
+ import { readRunProperties } from "./parse-run-formatting.ts";
18
+ import { findChildOptional, localName, readIntAttr, readIntVal, readOnOff } from "./xml-attr-helpers.ts";
19
+ import type { XmlElementNode } from "./xml-element.ts";
20
+
21
+ function readSpacing(node: XmlElementNode): ParagraphSpacing | undefined {
22
+ const out: ParagraphSpacing = {};
23
+ const before = readIntAttr(node, "w:before");
24
+ const after = readIntAttr(node, "w:after");
25
+ const line = readIntAttr(node, "w:line");
26
+ const rule = node.attributes["w:lineRule"] ?? node.attributes.lineRule;
27
+ if (before !== undefined) out.before = before;
28
+ if (after !== undefined) out.after = after;
29
+ if (line !== undefined) out.line = line;
30
+ if (rule) {
31
+ const n = rule.toLowerCase();
32
+ if (n === "auto" || n === "exact") out.lineRule = n;
33
+ else if (n === "atleast") out.lineRule = "atLeast";
34
+ }
35
+ return Object.keys(out).length > 0 ? out : undefined;
36
+ }
37
+
38
+ function readIndent(node: XmlElementNode): ParagraphIndentation | undefined {
39
+ const out: ParagraphIndentation = {};
40
+ const left = readIntAttr(node, "w:left") ?? readIntAttr(node, "w:start");
41
+ const right = readIntAttr(node, "w:right") ?? readIntAttr(node, "w:end");
42
+ const firstLine = readIntAttr(node, "w:firstLine");
43
+ const hanging = readIntAttr(node, "w:hanging");
44
+ if (left !== undefined) out.left = left;
45
+ if (right !== undefined) out.right = right;
46
+ if (firstLine !== undefined) out.firstLine = firstLine;
47
+ if (hanging !== undefined) out.hanging = hanging;
48
+ return Object.keys(out).length > 0 ? out : undefined;
49
+ }
50
+
51
+ function readTabStops(node: XmlElementNode): TabStop[] | undefined {
52
+ const tabs: TabStop[] = [];
53
+ for (const c of node.children) {
54
+ if (c.type !== "element" || localName(c.name) !== "tab") continue;
55
+ const pos = Number.parseInt(c.attributes["w:pos"] ?? c.attributes.pos ?? "", 10);
56
+ if (!Number.isFinite(pos)) continue;
57
+ const val = (c.attributes["w:val"] ?? c.attributes.val ?? "left").toLowerCase();
58
+ const leader = (c.attributes["w:leader"] ?? c.attributes.leader ?? "none").toLowerCase();
59
+ const align: TabStop["align"] =
60
+ val === "center" || val === "right" || val === "decimal" || val === "bar" || val === "num" || val === "clear"
61
+ ? (val as TabStop["align"])
62
+ : "left";
63
+ const mappedLeader: TabStop["leader"] | undefined =
64
+ leader === "dot" || leader === "hyphen" || leader === "underscore" || leader === "heavy"
65
+ ? (leader as TabStop["leader"])
66
+ : leader === "middledot"
67
+ ? "middleDot"
68
+ : undefined;
69
+ tabs.push({
70
+ position: pos,
71
+ align,
72
+ ...(mappedLeader && mappedLeader !== "none" ? { leader: mappedLeader } : {}),
73
+ });
74
+ }
75
+ return tabs.length > 0 ? tabs : undefined;
76
+ }
77
+
78
+ function readBorders(node: XmlElementNode): ParagraphBorders | undefined {
79
+ const out: ParagraphBorders = {};
80
+ const sides = ["top", "bottom", "left", "right", "between", "bar"] as const;
81
+ for (const side of sides) {
82
+ const child = findChildOptional(node, side);
83
+ if (!child) continue;
84
+ const val = child.attributes["w:val"] ?? child.attributes.val;
85
+ const sz = readIntAttr(child, "w:sz");
86
+ const space = readIntAttr(child, "w:space");
87
+ const color = child.attributes["w:color"] ?? child.attributes.color;
88
+ out[side] = {
89
+ ...(val ? { value: val } : {}),
90
+ ...(sz !== undefined ? { size: sz } : {}),
91
+ ...(space !== undefined ? { space } : {}),
92
+ ...(color ? { color } : {}),
93
+ };
94
+ }
95
+ return Object.keys(out).length > 0 ? out : undefined;
96
+ }
97
+
98
+ function readShading(node: XmlElementNode): ParagraphShading | undefined {
99
+ const val = node.attributes["w:val"] ?? node.attributes.val;
100
+ const fill = node.attributes["w:fill"] ?? node.attributes.fill;
101
+ const color = node.attributes["w:color"] ?? node.attributes.color;
102
+ if (!val && !fill && !color) return undefined;
103
+ return {
104
+ ...(val ? { val } : {}),
105
+ ...(fill ? { fill } : {}),
106
+ ...(color ? { color } : {}),
107
+ };
108
+ }
109
+
110
+ export function readParagraphProperties(
111
+ node: XmlElementNode | undefined,
112
+ ): CanonicalParagraphFormatting | undefined {
113
+ if (!node) return undefined;
114
+
115
+ const out: CanonicalParagraphFormatting = {};
116
+
117
+ const spacingNode = findChildOptional(node, "spacing");
118
+ if (spacingNode) {
119
+ const spacing = readSpacing(spacingNode);
120
+ if (spacing) out.spacing = spacing;
121
+ }
122
+
123
+ const indNode = findChildOptional(node, "ind");
124
+ if (indNode) {
125
+ const ind = readIndent(indNode);
126
+ if (ind) out.indentation = ind;
127
+ }
128
+
129
+ const jcNode = findChildOptional(node, "jc");
130
+ if (jcNode) {
131
+ const raw = jcNode.attributes["w:val"] ?? jcNode.attributes.val;
132
+ if (
133
+ raw === "left" ||
134
+ raw === "center" ||
135
+ raw === "right" ||
136
+ raw === "both" ||
137
+ raw === "distribute" ||
138
+ raw === "start" ||
139
+ raw === "end"
140
+ ) {
141
+ out.alignment = raw;
142
+ }
143
+ }
144
+
145
+ const bordersNode = findChildOptional(node, "pBdr");
146
+ if (bordersNode) {
147
+ const borders = readBorders(bordersNode);
148
+ if (borders) out.borders = borders;
149
+ }
150
+
151
+ const shdNode = findChildOptional(node, "shd");
152
+ if (shdNode) {
153
+ const shading = readShading(shdNode);
154
+ if (shading) out.shading = shading;
155
+ }
156
+
157
+ const tabsNode = findChildOptional(node, "tabs");
158
+ if (tabsNode) {
159
+ const tabs = readTabStops(tabsNode);
160
+ if (tabs) out.tabStops = tabs;
161
+ }
162
+
163
+ const keepNext = readOnOff(findChildOptional(node, "keepNext"));
164
+ if (keepNext !== undefined) out.keepNext = keepNext;
165
+ const keepLines = readOnOff(findChildOptional(node, "keepLines"));
166
+ if (keepLines !== undefined) out.keepLines = keepLines;
167
+ const widow = readOnOff(findChildOptional(node, "widowControl"));
168
+ if (widow !== undefined) out.widowControl = widow;
169
+ const pbb = readOnOff(findChildOptional(node, "pageBreakBefore"));
170
+ if (pbb !== undefined) out.pageBreakBefore = pbb;
171
+ const ctx = readOnOff(findChildOptional(node, "contextualSpacing"));
172
+ if (ctx !== undefined) out.contextualSpacing = ctx;
173
+ const bidi = readOnOff(findChildOptional(node, "bidi"));
174
+ if (bidi !== undefined) out.bidi = bidi;
175
+ const suppressLn = readOnOff(findChildOptional(node, "suppressLineNumbers"));
176
+ if (suppressLn !== undefined) out.suppressLineNumbers = suppressLn;
177
+ const suppressAh = readOnOff(findChildOptional(node, "suppressAutoHyphens"));
178
+ if (suppressAh !== undefined) out.suppressAutoHyphens = suppressAh;
179
+
180
+ const outline = readIntVal(findChildOptional(node, "outlineLvl"));
181
+ if (outline !== undefined) out.outlineLevel = outline;
182
+
183
+ const rPrNode = findChildOptional(node, "rPr");
184
+ const markRpr = readRunProperties(rPrNode);
185
+ if (markRpr) out.paragraphMarkRunProperties = markRpr;
186
+
187
+ return Object.keys(out).length > 0 ? out : undefined;
188
+ }
@@ -0,0 +1,129 @@
1
+ import type { CanonicalRunFormatting } from "../../model/canonical-document.ts";
2
+ import { findChildOptional, readIntVal, readOnOff, readStringAttr } from "./xml-attr-helpers.ts";
3
+ import type { XmlElementNode } from "./xml-element.ts";
4
+
5
+ /**
6
+ * Read `<w:rPr>` (run properties) into a `CanonicalRunFormatting` value.
7
+ *
8
+ * Returns `undefined` when the input is `undefined` or when the rPr is empty
9
+ * (i.e., no recognized child produces a field). `colorHex` may carry the
10
+ * sentinel `"auto"`; `fontFamily` is the alias of the first-available
11
+ * `fontFamily{Ascii,HAnsi,EastAsia,Cs}`.
12
+ *
13
+ * Caller-side: route every `<w:rPr>` from styles.xml, numbering.xml, and
14
+ * the paragraph mark in document.xml through this helper so the cascade
15
+ * sees the same shape.
16
+ */
17
+ export function readRunProperties(
18
+ node: XmlElementNode | undefined,
19
+ ): CanonicalRunFormatting | undefined {
20
+ if (!node) return undefined;
21
+
22
+ const rPr: CanonicalRunFormatting = {};
23
+
24
+ const bold = readOnOff(findChildOptional(node, "b"));
25
+ if (bold !== undefined) rPr.bold = bold;
26
+
27
+ const italic = readOnOff(findChildOptional(node, "i"));
28
+ if (italic !== undefined) rPr.italic = italic;
29
+
30
+ const strike = readOnOff(findChildOptional(node, "strike"));
31
+ if (strike !== undefined) rPr.strikethrough = strike;
32
+
33
+ const dstrike = readOnOff(findChildOptional(node, "dstrike"));
34
+ if (dstrike !== undefined) rPr.doubleStrikethrough = dstrike;
35
+
36
+ const vanish = readOnOff(findChildOptional(node, "vanish"));
37
+ if (vanish !== undefined) rPr.vanish = vanish;
38
+
39
+ const allCaps = readOnOff(findChildOptional(node, "caps"));
40
+ if (allCaps !== undefined) rPr.allCaps = allCaps;
41
+
42
+ const smallCaps = readOnOff(findChildOptional(node, "smallCaps"));
43
+ if (smallCaps !== undefined) rPr.smallCaps = smallCaps;
44
+
45
+ const u = findChildOptional(node, "u");
46
+ if (u) {
47
+ const val =
48
+ u.attributes["w:val"] ?? u.attributes["val"] ?? "single";
49
+ if (val === "none") {
50
+ rPr.underline = "none";
51
+ } else if (
52
+ val === "single" ||
53
+ val === "double" ||
54
+ val === "thick" ||
55
+ val === "dotted" ||
56
+ val === "dash" ||
57
+ val === "wave"
58
+ ) {
59
+ rPr.underline = val;
60
+ } else {
61
+ // Unknown underline type — coerce to "single"
62
+ rPr.underline = "single";
63
+ }
64
+ }
65
+
66
+ const vertAlign = findChildOptional(node, "vertAlign");
67
+ if (vertAlign) {
68
+ const val =
69
+ vertAlign.attributes["w:val"] ?? vertAlign.attributes["val"];
70
+ if (
71
+ val === "superscript" ||
72
+ val === "subscript" ||
73
+ val === "baseline"
74
+ ) {
75
+ rPr.verticalAlign = val;
76
+ }
77
+ }
78
+
79
+ const rFonts = findChildOptional(node, "rFonts");
80
+ if (rFonts) {
81
+ const ascii = rFonts.attributes["w:ascii"] ?? rFonts.attributes.ascii;
82
+ const hAnsi = rFonts.attributes["w:hAnsi"] ?? rFonts.attributes.hAnsi;
83
+ const eastAsia = rFonts.attributes["w:eastAsia"] ?? rFonts.attributes.eastAsia;
84
+ const cs = rFonts.attributes["w:cs"] ?? rFonts.attributes.cs;
85
+ if (ascii) rPr.fontFamilyAscii = ascii;
86
+ if (hAnsi) rPr.fontFamilyHAnsi = hAnsi;
87
+ if (eastAsia) rPr.fontFamilyEastAsia = eastAsia;
88
+ if (cs) rPr.fontFamilyCs = cs;
89
+ const primary = ascii ?? hAnsi ?? eastAsia ?? cs;
90
+ if (primary) rPr.fontFamily = primary;
91
+ }
92
+
93
+ const sz = readIntVal(findChildOptional(node, "sz"));
94
+ if (sz !== undefined) rPr.fontSizeHalfPoints = sz;
95
+
96
+ const szCs = readIntVal(findChildOptional(node, "szCs"));
97
+ if (szCs !== undefined) rPr.fontSizeCsHalfPoints = szCs;
98
+
99
+ const color = findChildOptional(node, "color");
100
+ if (color) {
101
+ const val = color.attributes["w:val"] ?? color.attributes["val"];
102
+ const theme =
103
+ color.attributes["w:themeColor"] ?? color.attributes["themeColor"];
104
+ if (val) rPr.colorHex = val;
105
+ if (theme) rPr.colorThemeSlot = theme;
106
+ }
107
+
108
+ const highlight = findChildOptional(node, "highlight");
109
+ if (highlight) {
110
+ const val =
111
+ highlight.attributes["w:val"] ?? highlight.attributes["val"];
112
+ if (val) rPr.highlight = val;
113
+ }
114
+
115
+ const spacing = readIntVal(findChildOptional(node, "spacing"));
116
+ if (spacing !== undefined) rPr.characterSpacingTwips = spacing;
117
+
118
+ const rStyleNode = findChildOptional(node, "rStyle");
119
+ const rStyle = rStyleNode ? readStringAttr(rStyleNode, "w:val") : undefined;
120
+ if (rStyle) rPr.characterStyleId = rStyle;
121
+
122
+ const lang = findChildOptional(node, "lang");
123
+ if (lang) {
124
+ const val = lang.attributes["w:val"] ?? lang.attributes["val"];
125
+ if (val) rPr.languageCode = val;
126
+ }
127
+
128
+ return Object.keys(rPr).length > 0 ? rPr : undefined;
129
+ }
@@ -10,6 +10,7 @@
10
10
  import type {
11
11
  CellShading,
12
12
  CharacterStyleDefinition,
13
+ DocumentDefaults,
13
14
  LatentStyleDefinition,
14
15
  ParagraphStyleDefinition,
15
16
  StylesCatalog,
@@ -37,6 +38,8 @@ import {
37
38
  readTableWidth,
38
39
  } from "./parse-tables.ts";
39
40
  import { toCanonicalNumberingInstanceId } from "./parse-numbering.ts";
41
+ import { readRunProperties } from "./parse-run-formatting.ts";
42
+ import { readParagraphProperties } from "./parse-paragraph-formatting.ts";
40
43
 
41
44
  // ---------------------------------------------------------------------------
42
45
  // Inline XML node types (same pattern as parse-numbering.ts)
@@ -116,11 +119,28 @@ export function parseStylesXml(xml: string): ParseStylesResult {
116
119
  const characters: Record<string, CharacterStyleDefinition> = {};
117
120
  const tables: Record<string, TableStyleDefinition> = {};
118
121
  const latentStyles: Record<string, LatentStyleDefinition> = {};
122
+ let docDefaults: DocumentDefaults | undefined;
119
123
 
120
124
  for (const child of stylesElement.children) {
121
125
  if (child.type !== "element") continue;
122
126
  const local = localName(child.name);
123
127
 
128
+ if (local === "docDefaults") {
129
+ const pPrDefault = findChildElementOptional(child, "pPrDefault");
130
+ const rPrDefault = findChildElementOptional(child, "rPrDefault");
131
+ const pPrNode = pPrDefault ? findChildElementOptional(pPrDefault, "pPr") : undefined;
132
+ const rPrNode = rPrDefault ? findChildElementOptional(rPrDefault, "rPr") : undefined;
133
+ const paragraph = readParagraphProperties(pPrNode);
134
+ const run = readRunProperties(rPrNode);
135
+ if (paragraph || run) {
136
+ docDefaults = {
137
+ ...(paragraph ? { paragraph } : {}),
138
+ ...(run ? { run } : {}),
139
+ };
140
+ }
141
+ continue;
142
+ }
143
+
124
144
  if (local === "style") {
125
145
  const styleType = child.attributes["w:type"] ?? child.attributes.type;
126
146
  const styleId = child.attributes["w:styleId"] ?? child.attributes.styleId;
@@ -135,6 +155,10 @@ export function parseStylesXml(xml: string): ParseStylesResult {
135
155
  const nextStyle = readLinkedStyleId(child, "next");
136
156
  const outlineLevel = readParagraphStyleOutlineLevel(child);
137
157
  const numbering = readParagraphStyleNumbering(child);
158
+ const pPrNode = findChildElementOptional(child, "pPr");
159
+ const rPrNode = findChildElementOptional(child, "rPr");
160
+ const paragraphProperties = readParagraphProperties(pPrNode);
161
+ const runProperties = readRunProperties(rPrNode);
138
162
  paragraphs[styleId] = {
139
163
  styleId,
140
164
  displayName,
@@ -144,16 +168,21 @@ export function parseStylesXml(xml: string): ParseStylesResult {
144
168
  ...(nextStyle ? { nextStyle } : {}),
145
169
  ...(outlineLevel !== undefined ? { outlineLevel } : {}),
146
170
  ...(numbering ? { numbering } : {}),
171
+ ...(paragraphProperties ? { paragraphProperties } : {}),
172
+ ...(runProperties ? { runProperties } : {}),
147
173
  };
148
174
  break;
149
175
  }
150
176
  case "character": {
177
+ const rPrNode = findChildElementOptional(child, "rPr");
178
+ const runProperties = readRunProperties(rPrNode);
151
179
  characters[styleId] = {
152
180
  styleId,
153
181
  displayName,
154
182
  kind: "character",
155
183
  isDefault,
156
184
  ...(basedOn ? { basedOn } : {}),
185
+ ...(runProperties ? { runProperties } : {}),
157
186
  };
158
187
  break;
159
188
  }
@@ -194,6 +223,8 @@ export function parseStylesXml(xml: string): ParseStylesResult {
194
223
  characters,
195
224
  tables,
196
225
  ...(hasLatent ? { latentStyles } : {}),
226
+ fromPackage: true,
227
+ ...(docDefaults ? { docDefaults } : {}),
197
228
  },
198
229
  fromPackage: true,
199
230
  diagnostics,