@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.
- package/package.json +41 -31
- package/src/api/public-types.ts +496 -1
- package/src/core/commands/section-layout-commands.ts +58 -0
- package/src/core/commands/table-grid.ts +431 -0
- package/src/core/commands/table-structure-commands.ts +845 -56
- package/src/core/commands/text-commands.ts +122 -2
- package/src/io/docx-session.ts +1 -0
- package/src/io/export/serialize-main-document.ts +2 -11
- package/src/io/export/serialize-numbering.ts +43 -10
- package/src/io/export/serialize-paragraph-formatting.ts +152 -0
- package/src/io/export/serialize-run-formatting.ts +90 -0
- package/src/io/export/serialize-styles.ts +212 -0
- package/src/io/export/serialize-tables.ts +74 -0
- package/src/io/export/table-properties-xml.ts +139 -4
- package/src/io/normalize/normalize-text.ts +15 -0
- package/src/io/ooxml/parse-fields.ts +10 -3
- package/src/io/ooxml/parse-footnotes.ts +60 -0
- package/src/io/ooxml/parse-headers-footers.ts +60 -0
- package/src/io/ooxml/parse-main-document.ts +137 -0
- package/src/io/ooxml/parse-numbering.ts +41 -1
- package/src/io/ooxml/parse-paragraph-formatting.ts +188 -0
- package/src/io/ooxml/parse-run-formatting.ts +129 -0
- package/src/io/ooxml/parse-styles.ts +31 -0
- package/src/io/ooxml/parse-tables.ts +249 -0
- package/src/io/ooxml/xml-attr-helpers.ts +60 -0
- package/src/io/ooxml/xml-element.ts +19 -0
- package/src/model/canonical-document.ts +117 -3
- package/src/runtime/collab/event-types.ts +165 -0
- package/src/runtime/collab/index.ts +22 -0
- package/src/runtime/collab/remote-cursor-awareness.ts +93 -0
- package/src/runtime/collab/runtime-collab-sync.ts +273 -0
- package/src/runtime/document-layout.ts +4 -2
- package/src/runtime/document-navigation.ts +1 -1
- package/src/runtime/document-runtime.ts +248 -18
- package/src/runtime/layout/default-page-format.ts +96 -0
- package/src/runtime/layout/index.ts +47 -0
- package/src/runtime/layout/inert-layout-facet.ts +16 -0
- package/src/runtime/layout/layout-engine-instance.ts +100 -23
- package/src/runtime/layout/layout-invalidation.ts +14 -5
- package/src/runtime/layout/margin-preset-catalog.ts +178 -0
- package/src/runtime/layout/page-format-catalog.ts +233 -0
- package/src/runtime/layout/page-graph.ts +55 -0
- package/src/runtime/layout/paginate-paragraph-lines.ts +128 -0
- package/src/runtime/layout/paginated-layout-engine.ts +484 -37
- package/src/runtime/layout/project-block-fragments.ts +225 -0
- package/src/runtime/layout/public-facet.ts +748 -16
- package/src/runtime/layout/resolve-page-fields.ts +70 -0
- package/src/runtime/layout/resolve-page-previews.ts +185 -0
- package/src/runtime/layout/resolved-formatting-state.ts +30 -26
- package/src/runtime/layout/table-render-plan.ts +249 -0
- package/src/runtime/numbering-prefix.ts +5 -0
- package/src/runtime/paragraph-style-resolver.ts +194 -0
- package/src/runtime/render/block-fragment-projection.ts +35 -0
- package/src/runtime/render/decoration-resolver.ts +189 -0
- package/src/runtime/render/index.ts +57 -0
- package/src/runtime/render/pending-op-delta-reader.ts +129 -0
- package/src/runtime/render/render-frame-types.ts +317 -0
- package/src/runtime/render/render-kernel.ts +759 -0
- package/src/runtime/resolved-numbering-geometry.ts +9 -1
- package/src/runtime/surface-projection.ts +129 -9
- package/src/runtime/table-schema.ts +11 -0
- package/src/runtime/view-state.ts +67 -0
- package/src/runtime/workflow-markup.ts +1 -5
- package/src/runtime/workflow-rail-segments.ts +280 -0
- package/src/ui/WordReviewEditor.tsx +368 -19
- package/src/ui/editor-command-bag.ts +4 -0
- package/src/ui/editor-runtime-boundary.ts +16 -0
- package/src/ui/editor-shell-view.tsx +10 -0
- package/src/ui/editor-surface-controller.tsx +9 -1
- package/src/ui/headless/chrome-registry.ts +310 -15
- package/src/ui/headless/scoped-chrome-policy.ts +49 -1
- package/src/ui/headless/selection-tool-types.ts +10 -0
- package/src/ui-tailwind/chrome/chrome-preset-model.ts +23 -2
- package/src/ui-tailwind/chrome/review-queue-bar.tsx +2 -14
- package/src/ui-tailwind/chrome/role-action-sets.ts +80 -0
- package/src/ui-tailwind/chrome/tw-detach-handle.tsx +147 -0
- package/src/ui-tailwind/chrome/tw-selection-anchor-resolver.ts +160 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-host.tsx +68 -92
- package/src/ui-tailwind/chrome/tw-selection-tool-placement.ts +149 -0
- package/src/ui-tailwind/chrome/tw-selection-tool-structure.tsx +11 -0
- package/src/ui-tailwind/chrome/tw-selection-toolbar.tsx +15 -4
- package/src/ui-tailwind/chrome/tw-table-border-picker.tsx +245 -0
- package/src/ui-tailwind/chrome/tw-table-context-toolbar.tsx +356 -140
- package/src/ui-tailwind/chrome/tw-table-grip-layer.tsx +284 -0
- package/src/ui-tailwind/chrome-overlay/chrome-overlay-projector.ts +94 -0
- package/src/ui-tailwind/chrome-overlay/index.ts +16 -0
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +96 -0
- package/src/ui-tailwind/chrome-overlay/tw-scope-rail-layer.tsx +178 -0
- package/src/ui-tailwind/editor-surface/fast-text-edit-lane.ts +4 -0
- package/src/ui-tailwind/editor-surface/local-edit-session-state.ts +11 -0
- package/src/ui-tailwind/editor-surface/page-slice-util.ts +15 -0
- package/src/ui-tailwind/editor-surface/perf-probe.ts +7 -1
- package/src/ui-tailwind/editor-surface/pm-command-bridge.ts +40 -4
- package/src/ui-tailwind/editor-surface/pm-decorations.ts +22 -12
- package/src/ui-tailwind/editor-surface/pm-page-break-decorations.ts +389 -0
- package/src/ui-tailwind/editor-surface/pm-schema.ts +40 -2
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +144 -62
- package/src/ui-tailwind/editor-surface/remote-cursor-plugin.ts +179 -0
- package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +559 -0
- package/src/ui-tailwind/editor-surface/tw-prosemirror-surface.tsx +224 -75
- package/src/ui-tailwind/editor-surface/tw-table-bands.css +61 -0
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +19 -0
- package/src/ui-tailwind/index.ts +29 -0
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +2 -2
- package/src/ui-tailwind/review/tw-rail-card.tsx +150 -0
- package/src/ui-tailwind/review/tw-review-rail-footer.tsx +52 -0
- package/src/ui-tailwind/review/tw-review-rail.tsx +166 -11
- package/src/ui-tailwind/review/tw-workflow-tab.tsx +108 -0
- package/src/ui-tailwind/theme/editor-theme.css +498 -163
- package/src/ui-tailwind/toolbar/tw-role-action-region.tsx +680 -0
- package/src/ui-tailwind/toolbar/tw-scope-posture-menu.tsx +182 -0
- package/src/ui-tailwind/toolbar/tw-shell-header.tsx +162 -0
- package/src/ui-tailwind/toolbar/tw-toolbar.tsx +104 -2
- package/src/ui-tailwind/tw-review-workspace.tsx +234 -21
- package/src/runtime/collab-review-sync.ts +0 -254
- 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,
|