返回 ppt-master
native-data-interface.md
根目录 / skills / ppt-master / references / native-data-interface.md
1 > See [`executor-base.md`](./executor-base.md) for the Shape-first page authority and [`shared-standards-core.md`](./shared-standards-core.md) for the mandatory SVG foundation.
2
3 # Native Data Interface
4
5 Sole conditional interface for preset pattern fills and PowerPoint-native chart/table replacement eligibility, markers, metadata schemas, and export activation. Load only when either feature is selected for the authored SVG.
6
7 ## 1. Pattern Fill — `<pattern>` with PPTX preset annotation
8
9 `<pattern>` requests one fixed DrawingML preset; the converter does not render
10 the tile's arbitrary geometry. Use this interface only when that preset mapping
11 is intended.
12
13 `data-pptx-pattern="<preset>"` is the generated default for selecting the
14 intended preset from the enum below. The converter retains an `ltUpDiag`
15 fallback when the annotation is absent; the checker reports that fallback as a
16 non-blocking fidelity warning. Invalid explicit preset names remain errors
17 because they violate the closed OOXML enum.
18
19 Pattern colors may come from importer metadata (`data-pptx-fg` /
20 `data-pptx-bg`) or from the pattern's child paint. Without metadata, the first
21 child `<rect>` fill becomes the background and the first stroke (or other fill)
22 becomes the foreground. A missing background defaults to white; a missing
23 foreground means no native pattern fill can be emitted. The child geometry
24 itself is never used as a repeatable tile.
25
26 **Valid `data-pptx-pattern` values** (OOXML `ST_PresetPatternVal` — closed enum, anything outside makes PowerPoint open with "needs to be repaired"):
27
28 | Category | Values |
29 |---|---|
30 | Grids | `smGrid` · `lgGrid` · `dotGrid` *(no `ltGrid` — common typo)* |
31 | Diagonal lines | `ltUpDiag` · `ltDnDiag` · `dkUpDiag` · `dkDnDiag` · `wdUpDiag` · `wdDnDiag` · `dashUpDiag` · `dashDnDiag` · `diagCross` |
32 | Horizontal / vertical lines | `horz` · `vert` · `ltHorz` · `ltVert` · `dkHorz` · `dkVert` · `narHorz` · `narVert` · `dashHorz` · `dashVert` · `cross` |
33 | Percent fills | `pct5` · `pct10` · `pct20` · `pct25` · `pct30` · `pct40` · `pct50` · `pct60` · `pct70` · `pct75` · `pct80` · `pct90` |
34 | Checks & confetti | `smCheck` · `lgCheck` · `smConfetti` · `lgConfetti` |
35 | Decorative | `horzBrick` · `diagBrick` · `weave` · `plaid` · `trellis` · `zigZag` · `wave` · `sphere` · `divot` · `shingle` · `solidDmnd` · `openDmnd` · `dotDmnd` |
36
37 `svg_quality_checker.py` warns when a referenced pattern lacks the annotation;
38 it errors when the pattern uses `patternTransform` or names a preset outside
39 this enum.
40
41 ## 2. PowerPoint-Native Chart / Table Replacement Markers (Opt-in)
42
43 [`executor-base.md`](./executor-base.md) remains the single Shape-first authoring authority: the complete visible SVG fallback is required regardless of native eligibility. This section only adds dormant replacement metadata to independently selected objects and defines how export may activate it.
44
45 **Hard rule — selected-object authoring**: write the marker and JSON metadata in
46 the same edit for every supported chart and pure text-grid table; both are
47 native-ready by default. An unactivated marker changes no export, so never skip
48 an eligible object because the current request did not ask for native output.
49 The Default route reads the exact semantic object key from §IX
50 `Native-ready: <object-key>=yes|no; ...`; Quick assigns the same page-local
51 `kebab-case` key in active context before drawing. Use that key as the marker
52 group `id` and metadata `name`. A catalog `family/key`, family name, §VII row,
53 numeric content, or another ready object on the page never implies eligibility.
54 A `<object-key>=no` entry and unlisted incidental microvisuals stay on the SVG
55 fallback route. Canonical rectangular merged text cells may use the narrow
56 `row_span` / `col_span` contract below; graphical cells stay unmarked. The
57 marker group supplies visible fallback children for browser rendering and JSON
58 metadata for `svg_to_pptx` native export.
59
60 A legacy bare `Native-ready: yes|no` maps only to the page's sole eligible
61 object. Zero or multiple eligible objects make it ambiguous and require
62 upstream repair.
63
64 **MUST — atomic authoring**: treat one object's visible SVG fallback, parent
65 `data-pptx-replace-with` marker, and single JSON `<metadata>` child as one
66 authoring unit. Write all three while that object's data is in context. Do not
67 defer the marker or metadata to `verify-charts`, the final quality gate, or
68 export.
69
70 **Hard rule — activation is the opt-in, dormant unless exported with `--native-charts-and-tables`**: A marker only declares that a group is eligible for PowerPoint-native Chart/Table replacement. Normal `svg_to_pptx.py` runs keep the fallback SVG children and convert them into independently editable DrawingML shapes. Pass `--native-charts-and-tables` only when the data source and chart/table-specific object model matter more than cross-renderer layout fidelity: it emits the PowerPoint Chart/Table object and skips the fallback children to avoid duplicates. Native styling preserves the core palette, text, axis, grid, and background colors where possible, but it is still a PowerPoint Chart/Table object rather than a pixel-identical SVG drawing.
71
72 The native route is deliberately data-object-first and may be lossy: marker-local labels, callouts, KPIs, guide lines, custom split/bin semantics, or styling that is absent from the payload may disappear or normalize. Export warns about this route-level risk and any narrower issue it can detect. Loss of visual parity is not grounds to remove an active marker that the emitter can otherwise convert; use the default SVG-fallback export when exact authored artwork matters more than a native data source and object-specific controls.
73
74 | Replacement marker | Native output | Required metadata |
75 |---|---|---|
76 | `<g data-pptx-replace-with="table">` | `<p:graphicFrame>` with `<a:tbl>` | bounds + `columns` or `rows` |
77 | `<g data-pptx-replace-with="chart">` | `<p:graphicFrame>` with `c:chart` / `cx:chart` + chart part + embedded workbook | bounds + `type`, plus chart data |
78
79 **Metadata placement**: Put JSON in one child
80 `<metadata type="application/json">`. The parent group's
81 `data-pptx-replace-with` value selects the table or chart schema, so the
82 metadata child does not repeat an object-kind attribute. Attribute JSON
83 (`data-pptx-json="..."`) remains read-compatible but is harder to XML-escape
84 correctly and is not canonical authoring.
85
86 **Bounds**: Provide `x`, `y`, `width`, and `height` in metadata, or as
87 `data-pptx-x` / `data-pptx-y` / `data-pptx-width` / `data-pptx-height` on the
88 marker group. If any bound is omitted, the exporter infers the object frame
89 from the visible fallback geometry; this keeps SVG fallback and native object
90 placement aligned. Complete explicit bounds are absolute slide coordinates;
91 marker/ancestor `translate` and `scale` transforms apply only when at least one
92 bound is inferred. `x`, `y`, `width`, and `height` must be finite and resolve
93 inside PowerPoint's 32-bit DrawingML coordinate range; `width` and `height`
94 must resolve to at least one EMU. Native table frames must additionally resolve
95 to at least one EMU per resolved row and column.
96
97 **Classic plot-area layout**: supported classic charts accept root `plot_area`;
98 ChartEx rejects it. It contains only finite `x`, `y`, `width`, `height` in
99 absolute slide px and forms a positive rectangle inside the chart frame. Export
100 writes `c:manualLayout`; omission keeps automatic layout.
101
102 **Validation**: `svg_quality_checker.py` validates replacement marker kind, JSON
103 metadata, bounds/fallback availability, table rows/columns, supported chart
104 type, chart data shape, and any imported fallback baseline before export.
105
106 Imported marker freshness, fallback classification, provenance, and legacy
107 read compatibility are operational import concerns. Keep generated authoring
108 free of those attributes; use the exact behavior and field index in
109 [`conversion.md`](../scripts/docs/conversion.md#native-table-and-chart-import-claims).
110
111 ```xml
112 <g id="p03-revenue-chart" data-pptx-replace-with="chart">
113 <metadata type="application/json">
114 {
115 "x": 120, "y": 150, "width": 520, "height": 320,
116 "name": "p03-revenue-chart",
117 "type": "column",
118 "title": "Revenue by Segment",
119 "categories": ["Q1", "Q2", "Q3"],
120 "series": [
121 {"name": "Cloud", "values": [12, 15, 19]},
122 {"name": "Services", "values": [8, 9, 11]}
123 ]
124 }
125 </metadata>
126 <!-- Visible SVG fallback for live preview / non-native export goes here. -->
127 </g>
128 ```
129
130 **Hard rule — transcribe the authored object**: metadata is the native object's
131 source of truth and must describe the same data and visible chart/table chrome
132 as the fallback drawn in that marker group.
133
134 | Object | Required projection from the visible fallback |
135 |---|---|
136 | Chart | Every category/point and series value, the actual x/y/size data where applicable, visible point colors and labels, line/area treatment needed by the schema, visible title/axis/legend chrome, companion text, bounds, and fallback typography/style values that native export cannot infer unambiguously |
137 | Table | Every resolved row/column cell, header/summary line, rectangular span, required cell style, alignment, bounds, and visible typography |
138
139 Do not simplify the SVG artwork to match the native object model. When the
140 closed payload cannot represent an object without losing required data or cell
141 topology, Default returns the native-ready decision upstream and Quick revises
142 that per-object decision before drawing; only the resolved non-native object
143 stays unmarked on its complete SVG fallback. Never silently ignore an explicit
144 `<object-key>=yes` declaration.
145
146 **Per-page verification**: enumerate every `<object-key>=yes` on the current
147 page and confirm a one-to-one key match. Each key identifies one parent marker
148 and exactly one JSON metadata child; `<object-key>=no` and unlisted incidental
149 objects have no marker. Finding one marker somewhere on a page is insufficient.
150
151 ```bash
152 rg -n 'data-pptx-replace-with="(chart|table)"|<metadata type="application/json">' <project_path>/svg_output/<current_page>.svg
153 ```
154
155 **Table schema**: Native tables are rectangular DrawingML grids. Use `columns`
156 for the optional header row and `rows` for body rows; shorter rows are padded
157 with blank cells unless `strict_grid: true` is set. Tables may contain at most
158 1000 resolved rows and 1000 resolved columns. Use `column_widths` and
159 `row_heights` as relative weights. Weight lists must match the resolved grid,
160 contain finite non-negative numbers, and include at least one positive value.
161 If present, `header_rows` must be an integer from `0` through the resolved row
162 count. Write `strict_grid`, `style.band_row`, and cell `bold` as JSON booleans.
163 Cell objects accept `text`, `fill`, `color`,
164 `align`, `valign`, `bold`, `font_size`, `padding`, `border_color`, and
165 `border_width`, plus optional `lang`; the same `padding`, `border_color`,
166 `border_width`, and `lang` keys may also live under `style` as table defaults.
167 For multi-paragraph text, replace cell `text` with a non-empty `paragraphs`
168 list. Each entry is either a string or an object containing optional
169 `align: "l|ctr|r"` and exactly one of `text` or non-empty `runs`; empty
170 paragraph strings are preserved, and cell `text` / `paragraphs` are mutually
171 exclusive. Each run is an object with required string `text` and optional JSON
172 boolean `bold`, `italic`, `underline`, and `strike`, plus optional `color`,
173 `font_size`, one-typeface `font_family`, `lang`, and `alt_lang`. Unknown fields,
174 wrong types, empty run lists, multi-typeface `font_family`, and unsupported
175 colors fail fast. PPTX import requires exact physical row/grid topology and
176 normalizes source presentation-only run XML outside this closed schema only
177 when it contains no non-empty `rPr` / `defRPr` / `endParaRPr` `effectLst` or
178 `effectDag`. A table-cell run effect follows the blocking effect contract above
179 instead of entering either the native payload or an effect-free fallback.
180 Relationship-bearing text, extensions, structural line breaks, fields, tabs,
181 bullets, malformed run topology, and unsupported text-body structure remain
182 fallback-only.
183 Per-side cell borders use `borders.left|right|top|bottom`, where each value is
184 either `{ "style": "none" }` or
185 `{ "style": "solid", "color": "#RRGGBB", "width": <positive-px> }`.
186 Per-side borders are cell-only; legacy uniform `border_color` / `border_width`
187 remain supported as defaults that an individual side may override.
188 When `lang` is absent, export derives `zh-CN` for CJK text and `en-US`
189 otherwise. `style.band_row: false` disables both `<a:tblPr bandRow>` and
190 materialized alternating row fills. Native table typography mirrors the
191 visible SVG fallback: put `style.font_family` and `style.font_size` on the
192 marker from the table text already drawn, then use `style.header_font_size` or
193 per-cell `font_size` only when the fallback visibly differs. If the fallback
194 has no explicit table font, Default uses the deck body family and declared body
195 anchor from `spec_lock.md`; Quick uses its active-context body family and size.
196
197 **Hard rule — table metadata is the native source of truth**: Every row,
198 summary line, value, and cell-level style that must survive
199 `--native-charts-and-tables` must be present in `columns` / `rows`. SVG fallback text is
200 discarded during native export. `svg_quality_checker.py` warns when visible
201 fallback `<text>` inside a native table marker does not appear in metadata.
202 For numeric or currency columns, use cell objects with `align: "r"`; SVG
203 `text-anchor="end"` does not carry into the native table.
204
205 **Merged table cells — canonical rectangular contract only**: Put positive JSON
206 integer `row_span` / `col_span` values on the merge anchor and keep every
207 covered grid cell blank. Spans must stay within the resolved rectangular grid
208 and may not overlap. The exporter emits the canonical DrawingML topology
209 (`rowSpan` on the top edge, `gridSpan` on the left edge, `hMerge` / `vMerge` on
210 covered cells). CamelCase aliases, raw OOXML merge fields, top-level merge lists,
211 nonblank covered cells, invalid spans, and overlaps fail fast. The PPTX importer
212 activates native reconstruction only for that same explicit rectangular topology
213 with empty merge-slave text bodies; other merge encodings remain fallback-only
214 with `unsupported-merge-topology`.
215
216 **Category chart schema**: `column`, `bar`, `line`, `area`, `pie`,
217 `doughnut`, `pieOfPie`, `barOfPie`, and `radar` use `categories` plus
218 `series[].values`. Pie-family charts (`pie`, `doughnut`, `pieOfPie`, and
219 `barOfPie`) must have exactly one series; the exporter assigns per-category
220 slice colors so single-series charts do not collapse into one solid color.
221 Root `hole_size` is doughnut-only, integer `10..90`, default `75`;
222 no pie-family rotation or angle field exists.
223 Column and bar charts may set per-point colors with `series[].point_colors`
224 or `series[].pointColors`; the list must match `series[].values` length.
225 Classic category charts may set native PowerPoint data labels with
226 `data_labels`. Use `data_labels: true` for default value labels, or an object
227 with `show_value`, `position`, `number_format`, `font_size`, `font_family`,
228 `bold`, `color`, and optional per-point `colors`. Supported label positions
229 depend on chart type: clustered column/bar labels may use `outside_end`,
230 `inside_end`, `inside_base`, or `center`; stacked / percent-stacked column/bar
231 labels may use `inside_end`, `inside_base`, or `center`; line labels may use
232 `above`, `center`, or `best_fit`; area labels do not emit a native label
233 position. To label only selected data points, use `data_labels.points` with
234 zero-based `idx` plus optional per-point `position`, `number_format`,
235 `font_size`, `font_family`, `bold`, and `color`.
236
237 **Combo chart schema**: `combo` uses shared `categories` plus either `plots[]`
238 or typed `series[]`. Each plot supports `type: "column" | "line" | "area"`,
239 its own `series`, and optional `axis: "secondary"` for a right-side value axis.
240 When primary and secondary plots genuinely use different category caches,
241 `plots[]` may also carry its own `categories` and `category_numeric`; the
242 workbook writer allocates independent category/value ranges. Typed `series[]`
243 continues to require the shared top-level categories.
244 Imported `plots[]` may carry `series_indices` so the verified source identity
245 where each `c:idx` equals its `c:order` survives when physical plot order differs
246 from legend order. If one plot supplies it, every plot must supply a same-length
247 list of unique non-negative JSON integers, and the combined values must form one
248 contiguous `0..N-1` range. Sources whose `idx` and `order` differ stay
249 fallback-only; typed `series[]` does not accept this plot-scoped field.
250 Typed `series[]` accepts the same `type` and `axis` fields per series, and
251 adjacent compatible series are grouped into the same PowerPoint plot. Area
252 series may set `fill_opacity` / `fillOpacity` as a `0..1` SVG opacity value
253 when the SVG fallback uses a transparent area fill under an opaque line. A line plot with `area_fill: true`
254 is exported as a PowerPoint area chart under the hood; `fill_opacity` only sets
255 the fill style and does not trigger conversion by itself. Combo export layers
256 area plots below columns and lines while preserving the original series indices.
257 Line and area series may set `line_width` / `lineWidth` in SVG px units to
258 match fallback `stroke-width`.
259
260 **Narrow classic-axis schema**: `axes` is a closed object with the roles
261 `category`, `value`, `secondary_category`, and `secondary_value`. Each role may
262 set only `kind` (`text`, `date`, or `value`, as appropriate), `position`,
263 `visible`, `label_position` (`next_to`, `none`, `low`, or `high`),
264 `number_format`, `minimum`, `maximum`, `major_unit`, `reverse`, and
265 `major_gridlines`. `major_unit` applies to value axes only. PPTX date-axis
266 **import** is deliberately narrow: numeric Excel date serials are accepted for
267 area charts and OHLC stock charts; arbitrary date-axis source families are not.
268 This contract is not a full `AxisSpec`: logarithmic scales, minor units/gridlines,
269 crossing values, display units, tick skipping, and other unlisted OOXML semantics
270 remain unsupported and fail closed on import.
271 Single-plot `bar` accepts `category` at left/right and `value` at bottom/top;
272 `pie`, `doughnut`, and `pieOfPie` / `barOfPie` reject `axes`.
273
274 **Narrow XY-axis schema**: `scatter` and `bubble` may use a closed `axes` object
275 with only `x` and `y` roles. Both roles have `kind: "value"`; `x.position`
276 is `bottom` or `top`, while `y.position` is `left` or `right`. Each accepts the
277 same closed fields above, and `major_unit` is valid on both value axes. PPTX
278 import requires the plot to reference exactly two mutually cross-linked
279 `c:valAx` nodes and separately enforces the closed field/topology gates. The
280 native writer emits and the importer reads back every field in this closed
281 contract. Scatter import derives the effective `scatter_style` from a uniform
282 per-series line/marker/smooth state; unsupported or nonuniform states remain
283 fallback-only. The normalized SVG fallback newly consumes only
284 `axes.x.major_gridlines` and `axes.y.major_gridlines`; the other fields do not
285 imply full visual-axis parity.
286
287 **XY chart schema**: `scatter` and `bubble` use `series[].x` + `series[].y`;
288 `bubble` also requires one `series[].size` / `series[].sizes` value per point.
289 `series[].points` is also accepted as `[x, y]` / `[x, y, size]` tuples or
290 `{x, y, size}` objects.
291
292 **Chart typography**: Metadata sizes use the same px-style unit as SVG text
293 (`1px = 0.75pt`). `style.font_family` and the role-specific
294 `title_font_size`, `subtitle_font_size`, `axis_font_size`,
295 `axis_title_font_size`, `legend_font_size`, and `note_font_size` fields are
296 required only when the native object must preserve typography that cannot be
297 inferred unambiguously from the visible fallback.
298
299 **Chart chrome metadata**: Metadata MUST match fallback chrome. For classic
300 charts, a string or unbounded-object `title` becomes native `c:title`;
301 `subtitle` is line two. A title object with complete `x`, `y`,
302 `width`, and `height` becomes a companion editable text box at those absolute
303 slide-px bounds; partial bounds or `subtitle` fail. Use `name`, not
304 `title`, for object naming. `title`, `subtitle`, and axis-title objects may set
305 `text`, `font_size`, `font_family`, and `color`. The checker rejects title/axis
306 text absent from the fallback; export omits it with a warning. ChartEx keeps an empty `<cx:title>` and
307 emits title/subtitle as companion editable text boxes. Axis
308 titles are optional and explicit: use `axis_titles` with
309 `category`, `value`, `x`, `y`, or `secondary_value` keys, or the root aliases
310 `category_axis_title`, `value_axis_title`, `x_axis_title`, `y_axis_title`, and
311 `secondary_value_axis_title`; do not add semantic axis titles that are not
312 visible in the fallback. Set `show_value_axis_labels: false` when the fallback
313 keeps category labels but omits numeric value-axis tick labels, such as a radar
314 chart without radial coordinates. Native legends are metadata-controlled: use
315 `show_legend: true` and `legend_position` only when the fallback's legend is
316 meant to be replaced by PowerPoint's native legend.
317 Companion text such as `caption`, `source`, `note`, `notes`, `footnote`, and
318 `footnotes` is exported as editable PPT text boxes next to the native chart. A
319 companion entry may be a string or an object with `text`, `x`, `y`, `width`,
320 `height`, `font_size`, `color`, `align`, and `bold`; explicit bounds are
321 recommended so the native export matches the SVG fallback placement. Explicit
322 companion bounds are slide coordinates, not local coordinates inside a
323 transformed marker group. Use companion text for chart captions, source notes,
324 center labels, and freeform annotations; use `data_labels` for values that
325 belong to chart points.
326
327 **Chart color styling**: For classic native charts, `style.colors` sets series
328 colors. The exporter also writes explicit chart-area fill, plot-area fill,
329 axis line, gridline, and label text colors so PowerPoint does not substitute a
330 white/default-theme chart. If omitted, the exporter infers these colors from
331 the visible SVG fallback: the largest panel-like `<rect>` becomes the chart
332 background, fallback text supplies label color, and fallback strokes supply
333 axis/grid colors. Override any of them explicitly under `style` with
334 `chart_area_fill`, `plot_area_fill`, `text_color`, `axis_color`, and
335 `grid_color`; use `"none"` for transparent chart or plot area fill. Generated
336 payloads default to uppercase `#RRGGBB`. The exporter retains compatibility for
337 `#RGB`, `rgb(...)` / `rgba(...)`, and common CSS names, normalizing them to
338 6-digit OOXML RGB. Bar and column series also disable PowerPoint's negative-value
339 inversion so negative bars keep the same series fill instead of turning into
340 white/theme fill.
341
342 For ChartEx native charts, valid payload `style.colors` (or root `colors`)
343 populate the ChartEx color-style part instead of being replaced by a fixed
344 accent1–accent6 list. Other ChartEx style semantics remain normalized.
345
346 **PowerPoint chartEx schema**: `treemap`, `sunburst`, `histogram`, `pareto`,
347 `boxWhisker`, `waterfall`, and `funnel` use Office 2016+ chartEx parts. Use
348 these input shapes:
349
350 | Type | Required data |
351 |---|---|
352 | `treemap`, `sunburst` | `values` plus either `levels` (`levels[level][point]`) or path-style `categories` (`[["Region", "Group", "Leaf"], ...]`) |
353 | `treemap` display note | Top-level group labels default to `overlapping`; override with `parent_label_layout: "banner" \| "overlapping" \| "none"`. PowerPoint labels only the top level and leaves — intermediate levels group tiles spatially without labels (sunburst shows every ring). |
354 | `histogram` | `values` |
355 | `pareto`, `waterfall`, `funnel` | `categories` + `values`; `waterfall` also accepts `subtotals` / `subtotal_indices` point indexes |
356 | `boxWhisker` | `series[].values`; optional `series[].categories` per value |
357
358 > Note: chartEx files are valid PPTX and editable in PowerPoint; non-Microsoft
359 > renderers can display a limited subset.
360
361 **Stock chart schema**: `stock` uses numeric Excel date serials in
362 `categories` or `dates`, plus exactly four series in open / high / low / close
363 order. Use either `series` with four entries, or top-level `open`, `high`,
364 `low`, and `close` arrays. PPTX import currently recognizes only canonical OHLC
365 stock charts with shared numeric date caches, `hiLowLines`, and `upDownBars`.
366 Safe stock series style may pass the structural gate, but stock series,
367 `hiLowLines`, and up-down bar local styling can still normalize under the
368 data-object-first contract. HLC, volume, noncanonical structure, and style XML
369 outside the safe parsing boundary stay fallback-only.
370
371 **PPTX chart-import boundary**: The importer recognizes conservative classic
372 single-plot charts plus the verified scatter/bubble XY-axis, column/line/area
373 combo, area date-axis, canonical OHLC stock, radar, safe `of_pie` `serLines`,
374 axis/title/legend normalization, and bar/column gap/overlap subsets. Imported
375 `gapWidth` must be one canonical integer in `0..500`; imported `overlap` must be
376 one canonical integer in `-100..100`. Both values intentionally normalize to
377 the native writer contract rather than claiming exact source-style retention.
378 Malformed, duplicate, or out-of-range values fail closed.
379
380 ChartEx import is closed to seven validated data models: `treemap`, `sunburst`,
381 `histogram`, `pareto`, `box_whisker`, `waterfall`, and `funnel`. The importer
382 retains their supported hierarchy/category/value/series/subtotal topology for
383 native read-back. Numeric cache values must be non-empty and finite, and cache
384 counts/indexes must be canonical non-negative decimal integers with exact,
385 contiguous topology; malformed, non-numeric, `NaN`, infinite, sparse, duplicate,
386 or mismatched caches fail closed. ChartEx style, axis, label, and binning details
387 outside the payload normalize. Full `AxisSpec`, arbitrary ChartEx families or
388 presentation fidelity, arbitrary stock variants, and axis/combo/date-axis
389 semantics outside the closed fields above remain fallback-only. The C4/C5
390 import work does not expand the normalized SVG renderer and does not reduce
391 existing SVG-marker-to-native writer support.
392
393 **Deferred chart types**: Exploded pie / doughnut variants, `map`, `heatmap`,
394 `bullet`, and `gantt` are intentionally outside the current native-object
395 support boundary. The exporter fails fast for these types until each mapping is
396 implemented and validated one by one.
397
398 **Supported chart types**:
399
400 - `column`, `bar`: `clustered`, `stacked`, or `percentStacked` (`grouping`)
401 - `line`: `standard`, `stacked`, or `percentStacked` (`grouping`); `line` or `lineMarker` (`line_style`, default `line` / no markers)
402 - `area`: `standard`, `stacked`, or `percentStacked` (`grouping`)
403 - `pie`: exactly one series, per-slice colors
404 - `doughnut`: exactly one series, per-slice colors
405 - `pieOfPie`, `barOfPie`: exactly one series, per-slice colors
406 - `radar`, `radarMarkers`, `radarFilled`
407 - `scatter`: `marker` (default), `lineMarker`, `line`, `smoothMarker`, or `smooth` (`scatter_style`)
408 - `bubble`: x/y/size series
409 - `combo`: `column`, `line`, and `area` plots, optional secondary value axis
410 - `treemap`, `sunburst`: hierarchical chartEx charts
411 - `histogram`, `pareto`
412 - `boxWhisker`
413 - `waterfall`, `funnel`
414 - `stock`: open / high / low / close series
415
416 3D chart aliases (`3DColumn`, `3DBar`, `3DLine`, `3DArea`, `3DPie`, cone,
417 cylinder, pyramid variants, and `surface`) are unsupported.
418
419 Native legends are opt-in through `show_legend: true`; `legend_position`
420 defaults to `bottom` and accepts `top`, `left`, or `right`.
421
422 **Forbidden — replacement marker transforms**: Do not rotate, skew, or matrix-transform table/chart replacement groups. Translate / scale is accepted; complex transforms fail export because PowerPoint-native table/chart frames do not preserve arbitrary SVG transforms.
423
423 lines MARKDOWN