@beyondwork/docx-react-component 1.0.58 → 1.0.60
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/README.md +2 -2
- package/package.json +2 -1
- package/src/api/awareness-identity-types.ts +4 -2
- package/src/api/comment-negotiation-types.ts +4 -1
- package/src/api/external-custody-types.ts +16 -0
- package/src/api/internal/build-ref-projections.ts +108 -0
- package/src/api/package-version.ts +1 -1
- package/src/api/participants-types.ts +11 -1
- package/src/api/public-types.ts +980 -10
- package/src/api/scope-metadata-resolver-types.ts +6 -0
- package/src/compare/diff-engine.ts +3 -0
- package/src/core/commands/formatting-commands.ts +1 -0
- package/src/core/commands/index.ts +225 -16
- package/src/core/commands/legacy-form-field-commands.ts +181 -0
- package/src/core/commands/table-structure-commands.ts +149 -31
- package/src/core/selection/mapping.ts +20 -0
- package/src/core/state/editor-state.ts +4 -1
- package/src/index.ts +28 -0
- package/src/io/docx-session.ts +22 -3
- package/src/io/export/export-session.ts +11 -7
- package/src/io/export/ooxml-namespaces.ts +47 -0
- package/src/io/export/reattach-preserved-parts.ts +4 -16
- package/src/io/export/serialize-comments.ts +3 -131
- package/src/io/export/serialize-ffdata.ts +89 -0
- package/src/io/export/serialize-headers-footers.ts +5 -0
- package/src/io/export/serialize-main-document.ts +224 -34
- package/src/io/export/serialize-numbering.ts +22 -2
- package/src/io/export/serialize-revisions.ts +99 -0
- package/src/io/export/serialize-tables.ts +9 -0
- package/src/io/export/split-review-boundaries.ts +1 -0
- package/src/io/export/table-properties-xml.ts +14 -0
- package/src/io/load-scheduler.ts +70 -28
- package/src/io/normalize/normalize-text.ts +13 -0
- package/src/io/ooxml/_mini-xml.ts +198 -0
- package/src/io/ooxml/canonicalize-payload.ts +1 -4
- package/src/io/ooxml/chart/chart-style-table.ts +4 -3
- package/src/io/ooxml/chart/parse-chart-space.ts +2 -4
- package/src/io/ooxml/chart/parse-series.ts +2 -1
- package/src/io/ooxml/chart/resolve-color.ts +2 -2
- package/src/io/ooxml/chart/types.ts +6 -434
- package/src/io/ooxml/comment-presentation-payload.ts +6 -5
- package/src/io/ooxml/highlight-colors.ts +8 -5
- package/src/io/ooxml/parse-anchor.ts +68 -53
- package/src/io/ooxml/parse-comments.ts +14 -142
- package/src/io/ooxml/parse-complex-content.ts +3 -106
- package/src/io/ooxml/parse-drawing.ts +100 -195
- package/src/io/ooxml/parse-ffdata.ts +93 -0
- package/src/io/ooxml/parse-fields.ts +7 -146
- package/src/io/ooxml/parse-fill.ts +88 -8
- package/src/io/ooxml/parse-font-table.ts +5 -105
- package/src/io/ooxml/parse-footnotes.ts +28 -152
- package/src/io/ooxml/parse-headers-footers.ts +106 -212
- package/src/io/ooxml/parse-inline-media.ts +3 -200
- package/src/io/ooxml/parse-main-document.ts +180 -217
- package/src/io/ooxml/parse-numbering.ts +154 -335
- package/src/io/ooxml/parse-object.ts +147 -0
- package/src/io/ooxml/parse-ole-relationship.ts +82 -0
- package/src/io/ooxml/parse-paragraph-formatting.ts +7 -10
- package/src/io/ooxml/parse-picture-sdt.ts +85 -0
- package/src/io/ooxml/parse-picture.ts +72 -42
- package/src/io/ooxml/parse-revisions.ts +285 -51
- package/src/io/ooxml/parse-settings.ts +6 -99
- package/src/io/ooxml/parse-shapes.ts +25 -140
- package/src/io/ooxml/parse-styles.ts +3 -218
- package/src/io/ooxml/parse-tables.ts +76 -256
- package/src/io/ooxml/parse-theme.ts +1 -4
- package/src/io/ooxml/property-grab-bag.ts +5 -47
- package/src/io/ooxml/workflow-payload.ts +6 -1
- package/src/io/ooxml/xml-element-serialize.ts +32 -0
- package/src/io/ooxml/xml-parser.ts +183 -0
- package/src/legal/bookmarks.ts +1 -1
- package/src/legal/cross-references.ts +1 -1
- package/src/legal/defined-terms.ts +1 -1
- package/src/legal/{_document-root.ts → document-root.ts} +8 -0
- package/src/legal/signature-blocks.ts +1 -1
- package/src/model/canonical-document.ts +159 -6
- package/src/model/chart-types.ts +439 -0
- package/src/model/snapshot.ts +5 -1
- package/src/review/store/comment-remapping.ts +24 -11
- package/src/review/store/revision-actions.ts +482 -2
- package/src/review/store/revision-store.ts +15 -0
- package/src/review/store/revision-types.ts +76 -0
- package/src/runtime/collab/remote-cursor-awareness.ts +24 -0
- package/src/runtime/collab/runtime-collab-sync.ts +33 -0
- package/src/runtime/diagnostics/build-diagnostic.ts +153 -0
- package/src/runtime/diagnostics/code-metadata-table.ts +230 -0
- package/src/runtime/document-runtime.ts +821 -54
- package/src/runtime/document-search.ts +115 -0
- package/src/runtime/edit-ops/index.ts +18 -2
- package/src/runtime/footnote-resolver.ts +130 -0
- package/src/runtime/layout/layout-engine-instance.ts +31 -4
- package/src/runtime/layout/layout-engine-version.ts +37 -1
- package/src/runtime/layout/page-graph.ts +14 -1
- package/src/runtime/layout/resolved-formatting-state.ts +21 -0
- package/src/runtime/numbering-prefix.ts +17 -0
- package/src/runtime/query-scopes.ts +108 -10
- package/src/runtime/resolved-numbering-geometry.ts +37 -6
- package/src/runtime/revision-runtime.ts +27 -1
- package/src/runtime/selection/post-edit-validator.ts +60 -6
- package/src/runtime/structure-ops/index.ts +20 -4
- package/src/runtime/surface-projection.ts +290 -21
- package/src/runtime/table-schema.ts +6 -0
- package/src/runtime/theme-color-resolver.ts +2 -2
- package/src/runtime/units.ts +9 -0
- package/src/runtime/workflow-rail-segments.ts +4 -0
- package/src/ui/WordReviewEditor.tsx +187 -43
- package/src/ui/editor-runtime-boundary.ts +10 -0
- package/src/ui/editor-shell-view.tsx +4 -1
- package/src/ui/headless/chrome-registry.ts +53 -0
- package/src/ui/headless/selection-tool-resolver.ts +11 -1
- package/src/ui-tailwind/chrome/chrome-preset-model.ts +13 -0
- package/src/ui-tailwind/chrome/tw-command-palette-mount.tsx +96 -0
- package/src/ui-tailwind/chrome/tw-context-menu.tsx +2 -1
- package/src/ui-tailwind/chrome/tw-image-context-toolbar.tsx +5 -4
- package/src/ui-tailwind/chrome/tw-mode-dock.tsx +6 -2
- package/src/ui-tailwind/chrome/use-container-breakpoint.ts +111 -0
- package/src/ui-tailwind/chrome-overlay/tw-chrome-overlay.tsx +0 -9
- package/src/ui-tailwind/chrome-overlay/tw-object-selection-overlay.tsx +1 -0
- package/src/ui-tailwind/chrome-overlay/tw-page-stack-overlay-layer.tsx +6 -7
- package/src/ui-tailwind/editor-surface/pm-schema.ts +87 -25
- package/src/ui-tailwind/editor-surface/pm-state-from-snapshot.ts +9 -0
- package/src/ui-tailwind/editor-surface/shape-renderer.ts +76 -14
- package/src/ui-tailwind/editor-surface/tw-page-block-view.helpers.ts +18 -1
- package/src/ui-tailwind/editor-surface/tw-page-block-view.tsx +2 -0
- package/src/ui-tailwind/editor-surface/tw-table-node-view.tsx +18 -2
- package/src/ui-tailwind/index.ts +9 -0
- package/src/ui-tailwind/page-chrome-model.ts +77 -5
- package/src/ui-tailwind/page-stack/tw-page-stack-chrome-layer.tsx +56 -1
- package/src/ui-tailwind/page-stack/tw-region-block-renderer.tsx +2 -0
- package/src/ui-tailwind/review/tw-comment-sidebar.tsx +116 -113
- package/src/ui-tailwind/review/tw-review-rail-footer.tsx +2 -2
- package/src/ui-tailwind/theme/tokens.ts +14 -0
- package/src/ui-tailwind/toolbar/tw-shell-header.tsx +5 -0
- package/src/ui-tailwind/tw-review-workspace.tsx +29 -87
- package/src/validation/diagnostics.ts +1 -0
|
@@ -1,439 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Chart data-model types (Stage 1).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* `
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* coverage.
|
|
10
|
-
*
|
|
11
|
-
* Stage 2 will add the theme/colors/style cascade that turns `ColorRef`
|
|
12
|
-
* values into concrete sRGB strings. Until then, colors are declared as
|
|
13
|
-
* references; consumers of Stage 1 models should treat color resolution as
|
|
14
|
-
* "not yet available."
|
|
15
|
-
*
|
|
16
|
-
* See docs/plans/lane-5-charts.md §3 Task 1.1 for the full specification.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
|
-
// Top-level union
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
|
|
23
|
-
export type ChartModel =
|
|
24
|
-
| BarChartModel
|
|
25
|
-
| LineChartModel
|
|
26
|
-
| PieChartModel
|
|
27
|
-
| AreaChartModel
|
|
28
|
-
| ScatterChartModel
|
|
29
|
-
| BubbleChartModel
|
|
30
|
-
| ComboChartModel
|
|
31
|
-
| UnsupportedChartModel;
|
|
32
|
-
|
|
33
|
-
export interface ChartCommon {
|
|
34
|
-
/** Chart title, if present. */
|
|
35
|
-
title?: Title;
|
|
36
|
-
/** Legend configuration; absent if the chart has no legend. */
|
|
37
|
-
legend?: Legend;
|
|
38
|
-
/** Whether to plot only visible cells (c:plotVisOnly). */
|
|
39
|
-
plotVisOnly: boolean;
|
|
40
|
-
/** How to render blank/null values (c:dispBlanksAs). */
|
|
41
|
-
dispBlanksAs: "gap" | "zero" | "span";
|
|
42
|
-
/** Legacy chart style id (c:style val, 1–48), if present. */
|
|
43
|
-
styleId?: number;
|
|
44
|
-
/** Theme color scheme slot names available to this chart (accent1..6 etc.). */
|
|
45
|
-
themeColorScheme?: string[];
|
|
46
|
-
/**
|
|
47
|
-
* The raw chart-space XML that produced this model. Preserved so the
|
|
48
|
-
* export path can re-emit the original drawing without depending on the
|
|
49
|
-
* renderer's coverage of a given chart family.
|
|
50
|
-
*/
|
|
51
|
-
rawXml: string;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Category-like axis binding for bar/line/area charts. Date axes are a
|
|
56
|
-
* legal substitute for a category axis at the XML level (c:dateAx replaces
|
|
57
|
-
* c:catAx) and we preserve the kind here so the renderer can format
|
|
58
|
-
* category labels as dates when the source authored them that way.
|
|
59
|
-
*/
|
|
60
|
-
export type CategoryLikeAxis = CategoryAxis | DateAxis;
|
|
61
|
-
|
|
62
|
-
export interface BarChartModel extends ChartCommon {
|
|
63
|
-
kind: "bar";
|
|
64
|
-
/** "bar" = horizontal; "column" = vertical. */
|
|
65
|
-
direction: "bar" | "column";
|
|
66
|
-
grouping: "clustered" | "stacked" | "percentStacked" | "standard";
|
|
67
|
-
/** Gap between categories in percent of bar width (c:gapWidth). */
|
|
68
|
-
gapWidth: number;
|
|
69
|
-
/** Overlap within a category in percent, -100..100 (c:overlap). */
|
|
70
|
-
overlap: number;
|
|
71
|
-
series: Series[];
|
|
72
|
-
categoryAxis: CategoryLikeAxis;
|
|
73
|
-
valueAxis: ValueAxis;
|
|
74
|
-
/** Present when any series/group targeted the secondary axis. */
|
|
75
|
-
secondaryValueAxis?: ValueAxis;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export interface LineChartModel extends ChartCommon {
|
|
79
|
-
kind: "line";
|
|
80
|
-
grouping: "standard" | "stacked" | "percentStacked";
|
|
81
|
-
/** Global smooth flag; per-series values can override. */
|
|
82
|
-
smooth: boolean;
|
|
83
|
-
/** Global marker flag; per-series values can override. */
|
|
84
|
-
marker: boolean;
|
|
85
|
-
series: LineSeries[];
|
|
86
|
-
categoryAxis: CategoryLikeAxis;
|
|
87
|
-
valueAxis: ValueAxis;
|
|
88
|
-
secondaryValueAxis?: ValueAxis;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export interface PieChartModel extends ChartCommon {
|
|
92
|
-
kind: "pie";
|
|
93
|
-
doughnut: boolean;
|
|
94
|
-
/** Doughnut hole size in percent, typical 10–75 (c:holeSize). */
|
|
95
|
-
holeSizePercent?: number;
|
|
96
|
-
/** Clockwise degrees from 12 o'clock, 0–360 (c:firstSliceAngle / 60000). */
|
|
97
|
-
firstSliceAngle: number;
|
|
98
|
-
varyColors: boolean;
|
|
99
|
-
/** Almost always one series; pie-of-pie is length 2 (deferred). */
|
|
100
|
-
series: PieSeries[];
|
|
101
|
-
/** Category labels (from the first series' c:cat). */
|
|
102
|
-
categoryLabels: string[];
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export interface AreaChartModel extends ChartCommon {
|
|
106
|
-
kind: "area";
|
|
107
|
-
grouping: "standard" | "stacked" | "percentStacked";
|
|
108
|
-
series: Series[];
|
|
109
|
-
categoryAxis: CategoryLikeAxis;
|
|
110
|
-
valueAxis: ValueAxis;
|
|
111
|
-
secondaryValueAxis?: ValueAxis;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export interface ScatterChartModel extends ChartCommon {
|
|
115
|
-
kind: "scatter";
|
|
116
|
-
style: "line" | "lineMarker" | "marker" | "smooth" | "smoothMarker";
|
|
117
|
-
series: ScatterSeries[];
|
|
118
|
-
/** Scatter uses a numeric x-axis, not a category axis. */
|
|
119
|
-
xAxis: ValueAxis;
|
|
120
|
-
yAxis: ValueAxis;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export interface BubbleChartModel extends ChartCommon {
|
|
124
|
-
kind: "bubble";
|
|
125
|
-
bubble3D: boolean;
|
|
126
|
-
series: BubbleSeries[];
|
|
127
|
-
xAxis: ValueAxis;
|
|
128
|
-
yAxis: ValueAxis;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export interface ComboChartModel extends ChartCommon {
|
|
132
|
-
kind: "combo";
|
|
133
|
-
/**
|
|
134
|
-
* Each type-group (bar/line/area) contributes its own series list. Axes
|
|
135
|
-
* may be shared or split into primary/secondary pairs.
|
|
136
|
-
*/
|
|
137
|
-
groups: Array<BarChartModel | LineChartModel | AreaChartModel>;
|
|
138
|
-
/** True if any group targeted a secondary value axis. */
|
|
139
|
-
hasSecondaryAxis: boolean;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export interface UnsupportedChartModel extends ChartCommon {
|
|
143
|
-
kind: "unsupported";
|
|
144
|
-
reason: UnsupportedReason;
|
|
145
|
-
/** Human-readable detail (e.g. "Chart family lineChart not yet implemented"). */
|
|
146
|
-
detail: string;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Discriminator values for `UnsupportedChartModel.reason`.
|
|
151
|
-
*
|
|
152
|
-
* - `not-yet-implemented`: the parser recognises the chart family but a
|
|
153
|
-
* subsequent slice is responsible for implementing it (line/pie/area/
|
|
154
|
-
* scatter/bubble/combo in this slice).
|
|
155
|
-
* - `pivot`/`stock`/`surface`/…: families that are intentionally deferred
|
|
156
|
-
* indefinitely per the plan's non-goals (rare in legal/finance corpora,
|
|
157
|
-
* disproportionate renderer cost).
|
|
158
|
-
* - `no-plot-area`: the chart XML had no c:plotArea child.
|
|
159
|
-
* - `parse-error`: unexpected structure or exception during parse.
|
|
4
|
+
* Re-export shim. The canonical chart type definitions live in
|
|
5
|
+
* `src/model/chart-types.ts` — that location avoids the former
|
|
6
|
+
* `model → io` backward dependency (see `docs/plans/architecture-lane.md`
|
|
7
|
+
* §F1). io/ooxml/chart and ui-tailwind/chart consumers can continue
|
|
8
|
+
* importing from this path unchanged.
|
|
160
9
|
*/
|
|
161
|
-
export type UnsupportedReason =
|
|
162
|
-
| "not-yet-implemented"
|
|
163
|
-
| "pivot"
|
|
164
|
-
| "stock"
|
|
165
|
-
| "surface"
|
|
166
|
-
| "treemap"
|
|
167
|
-
| "sunburst"
|
|
168
|
-
| "histogram"
|
|
169
|
-
| "waterfall"
|
|
170
|
-
| "funnel"
|
|
171
|
-
| "map"
|
|
172
|
-
| "no-plot-area"
|
|
173
|
-
| "parse-error";
|
|
174
|
-
|
|
175
|
-
// ---------------------------------------------------------------------------
|
|
176
|
-
// Series
|
|
177
|
-
// ---------------------------------------------------------------------------
|
|
178
|
-
|
|
179
|
-
export interface SeriesBase {
|
|
180
|
-
/** c:idx — render order. */
|
|
181
|
-
idx: number;
|
|
182
|
-
/** c:order — data order. */
|
|
183
|
-
order: number;
|
|
184
|
-
/** Series display name (c:tx/c:strRef/c:strCache or c:v). */
|
|
185
|
-
name?: string;
|
|
186
|
-
/** Explicit fill/stroke overrides from c:spPr. */
|
|
187
|
-
spPr?: ShapeProperties;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export interface Series extends SeriesBase {
|
|
191
|
-
/** Category labels; string-form even when c:numRef was used. */
|
|
192
|
-
categories: string[];
|
|
193
|
-
/** Numeric values; `null` for blank/missing points (sparse cache). */
|
|
194
|
-
values: Array<number | null>;
|
|
195
|
-
dataLabels?: DataLabelsSpec;
|
|
196
|
-
/** Per-data-point overrides (c:dPt). */
|
|
197
|
-
dataPoints?: DataPointOverride[];
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export interface LineSeries extends Series {
|
|
201
|
-
/** Per-series smooth override. */
|
|
202
|
-
smooth?: boolean;
|
|
203
|
-
marker?: MarkerSpec;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export interface PieSeries extends SeriesBase {
|
|
207
|
-
values: Array<number | null>;
|
|
208
|
-
/** Per-series default explosion percent. */
|
|
209
|
-
explosion?: number;
|
|
210
|
-
dataPoints?: DataPointOverride[];
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export interface ScatterSeries extends SeriesBase {
|
|
214
|
-
xValues: Array<number | null>;
|
|
215
|
-
yValues: Array<number | null>;
|
|
216
|
-
smooth?: boolean;
|
|
217
|
-
marker?: MarkerSpec;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
export interface BubbleSeries extends SeriesBase {
|
|
221
|
-
xValues: Array<number | null>;
|
|
222
|
-
yValues: Array<number | null>;
|
|
223
|
-
sizes: Array<number | null>;
|
|
224
|
-
bubbleScale?: number;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
// ---------------------------------------------------------------------------
|
|
228
|
-
// Axes
|
|
229
|
-
// ---------------------------------------------------------------------------
|
|
230
|
-
|
|
231
|
-
export type Axis = CategoryAxis | ValueAxis | DateAxis | SeriesAxis;
|
|
232
|
-
|
|
233
|
-
export interface AxisBase {
|
|
234
|
-
/** c:axId — unique within the plot area. */
|
|
235
|
-
id: string;
|
|
236
|
-
/** c:crossAx — the id of the perpendicular axis this one crosses. */
|
|
237
|
-
crossAxisId?: string;
|
|
238
|
-
/** Value at which the perpendicular axis crosses this one (c:crossesAt). */
|
|
239
|
-
crossesAt?: number | "autoZero" | "max" | "min";
|
|
240
|
-
/** c:axPos: b = bottom, t = top, l = left, r = right. */
|
|
241
|
-
position: "b" | "t" | "l" | "r";
|
|
242
|
-
/**
|
|
243
|
-
* Whether the axis is visible. Note: c:delete has inverted semantics —
|
|
244
|
-
* `val="1"` means invisible; we store the normal-sense boolean here.
|
|
245
|
-
*/
|
|
246
|
-
visible: boolean;
|
|
247
|
-
title?: Title;
|
|
248
|
-
majorGridlines?: boolean;
|
|
249
|
-
minorGridlines?: boolean;
|
|
250
|
-
majorUnit?: number;
|
|
251
|
-
minorUnit?: number;
|
|
252
|
-
/** c:numFmt/@formatCode. */
|
|
253
|
-
numberFormat?: string;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
export interface CategoryAxis extends AxisBase {
|
|
257
|
-
kind: "category";
|
|
258
|
-
/** c:auto — whether category width is chosen automatically. */
|
|
259
|
-
auto: boolean;
|
|
260
|
-
labelAlign?: "ctr" | "l" | "r";
|
|
261
|
-
labelOffset?: number;
|
|
262
|
-
tickMark?: "none" | "in" | "out" | "cross";
|
|
263
|
-
tickLabelSkip?: number;
|
|
264
|
-
tickMarkSkip?: number;
|
|
265
|
-
/** Category labels resolved from the first series' c:cat cache. */
|
|
266
|
-
categoryLabels: string[];
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
export interface ValueAxis extends AxisBase {
|
|
270
|
-
kind: "value";
|
|
271
|
-
min?: number;
|
|
272
|
-
max?: number;
|
|
273
|
-
logBase?: number;
|
|
274
|
-
/** True when c:scaling/c:orientation val="maxMin". */
|
|
275
|
-
reverse: boolean;
|
|
276
|
-
crossBetween?: "between" | "midCat";
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export interface DateAxis extends AxisBase {
|
|
280
|
-
kind: "date";
|
|
281
|
-
baseTimeUnit?: "days" | "months" | "years";
|
|
282
|
-
/** Serial date (days since 1899-12-30). */
|
|
283
|
-
min?: number;
|
|
284
|
-
max?: number;
|
|
285
|
-
majorTimeUnit?: "days" | "months" | "years";
|
|
286
|
-
minorTimeUnit?: "days" | "months" | "years";
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
export interface SeriesAxis extends AxisBase {
|
|
290
|
-
kind: "series";
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// ---------------------------------------------------------------------------
|
|
294
|
-
// Other chart elements
|
|
295
|
-
// ---------------------------------------------------------------------------
|
|
296
|
-
|
|
297
|
-
export interface Title {
|
|
298
|
-
/**
|
|
299
|
-
* Plain-text rendering of the title. Rich-text formatting is not preserved
|
|
300
|
-
* at Stage 1; Stage 2/3 may extend this with per-run styling.
|
|
301
|
-
*/
|
|
302
|
-
text?: string;
|
|
303
|
-
overlay: boolean;
|
|
304
|
-
spPr?: ShapeProperties;
|
|
305
|
-
txPr?: TextProperties;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
export interface Legend {
|
|
309
|
-
position: "b" | "t" | "l" | "r" | "tr";
|
|
310
|
-
overlay: boolean;
|
|
311
|
-
spPr?: ShapeProperties;
|
|
312
|
-
txPr?: TextProperties;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
export interface DataLabelsSpec {
|
|
316
|
-
showVal: boolean;
|
|
317
|
-
showCatName: boolean;
|
|
318
|
-
showSerName: boolean;
|
|
319
|
-
showPercent: boolean;
|
|
320
|
-
showBubbleSize: boolean;
|
|
321
|
-
showLegendKey: boolean;
|
|
322
|
-
position?: "b" | "ctr" | "l" | "r" | "t" | "bestFit" | "inBase" | "inEnd" | "outEnd";
|
|
323
|
-
separator?: string;
|
|
324
|
-
numberFormat?: string;
|
|
325
|
-
txPr?: TextProperties;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
export interface MarkerSpec {
|
|
329
|
-
symbol:
|
|
330
|
-
| "circle"
|
|
331
|
-
| "square"
|
|
332
|
-
| "diamond"
|
|
333
|
-
| "triangle"
|
|
334
|
-
| "x"
|
|
335
|
-
| "star"
|
|
336
|
-
| "dot"
|
|
337
|
-
| "dash"
|
|
338
|
-
| "plus"
|
|
339
|
-
| "picture"
|
|
340
|
-
| "none"
|
|
341
|
-
| "auto";
|
|
342
|
-
/** Point size 2..72. */
|
|
343
|
-
size?: number;
|
|
344
|
-
spPr?: ShapeProperties;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
export interface DataPointOverride {
|
|
348
|
-
/** Index of the data point within the series. */
|
|
349
|
-
idx: number;
|
|
350
|
-
spPr?: ShapeProperties;
|
|
351
|
-
marker?: MarkerSpec;
|
|
352
|
-
/** Pie only: per-slice explosion percent. */
|
|
353
|
-
explosion?: number;
|
|
354
|
-
/** Bar only: render negative values with inverted fill. */
|
|
355
|
-
invertIfNegative?: boolean;
|
|
356
|
-
/** Bubble only: 3D bubble flag (rendered as 2D regardless). */
|
|
357
|
-
bubble3D?: boolean;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// ---------------------------------------------------------------------------
|
|
361
|
-
// Shape / fill / stroke / color primitives
|
|
362
|
-
// ---------------------------------------------------------------------------
|
|
363
|
-
|
|
364
|
-
export interface ShapeProperties {
|
|
365
|
-
fill?: FillSpec;
|
|
366
|
-
stroke?: StrokeSpec;
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
export type FillSpec =
|
|
370
|
-
| { kind: "solid"; color: ColorRef }
|
|
371
|
-
| { kind: "gradient"; stops: Array<{ pos: number; color: ColorRef }>; angle?: number }
|
|
372
|
-
| { kind: "none" }
|
|
373
|
-
| { kind: "auto" };
|
|
374
|
-
|
|
375
|
-
export interface StrokeSpec {
|
|
376
|
-
color?: ColorRef;
|
|
377
|
-
/** Stroke width in EMU (English Metric Units). */
|
|
378
|
-
widthEmu?: number;
|
|
379
|
-
dash?: "solid" | "dash" | "dashDot" | "lgDash" | "lgDashDot" | "sysDash" | "sysDashDot";
|
|
380
|
-
noFill?: boolean;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/**
|
|
384
|
-
* An unresolved color reference. Stage 2 adds `resolveColor(ref, theme)`
|
|
385
|
-
* which turns this into a concrete sRGB string via the chart-color cascade
|
|
386
|
-
* (explicit sRGB → scheme color → theme color scheme).
|
|
387
|
-
*/
|
|
388
|
-
export type ColorRef =
|
|
389
|
-
| { kind: "srgb"; value: string } // "#RRGGBB"
|
|
390
|
-
| { kind: "scheme"; value: string; mods?: ColorMod[] }
|
|
391
|
-
| { kind: "themeLinked"; value: string; mods?: ColorMod[] };
|
|
392
|
-
|
|
393
|
-
export interface ColorMod {
|
|
394
|
-
kind: "lumMod" | "lumOff" | "shade" | "tint" | "satMod" | "hueMod" | "alpha";
|
|
395
|
-
/** Parts per 100,000 (OOXML convention). */
|
|
396
|
-
value: number;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
export interface TextProperties {
|
|
400
|
-
fontFamily?: string;
|
|
401
|
-
fontSizePt?: number;
|
|
402
|
-
bold?: boolean;
|
|
403
|
-
italic?: boolean;
|
|
404
|
-
color?: ColorRef;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
// ---------------------------------------------------------------------------
|
|
408
|
-
// Exhaustiveness canary (compile-time only)
|
|
409
|
-
// ---------------------------------------------------------------------------
|
|
410
|
-
|
|
411
|
-
/**
|
|
412
|
-
* Compile-time assertion that `ChartModel["kind"]` equals the expected
|
|
413
|
-
* literal-union below. If a new variant is added to `ChartModel` without
|
|
414
|
-
* being listed in `_ExpectedKinds`, `_Equals` resolves to `false` and the
|
|
415
|
-
* subsequent `true` assignment fails at compile time. The previous
|
|
416
|
-
* dual-assign-cast pattern did not actually enforce union equality — any
|
|
417
|
-
* new kind silently passed through.
|
|
418
|
-
*
|
|
419
|
-
* Reference: the standard "exact type equality" trick using contravariance
|
|
420
|
-
* of conditional-type generic functions.
|
|
421
|
-
*/
|
|
422
|
-
type _Equals<X, Y> =
|
|
423
|
-
(<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2)
|
|
424
|
-
? true
|
|
425
|
-
: false;
|
|
426
|
-
|
|
427
|
-
type _ExpectedKinds =
|
|
428
|
-
| "bar"
|
|
429
|
-
| "line"
|
|
430
|
-
| "pie"
|
|
431
|
-
| "area"
|
|
432
|
-
| "scatter"
|
|
433
|
-
| "bubble"
|
|
434
|
-
| "combo"
|
|
435
|
-
| "unsupported";
|
|
436
10
|
|
|
437
|
-
type
|
|
438
|
-
const _kindExhaustive: _ChartKindCheck = true;
|
|
439
|
-
void _kindExhaustive;
|
|
11
|
+
export type * from "../../../model/chart-types.ts";
|
|
@@ -160,9 +160,9 @@ export function parseCommentPresentationXml(
|
|
|
160
160
|
for (const commentEl of childrenOf(root, "comment")) {
|
|
161
161
|
const commentId = commentEl.attributes["commentId"] ?? "";
|
|
162
162
|
if (!commentId) continue;
|
|
163
|
-
const
|
|
164
|
-
const audience: CommentAudience = AUDIENCE_VOCAB.has(
|
|
165
|
-
?
|
|
163
|
+
const rawAudience = commentEl.attributes["audience"];
|
|
164
|
+
const audience: CommentAudience = AUDIENCE_VOCAB.has(rawAudience as CommentAudience)
|
|
165
|
+
? (rawAudience as CommentAudience)
|
|
166
166
|
: "internal"; // fail-closed per schema
|
|
167
167
|
const bodyEl = firstChild(commentEl, "body");
|
|
168
168
|
const body: CommentBody = bodyEl ? parseBody(bodyEl) : emptyBody();
|
|
@@ -246,9 +246,10 @@ function parseAttachments(
|
|
|
246
246
|
const out: CommentAttachment[] = [];
|
|
247
247
|
for (const el of childrenOf(container, "attachment")) {
|
|
248
248
|
const id = el.attributes["id"];
|
|
249
|
-
const
|
|
249
|
+
const rawKind = el.attributes["kind"];
|
|
250
250
|
const displayName = el.attributes["displayName"];
|
|
251
|
-
if (!id || !displayName || !ATTACHMENT_KIND_VOCAB.has(kind)) continue;
|
|
251
|
+
if (!id || !displayName || !ATTACHMENT_KIND_VOCAB.has(rawKind as CommentAttachment["kind"])) continue;
|
|
252
|
+
const kind = rawKind as CommentAttachment["kind"];
|
|
252
253
|
const a: CommentAttachment = { id, kind, displayName };
|
|
253
254
|
if (el.attributes["mimeType"] !== undefined) {
|
|
254
255
|
a.mimeType = el.attributes["mimeType"];
|
|
@@ -19,6 +19,10 @@ export const HIGHLIGHT_COLOR_MAP = {
|
|
|
19
19
|
|
|
20
20
|
export type HighlightColorName = keyof typeof HIGHLIGHT_COLOR_MAP;
|
|
21
21
|
|
|
22
|
+
const HIGHLIGHT_COLOR_VOCAB = new Set<HighlightColorName>(
|
|
23
|
+
Object.keys(HIGHLIGHT_COLOR_MAP) as HighlightColorName[],
|
|
24
|
+
);
|
|
25
|
+
|
|
22
26
|
export function resolveHighlightColor(
|
|
23
27
|
value: string | null | undefined,
|
|
24
28
|
): { color: string; val: HighlightColorName } | undefined {
|
|
@@ -26,14 +30,13 @@ export function resolveHighlightColor(
|
|
|
26
30
|
return undefined;
|
|
27
31
|
}
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
const color = HIGHLIGHT_COLOR_MAP[normalizedValue];
|
|
31
|
-
if (!color) {
|
|
33
|
+
if (!HIGHLIGHT_COLOR_VOCAB.has(value as HighlightColorName)) {
|
|
32
34
|
return undefined;
|
|
33
35
|
}
|
|
34
36
|
|
|
37
|
+
const name = value as HighlightColorName;
|
|
35
38
|
return {
|
|
36
|
-
color,
|
|
37
|
-
val:
|
|
39
|
+
color: HIGHLIGHT_COLOR_MAP[name],
|
|
40
|
+
val: name,
|
|
38
41
|
};
|
|
39
42
|
}
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
import type { AnchorGeometry } from "../../model/canonical-document.ts";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface XmlTextNode {
|
|
11
|
-
type: "text";
|
|
12
|
-
text: string;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
type XmlNode = XmlElementNode | XmlTextNode;
|
|
2
|
+
import {
|
|
3
|
+
type XmlElementNode,
|
|
4
|
+
findFirstChild,
|
|
5
|
+
findFirstDescendant,
|
|
6
|
+
localName,
|
|
7
|
+
extractText,
|
|
8
|
+
} from "./_mini-xml.ts";
|
|
16
9
|
|
|
17
10
|
export function parseAnchorGeometry(container: XmlElementNode): AnchorGeometry {
|
|
18
11
|
const tag = localName(container.name);
|
|
@@ -49,19 +42,33 @@ export function parseAnchorGeometry(container: XmlElementNode): AnchorGeometry {
|
|
|
49
42
|
|
|
50
43
|
const docPrEl = findFirstChild(container, "docPr");
|
|
51
44
|
const docPr = docPrEl
|
|
52
|
-
? {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
45
|
+
? (() => {
|
|
46
|
+
const dp: NonNullable<AnchorGeometry["docPr"]> = {
|
|
47
|
+
id: docPrEl.attributes.id ?? "",
|
|
48
|
+
};
|
|
49
|
+
if (docPrEl.attributes.name) dp.name = docPrEl.attributes.name;
|
|
50
|
+
if (docPrEl.attributes.descr) dp.descr = docPrEl.attributes.descr;
|
|
51
|
+
// Phase 4.6 G8 — wp:docPr hidden flag
|
|
52
|
+
const hidden = readBoolAttr(docPrEl, "hidden");
|
|
53
|
+
if (hidden !== undefined) dp.hidden = hidden;
|
|
54
|
+
return dp;
|
|
55
|
+
})()
|
|
57
56
|
: undefined;
|
|
58
57
|
|
|
58
|
+
// Phase 4.6 G8 — wp:cNvGraphicFramePr/a:graphicFrameLocks for object chrome.
|
|
59
|
+
const cNvPr = findFirstChild(container, "cNvGraphicFramePr");
|
|
60
|
+
const frameLocks = cNvPr ? readFrameLocks(cNvPr) : undefined;
|
|
61
|
+
|
|
62
|
+
// Phase 4.2 G1 — wrapPolygon coords for wrapTight / wrapThrough.
|
|
63
|
+
const wrapPolygon = readWrapPolygon(container);
|
|
64
|
+
|
|
59
65
|
const geometry: AnchorGeometry = {
|
|
60
66
|
display,
|
|
61
67
|
extent,
|
|
62
68
|
wrapMode,
|
|
63
69
|
};
|
|
64
70
|
|
|
71
|
+
if (wrapPolygon) geometry.wrapPolygon = wrapPolygon;
|
|
65
72
|
if (positionHEl) geometry.positionH = readAxisPosition(positionHEl);
|
|
66
73
|
if (positionVEl) geometry.positionV = readAxisPosition(positionVEl);
|
|
67
74
|
if (distMargins) geometry.distMargins = distMargins;
|
|
@@ -71,6 +78,7 @@ export function parseAnchorGeometry(container: XmlElementNode): AnchorGeometry {
|
|
|
71
78
|
if (allowOverlap !== undefined) geometry.allowOverlap = allowOverlap;
|
|
72
79
|
if (simplePos !== undefined) geometry.simplePos = simplePos;
|
|
73
80
|
if (docPr) geometry.docPr = docPr;
|
|
81
|
+
if (frameLocks) geometry.frameLocks = frameLocks;
|
|
74
82
|
|
|
75
83
|
return geometry;
|
|
76
84
|
}
|
|
@@ -92,6 +100,47 @@ function readExtent(container: XmlElementNode): AnchorGeometry["extent"] {
|
|
|
92
100
|
};
|
|
93
101
|
}
|
|
94
102
|
|
|
103
|
+
function readWrapPolygon(
|
|
104
|
+
container: XmlElementNode,
|
|
105
|
+
): Array<{ x: number; y: number }> | undefined {
|
|
106
|
+
const wrapEl =
|
|
107
|
+
findFirstChild(container, "wrapTight") ??
|
|
108
|
+
findFirstChild(container, "wrapThrough");
|
|
109
|
+
if (!wrapEl) return undefined;
|
|
110
|
+
const polygon = findFirstChild(wrapEl, "wrapPolygon");
|
|
111
|
+
if (!polygon) return undefined;
|
|
112
|
+
|
|
113
|
+
const coords: Array<{ x: number; y: number }> = [];
|
|
114
|
+
const start = findFirstChild(polygon, "start");
|
|
115
|
+
if (start) {
|
|
116
|
+
const x = readIntAttr(start, "x");
|
|
117
|
+
const y = readIntAttr(start, "y");
|
|
118
|
+
coords.push({ x: x ?? 0, y: y ?? 0 });
|
|
119
|
+
}
|
|
120
|
+
for (const child of polygon.children) {
|
|
121
|
+
if (child.type !== "element") continue;
|
|
122
|
+
if (localName(child.name) !== "lineTo") continue;
|
|
123
|
+
const x = readIntAttr(child, "x");
|
|
124
|
+
const y = readIntAttr(child, "y");
|
|
125
|
+
coords.push({ x: x ?? 0, y: y ?? 0 });
|
|
126
|
+
}
|
|
127
|
+
return coords.length > 0 ? coords : undefined;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function readFrameLocks(
|
|
131
|
+
cNvPr: XmlElementNode,
|
|
132
|
+
): NonNullable<AnchorGeometry["frameLocks"]> | undefined {
|
|
133
|
+
const locks = findFirstChild(cNvPr, "graphicFrameLocks");
|
|
134
|
+
if (!locks) return undefined;
|
|
135
|
+
const result: NonNullable<AnchorGeometry["frameLocks"]> = {};
|
|
136
|
+
const keys = ["noChangeAspect", "noResize", "noMove", "noRot", "noSelect", "noGrp"] as const;
|
|
137
|
+
for (const key of keys) {
|
|
138
|
+
const v = readBoolAttr(locks, key);
|
|
139
|
+
if (v !== undefined) result[key] = v;
|
|
140
|
+
}
|
|
141
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
142
|
+
}
|
|
143
|
+
|
|
95
144
|
function readWrapMode(
|
|
96
145
|
container: XmlElementNode,
|
|
97
146
|
): AnchorGeometry["wrapMode"] {
|
|
@@ -129,40 +178,6 @@ function readAxisPosition(
|
|
|
129
178
|
return result;
|
|
130
179
|
}
|
|
131
180
|
|
|
132
|
-
function findFirstChild(
|
|
133
|
-
node: XmlElementNode,
|
|
134
|
-
local: string,
|
|
135
|
-
): XmlElementNode | undefined {
|
|
136
|
-
for (const child of node.children) {
|
|
137
|
-
if (child.type === "element" && localName(child.name) === local) return child;
|
|
138
|
-
}
|
|
139
|
-
return undefined;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function findFirstDescendant(
|
|
143
|
-
node: XmlElementNode,
|
|
144
|
-
local: string,
|
|
145
|
-
): XmlElementNode | undefined {
|
|
146
|
-
for (const child of node.children) {
|
|
147
|
-
if (child.type !== "element") continue;
|
|
148
|
-
if (localName(child.name) === local) return child;
|
|
149
|
-
const found = findFirstDescendant(child, local);
|
|
150
|
-
if (found) return found;
|
|
151
|
-
}
|
|
152
|
-
return undefined;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function localName(name: string): string {
|
|
156
|
-
const i = name.indexOf(":");
|
|
157
|
-
return i >= 0 ? name.slice(i + 1) : name;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function extractText(node: XmlElementNode): string {
|
|
161
|
-
return node.children
|
|
162
|
-
.map((c) => (c.type === "text" ? c.text : extractText(c as XmlElementNode)))
|
|
163
|
-
.join("");
|
|
164
|
-
}
|
|
165
|
-
|
|
166
181
|
function readIntAttr(node: XmlElementNode, name: string): number | undefined {
|
|
167
182
|
const v = node.attributes[name] ?? node.attributes[`wp:${name}`];
|
|
168
183
|
if (v === undefined) return undefined;
|