@liustack/pptwise 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +127 -0
- package/README.zh-CN.md +136 -0
- package/cordis.patch.yml +5 -0
- package/dist/chunk-3ZUKISTY.js +114 -0
- package/dist/chunk-3ZUKISTY.js.map +1 -0
- package/dist/chunk-M35M4QUC.js +1167 -0
- package/dist/chunk-M35M4QUC.js.map +1 -0
- package/dist/chunk-VUOLBHD7.js +19 -0
- package/dist/chunk-VUOLBHD7.js.map +1 -0
- package/dist/chunk-WL5KWYKS.js +49762 -0
- package/dist/chunk-WL5KWYKS.js.map +1 -0
- package/dist/cli.js +4753 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +4224 -0
- package/dist/index.js +99 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.ts +7 -0
- package/dist/node.js +11 -0
- package/dist/node.js.map +1 -0
- package/dist/pixel-audit-H5K6JK3X.js +218 -0
- package/dist/pixel-audit-H5K6JK3X.js.map +1 -0
- package/dist/registry-C0GJH7ZT.d.ts +46 -0
- package/dsh/client.js +1398 -0
- package/dsh/index.js +141 -0
- package/dsh/preview-tool.js +1931 -0
- package/dsh/spawnHidden.js +109 -0
- package/package.json +113 -0
- package/skills/pptwise/SKILL.md +100 -0
- package/skills/pptwise/SKILL.zh-CN.md +102 -0
- package/skills/pptwise/references/branding.md +18 -0
- package/skills/pptwise/references/branding.zh-CN.md +21 -0
- package/skills/pptwise/references/components.md +35 -0
- package/skills/pptwise/references/components.zh-CN.md +40 -0
- package/skills/pptwise/references/density.md +17 -0
- package/skills/pptwise/references/density.zh-CN.md +22 -0
- package/skills/pptwise/references/images.md +42 -0
- package/skills/pptwise/references/images.zh-CN.md +47 -0
- package/skills/pptwise/references/layouts.md +37 -0
- package/skills/pptwise/references/layouts.zh-CN.md +42 -0
- package/skills/pptwise/references/spec.md +107 -0
- package/skills/pptwise/references/spec.zh-CN.md +112 -0
- package/skills/pptwise/references/validate.md +82 -0
- package/skills/pptwise/references/validate.zh-CN.md +87 -0
- package/skills/pptwise/scripts/run.ps1 +192 -0
- package/skills/pptwise/scripts/run.sh +229 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4224 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export { P as PptwisePlatform, R as RasterizedImage, i as installPlatform } from './registry-C0GJH7ZT.js';
|
|
3
|
+
|
|
4
|
+
declare const VERSION = "0.22.0";
|
|
5
|
+
|
|
6
|
+
/** Error class thrown by pptwise's public API surface (validation, rendering, export). */
|
|
7
|
+
declare class PptwiseError extends Error {
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare const STRATEGY_VALUES: readonly ["pyramid", "storytelling", "instructional", "showcase", "briefing"];
|
|
11
|
+
declare const PACING_VALUES: readonly ["dense", "balanced", "spacious"];
|
|
12
|
+
declare const AUDIENCE_VALUES: readonly ["executive", "technical", "customer", "public"];
|
|
13
|
+
declare const BEAT_VALUES: readonly ["anchor", "dense", "breathing"];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The v4 IR schema root: theme/meta/assets/brand/branding/background/slide/narrative
|
|
17
|
+
* and the top-level `PptxIRSchema` a deck document parses against
|
|
18
|
+
* (`parsePptxIR`). The frozen v3 shape lives in `./legacy-v3.ts`, kept only
|
|
19
|
+
* for `migrateIrV3ToV4`'s input parsing (spec §9.3).
|
|
20
|
+
*
|
|
21
|
+
* **The `ComponentSchema` union below is a pure aggregator (src domain reorg
|
|
22
|
+
* wave 2, spec §4.3), same discipline as `src/svg/layouts/registry.ts`'s T1d
|
|
23
|
+
* precedent.** Every one of the component schemas used to live here as a
|
|
24
|
+
* literal `z.object({...})` entry directly inside the `discriminatedUnion`
|
|
25
|
+
* array. Each now lives in its own `src/ir/components/<name>.ts` domain file
|
|
26
|
+
* instead (schema + field aliases + render-trait declaration together, spec
|
|
27
|
+
* §4.1) — imported below and referenced by name, in the exact union position
|
|
28
|
+
* its literal used to occupy, so "take one component away whole" is a
|
|
29
|
+
* single-file operation instead of an edit split across this file,
|
|
30
|
+
* `field-aliases.ts`, and `component-traits.ts`. This file's own job for
|
|
31
|
+
* components is now purely computational: import every component schema, construct
|
|
32
|
+
* `ComponentSchema` via `z.discriminatedUnion`, and derive `COMPONENT_TYPES`
|
|
33
|
+
* from the result — never a hand-copied literal, never a re-export relay. A
|
|
34
|
+
* handful of schema fragments genuinely shared by ≥2 components (only the
|
|
35
|
+
* icon-name enum, as of this wave) live in `src/ir/components/shared.ts`
|
|
36
|
+
* instead of any one domain file; every other named sub-schema that reads as
|
|
37
|
+
* "shared" at a glance (e.g. `GanttItemSchema`, `PestQuadrantSchema`,
|
|
38
|
+
* `SankeyNodeSchema`/`SankeyLinkSchema`) turned out to be single-consumer and
|
|
39
|
+
* moved into its own component's domain file with it.
|
|
40
|
+
*
|
|
41
|
+
* The rest of this module — everything outside the `// ── Components` section
|
|
42
|
+
* — is unrelated to the component-domain split and was never in its scope:
|
|
43
|
+
* background/theme/meta/assets/brand/branding/slide/narrative and the top-level
|
|
44
|
+
* `PptxIRSchema` are genuinely this file's own content, not aggregated from
|
|
45
|
+
* elsewhere.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
declare const BUILTIN_THEME_IDS: readonly ["consulting", "enterprise", "academic", "insight", "campaign", "classroom", "ink", "tech", "runway", "journal", "luxe", "heritage", "pulse", "terra", "ember", "vermilion", "crayon", "arena", "museum", "stage", "lecture", "swiss", "memo", "playbill"];
|
|
49
|
+
declare const BackgroundSpecSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
50
|
+
kind: z.ZodLiteral<"color">;
|
|
51
|
+
value: z.ZodString;
|
|
52
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
53
|
+
kind: z.ZodLiteral<"gradient">;
|
|
54
|
+
from: z.ZodString;
|
|
55
|
+
to: z.ZodString;
|
|
56
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
57
|
+
tb: "tb";
|
|
58
|
+
lr: "lr";
|
|
59
|
+
diagonal: "diagonal";
|
|
60
|
+
}>>;
|
|
61
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
62
|
+
kind: z.ZodLiteral<"asset">;
|
|
63
|
+
asset_id: z.ZodString;
|
|
64
|
+
overlay: z.ZodOptional<z.ZodObject<{
|
|
65
|
+
color: z.ZodString;
|
|
66
|
+
opacity: z.ZodNumber;
|
|
67
|
+
}, z.core.$strict>>;
|
|
68
|
+
fit: z.ZodOptional<z.ZodEnum<{
|
|
69
|
+
contain: "contain";
|
|
70
|
+
cover: "cover";
|
|
71
|
+
}>>;
|
|
72
|
+
}, z.core.$strict>], "kind">;
|
|
73
|
+
/**
|
|
74
|
+
* Style-token override (theme.style): deep-partial palette/fonts/shape
|
|
75
|
+
* merged over the built-in theme (see themes/index.ts resolveStyle). Scope is
|
|
76
|
+
* deliberately palette-level (spec §11): no defaultBackgrounds or manifest
|
|
77
|
+
* overrides. gapScale / typeScale ranges mirror the documented sane ranges
|
|
78
|
+
* in themes/tokens.ts StyleShape.
|
|
79
|
+
*/
|
|
80
|
+
declare const StyleOverrideSchema: z.ZodObject<{
|
|
81
|
+
colors: z.ZodOptional<z.ZodObject<{
|
|
82
|
+
bg: z.ZodOptional<z.ZodString>;
|
|
83
|
+
surface: z.ZodOptional<z.ZodString>;
|
|
84
|
+
panel: z.ZodOptional<z.ZodString>;
|
|
85
|
+
primary: z.ZodOptional<z.ZodString>;
|
|
86
|
+
accent: z.ZodOptional<z.ZodString>;
|
|
87
|
+
text: z.ZodOptional<z.ZodString>;
|
|
88
|
+
muted: z.ZodOptional<z.ZodString>;
|
|
89
|
+
border: z.ZodOptional<z.ZodString>;
|
|
90
|
+
chartPalette: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
91
|
+
accentPool: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
92
|
+
cardStroke: z.ZodOptional<z.ZodString>;
|
|
93
|
+
}, z.core.$strict>>;
|
|
94
|
+
fonts: z.ZodOptional<z.ZodObject<{
|
|
95
|
+
heading: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
96
|
+
body: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
97
|
+
mono: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
98
|
+
}, z.core.$strict>>;
|
|
99
|
+
shape: z.ZodOptional<z.ZodObject<{
|
|
100
|
+
radius: z.ZodOptional<z.ZodNumber>;
|
|
101
|
+
gapScale: z.ZodOptional<z.ZodNumber>;
|
|
102
|
+
typeScale: z.ZodOptional<z.ZodNumber>;
|
|
103
|
+
}, z.core.$strict>>;
|
|
104
|
+
}, z.core.$strict>;
|
|
105
|
+
type StyleOverride = z.infer<typeof StyleOverrideSchema>;
|
|
106
|
+
/**
|
|
107
|
+
* Brand (logical slide-master) config: branding behavior owned by a theme.
|
|
108
|
+
* W1 scope was exactly the two flags migrated from the old theme-manifest footer flags;
|
|
109
|
+
* the ink v3 redesign (2026-08-18) added a third, orthogonal one.
|
|
110
|
+
* Single source of truth — the TS type is inferred, never hand-written.
|
|
111
|
+
*
|
|
112
|
+
* All three are independent switches, not a ladder: a theme may set any
|
|
113
|
+
* combination, and each names exactly one piece of brand footer. They are
|
|
114
|
+
* deliberately not collapsed into one "footer style" enum — a theme that
|
|
115
|
+
* draws its own divider is a different situation from one whose motif
|
|
116
|
+
* already carries the org/date, and merging them would force one to imply
|
|
117
|
+
* the other.
|
|
118
|
+
*/
|
|
119
|
+
declare const BrandConfigSchema: z.ZodObject<{
|
|
120
|
+
suppressFooterOnCardContent: z.ZodOptional<z.ZodBoolean>;
|
|
121
|
+
suppressFooterRule: z.ZodOptional<z.ZodBoolean>;
|
|
122
|
+
suppressFooterMeta: z.ZodOptional<z.ZodBoolean>;
|
|
123
|
+
}, z.core.$strict>;
|
|
124
|
+
type BrandConfig = z.infer<typeof BrandConfigSchema>;
|
|
125
|
+
declare const ThemeSchema: z.ZodObject<{
|
|
126
|
+
id: z.ZodDefault<z.ZodString>;
|
|
127
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
128
|
+
colors: z.ZodOptional<z.ZodObject<{
|
|
129
|
+
bg: z.ZodOptional<z.ZodString>;
|
|
130
|
+
surface: z.ZodOptional<z.ZodString>;
|
|
131
|
+
panel: z.ZodOptional<z.ZodString>;
|
|
132
|
+
primary: z.ZodOptional<z.ZodString>;
|
|
133
|
+
accent: z.ZodOptional<z.ZodString>;
|
|
134
|
+
text: z.ZodOptional<z.ZodString>;
|
|
135
|
+
muted: z.ZodOptional<z.ZodString>;
|
|
136
|
+
border: z.ZodOptional<z.ZodString>;
|
|
137
|
+
chartPalette: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
138
|
+
accentPool: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
139
|
+
cardStroke: z.ZodOptional<z.ZodString>;
|
|
140
|
+
}, z.core.$strict>>;
|
|
141
|
+
fonts: z.ZodOptional<z.ZodObject<{
|
|
142
|
+
heading: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
143
|
+
body: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
144
|
+
mono: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
145
|
+
}, z.core.$strict>>;
|
|
146
|
+
shape: z.ZodOptional<z.ZodObject<{
|
|
147
|
+
radius: z.ZodOptional<z.ZodNumber>;
|
|
148
|
+
gapScale: z.ZodOptional<z.ZodNumber>;
|
|
149
|
+
typeScale: z.ZodOptional<z.ZodNumber>;
|
|
150
|
+
}, z.core.$strict>>;
|
|
151
|
+
}, z.core.$strict>>;
|
|
152
|
+
brand: z.ZodOptional<z.ZodObject<{
|
|
153
|
+
suppressFooterOnCardContent: z.ZodOptional<z.ZodBoolean>;
|
|
154
|
+
suppressFooterRule: z.ZodOptional<z.ZodBoolean>;
|
|
155
|
+
suppressFooterMeta: z.ZodOptional<z.ZodBoolean>;
|
|
156
|
+
}, z.core.$strict>>;
|
|
157
|
+
}, z.core.$strict>;
|
|
158
|
+
declare const MetaSchema: z.ZodObject<{
|
|
159
|
+
organization: z.ZodOptional<z.ZodString>;
|
|
160
|
+
authors: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
161
|
+
name: z.ZodString;
|
|
162
|
+
role: z.ZodOptional<z.ZodString>;
|
|
163
|
+
org: z.ZodOptional<z.ZodString>;
|
|
164
|
+
}, z.core.$strict>>>;
|
|
165
|
+
date: z.ZodOptional<z.ZodString>;
|
|
166
|
+
version: z.ZodOptional<z.ZodString>;
|
|
167
|
+
confidentiality: z.ZodOptional<z.ZodEnum<{
|
|
168
|
+
public: "public";
|
|
169
|
+
internal: "internal";
|
|
170
|
+
confidential: "confidential";
|
|
171
|
+
restricted: "restricted";
|
|
172
|
+
}>>;
|
|
173
|
+
contact: z.ZodOptional<z.ZodObject<{
|
|
174
|
+
name: z.ZodOptional<z.ZodString>;
|
|
175
|
+
email: z.ZodOptional<z.ZodString>;
|
|
176
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
177
|
+
website: z.ZodOptional<z.ZodString>;
|
|
178
|
+
}, z.core.$strict>>;
|
|
179
|
+
copyright: z.ZodOptional<z.ZodString>;
|
|
180
|
+
animation: z.ZodOptional<z.ZodObject<{
|
|
181
|
+
transition: z.ZodOptional<z.ZodEnum<{
|
|
182
|
+
push: "push";
|
|
183
|
+
none: "none";
|
|
184
|
+
fade: "fade";
|
|
185
|
+
wipe: "wipe";
|
|
186
|
+
}>>;
|
|
187
|
+
elements: z.ZodOptional<z.ZodEnum<{
|
|
188
|
+
none: "none";
|
|
189
|
+
auto: "auto";
|
|
190
|
+
}>>;
|
|
191
|
+
}, z.core.$strict>>;
|
|
192
|
+
}, z.core.$strict>;
|
|
193
|
+
declare const AssetsSchema: z.ZodObject<{
|
|
194
|
+
images: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
195
|
+
src: z.ZodString;
|
|
196
|
+
alt: z.ZodOptional<z.ZodString>;
|
|
197
|
+
error: z.ZodOptional<z.ZodString>;
|
|
198
|
+
}, z.core.$strict>>>;
|
|
199
|
+
}, z.core.$strict>;
|
|
200
|
+
declare const ComponentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
201
|
+
type: z.ZodLiteral<"bullets">;
|
|
202
|
+
items: z.ZodArray<z.ZodString>;
|
|
203
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
204
|
+
default: "default";
|
|
205
|
+
checklist: "checklist";
|
|
206
|
+
numbered: "numbered";
|
|
207
|
+
plain: "plain";
|
|
208
|
+
divided: "divided";
|
|
209
|
+
}>>;
|
|
210
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
211
|
+
type: z.ZodLiteral<"paragraph">;
|
|
212
|
+
text: z.ZodString;
|
|
213
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
214
|
+
type: z.ZodLiteral<"quote">;
|
|
215
|
+
text: z.ZodString;
|
|
216
|
+
attribution: z.ZodOptional<z.ZodString>;
|
|
217
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
218
|
+
type: z.ZodLiteral<"callout">;
|
|
219
|
+
variant: z.ZodEnum<{
|
|
220
|
+
info: "info";
|
|
221
|
+
warn: "warn";
|
|
222
|
+
tip: "tip";
|
|
223
|
+
}>;
|
|
224
|
+
text: z.ZodString;
|
|
225
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
226
|
+
[x: string]: string;
|
|
227
|
+
}>>;
|
|
228
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
229
|
+
type: z.ZodLiteral<"code">;
|
|
230
|
+
language: z.ZodString;
|
|
231
|
+
code: z.ZodString;
|
|
232
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
233
|
+
type: z.ZodLiteral<"kpi_cards">;
|
|
234
|
+
items: z.ZodArray<z.ZodObject<{
|
|
235
|
+
value: z.ZodString;
|
|
236
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
237
|
+
label: z.ZodString;
|
|
238
|
+
delta: z.ZodOptional<z.ZodEnum<{
|
|
239
|
+
flat: "flat";
|
|
240
|
+
up: "up";
|
|
241
|
+
down: "down";
|
|
242
|
+
}>>;
|
|
243
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
244
|
+
[x: string]: string;
|
|
245
|
+
}>>;
|
|
246
|
+
source: z.ZodOptional<z.ZodString>;
|
|
247
|
+
}, z.core.$strict>>;
|
|
248
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
249
|
+
type: z.ZodLiteral<"chart">;
|
|
250
|
+
chart_type: z.ZodEnum<{
|
|
251
|
+
line: "line";
|
|
252
|
+
donut: "donut";
|
|
253
|
+
dumbbell: "dumbbell";
|
|
254
|
+
funnel: "funnel";
|
|
255
|
+
gauge: "gauge";
|
|
256
|
+
bar: "bar";
|
|
257
|
+
pie: "pie";
|
|
258
|
+
scatter: "scatter";
|
|
259
|
+
area: "area";
|
|
260
|
+
}>;
|
|
261
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
262
|
+
horizontal: "horizontal";
|
|
263
|
+
vertical: "vertical";
|
|
264
|
+
}>>;
|
|
265
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
266
|
+
donut: "donut";
|
|
267
|
+
}>>;
|
|
268
|
+
center_total: z.ZodOptional<z.ZodBoolean>;
|
|
269
|
+
gauge: z.ZodOptional<z.ZodObject<{
|
|
270
|
+
min: z.ZodOptional<z.ZodNumber>;
|
|
271
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
272
|
+
}, z.core.$strict>>;
|
|
273
|
+
axes: z.ZodOptional<z.ZodObject<{
|
|
274
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
275
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
276
|
+
show_grid: z.ZodOptional<z.ZodBoolean>;
|
|
277
|
+
}, z.core.$strict>>;
|
|
278
|
+
series: z.ZodArray<z.ZodObject<{
|
|
279
|
+
name: z.ZodString;
|
|
280
|
+
data: z.ZodArray<z.ZodObject<{
|
|
281
|
+
x: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
282
|
+
y: z.ZodNumber;
|
|
283
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
284
|
+
}, z.core.$strict>>;
|
|
285
|
+
}, z.core.$strict>>;
|
|
286
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
287
|
+
type: z.ZodLiteral<"flowchart">;
|
|
288
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
289
|
+
id: z.ZodString;
|
|
290
|
+
label: z.ZodString;
|
|
291
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
292
|
+
rect: "rect";
|
|
293
|
+
diamond: "diamond";
|
|
294
|
+
round: "round";
|
|
295
|
+
}>>;
|
|
296
|
+
}, z.core.$strict>>;
|
|
297
|
+
edges: z.ZodArray<z.ZodObject<{
|
|
298
|
+
from: z.ZodString;
|
|
299
|
+
to: z.ZodString;
|
|
300
|
+
label: z.ZodOptional<z.ZodString>;
|
|
301
|
+
}, z.core.$strict>>;
|
|
302
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
303
|
+
TB: "TB";
|
|
304
|
+
TD: "TD";
|
|
305
|
+
BT: "BT";
|
|
306
|
+
LR: "LR";
|
|
307
|
+
RL: "RL";
|
|
308
|
+
}>>;
|
|
309
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
310
|
+
type: z.ZodLiteral<"architecture">;
|
|
311
|
+
layers: z.ZodArray<z.ZodObject<{
|
|
312
|
+
title: z.ZodString;
|
|
313
|
+
items: z.ZodArray<z.ZodString>;
|
|
314
|
+
}, z.core.$strict>>;
|
|
315
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
316
|
+
top_down: "top_down";
|
|
317
|
+
bottom_up: "bottom_up";
|
|
318
|
+
}>>;
|
|
319
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
320
|
+
type: z.ZodLiteral<"timeline">;
|
|
321
|
+
layout: z.ZodOptional<z.ZodEnum<{
|
|
322
|
+
horizontal: "horizontal";
|
|
323
|
+
vertical: "vertical";
|
|
324
|
+
}>>;
|
|
325
|
+
milestones: z.ZodArray<z.ZodObject<{
|
|
326
|
+
date: z.ZodString;
|
|
327
|
+
title: z.ZodString;
|
|
328
|
+
desc: z.ZodOptional<z.ZodString>;
|
|
329
|
+
highlight: z.ZodOptional<z.ZodBoolean>;
|
|
330
|
+
}, z.core.$strict>>;
|
|
331
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
332
|
+
type: z.ZodLiteral<"comparison">;
|
|
333
|
+
columns: z.ZodArray<z.ZodString>;
|
|
334
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
335
|
+
label: z.ZodString;
|
|
336
|
+
cells: z.ZodArray<z.ZodString>;
|
|
337
|
+
}, z.core.$strict>>;
|
|
338
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
339
|
+
type: z.ZodLiteral<"icon_cards">;
|
|
340
|
+
items: z.ZodArray<z.ZodObject<{
|
|
341
|
+
icon: z.ZodEnum<{
|
|
342
|
+
[x: string]: string;
|
|
343
|
+
}>;
|
|
344
|
+
title: z.ZodString;
|
|
345
|
+
text: z.ZodString;
|
|
346
|
+
}, z.core.$strict>>;
|
|
347
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
348
|
+
type: z.ZodLiteral<"row_cards">;
|
|
349
|
+
items: z.ZodArray<z.ZodObject<{
|
|
350
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
351
|
+
[x: string]: string;
|
|
352
|
+
}>>;
|
|
353
|
+
title: z.ZodString;
|
|
354
|
+
text: z.ZodOptional<z.ZodString>;
|
|
355
|
+
sub: z.ZodOptional<z.ZodString>;
|
|
356
|
+
highlight: z.ZodOptional<z.ZodBoolean>;
|
|
357
|
+
}, z.core.$strict>>;
|
|
358
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
359
|
+
type: z.ZodLiteral<"steps">;
|
|
360
|
+
items: z.ZodArray<z.ZodObject<{
|
|
361
|
+
title: z.ZodString;
|
|
362
|
+
text: z.ZodString;
|
|
363
|
+
}, z.core.$strict>>;
|
|
364
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
365
|
+
type: z.ZodLiteral<"rings">;
|
|
366
|
+
items: z.ZodArray<z.ZodObject<{
|
|
367
|
+
label: z.ZodString;
|
|
368
|
+
desc: z.ZodOptional<z.ZodString>;
|
|
369
|
+
}, z.core.$strict>>;
|
|
370
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
371
|
+
type: z.ZodLiteral<"numbered_cards">;
|
|
372
|
+
items: z.ZodArray<z.ZodObject<{
|
|
373
|
+
title: z.ZodString;
|
|
374
|
+
text: z.ZodOptional<z.ZodString>;
|
|
375
|
+
sub: z.ZodOptional<z.ZodString>;
|
|
376
|
+
}, z.core.$strict>>;
|
|
377
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
378
|
+
type: z.ZodLiteral<"roadmap">;
|
|
379
|
+
items: z.ZodArray<z.ZodObject<{
|
|
380
|
+
title: z.ZodString;
|
|
381
|
+
period: z.ZodOptional<z.ZodString>;
|
|
382
|
+
rows: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
383
|
+
label: z.ZodString;
|
|
384
|
+
value: z.ZodString;
|
|
385
|
+
}, z.core.$strict>>>;
|
|
386
|
+
}, z.core.$strict>>;
|
|
387
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
388
|
+
type: z.ZodLiteral<"matrix">;
|
|
389
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
390
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
391
|
+
cols: z.ZodNumber;
|
|
392
|
+
items: z.ZodArray<z.ZodObject<{
|
|
393
|
+
title: z.ZodString;
|
|
394
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
395
|
+
tone: z.ZodOptional<z.ZodEnum<{
|
|
396
|
+
info: "info";
|
|
397
|
+
neutral: "neutral";
|
|
398
|
+
accent: "accent";
|
|
399
|
+
}>>;
|
|
400
|
+
}, z.core.$strict>>;
|
|
401
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
402
|
+
type: z.ZodLiteral<"insight_panel">;
|
|
403
|
+
title: z.ZodString;
|
|
404
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
405
|
+
label: z.ZodString;
|
|
406
|
+
text: z.ZodString;
|
|
407
|
+
}, z.core.$strict>>;
|
|
408
|
+
footnote: z.ZodOptional<z.ZodString>;
|
|
409
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
410
|
+
type: z.ZodLiteral<"verdict_banner">;
|
|
411
|
+
text: z.ZodString;
|
|
412
|
+
tone: z.ZodEnum<{
|
|
413
|
+
positive: "positive";
|
|
414
|
+
warning: "warning";
|
|
415
|
+
neutral: "neutral";
|
|
416
|
+
}>;
|
|
417
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
418
|
+
[x: string]: string;
|
|
419
|
+
}>>;
|
|
420
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
421
|
+
type: z.ZodLiteral<"citation">;
|
|
422
|
+
sources: z.ZodArray<z.ZodObject<{
|
|
423
|
+
label: z.ZodString;
|
|
424
|
+
url: z.ZodOptional<z.ZodString>;
|
|
425
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
426
|
+
}, z.core.$strict>>;
|
|
427
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
428
|
+
type: z.ZodLiteral<"image">;
|
|
429
|
+
asset_id: z.ZodString;
|
|
430
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
431
|
+
fit: z.ZodDefault<z.ZodEnum<{
|
|
432
|
+
contain: "contain";
|
|
433
|
+
cover: "cover";
|
|
434
|
+
}>>;
|
|
435
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
436
|
+
type: z.ZodLiteral<"image_grid">;
|
|
437
|
+
items: z.ZodArray<z.ZodObject<{
|
|
438
|
+
asset_id: z.ZodString;
|
|
439
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
440
|
+
}, z.core.$strict>>;
|
|
441
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
442
|
+
none: "none";
|
|
443
|
+
first: "first";
|
|
444
|
+
}>>;
|
|
445
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
446
|
+
type: z.ZodLiteral<"image_compare">;
|
|
447
|
+
left: z.ZodObject<{
|
|
448
|
+
asset_id: z.ZodString;
|
|
449
|
+
label: z.ZodString;
|
|
450
|
+
}, z.core.$strict>;
|
|
451
|
+
right: z.ZodObject<{
|
|
452
|
+
asset_id: z.ZodString;
|
|
453
|
+
label: z.ZodString;
|
|
454
|
+
}, z.core.$strict>;
|
|
455
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
456
|
+
vs: "vs";
|
|
457
|
+
before_after: "before_after";
|
|
458
|
+
}>>;
|
|
459
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
460
|
+
type: z.ZodLiteral<"swot">;
|
|
461
|
+
strengths: z.ZodArray<z.ZodString>;
|
|
462
|
+
weaknesses: z.ZodArray<z.ZodString>;
|
|
463
|
+
opportunities: z.ZodArray<z.ZodString>;
|
|
464
|
+
threats: z.ZodArray<z.ZodString>;
|
|
465
|
+
labels: z.ZodOptional<z.ZodObject<{
|
|
466
|
+
strengths: z.ZodOptional<z.ZodString>;
|
|
467
|
+
weaknesses: z.ZodOptional<z.ZodString>;
|
|
468
|
+
opportunities: z.ZodOptional<z.ZodString>;
|
|
469
|
+
threats: z.ZodOptional<z.ZodString>;
|
|
470
|
+
}, z.core.$strict>>;
|
|
471
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
472
|
+
type: z.ZodLiteral<"bmc">;
|
|
473
|
+
key_partners: z.ZodArray<z.ZodString>;
|
|
474
|
+
key_activities: z.ZodArray<z.ZodString>;
|
|
475
|
+
key_resources: z.ZodArray<z.ZodString>;
|
|
476
|
+
value_propositions: z.ZodArray<z.ZodString>;
|
|
477
|
+
customer_relationships: z.ZodArray<z.ZodString>;
|
|
478
|
+
channels: z.ZodArray<z.ZodString>;
|
|
479
|
+
customer_segments: z.ZodArray<z.ZodString>;
|
|
480
|
+
cost_structure: z.ZodArray<z.ZodString>;
|
|
481
|
+
revenue_streams: z.ZodArray<z.ZodString>;
|
|
482
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
483
|
+
type: z.ZodLiteral<"waterfall">;
|
|
484
|
+
items: z.ZodArray<z.ZodObject<{
|
|
485
|
+
label: z.ZodString;
|
|
486
|
+
value: z.ZodNumber;
|
|
487
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
488
|
+
delta: "delta";
|
|
489
|
+
total: "total";
|
|
490
|
+
}>>;
|
|
491
|
+
}, z.core.$strict>>;
|
|
492
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
493
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
494
|
+
type: z.ZodLiteral<"gantt">;
|
|
495
|
+
items: z.ZodArray<z.ZodObject<{
|
|
496
|
+
label: z.ZodString;
|
|
497
|
+
start: z.ZodNumber;
|
|
498
|
+
end: z.ZodNumber;
|
|
499
|
+
}, z.core.$strict>>;
|
|
500
|
+
axis_labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
501
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
502
|
+
type: z.ZodLiteral<"pest">;
|
|
503
|
+
political: z.ZodObject<{
|
|
504
|
+
title: z.ZodOptional<z.ZodString>;
|
|
505
|
+
items: z.ZodArray<z.ZodString>;
|
|
506
|
+
}, z.core.$strict>;
|
|
507
|
+
economic: z.ZodObject<{
|
|
508
|
+
title: z.ZodOptional<z.ZodString>;
|
|
509
|
+
items: z.ZodArray<z.ZodString>;
|
|
510
|
+
}, z.core.$strict>;
|
|
511
|
+
social: z.ZodObject<{
|
|
512
|
+
title: z.ZodOptional<z.ZodString>;
|
|
513
|
+
items: z.ZodArray<z.ZodString>;
|
|
514
|
+
}, z.core.$strict>;
|
|
515
|
+
technological: z.ZodObject<{
|
|
516
|
+
title: z.ZodOptional<z.ZodString>;
|
|
517
|
+
items: z.ZodArray<z.ZodString>;
|
|
518
|
+
}, z.core.$strict>;
|
|
519
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
520
|
+
type: z.ZodLiteral<"five_forces">;
|
|
521
|
+
rivalry: z.ZodObject<{
|
|
522
|
+
label: z.ZodOptional<z.ZodString>;
|
|
523
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
524
|
+
low: "low";
|
|
525
|
+
medium: "medium";
|
|
526
|
+
high: "high";
|
|
527
|
+
}>>;
|
|
528
|
+
items: z.ZodArray<z.ZodString>;
|
|
529
|
+
}, z.core.$strict>;
|
|
530
|
+
new_entrants: z.ZodObject<{
|
|
531
|
+
label: z.ZodOptional<z.ZodString>;
|
|
532
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
533
|
+
low: "low";
|
|
534
|
+
medium: "medium";
|
|
535
|
+
high: "high";
|
|
536
|
+
}>>;
|
|
537
|
+
items: z.ZodArray<z.ZodString>;
|
|
538
|
+
}, z.core.$strict>;
|
|
539
|
+
supplier_power: z.ZodObject<{
|
|
540
|
+
label: z.ZodOptional<z.ZodString>;
|
|
541
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
542
|
+
low: "low";
|
|
543
|
+
medium: "medium";
|
|
544
|
+
high: "high";
|
|
545
|
+
}>>;
|
|
546
|
+
items: z.ZodArray<z.ZodString>;
|
|
547
|
+
}, z.core.$strict>;
|
|
548
|
+
buyer_power: z.ZodObject<{
|
|
549
|
+
label: z.ZodOptional<z.ZodString>;
|
|
550
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
551
|
+
low: "low";
|
|
552
|
+
medium: "medium";
|
|
553
|
+
high: "high";
|
|
554
|
+
}>>;
|
|
555
|
+
items: z.ZodArray<z.ZodString>;
|
|
556
|
+
}, z.core.$strict>;
|
|
557
|
+
substitutes: z.ZodObject<{
|
|
558
|
+
label: z.ZodOptional<z.ZodString>;
|
|
559
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
560
|
+
low: "low";
|
|
561
|
+
medium: "medium";
|
|
562
|
+
high: "high";
|
|
563
|
+
}>>;
|
|
564
|
+
items: z.ZodArray<z.ZodString>;
|
|
565
|
+
}, z.core.$strict>;
|
|
566
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
567
|
+
type: z.ZodLiteral<"heatmap">;
|
|
568
|
+
x_labels: z.ZodArray<z.ZodString>;
|
|
569
|
+
y_labels: z.ZodArray<z.ZodString>;
|
|
570
|
+
values: z.ZodArray<z.ZodArray<z.ZodNumber>>;
|
|
571
|
+
domain: z.ZodOptional<z.ZodObject<{
|
|
572
|
+
min: z.ZodNumber;
|
|
573
|
+
max: z.ZodNumber;
|
|
574
|
+
}, z.core.$strict>>;
|
|
575
|
+
show_values: z.ZodOptional<z.ZodBoolean>;
|
|
576
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
577
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
578
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
579
|
+
type: z.ZodLiteral<"sankey">;
|
|
580
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
581
|
+
id: z.ZodString;
|
|
582
|
+
label: z.ZodString;
|
|
583
|
+
}, z.core.$strict>>;
|
|
584
|
+
links: z.ZodArray<z.ZodObject<{
|
|
585
|
+
from: z.ZodString;
|
|
586
|
+
to: z.ZodString;
|
|
587
|
+
value: z.ZodNumber;
|
|
588
|
+
}, z.core.$strict>>;
|
|
589
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
590
|
+
type: z.ZodLiteral<"data_table">;
|
|
591
|
+
columns: z.ZodArray<z.ZodObject<{
|
|
592
|
+
key: z.ZodString;
|
|
593
|
+
label: z.ZodString;
|
|
594
|
+
align: z.ZodOptional<z.ZodEnum<{
|
|
595
|
+
left: "left";
|
|
596
|
+
right: "right";
|
|
597
|
+
center: "center";
|
|
598
|
+
}>>;
|
|
599
|
+
}, z.core.$strict>>;
|
|
600
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
601
|
+
cells: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
602
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
603
|
+
highlight: "highlight";
|
|
604
|
+
total: "total";
|
|
605
|
+
}>>;
|
|
606
|
+
}, z.core.$strict>>;
|
|
607
|
+
source: z.ZodOptional<z.ZodString>;
|
|
608
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
609
|
+
type: z.ZodLiteral<"device_mockup">;
|
|
610
|
+
device: z.ZodEnum<{
|
|
611
|
+
phone: "phone";
|
|
612
|
+
browser: "browser";
|
|
613
|
+
}>;
|
|
614
|
+
asset_id: z.ZodString;
|
|
615
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
616
|
+
url: z.ZodOptional<z.ZodString>;
|
|
617
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
618
|
+
type: z.ZodLiteral<"cycle">;
|
|
619
|
+
title: z.ZodOptional<z.ZodString>;
|
|
620
|
+
items: z.ZodArray<z.ZodObject<{
|
|
621
|
+
label: z.ZodString;
|
|
622
|
+
description: z.ZodOptional<z.ZodString>;
|
|
623
|
+
}, z.core.$strict>>;
|
|
624
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
625
|
+
type: z.ZodLiteral<"people_cards">;
|
|
626
|
+
title: z.ZodOptional<z.ZodString>;
|
|
627
|
+
people: z.ZodArray<z.ZodObject<{
|
|
628
|
+
name: z.ZodString;
|
|
629
|
+
role: z.ZodOptional<z.ZodString>;
|
|
630
|
+
org: z.ZodOptional<z.ZodString>;
|
|
631
|
+
}, z.core.$strict>>;
|
|
632
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
633
|
+
type: z.ZodLiteral<"tag_row">;
|
|
634
|
+
title: z.ZodOptional<z.ZodString>;
|
|
635
|
+
items: z.ZodArray<z.ZodString>;
|
|
636
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
637
|
+
none: "none";
|
|
638
|
+
first: "first";
|
|
639
|
+
}>>;
|
|
640
|
+
}, z.core.$strict>], "type">;
|
|
641
|
+
/**
|
|
642
|
+
* All component `type` discriminant values, derived from `ComponentSchema`
|
|
643
|
+
* itself (never hand-copied) so this list can't drift from the union above.
|
|
644
|
+
* Typed as plain `readonly string[]` rather than `Component["type"][]` —
|
|
645
|
+
* every consumer of this list (W5's plan `focus` vocabulary gate,
|
|
646
|
+
* `src/spec/index.ts`) tests membership of an arbitrary author-supplied
|
|
647
|
+
* string, and TS's `Array.includes` is invariant in its element type, so a
|
|
648
|
+
* narrower literal-union type would reject that call at the caller.
|
|
649
|
+
*/
|
|
650
|
+
declare const COMPONENT_TYPES: readonly string[];
|
|
651
|
+
declare const SlideSchema: z.ZodObject<{
|
|
652
|
+
type: z.ZodDefault<z.ZodEnum<{
|
|
653
|
+
content: "content";
|
|
654
|
+
cover: "cover";
|
|
655
|
+
chapter: "chapter";
|
|
656
|
+
ending: "ending";
|
|
657
|
+
}>>;
|
|
658
|
+
id: z.ZodOptional<z.ZodString>;
|
|
659
|
+
placeholder: z.ZodOptional<z.ZodLiteral<true>>;
|
|
660
|
+
layout: z.ZodOptional<z.ZodString>;
|
|
661
|
+
beat: z.ZodOptional<z.ZodEnum<{
|
|
662
|
+
dense: "dense";
|
|
663
|
+
anchor: "anchor";
|
|
664
|
+
breathing: "breathing";
|
|
665
|
+
}>>;
|
|
666
|
+
arrangement: z.ZodOptional<z.ZodEnum<{
|
|
667
|
+
code: "code";
|
|
668
|
+
quote: "quote";
|
|
669
|
+
single: "single";
|
|
670
|
+
two_column: "two_column";
|
|
671
|
+
kpi_focus: "kpi_focus";
|
|
672
|
+
image_focus: "image_focus";
|
|
673
|
+
big_number: "big_number";
|
|
674
|
+
assertion_evidence: "assertion_evidence";
|
|
675
|
+
aside: "aside";
|
|
676
|
+
}>>;
|
|
677
|
+
heading: z.ZodOptional<z.ZodString>;
|
|
678
|
+
subheading: z.ZodOptional<z.ZodString>;
|
|
679
|
+
components: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
680
|
+
type: z.ZodLiteral<"bullets">;
|
|
681
|
+
items: z.ZodArray<z.ZodString>;
|
|
682
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
683
|
+
default: "default";
|
|
684
|
+
checklist: "checklist";
|
|
685
|
+
numbered: "numbered";
|
|
686
|
+
plain: "plain";
|
|
687
|
+
divided: "divided";
|
|
688
|
+
}>>;
|
|
689
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
690
|
+
type: z.ZodLiteral<"paragraph">;
|
|
691
|
+
text: z.ZodString;
|
|
692
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
693
|
+
type: z.ZodLiteral<"quote">;
|
|
694
|
+
text: z.ZodString;
|
|
695
|
+
attribution: z.ZodOptional<z.ZodString>;
|
|
696
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
697
|
+
type: z.ZodLiteral<"callout">;
|
|
698
|
+
variant: z.ZodEnum<{
|
|
699
|
+
info: "info";
|
|
700
|
+
warn: "warn";
|
|
701
|
+
tip: "tip";
|
|
702
|
+
}>;
|
|
703
|
+
text: z.ZodString;
|
|
704
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
705
|
+
[x: string]: string;
|
|
706
|
+
}>>;
|
|
707
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
708
|
+
type: z.ZodLiteral<"code">;
|
|
709
|
+
language: z.ZodString;
|
|
710
|
+
code: z.ZodString;
|
|
711
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
712
|
+
type: z.ZodLiteral<"kpi_cards">;
|
|
713
|
+
items: z.ZodArray<z.ZodObject<{
|
|
714
|
+
value: z.ZodString;
|
|
715
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
716
|
+
label: z.ZodString;
|
|
717
|
+
delta: z.ZodOptional<z.ZodEnum<{
|
|
718
|
+
flat: "flat";
|
|
719
|
+
up: "up";
|
|
720
|
+
down: "down";
|
|
721
|
+
}>>;
|
|
722
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
723
|
+
[x: string]: string;
|
|
724
|
+
}>>;
|
|
725
|
+
source: z.ZodOptional<z.ZodString>;
|
|
726
|
+
}, z.core.$strict>>;
|
|
727
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
728
|
+
type: z.ZodLiteral<"chart">;
|
|
729
|
+
chart_type: z.ZodEnum<{
|
|
730
|
+
line: "line";
|
|
731
|
+
donut: "donut";
|
|
732
|
+
dumbbell: "dumbbell";
|
|
733
|
+
funnel: "funnel";
|
|
734
|
+
gauge: "gauge";
|
|
735
|
+
bar: "bar";
|
|
736
|
+
pie: "pie";
|
|
737
|
+
scatter: "scatter";
|
|
738
|
+
area: "area";
|
|
739
|
+
}>;
|
|
740
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
741
|
+
horizontal: "horizontal";
|
|
742
|
+
vertical: "vertical";
|
|
743
|
+
}>>;
|
|
744
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
745
|
+
donut: "donut";
|
|
746
|
+
}>>;
|
|
747
|
+
center_total: z.ZodOptional<z.ZodBoolean>;
|
|
748
|
+
gauge: z.ZodOptional<z.ZodObject<{
|
|
749
|
+
min: z.ZodOptional<z.ZodNumber>;
|
|
750
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
751
|
+
}, z.core.$strict>>;
|
|
752
|
+
axes: z.ZodOptional<z.ZodObject<{
|
|
753
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
754
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
755
|
+
show_grid: z.ZodOptional<z.ZodBoolean>;
|
|
756
|
+
}, z.core.$strict>>;
|
|
757
|
+
series: z.ZodArray<z.ZodObject<{
|
|
758
|
+
name: z.ZodString;
|
|
759
|
+
data: z.ZodArray<z.ZodObject<{
|
|
760
|
+
x: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
761
|
+
y: z.ZodNumber;
|
|
762
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
763
|
+
}, z.core.$strict>>;
|
|
764
|
+
}, z.core.$strict>>;
|
|
765
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
766
|
+
type: z.ZodLiteral<"flowchart">;
|
|
767
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
768
|
+
id: z.ZodString;
|
|
769
|
+
label: z.ZodString;
|
|
770
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
771
|
+
rect: "rect";
|
|
772
|
+
diamond: "diamond";
|
|
773
|
+
round: "round";
|
|
774
|
+
}>>;
|
|
775
|
+
}, z.core.$strict>>;
|
|
776
|
+
edges: z.ZodArray<z.ZodObject<{
|
|
777
|
+
from: z.ZodString;
|
|
778
|
+
to: z.ZodString;
|
|
779
|
+
label: z.ZodOptional<z.ZodString>;
|
|
780
|
+
}, z.core.$strict>>;
|
|
781
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
782
|
+
TB: "TB";
|
|
783
|
+
TD: "TD";
|
|
784
|
+
BT: "BT";
|
|
785
|
+
LR: "LR";
|
|
786
|
+
RL: "RL";
|
|
787
|
+
}>>;
|
|
788
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
789
|
+
type: z.ZodLiteral<"architecture">;
|
|
790
|
+
layers: z.ZodArray<z.ZodObject<{
|
|
791
|
+
title: z.ZodString;
|
|
792
|
+
items: z.ZodArray<z.ZodString>;
|
|
793
|
+
}, z.core.$strict>>;
|
|
794
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
795
|
+
top_down: "top_down";
|
|
796
|
+
bottom_up: "bottom_up";
|
|
797
|
+
}>>;
|
|
798
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
799
|
+
type: z.ZodLiteral<"timeline">;
|
|
800
|
+
layout: z.ZodOptional<z.ZodEnum<{
|
|
801
|
+
horizontal: "horizontal";
|
|
802
|
+
vertical: "vertical";
|
|
803
|
+
}>>;
|
|
804
|
+
milestones: z.ZodArray<z.ZodObject<{
|
|
805
|
+
date: z.ZodString;
|
|
806
|
+
title: z.ZodString;
|
|
807
|
+
desc: z.ZodOptional<z.ZodString>;
|
|
808
|
+
highlight: z.ZodOptional<z.ZodBoolean>;
|
|
809
|
+
}, z.core.$strict>>;
|
|
810
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
811
|
+
type: z.ZodLiteral<"comparison">;
|
|
812
|
+
columns: z.ZodArray<z.ZodString>;
|
|
813
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
814
|
+
label: z.ZodString;
|
|
815
|
+
cells: z.ZodArray<z.ZodString>;
|
|
816
|
+
}, z.core.$strict>>;
|
|
817
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
818
|
+
type: z.ZodLiteral<"icon_cards">;
|
|
819
|
+
items: z.ZodArray<z.ZodObject<{
|
|
820
|
+
icon: z.ZodEnum<{
|
|
821
|
+
[x: string]: string;
|
|
822
|
+
}>;
|
|
823
|
+
title: z.ZodString;
|
|
824
|
+
text: z.ZodString;
|
|
825
|
+
}, z.core.$strict>>;
|
|
826
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
827
|
+
type: z.ZodLiteral<"row_cards">;
|
|
828
|
+
items: z.ZodArray<z.ZodObject<{
|
|
829
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
830
|
+
[x: string]: string;
|
|
831
|
+
}>>;
|
|
832
|
+
title: z.ZodString;
|
|
833
|
+
text: z.ZodOptional<z.ZodString>;
|
|
834
|
+
sub: z.ZodOptional<z.ZodString>;
|
|
835
|
+
highlight: z.ZodOptional<z.ZodBoolean>;
|
|
836
|
+
}, z.core.$strict>>;
|
|
837
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
838
|
+
type: z.ZodLiteral<"steps">;
|
|
839
|
+
items: z.ZodArray<z.ZodObject<{
|
|
840
|
+
title: z.ZodString;
|
|
841
|
+
text: z.ZodString;
|
|
842
|
+
}, z.core.$strict>>;
|
|
843
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
844
|
+
type: z.ZodLiteral<"rings">;
|
|
845
|
+
items: z.ZodArray<z.ZodObject<{
|
|
846
|
+
label: z.ZodString;
|
|
847
|
+
desc: z.ZodOptional<z.ZodString>;
|
|
848
|
+
}, z.core.$strict>>;
|
|
849
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
850
|
+
type: z.ZodLiteral<"numbered_cards">;
|
|
851
|
+
items: z.ZodArray<z.ZodObject<{
|
|
852
|
+
title: z.ZodString;
|
|
853
|
+
text: z.ZodOptional<z.ZodString>;
|
|
854
|
+
sub: z.ZodOptional<z.ZodString>;
|
|
855
|
+
}, z.core.$strict>>;
|
|
856
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
857
|
+
type: z.ZodLiteral<"roadmap">;
|
|
858
|
+
items: z.ZodArray<z.ZodObject<{
|
|
859
|
+
title: z.ZodString;
|
|
860
|
+
period: z.ZodOptional<z.ZodString>;
|
|
861
|
+
rows: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
862
|
+
label: z.ZodString;
|
|
863
|
+
value: z.ZodString;
|
|
864
|
+
}, z.core.$strict>>>;
|
|
865
|
+
}, z.core.$strict>>;
|
|
866
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
867
|
+
type: z.ZodLiteral<"matrix">;
|
|
868
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
869
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
870
|
+
cols: z.ZodNumber;
|
|
871
|
+
items: z.ZodArray<z.ZodObject<{
|
|
872
|
+
title: z.ZodString;
|
|
873
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
874
|
+
tone: z.ZodOptional<z.ZodEnum<{
|
|
875
|
+
info: "info";
|
|
876
|
+
neutral: "neutral";
|
|
877
|
+
accent: "accent";
|
|
878
|
+
}>>;
|
|
879
|
+
}, z.core.$strict>>;
|
|
880
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
881
|
+
type: z.ZodLiteral<"insight_panel">;
|
|
882
|
+
title: z.ZodString;
|
|
883
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
884
|
+
label: z.ZodString;
|
|
885
|
+
text: z.ZodString;
|
|
886
|
+
}, z.core.$strict>>;
|
|
887
|
+
footnote: z.ZodOptional<z.ZodString>;
|
|
888
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
889
|
+
type: z.ZodLiteral<"verdict_banner">;
|
|
890
|
+
text: z.ZodString;
|
|
891
|
+
tone: z.ZodEnum<{
|
|
892
|
+
positive: "positive";
|
|
893
|
+
warning: "warning";
|
|
894
|
+
neutral: "neutral";
|
|
895
|
+
}>;
|
|
896
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
897
|
+
[x: string]: string;
|
|
898
|
+
}>>;
|
|
899
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
900
|
+
type: z.ZodLiteral<"citation">;
|
|
901
|
+
sources: z.ZodArray<z.ZodObject<{
|
|
902
|
+
label: z.ZodString;
|
|
903
|
+
url: z.ZodOptional<z.ZodString>;
|
|
904
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
905
|
+
}, z.core.$strict>>;
|
|
906
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
907
|
+
type: z.ZodLiteral<"image">;
|
|
908
|
+
asset_id: z.ZodString;
|
|
909
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
910
|
+
fit: z.ZodDefault<z.ZodEnum<{
|
|
911
|
+
contain: "contain";
|
|
912
|
+
cover: "cover";
|
|
913
|
+
}>>;
|
|
914
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
915
|
+
type: z.ZodLiteral<"image_grid">;
|
|
916
|
+
items: z.ZodArray<z.ZodObject<{
|
|
917
|
+
asset_id: z.ZodString;
|
|
918
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
919
|
+
}, z.core.$strict>>;
|
|
920
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
921
|
+
none: "none";
|
|
922
|
+
first: "first";
|
|
923
|
+
}>>;
|
|
924
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
925
|
+
type: z.ZodLiteral<"image_compare">;
|
|
926
|
+
left: z.ZodObject<{
|
|
927
|
+
asset_id: z.ZodString;
|
|
928
|
+
label: z.ZodString;
|
|
929
|
+
}, z.core.$strict>;
|
|
930
|
+
right: z.ZodObject<{
|
|
931
|
+
asset_id: z.ZodString;
|
|
932
|
+
label: z.ZodString;
|
|
933
|
+
}, z.core.$strict>;
|
|
934
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
935
|
+
vs: "vs";
|
|
936
|
+
before_after: "before_after";
|
|
937
|
+
}>>;
|
|
938
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
939
|
+
type: z.ZodLiteral<"swot">;
|
|
940
|
+
strengths: z.ZodArray<z.ZodString>;
|
|
941
|
+
weaknesses: z.ZodArray<z.ZodString>;
|
|
942
|
+
opportunities: z.ZodArray<z.ZodString>;
|
|
943
|
+
threats: z.ZodArray<z.ZodString>;
|
|
944
|
+
labels: z.ZodOptional<z.ZodObject<{
|
|
945
|
+
strengths: z.ZodOptional<z.ZodString>;
|
|
946
|
+
weaknesses: z.ZodOptional<z.ZodString>;
|
|
947
|
+
opportunities: z.ZodOptional<z.ZodString>;
|
|
948
|
+
threats: z.ZodOptional<z.ZodString>;
|
|
949
|
+
}, z.core.$strict>>;
|
|
950
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
951
|
+
type: z.ZodLiteral<"bmc">;
|
|
952
|
+
key_partners: z.ZodArray<z.ZodString>;
|
|
953
|
+
key_activities: z.ZodArray<z.ZodString>;
|
|
954
|
+
key_resources: z.ZodArray<z.ZodString>;
|
|
955
|
+
value_propositions: z.ZodArray<z.ZodString>;
|
|
956
|
+
customer_relationships: z.ZodArray<z.ZodString>;
|
|
957
|
+
channels: z.ZodArray<z.ZodString>;
|
|
958
|
+
customer_segments: z.ZodArray<z.ZodString>;
|
|
959
|
+
cost_structure: z.ZodArray<z.ZodString>;
|
|
960
|
+
revenue_streams: z.ZodArray<z.ZodString>;
|
|
961
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
962
|
+
type: z.ZodLiteral<"waterfall">;
|
|
963
|
+
items: z.ZodArray<z.ZodObject<{
|
|
964
|
+
label: z.ZodString;
|
|
965
|
+
value: z.ZodNumber;
|
|
966
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
967
|
+
delta: "delta";
|
|
968
|
+
total: "total";
|
|
969
|
+
}>>;
|
|
970
|
+
}, z.core.$strict>>;
|
|
971
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
972
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
973
|
+
type: z.ZodLiteral<"gantt">;
|
|
974
|
+
items: z.ZodArray<z.ZodObject<{
|
|
975
|
+
label: z.ZodString;
|
|
976
|
+
start: z.ZodNumber;
|
|
977
|
+
end: z.ZodNumber;
|
|
978
|
+
}, z.core.$strict>>;
|
|
979
|
+
axis_labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
980
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
981
|
+
type: z.ZodLiteral<"pest">;
|
|
982
|
+
political: z.ZodObject<{
|
|
983
|
+
title: z.ZodOptional<z.ZodString>;
|
|
984
|
+
items: z.ZodArray<z.ZodString>;
|
|
985
|
+
}, z.core.$strict>;
|
|
986
|
+
economic: z.ZodObject<{
|
|
987
|
+
title: z.ZodOptional<z.ZodString>;
|
|
988
|
+
items: z.ZodArray<z.ZodString>;
|
|
989
|
+
}, z.core.$strict>;
|
|
990
|
+
social: z.ZodObject<{
|
|
991
|
+
title: z.ZodOptional<z.ZodString>;
|
|
992
|
+
items: z.ZodArray<z.ZodString>;
|
|
993
|
+
}, z.core.$strict>;
|
|
994
|
+
technological: z.ZodObject<{
|
|
995
|
+
title: z.ZodOptional<z.ZodString>;
|
|
996
|
+
items: z.ZodArray<z.ZodString>;
|
|
997
|
+
}, z.core.$strict>;
|
|
998
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
999
|
+
type: z.ZodLiteral<"five_forces">;
|
|
1000
|
+
rivalry: z.ZodObject<{
|
|
1001
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1002
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1003
|
+
low: "low";
|
|
1004
|
+
medium: "medium";
|
|
1005
|
+
high: "high";
|
|
1006
|
+
}>>;
|
|
1007
|
+
items: z.ZodArray<z.ZodString>;
|
|
1008
|
+
}, z.core.$strict>;
|
|
1009
|
+
new_entrants: z.ZodObject<{
|
|
1010
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1011
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1012
|
+
low: "low";
|
|
1013
|
+
medium: "medium";
|
|
1014
|
+
high: "high";
|
|
1015
|
+
}>>;
|
|
1016
|
+
items: z.ZodArray<z.ZodString>;
|
|
1017
|
+
}, z.core.$strict>;
|
|
1018
|
+
supplier_power: z.ZodObject<{
|
|
1019
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1020
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1021
|
+
low: "low";
|
|
1022
|
+
medium: "medium";
|
|
1023
|
+
high: "high";
|
|
1024
|
+
}>>;
|
|
1025
|
+
items: z.ZodArray<z.ZodString>;
|
|
1026
|
+
}, z.core.$strict>;
|
|
1027
|
+
buyer_power: z.ZodObject<{
|
|
1028
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1029
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1030
|
+
low: "low";
|
|
1031
|
+
medium: "medium";
|
|
1032
|
+
high: "high";
|
|
1033
|
+
}>>;
|
|
1034
|
+
items: z.ZodArray<z.ZodString>;
|
|
1035
|
+
}, z.core.$strict>;
|
|
1036
|
+
substitutes: z.ZodObject<{
|
|
1037
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1038
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1039
|
+
low: "low";
|
|
1040
|
+
medium: "medium";
|
|
1041
|
+
high: "high";
|
|
1042
|
+
}>>;
|
|
1043
|
+
items: z.ZodArray<z.ZodString>;
|
|
1044
|
+
}, z.core.$strict>;
|
|
1045
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1046
|
+
type: z.ZodLiteral<"heatmap">;
|
|
1047
|
+
x_labels: z.ZodArray<z.ZodString>;
|
|
1048
|
+
y_labels: z.ZodArray<z.ZodString>;
|
|
1049
|
+
values: z.ZodArray<z.ZodArray<z.ZodNumber>>;
|
|
1050
|
+
domain: z.ZodOptional<z.ZodObject<{
|
|
1051
|
+
min: z.ZodNumber;
|
|
1052
|
+
max: z.ZodNumber;
|
|
1053
|
+
}, z.core.$strict>>;
|
|
1054
|
+
show_values: z.ZodOptional<z.ZodBoolean>;
|
|
1055
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
1056
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
1057
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1058
|
+
type: z.ZodLiteral<"sankey">;
|
|
1059
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
1060
|
+
id: z.ZodString;
|
|
1061
|
+
label: z.ZodString;
|
|
1062
|
+
}, z.core.$strict>>;
|
|
1063
|
+
links: z.ZodArray<z.ZodObject<{
|
|
1064
|
+
from: z.ZodString;
|
|
1065
|
+
to: z.ZodString;
|
|
1066
|
+
value: z.ZodNumber;
|
|
1067
|
+
}, z.core.$strict>>;
|
|
1068
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1069
|
+
type: z.ZodLiteral<"data_table">;
|
|
1070
|
+
columns: z.ZodArray<z.ZodObject<{
|
|
1071
|
+
key: z.ZodString;
|
|
1072
|
+
label: z.ZodString;
|
|
1073
|
+
align: z.ZodOptional<z.ZodEnum<{
|
|
1074
|
+
left: "left";
|
|
1075
|
+
right: "right";
|
|
1076
|
+
center: "center";
|
|
1077
|
+
}>>;
|
|
1078
|
+
}, z.core.$strict>>;
|
|
1079
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
1080
|
+
cells: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
1081
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
1082
|
+
highlight: "highlight";
|
|
1083
|
+
total: "total";
|
|
1084
|
+
}>>;
|
|
1085
|
+
}, z.core.$strict>>;
|
|
1086
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1087
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1088
|
+
type: z.ZodLiteral<"device_mockup">;
|
|
1089
|
+
device: z.ZodEnum<{
|
|
1090
|
+
phone: "phone";
|
|
1091
|
+
browser: "browser";
|
|
1092
|
+
}>;
|
|
1093
|
+
asset_id: z.ZodString;
|
|
1094
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
1095
|
+
url: z.ZodOptional<z.ZodString>;
|
|
1096
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1097
|
+
type: z.ZodLiteral<"cycle">;
|
|
1098
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1099
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1100
|
+
label: z.ZodString;
|
|
1101
|
+
description: z.ZodOptional<z.ZodString>;
|
|
1102
|
+
}, z.core.$strict>>;
|
|
1103
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1104
|
+
type: z.ZodLiteral<"people_cards">;
|
|
1105
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1106
|
+
people: z.ZodArray<z.ZodObject<{
|
|
1107
|
+
name: z.ZodString;
|
|
1108
|
+
role: z.ZodOptional<z.ZodString>;
|
|
1109
|
+
org: z.ZodOptional<z.ZodString>;
|
|
1110
|
+
}, z.core.$strict>>;
|
|
1111
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1112
|
+
type: z.ZodLiteral<"tag_row">;
|
|
1113
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1114
|
+
items: z.ZodArray<z.ZodString>;
|
|
1115
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
1116
|
+
none: "none";
|
|
1117
|
+
first: "first";
|
|
1118
|
+
}>>;
|
|
1119
|
+
}, z.core.$strict>], "type">>>;
|
|
1120
|
+
background: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1121
|
+
kind: z.ZodLiteral<"color">;
|
|
1122
|
+
value: z.ZodString;
|
|
1123
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1124
|
+
kind: z.ZodLiteral<"gradient">;
|
|
1125
|
+
from: z.ZodString;
|
|
1126
|
+
to: z.ZodString;
|
|
1127
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
1128
|
+
tb: "tb";
|
|
1129
|
+
lr: "lr";
|
|
1130
|
+
diagonal: "diagonal";
|
|
1131
|
+
}>>;
|
|
1132
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1133
|
+
kind: z.ZodLiteral<"asset">;
|
|
1134
|
+
asset_id: z.ZodString;
|
|
1135
|
+
overlay: z.ZodOptional<z.ZodObject<{
|
|
1136
|
+
color: z.ZodString;
|
|
1137
|
+
opacity: z.ZodNumber;
|
|
1138
|
+
}, z.core.$strict>>;
|
|
1139
|
+
fit: z.ZodOptional<z.ZodEnum<{
|
|
1140
|
+
contain: "contain";
|
|
1141
|
+
cover: "cover";
|
|
1142
|
+
}>>;
|
|
1143
|
+
}, z.core.$strict>], "kind">>;
|
|
1144
|
+
decor: z.ZodOptional<z.ZodObject<{
|
|
1145
|
+
kind: z.ZodEnum<{
|
|
1146
|
+
big_number: "big_number";
|
|
1147
|
+
corner_tag: "corner_tag";
|
|
1148
|
+
rule_line: "rule_line";
|
|
1149
|
+
quote_marks: "quote_marks";
|
|
1150
|
+
geo_dots: "geo_dots";
|
|
1151
|
+
}>;
|
|
1152
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1153
|
+
subtle: "subtle";
|
|
1154
|
+
normal: "normal";
|
|
1155
|
+
}>>;
|
|
1156
|
+
text: z.ZodOptional<z.ZodString>;
|
|
1157
|
+
}, z.core.$strict>>;
|
|
1158
|
+
image_side: z.ZodOptional<z.ZodEnum<{
|
|
1159
|
+
left: "left";
|
|
1160
|
+
right: "right";
|
|
1161
|
+
}>>;
|
|
1162
|
+
footnote: z.ZodOptional<z.ZodString>;
|
|
1163
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
1164
|
+
}, z.core.$strict>;
|
|
1165
|
+
declare const PptxIRSchema: z.ZodObject<{
|
|
1166
|
+
version: z.ZodDefault<z.ZodLiteral<"4">>;
|
|
1167
|
+
filename: z.ZodDefault<z.ZodString>;
|
|
1168
|
+
narrative: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
1169
|
+
theme: z.ZodDefault<z.ZodObject<{
|
|
1170
|
+
id: z.ZodDefault<z.ZodString>;
|
|
1171
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
1172
|
+
colors: z.ZodOptional<z.ZodObject<{
|
|
1173
|
+
bg: z.ZodOptional<z.ZodString>;
|
|
1174
|
+
surface: z.ZodOptional<z.ZodString>;
|
|
1175
|
+
panel: z.ZodOptional<z.ZodString>;
|
|
1176
|
+
primary: z.ZodOptional<z.ZodString>;
|
|
1177
|
+
accent: z.ZodOptional<z.ZodString>;
|
|
1178
|
+
text: z.ZodOptional<z.ZodString>;
|
|
1179
|
+
muted: z.ZodOptional<z.ZodString>;
|
|
1180
|
+
border: z.ZodOptional<z.ZodString>;
|
|
1181
|
+
chartPalette: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1182
|
+
accentPool: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1183
|
+
cardStroke: z.ZodOptional<z.ZodString>;
|
|
1184
|
+
}, z.core.$strict>>;
|
|
1185
|
+
fonts: z.ZodOptional<z.ZodObject<{
|
|
1186
|
+
heading: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1187
|
+
body: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1188
|
+
mono: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1189
|
+
}, z.core.$strict>>;
|
|
1190
|
+
shape: z.ZodOptional<z.ZodObject<{
|
|
1191
|
+
radius: z.ZodOptional<z.ZodNumber>;
|
|
1192
|
+
gapScale: z.ZodOptional<z.ZodNumber>;
|
|
1193
|
+
typeScale: z.ZodOptional<z.ZodNumber>;
|
|
1194
|
+
}, z.core.$strict>>;
|
|
1195
|
+
}, z.core.$strict>>;
|
|
1196
|
+
brand: z.ZodOptional<z.ZodObject<{
|
|
1197
|
+
suppressFooterOnCardContent: z.ZodOptional<z.ZodBoolean>;
|
|
1198
|
+
suppressFooterRule: z.ZodOptional<z.ZodBoolean>;
|
|
1199
|
+
suppressFooterMeta: z.ZodOptional<z.ZodBoolean>;
|
|
1200
|
+
}, z.core.$strict>>;
|
|
1201
|
+
}, z.core.$strict>>;
|
|
1202
|
+
meta: z.ZodDefault<z.ZodObject<{
|
|
1203
|
+
organization: z.ZodOptional<z.ZodString>;
|
|
1204
|
+
authors: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1205
|
+
name: z.ZodString;
|
|
1206
|
+
role: z.ZodOptional<z.ZodString>;
|
|
1207
|
+
org: z.ZodOptional<z.ZodString>;
|
|
1208
|
+
}, z.core.$strict>>>;
|
|
1209
|
+
date: z.ZodOptional<z.ZodString>;
|
|
1210
|
+
version: z.ZodOptional<z.ZodString>;
|
|
1211
|
+
confidentiality: z.ZodOptional<z.ZodEnum<{
|
|
1212
|
+
public: "public";
|
|
1213
|
+
internal: "internal";
|
|
1214
|
+
confidential: "confidential";
|
|
1215
|
+
restricted: "restricted";
|
|
1216
|
+
}>>;
|
|
1217
|
+
contact: z.ZodOptional<z.ZodObject<{
|
|
1218
|
+
name: z.ZodOptional<z.ZodString>;
|
|
1219
|
+
email: z.ZodOptional<z.ZodString>;
|
|
1220
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
1221
|
+
website: z.ZodOptional<z.ZodString>;
|
|
1222
|
+
}, z.core.$strict>>;
|
|
1223
|
+
copyright: z.ZodOptional<z.ZodString>;
|
|
1224
|
+
animation: z.ZodOptional<z.ZodObject<{
|
|
1225
|
+
transition: z.ZodOptional<z.ZodEnum<{
|
|
1226
|
+
push: "push";
|
|
1227
|
+
none: "none";
|
|
1228
|
+
fade: "fade";
|
|
1229
|
+
wipe: "wipe";
|
|
1230
|
+
}>>;
|
|
1231
|
+
elements: z.ZodOptional<z.ZodEnum<{
|
|
1232
|
+
none: "none";
|
|
1233
|
+
auto: "auto";
|
|
1234
|
+
}>>;
|
|
1235
|
+
}, z.core.$strict>>;
|
|
1236
|
+
}, z.core.$strict>>;
|
|
1237
|
+
assets: z.ZodDefault<z.ZodObject<{
|
|
1238
|
+
images: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
1239
|
+
src: z.ZodString;
|
|
1240
|
+
alt: z.ZodOptional<z.ZodString>;
|
|
1241
|
+
error: z.ZodOptional<z.ZodString>;
|
|
1242
|
+
}, z.core.$strict>>>;
|
|
1243
|
+
}, z.core.$strict>>;
|
|
1244
|
+
brand: z.ZodOptional<z.ZodObject<{
|
|
1245
|
+
logo_asset_id: z.ZodOptional<z.ZodString>;
|
|
1246
|
+
position: z.ZodOptional<z.ZodEnum<{
|
|
1247
|
+
tl: "tl";
|
|
1248
|
+
tr: "tr";
|
|
1249
|
+
bl: "bl";
|
|
1250
|
+
br: "br";
|
|
1251
|
+
}>>;
|
|
1252
|
+
}, z.core.$strict>>;
|
|
1253
|
+
branding: z.ZodOptional<z.ZodEnum<{
|
|
1254
|
+
full: "full";
|
|
1255
|
+
"cover-only": "cover-only";
|
|
1256
|
+
minimal: "minimal";
|
|
1257
|
+
}>>;
|
|
1258
|
+
seed: z.ZodOptional<z.ZodNumber>;
|
|
1259
|
+
slides: z.ZodArray<z.ZodObject<{
|
|
1260
|
+
type: z.ZodDefault<z.ZodEnum<{
|
|
1261
|
+
content: "content";
|
|
1262
|
+
cover: "cover";
|
|
1263
|
+
chapter: "chapter";
|
|
1264
|
+
ending: "ending";
|
|
1265
|
+
}>>;
|
|
1266
|
+
id: z.ZodOptional<z.ZodString>;
|
|
1267
|
+
placeholder: z.ZodOptional<z.ZodLiteral<true>>;
|
|
1268
|
+
layout: z.ZodOptional<z.ZodString>;
|
|
1269
|
+
beat: z.ZodOptional<z.ZodEnum<{
|
|
1270
|
+
dense: "dense";
|
|
1271
|
+
anchor: "anchor";
|
|
1272
|
+
breathing: "breathing";
|
|
1273
|
+
}>>;
|
|
1274
|
+
arrangement: z.ZodOptional<z.ZodEnum<{
|
|
1275
|
+
code: "code";
|
|
1276
|
+
quote: "quote";
|
|
1277
|
+
single: "single";
|
|
1278
|
+
two_column: "two_column";
|
|
1279
|
+
kpi_focus: "kpi_focus";
|
|
1280
|
+
image_focus: "image_focus";
|
|
1281
|
+
big_number: "big_number";
|
|
1282
|
+
assertion_evidence: "assertion_evidence";
|
|
1283
|
+
aside: "aside";
|
|
1284
|
+
}>>;
|
|
1285
|
+
heading: z.ZodOptional<z.ZodString>;
|
|
1286
|
+
subheading: z.ZodOptional<z.ZodString>;
|
|
1287
|
+
components: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1288
|
+
type: z.ZodLiteral<"bullets">;
|
|
1289
|
+
items: z.ZodArray<z.ZodString>;
|
|
1290
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
1291
|
+
default: "default";
|
|
1292
|
+
checklist: "checklist";
|
|
1293
|
+
numbered: "numbered";
|
|
1294
|
+
plain: "plain";
|
|
1295
|
+
divided: "divided";
|
|
1296
|
+
}>>;
|
|
1297
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1298
|
+
type: z.ZodLiteral<"paragraph">;
|
|
1299
|
+
text: z.ZodString;
|
|
1300
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1301
|
+
type: z.ZodLiteral<"quote">;
|
|
1302
|
+
text: z.ZodString;
|
|
1303
|
+
attribution: z.ZodOptional<z.ZodString>;
|
|
1304
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1305
|
+
type: z.ZodLiteral<"callout">;
|
|
1306
|
+
variant: z.ZodEnum<{
|
|
1307
|
+
info: "info";
|
|
1308
|
+
warn: "warn";
|
|
1309
|
+
tip: "tip";
|
|
1310
|
+
}>;
|
|
1311
|
+
text: z.ZodString;
|
|
1312
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
1313
|
+
[x: string]: string;
|
|
1314
|
+
}>>;
|
|
1315
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1316
|
+
type: z.ZodLiteral<"code">;
|
|
1317
|
+
language: z.ZodString;
|
|
1318
|
+
code: z.ZodString;
|
|
1319
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1320
|
+
type: z.ZodLiteral<"kpi_cards">;
|
|
1321
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1322
|
+
value: z.ZodString;
|
|
1323
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
1324
|
+
label: z.ZodString;
|
|
1325
|
+
delta: z.ZodOptional<z.ZodEnum<{
|
|
1326
|
+
flat: "flat";
|
|
1327
|
+
up: "up";
|
|
1328
|
+
down: "down";
|
|
1329
|
+
}>>;
|
|
1330
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
1331
|
+
[x: string]: string;
|
|
1332
|
+
}>>;
|
|
1333
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1334
|
+
}, z.core.$strict>>;
|
|
1335
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1336
|
+
type: z.ZodLiteral<"chart">;
|
|
1337
|
+
chart_type: z.ZodEnum<{
|
|
1338
|
+
line: "line";
|
|
1339
|
+
donut: "donut";
|
|
1340
|
+
dumbbell: "dumbbell";
|
|
1341
|
+
funnel: "funnel";
|
|
1342
|
+
gauge: "gauge";
|
|
1343
|
+
bar: "bar";
|
|
1344
|
+
pie: "pie";
|
|
1345
|
+
scatter: "scatter";
|
|
1346
|
+
area: "area";
|
|
1347
|
+
}>;
|
|
1348
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
1349
|
+
horizontal: "horizontal";
|
|
1350
|
+
vertical: "vertical";
|
|
1351
|
+
}>>;
|
|
1352
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
1353
|
+
donut: "donut";
|
|
1354
|
+
}>>;
|
|
1355
|
+
center_total: z.ZodOptional<z.ZodBoolean>;
|
|
1356
|
+
gauge: z.ZodOptional<z.ZodObject<{
|
|
1357
|
+
min: z.ZodOptional<z.ZodNumber>;
|
|
1358
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
1359
|
+
}, z.core.$strict>>;
|
|
1360
|
+
axes: z.ZodOptional<z.ZodObject<{
|
|
1361
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
1362
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
1363
|
+
show_grid: z.ZodOptional<z.ZodBoolean>;
|
|
1364
|
+
}, z.core.$strict>>;
|
|
1365
|
+
series: z.ZodArray<z.ZodObject<{
|
|
1366
|
+
name: z.ZodString;
|
|
1367
|
+
data: z.ZodArray<z.ZodObject<{
|
|
1368
|
+
x: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
1369
|
+
y: z.ZodNumber;
|
|
1370
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
1371
|
+
}, z.core.$strict>>;
|
|
1372
|
+
}, z.core.$strict>>;
|
|
1373
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1374
|
+
type: z.ZodLiteral<"flowchart">;
|
|
1375
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
1376
|
+
id: z.ZodString;
|
|
1377
|
+
label: z.ZodString;
|
|
1378
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
1379
|
+
rect: "rect";
|
|
1380
|
+
diamond: "diamond";
|
|
1381
|
+
round: "round";
|
|
1382
|
+
}>>;
|
|
1383
|
+
}, z.core.$strict>>;
|
|
1384
|
+
edges: z.ZodArray<z.ZodObject<{
|
|
1385
|
+
from: z.ZodString;
|
|
1386
|
+
to: z.ZodString;
|
|
1387
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1388
|
+
}, z.core.$strict>>;
|
|
1389
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
1390
|
+
TB: "TB";
|
|
1391
|
+
TD: "TD";
|
|
1392
|
+
BT: "BT";
|
|
1393
|
+
LR: "LR";
|
|
1394
|
+
RL: "RL";
|
|
1395
|
+
}>>;
|
|
1396
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1397
|
+
type: z.ZodLiteral<"architecture">;
|
|
1398
|
+
layers: z.ZodArray<z.ZodObject<{
|
|
1399
|
+
title: z.ZodString;
|
|
1400
|
+
items: z.ZodArray<z.ZodString>;
|
|
1401
|
+
}, z.core.$strict>>;
|
|
1402
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
1403
|
+
top_down: "top_down";
|
|
1404
|
+
bottom_up: "bottom_up";
|
|
1405
|
+
}>>;
|
|
1406
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1407
|
+
type: z.ZodLiteral<"timeline">;
|
|
1408
|
+
layout: z.ZodOptional<z.ZodEnum<{
|
|
1409
|
+
horizontal: "horizontal";
|
|
1410
|
+
vertical: "vertical";
|
|
1411
|
+
}>>;
|
|
1412
|
+
milestones: z.ZodArray<z.ZodObject<{
|
|
1413
|
+
date: z.ZodString;
|
|
1414
|
+
title: z.ZodString;
|
|
1415
|
+
desc: z.ZodOptional<z.ZodString>;
|
|
1416
|
+
highlight: z.ZodOptional<z.ZodBoolean>;
|
|
1417
|
+
}, z.core.$strict>>;
|
|
1418
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1419
|
+
type: z.ZodLiteral<"comparison">;
|
|
1420
|
+
columns: z.ZodArray<z.ZodString>;
|
|
1421
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
1422
|
+
label: z.ZodString;
|
|
1423
|
+
cells: z.ZodArray<z.ZodString>;
|
|
1424
|
+
}, z.core.$strict>>;
|
|
1425
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1426
|
+
type: z.ZodLiteral<"icon_cards">;
|
|
1427
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1428
|
+
icon: z.ZodEnum<{
|
|
1429
|
+
[x: string]: string;
|
|
1430
|
+
}>;
|
|
1431
|
+
title: z.ZodString;
|
|
1432
|
+
text: z.ZodString;
|
|
1433
|
+
}, z.core.$strict>>;
|
|
1434
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1435
|
+
type: z.ZodLiteral<"row_cards">;
|
|
1436
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1437
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
1438
|
+
[x: string]: string;
|
|
1439
|
+
}>>;
|
|
1440
|
+
title: z.ZodString;
|
|
1441
|
+
text: z.ZodOptional<z.ZodString>;
|
|
1442
|
+
sub: z.ZodOptional<z.ZodString>;
|
|
1443
|
+
highlight: z.ZodOptional<z.ZodBoolean>;
|
|
1444
|
+
}, z.core.$strict>>;
|
|
1445
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1446
|
+
type: z.ZodLiteral<"steps">;
|
|
1447
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1448
|
+
title: z.ZodString;
|
|
1449
|
+
text: z.ZodString;
|
|
1450
|
+
}, z.core.$strict>>;
|
|
1451
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1452
|
+
type: z.ZodLiteral<"rings">;
|
|
1453
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1454
|
+
label: z.ZodString;
|
|
1455
|
+
desc: z.ZodOptional<z.ZodString>;
|
|
1456
|
+
}, z.core.$strict>>;
|
|
1457
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1458
|
+
type: z.ZodLiteral<"numbered_cards">;
|
|
1459
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1460
|
+
title: z.ZodString;
|
|
1461
|
+
text: z.ZodOptional<z.ZodString>;
|
|
1462
|
+
sub: z.ZodOptional<z.ZodString>;
|
|
1463
|
+
}, z.core.$strict>>;
|
|
1464
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1465
|
+
type: z.ZodLiteral<"roadmap">;
|
|
1466
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1467
|
+
title: z.ZodString;
|
|
1468
|
+
period: z.ZodOptional<z.ZodString>;
|
|
1469
|
+
rows: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
1470
|
+
label: z.ZodString;
|
|
1471
|
+
value: z.ZodString;
|
|
1472
|
+
}, z.core.$strict>>>;
|
|
1473
|
+
}, z.core.$strict>>;
|
|
1474
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1475
|
+
type: z.ZodLiteral<"matrix">;
|
|
1476
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
1477
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
1478
|
+
cols: z.ZodNumber;
|
|
1479
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1480
|
+
title: z.ZodString;
|
|
1481
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
1482
|
+
tone: z.ZodOptional<z.ZodEnum<{
|
|
1483
|
+
info: "info";
|
|
1484
|
+
neutral: "neutral";
|
|
1485
|
+
accent: "accent";
|
|
1486
|
+
}>>;
|
|
1487
|
+
}, z.core.$strict>>;
|
|
1488
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1489
|
+
type: z.ZodLiteral<"insight_panel">;
|
|
1490
|
+
title: z.ZodString;
|
|
1491
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
1492
|
+
label: z.ZodString;
|
|
1493
|
+
text: z.ZodString;
|
|
1494
|
+
}, z.core.$strict>>;
|
|
1495
|
+
footnote: z.ZodOptional<z.ZodString>;
|
|
1496
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1497
|
+
type: z.ZodLiteral<"verdict_banner">;
|
|
1498
|
+
text: z.ZodString;
|
|
1499
|
+
tone: z.ZodEnum<{
|
|
1500
|
+
positive: "positive";
|
|
1501
|
+
warning: "warning";
|
|
1502
|
+
neutral: "neutral";
|
|
1503
|
+
}>;
|
|
1504
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
1505
|
+
[x: string]: string;
|
|
1506
|
+
}>>;
|
|
1507
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1508
|
+
type: z.ZodLiteral<"citation">;
|
|
1509
|
+
sources: z.ZodArray<z.ZodObject<{
|
|
1510
|
+
label: z.ZodString;
|
|
1511
|
+
url: z.ZodOptional<z.ZodString>;
|
|
1512
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
1513
|
+
}, z.core.$strict>>;
|
|
1514
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1515
|
+
type: z.ZodLiteral<"image">;
|
|
1516
|
+
asset_id: z.ZodString;
|
|
1517
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
1518
|
+
fit: z.ZodDefault<z.ZodEnum<{
|
|
1519
|
+
contain: "contain";
|
|
1520
|
+
cover: "cover";
|
|
1521
|
+
}>>;
|
|
1522
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1523
|
+
type: z.ZodLiteral<"image_grid">;
|
|
1524
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1525
|
+
asset_id: z.ZodString;
|
|
1526
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
1527
|
+
}, z.core.$strict>>;
|
|
1528
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
1529
|
+
none: "none";
|
|
1530
|
+
first: "first";
|
|
1531
|
+
}>>;
|
|
1532
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1533
|
+
type: z.ZodLiteral<"image_compare">;
|
|
1534
|
+
left: z.ZodObject<{
|
|
1535
|
+
asset_id: z.ZodString;
|
|
1536
|
+
label: z.ZodString;
|
|
1537
|
+
}, z.core.$strict>;
|
|
1538
|
+
right: z.ZodObject<{
|
|
1539
|
+
asset_id: z.ZodString;
|
|
1540
|
+
label: z.ZodString;
|
|
1541
|
+
}, z.core.$strict>;
|
|
1542
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
1543
|
+
vs: "vs";
|
|
1544
|
+
before_after: "before_after";
|
|
1545
|
+
}>>;
|
|
1546
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1547
|
+
type: z.ZodLiteral<"swot">;
|
|
1548
|
+
strengths: z.ZodArray<z.ZodString>;
|
|
1549
|
+
weaknesses: z.ZodArray<z.ZodString>;
|
|
1550
|
+
opportunities: z.ZodArray<z.ZodString>;
|
|
1551
|
+
threats: z.ZodArray<z.ZodString>;
|
|
1552
|
+
labels: z.ZodOptional<z.ZodObject<{
|
|
1553
|
+
strengths: z.ZodOptional<z.ZodString>;
|
|
1554
|
+
weaknesses: z.ZodOptional<z.ZodString>;
|
|
1555
|
+
opportunities: z.ZodOptional<z.ZodString>;
|
|
1556
|
+
threats: z.ZodOptional<z.ZodString>;
|
|
1557
|
+
}, z.core.$strict>>;
|
|
1558
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1559
|
+
type: z.ZodLiteral<"bmc">;
|
|
1560
|
+
key_partners: z.ZodArray<z.ZodString>;
|
|
1561
|
+
key_activities: z.ZodArray<z.ZodString>;
|
|
1562
|
+
key_resources: z.ZodArray<z.ZodString>;
|
|
1563
|
+
value_propositions: z.ZodArray<z.ZodString>;
|
|
1564
|
+
customer_relationships: z.ZodArray<z.ZodString>;
|
|
1565
|
+
channels: z.ZodArray<z.ZodString>;
|
|
1566
|
+
customer_segments: z.ZodArray<z.ZodString>;
|
|
1567
|
+
cost_structure: z.ZodArray<z.ZodString>;
|
|
1568
|
+
revenue_streams: z.ZodArray<z.ZodString>;
|
|
1569
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1570
|
+
type: z.ZodLiteral<"waterfall">;
|
|
1571
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1572
|
+
label: z.ZodString;
|
|
1573
|
+
value: z.ZodNumber;
|
|
1574
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
1575
|
+
delta: "delta";
|
|
1576
|
+
total: "total";
|
|
1577
|
+
}>>;
|
|
1578
|
+
}, z.core.$strict>>;
|
|
1579
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
1580
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1581
|
+
type: z.ZodLiteral<"gantt">;
|
|
1582
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1583
|
+
label: z.ZodString;
|
|
1584
|
+
start: z.ZodNumber;
|
|
1585
|
+
end: z.ZodNumber;
|
|
1586
|
+
}, z.core.$strict>>;
|
|
1587
|
+
axis_labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
1588
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1589
|
+
type: z.ZodLiteral<"pest">;
|
|
1590
|
+
political: z.ZodObject<{
|
|
1591
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1592
|
+
items: z.ZodArray<z.ZodString>;
|
|
1593
|
+
}, z.core.$strict>;
|
|
1594
|
+
economic: z.ZodObject<{
|
|
1595
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1596
|
+
items: z.ZodArray<z.ZodString>;
|
|
1597
|
+
}, z.core.$strict>;
|
|
1598
|
+
social: z.ZodObject<{
|
|
1599
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1600
|
+
items: z.ZodArray<z.ZodString>;
|
|
1601
|
+
}, z.core.$strict>;
|
|
1602
|
+
technological: z.ZodObject<{
|
|
1603
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1604
|
+
items: z.ZodArray<z.ZodString>;
|
|
1605
|
+
}, z.core.$strict>;
|
|
1606
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1607
|
+
type: z.ZodLiteral<"five_forces">;
|
|
1608
|
+
rivalry: z.ZodObject<{
|
|
1609
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1610
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1611
|
+
low: "low";
|
|
1612
|
+
medium: "medium";
|
|
1613
|
+
high: "high";
|
|
1614
|
+
}>>;
|
|
1615
|
+
items: z.ZodArray<z.ZodString>;
|
|
1616
|
+
}, z.core.$strict>;
|
|
1617
|
+
new_entrants: z.ZodObject<{
|
|
1618
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1619
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1620
|
+
low: "low";
|
|
1621
|
+
medium: "medium";
|
|
1622
|
+
high: "high";
|
|
1623
|
+
}>>;
|
|
1624
|
+
items: z.ZodArray<z.ZodString>;
|
|
1625
|
+
}, z.core.$strict>;
|
|
1626
|
+
supplier_power: z.ZodObject<{
|
|
1627
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1628
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1629
|
+
low: "low";
|
|
1630
|
+
medium: "medium";
|
|
1631
|
+
high: "high";
|
|
1632
|
+
}>>;
|
|
1633
|
+
items: z.ZodArray<z.ZodString>;
|
|
1634
|
+
}, z.core.$strict>;
|
|
1635
|
+
buyer_power: z.ZodObject<{
|
|
1636
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1637
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1638
|
+
low: "low";
|
|
1639
|
+
medium: "medium";
|
|
1640
|
+
high: "high";
|
|
1641
|
+
}>>;
|
|
1642
|
+
items: z.ZodArray<z.ZodString>;
|
|
1643
|
+
}, z.core.$strict>;
|
|
1644
|
+
substitutes: z.ZodObject<{
|
|
1645
|
+
label: z.ZodOptional<z.ZodString>;
|
|
1646
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1647
|
+
low: "low";
|
|
1648
|
+
medium: "medium";
|
|
1649
|
+
high: "high";
|
|
1650
|
+
}>>;
|
|
1651
|
+
items: z.ZodArray<z.ZodString>;
|
|
1652
|
+
}, z.core.$strict>;
|
|
1653
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1654
|
+
type: z.ZodLiteral<"heatmap">;
|
|
1655
|
+
x_labels: z.ZodArray<z.ZodString>;
|
|
1656
|
+
y_labels: z.ZodArray<z.ZodString>;
|
|
1657
|
+
values: z.ZodArray<z.ZodArray<z.ZodNumber>>;
|
|
1658
|
+
domain: z.ZodOptional<z.ZodObject<{
|
|
1659
|
+
min: z.ZodNumber;
|
|
1660
|
+
max: z.ZodNumber;
|
|
1661
|
+
}, z.core.$strict>>;
|
|
1662
|
+
show_values: z.ZodOptional<z.ZodBoolean>;
|
|
1663
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
1664
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
1665
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1666
|
+
type: z.ZodLiteral<"sankey">;
|
|
1667
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
1668
|
+
id: z.ZodString;
|
|
1669
|
+
label: z.ZodString;
|
|
1670
|
+
}, z.core.$strict>>;
|
|
1671
|
+
links: z.ZodArray<z.ZodObject<{
|
|
1672
|
+
from: z.ZodString;
|
|
1673
|
+
to: z.ZodString;
|
|
1674
|
+
value: z.ZodNumber;
|
|
1675
|
+
}, z.core.$strict>>;
|
|
1676
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1677
|
+
type: z.ZodLiteral<"data_table">;
|
|
1678
|
+
columns: z.ZodArray<z.ZodObject<{
|
|
1679
|
+
key: z.ZodString;
|
|
1680
|
+
label: z.ZodString;
|
|
1681
|
+
align: z.ZodOptional<z.ZodEnum<{
|
|
1682
|
+
left: "left";
|
|
1683
|
+
right: "right";
|
|
1684
|
+
center: "center";
|
|
1685
|
+
}>>;
|
|
1686
|
+
}, z.core.$strict>>;
|
|
1687
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
1688
|
+
cells: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
1689
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
1690
|
+
highlight: "highlight";
|
|
1691
|
+
total: "total";
|
|
1692
|
+
}>>;
|
|
1693
|
+
}, z.core.$strict>>;
|
|
1694
|
+
source: z.ZodOptional<z.ZodString>;
|
|
1695
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1696
|
+
type: z.ZodLiteral<"device_mockup">;
|
|
1697
|
+
device: z.ZodEnum<{
|
|
1698
|
+
phone: "phone";
|
|
1699
|
+
browser: "browser";
|
|
1700
|
+
}>;
|
|
1701
|
+
asset_id: z.ZodString;
|
|
1702
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
1703
|
+
url: z.ZodOptional<z.ZodString>;
|
|
1704
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1705
|
+
type: z.ZodLiteral<"cycle">;
|
|
1706
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1707
|
+
items: z.ZodArray<z.ZodObject<{
|
|
1708
|
+
label: z.ZodString;
|
|
1709
|
+
description: z.ZodOptional<z.ZodString>;
|
|
1710
|
+
}, z.core.$strict>>;
|
|
1711
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1712
|
+
type: z.ZodLiteral<"people_cards">;
|
|
1713
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1714
|
+
people: z.ZodArray<z.ZodObject<{
|
|
1715
|
+
name: z.ZodString;
|
|
1716
|
+
role: z.ZodOptional<z.ZodString>;
|
|
1717
|
+
org: z.ZodOptional<z.ZodString>;
|
|
1718
|
+
}, z.core.$strict>>;
|
|
1719
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1720
|
+
type: z.ZodLiteral<"tag_row">;
|
|
1721
|
+
title: z.ZodOptional<z.ZodString>;
|
|
1722
|
+
items: z.ZodArray<z.ZodString>;
|
|
1723
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
1724
|
+
none: "none";
|
|
1725
|
+
first: "first";
|
|
1726
|
+
}>>;
|
|
1727
|
+
}, z.core.$strict>], "type">>>;
|
|
1728
|
+
background: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1729
|
+
kind: z.ZodLiteral<"color">;
|
|
1730
|
+
value: z.ZodString;
|
|
1731
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1732
|
+
kind: z.ZodLiteral<"gradient">;
|
|
1733
|
+
from: z.ZodString;
|
|
1734
|
+
to: z.ZodString;
|
|
1735
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
1736
|
+
tb: "tb";
|
|
1737
|
+
lr: "lr";
|
|
1738
|
+
diagonal: "diagonal";
|
|
1739
|
+
}>>;
|
|
1740
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
1741
|
+
kind: z.ZodLiteral<"asset">;
|
|
1742
|
+
asset_id: z.ZodString;
|
|
1743
|
+
overlay: z.ZodOptional<z.ZodObject<{
|
|
1744
|
+
color: z.ZodString;
|
|
1745
|
+
opacity: z.ZodNumber;
|
|
1746
|
+
}, z.core.$strict>>;
|
|
1747
|
+
fit: z.ZodOptional<z.ZodEnum<{
|
|
1748
|
+
contain: "contain";
|
|
1749
|
+
cover: "cover";
|
|
1750
|
+
}>>;
|
|
1751
|
+
}, z.core.$strict>], "kind">>;
|
|
1752
|
+
decor: z.ZodOptional<z.ZodObject<{
|
|
1753
|
+
kind: z.ZodEnum<{
|
|
1754
|
+
big_number: "big_number";
|
|
1755
|
+
corner_tag: "corner_tag";
|
|
1756
|
+
rule_line: "rule_line";
|
|
1757
|
+
quote_marks: "quote_marks";
|
|
1758
|
+
geo_dots: "geo_dots";
|
|
1759
|
+
}>;
|
|
1760
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
1761
|
+
subtle: "subtle";
|
|
1762
|
+
normal: "normal";
|
|
1763
|
+
}>>;
|
|
1764
|
+
text: z.ZodOptional<z.ZodString>;
|
|
1765
|
+
}, z.core.$strict>>;
|
|
1766
|
+
image_side: z.ZodOptional<z.ZodEnum<{
|
|
1767
|
+
left: "left";
|
|
1768
|
+
right: "right";
|
|
1769
|
+
}>>;
|
|
1770
|
+
footnote: z.ZodOptional<z.ZodString>;
|
|
1771
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
1772
|
+
}, z.core.$strict>>;
|
|
1773
|
+
}, z.core.$strict>;
|
|
1774
|
+
type PptxIR = z.infer<typeof PptxIRSchema>;
|
|
1775
|
+
type Component = z.infer<typeof ComponentSchema>;
|
|
1776
|
+
type BackgroundSpec = z.infer<typeof BackgroundSpecSchema>;
|
|
1777
|
+
type Slide = z.infer<typeof SlideSchema>;
|
|
1778
|
+
type Assets = z.infer<typeof AssetsSchema>;
|
|
1779
|
+
type Meta = z.infer<typeof MetaSchema>;
|
|
1780
|
+
|
|
1781
|
+
interface ValidationIssue {
|
|
1782
|
+
path: string;
|
|
1783
|
+
message: string;
|
|
1784
|
+
/** 1-based slide number when the issue is scoped to a slide. */
|
|
1785
|
+
page?: number;
|
|
1786
|
+
/**
|
|
1787
|
+
* The offending slide's own `id` (`Slide.id`, `ir/index.ts`) — W5
|
|
1788
|
+
* whole-branch review finding 2: the README already claimed "validation
|
|
1789
|
+
* error messages reference [a slide] by [its] id"; this is what makes
|
|
1790
|
+
* that true. Set by every page-scoped issue producer
|
|
1791
|
+
* ({@link checkLayoutApplicability}, {@link checkBoundaryPageContent},
|
|
1792
|
+
* the content-quality-gate translation in {@link validateIr},
|
|
1793
|
+
* {@link checkDuplicateSlideIds}, {@link checkUnofferedSparsePins})
|
|
1794
|
+
* when the slide in question has an `id` — absent when the slide has
|
|
1795
|
+
* none (bare, pre-W5 IR) or the issue is deck-level, not scoped to any
|
|
1796
|
+
* single slide. {@link formatIssues} appends it in parens after the page
|
|
1797
|
+
* number.
|
|
1798
|
+
*/
|
|
1799
|
+
slideId?: string;
|
|
1800
|
+
}
|
|
1801
|
+
interface ValidateResult {
|
|
1802
|
+
ok: boolean;
|
|
1803
|
+
ir?: PptxIR;
|
|
1804
|
+
errors: ValidationIssue[];
|
|
1805
|
+
/**
|
|
1806
|
+
* Human-readable "`path`: `alias` → `canonical`" entries for every
|
|
1807
|
+
* deterministic field-alias rewrite `validateIr` applied before parsing
|
|
1808
|
+
* (W5 task 4, `ir/field-aliases.ts`'s `normalizeComponentAliases`) — e.g. a
|
|
1809
|
+
* kpi item's `title` silently adopted as `label`. Present only when at
|
|
1810
|
+
* least one rewrite happened; informational, never gates `ok` on its own.
|
|
1811
|
+
*/
|
|
1812
|
+
normalized?: string[];
|
|
1813
|
+
/**
|
|
1814
|
+
* Backward-compatible addition (borrow wave, Task 2 — dual-threshold
|
|
1815
|
+
* severity recalibration): warn-severity {@link checkIrQuality} findings
|
|
1816
|
+
* (editorial-budget codes — `missing_heading`/`long_heading`/`density`/
|
|
1817
|
+
* `bullets_overflow`/`bullet_item_long`/`big_number_no_kpi`) plus
|
|
1818
|
+
* {@link checkAssetReferences}'s dangling-`asset_id` findings (borrow wave,
|
|
1819
|
+
* Task 2, B5 — a reference to an `assets.images` key that doesn't exist),
|
|
1820
|
+
* formatted the same shape {@link formatIssues} already prints for `errors`
|
|
1821
|
+
* (page/id/path all included). Present only when at least one warn-severity
|
|
1822
|
+
* finding exists, and never gates `ok` on its own — that is exactly what
|
|
1823
|
+
* moved these findings off `errors` and onto here. Can be present alongside
|
|
1824
|
+
* a failing (`ok:false`) result too, whenever `checkIrQuality`/
|
|
1825
|
+
* `checkAssetReferences` themselves ran (an *earlier* hard gate — schema,
|
|
1826
|
+
* theme id, layout applicability, full-body exclusivity, boundary-page
|
|
1827
|
+
* content, duplicate ids, asset bytes, narrative — short-circuits before
|
|
1828
|
+
* either runs at all, so a deck rejected by one of those never reaches
|
|
1829
|
+
* this field either way, see `validateIr`'s own body for the exact gate
|
|
1830
|
+
* order). {@link formatWarnings} renders this array as CLI-ready
|
|
1831
|
+
* `"warning: ..."` lines.
|
|
1832
|
+
*/
|
|
1833
|
+
warnings?: ValidationIssue[];
|
|
1834
|
+
}
|
|
1835
|
+
/**
|
|
1836
|
+
* Validate raw JSON against the IR schema, then — once it parses — resolve
|
|
1837
|
+
* `narrative` (`resolveNarrative`, spec §5: an unrecognized preset name is a
|
|
1838
|
+
* `narrative`-path error, page-less) and run the content-quality gate
|
|
1839
|
+
* (`checkIrQuality`, passed the resolved axes) against the parsed IR. Every
|
|
1840
|
+
* hard-gate stage (schema, theme id, layout applicability, full-body
|
|
1841
|
+
* exclusivity, boundary-page content, duplicate ids, asset bytes, narrative)
|
|
1842
|
+
* must pass for `ok: true`, same as before. Quality findings are reported
|
|
1843
|
+
* the same way as schema errors (page-scoped, 1-based).
|
|
1844
|
+
*
|
|
1845
|
+
* Dual-threshold severity (borrow wave, Task 2 — recalibrated from the prior
|
|
1846
|
+
* "any finding blocks" design): `checkIrQuality`'s own "warn" vs "error" tag
|
|
1847
|
+
* is now respected, not flattened. Only "error"-severity findings
|
|
1848
|
+
* (`empty_deck`, `bullet_item_overflow` — content genuinely lost: an empty
|
|
1849
|
+
* deck, or a bullet item long enough to hit `bullets.tsx`'s MIN_FONT floor
|
|
1850
|
+
* and actually get truncated) gate `ok`. "warn"-severity findings — the
|
|
1851
|
+
* editorial-budget codes (`missing_heading`/`long_heading`/`density`/
|
|
1852
|
+
* `bullets_overflow`/`bullet_item_long`/`big_number_no_kpi`) — surface on
|
|
1853
|
+
* {@link ValidateResult.warnings} instead: visible to every caller (the SDK,
|
|
1854
|
+
* the CLI's `validate`/`render` pre-flight), never blocking. This reverses
|
|
1855
|
+
* the prior posture (this comment used to read "any finding blocks... not
|
|
1856
|
+
* only 'error'-severity ones") because the evidence behind it did not hold:
|
|
1857
|
+
* a boundary scan (borrow-wave fact-report, Q3) found the editorial bullets
|
|
1858
|
+
* threshold blocking content roughly 3.5x below where `bullets.tsx`'s own
|
|
1859
|
+
* render safety net (2-line wrap, shrink to a 14px floor) actually starts
|
|
1860
|
+
* losing characters — so the hard gate was rejecting deck content that
|
|
1861
|
+
* would have rendered with zero visible defect, and a tight hard gate on an
|
|
1862
|
+
* editorial (not geometric) threshold taught truncate-content-to-pass
|
|
1863
|
+
* workarounds rather than catching real loss. `generatePptx`'s default path
|
|
1864
|
+
* inherits this unchanged (`if (!v.ok) throw`) — it already only ever
|
|
1865
|
+
* blocked on `ok`, never inspected `errors`/`warnings` directly.
|
|
1866
|
+
*
|
|
1867
|
+
* Before any of that, two deterministic pre-parse rewrite passes run, each
|
|
1868
|
+
* threading its rewrite notes onto `ValidateResult.normalized` on *every*
|
|
1869
|
+
* return path below via `withNormalized`, success or failure alike — neither
|
|
1870
|
+
* ever gates `ok` on its own:
|
|
1871
|
+
* - {@link normalizeComponentAliases} (W5 task 4): the component
|
|
1872
|
+
* field-name synonym rescue (kpi `title`→`label`, quote `content`→`text`,
|
|
1873
|
+
* …), scoped to `slides[]`. Only rewrites where the canonical key is
|
|
1874
|
+
* absent, so the schema parse below never sees an alias as an
|
|
1875
|
+
* "unrecognized key" in the first place.
|
|
1876
|
+
* - {@link normalizeNarrativeShape} (`./narrative`, T0b bench-evidence fix
|
|
1877
|
+
* 2 — see its own doc comment for the full rationale): the root-level
|
|
1878
|
+
* `narrative: {id: <preset>}` shape rescue. A model that just wrote
|
|
1879
|
+
* `theme: {id: "consulting"}` a few lines above pattern-matches the same
|
|
1880
|
+
* wrapper shape onto `narrative`; this rewrites it to the bare preset
|
|
1881
|
+
* string `resolveNarrative`'s string branch actually expects. Fires only
|
|
1882
|
+
* when `id` is the object's sole narrative-relevant key (none of
|
|
1883
|
+
* strategy/pacing/audience alongside it) — a mixed shape stays
|
|
1884
|
+
* unrescued, ambiguous, and hard-errors exactly as it did before this
|
|
1885
|
+
* pass existed.
|
|
1886
|
+
*
|
|
1887
|
+
* Both are the same class of fix — a weak-model *synonym* rescue (a name
|
|
1888
|
+
* drift for the component-alias pass, a *shape* drift for the narrative
|
|
1889
|
+
* pass) — which is the actual boundary the next paragraph's "no
|
|
1890
|
+
* old-vocabulary rescue" draws, not "no rewrite ever touches `narrative`."
|
|
1891
|
+
*
|
|
1892
|
+
* There is still deliberately no *old-vocabulary* rescue (spec §16,
|
|
1893
|
+
* reversing the now-superseded §15.4): a v4 document that still spells its
|
|
1894
|
+
* pre-rename vocabulary — `scenario` instead of `narrative`, `mode`/
|
|
1895
|
+
* `delivery` instead of `strategy`/`pacing`, or the old enum values
|
|
1896
|
+
* `"text"`/`"presentation"`/`"narrative"` — is not old-vocabulary
|
|
1897
|
+
* *compatibility*, it is exactly the vocabulary this rename retired, so it
|
|
1898
|
+
* hard-errors like any other unknown key or value: `scenario` fails the
|
|
1899
|
+
* schema's `.strict()` parse below as an unrecognized key, and an old enum
|
|
1900
|
+
* value (or the axis-key names `mode`/`delivery` inside `narrative`, which
|
|
1901
|
+
* the schema itself leaves open) fails `resolveNarrative`'s own runtime
|
|
1902
|
+
* check, listing the current values. `{id: <preset>}` was never a v3
|
|
1903
|
+
* `scenario` shape, so `normalizeNarrativeShape` above does not reopen this
|
|
1904
|
+
* door — it rescues a shape weak models invent by analogy to `theme.id`, not
|
|
1905
|
+
* a shape the pre-rename vocabulary ever spoke. `pptwise migrate`
|
|
1906
|
+
* (`ir/migrate.ts`) remains the sanctioned bridge for a genuine v3 document —
|
|
1907
|
+
* see the v3 hard reject below, which points there. Hard-erroring is not the
|
|
1908
|
+
* same as leaving the error message unhelpful, though: the schema-parse
|
|
1909
|
+
* branch below appends a rename hint to `scenario` and the rest of the
|
|
1910
|
+
* documented v2/v3 rename map (`blocks`/`variant`/`theme.override` —
|
|
1911
|
+
* `./ir/rename-hints.ts`, borrow-wave task 3) whenever the offending key
|
|
1912
|
+
* matches one, and a generic "belongs inside components[]" hint for any
|
|
1913
|
+
* other slide-level unrecognized key — message-layer annotation only, never
|
|
1914
|
+
* a second, silent rewrite path alongside the two passes above.
|
|
1915
|
+
*
|
|
1916
|
+
* Both pre-parse passes only ever run for a document already headed for the
|
|
1917
|
+
* v4 schema — an explicit `version: "2"` or `version: "3"` is hard-rejected
|
|
1918
|
+
* first, below, before either pass or any schema parse (spec §9.3: a v2/v3
|
|
1919
|
+
* document is never silently reinterpreted as v4).
|
|
1920
|
+
*/
|
|
1921
|
+
declare function validateIr(input: unknown): ValidateResult;
|
|
1922
|
+
/**
|
|
1923
|
+
* `"page 2 (p-kpi) — path: message"` when the issue carries both a `page`
|
|
1924
|
+
* and a `slideId` (W5 whole-branch review finding 2 — the README's own
|
|
1925
|
+
* claim that a validation error "references [a slide] by [its] id", made
|
|
1926
|
+
* true) — the parenthesized id is appended only alongside a `page` number,
|
|
1927
|
+
* never on its own: a deck-level issue that happens to set a representative
|
|
1928
|
+
* `slideId` with no `page` ({@link checkDuplicateSlideIds} above) keeps its
|
|
1929
|
+
* pre-existing, unchanged format. Every other combination — `page` with no
|
|
1930
|
+
* `slideId` (an id-less slide), or neither — is byte-identical to before
|
|
1931
|
+
* this task.
|
|
1932
|
+
*/
|
|
1933
|
+
declare function formatIssues(errors: ValidationIssue[]): string;
|
|
1934
|
+
interface ThemeInfo {
|
|
1935
|
+
id: string;
|
|
1936
|
+
label: string;
|
|
1937
|
+
colors: Record<string, unknown>;
|
|
1938
|
+
}
|
|
1939
|
+
/** Built-in theme catalog with labels and style color tokens. */
|
|
1940
|
+
declare function listThemes(): ThemeInfo[];
|
|
1941
|
+
/** JSON Schema for the IR — feed this to a model before it writes IR. */
|
|
1942
|
+
declare function irJsonSchema(): Record<string, unknown>;
|
|
1943
|
+
/** JSON Schema for style-token overrides (IR theme.style, --style files, config "style"). */
|
|
1944
|
+
declare function styleJsonSchema(): Record<string, unknown>;
|
|
1945
|
+
|
|
1946
|
+
/**
|
|
1947
|
+
* Public API surface: validateIr's own logic lives in `./validate-core`
|
|
1948
|
+
* (P2 browser-distribution wave, task 1 — see that file's own doc comment
|
|
1949
|
+
* for why) and is re-exported below unchanged, so every existing consumer
|
|
1950
|
+
* of this module keeps working exactly as before. `renderSlideSvg` and
|
|
1951
|
+
* `generatePptx` stay defined here — this is the one file allowed to reach
|
|
1952
|
+
* into `./svg/render-slide` and `./pptx/generate` (react-dom/server, jszip,
|
|
1953
|
+
* pptxgenjs).
|
|
1954
|
+
*/
|
|
1955
|
+
|
|
1956
|
+
/** Render a single slide to standalone SVG markup (preview / self-check). */
|
|
1957
|
+
declare function renderSlideSvg(ir: PptxIR, slideIndex: number): string;
|
|
1958
|
+
/**
|
|
1959
|
+
* Full pipeline: validate → SVG → DrawingML → animation patches → pptx bytes.
|
|
1960
|
+
*
|
|
1961
|
+
* Two export gates, both "refuse to hand over a deliverable the caller
|
|
1962
|
+
* cannot see is broken, unless they say they know": `draft` skips the
|
|
1963
|
+
* unfilled-placeholder gate above, `allowDroppedContent` skips the
|
|
1964
|
+
* content-drop gate (`checkContentDropGate` in `./pptx/generate` — it lives
|
|
1965
|
+
* there because only a real layout can answer it, and the export renders
|
|
1966
|
+
* every slide there already).
|
|
1967
|
+
*/
|
|
1968
|
+
declare function generatePptx(input: unknown, opts?: {
|
|
1969
|
+
draft?: boolean;
|
|
1970
|
+
allowDroppedContent?: boolean;
|
|
1971
|
+
}): Promise<Uint8Array>;
|
|
1972
|
+
|
|
1973
|
+
/**
|
|
1974
|
+
* The frozen IR v3 top-level shape (vocabulary-v4 rename, task 1 — spec
|
|
1975
|
+
* §9.3: "v3 已冻结... 顶层字段和枚举改名必须进入新的 IR 版本,不能在 v3
|
|
1976
|
+
* 内静默改变含义"). `./index.ts`'s `PptxIRSchema` is v4 now — this module
|
|
1977
|
+
* exists only so a genuinely v3-shaped document still has somewhere to parse
|
|
1978
|
+
* against: `migrateIrV3ToV4`'s input type (`./migrate.ts`), and the
|
|
1979
|
+
* v3-hard-reject path's own tests (constructing a *valid* v3 IR to prove the
|
|
1980
|
+
* reject fires on version alone, not on some other schema defect).
|
|
1981
|
+
*
|
|
1982
|
+
* `validateIr` (`src/api.ts`) never calls this schema itself — an incoming
|
|
1983
|
+
* v3 document (`version === "3"`) is hard-rejected before any schema parse
|
|
1984
|
+
* runs at all (spec §9.3), full stop. This schema is a migration-tooling and
|
|
1985
|
+
* test fixture, not a second accepted input shape.
|
|
1986
|
+
*
|
|
1987
|
+
* Every field but `version` and `scenario` is byte-identical to `./index.ts`'s
|
|
1988
|
+
* v4 `PptxIRSchema` (spec §9.1: "其余 IR 字段保持不变") — reuses the exact
|
|
1989
|
+
* same `ThemeSchema`/`MetaSchema`/`AssetsSchema`/`BrandSchema`/`SlideSchema`
|
|
1990
|
+
* instances rather than redefining them, so there is no way for this frozen
|
|
1991
|
+
* shape to silently drift from the fields it shares with v4.
|
|
1992
|
+
*/
|
|
1993
|
+
declare const PptxIRV3Schema: z.ZodObject<{
|
|
1994
|
+
version: z.ZodDefault<z.ZodLiteral<"3">>;
|
|
1995
|
+
filename: z.ZodDefault<z.ZodString>;
|
|
1996
|
+
scenario: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
1997
|
+
theme: z.ZodDefault<z.ZodObject<{
|
|
1998
|
+
id: z.ZodDefault<z.ZodString>;
|
|
1999
|
+
style: z.ZodOptional<z.ZodObject<{
|
|
2000
|
+
colors: z.ZodOptional<z.ZodObject<{
|
|
2001
|
+
bg: z.ZodOptional<z.ZodString>;
|
|
2002
|
+
surface: z.ZodOptional<z.ZodString>;
|
|
2003
|
+
panel: z.ZodOptional<z.ZodString>;
|
|
2004
|
+
primary: z.ZodOptional<z.ZodString>;
|
|
2005
|
+
accent: z.ZodOptional<z.ZodString>;
|
|
2006
|
+
text: z.ZodOptional<z.ZodString>;
|
|
2007
|
+
muted: z.ZodOptional<z.ZodString>;
|
|
2008
|
+
border: z.ZodOptional<z.ZodString>;
|
|
2009
|
+
chartPalette: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2010
|
+
accentPool: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2011
|
+
cardStroke: z.ZodOptional<z.ZodString>;
|
|
2012
|
+
}, z.core.$strict>>;
|
|
2013
|
+
fonts: z.ZodOptional<z.ZodObject<{
|
|
2014
|
+
heading: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2015
|
+
body: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2016
|
+
mono: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2017
|
+
}, z.core.$strict>>;
|
|
2018
|
+
shape: z.ZodOptional<z.ZodObject<{
|
|
2019
|
+
radius: z.ZodOptional<z.ZodNumber>;
|
|
2020
|
+
gapScale: z.ZodOptional<z.ZodNumber>;
|
|
2021
|
+
typeScale: z.ZodOptional<z.ZodNumber>;
|
|
2022
|
+
}, z.core.$strict>>;
|
|
2023
|
+
}, z.core.$strict>>;
|
|
2024
|
+
brand: z.ZodOptional<z.ZodObject<{
|
|
2025
|
+
suppressFooterOnCardContent: z.ZodOptional<z.ZodBoolean>;
|
|
2026
|
+
suppressFooterRule: z.ZodOptional<z.ZodBoolean>;
|
|
2027
|
+
suppressFooterMeta: z.ZodOptional<z.ZodBoolean>;
|
|
2028
|
+
}, z.core.$strict>>;
|
|
2029
|
+
}, z.core.$strict>>;
|
|
2030
|
+
meta: z.ZodDefault<z.ZodObject<{
|
|
2031
|
+
organization: z.ZodOptional<z.ZodString>;
|
|
2032
|
+
authors: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
2033
|
+
name: z.ZodString;
|
|
2034
|
+
role: z.ZodOptional<z.ZodString>;
|
|
2035
|
+
org: z.ZodOptional<z.ZodString>;
|
|
2036
|
+
}, z.core.$strict>>>;
|
|
2037
|
+
date: z.ZodOptional<z.ZodString>;
|
|
2038
|
+
version: z.ZodOptional<z.ZodString>;
|
|
2039
|
+
confidentiality: z.ZodOptional<z.ZodEnum<{
|
|
2040
|
+
public: "public";
|
|
2041
|
+
internal: "internal";
|
|
2042
|
+
confidential: "confidential";
|
|
2043
|
+
restricted: "restricted";
|
|
2044
|
+
}>>;
|
|
2045
|
+
contact: z.ZodOptional<z.ZodObject<{
|
|
2046
|
+
name: z.ZodOptional<z.ZodString>;
|
|
2047
|
+
email: z.ZodOptional<z.ZodString>;
|
|
2048
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
2049
|
+
website: z.ZodOptional<z.ZodString>;
|
|
2050
|
+
}, z.core.$strict>>;
|
|
2051
|
+
copyright: z.ZodOptional<z.ZodString>;
|
|
2052
|
+
animation: z.ZodOptional<z.ZodObject<{
|
|
2053
|
+
transition: z.ZodOptional<z.ZodEnum<{
|
|
2054
|
+
push: "push";
|
|
2055
|
+
none: "none";
|
|
2056
|
+
fade: "fade";
|
|
2057
|
+
wipe: "wipe";
|
|
2058
|
+
}>>;
|
|
2059
|
+
elements: z.ZodOptional<z.ZodEnum<{
|
|
2060
|
+
none: "none";
|
|
2061
|
+
auto: "auto";
|
|
2062
|
+
}>>;
|
|
2063
|
+
}, z.core.$strict>>;
|
|
2064
|
+
}, z.core.$strict>>;
|
|
2065
|
+
assets: z.ZodDefault<z.ZodObject<{
|
|
2066
|
+
images: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
2067
|
+
src: z.ZodString;
|
|
2068
|
+
alt: z.ZodOptional<z.ZodString>;
|
|
2069
|
+
error: z.ZodOptional<z.ZodString>;
|
|
2070
|
+
}, z.core.$strict>>>;
|
|
2071
|
+
}, z.core.$strict>>;
|
|
2072
|
+
brand: z.ZodOptional<z.ZodObject<{
|
|
2073
|
+
logo_asset_id: z.ZodOptional<z.ZodString>;
|
|
2074
|
+
position: z.ZodOptional<z.ZodEnum<{
|
|
2075
|
+
tl: "tl";
|
|
2076
|
+
tr: "tr";
|
|
2077
|
+
bl: "bl";
|
|
2078
|
+
br: "br";
|
|
2079
|
+
}>>;
|
|
2080
|
+
}, z.core.$strict>>;
|
|
2081
|
+
chrome: z.ZodOptional<z.ZodEnum<{
|
|
2082
|
+
full: "full";
|
|
2083
|
+
"cover-only": "cover-only";
|
|
2084
|
+
minimal: "minimal";
|
|
2085
|
+
}>>;
|
|
2086
|
+
seed: z.ZodOptional<z.ZodNumber>;
|
|
2087
|
+
slides: z.ZodArray<z.ZodObject<{
|
|
2088
|
+
type: z.ZodDefault<z.ZodEnum<{
|
|
2089
|
+
content: "content";
|
|
2090
|
+
cover: "cover";
|
|
2091
|
+
chapter: "chapter";
|
|
2092
|
+
ending: "ending";
|
|
2093
|
+
}>>;
|
|
2094
|
+
id: z.ZodOptional<z.ZodString>;
|
|
2095
|
+
placeholder: z.ZodOptional<z.ZodLiteral<true>>;
|
|
2096
|
+
layout: z.ZodOptional<z.ZodString>;
|
|
2097
|
+
beat: z.ZodOptional<z.ZodEnum<{
|
|
2098
|
+
dense: "dense";
|
|
2099
|
+
anchor: "anchor";
|
|
2100
|
+
breathing: "breathing";
|
|
2101
|
+
}>>;
|
|
2102
|
+
arrangement: z.ZodOptional<z.ZodEnum<{
|
|
2103
|
+
code: "code";
|
|
2104
|
+
quote: "quote";
|
|
2105
|
+
single: "single";
|
|
2106
|
+
two_column: "two_column";
|
|
2107
|
+
kpi_focus: "kpi_focus";
|
|
2108
|
+
image_focus: "image_focus";
|
|
2109
|
+
big_number: "big_number";
|
|
2110
|
+
assertion_evidence: "assertion_evidence";
|
|
2111
|
+
aside: "aside";
|
|
2112
|
+
}>>;
|
|
2113
|
+
heading: z.ZodOptional<z.ZodString>;
|
|
2114
|
+
subheading: z.ZodOptional<z.ZodString>;
|
|
2115
|
+
components: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
2116
|
+
type: z.ZodLiteral<"bullets">;
|
|
2117
|
+
items: z.ZodArray<z.ZodString>;
|
|
2118
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
2119
|
+
default: "default";
|
|
2120
|
+
checklist: "checklist";
|
|
2121
|
+
numbered: "numbered";
|
|
2122
|
+
plain: "plain";
|
|
2123
|
+
divided: "divided";
|
|
2124
|
+
}>>;
|
|
2125
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2126
|
+
type: z.ZodLiteral<"paragraph">;
|
|
2127
|
+
text: z.ZodString;
|
|
2128
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2129
|
+
type: z.ZodLiteral<"quote">;
|
|
2130
|
+
text: z.ZodString;
|
|
2131
|
+
attribution: z.ZodOptional<z.ZodString>;
|
|
2132
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2133
|
+
type: z.ZodLiteral<"callout">;
|
|
2134
|
+
variant: z.ZodEnum<{
|
|
2135
|
+
info: "info";
|
|
2136
|
+
warn: "warn";
|
|
2137
|
+
tip: "tip";
|
|
2138
|
+
}>;
|
|
2139
|
+
text: z.ZodString;
|
|
2140
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
2141
|
+
[x: string]: string;
|
|
2142
|
+
}>>;
|
|
2143
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2144
|
+
type: z.ZodLiteral<"code">;
|
|
2145
|
+
language: z.ZodString;
|
|
2146
|
+
code: z.ZodString;
|
|
2147
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2148
|
+
type: z.ZodLiteral<"kpi_cards">;
|
|
2149
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2150
|
+
value: z.ZodString;
|
|
2151
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
2152
|
+
label: z.ZodString;
|
|
2153
|
+
delta: z.ZodOptional<z.ZodEnum<{
|
|
2154
|
+
flat: "flat";
|
|
2155
|
+
up: "up";
|
|
2156
|
+
down: "down";
|
|
2157
|
+
}>>;
|
|
2158
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
2159
|
+
[x: string]: string;
|
|
2160
|
+
}>>;
|
|
2161
|
+
source: z.ZodOptional<z.ZodString>;
|
|
2162
|
+
}, z.core.$strict>>;
|
|
2163
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2164
|
+
type: z.ZodLiteral<"chart">;
|
|
2165
|
+
chart_type: z.ZodEnum<{
|
|
2166
|
+
line: "line";
|
|
2167
|
+
donut: "donut";
|
|
2168
|
+
dumbbell: "dumbbell";
|
|
2169
|
+
funnel: "funnel";
|
|
2170
|
+
gauge: "gauge";
|
|
2171
|
+
bar: "bar";
|
|
2172
|
+
pie: "pie";
|
|
2173
|
+
scatter: "scatter";
|
|
2174
|
+
area: "area";
|
|
2175
|
+
}>;
|
|
2176
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
2177
|
+
horizontal: "horizontal";
|
|
2178
|
+
vertical: "vertical";
|
|
2179
|
+
}>>;
|
|
2180
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
2181
|
+
donut: "donut";
|
|
2182
|
+
}>>;
|
|
2183
|
+
center_total: z.ZodOptional<z.ZodBoolean>;
|
|
2184
|
+
gauge: z.ZodOptional<z.ZodObject<{
|
|
2185
|
+
min: z.ZodOptional<z.ZodNumber>;
|
|
2186
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
2187
|
+
}, z.core.$strict>>;
|
|
2188
|
+
axes: z.ZodOptional<z.ZodObject<{
|
|
2189
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
2190
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
2191
|
+
show_grid: z.ZodOptional<z.ZodBoolean>;
|
|
2192
|
+
}, z.core.$strict>>;
|
|
2193
|
+
series: z.ZodArray<z.ZodObject<{
|
|
2194
|
+
name: z.ZodString;
|
|
2195
|
+
data: z.ZodArray<z.ZodObject<{
|
|
2196
|
+
x: z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>;
|
|
2197
|
+
y: z.ZodNumber;
|
|
2198
|
+
size: z.ZodOptional<z.ZodNumber>;
|
|
2199
|
+
}, z.core.$strict>>;
|
|
2200
|
+
}, z.core.$strict>>;
|
|
2201
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2202
|
+
type: z.ZodLiteral<"flowchart">;
|
|
2203
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
2204
|
+
id: z.ZodString;
|
|
2205
|
+
label: z.ZodString;
|
|
2206
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
2207
|
+
rect: "rect";
|
|
2208
|
+
diamond: "diamond";
|
|
2209
|
+
round: "round";
|
|
2210
|
+
}>>;
|
|
2211
|
+
}, z.core.$strict>>;
|
|
2212
|
+
edges: z.ZodArray<z.ZodObject<{
|
|
2213
|
+
from: z.ZodString;
|
|
2214
|
+
to: z.ZodString;
|
|
2215
|
+
label: z.ZodOptional<z.ZodString>;
|
|
2216
|
+
}, z.core.$strict>>;
|
|
2217
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
2218
|
+
TB: "TB";
|
|
2219
|
+
TD: "TD";
|
|
2220
|
+
BT: "BT";
|
|
2221
|
+
LR: "LR";
|
|
2222
|
+
RL: "RL";
|
|
2223
|
+
}>>;
|
|
2224
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2225
|
+
type: z.ZodLiteral<"architecture">;
|
|
2226
|
+
layers: z.ZodArray<z.ZodObject<{
|
|
2227
|
+
title: z.ZodString;
|
|
2228
|
+
items: z.ZodArray<z.ZodString>;
|
|
2229
|
+
}, z.core.$strict>>;
|
|
2230
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
2231
|
+
top_down: "top_down";
|
|
2232
|
+
bottom_up: "bottom_up";
|
|
2233
|
+
}>>;
|
|
2234
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2235
|
+
type: z.ZodLiteral<"timeline">;
|
|
2236
|
+
layout: z.ZodOptional<z.ZodEnum<{
|
|
2237
|
+
horizontal: "horizontal";
|
|
2238
|
+
vertical: "vertical";
|
|
2239
|
+
}>>;
|
|
2240
|
+
milestones: z.ZodArray<z.ZodObject<{
|
|
2241
|
+
date: z.ZodString;
|
|
2242
|
+
title: z.ZodString;
|
|
2243
|
+
desc: z.ZodOptional<z.ZodString>;
|
|
2244
|
+
highlight: z.ZodOptional<z.ZodBoolean>;
|
|
2245
|
+
}, z.core.$strict>>;
|
|
2246
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2247
|
+
type: z.ZodLiteral<"comparison">;
|
|
2248
|
+
columns: z.ZodArray<z.ZodString>;
|
|
2249
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
2250
|
+
label: z.ZodString;
|
|
2251
|
+
cells: z.ZodArray<z.ZodString>;
|
|
2252
|
+
}, z.core.$strict>>;
|
|
2253
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2254
|
+
type: z.ZodLiteral<"icon_cards">;
|
|
2255
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2256
|
+
icon: z.ZodEnum<{
|
|
2257
|
+
[x: string]: string;
|
|
2258
|
+
}>;
|
|
2259
|
+
title: z.ZodString;
|
|
2260
|
+
text: z.ZodString;
|
|
2261
|
+
}, z.core.$strict>>;
|
|
2262
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2263
|
+
type: z.ZodLiteral<"row_cards">;
|
|
2264
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2265
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
2266
|
+
[x: string]: string;
|
|
2267
|
+
}>>;
|
|
2268
|
+
title: z.ZodString;
|
|
2269
|
+
text: z.ZodOptional<z.ZodString>;
|
|
2270
|
+
sub: z.ZodOptional<z.ZodString>;
|
|
2271
|
+
highlight: z.ZodOptional<z.ZodBoolean>;
|
|
2272
|
+
}, z.core.$strict>>;
|
|
2273
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2274
|
+
type: z.ZodLiteral<"steps">;
|
|
2275
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2276
|
+
title: z.ZodString;
|
|
2277
|
+
text: z.ZodString;
|
|
2278
|
+
}, z.core.$strict>>;
|
|
2279
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2280
|
+
type: z.ZodLiteral<"rings">;
|
|
2281
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2282
|
+
label: z.ZodString;
|
|
2283
|
+
desc: z.ZodOptional<z.ZodString>;
|
|
2284
|
+
}, z.core.$strict>>;
|
|
2285
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2286
|
+
type: z.ZodLiteral<"numbered_cards">;
|
|
2287
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2288
|
+
title: z.ZodString;
|
|
2289
|
+
text: z.ZodOptional<z.ZodString>;
|
|
2290
|
+
sub: z.ZodOptional<z.ZodString>;
|
|
2291
|
+
}, z.core.$strict>>;
|
|
2292
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2293
|
+
type: z.ZodLiteral<"roadmap">;
|
|
2294
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2295
|
+
title: z.ZodString;
|
|
2296
|
+
period: z.ZodOptional<z.ZodString>;
|
|
2297
|
+
rows: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
2298
|
+
label: z.ZodString;
|
|
2299
|
+
value: z.ZodString;
|
|
2300
|
+
}, z.core.$strict>>>;
|
|
2301
|
+
}, z.core.$strict>>;
|
|
2302
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2303
|
+
type: z.ZodLiteral<"matrix">;
|
|
2304
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
2305
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
2306
|
+
cols: z.ZodNumber;
|
|
2307
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2308
|
+
title: z.ZodString;
|
|
2309
|
+
tag: z.ZodOptional<z.ZodString>;
|
|
2310
|
+
tone: z.ZodOptional<z.ZodEnum<{
|
|
2311
|
+
info: "info";
|
|
2312
|
+
neutral: "neutral";
|
|
2313
|
+
accent: "accent";
|
|
2314
|
+
}>>;
|
|
2315
|
+
}, z.core.$strict>>;
|
|
2316
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2317
|
+
type: z.ZodLiteral<"insight_panel">;
|
|
2318
|
+
title: z.ZodString;
|
|
2319
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
2320
|
+
label: z.ZodString;
|
|
2321
|
+
text: z.ZodString;
|
|
2322
|
+
}, z.core.$strict>>;
|
|
2323
|
+
footnote: z.ZodOptional<z.ZodString>;
|
|
2324
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2325
|
+
type: z.ZodLiteral<"verdict_banner">;
|
|
2326
|
+
text: z.ZodString;
|
|
2327
|
+
tone: z.ZodEnum<{
|
|
2328
|
+
positive: "positive";
|
|
2329
|
+
warning: "warning";
|
|
2330
|
+
neutral: "neutral";
|
|
2331
|
+
}>;
|
|
2332
|
+
icon: z.ZodOptional<z.ZodEnum<{
|
|
2333
|
+
[x: string]: string;
|
|
2334
|
+
}>>;
|
|
2335
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2336
|
+
type: z.ZodLiteral<"citation">;
|
|
2337
|
+
sources: z.ZodArray<z.ZodObject<{
|
|
2338
|
+
label: z.ZodString;
|
|
2339
|
+
url: z.ZodOptional<z.ZodString>;
|
|
2340
|
+
ref: z.ZodOptional<z.ZodString>;
|
|
2341
|
+
}, z.core.$strict>>;
|
|
2342
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2343
|
+
type: z.ZodLiteral<"image">;
|
|
2344
|
+
asset_id: z.ZodString;
|
|
2345
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
2346
|
+
fit: z.ZodDefault<z.ZodEnum<{
|
|
2347
|
+
contain: "contain";
|
|
2348
|
+
cover: "cover";
|
|
2349
|
+
}>>;
|
|
2350
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2351
|
+
type: z.ZodLiteral<"image_grid">;
|
|
2352
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2353
|
+
asset_id: z.ZodString;
|
|
2354
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
2355
|
+
}, z.core.$strict>>;
|
|
2356
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
2357
|
+
none: "none";
|
|
2358
|
+
first: "first";
|
|
2359
|
+
}>>;
|
|
2360
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2361
|
+
type: z.ZodLiteral<"image_compare">;
|
|
2362
|
+
left: z.ZodObject<{
|
|
2363
|
+
asset_id: z.ZodString;
|
|
2364
|
+
label: z.ZodString;
|
|
2365
|
+
}, z.core.$strict>;
|
|
2366
|
+
right: z.ZodObject<{
|
|
2367
|
+
asset_id: z.ZodString;
|
|
2368
|
+
label: z.ZodString;
|
|
2369
|
+
}, z.core.$strict>;
|
|
2370
|
+
style: z.ZodOptional<z.ZodEnum<{
|
|
2371
|
+
vs: "vs";
|
|
2372
|
+
before_after: "before_after";
|
|
2373
|
+
}>>;
|
|
2374
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2375
|
+
type: z.ZodLiteral<"swot">;
|
|
2376
|
+
strengths: z.ZodArray<z.ZodString>;
|
|
2377
|
+
weaknesses: z.ZodArray<z.ZodString>;
|
|
2378
|
+
opportunities: z.ZodArray<z.ZodString>;
|
|
2379
|
+
threats: z.ZodArray<z.ZodString>;
|
|
2380
|
+
labels: z.ZodOptional<z.ZodObject<{
|
|
2381
|
+
strengths: z.ZodOptional<z.ZodString>;
|
|
2382
|
+
weaknesses: z.ZodOptional<z.ZodString>;
|
|
2383
|
+
opportunities: z.ZodOptional<z.ZodString>;
|
|
2384
|
+
threats: z.ZodOptional<z.ZodString>;
|
|
2385
|
+
}, z.core.$strict>>;
|
|
2386
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2387
|
+
type: z.ZodLiteral<"bmc">;
|
|
2388
|
+
key_partners: z.ZodArray<z.ZodString>;
|
|
2389
|
+
key_activities: z.ZodArray<z.ZodString>;
|
|
2390
|
+
key_resources: z.ZodArray<z.ZodString>;
|
|
2391
|
+
value_propositions: z.ZodArray<z.ZodString>;
|
|
2392
|
+
customer_relationships: z.ZodArray<z.ZodString>;
|
|
2393
|
+
channels: z.ZodArray<z.ZodString>;
|
|
2394
|
+
customer_segments: z.ZodArray<z.ZodString>;
|
|
2395
|
+
cost_structure: z.ZodArray<z.ZodString>;
|
|
2396
|
+
revenue_streams: z.ZodArray<z.ZodString>;
|
|
2397
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2398
|
+
type: z.ZodLiteral<"waterfall">;
|
|
2399
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2400
|
+
label: z.ZodString;
|
|
2401
|
+
value: z.ZodNumber;
|
|
2402
|
+
kind: z.ZodOptional<z.ZodEnum<{
|
|
2403
|
+
delta: "delta";
|
|
2404
|
+
total: "total";
|
|
2405
|
+
}>>;
|
|
2406
|
+
}, z.core.$strict>>;
|
|
2407
|
+
unit: z.ZodOptional<z.ZodString>;
|
|
2408
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2409
|
+
type: z.ZodLiteral<"gantt">;
|
|
2410
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2411
|
+
label: z.ZodString;
|
|
2412
|
+
start: z.ZodNumber;
|
|
2413
|
+
end: z.ZodNumber;
|
|
2414
|
+
}, z.core.$strict>>;
|
|
2415
|
+
axis_labels: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
2416
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2417
|
+
type: z.ZodLiteral<"pest">;
|
|
2418
|
+
political: z.ZodObject<{
|
|
2419
|
+
title: z.ZodOptional<z.ZodString>;
|
|
2420
|
+
items: z.ZodArray<z.ZodString>;
|
|
2421
|
+
}, z.core.$strict>;
|
|
2422
|
+
economic: z.ZodObject<{
|
|
2423
|
+
title: z.ZodOptional<z.ZodString>;
|
|
2424
|
+
items: z.ZodArray<z.ZodString>;
|
|
2425
|
+
}, z.core.$strict>;
|
|
2426
|
+
social: z.ZodObject<{
|
|
2427
|
+
title: z.ZodOptional<z.ZodString>;
|
|
2428
|
+
items: z.ZodArray<z.ZodString>;
|
|
2429
|
+
}, z.core.$strict>;
|
|
2430
|
+
technological: z.ZodObject<{
|
|
2431
|
+
title: z.ZodOptional<z.ZodString>;
|
|
2432
|
+
items: z.ZodArray<z.ZodString>;
|
|
2433
|
+
}, z.core.$strict>;
|
|
2434
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2435
|
+
type: z.ZodLiteral<"five_forces">;
|
|
2436
|
+
rivalry: z.ZodObject<{
|
|
2437
|
+
label: z.ZodOptional<z.ZodString>;
|
|
2438
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
2439
|
+
low: "low";
|
|
2440
|
+
medium: "medium";
|
|
2441
|
+
high: "high";
|
|
2442
|
+
}>>;
|
|
2443
|
+
items: z.ZodArray<z.ZodString>;
|
|
2444
|
+
}, z.core.$strict>;
|
|
2445
|
+
new_entrants: z.ZodObject<{
|
|
2446
|
+
label: z.ZodOptional<z.ZodString>;
|
|
2447
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
2448
|
+
low: "low";
|
|
2449
|
+
medium: "medium";
|
|
2450
|
+
high: "high";
|
|
2451
|
+
}>>;
|
|
2452
|
+
items: z.ZodArray<z.ZodString>;
|
|
2453
|
+
}, z.core.$strict>;
|
|
2454
|
+
supplier_power: z.ZodObject<{
|
|
2455
|
+
label: z.ZodOptional<z.ZodString>;
|
|
2456
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
2457
|
+
low: "low";
|
|
2458
|
+
medium: "medium";
|
|
2459
|
+
high: "high";
|
|
2460
|
+
}>>;
|
|
2461
|
+
items: z.ZodArray<z.ZodString>;
|
|
2462
|
+
}, z.core.$strict>;
|
|
2463
|
+
buyer_power: z.ZodObject<{
|
|
2464
|
+
label: z.ZodOptional<z.ZodString>;
|
|
2465
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
2466
|
+
low: "low";
|
|
2467
|
+
medium: "medium";
|
|
2468
|
+
high: "high";
|
|
2469
|
+
}>>;
|
|
2470
|
+
items: z.ZodArray<z.ZodString>;
|
|
2471
|
+
}, z.core.$strict>;
|
|
2472
|
+
substitutes: z.ZodObject<{
|
|
2473
|
+
label: z.ZodOptional<z.ZodString>;
|
|
2474
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
2475
|
+
low: "low";
|
|
2476
|
+
medium: "medium";
|
|
2477
|
+
high: "high";
|
|
2478
|
+
}>>;
|
|
2479
|
+
items: z.ZodArray<z.ZodString>;
|
|
2480
|
+
}, z.core.$strict>;
|
|
2481
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2482
|
+
type: z.ZodLiteral<"heatmap">;
|
|
2483
|
+
x_labels: z.ZodArray<z.ZodString>;
|
|
2484
|
+
y_labels: z.ZodArray<z.ZodString>;
|
|
2485
|
+
values: z.ZodArray<z.ZodArray<z.ZodNumber>>;
|
|
2486
|
+
domain: z.ZodOptional<z.ZodObject<{
|
|
2487
|
+
min: z.ZodNumber;
|
|
2488
|
+
max: z.ZodNumber;
|
|
2489
|
+
}, z.core.$strict>>;
|
|
2490
|
+
show_values: z.ZodOptional<z.ZodBoolean>;
|
|
2491
|
+
x_title: z.ZodOptional<z.ZodString>;
|
|
2492
|
+
y_title: z.ZodOptional<z.ZodString>;
|
|
2493
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2494
|
+
type: z.ZodLiteral<"sankey">;
|
|
2495
|
+
nodes: z.ZodArray<z.ZodObject<{
|
|
2496
|
+
id: z.ZodString;
|
|
2497
|
+
label: z.ZodString;
|
|
2498
|
+
}, z.core.$strict>>;
|
|
2499
|
+
links: z.ZodArray<z.ZodObject<{
|
|
2500
|
+
from: z.ZodString;
|
|
2501
|
+
to: z.ZodString;
|
|
2502
|
+
value: z.ZodNumber;
|
|
2503
|
+
}, z.core.$strict>>;
|
|
2504
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2505
|
+
type: z.ZodLiteral<"data_table">;
|
|
2506
|
+
columns: z.ZodArray<z.ZodObject<{
|
|
2507
|
+
key: z.ZodString;
|
|
2508
|
+
label: z.ZodString;
|
|
2509
|
+
align: z.ZodOptional<z.ZodEnum<{
|
|
2510
|
+
left: "left";
|
|
2511
|
+
right: "right";
|
|
2512
|
+
center: "center";
|
|
2513
|
+
}>>;
|
|
2514
|
+
}, z.core.$strict>>;
|
|
2515
|
+
rows: z.ZodArray<z.ZodObject<{
|
|
2516
|
+
cells: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
|
|
2517
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
2518
|
+
highlight: "highlight";
|
|
2519
|
+
total: "total";
|
|
2520
|
+
}>>;
|
|
2521
|
+
}, z.core.$strict>>;
|
|
2522
|
+
source: z.ZodOptional<z.ZodString>;
|
|
2523
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2524
|
+
type: z.ZodLiteral<"device_mockup">;
|
|
2525
|
+
device: z.ZodEnum<{
|
|
2526
|
+
phone: "phone";
|
|
2527
|
+
browser: "browser";
|
|
2528
|
+
}>;
|
|
2529
|
+
asset_id: z.ZodString;
|
|
2530
|
+
caption: z.ZodOptional<z.ZodString>;
|
|
2531
|
+
url: z.ZodOptional<z.ZodString>;
|
|
2532
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2533
|
+
type: z.ZodLiteral<"cycle">;
|
|
2534
|
+
title: z.ZodOptional<z.ZodString>;
|
|
2535
|
+
items: z.ZodArray<z.ZodObject<{
|
|
2536
|
+
label: z.ZodString;
|
|
2537
|
+
description: z.ZodOptional<z.ZodString>;
|
|
2538
|
+
}, z.core.$strict>>;
|
|
2539
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2540
|
+
type: z.ZodLiteral<"people_cards">;
|
|
2541
|
+
title: z.ZodOptional<z.ZodString>;
|
|
2542
|
+
people: z.ZodArray<z.ZodObject<{
|
|
2543
|
+
name: z.ZodString;
|
|
2544
|
+
role: z.ZodOptional<z.ZodString>;
|
|
2545
|
+
org: z.ZodOptional<z.ZodString>;
|
|
2546
|
+
}, z.core.$strict>>;
|
|
2547
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2548
|
+
type: z.ZodLiteral<"tag_row">;
|
|
2549
|
+
title: z.ZodOptional<z.ZodString>;
|
|
2550
|
+
items: z.ZodArray<z.ZodString>;
|
|
2551
|
+
emphasis: z.ZodOptional<z.ZodEnum<{
|
|
2552
|
+
none: "none";
|
|
2553
|
+
first: "first";
|
|
2554
|
+
}>>;
|
|
2555
|
+
}, z.core.$strict>], "type">>>;
|
|
2556
|
+
background: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
2557
|
+
kind: z.ZodLiteral<"color">;
|
|
2558
|
+
value: z.ZodString;
|
|
2559
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2560
|
+
kind: z.ZodLiteral<"gradient">;
|
|
2561
|
+
from: z.ZodString;
|
|
2562
|
+
to: z.ZodString;
|
|
2563
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
2564
|
+
tb: "tb";
|
|
2565
|
+
lr: "lr";
|
|
2566
|
+
diagonal: "diagonal";
|
|
2567
|
+
}>>;
|
|
2568
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
2569
|
+
kind: z.ZodLiteral<"asset">;
|
|
2570
|
+
asset_id: z.ZodString;
|
|
2571
|
+
overlay: z.ZodOptional<z.ZodObject<{
|
|
2572
|
+
color: z.ZodString;
|
|
2573
|
+
opacity: z.ZodNumber;
|
|
2574
|
+
}, z.core.$strict>>;
|
|
2575
|
+
fit: z.ZodOptional<z.ZodEnum<{
|
|
2576
|
+
contain: "contain";
|
|
2577
|
+
cover: "cover";
|
|
2578
|
+
}>>;
|
|
2579
|
+
}, z.core.$strict>], "kind">>;
|
|
2580
|
+
decor: z.ZodOptional<z.ZodObject<{
|
|
2581
|
+
kind: z.ZodEnum<{
|
|
2582
|
+
big_number: "big_number";
|
|
2583
|
+
corner_tag: "corner_tag";
|
|
2584
|
+
rule_line: "rule_line";
|
|
2585
|
+
quote_marks: "quote_marks";
|
|
2586
|
+
geo_dots: "geo_dots";
|
|
2587
|
+
}>;
|
|
2588
|
+
intensity: z.ZodOptional<z.ZodEnum<{
|
|
2589
|
+
subtle: "subtle";
|
|
2590
|
+
normal: "normal";
|
|
2591
|
+
}>>;
|
|
2592
|
+
text: z.ZodOptional<z.ZodString>;
|
|
2593
|
+
}, z.core.$strict>>;
|
|
2594
|
+
image_side: z.ZodOptional<z.ZodEnum<{
|
|
2595
|
+
left: "left";
|
|
2596
|
+
right: "right";
|
|
2597
|
+
}>>;
|
|
2598
|
+
footnote: z.ZodOptional<z.ZodString>;
|
|
2599
|
+
notes: z.ZodOptional<z.ZodString>;
|
|
2600
|
+
}, z.core.$strict>>;
|
|
2601
|
+
}, z.core.$strict>;
|
|
2602
|
+
type PptxIRV3 = z.infer<typeof PptxIRV3Schema>;
|
|
2603
|
+
|
|
2604
|
+
/**
|
|
2605
|
+
* Deterministic, pure IR v3 → v4 migration (spec §9.1). Field-for-field,
|
|
2606
|
+
* value-for-value per the mapping in {@link migrateNarrativeInput}'s
|
|
2607
|
+
* docstring — every field this function doesn't touch (`filename`, `theme`,
|
|
2608
|
+
* `meta`, `assets`, `brand`, `seed`, `slides`) carries across by the exact
|
|
2609
|
+
* same reference it came in with, unchanged (spec §9.1: "其余 IR 字段保持不
|
|
2610
|
+
* 变"; spec §10: no weight/budget/selection/render change is in scope for
|
|
2611
|
+
* this migration, ever).
|
|
2612
|
+
*
|
|
2613
|
+
* Exported from the SDK surface (`src/index.ts`) as the deterministic
|
|
2614
|
+
* migration primitive the `pptwise migrate` CLI command (task 2) wraps —
|
|
2615
|
+
* this function itself does no I/O and never runs a model, per spec §9.3's
|
|
2616
|
+
* "只做已声明的结构映射,不运行模型,不重写内容,不重新选择 layout".
|
|
2617
|
+
*
|
|
2618
|
+
* Takes an already-parsed `PptxIRV3` (i.e. `PptxIRV3Schema.parse(...)`'s
|
|
2619
|
+
* output, defaults already applied) rather than raw `unknown` JSON — schema
|
|
2620
|
+
* validation of the v3 input is the caller's job (the CLI parses-then-
|
|
2621
|
+
* migrates; `validateIr`'s own v3 path hard-rejects before ever reaching
|
|
2622
|
+
* this function, spec §9.3, so `validateIr` itself never calls this).
|
|
2623
|
+
*/
|
|
2624
|
+
declare function migrateIrV3ToV4(v3: PptxIRV3): PptxIR;
|
|
2625
|
+
|
|
2626
|
+
type LayoutType = "cover" | "chapter" | "content" | "ending";
|
|
2627
|
+
interface StyleColors {
|
|
2628
|
+
bg: string;
|
|
2629
|
+
surface: string;
|
|
2630
|
+
panel?: string;
|
|
2631
|
+
primary: string;
|
|
2632
|
+
accent: string;
|
|
2633
|
+
text: string;
|
|
2634
|
+
muted: string;
|
|
2635
|
+
border?: string;
|
|
2636
|
+
chartPalette: string[];
|
|
2637
|
+
/**
|
|
2638
|
+
* Optional accent color pool for themes whose layout grammar cycles through
|
|
2639
|
+
* multiple accent colors (e.g. tech card corner stripes). Themes that
|
|
2640
|
+
* only use a single accent color can omit this.
|
|
2641
|
+
*/
|
|
2642
|
+
accentPool?: string[];
|
|
2643
|
+
/**
|
|
2644
|
+
* Optional hairline stroke color for the shared "surface card" shells
|
|
2645
|
+
* (kpi_cards / icon_cards / callout — see components/kpi.tsx,
|
|
2646
|
+
* components/icon-cards.tsx, components/callout.tsx). Those component renderers are
|
|
2647
|
+
* shared across every theme and must stay theme-agnostic (no
|
|
2648
|
+
* `if (themeId === ...)` branching), so a theme that wants its cards
|
|
2649
|
+
* outlined sets this token instead — the renderers just consult it and add
|
|
2650
|
+
* a 1px stroke when it's defined. Omitted (`undefined`, the default) draws
|
|
2651
|
+
* no stroke, so every theme that doesn't set it keeps its current
|
|
2652
|
+
* fill-only card unchanged.
|
|
2653
|
+
*/
|
|
2654
|
+
cardStroke?: string;
|
|
2655
|
+
/**
|
|
2656
|
+
* Optional semantic-role colors — the "this is an error", "this is a
|
|
2657
|
+
* caution", "this is a good result" trio that shared component renderers
|
|
2658
|
+
* used to bake in as literal hexes (`callout`'s warn rule and icon in
|
|
2659
|
+
* components/callout.tsx, `kpi_cards`' delta arrow in components/kpi.tsx).
|
|
2660
|
+
* Same reasoning as `cardStroke` above: those renderers are shared across
|
|
2661
|
+
* every theme and must stay theme-agnostic (no `if (themeId === ...)`
|
|
2662
|
+
* branching), so a theme that wants its own red or green sets these tokens
|
|
2663
|
+
* and the renderers read them through `resolveSemanticColor`
|
|
2664
|
+
* (`src/svg/ink.ts`), which owns the fallback order.
|
|
2665
|
+
*
|
|
2666
|
+
* All three are optional on the type, and an omitted role resolves to
|
|
2667
|
+
* exactly the hex its renderers baked in before this channel existed —
|
|
2668
|
+
* `#DC2626` for `danger`, `#16A34A` for `success`, and `warning` follows
|
|
2669
|
+
* whatever `danger` resolves to. So a theme that sets none of them renders
|
|
2670
|
+
* byte-for-byte as it did before the tokens were added.
|
|
2671
|
+
*
|
|
2672
|
+
* Every one of the 22 built-in themes does set all three (visual review
|
|
2673
|
+
* round 4 ruled that the alert color must belong to the theme's own
|
|
2674
|
+
* palette, not be one universal red), so in practice only a `--theme-file`
|
|
2675
|
+
* brand theme reaches the fallbacks. `danger` and `success` are calibrated
|
|
2676
|
+
* to clear 4.5:1 on their own theme's `surface` — they render as the kpi
|
|
2677
|
+
* delta arrow's *text*, which `accessibleInk` would otherwise demote to
|
|
2678
|
+
* neutral ink — while `warning` only has to clear the 3:1 non-text floor,
|
|
2679
|
+
* since `callout` paints it as a rule and an icon. Both floors are pinned
|
|
2680
|
+
* in `svg/audit/full-matrix-contrast.test.ts`.
|
|
2681
|
+
*/
|
|
2682
|
+
danger?: string;
|
|
2683
|
+
warning?: string;
|
|
2684
|
+
success?: string;
|
|
2685
|
+
}
|
|
2686
|
+
interface StyleFonts {
|
|
2687
|
+
heading: string[];
|
|
2688
|
+
body: string[];
|
|
2689
|
+
mono?: string[];
|
|
2690
|
+
}
|
|
2691
|
+
interface StyleTokens {
|
|
2692
|
+
id: string;
|
|
2693
|
+
allowCustomBackground?: boolean;
|
|
2694
|
+
colors: StyleColors;
|
|
2695
|
+
fonts: StyleFonts;
|
|
2696
|
+
shape?: StyleShape;
|
|
2697
|
+
defaultBackgrounds: Record<LayoutType, BackgroundSpec>;
|
|
2698
|
+
}
|
|
2699
|
+
/**
|
|
2700
|
+
* 主题细节 shape token(2026-07-10 用户立项,spec:
|
|
2701
|
+
* .issues/specs/2026-07-10-pptx-theme-detail-tokens-design.md)。
|
|
2702
|
+
* 全部可选——缺省时各消费点沿用自己的 baked 值(零观感)。
|
|
2703
|
+
*/
|
|
2704
|
+
interface StyleShape {
|
|
2705
|
+
/** 卡片/横幅圆角 px(统一值)。缺省=各消费点原 baked 值(kpi 8/architecture 6/白卡 14 等)。 */
|
|
2706
|
+
radius?: number;
|
|
2707
|
+
/** 块间距缩放(1=现 BLOCK_GAP)。建议范围 [0.8, 1.3]。 */
|
|
2708
|
+
gapScale?: number;
|
|
2709
|
+
/**
|
|
2710
|
+
* Heading and display size multiplier. Applied to the layout's designed
|
|
2711
|
+
* max size *before* heading-fit shrinks to the box (`fitHeadingLines` /
|
|
2712
|
+
* `fitHeadingPt`, `src/svg/heading-fit.ts`). Cover, chapter, ending, and
|
|
2713
|
+
* pin-only speech pages pass it through. Content layouts that share the
|
|
2714
|
+
* page with a body stack omit it, so density still holds. Body, meta,
|
|
2715
|
+
* kicker, and footnote sizes are untouched. Omit (or `1`) for a
|
|
2716
|
+
* byte-identical no-op. Fit still owns the floor: `minPt` is not scaled,
|
|
2717
|
+
* so a long title still shrinks instead of overflowing. Suggested range
|
|
2718
|
+
* `[0.8, 1.6]`.
|
|
2719
|
+
*/
|
|
2720
|
+
typeScale?: number;
|
|
2721
|
+
/**
|
|
2722
|
+
* Optional cover-layout knobs. Layouts read these. They never branch on
|
|
2723
|
+
* theme id. Omit every field and the layout uses its own file constants
|
|
2724
|
+
* (`band-title`: y=260, h=200, start, no mark, no wave.
|
|
2725
|
+
* `corner-wedge`: peakY=340, startX=980, middle, meta on paper.
|
|
2726
|
+
* `poster-center`: no kicker, primary bar, centered meta.
|
|
2727
|
+
* `left-anchor`: corner triangle on, title vertically centered.
|
|
2728
|
+
* `constellation`: last line on y520, 84×4 bar.
|
|
2729
|
+
* `tone-adaptive-header`: title 92, right-bottom date shown.
|
|
2730
|
+
* `editorial-masthead`: middle anchor, no kicker).
|
|
2731
|
+
* Not part of `StyleOverrideSchema`. IR overrides stay
|
|
2732
|
+
* `{ radius, gapScale, typeScale }`.
|
|
2733
|
+
*/
|
|
2734
|
+
cover?: {
|
|
2735
|
+
textAnchor?: "start" | "middle";
|
|
2736
|
+
bandY?: number;
|
|
2737
|
+
bandH?: number;
|
|
2738
|
+
/** Small accent square on the band (enterprise). */
|
|
2739
|
+
bandMark?: boolean;
|
|
2740
|
+
/** Accent q-curve under the band (classroom). */
|
|
2741
|
+
bandWave?: boolean;
|
|
2742
|
+
wedgePeakY?: number;
|
|
2743
|
+
wedgeStartX?: number;
|
|
2744
|
+
/** Meta in readableOn(primary) inside the wedge (ember). */
|
|
2745
|
+
metaInWedge?: boolean;
|
|
2746
|
+
/** Independent kicker row above the title. Default false. poster-center + editorial-masthead. */
|
|
2747
|
+
showKicker?: boolean;
|
|
2748
|
+
/** Short bar fill. Default "primary". poster-center. */
|
|
2749
|
+
barFill?: "primary" | "accent";
|
|
2750
|
+
/** Merged meta placement. Default "center". poster-center. */
|
|
2751
|
+
metaPlacement?: "center" | "bottom-left" | "bottom-right" | "top" | "none";
|
|
2752
|
+
/** Corner triangle on the color block. Default true. left-anchor. */
|
|
2753
|
+
showCornerTriangle?: boolean;
|
|
2754
|
+
/** Title vertical alignment inside the block. Default "center". left-anchor. */
|
|
2755
|
+
titleBlockAlign?: "center" | "upper";
|
|
2756
|
+
/** Org as in-block kicker. Default false. left-anchor. */
|
|
2757
|
+
showInBlockKicker?: boolean;
|
|
2758
|
+
/** Pin last title line to y520. Default true. constellation. */
|
|
2759
|
+
titleBottomAnchor?: boolean;
|
|
2760
|
+
/** Rule under the title. Default "bar". constellation. */
|
|
2761
|
+
ruleStyle?: "bar" | "star-chain";
|
|
2762
|
+
/** Cover title size in px. Default 92. tone-adaptive-header. */
|
|
2763
|
+
titleSize?: number;
|
|
2764
|
+
/** Hide the right-bottom date/version slot. Default false. tone-adaptive-header. */
|
|
2765
|
+
hideRightMeta?: boolean;
|
|
2766
|
+
/** verdict-index. Omit for the restore-wave-1 constants. */
|
|
2767
|
+
verdictTitleY?: number;
|
|
2768
|
+
verdictTitleSize?: number;
|
|
2769
|
+
verdictKickerY?: number;
|
|
2770
|
+
verdictColNumY?: number;
|
|
2771
|
+
verdictColBodyY?: number;
|
|
2772
|
+
verdictFootY?: number;
|
|
2773
|
+
verdictFootRule?: boolean;
|
|
2774
|
+
/** corner-wedge inner overlay (ember dual wedge). Omit for the single overlay. */
|
|
2775
|
+
wedgeInnerStartX?: number;
|
|
2776
|
+
wedgeInnerPeakY?: number;
|
|
2777
|
+
};
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
type MotifId = "banner-motif" | "rail-motif" | "poster-motif" | "constellation-motif" | "corner-ornament-motif" | "tone-adaptive-motif" | "campaign-motif" | "classroom-motif" | "ink-motif" | "luxe-motif" | "enterprise-motif" | "heritage-motif" | "pulse-motif" | "terra-motif" | "ember-motif" | "vermilion-motif" | "crayon-motif" | "arena-motif" | "lecture-motif" | "swiss-motif" | "memo-motif" | "playbill-motif";
|
|
2781
|
+
|
|
2782
|
+
/**
|
|
2783
|
+
* A theme = distributable bundle: `style` (style tokens) + `brand` (brand
|
|
2784
|
+
* frame) + affinity tags (filled in W4).
|
|
2785
|
+
*
|
|
2786
|
+
* `id` is a plain `string`, not `CanonicalThemeId` — the 13 builtins satisfy
|
|
2787
|
+
* this (`CanonicalThemeId` is a subtype of `string`), but `registerTheme`
|
|
2788
|
+
* below (W3 task 4's SDK registration seam) must also accept ids outside that
|
|
2789
|
+
* closed union.
|
|
2790
|
+
*/
|
|
2791
|
+
interface ThemeDefinition {
|
|
2792
|
+
id: string;
|
|
2793
|
+
style: StyleTokens;
|
|
2794
|
+
brand: BrandConfig;
|
|
2795
|
+
tags: readonly string[];
|
|
2796
|
+
/**
|
|
2797
|
+
* 主题的「选择权」配置(spec §3 theme.layouts 命名裁决;W2 任务 2 由
|
|
2798
|
+
* src/themes/manifest.ts〔已删除〕的旧选择权类型原地迁居于此)——四页型
|
|
2799
|
+
* 各自允许哪些 layout 参与自动选型。排印/色彩在 style,这里只放集合。
|
|
2800
|
+
* **W4 全集放开**(spec §3「缺省 = 全集,策展收窄塑造个性」,design
|
|
2801
|
+
* decision 7):十三内置主题四页型默认均为 {@link fullLayoutSet} 的
|
|
2802
|
+
* 全集。design decision 7/8 曾经的六处对比度策展排除(luxe/campaign/
|
|
2803
|
+
* classroom 的 content 排除 banner-heading、tech 的 cover/content、
|
|
2804
|
+
* consulting 的 chapter)已在 W4 fix round 随对比度自适应 ink helper
|
|
2805
|
+
* (`src/svg/ink.ts`)的根因修复全部撤销。fix round 自身新发现的两处
|
|
2806
|
+
* (classroom/heritage 的 chapter 排除 fashion-chapter)也已在
|
|
2807
|
+
* post-v0.3 W8 fix round 随 `readableOn` 两墨实测对比度取优的根因修复一并
|
|
2808
|
+
* 撤销(backlog item 2)——十三主题四页型现在均为不折不扣的全集,无任何
|
|
2809
|
+
* 排除残留。页型空集 = 该页型回落调用侧兜底(十三主题四页型均非空,
|
|
2810
|
+
* `definitions.test.ts` 锁死)。id 是通用 string(不再按页型区分
|
|
2811
|
+
* layout id 联合类型)。
|
|
2812
|
+
*/
|
|
2813
|
+
layouts: Record<Slide["type"], readonly string[]>;
|
|
2814
|
+
/** Motif:单值,非 allowed-set(spec §3 示意)。undefined = 该主题无 motif 装饰(十三主题中 runway 留空,其余均已设)。 */
|
|
2815
|
+
motif?: MotifId;
|
|
2816
|
+
/**
|
|
2817
|
+
* A theme's own structural personality (theme-structure wave, task T1 —
|
|
2818
|
+
* `.issues/2026-07-26-theme-structure/plan.md`'s 控制器设计裁定 2): per
|
|
2819
|
+
* page type, the layout ids this theme's author wants `resolveLayoutId`
|
|
2820
|
+
* (`src/svg/layout-selection.ts`) to lean toward. Shape mirrors
|
|
2821
|
+
* `StrategyDefinition.layoutTendencies` (`@/narrative`) — the same "named
|
|
2822
|
+
* ids get a soft weight bump, everyone else stays at the floor" contract —
|
|
2823
|
+
* but declared **per slide type** rather than content-only: a strategy's
|
|
2824
|
+
* `layoutTendencies` is content-only, so on cover/chapter/ending a theme
|
|
2825
|
+
* competes only with `StrategyDefinition.identityTendencies` (which
|
|
2826
|
+
* `tendencyIdsFor` does consult for those three types — an earlier draft
|
|
2827
|
+
* of this comment wrongly claimed no strategy signal reached them at all).
|
|
2828
|
+
* **Consequence worth knowing when declaring:** because `weightOf`
|
|
2829
|
+
* composes via `Math.max`, a theme tendency naming an id the active
|
|
2830
|
+
* strategy's `identityTendencies` already names adds no differential pull
|
|
2831
|
+
* for that id under that strategy (max(3,3) = 3) — a theme's structural
|
|
2832
|
+
* character therefore reads most clearly on ids the strategies do not
|
|
2833
|
+
* already favor. Content can carry both a strategy tendency
|
|
2834
|
+
* and a theme tendency at once; `weightOf` composes every live layer via
|
|
2835
|
+
* `Math.max`, never multiplication (same ruling `BEAT_TENDENCY_WEIGHT`'s
|
|
2836
|
+
* doc comment already argues for: agreement between layers corroborates
|
|
2837
|
+
* the same preference dimension, it does not square the pull).
|
|
2838
|
+
*
|
|
2839
|
+
* **Soft weight, not a whitelist — `layouts` above stays the one hard
|
|
2840
|
+
* boundary.** A slide type's candidate pool is built from `layouts[slideType]`
|
|
2841
|
+
* *before* any tendency is ever consulted (`resolveLayoutId`'s own
|
|
2842
|
+
* `pool` construction), so an id this record names for a page type it is
|
|
2843
|
+
* not also present in that same page type's `layouts` set can never be
|
|
2844
|
+
* scored — it is invisible to `weightOf`, not merely down-weighted. That
|
|
2845
|
+
* silent no-op is exactly why it counts as a theme-author mistake rather
|
|
2846
|
+
* than a legal (if unusual) declaration — `definitions.test.ts`'s
|
|
2847
|
+
* consistency sweep over the 13 builtins, and `registerTheme`'s own
|
|
2848
|
+
* validation below for any future custom theme, both fail loudly the
|
|
2849
|
+
* moment a `layoutTendencies` entry names an id outside its own page
|
|
2850
|
+
* type's `layouts` set, so the mistake surfaces at registration/test time
|
|
2851
|
+
* instead of silently doing nothing at render time.
|
|
2852
|
+
*
|
|
2853
|
+
* Optional at every level (the whole field, and independently each of its
|
|
2854
|
+
* four page-type entries) — **omission is not a lesser default, it is
|
|
2855
|
+
* today's exact behavior**: a page type this record doesn't cover (key
|
|
2856
|
+
* absent, or the field itself `undefined`) contributes a uniform weight of
|
|
2857
|
+
* 1 to every candidate, the same "no theme-layer opinion" no-op floor
|
|
2858
|
+
* `beatTendencies === undefined` already gives beat. None of the 13
|
|
2859
|
+
* builtins declare this field yet (theme-structure wave task T1 is the
|
|
2860
|
+
* mechanism only — task T2 is where individual builtins pick up a
|
|
2861
|
+
* personality), so every one of them renders byte-identically to before
|
|
2862
|
+
* this field existed.
|
|
2863
|
+
*/
|
|
2864
|
+
layoutTendencies?: Partial<Record<Slide["type"], readonly string[]>>;
|
|
2865
|
+
/**
|
|
2866
|
+
* Which sparse climax pins this theme is willing to honour. This is not a
|
|
2867
|
+
* curated auto-pick pool: pinOnly sparse ids never enter `layouts[slideType]`
|
|
2868
|
+
* (`fullLayoutSet` / `excludePinOnly` already drop them), so a list here
|
|
2869
|
+
* does not make `resolveLayoutId` sample them. It is the offer table for
|
|
2870
|
+
* an explicit `slide.layout` pin — the only road that can ever reach a
|
|
2871
|
+
* sparse page.
|
|
2872
|
+
*
|
|
2873
|
+
* **Three shapes, none of them a defaulted array:**
|
|
2874
|
+
* - omitted / `undefined`: this theme offers every id in
|
|
2875
|
+
* {@link SPARSE_LAYOUT_IDS}. Builtins that have not boarded a face still
|
|
2876
|
+
* render the generic content face (`sparseFace` miss → `content-*.tsx`).
|
|
2877
|
+
* Custom themes registered via {@link registerTheme} get the same
|
|
2878
|
+
* omitted-means-all contract; do not default the field to `[]` or the
|
|
2879
|
+
* six-id list on the way in (`getThemeDefinition` round-trips the
|
|
2880
|
+
* registration object).
|
|
2881
|
+
* - `[]`: this theme offers none. An explicit pin of any sparse id warns
|
|
2882
|
+
* at `validateIr` (`ok` stays true) and render falls back to auto-pick
|
|
2883
|
+
* from the ordinary content (or chapter, for `verse-chapter`) pool.
|
|
2884
|
+
* - a list: only those ids. A listed id must be one of the six sparse
|
|
2885
|
+
* ids (`registerTheme` throws {@link PptwiseError} otherwise). It does
|
|
2886
|
+
* **not** have to sit in `layouts[slideType]` — those pools exclude
|
|
2887
|
+
* pinOnly members by construction.
|
|
2888
|
+
*
|
|
2889
|
+
* {@link themeOffersSparse} is the only offer check. Renderers must not
|
|
2890
|
+
* branch on theme id. A pin this theme does not offer is stripped
|
|
2891
|
+
* (`effectiveRequestedLayout`) *before* `resolveLayoutId`'s pin
|
|
2892
|
+
* short-circuit, so fallback reuses the existing auto-pick path instead
|
|
2893
|
+
* of teaching selection about this table.
|
|
2894
|
+
*/
|
|
2895
|
+
sparseLayouts?: readonly string[];
|
|
2896
|
+
}
|
|
2897
|
+
/**
|
|
2898
|
+
* `registerTheme`'s input shape (W4, spec §3 "缺省 = 全集"): identical to
|
|
2899
|
+
* {@link ThemeDefinition} except `layouts` is optional, and — when present —
|
|
2900
|
+
* each of its four slide-type entries is independently optional too. A
|
|
2901
|
+
* slide type this theme doesn't narrow (its own key omitted, or the whole
|
|
2902
|
+
* `layouts` object omitted) defaults to that type's full registered-
|
|
2903
|
+
* layout set ({@link FULL_LAYOUTS}) — the exact same default every
|
|
2904
|
+
* builtin theme in `LAYOUTS` above resolves to for a slide type it doesn't
|
|
2905
|
+
* curate away from. `getThemeDefinition`/`REGISTERED_THEMES` still only ever
|
|
2906
|
+
* hold the fully-resolved `ThemeDefinition` shape (`layouts` total over all
|
|
2907
|
+
* four types) — `registerTheme` performs the defaulting once, here, so
|
|
2908
|
+
* every downstream reader (`resolveLayoutId` foremost) can keep assuming
|
|
2909
|
+
* a total record and never re-derive "was this slide type curated or
|
|
2910
|
+
* defaulted".
|
|
2911
|
+
*/
|
|
2912
|
+
type ThemeRegistration = Omit<ThemeDefinition, "layouts"> & {
|
|
2913
|
+
layouts?: Partial<Record<Slide["type"], readonly string[]>>;
|
|
2914
|
+
};
|
|
2915
|
+
/**
|
|
2916
|
+
* Register a theme at runtime (SDK seam, not the v0.4 distribution
|
|
2917
|
+
* protocol). Validates just enough to keep the render chain from silently
|
|
2918
|
+
* breaking on a malformed registration — not a full schema:
|
|
2919
|
+
*
|
|
2920
|
+
* - `id` must not collide with a builtin or an already-registered theme.
|
|
2921
|
+
* - each of the four slide types, once defaulted ({@link ThemeRegistration}),
|
|
2922
|
+
* must have at least one layout id that is both registered in
|
|
2923
|
+
* `LAYOUT_REGISTRY` and valid for that slide type (the same registry
|
|
2924
|
+
* `resolveLayoutId`/`FullSlideSvg` select from — a theme never ships
|
|
2925
|
+
* new render code, only a curated subset of the existing 30 layouts +
|
|
2926
|
+
* 4 takeovers, per `docs/architecture.md`'s "Adding a theme" section). An
|
|
2927
|
+
* *explicit* empty array for a slide type still fails this check (the
|
|
2928
|
+
* default only kicks in when the key — or `layouts` itself — is omitted
|
|
2929
|
+
* entirely, `undefined`, never for a caller-supplied `[]`).
|
|
2930
|
+
* - `style` must be present (a JS caller can bypass the TS type).
|
|
2931
|
+
* - `style.colors.text`/`style.colors.muted` must each clear the
|
|
2932
|
+
* {@link CONTRAST_FLOOR} against a {@link CONTRAST_CHECKED_SLIDE_TYPES}
|
|
2933
|
+
* slide type's own resolved default background — see
|
|
2934
|
+
* {@link assertContrastFloor}'s own doc comment.
|
|
2935
|
+
* - `sparseLayouts`, when present, may be empty (offers none) or a list of
|
|
2936
|
+
* {@link SPARSE_LAYOUT_IDS} members. A listed non-sparse id throws. The
|
|
2937
|
+
* field is not defaulted when omitted (`undefined` = offer all six).
|
|
2938
|
+
*
|
|
2939
|
+
* Also `console.warn`s (never throws) once for each of `style.fonts.heading`/
|
|
2940
|
+
* `style.fonts.body` that resolves to a face with no exact width table — see
|
|
2941
|
+
* {@link warnUnmeasuredFace}'s own doc comment. Fires only for a
|
|
2942
|
+
* registration that clears every check above (i.e. one that is actually
|
|
2943
|
+
* about to succeed).
|
|
2944
|
+
*
|
|
2945
|
+
* Once registered, the theme participates in `getInstalledThemeIds`,
|
|
2946
|
+
* `getThemeDefinition` (hence `layout-selection.ts`/`FullSlideSvg`'s
|
|
2947
|
+
* selection and `resolveBrand`), and `themes/index.ts`'s `resolveStyle` —
|
|
2948
|
+
* every internal theme lookup, with no separate "registered theme" branch
|
|
2949
|
+
* for callers to remember.
|
|
2950
|
+
*/
|
|
2951
|
+
declare function registerTheme(def: ThemeRegistration): void;
|
|
2952
|
+
/** Every installed theme id: the 13 builtins, then registered themes in registration order. */
|
|
2953
|
+
declare function getInstalledThemeIds(): readonly string[];
|
|
2954
|
+
/**
|
|
2955
|
+
* Resolve a theme id to its full definition — a registered theme first, then
|
|
2956
|
+
* the builtin fallback (`THEME_DEFINITIONS[resolveThemeId(id)]`, which itself
|
|
2957
|
+
* folds an unrecognized id to consulting). The one lookup every internal
|
|
2958
|
+
* consumer that used to read `THEME_DEFINITIONS[resolveThemeId(id)]`
|
|
2959
|
+
* directly (`layout-selection.ts`, `full-slide-svg.tsx`) now calls instead, so
|
|
2960
|
+
* a registered theme's curated layouts actually drive selection end-to-end.
|
|
2961
|
+
*/
|
|
2962
|
+
declare function getThemeDefinition(id: string): ThemeDefinition;
|
|
2963
|
+
|
|
2964
|
+
/** The theme-file JSON shape written by `pptwise brand extract` / SDK
|
|
2965
|
+
* {@link extractBrandTheme}, and read back by `--theme-file` /
|
|
2966
|
+
* `brand-theme-file.ts`'s `registerBrandThemeFile`. Pure data (裁定 3): no
|
|
2967
|
+
* `layouts`/`motif`/`layoutTendencies` — those default to the full set,
|
|
2968
|
+
* same as any other `registerTheme` caller that omits them. `label` is
|
|
2969
|
+
* informational only (a human-readable name for the CLI/UI to show); the
|
|
2970
|
+
* render chain never reads it — the theme's own `id` is what everything
|
|
2971
|
+
* else keys off. */
|
|
2972
|
+
interface BrandThemeFile {
|
|
2973
|
+
id: string;
|
|
2974
|
+
label: string;
|
|
2975
|
+
style: StyleTokens;
|
|
2976
|
+
brand: BrandConfig;
|
|
2977
|
+
tags: string[];
|
|
2978
|
+
}
|
|
2979
|
+
interface ExtractBrandThemeOptions {
|
|
2980
|
+
/** Theme id — defaults to a slug of {@link ExtractBrandThemeOptions.label},
|
|
2981
|
+
* or (when that's also absent) a slug of the source theme part's own
|
|
2982
|
+
* `<a:clrScheme name="…">`. The CLI (`pptwise brand extract`) always
|
|
2983
|
+
* passes one explicitly (`--id`, or a slug of the `-o` filename — 裁定
|
|
2984
|
+
* 4) — this default only ever fires for a bare SDK caller. */
|
|
2985
|
+
id?: string;
|
|
2986
|
+
/** Human-readable label — defaults to the source theme part's own
|
|
2987
|
+
* `<a:clrScheme name="…">`. */
|
|
2988
|
+
label?: string;
|
|
2989
|
+
}
|
|
2990
|
+
/**
|
|
2991
|
+
* Extract a {@link BrandThemeFile} from raw OOXML package bytes (a
|
|
2992
|
+
* `.thmx`/`.potx`/`.pptx` file's own bytes — this function only ever reads
|
|
2993
|
+
* the theme part inside, nothing else in the package). Deterministic: the
|
|
2994
|
+
* same bytes always produce the same output (no randomness, no wall-clock
|
|
2995
|
+
* read) — required for this wave's fixture tests' double-run-equality
|
|
2996
|
+
* assertions.
|
|
2997
|
+
*
|
|
2998
|
+
* Throws {@link PptwiseError} for two *structural* failures — data this
|
|
2999
|
+
* function has no reasonable default for:
|
|
3000
|
+
* - no theme part found in the package at all
|
|
3001
|
+
* - a theme part with no `dk1`/`lt1` (nothing to derive `bg`/`text` from) or
|
|
3002
|
+
* no accent color at all (nothing to derive `primary`/`chartPalette` from)
|
|
3003
|
+
*
|
|
3004
|
+
* Everything else degrades gracefully rather than throwing — a missing
|
|
3005
|
+
* `lt2` falls back to `bg` (no distinct surface tone available), a missing
|
|
3006
|
+
* `accent1` falls back to `dk2` then to the first available chart color, a
|
|
3007
|
+
* missing font falls back to a Windows-safe generic stack — so a real-world
|
|
3008
|
+
* theme missing a slot or two (this wave's own fixture matrix covers
|
|
3009
|
+
* several) still produces a usable, if plainer, theme. A palette that
|
|
3010
|
+
* degrades all the way into unreadable territory (near-identical
|
|
3011
|
+
* text/bg/muted tones) is *not* rejected here — that's `registerTheme`'s
|
|
3012
|
+
* own `assertContrastFloor` (`./definitions.ts`) job, at load time, with a
|
|
3013
|
+
* message naming the actual failing token/ratio (see `brand-theme-file.ts`).
|
|
3014
|
+
*/
|
|
3015
|
+
declare function extractBrandTheme(bytes: Uint8Array | ArrayBuffer, opts?: ExtractBrandThemeOptions): Promise<BrandThemeFile>;
|
|
3016
|
+
|
|
3017
|
+
/**
|
|
3018
|
+
* Load an on-disk {@link BrandThemeFile} (`./brand-extract.ts`'s output, or
|
|
3019
|
+
* a hand-authored equivalent) into the theme registry (brand-extract wave,
|
|
3020
|
+
* 裁定 3: "装载走 registerTheme"). Split from `brand-extract.ts` because this
|
|
3021
|
+
* module's job is untrusted-input validation + registration — a theme file
|
|
3022
|
+
* is user-editable JSON, not something `extractBrandTheme`'s own return
|
|
3023
|
+
* value needs re-validated against when it's the one producing it — while
|
|
3024
|
+
* that module's job is the pure OOXML→tokens derivation. Both stay
|
|
3025
|
+
* browser-safe (no Node-only import), same as every other file under
|
|
3026
|
+
* `src/themes/` (`AGENTS.md`'s dependency-closure rule): the actual file
|
|
3027
|
+
* read (`readFile`) happens in `src/cli/commands.ts`, which hands this
|
|
3028
|
+
* module already-parsed JSON.
|
|
3029
|
+
*/
|
|
3030
|
+
|
|
3031
|
+
declare const BrandThemeFileSchema: z.ZodObject<{
|
|
3032
|
+
id: z.ZodString;
|
|
3033
|
+
label: z.ZodOptional<z.ZodString>;
|
|
3034
|
+
style: z.ZodObject<{
|
|
3035
|
+
id: z.ZodString;
|
|
3036
|
+
allowCustomBackground: z.ZodOptional<z.ZodBoolean>;
|
|
3037
|
+
colors: z.ZodObject<{
|
|
3038
|
+
bg: z.ZodString;
|
|
3039
|
+
surface: z.ZodString;
|
|
3040
|
+
panel: z.ZodOptional<z.ZodString>;
|
|
3041
|
+
primary: z.ZodString;
|
|
3042
|
+
accent: z.ZodString;
|
|
3043
|
+
text: z.ZodString;
|
|
3044
|
+
muted: z.ZodString;
|
|
3045
|
+
border: z.ZodOptional<z.ZodString>;
|
|
3046
|
+
chartPalette: z.ZodArray<z.ZodString>;
|
|
3047
|
+
accentPool: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
3048
|
+
cardStroke: z.ZodOptional<z.ZodString>;
|
|
3049
|
+
}, z.core.$strict>;
|
|
3050
|
+
fonts: z.ZodObject<{
|
|
3051
|
+
heading: z.ZodArray<z.ZodString>;
|
|
3052
|
+
body: z.ZodArray<z.ZodString>;
|
|
3053
|
+
mono: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
3054
|
+
}, z.core.$strict>;
|
|
3055
|
+
shape: z.ZodOptional<z.ZodObject<{
|
|
3056
|
+
radius: z.ZodOptional<z.ZodNumber>;
|
|
3057
|
+
gapScale: z.ZodOptional<z.ZodNumber>;
|
|
3058
|
+
typeScale: z.ZodOptional<z.ZodNumber>;
|
|
3059
|
+
}, z.core.$strict>>;
|
|
3060
|
+
defaultBackgrounds: z.ZodObject<{
|
|
3061
|
+
cover: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
3062
|
+
kind: z.ZodLiteral<"color">;
|
|
3063
|
+
value: z.ZodString;
|
|
3064
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
3065
|
+
kind: z.ZodLiteral<"gradient">;
|
|
3066
|
+
from: z.ZodString;
|
|
3067
|
+
to: z.ZodString;
|
|
3068
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
3069
|
+
tb: "tb";
|
|
3070
|
+
lr: "lr";
|
|
3071
|
+
diagonal: "diagonal";
|
|
3072
|
+
}>>;
|
|
3073
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
3074
|
+
kind: z.ZodLiteral<"asset">;
|
|
3075
|
+
asset_id: z.ZodString;
|
|
3076
|
+
overlay: z.ZodOptional<z.ZodObject<{
|
|
3077
|
+
color: z.ZodString;
|
|
3078
|
+
opacity: z.ZodNumber;
|
|
3079
|
+
}, z.core.$strict>>;
|
|
3080
|
+
fit: z.ZodOptional<z.ZodEnum<{
|
|
3081
|
+
contain: "contain";
|
|
3082
|
+
cover: "cover";
|
|
3083
|
+
}>>;
|
|
3084
|
+
}, z.core.$strict>], "kind">;
|
|
3085
|
+
chapter: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
3086
|
+
kind: z.ZodLiteral<"color">;
|
|
3087
|
+
value: z.ZodString;
|
|
3088
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
3089
|
+
kind: z.ZodLiteral<"gradient">;
|
|
3090
|
+
from: z.ZodString;
|
|
3091
|
+
to: z.ZodString;
|
|
3092
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
3093
|
+
tb: "tb";
|
|
3094
|
+
lr: "lr";
|
|
3095
|
+
diagonal: "diagonal";
|
|
3096
|
+
}>>;
|
|
3097
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
3098
|
+
kind: z.ZodLiteral<"asset">;
|
|
3099
|
+
asset_id: z.ZodString;
|
|
3100
|
+
overlay: z.ZodOptional<z.ZodObject<{
|
|
3101
|
+
color: z.ZodString;
|
|
3102
|
+
opacity: z.ZodNumber;
|
|
3103
|
+
}, z.core.$strict>>;
|
|
3104
|
+
fit: z.ZodOptional<z.ZodEnum<{
|
|
3105
|
+
contain: "contain";
|
|
3106
|
+
cover: "cover";
|
|
3107
|
+
}>>;
|
|
3108
|
+
}, z.core.$strict>], "kind">;
|
|
3109
|
+
content: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
3110
|
+
kind: z.ZodLiteral<"color">;
|
|
3111
|
+
value: z.ZodString;
|
|
3112
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
3113
|
+
kind: z.ZodLiteral<"gradient">;
|
|
3114
|
+
from: z.ZodString;
|
|
3115
|
+
to: z.ZodString;
|
|
3116
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
3117
|
+
tb: "tb";
|
|
3118
|
+
lr: "lr";
|
|
3119
|
+
diagonal: "diagonal";
|
|
3120
|
+
}>>;
|
|
3121
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
3122
|
+
kind: z.ZodLiteral<"asset">;
|
|
3123
|
+
asset_id: z.ZodString;
|
|
3124
|
+
overlay: z.ZodOptional<z.ZodObject<{
|
|
3125
|
+
color: z.ZodString;
|
|
3126
|
+
opacity: z.ZodNumber;
|
|
3127
|
+
}, z.core.$strict>>;
|
|
3128
|
+
fit: z.ZodOptional<z.ZodEnum<{
|
|
3129
|
+
contain: "contain";
|
|
3130
|
+
cover: "cover";
|
|
3131
|
+
}>>;
|
|
3132
|
+
}, z.core.$strict>], "kind">;
|
|
3133
|
+
ending: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
3134
|
+
kind: z.ZodLiteral<"color">;
|
|
3135
|
+
value: z.ZodString;
|
|
3136
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
3137
|
+
kind: z.ZodLiteral<"gradient">;
|
|
3138
|
+
from: z.ZodString;
|
|
3139
|
+
to: z.ZodString;
|
|
3140
|
+
direction: z.ZodOptional<z.ZodEnum<{
|
|
3141
|
+
tb: "tb";
|
|
3142
|
+
lr: "lr";
|
|
3143
|
+
diagonal: "diagonal";
|
|
3144
|
+
}>>;
|
|
3145
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
3146
|
+
kind: z.ZodLiteral<"asset">;
|
|
3147
|
+
asset_id: z.ZodString;
|
|
3148
|
+
overlay: z.ZodOptional<z.ZodObject<{
|
|
3149
|
+
color: z.ZodString;
|
|
3150
|
+
opacity: z.ZodNumber;
|
|
3151
|
+
}, z.core.$strict>>;
|
|
3152
|
+
fit: z.ZodOptional<z.ZodEnum<{
|
|
3153
|
+
contain: "contain";
|
|
3154
|
+
cover: "cover";
|
|
3155
|
+
}>>;
|
|
3156
|
+
}, z.core.$strict>], "kind">;
|
|
3157
|
+
}, z.core.$strict>;
|
|
3158
|
+
}, z.core.$strict>;
|
|
3159
|
+
brand: z.ZodOptional<z.ZodObject<{
|
|
3160
|
+
suppressFooterOnCardContent: z.ZodOptional<z.ZodBoolean>;
|
|
3161
|
+
suppressFooterRule: z.ZodOptional<z.ZodBoolean>;
|
|
3162
|
+
suppressFooterMeta: z.ZodOptional<z.ZodBoolean>;
|
|
3163
|
+
}, z.core.$strict>>;
|
|
3164
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
3165
|
+
}, z.core.$strict>;
|
|
3166
|
+
/** Parse+validate raw JSON (already `JSON.parse`d by the caller — see
|
|
3167
|
+
* `src/cli/load-ir.ts`'s `loadIrFile`) as a {@link BrandThemeFile}. `source`
|
|
3168
|
+
* names the file in the thrown message (a path, or another caller-chosen
|
|
3169
|
+
* label) — mirrors `loadStyleFile`'s (`src/cli/commands.ts`) own
|
|
3170
|
+
* "invalid <kind> file <path>:\n<detail>" shape so a theme-file error reads
|
|
3171
|
+
* exactly like every other config-file validation error in this CLI. */
|
|
3172
|
+
declare function parseBrandThemeFile(raw: unknown, source: string): BrandThemeFile;
|
|
3173
|
+
/**
|
|
3174
|
+
* Register a parsed {@link BrandThemeFile} (`registerTheme`, `./definitions.ts`
|
|
3175
|
+
* — 裁定 3: this is the *only* loading path, so its contrast floor
|
|
3176
|
+
* automatically gates every custom theme). Two collision outcomes, per 裁定
|
|
3177
|
+
* 4:
|
|
3178
|
+
*
|
|
3179
|
+
* - `file.id` names a builtin (`CANONICAL_THEME_IDS`) → always a hard error,
|
|
3180
|
+
* regardless of whether this exact file was already loaded once — a
|
|
3181
|
+
* custom theme must never shadow a builtin id (determinism: which
|
|
3182
|
+
* `layouts`/`layoutTendencies` "consulting" resolves to must never depend
|
|
3183
|
+
* on whether some unrelated `--theme-file` ran first).
|
|
3184
|
+
* - `file.id` is already registered (not a builtin) → a silent no-op, not a
|
|
3185
|
+
* second error. `registerTheme` itself throws unconditionally on *any*
|
|
3186
|
+
* id collision, builtin or not — this idempotent skip exists because
|
|
3187
|
+
* `pptwise serve`'s rebuild loop (`src/cli/serve.ts`) calls this on every
|
|
3188
|
+
* file-watch rebuild for the *same* deck, and the theme-file/deck-dir
|
|
3189
|
+
* `theme.json` it re-reads each time resolves to the same id every time.
|
|
3190
|
+
* (A theme file edited *between* two rebuilds keeps whichever version
|
|
3191
|
+
* registered first for that process's lifetime — no live-reload for a
|
|
3192
|
+
* theme file's own content, only for deck content; out of this wave's
|
|
3193
|
+
* scope.)
|
|
3194
|
+
*
|
|
3195
|
+
* Returns `file.id` so a caller can fold it into the deck's own
|
|
3196
|
+
* theme-resolution precedence chain (`applyDeckConfig`, `src/cli/commands.ts`).
|
|
3197
|
+
*/
|
|
3198
|
+
declare function registerBrandThemeFile(file: BrandThemeFile): string;
|
|
3199
|
+
|
|
3200
|
+
/**
|
|
3201
|
+
* Narrative argument style (spec §5's five-way strategy classification,
|
|
3202
|
+
* renamed from "mode" — spec §8.1). Each strategy carries a
|
|
3203
|
+
* component/layout tendency set (soft-weight material, consumed by W4's
|
|
3204
|
+
* weighted selection — nothing consumes it this wave) and a beat policy
|
|
3205
|
+
* (renamed from "rhythm policy" — spec §2.3's deck/page beat split; consumed
|
|
3206
|
+
* by W5's spec-validate rotation gate).
|
|
3207
|
+
*/
|
|
3208
|
+
type Strategy = (typeof STRATEGY_VALUES)[number];
|
|
3209
|
+
/**
|
|
3210
|
+
* Content density budget + typographic baseline (spec §5 pacing table,
|
|
3211
|
+
* renamed from "delivery" — spec §8.1). See {@link PacingBudget} for the
|
|
3212
|
+
* dual-attribute capacity split this axis is one half of.
|
|
3213
|
+
*/
|
|
3214
|
+
type Pacing = (typeof PACING_VALUES)[number];
|
|
3215
|
+
/**
|
|
3216
|
+
* Tone anchor only (spec §5: audience is tone-anchoring only, no rendering
|
|
3217
|
+
* effect on the IR yet). Reserved for a future lint pass (e.g. executive ×
|
|
3218
|
+
* long paragraphs → suggest kpi_cards/verdict_banner instead). The rule set
|
|
3219
|
+
* itself is explicitly out of scope this wave (spec §10 open questions).
|
|
3220
|
+
* Name unchanged by the vocabulary-v4 rename (spec §4.3: "audience 保持不变").
|
|
3221
|
+
*/
|
|
3222
|
+
type Audience = (typeof AUDIENCE_VALUES)[number];
|
|
3223
|
+
interface NarrativeProfile {
|
|
3224
|
+
readonly strategy: Strategy;
|
|
3225
|
+
readonly pacing: Pacing;
|
|
3226
|
+
readonly audience: Audience;
|
|
3227
|
+
}
|
|
3228
|
+
|
|
3229
|
+
interface StrategyDefinition {
|
|
3230
|
+
id: Strategy;
|
|
3231
|
+
/**
|
|
3232
|
+
* Layout/component tendency set (soft-weight material). Filled row-for-row
|
|
3233
|
+
* from spec §5's strategy table for W4's weighted selection step (spec §6
|
|
3234
|
+
* step 4: in-set candidates get ×3 weight, out-of-set ×1 floor — not
|
|
3235
|
+
* implemented yet, this module only stores the data).
|
|
3236
|
+
*
|
|
3237
|
+
* The set deliberately mixes two different vocabularies: component `type`
|
|
3238
|
+
* names (e.g. "kpi_cards", "chart" — see the `Component` discriminated
|
|
3239
|
+
* union in `ir/index.ts`) and layout `id`s (e.g. "image-split" — see
|
|
3240
|
+
* `LAYOUT_REGISTRY` in `svg/layouts/registry.ts`). This is intentional,
|
|
3241
|
+
* not an oversight: W4's weighting step resolves each entry against
|
|
3242
|
+
* whichever vocabulary it belongs to (component types when scoring a
|
|
3243
|
+
* candidate's components, layout ids when scoring the candidate layout
|
|
3244
|
+
* itself). Nothing in this wave (W3) reads this field.
|
|
3245
|
+
*/
|
|
3246
|
+
tendencies: readonly string[];
|
|
3247
|
+
/**
|
|
3248
|
+
* Content-layout soft-weight set for W4's weighted layout selection
|
|
3249
|
+
* (spec §6 step 4: in-set candidates get `TENDENCY_WEIGHT` (×3), out-of-set
|
|
3250
|
+
* get the `BASE_WEIGHT` floor (×1) — both named constants live in
|
|
3251
|
+
* `svg/layout-selection.ts`, next to `resolveLayoutId`, the sole
|
|
3252
|
+
* consumer). Deliberately a separate field from {@link tendencies} above,
|
|
3253
|
+
* not a reinterpretation of it: `tendencies` mixes component-type names and
|
|
3254
|
+
* layout ids drawn from spec §5's strategy table verbatim and also feeds W5's
|
|
3255
|
+
* spec `focus` vocabulary gate, so narrowing its meaning here would be a
|
|
3256
|
+
* breaking change to an existing consumer. This field holds only
|
|
3257
|
+
* `LAYOUT_REGISTRY` content-layout ids (`svg/layouts/registry.ts`'s
|
|
3258
|
+
* `CONTENT_LAYOUT_DEFS` keys) — cover/chapter/ending ids never appear in this
|
|
3259
|
+
* field's list, `resolveLayoutId` reads {@link identityTendencies}
|
|
3260
|
+
* below for those three slide types instead, so the two fields' id
|
|
3261
|
+
* namespaces stay disjoint by construction rather than by convention.
|
|
3262
|
+
* `tone-adaptive-content` appears in no strategy's list here (spec's "万金
|
|
3263
|
+
* 油" call-out: it is the one content layout meant to read as
|
|
3264
|
+
* strategy-neutral, so it always gets the ×1 floor).
|
|
3265
|
+
*
|
|
3266
|
+
* **`image-lead-split` (content-layout expansion wave, task T3) joins
|
|
3267
|
+
* it, deliberately, as this field's third permanently-neutral member** — a
|
|
3268
|
+
* decision, not an oversight (T1's own review flagged its absence here as
|
|
3269
|
+
* looking accidental, so this note exists to close that off explicitly).
|
|
3270
|
+
* Its defining trait is an *asset-availability* choice, not an
|
|
3271
|
+
* *argument-style* one: the unconditional visual/text split depends on
|
|
3272
|
+
* whether the deck's author actually has a chart/photo worth leading with
|
|
3273
|
+
* (see `content-image-lead-split.tsx`'s own file header) — a pyramid deck,
|
|
3274
|
+
* a storytelling deck, a showcase deck, and a briefing deck can equally
|
|
3275
|
+
* have (or lack) a strong image to lead with, so no single strategy's
|
|
3276
|
+
* rhetorical register (MECE evidence-first, editorial restraint,
|
|
3277
|
+
* step-by-step procedure, glossy visual punch, plain scannability) owns
|
|
3278
|
+
* this composition more than another's. **Reconsidered specifically
|
|
3279
|
+
* against `showcase`** (the wave's final review, see `split-band`'s own
|
|
3280
|
+
* entry in `showcase.layoutTendencies` below): showcase's register is
|
|
3281
|
+
* visual *punch* (bold color blocks, opaque highlight panels), not visual
|
|
3282
|
+
* *presence* — having an image at all doesn't say anything about how
|
|
3283
|
+
* loudly the page asserts itself, so this layout's asset-dependence
|
|
3284
|
+
* still doesn't map onto showcase's own membership criterion the way
|
|
3285
|
+
* `split-band`'s full-bleed color band does. It still went back to
|
|
3286
|
+
* neutral, not out of inertia. It *does* carry a beat-level personality
|
|
3287
|
+
* instead (`BEAT_TENDENCIES`, `svg/layout-selection.ts` — `breathing`) —
|
|
3288
|
+
* that axis measures page-level density character, a question this
|
|
3289
|
+
* field's argument-style axis doesn't ask.
|
|
3290
|
+
*
|
|
3291
|
+
* **`split-band` (same wave, same task) does NOT join this field** — it
|
|
3292
|
+
* was originally proposed here on the same "frame, not argument" theory
|
|
3293
|
+
* above, but the wave's final review refuted that specific claim with
|
|
3294
|
+
* in-file evidence: `split-band`'s defining feature, a full-bleed
|
|
3295
|
+
* (x=0, w=1280) `colors.primary` header band, is the "bold opaque color
|
|
3296
|
+
* block" idiom that earns `showcase.layoutTendencies` membership (the
|
|
3297
|
+
* retired `side-highlight` panel used to share that register), and
|
|
3298
|
+
* showcase's identity picks (`fashion-masthead`/`fashion-chapter`/
|
|
3299
|
+
* `fashion-ending`) are themselves built from full-bleed color blocks —
|
|
3300
|
+
* visual weight *is* showcase's rhetorical register, not a
|
|
3301
|
+
* register-neutral frame choice. `split-band` is listed in
|
|
3302
|
+
* `showcase.layoutTendencies` below instead of here.
|
|
3303
|
+
*
|
|
3304
|
+
* **Historical note (corrected P1 variety wave, task 3):** this field's
|
|
3305
|
+
* doc comment used to claim cover/chapter/ending stayed uniformly sampled
|
|
3306
|
+
* because "身份页个性来自 theme 不来自 strategy" — that claim was already
|
|
3307
|
+
* false when written (`theme.layouts` only curates the candidate *pool*,
|
|
3308
|
+
* spec §6 step 3 — the 13 built-in themes' pools are all the full registry
|
|
3309
|
+
* set for every slide type, so `theme.id` contributes zero shaping either —
|
|
3310
|
+
* see `.issues/.../dr/c-diversity.md`'s §1.1 measurement). Identity pages
|
|
3311
|
+
* now get their own strategy-driven soft weighting via
|
|
3312
|
+
* {@link identityTendencies} — theme's role stays exactly what step 3
|
|
3313
|
+
* always said it was — pool curation, not per-layout preference — for
|
|
3314
|
+
* both content and identity slides alike.
|
|
3315
|
+
*/
|
|
3316
|
+
layoutTendencies: readonly string[];
|
|
3317
|
+
/**
|
|
3318
|
+
* Cover/chapter/ending soft-weight sets (P1 variety wave, task 3 — "身份页
|
|
3319
|
+
* strategy 软加权"), one per identity slide type. Same ×3/×1 mechanics as
|
|
3320
|
+
* {@link layoutTendencies} (`TENDENCY_WEIGHT`/`BASE_WEIGHT`,
|
|
3321
|
+
* `svg/layout-selection.ts`) and the same consumer (`resolveLayoutId`),
|
|
3322
|
+
* just scoped to a disjoint id namespace: this field holds only
|
|
3323
|
+
* `LAYOUT_REGISTRY` cover/chapter/ending layout ids
|
|
3324
|
+
* (`svg/layouts/registry.ts`'s `COVER_LAYOUT_DEFS`/`CHAPTER_LAYOUT_DEFS`/
|
|
3325
|
+
* `ENDING_LAYOUT_DEFS` keys), never a content id — `resolveLayoutId` picks
|
|
3326
|
+
* this field or {@link layoutTendencies} based on the slide type being
|
|
3327
|
+
* resolved, never both for the same candidate.
|
|
3328
|
+
*
|
|
3329
|
+
* Deliberately small (2-3 members per page type, out of a 7-8-id pool) —
|
|
3330
|
+
* spec: "映射表提案是内容决策...权重不是排除", so every non-member layout
|
|
3331
|
+
* still stays reachable at the `BASE_WEIGHT` floor, just less often. Each
|
|
3332
|
+
* member's rationale is documented next to its own strategy entry below,
|
|
3333
|
+
* grounded in that layout's own body comment in
|
|
3334
|
+
* `svg/layouts/registry.ts` (`COVER_LAYOUT_DEFS`/`CHAPTER_LAYOUT_DEFS`/
|
|
3335
|
+
* `ENDING_LAYOUT_DEFS`), not its name alone.
|
|
3336
|
+
*
|
|
3337
|
+
* `tone-adaptive-header`/`tone-adaptive-chapter`/`tone-adaptive-ending`
|
|
3338
|
+
* never appear in any strategy's set here, mirroring
|
|
3339
|
+
* `tone-adaptive-content`'s absence from every {@link layoutTendencies}
|
|
3340
|
+
* list: each is its page type's "万金油" (registry.ts's own convention),
|
|
3341
|
+
* the one layout each identity slide type is meant to keep reading as
|
|
3342
|
+
* strategy-neutral.
|
|
3343
|
+
*
|
|
3344
|
+
* Supersedes the old design note this field replaces (formerly recorded
|
|
3345
|
+
* on {@link layoutTendencies} below, now corrected there): identity pages
|
|
3346
|
+
* were never actually reading `theme.id` for their character either
|
|
3347
|
+
* (`theme.layouts` only curates the *pool*, spec §6 step 3 — it was never
|
|
3348
|
+
* a per-layout weighting signal, for content or identity slides alike)
|
|
3349
|
+
* — this field is what now gives cover/chapter/ending a strategy-driven
|
|
3350
|
+
* personality, the same soft-weight mechanism content pages have had since
|
|
3351
|
+
* W4.
|
|
3352
|
+
*/
|
|
3353
|
+
identityTendencies: {
|
|
3354
|
+
readonly cover: readonly string[];
|
|
3355
|
+
readonly chapter: readonly string[];
|
|
3356
|
+
readonly ending: readonly string[];
|
|
3357
|
+
};
|
|
3358
|
+
/**
|
|
3359
|
+
* Beat template descriptor (spec §5's per-strategy beat-default column,
|
|
3360
|
+
* renamed from "rhythm" — spec §2.3), parameterized by strategy for W5's
|
|
3361
|
+
* spec-validate rotation gate — e.g. briefing is exempt from a generic
|
|
3362
|
+
* "three same-beat pages in a row is an error" rule because uniform-dense
|
|
3363
|
+
* *is* briefing's correct default, not a violation of it (spec §5's
|
|
3364
|
+
* spec-gate section calls out that a generic same-beat-streak rule would
|
|
3365
|
+
* reject briefing's own default). Not consumed this wave.
|
|
3366
|
+
*/
|
|
3367
|
+
beatPolicy: "anchor-open" | "alternate" | "repetition-ok" | "anchor-sparse" | "uniform-dense";
|
|
3368
|
+
}
|
|
3369
|
+
declare const STRATEGY_DEFINITIONS: Record<Strategy, StrategyDefinition>;
|
|
3370
|
+
|
|
3371
|
+
interface PacingBudget {
|
|
3372
|
+
/**
|
|
3373
|
+
* Body-text baseline, in px, at 1280×720 slide geometry (spec §5 pacing
|
|
3374
|
+
* table's body-baseline column). Wired into rendering as of W4 task 3
|
|
3375
|
+
* (design decision 9): `src/svg/full-slide-svg.tsx` resolves
|
|
3376
|
+
* `PACING_BUDGETS[resolveNarrative(ir.narrative).pacing].bodyBaselinePx`
|
|
3377
|
+
* once and passes it into `buildCtx`, which stores it as
|
|
3378
|
+
* `ComponentCtx.bodyFontPx` — the sole font-size input for the
|
|
3379
|
+
* paragraph/bullets/callout trio ("正文" = continuous running text).
|
|
3380
|
+
* Every other component's own bespoke type scale, the heading system, and
|
|
3381
|
+
* quote's fixed 26px attribution line don't read this field. Since
|
|
3382
|
+
* `balanced` (24px) is the narrative default, an omitted-narrative deck
|
|
3383
|
+
* now renders body text at 24px, not the previous fixed 20px — the
|
|
3384
|
+
* one-time, spec-sanctioned snapshot re-pin that landed alongside this
|
|
3385
|
+
* wiring (W4 task 3, unchanged since — vocabulary-v4 only renames this
|
|
3386
|
+
* table, it doesn't touch any of its numbers, spec §10).
|
|
3387
|
+
*/
|
|
3388
|
+
bodyBaselinePx: number;
|
|
3389
|
+
/**
|
|
3390
|
+
* Per-slide editorial budget (component count) — content discipline
|
|
3391
|
+
* ("how many things belong on this slide"), not geometry. Spec §5's
|
|
3392
|
+
* dual-attribute capacity split keeps *physical* capacity ("how many
|
|
3393
|
+
* things fit in this layout's slots") on the layout registry's body-slot
|
|
3394
|
+
* `capacity` metadata (`svg/layouts/registry.ts`). The W3 quality gate
|
|
3395
|
+
* takes `min(this budget, the resolved layout's body capacity)`.
|
|
3396
|
+
*/
|
|
3397
|
+
maxComponentsPerSlide: number;
|
|
3398
|
+
bullets: {
|
|
3399
|
+
maxItems: number;
|
|
3400
|
+
/**
|
|
3401
|
+
* Same "unit" concept the deleted `CAPACITY.bullets` used
|
|
3402
|
+
* (`measureTextUnits`, CJK weight = 1.0) — a visual-width-weighted
|
|
3403
|
+
* character count, not a raw `.length`. The old physical ceiling (53,
|
|
3404
|
+
* derived from render geometry) was deleted in W3 without a replacement
|
|
3405
|
+
* check because every pacing's editorial budget here (30/40/48) is
|
|
3406
|
+
* already strictly tighter than it — the quality gate now applies
|
|
3407
|
+
* exactly this one number per pacing.
|
|
3408
|
+
*/
|
|
3409
|
+
maxUnitsPerItem: number;
|
|
3410
|
+
};
|
|
3411
|
+
}
|
|
3412
|
+
/**
|
|
3413
|
+
* Pinned to spec §5's pacing table (`bodyBaselinePx` / editorial budget /
|
|
3414
|
+
* bullets budget columns): dense 20/5/6×48, balanced 24/4/5×40, spacious
|
|
3415
|
+
* 32/3/4×30 — same three rows as the pre-rename `text`/`balanced`/
|
|
3416
|
+
* `presentation` delivery table, values byte-for-byte unchanged (spec §10).
|
|
3417
|
+
*/
|
|
3418
|
+
declare const PACING_BUDGETS: Record<Pacing, PacingBudget>;
|
|
3419
|
+
|
|
3420
|
+
interface NarrativePreset {
|
|
3421
|
+
id: string;
|
|
3422
|
+
axes: NarrativeProfile;
|
|
3423
|
+
/**
|
|
3424
|
+
* Soft theme recommendations — a suggestion, never a hard constraint
|
|
3425
|
+
* (spec §5). Surfaced in workflow step ① so an agent can open with a
|
|
3426
|
+
* themed proposal — the user may still pick any theme. Every entry here
|
|
3427
|
+
* must be a real `BUILTIN_THEME_IDS` member (`ir/index.ts`) — enforced by
|
|
3428
|
+
* this module's test suite, which imports and tests against it.
|
|
3429
|
+
*/
|
|
3430
|
+
themeRecommendations: readonly string[];
|
|
3431
|
+
}
|
|
3432
|
+
/**
|
|
3433
|
+
* Pinned to spec §5's 7 named presets and their theme recommendation table.
|
|
3434
|
+
* Preset ids are unchanged by the vocabulary-v4 rename (spec §5: "预设 ID
|
|
3435
|
+
* 保持不变") — only each preset's internal axes keys/values follow the
|
|
3436
|
+
* strategy/pacing rename (e.g. `annual-review`'s `mode: "narrative"` is now
|
|
3437
|
+
* `strategy: "storytelling"`, spec §5's own worked example).
|
|
3438
|
+
*/
|
|
3439
|
+
declare const NARRATIVE_PRESETS: Record<string, NarrativePreset>;
|
|
3440
|
+
/**
|
|
3441
|
+
* = `NARRATIVE_PRESETS.general.axes` (briefing × balanced × public) — the
|
|
3442
|
+
* global default when narrative is omitted entirely (spec §5's defaults
|
|
3443
|
+
* chain).
|
|
3444
|
+
*/
|
|
3445
|
+
declare const DEFAULT_NARRATIVE: NarrativeProfile;
|
|
3446
|
+
/**
|
|
3447
|
+
* Resolve a narrative input down to concrete axes, per spec §5's design
|
|
3448
|
+
* principle "omission gets the default, a typo is a hard error" (weak-model
|
|
3449
|
+
* friendly: a model that leaves a field out gets a sane deck, a model that
|
|
3450
|
+
* misspells a value gets a loud, actionable error instead of a silently
|
|
3451
|
+
* wrong deck):
|
|
3452
|
+
*
|
|
3453
|
+
* - `undefined` → {@link DEFAULT_NARRATIVE} (the `general` preset's axes)
|
|
3454
|
+
* - a preset id string → that preset's axes (unknown id throws
|
|
3455
|
+
* {@link PptwiseError}, listing the available preset ids)
|
|
3456
|
+
* - a partial axes object → each axis defaults independently
|
|
3457
|
+
* (strategy → "briefing", pacing → "balanced", audience → "public" — these
|
|
3458
|
+
* happen to equal `DEFAULT_NARRATIVE`'s values because `general` *is* that
|
|
3459
|
+
* exact combination, but the fallback here is per-axis, not "any omitted
|
|
3460
|
+
* axis falls back to the whole default object")
|
|
3461
|
+
* - an `{id: <preset>}` object (T0b fix 2, scope-extended — see
|
|
3462
|
+
* {@link rescueIdShape}) → silently treated as that bare preset-id string,
|
|
3463
|
+
* the same weak-model shape slip `theme: {id: "consulting"}` invites by
|
|
3464
|
+
* analogy. Folded directly into this function's own entry (not just a
|
|
3465
|
+
* pre-parse pass two of its six call sites happen to run) so every caller
|
|
3466
|
+
* — `validateIr`, `validateSpec`, `layout-selection.ts`,
|
|
3467
|
+
* `full-slide-svg.tsx`, `ir-quality.ts`, `cli/commands.ts` alike — gets
|
|
3468
|
+
* this tolerance for free, present and future. Silent here (no rewrite
|
|
3469
|
+
* note — this is a pure resolver with no reporting channel, and adding one
|
|
3470
|
+
* would ripple into every one of those call sites' own return-shape
|
|
3471
|
+
* expectations); `validateIr`/`validateSpec` additionally run
|
|
3472
|
+
* {@link normalizeNarrativeShape} on their own raw pre-parse input first,
|
|
3473
|
+
* specifically to report + persist the rewrite into what they return.
|
|
3474
|
+
*
|
|
3475
|
+
* An unknown axis value, or an unknown key on the partial axes object,
|
|
3476
|
+
* always throws {@link PptwiseError} (never silently ignored or dropped) —
|
|
3477
|
+
* omission and a typo are different intents, and only the former has a
|
|
3478
|
+
* reasonable default. A mixed `{id, strategy}`-style shape is exactly this
|
|
3479
|
+
* case ({@link rescueIdShape} declines it): `id` is simply an unrecognized
|
|
3480
|
+
* key, so it hard-errors the same as any other typo.
|
|
3481
|
+
*
|
|
3482
|
+
* Renamed from `resolveScenario` (spec §8.1). Callers that still hold a
|
|
3483
|
+
* pre-rename `mode`/`delivery` shaped input (e.g. a v3 IR's `scenario`
|
|
3484
|
+
* field) must migrate it first — see `migrateIrV3ToV4`
|
|
3485
|
+
* (`src/ir/migrate.ts`) for the deterministic field/value mapping. A
|
|
3486
|
+
* v4-track document that still writes the old field/value spelling gets no
|
|
3487
|
+
* such rescue (spec §16, reversing the now-superseded §15.4): this function
|
|
3488
|
+
* hard-errors on it, same as any other unknown axis key or value. The
|
|
3489
|
+
* `{id}` shape above is not that — it was never a v3 `scenario` shape, just
|
|
3490
|
+
* a new confusion weak models invent by analogy to `theme.id`.
|
|
3491
|
+
*/
|
|
3492
|
+
declare function resolveNarrative(input: string | Partial<NarrativeProfile> | undefined): NarrativeProfile;
|
|
3493
|
+
|
|
3494
|
+
/**
|
|
3495
|
+
* Deck spec schema + validation (spec §5 "plan artifact and hard gates", W5
|
|
3496
|
+
* task 2 — renamed to "Deck Spec" per the vocabulary-v4 rename, spec §6/§8.1;
|
|
3497
|
+
* "spec §N" citations throughout this file that predate this rename still
|
|
3498
|
+
* point at that original W5 design doc, not this rename's own spec — left
|
|
3499
|
+
* as historical citations, not renumbered). That rename originally covered
|
|
3500
|
+
* the exported concepts and CLI vocabulary only — this module's own
|
|
3501
|
+
* directory stayed `src/plan` for a while after, a known stale name the
|
|
3502
|
+
* src domain-reorg wave's task T1c closed by moving it to `src/spec`
|
|
3503
|
+
* (mechanical `git mv`, every exported symbol unchanged): the path now
|
|
3504
|
+
* matches the vocabulary this header already used throughout.
|
|
3505
|
+
*
|
|
3506
|
+
* A deck spec is a workflow artifact, not a render prerequisite (spec §5's
|
|
3507
|
+
* "escape hatch": a bare IR v3 renders directly, `spec validate` is a
|
|
3508
|
+
* separate, optional gate for the spec-authoring stage of the six-phase
|
|
3509
|
+
* workflow). This module stays pure and Node-free — no `fs`, no CLI concerns
|
|
3510
|
+
* — so it can sit in `src/index.ts`'s dependency closure exactly like
|
|
3511
|
+
* `src/ir` and `src/narrative` already do (`AGENTS.md`'s layout rule).
|
|
3512
|
+
* `src/cli/commands.ts` owns the one Node-touching wrapper
|
|
3513
|
+
* (`runSpecValidate`: read file, call {@link validateSpec}, format the
|
|
3514
|
+
* result).
|
|
3515
|
+
*
|
|
3516
|
+
* Design mirrors `api.ts`'s `validateIr`/`ValidateResult` throughout
|
|
3517
|
+
* (structural zod pass first, then a sequential chain of hard-gate
|
|
3518
|
+
* categories, each short-circuiting the chain on its own failure — see
|
|
3519
|
+
* {@link validateSpec}'s own comment for why): same overall shape, adapted
|
|
3520
|
+
* for spec pages being keyed by an author-assigned `id` instead of IR's
|
|
3521
|
+
* positional slide index.
|
|
3522
|
+
*/
|
|
3523
|
+
|
|
3524
|
+
/**
|
|
3525
|
+
* Mirrors `SlideSchema.type` / `SlideType` (`ir/index.ts`,
|
|
3526
|
+
* `svg/layouts/registry.ts`) exactly. Kept as an independent literal tuple
|
|
3527
|
+
* here (not imported from either) — a page spec's `type` is a 4-value enum
|
|
3528
|
+
* on its own schema, not a re-export of IR's — but the `satisfies` clause
|
|
3529
|
+
* makes any future drift between the two a compile error instead of a
|
|
3530
|
+
* silent mismatch.
|
|
3531
|
+
*/
|
|
3532
|
+
declare const PAGE_TYPES: readonly ["cover", "chapter", "content", "ending"];
|
|
3533
|
+
type PageSpecType = (typeof PAGE_TYPES)[number];
|
|
3534
|
+
type PageBeat = (typeof BEAT_VALUES)[number];
|
|
3535
|
+
/**
|
|
3536
|
+
* A single page spec (spec §5, §6). `type`/`heading` are required — unlike
|
|
3537
|
+
* IR's own `SlideSchema` (where both default/omit for weak-model
|
|
3538
|
+
* friendliness), a deck spec is the authoring artifact those fields get
|
|
3539
|
+
* *locked* from at assemble time (W5 task 3), so leaving either implicit
|
|
3540
|
+
* here would defeat the point. `beat`/`focus`/`summary` stay optional per
|
|
3541
|
+
* spec §5's defaults chain ("beat omitted → auto-rotates by page position —
|
|
3542
|
+
* focus/summary/layout/slot can all be omitted").
|
|
3543
|
+
*/
|
|
3544
|
+
declare const PageSpecSchema: z.ZodObject<{
|
|
3545
|
+
id: z.ZodString;
|
|
3546
|
+
type: z.ZodEnum<{
|
|
3547
|
+
content: "content";
|
|
3548
|
+
cover: "cover";
|
|
3549
|
+
chapter: "chapter";
|
|
3550
|
+
ending: "ending";
|
|
3551
|
+
}>;
|
|
3552
|
+
heading: z.ZodString;
|
|
3553
|
+
beat: z.ZodOptional<z.ZodEnum<{
|
|
3554
|
+
dense: "dense";
|
|
3555
|
+
anchor: "anchor";
|
|
3556
|
+
breathing: "breathing";
|
|
3557
|
+
}>>;
|
|
3558
|
+
focus: z.ZodOptional<z.ZodString>;
|
|
3559
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
3560
|
+
}, z.core.$strict>;
|
|
3561
|
+
type PageSpec = z.infer<typeof PageSpecSchema>;
|
|
3562
|
+
/**
|
|
3563
|
+
* Top-level deck spec shape (spec §5, §6). `narrative`/`theme` deliberately
|
|
3564
|
+
* have no schema-level `.default(...)` — same reasoning as `PptxIRSchema`'s
|
|
3565
|
+
* own `narrative` field (`ir/index.ts`): the resolved value is never baked
|
|
3566
|
+
* back into the parsed shape, {@link validateSpec} (here) and, later,
|
|
3567
|
+
* assemble (W5 task 3) each resolve it themselves. `seed` is accepted but
|
|
3568
|
+
* entirely unexamined by this module — "not validateSpec's concern" (spec's
|
|
3569
|
+
* own wording): assemble generates and suggests writing one back on first
|
|
3570
|
+
* materialization.
|
|
3571
|
+
*
|
|
3572
|
+
* `version` stays the literal `"1"` (unchanged value) but now carries an
|
|
3573
|
+
* independent Deck Spec versioning scheme (spec §6: "`deck.spec.json` 使用
|
|
3574
|
+
* 独立的 spec 版本 1。它是新工件,不继承 `deck.plan.json` 的版本号语义") —
|
|
3575
|
+
* this "1" is the Deck Spec artifact's own first version, not a continuation
|
|
3576
|
+
* of the old deck-plan artifact's version counter, even though the digit is
|
|
3577
|
+
* the same.
|
|
3578
|
+
*/
|
|
3579
|
+
declare const DeckSpecSchema: z.ZodObject<{
|
|
3580
|
+
version: z.ZodDefault<z.ZodLiteral<"1">>;
|
|
3581
|
+
narrative: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>]>>;
|
|
3582
|
+
theme: z.ZodOptional<z.ZodString>;
|
|
3583
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
3584
|
+
seed: z.ZodOptional<z.ZodNumber>;
|
|
3585
|
+
meta: z.ZodDefault<z.ZodObject<{
|
|
3586
|
+
organization: z.ZodOptional<z.ZodString>;
|
|
3587
|
+
authors: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
3588
|
+
name: z.ZodString;
|
|
3589
|
+
role: z.ZodOptional<z.ZodString>;
|
|
3590
|
+
org: z.ZodOptional<z.ZodString>;
|
|
3591
|
+
}, z.core.$strict>>>;
|
|
3592
|
+
date: z.ZodOptional<z.ZodString>;
|
|
3593
|
+
version: z.ZodOptional<z.ZodString>;
|
|
3594
|
+
confidentiality: z.ZodOptional<z.ZodEnum<{
|
|
3595
|
+
public: "public";
|
|
3596
|
+
internal: "internal";
|
|
3597
|
+
confidential: "confidential";
|
|
3598
|
+
restricted: "restricted";
|
|
3599
|
+
}>>;
|
|
3600
|
+
contact: z.ZodOptional<z.ZodObject<{
|
|
3601
|
+
name: z.ZodOptional<z.ZodString>;
|
|
3602
|
+
email: z.ZodOptional<z.ZodString>;
|
|
3603
|
+
phone: z.ZodOptional<z.ZodString>;
|
|
3604
|
+
website: z.ZodOptional<z.ZodString>;
|
|
3605
|
+
}, z.core.$strict>>;
|
|
3606
|
+
copyright: z.ZodOptional<z.ZodString>;
|
|
3607
|
+
animation: z.ZodOptional<z.ZodObject<{
|
|
3608
|
+
transition: z.ZodOptional<z.ZodEnum<{
|
|
3609
|
+
push: "push";
|
|
3610
|
+
none: "none";
|
|
3611
|
+
fade: "fade";
|
|
3612
|
+
wipe: "wipe";
|
|
3613
|
+
}>>;
|
|
3614
|
+
elements: z.ZodOptional<z.ZodEnum<{
|
|
3615
|
+
none: "none";
|
|
3616
|
+
auto: "auto";
|
|
3617
|
+
}>>;
|
|
3618
|
+
}, z.core.$strict>>;
|
|
3619
|
+
}, z.core.$strict>>;
|
|
3620
|
+
brand: z.ZodOptional<z.ZodObject<{
|
|
3621
|
+
logo_asset_id: z.ZodOptional<z.ZodString>;
|
|
3622
|
+
position: z.ZodOptional<z.ZodEnum<{
|
|
3623
|
+
tl: "tl";
|
|
3624
|
+
tr: "tr";
|
|
3625
|
+
bl: "bl";
|
|
3626
|
+
br: "br";
|
|
3627
|
+
}>>;
|
|
3628
|
+
}, z.core.$strict>>;
|
|
3629
|
+
branding: z.ZodOptional<z.ZodEnum<{
|
|
3630
|
+
full: "full";
|
|
3631
|
+
"cover-only": "cover-only";
|
|
3632
|
+
minimal: "minimal";
|
|
3633
|
+
}>>;
|
|
3634
|
+
pages: z.ZodArray<z.ZodObject<{
|
|
3635
|
+
id: z.ZodString;
|
|
3636
|
+
type: z.ZodEnum<{
|
|
3637
|
+
content: "content";
|
|
3638
|
+
cover: "cover";
|
|
3639
|
+
chapter: "chapter";
|
|
3640
|
+
ending: "ending";
|
|
3641
|
+
}>;
|
|
3642
|
+
heading: z.ZodString;
|
|
3643
|
+
beat: z.ZodOptional<z.ZodEnum<{
|
|
3644
|
+
dense: "dense";
|
|
3645
|
+
anchor: "anchor";
|
|
3646
|
+
breathing: "breathing";
|
|
3647
|
+
}>>;
|
|
3648
|
+
focus: z.ZodOptional<z.ZodString>;
|
|
3649
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
3650
|
+
}, z.core.$strict>>;
|
|
3651
|
+
}, z.core.$strict>;
|
|
3652
|
+
type DeckSpec = z.infer<typeof DeckSpecSchema>;
|
|
3653
|
+
/** JSON Schema for the deck spec — feed this to a model before it writes one (see `pptwise schema --spec`). */
|
|
3654
|
+
declare function specJsonSchema(): Record<string, unknown>;
|
|
3655
|
+
interface SpecValidationIssue {
|
|
3656
|
+
path: string;
|
|
3657
|
+
message: string;
|
|
3658
|
+
/** The offending page's `id`, when the issue is scoped to one specific
|
|
3659
|
+
* page and that page's `id` could be determined — absent for deck-level
|
|
3660
|
+
* issues (e.g. "pages non-empty") and for structural issues on a page
|
|
3661
|
+
* whose own `id` itself failed to parse. */
|
|
3662
|
+
pageId?: string;
|
|
3663
|
+
}
|
|
3664
|
+
interface SpecValidateResult {
|
|
3665
|
+
ok: boolean;
|
|
3666
|
+
spec?: DeckSpec;
|
|
3667
|
+
errors: SpecValidationIssue[];
|
|
3668
|
+
/**
|
|
3669
|
+
* Same shape and channel as `ValidateResult.normalized` (`../validate-core.ts`)
|
|
3670
|
+
* — human-readable `path: alias → canonical`-style rewrite entries for every
|
|
3671
|
+
* deterministic pre-parse rewrite `validateSpec` applied before parsing.
|
|
3672
|
+
* Sources: `normalizeDeckRootAliases` (`chrome` → `branding`) and
|
|
3673
|
+
* `normalizeNarrativeShape` (`../narrative`, T0b fix 2): a top-level
|
|
3674
|
+
* `narrative: {id: "<preset>"}` shape rewritten to the bare preset string.
|
|
3675
|
+
* Present only when at least one rewrite happened; informational, never
|
|
3676
|
+
* gates `ok` on its own.
|
|
3677
|
+
* `cli/commands.ts`'s `runSpecValidate` prints this through the same
|
|
3678
|
+
* `normalizedNote` helper `runValidate`/`runRender` already use for the
|
|
3679
|
+
* bare-IR path's own component field-alias notes.
|
|
3680
|
+
*/
|
|
3681
|
+
normalized?: string[];
|
|
3682
|
+
}
|
|
3683
|
+
declare function formatSpecIssues(errors: SpecValidationIssue[]): string;
|
|
3684
|
+
/**
|
|
3685
|
+
* Deck-spec-level theme default (spec §5's defaults chain: "theme omitted →
|
|
3686
|
+
* consulting") — the same default IR's own `theme.id` field carries
|
|
3687
|
+
* (`ThemeSchema` in `ir/index.ts`). Exported so a caller already holding a
|
|
3688
|
+
* validated {@link DeckSpec} (the CLI's OK-summary line) doesn't re-derive
|
|
3689
|
+
* the fallback itself.
|
|
3690
|
+
*/
|
|
3691
|
+
declare function resolveSpecThemeId(spec: DeckSpec): string;
|
|
3692
|
+
/**
|
|
3693
|
+
* Deck-level page-count range per pacing (spec §5's pacing table,
|
|
3694
|
+
* initial values — "dense 8-30 / balanced 6-24 / spacious 4-16", not yet
|
|
3695
|
+
* tuned against real usage). Independent of `PACING_BUDGETS`
|
|
3696
|
+
* (`narrative/index.ts`, per-slide component-count/bullets editorial
|
|
3697
|
+
* budget) — this is a separate, deck-wide page-count concern the spec calls
|
|
3698
|
+
* out as its own hard gate ("page count vs. pacing recommended range").
|
|
3699
|
+
* Message wording renamed from "delivery" to "pacing" (vocabulary-v4
|
|
3700
|
+
* residual, routed from the task 1 review) — the axis itself was already
|
|
3701
|
+
* `Pacing` at the type level, this closes the last stale word in the
|
|
3702
|
+
* error text.
|
|
3703
|
+
*/
|
|
3704
|
+
declare const SPEC_PAGE_COUNT_RANGE: Record<Pacing, {
|
|
3705
|
+
min: number;
|
|
3706
|
+
max: number;
|
|
3707
|
+
}>;
|
|
3708
|
+
/**
|
|
3709
|
+
* Validate raw JSON against the spec schema, then — once it parses — run the
|
|
3710
|
+
* spec §5 hard-gate chain. Mirrors `validateIr`'s (`api.ts`) overall shape: a
|
|
3711
|
+
* structural zod pass first, then a sequence of isolated hard-gate
|
|
3712
|
+
* categories, each short-circuiting the whole chain on its own failure
|
|
3713
|
+
* (rather than accumulating errors across categories) so a later category
|
|
3714
|
+
* never has to guess at what an earlier, already-broken one would have
|
|
3715
|
+
* meant — e.g. beat-rotation and page-count both need a resolved
|
|
3716
|
+
* narrative, so nothing past the narrative/theme stage runs until that
|
|
3717
|
+
* resolves cleanly. Every spec-gate philosophy here is "hard block, no soft
|
|
3718
|
+
* warning" (spec §5's "escape hatch" section — a spec that doesn't fit this shape
|
|
3719
|
+
* should be authored as bare IR instead, not warned-and-shipped).
|
|
3720
|
+
*
|
|
3721
|
+
* Before the schema parse, {@link normalizeNarrativeShape} (`../narrative`,
|
|
3722
|
+
* T0b fix 2 scope extension) runs on the raw input, exactly mirroring
|
|
3723
|
+
* `validateIr`'s own pre-parse pass (`../validate-core.ts`) — a top-level
|
|
3724
|
+
* `narrative: {id: "<preset>"}` shape is rewritten to the bare preset
|
|
3725
|
+
* string before `DeckSpecSchema.safeParse` ever sees it, so the correction
|
|
3726
|
+
* lands in the returned `spec` itself (read again by `checkBeatRotation`/
|
|
3727
|
+
* `checkFocusVocabulary`/`checkPageCount` below, and by `runSpecValidate`'s
|
|
3728
|
+
* own OK-summary line, `../cli/commands.ts`), not just this function's own
|
|
3729
|
+
* local `resolveNarrative` call below. Every return path is wrapped in
|
|
3730
|
+
* `withNormalized` so the rewrite note (`SpecValidateResult.normalized`)
|
|
3731
|
+
* surfaces on success *or* failure, success or failure alike — same
|
|
3732
|
+
* "informational, never gates `ok`" contract `ValidateResult.normalized`
|
|
3733
|
+
* has.
|
|
3734
|
+
*/
|
|
3735
|
+
declare function validateSpec(input: unknown): SpecValidateResult;
|
|
3736
|
+
|
|
3737
|
+
/**
|
|
3738
|
+
* One page's fillable content — everything a page spec's `id` does *not*
|
|
3739
|
+
* already lock in. Deliberately excludes `type`/`heading` (spec-owned, see
|
|
3740
|
+
* {@link assembleDeck}'s locked-field gate) and `subheading`/`decor`
|
|
3741
|
+
* (legitimate `Slide` fields, but outside this record's shape by spec §7's
|
|
3742
|
+
* own layout — "pages/<id>.json contains only components" — a spec/pages deck can't
|
|
3743
|
+
* author either one — a hand-authored bare IR still can). Every field here is
|
|
3744
|
+
* a same-name, same-shape subset of `Slide`'s own optional fields
|
|
3745
|
+
* (`../ir`'s `SlideSchema`) — reused, not redeclared, so the two can't drift.
|
|
3746
|
+
*/
|
|
3747
|
+
interface PageContent {
|
|
3748
|
+
components?: Component[];
|
|
3749
|
+
layout?: string;
|
|
3750
|
+
arrangement?: NonNullable<Slide["arrangement"]>;
|
|
3751
|
+
background?: BackgroundSpec;
|
|
3752
|
+
image_side?: "left" | "right";
|
|
3753
|
+
footnote?: string;
|
|
3754
|
+
notes?: string;
|
|
3755
|
+
}
|
|
3756
|
+
interface AssembleResult {
|
|
3757
|
+
ir: PptxIR;
|
|
3758
|
+
/**
|
|
3759
|
+
* Set only when `spec.seed` was absent and {@link assembleDeck} generated
|
|
3760
|
+
* one deterministically (see the seed section of this function's doc
|
|
3761
|
+
* comment) — `undefined` when `spec.seed` was already present and simply
|
|
3762
|
+
* passed through. The CLI shell (W5 task 5) is the one that acts on this:
|
|
3763
|
+
* suggest writing the value back into the spec file, never rewrite it
|
|
3764
|
+
* itself (assemble stays a pure function, no fs side effects here).
|
|
3765
|
+
*/
|
|
3766
|
+
generatedSeed?: number;
|
|
3767
|
+
/**
|
|
3768
|
+
* Count of pages whose `layout` field this call filled in via
|
|
3769
|
+
* {@link materializeEffectiveLayouts} (W4 design decision 10) —
|
|
3770
|
+
* `undefined` when zero, same "absent means nothing to report" posture as
|
|
3771
|
+
* {@link generatedSeed} just above (a page with an explicit pin already in
|
|
3772
|
+
* its page file, or every omitted page landing on the image-cover
|
|
3773
|
+
* takeover's `null` bypass, both leave this unset). Purely informational:
|
|
3774
|
+
* the CLI shell (`runAssemble`, `../cli/commands.ts`) surfaces it as a
|
|
3775
|
+
* one-line note, nothing here or downstream acts on the number itself.
|
|
3776
|
+
*/
|
|
3777
|
+
materializedLayoutCount?: number;
|
|
3778
|
+
}
|
|
3779
|
+
/**
|
|
3780
|
+
* Assemble a validated deck spec plus a per-page content record into a
|
|
3781
|
+
* renderable IR. See this module's own top comment for the overall shape.
|
|
3782
|
+
* Step numbers below match the W5 task-3 brief's own numbered "inject
|
|
3783
|
+
* semantics" list verbatim — kept in that exact order because two of them
|
|
3784
|
+
* (locked-field vs. orphan) both throw and their relative order is
|
|
3785
|
+
* otherwise unobservable from either doc comment alone.
|
|
3786
|
+
*
|
|
3787
|
+
* 1. `spec` is `unknown` (same boundary `validateSpec` itself has — a spec
|
|
3788
|
+
* is almost always freshly `JSON.parse`d off disk by the caller) —
|
|
3789
|
+
* invalid shape or a failed hard gate throws {@link PptwiseError} with
|
|
3790
|
+
* `validateSpec`'s own formatted issue list, not a re-derived message.
|
|
3791
|
+
* 2. Shape guard + locked-field protection: a `pages[id]` entry must first be
|
|
3792
|
+
* a plain object — not `null`, an array, or a primitive — else throws.
|
|
3793
|
+
* `pages` is `unknown`-shaped off disk same as `spec` itself (step 1), so
|
|
3794
|
+
* a JSON `null`/string/array content value is a real possibility, not
|
|
3795
|
+
* just a type-system hole, and `Object.hasOwn` throws its own
|
|
3796
|
+
* uninformative native `TypeError` on `null` (and silently no-ops on a
|
|
3797
|
+
* string/array/number) rather than this gate's own readable message.
|
|
3798
|
+
* Once that holds, a `pages[id]` entry that carries a `type` or `heading`
|
|
3799
|
+
* *key* — even set to `undefined` — throws. `Object.hasOwn`, not a
|
|
3800
|
+
* `!== undefined` read, is what makes that "even `undefined`" case
|
|
3801
|
+
* catchable: `PageContent` itself never declares either field, but a
|
|
3802
|
+
* page file freshly parsed off disk is `unknown` before it reaches this
|
|
3803
|
+
* function's declared `PageContent` parameter type, so a stray
|
|
3804
|
+
* `"heading": null`-turned-`undefined` or a copy-pasted empty key is
|
|
3805
|
+
* exactly the drift this gate exists to catch instead of silently
|
|
3806
|
+
* ignoring.
|
|
3807
|
+
* 3. Orphan keys: a `pages` entry whose id isn't any spec page's id. Listed
|
|
3808
|
+
* together with a fix suggestion, checked only after every present page
|
|
3809
|
+
* has cleared the locked-field gate (step 2) — an orphan file that
|
|
3810
|
+
* *also* happens to redeclare `heading` reports as locked-field first.
|
|
3811
|
+
* 4. Missing pages (a spec id with no `pages` entry) become a placeholder
|
|
3812
|
+
* slide — never an error. Spec §7's own words: "assemble's precise
|
|
3813
|
+
* semantics — a missing page always succeeds (placeholder), a structural
|
|
3814
|
+
* contradiction (orphan file / bad spec / id conflict) errors". A
|
|
3815
|
+
* declared `summary` becomes the placeholder's `subheading` so a
|
|
3816
|
+
* `--draft` preview of an unfilled deck still reads as more than a bare
|
|
3817
|
+
* "Untitled". Step 5 preserves the same visible line for filled boundary
|
|
3818
|
+
* pages while keeping it fill-only on filled content pages. A declared
|
|
3819
|
+
* `beat` carries straight into the
|
|
3820
|
+
* placeholder's own `Slide.beat` too (P1 variety wave, task 1 — see step
|
|
3821
|
+
* 5's note below). A placeholder page still participates in this
|
|
3822
|
+
* function's own layout materialization below, so its beat still needs
|
|
3823
|
+
* to reach the IR for that weighting to see it once the page is filled
|
|
3824
|
+
* in later without re-materializing.
|
|
3825
|
+
* 5. Present pages become a full slide: `id`/`type`/`heading` from the page
|
|
3826
|
+
* spec (never the content record — see step 2), plus whichever of
|
|
3827
|
+
* {@link PageContent}'s seven fields the content record actually set.
|
|
3828
|
+
* `beat` now carries straight into the IR's own `Slide.beat` field too —
|
|
3829
|
+
* reached from `PageSpec`, not `PageContent` (same source as `id`/`type`/
|
|
3830
|
+
* `heading`, since `beat` is spec-owned, not per-page content) — as of
|
|
3831
|
+
* the P1 variety wave's task 1. Previously dropped here as a spec-only
|
|
3832
|
+
* authoring anchor, `SlideSchema.beat`'s own doc comment
|
|
3833
|
+
* (`../ir/index.ts`) has the full accounting of what it now does
|
|
3834
|
+
* downstream. `focus` remains a spec-only authoring anchor. A filled
|
|
3835
|
+
* boundary page (`cover`, `chapter`, or `ending`) carries `summary` into
|
|
3836
|
+
* `subheading`, because its page file has no body-content field that can
|
|
3837
|
+
* express the line after filling. A filled `content` page keeps summary
|
|
3838
|
+
* spec-only, so its fill prompt does not become duplicate visible slide
|
|
3839
|
+
* content.
|
|
3840
|
+
* 6. Top-level: `version` is always the literal `"4"` (IR's own version,
|
|
3841
|
+
* unrelated to the deck spec's own `version: "1"`) — the deck spec's own
|
|
3842
|
+
* `narrative` field (renamed this task from `scenario`, spec §8.1's
|
|
3843
|
+
* `DeckPlan`→`DeckSpec` rename, task 2) carries across into the v4 IR's
|
|
3844
|
+
* own `narrative` field, its value already in the new strategy/pacing
|
|
3845
|
+
* vocabulary (vocabulary-v4 rename, task 1 — `spec/index.ts`'s own
|
|
3846
|
+
* `resolveNarrative` call already validates it against that vocabulary
|
|
3847
|
+
* before this function ever runs).
|
|
3848
|
+
* `theme`/`filename`/`brand`/`branding`/`meta`/`seed` (step 7) carry over from the spec when
|
|
3849
|
+
* present. When absent, this function omits the field from the raw
|
|
3850
|
+
* object it hands to {@link PptxIRSchema} rather than re-deriving IR's
|
|
3851
|
+
* own default value a second time — one default source of truth, the
|
|
3852
|
+
* schema itself (e.g. `theme` omitted here becomes `{ id: "consulting" }`,
|
|
3853
|
+
* exactly like a bare hand-authored IR that never mentions theme at all —
|
|
3854
|
+
* not a value this function needs to know). `branding` is the same omit
|
|
3855
|
+
* posture: a spec that never sets it produces an IR that never sets it,
|
|
3856
|
+
* and the renderer treats that as `"cover-only"`. This function must not
|
|
3857
|
+
* infer branding from narrative.
|
|
3858
|
+
* 7. Seed: `spec.seed` present → passed through, `generatedSeed` stays
|
|
3859
|
+
* `undefined` on the result. Absent → {@link generateSeed} derives one
|
|
3860
|
+
* from `filename` + the spec's own ordered page-id list (never page
|
|
3861
|
+
* *content* — see that function's own doc comment for why), written to
|
|
3862
|
+
* `ir.seed` *and* returned as `generatedSeed` so a CLI shell can suggest
|
|
3863
|
+
* writing it back into the spec file (this function never touches disk
|
|
3864
|
+
* itself).
|
|
3865
|
+
* 8. Idempotence: every step above is a pure function of its inputs (no
|
|
3866
|
+
* randomness, no wall-clock, no reliance on unordered iteration) — two
|
|
3867
|
+
* calls with structurally-equal `spec`/`pages` produce deep-equal
|
|
3868
|
+
* results, `generatedSeed` included. Exercised directly by this module's
|
|
3869
|
+
* test suite rather than asserted here.
|
|
3870
|
+
*/
|
|
3871
|
+
declare function assembleDeck(spec: unknown, pages: Record<string, PageContent>): AssembleResult;
|
|
3872
|
+
/**
|
|
3873
|
+
* Inverse of {@link assembleDeck}: reconstructs `{ spec, pages }` from an
|
|
3874
|
+
* existing IR well enough that `assembleDeck(...disassembleDeck(ir))`
|
|
3875
|
+
* reproduces the deck-project content surface. The map is not lossless for
|
|
3876
|
+
* fields that the spec/pages format cannot represent. The known losses and
|
|
3877
|
+
* recoveries are:
|
|
3878
|
+
*
|
|
3879
|
+
* - `focus` never appears on any produced {@link PageSpec} — it is a
|
|
3880
|
+
* spec-only authoring anchor with no corresponding `Slide` field at all
|
|
3881
|
+
* (see {@link assembleDeck} step 5's doc comment). Nothing here could
|
|
3882
|
+
* recover a value that was never written anywhere. `beat` used to share
|
|
3883
|
+
* this fate but no longer does (P1 variety wave, task 1): it is now a
|
|
3884
|
+
* plain passthrough on both sides, exactly like `layout`/`heading` below —
|
|
3885
|
+
* `assembleDeck` step 5/6 reads `pageSpec.beat` into `slide.beat`, this
|
|
3886
|
+
* function reads `slide.beat` straight back below.
|
|
3887
|
+
* - `summary` is recovered from `subheading` for every placeholder slide and
|
|
3888
|
+
* for filled boundary slides (`cover`, `chapter`, and `ending`). This
|
|
3889
|
+
* reverses steps 4 and 5 without losing their visible subtitle. A filled
|
|
3890
|
+
* content slide's own `subheading` remains a separate authored field. It
|
|
3891
|
+
* has no {@link PageContent} field to land in, and treating it as summary
|
|
3892
|
+
* would turn visible slide copy into a fill-only prompt, so it is dropped.
|
|
3893
|
+
* Same for `decor`: a real `Slide` field absent from `PageContent`.
|
|
3894
|
+
* - `theme.style` / `theme.brand` overrides collapse to a bare theme-id
|
|
3895
|
+
* string (`DeckSpecSchema.theme` has no shape for either) — only `theme.id`
|
|
3896
|
+
* survives. That `theme.brand` is `ThemeSchema.brand` (`BrandConfigSchema`
|
|
3897
|
+
* — `suppressFooterOnCardContent`/`suppressFooterRule`/`suppressFooterMeta`,
|
|
3898
|
+
* brand-footer flags owned by the *theme*) — not to be confused with the deck-level
|
|
3899
|
+
* `brand` field below, a different, unrelated schema despite the shared
|
|
3900
|
+
* name.
|
|
3901
|
+
* - `ir.assets.images` is not part of this function's return value at all —
|
|
3902
|
+
* `{ spec, pages }` has no `assets` field, and this module stays zero-fs
|
|
3903
|
+
* by design (this file's own top comment), so it has no way to write an
|
|
3904
|
+
* `assets/` directory itself. Any `asset_id` reference inside a copied
|
|
3905
|
+
* `components`/`background` survives untouched ({@link extractPageContent}
|
|
3906
|
+
* copies both as-is), but the underlying image bytes are deliberately left
|
|
3907
|
+
* for the caller: the CLI shell closes that gap. `runDisassemble`
|
|
3908
|
+
* (`../cli/commands.ts`) walks the *input* IR's `ir.assets.images` itself
|
|
3909
|
+
* and materializes every entry into `<outDir>/assets/<id>.<ext>`
|
|
3910
|
+
* (`writeDeckAssets`, `../cli/deck-dir.ts`) so a later `readDeckDir`'s
|
|
3911
|
+
* `scanAssets` re-registers them exactly like any other deck-directory
|
|
3912
|
+
* asset. Skipping that shell-side step is not a doc-comment nuance — it
|
|
3913
|
+
* reproduces as a real bug: an image deck disassembles with every
|
|
3914
|
+
* `asset_id` left dangling, then re-assembles and renders with the image
|
|
3915
|
+
* silently missing.
|
|
3916
|
+
*
|
|
3917
|
+
* Round-trip-safe despite the above, worth calling out because of that name
|
|
3918
|
+
* collision: the top-level `brand` field (`BrandSchema` — `logo_asset_id` /
|
|
3919
|
+
* `position`, the deck logo/position `Branding` reads,
|
|
3920
|
+
* `src/svg/branding.tsx`) is a plain passthrough on both sides
|
|
3921
|
+
* ({@link assembleDeck} step 6 reads `spec.brand` into `ir.brand` — this
|
|
3922
|
+
* function reads `ir.brand` back into `spec.brand` below) — carried through
|
|
3923
|
+
* unmodified, same as `narrative`/`filename`/`seed`/`branding`, never
|
|
3924
|
+
* synthesized or dropped.
|
|
3925
|
+
*
|
|
3926
|
+
* `layout` deserves a different kind of callout: it round-trips as plain
|
|
3927
|
+
* content like any other field ({@link extractPageContent} copies
|
|
3928
|
+
* `slide.layout` into `PageContent.layout` whenever the slide has one, no
|
|
3929
|
+
* special case) — but a `deck.json` produced by {@link assembleDeck} now
|
|
3930
|
+
* carries a `layout` on nearly every slide (W4 design decision 10's
|
|
3931
|
+
* materialization, see that function's own doc comment), even on pages whose
|
|
3932
|
+
* *original page file* never set one. Nothing on `Slide` marks which is
|
|
3933
|
+
* which — `layout` is just a string either way — so disassembling an
|
|
3934
|
+
* already-assembled `deck.json` writes every materialized pick into the
|
|
3935
|
+
* regenerated page file as if it had been an explicit pin all along, and a
|
|
3936
|
+
* later re-`assembleDeck` call skips materialization for that page from then
|
|
3937
|
+
* on, same as any hand-authored pin. Accepted, not a bug: `disassembleDeck`
|
|
3938
|
+
* is a one-time bare-IR importer into an editable project directory, not a
|
|
3939
|
+
* round-trip channel for `deck.json` itself. A deck project's own
|
|
3940
|
+
* `pages/<id>.json` files are the durable, edit-in-place artifacts —
|
|
3941
|
+
* `deck.json` is downstream output, and feeding it back through
|
|
3942
|
+
* `disassembleDeck` (instead of editing the project directory that produced
|
|
3943
|
+
* it) is what actually costs those pages their revision-stability
|
|
3944
|
+
* re-selection eligibility going forward. A real, user-visible narrowing,
|
|
3945
|
+
* worth knowing about here, not worth adding code to guard against for a
|
|
3946
|
+
* usage pattern nothing in this codebase actually exercises.
|
|
3947
|
+
*
|
|
3948
|
+
* Two structural fields are synthesized rather than copied when the source
|
|
3949
|
+
* slide omits them, each documented where it is generated:
|
|
3950
|
+
* {@link UNTITLED_HEADING} for a missing/blank `heading`, and a positional
|
|
3951
|
+
* `p-<1-based-ordinal>-<type>` scheme for a missing `id` (stable across
|
|
3952
|
+
* repeated calls on the same IR — it is a pure function of slide position
|
|
3953
|
+
* and type — but, unlike a spec-assigned id, *not* stable across inserting
|
|
3954
|
+
* or reordering slides — out of scope here, since a bare IR with no `id` at
|
|
3955
|
+
* all has no stabler identity to fall back to in the first place).
|
|
3956
|
+
*
|
|
3957
|
+
* That generated `p-<ordinal>-<type>` id is safe by construction as a
|
|
3958
|
+
* page/asset file-name segment (W5 whole-branch review finding 1, verified
|
|
3959
|
+
* — not just asserted — rather than also routing it through
|
|
3960
|
+
* `assertSafeFileSegment`, `../cli/deck-dir.ts`): `<ordinal>` is
|
|
3961
|
+
* `index + 1`, always a plain non-negative integer, and `<type>` is a
|
|
3962
|
+
* `Slide["type"]`, a closed schema enum (`"cover" | "chapter" | "content" |
|
|
3963
|
+
* "ending"`, `SlideSchema.type` in `../ir/index.ts`) — neither half can ever
|
|
3964
|
+
* contain a `/`, a `\`, or resolve to `".."`, so the joined id can't either.
|
|
3965
|
+
* A carried-over `slide.id` (the `??` branch's other side) has no such
|
|
3966
|
+
* guarantee — that is the one this function passes straight through
|
|
3967
|
+
* unchecked, same as every other field {@link extractPageContent} copies —
|
|
3968
|
+
* which is exactly why the write-time gate in `../cli/deck-dir.ts` (not this
|
|
3969
|
+
* function) is what actually closes the vulnerability.
|
|
3970
|
+
*/
|
|
3971
|
+
declare function disassembleDeck(ir: PptxIR): {
|
|
3972
|
+
spec: DeckSpec;
|
|
3973
|
+
pages: Record<string, PageContent>;
|
|
3974
|
+
};
|
|
3975
|
+
|
|
3976
|
+
declare function migrateDeckPlanToSpec(raw: unknown): unknown;
|
|
3977
|
+
|
|
3978
|
+
/**
|
|
3979
|
+
* `pptwise audit` finding shape (v0.3 W6, spec §7 workflow ④). `page` is
|
|
3980
|
+
* 1-based (matches `ValidationIssue.page` in `api.ts`); `slideId` is set
|
|
3981
|
+
* whenever the offending slide has a stable `id` (assemble-stamped or
|
|
3982
|
+
* author-supplied), same "page + optional id" convention `formatIssues`
|
|
3983
|
+
* already uses for validate errors.
|
|
3984
|
+
*/
|
|
3985
|
+
interface AuditFinding {
|
|
3986
|
+
page: number;
|
|
3987
|
+
slideId?: string;
|
|
3988
|
+
code: "overflow" | "out-of-bounds" | "low-contrast" | "overlap" | "content-truncated" | "content-dropped";
|
|
3989
|
+
message: string;
|
|
3990
|
+
detail?: Record<string, unknown>;
|
|
3991
|
+
}
|
|
3992
|
+
/**
|
|
3993
|
+
* Which check families actually ran (audit-v2 phase B, spec §4.2/§11.6) —
|
|
3994
|
+
* the one piece of the spec's original metrics design that survives into
|
|
3995
|
+
* this wave (§11.6: metrics itself deferred, "唯一现值是 checks 结构"). This
|
|
3996
|
+
* is the wave's own spirit made literal: a field can only ever be
|
|
3997
|
+
* `"completed"` once its check family genuinely ran over every audited
|
|
3998
|
+
* page, never a default that silently reads as "passed". `svg` has no
|
|
3999
|
+
* `"not-requested"` state — the deterministic SVG audit always runs, so it
|
|
4000
|
+
* is always `"completed"`. `pixels` starts `"not-requested"` and only ever
|
|
4001
|
+
* becomes `"completed"`; there is deliberately no `"failed"` value — a
|
|
4002
|
+
* failed pixel audit throws (spec §11.7's "契约层"), it never reports
|
|
4003
|
+
* itself as a completed check that happens to carry no findings.
|
|
4004
|
+
*/
|
|
4005
|
+
interface AuditChecks {
|
|
4006
|
+
svg: "completed";
|
|
4007
|
+
pixels: "not-requested" | "completed";
|
|
4008
|
+
}
|
|
4009
|
+
interface AuditReport {
|
|
4010
|
+
findings: AuditFinding[];
|
|
4011
|
+
pagesAudited: number;
|
|
4012
|
+
pagesSkipped: number;
|
|
4013
|
+
checks: AuditChecks;
|
|
4014
|
+
}
|
|
4015
|
+
/** `auditDeck`'s second parameter (audit-v2 phase B) — see that function's
|
|
4016
|
+
* own doc comment for the overload contract this shape backs. */
|
|
4017
|
+
interface AuditDeckOptions {
|
|
4018
|
+
pixels?: boolean;
|
|
4019
|
+
}
|
|
4020
|
+
/**
|
|
4021
|
+
* The SDK entry point. Advisory, not a hard gate: `validateIr` already
|
|
4022
|
+
* rejects structurally invalid or over-dense decks before a caller ever
|
|
4023
|
+
* gets this far; this function looks for the visual problems that can still
|
|
4024
|
+
* slip through a valid deck at render time (an author-chosen near-background
|
|
4025
|
+
* text color, two components whose combined content happens to collide, a
|
|
4026
|
+
* card list that had to drop an item to fit). A non-empty `findings` array
|
|
4027
|
+
* is a prompt for a human/agent to look, not a rejection.
|
|
4028
|
+
*
|
|
4029
|
+
* Placeholder pages (`slide.placeholder === true`) are skipped — assemble's
|
|
4030
|
+
* stand-in for content nobody has written yet has nothing to audit, same
|
|
4031
|
+
* reasoning `checkIrQuality` already uses to skip them (`ir-quality.ts`).
|
|
4032
|
+
*
|
|
4033
|
+
* `auditDeck` itself never calls `installNodePlatform()`; that's the
|
|
4034
|
+
* caller's job (the CLI does it automatically).
|
|
4035
|
+
*
|
|
4036
|
+
* `opts.pixels` (audit-v2 phase B, spec §4.3/§11.7) opts into the optional
|
|
4037
|
+
* pixel-level contrast audit over image-backed text (`../svg/audit/pixel-audit.ts`)
|
|
4038
|
+
* — overloaded so the far more common omitted/`false` case keeps returning
|
|
4039
|
+
* a plain, synchronous `AuditReport` (spec §11.7's "语义层": the default
|
|
4040
|
+
* audit stays pure TS with zero added latency or Promise-wrapping), while
|
|
4041
|
+
* `pixels: true` returns a `Promise<AuditReport>` that resolves once the
|
|
4042
|
+
* rasterization pass completes. A caller holding a non-literal
|
|
4043
|
+
* `{ pixels: someBoolean }` won't match either overload directly (TypeScript
|
|
4044
|
+
* can't narrow it to one specific branch) — branch on the boolean first and
|
|
4045
|
+
* call this function with a literal in each arm, e.g. `opts.pixels ? await
|
|
4046
|
+
* auditDeck(ir, { pixels: true }) : auditDeck(ir)` (`cli/commands.ts`'s
|
|
4047
|
+
* `runAudit` does exactly this).
|
|
4048
|
+
*/
|
|
4049
|
+
declare function auditDeck(ir: PptxIR, opts?: {
|
|
4050
|
+
pixels?: false;
|
|
4051
|
+
}): AuditReport;
|
|
4052
|
+
declare function auditDeck(ir: PptxIR, opts: {
|
|
4053
|
+
pixels: true;
|
|
4054
|
+
}): Promise<AuditReport>;
|
|
4055
|
+
|
|
4056
|
+
/**
|
|
4057
|
+
* Real rendered frame for one image slot, in canvas px (0-1280 × 0-720 —
|
|
4058
|
+
* `../constants`'s `CANVAS_W_PX`/`CANVAS_H_PX`). This is the whole point of
|
|
4059
|
+
* this module (asset-brief plan, 裁定 1): it comes from parsing an actual
|
|
4060
|
+
* render pass's SVG output, never from hand-copying `image.tsx`'s
|
|
4061
|
+
* `w * 0.5`/`MAX_IMAGE_H` constants — those change independently of this
|
|
4062
|
+
* file, and a shadow copy would silently start lying the day they do.
|
|
4063
|
+
*/
|
|
4064
|
+
interface AssetBriefFrame {
|
|
4065
|
+
x: number;
|
|
4066
|
+
y: number;
|
|
4067
|
+
w: number;
|
|
4068
|
+
h: number;
|
|
4069
|
+
/** e.g. "2:1" when w:h reduces to a small clean ratio, else "1.63:1". */
|
|
4070
|
+
aspect: string;
|
|
4071
|
+
}
|
|
4072
|
+
interface AssetBriefFit {
|
|
4073
|
+
mode: "cover" | "contain";
|
|
4074
|
+
/** One sentence: crop behavior + safe-zone guidance for a generator. */
|
|
4075
|
+
note: string;
|
|
4076
|
+
}
|
|
4077
|
+
interface AssetBriefPalette {
|
|
4078
|
+
/** Deduplicated theme hex values, in `StyleColors`' own field order. */
|
|
4079
|
+
hexes: string[];
|
|
4080
|
+
primary: string;
|
|
4081
|
+
accent: string;
|
|
4082
|
+
}
|
|
4083
|
+
interface AssetBriefMood {
|
|
4084
|
+
/** `ThemeDefinition.tags` passed through as-is (empty for every one of
|
|
4085
|
+
* the 13 builtins today — none has adopted this field yet — but a
|
|
4086
|
+
* registered custom theme may set it). */
|
|
4087
|
+
tags: readonly string[];
|
|
4088
|
+
/** One sentence assembled from the theme's own label/motif — never a
|
|
4089
|
+
* hand-written per-theme paragraph (asset-brief plan 裁定: "不新写 13 段
|
|
4090
|
+
* 文案"). */
|
|
4091
|
+
description: string;
|
|
4092
|
+
}
|
|
4093
|
+
interface AssetBriefPage {
|
|
4094
|
+
index: number;
|
|
4095
|
+
id?: string;
|
|
4096
|
+
type: Slide["type"];
|
|
4097
|
+
heading?: string;
|
|
4098
|
+
}
|
|
4099
|
+
interface AssetBriefItem {
|
|
4100
|
+
page: AssetBriefPage;
|
|
4101
|
+
asset_id: string;
|
|
4102
|
+
/** `ir.assets.images[asset_id].alt` passed straight through (A11Y-01 alt
|
|
4103
|
+
* chain wave, task 1) — this is already a per-asset structure, so a
|
|
4104
|
+
* generator agent filling in `missing`/`suggested_prompt` items sees
|
|
4105
|
+
* right alongside them which ids already have an accessibility
|
|
4106
|
+
* description written and which don't. Omitted (not an empty string)
|
|
4107
|
+
* when the asset has no `alt` — same "don't fabricate a value that
|
|
4108
|
+
* isn't there" discipline the rest of this file already follows for
|
|
4109
|
+
* `frame`/`suggested_pixels`. */
|
|
4110
|
+
alt?: string;
|
|
4111
|
+
/** Discriminant reserved for v2 (asset-brief plan 裁定 4): only `"image"`
|
|
4112
|
+
* is produced today (one `AssetBriefItem` per `image` component, or per
|
|
4113
|
+
* shared frame — see `shared` below). `"background"` is the documented
|
|
4114
|
+
* extension slot for background asset specs, deliberately not built in
|
|
4115
|
+
* v1 (no `background` geometry extraction exists yet) — this field lets
|
|
4116
|
+
* a future v2 add it without a breaking shape change for consumers that
|
|
4117
|
+
* already switch on `kind`. */
|
|
4118
|
+
kind: "image";
|
|
4119
|
+
/** No usable `src` in `ir.assets.images` for this `asset_id` — this is a
|
|
4120
|
+
* generation to-do item, not a defect (asset-brief plan 裁定 2). */
|
|
4121
|
+
missing: boolean;
|
|
4122
|
+
/** `false` when the selected layout dropped this image component
|
|
4123
|
+
* entirely (e.g. an overflow guard) — still listed rather than silently
|
|
4124
|
+
* dropped (task brief's explicit requirement). `frame`/`suggested_pixels`
|
|
4125
|
+
* are omitted in that case; there is no real geometry to report. */
|
|
4126
|
+
rendered: boolean;
|
|
4127
|
+
frame?: AssetBriefFrame;
|
|
4128
|
+
/** 2× the frame's own pixel dimensions — omitted alongside `frame` when `rendered` is false. */
|
|
4129
|
+
suggested_pixels?: {
|
|
4130
|
+
w: number;
|
|
4131
|
+
h: number;
|
|
4132
|
+
};
|
|
4133
|
+
fit: AssetBriefFit;
|
|
4134
|
+
palette: AssetBriefPalette;
|
|
4135
|
+
mood: AssetBriefMood;
|
|
4136
|
+
/** One English paragraph, paste-ready for an image-generation tool. */
|
|
4137
|
+
suggested_prompt: string;
|
|
4138
|
+
/** True when this item's `frame` cannot be attributed to one specific
|
|
4139
|
+
* `image` component: `occurrenceCount` (>=2) `image` components on this
|
|
4140
|
+
* same page share this `asset_id`. Because a shared `asset_id` resolves
|
|
4141
|
+
* to the exact same dummy href in the render-only pass, every occurrence
|
|
4142
|
+
* produces an *identical* `<image>` `href` in the rendered SVG — there is
|
|
4143
|
+
* no signal left to tell which `<image>` element came from which
|
|
4144
|
+
* component, in principle, not just in this implementation. Rather than
|
|
4145
|
+
* guess (see `buildAssetBrief`'s own doc comment for the bug this
|
|
4146
|
+
* replaced), every real rendered frame for the shared `asset_id` gets its
|
|
4147
|
+
* own item, all flagged `shared: true`, none claiming a specific
|
|
4148
|
+
* component. Omitted (not `false`) for the single-occurrence case — the
|
|
4149
|
+
* overwhelmingly common one — so that path's output shape is byte-for-
|
|
4150
|
+
* byte what it was before this field existed. */
|
|
4151
|
+
shared?: true;
|
|
4152
|
+
/** Present iff `shared` is true: how many `image` components on this page
|
|
4153
|
+
* reference this same `asset_id`. */
|
|
4154
|
+
occurrenceCount?: number;
|
|
4155
|
+
}
|
|
4156
|
+
interface AssetBrief {
|
|
4157
|
+
theme: string;
|
|
4158
|
+
items: AssetBriefItem[];
|
|
4159
|
+
}
|
|
4160
|
+
/**
|
|
4161
|
+
* Build an image-generation brief for every `image` component in a deck: the
|
|
4162
|
+
* real rendered frame (from an actual render pass — see `extractImageFrames`),
|
|
4163
|
+
* fit/crop mode with a safe-zone note, suggested generation pixels (2× the
|
|
4164
|
+
* frame), the resolved theme's palette/mood, and a paste-ready English
|
|
4165
|
+
* `suggested_prompt`. Pure function of `ir` (same input → same output, proven
|
|
4166
|
+
* by `asset-brief.test.ts`'s double-call check) — like `auditDeck`, it never
|
|
4167
|
+
* mutates its argument and never touches the filesystem or network.
|
|
4168
|
+
*
|
|
4169
|
+
* v1 scope (asset-brief plan 裁定 4): only `image`-typed components — not
|
|
4170
|
+
* `image_grid`/`image_compare` (separate component types with their own
|
|
4171
|
+
* asset_id arrays), and not `background` asset specs. Both are natural v2
|
|
4172
|
+
* extensions of this same shape and are deliberately left off `AssetBrief`
|
|
4173
|
+
* rather than bolted on half-done.
|
|
4174
|
+
*
|
|
4175
|
+
* Missing-asset handling (裁定 2): every `image` component's `asset_id`,
|
|
4176
|
+
* present or not, gets overridden to the same dummy 1×1 PNG (tagged with a
|
|
4177
|
+
* `#<asset_id>` fragment) in an in-memory copy of `ir` used *only* for this
|
|
4178
|
+
* function's own extraction render pass — `ir` itself, and the real render/
|
|
4179
|
+
* export path, never see this override. `missing` below is decided from the
|
|
4180
|
+
* real `ir.assets.images` (before the override), so it still accurately
|
|
4181
|
+
* reports "nothing usable was ever supplied here" even though the
|
|
4182
|
+
* extraction render always has *something* to draw. Overriding every
|
|
4183
|
+
* asset_id uniformly (not just the missing ones) is what makes the fragment
|
|
4184
|
+
* a reliable identifier regardless of whether the real asset was already
|
|
4185
|
+
* resolved — the alternative (leaving resolved assets' real `src` alone)
|
|
4186
|
+
* would have no way to tell two different real images' hrefs apart when a
|
|
4187
|
+
* page has more than one.
|
|
4188
|
+
*
|
|
4189
|
+
* Known limitation: an `asset_id` shared between an `image` component and a
|
|
4190
|
+
* `background` asset spec on the same page would get the same dummy
|
|
4191
|
+
* fragment on both, which could ambiguate which rendered `<image>` this
|
|
4192
|
+
* function attributes to the component — rare in practice (v1 doesn't cover
|
|
4193
|
+
* background geometry at all, see above) and left as a documented gap
|
|
4194
|
+
* rather than engineered around.
|
|
4195
|
+
*
|
|
4196
|
+
* Shared-`asset_id` handling (task reviewer finding, fixed after v1's first
|
|
4197
|
+
* pass): the IR schema places no uniqueness constraint on `asset_id`
|
|
4198
|
+
* (`src/ir/index.ts`) — two different `image` components on the same page
|
|
4199
|
+
* legally reference the same one. Because the override above (deliberately)
|
|
4200
|
+
* maps a shared `asset_id` to one shared dummy href, both occurrences render
|
|
4201
|
+
* an *identical* `<image href>` — the rendered SVG carries no signal left to
|
|
4202
|
+
* tell them apart. (v1's first pass tried anyway: a FIFO queue keyed by
|
|
4203
|
+
* `asset_id`, drained in `slide.components` order under the assumption that
|
|
4204
|
+
* extraction order would match — it doesn't in general, e.g.
|
|
4205
|
+
* `content-image-lead-split.tsx` renders its narrow-column body *before*
|
|
4206
|
+
* its visual-lead column in the JSX it returns, so the queue was backwards
|
|
4207
|
+
* and every frame ended up attributed to the wrong occurrence. Not a fixable
|
|
4208
|
+
* ordering bug: no ordering convention could be relied on across every
|
|
4209
|
+
* layout's own JSX emission order, present and future.) The honest fix:
|
|
4210
|
+
* per page, group `image` components by `asset_id` first. A group of size 1
|
|
4211
|
+
* (the overwhelmingly common case) keeps the exact single-item shape this
|
|
4212
|
+
* function always produced. A group of size >1 abandons per-component
|
|
4213
|
+
* attribution entirely — it emits one item per *real rendered frame* for
|
|
4214
|
+
* that `asset_id` (not per component), each flagged `shared: true` with the
|
|
4215
|
+
* group's `occurrenceCount`, so every real frame is still reported (nothing
|
|
4216
|
+
* silently dropped) without asserting a specific component<->frame pairing
|
|
4217
|
+
* that cannot be known. If fewer frames render than there are occurrences
|
|
4218
|
+
* (e.g. the layout dropped one), the shortfall is padded with `rendered:
|
|
4219
|
+
* false` shared items so the count of components sharing the id is still
|
|
4220
|
+
* fully visible to a reader of the brief.
|
|
4221
|
+
*/
|
|
4222
|
+
declare function buildAssetBrief(ir: PptxIR): AssetBrief;
|
|
4223
|
+
|
|
4224
|
+
export { AUDIENCE_VALUES, type AssembleResult, type AssetBrief, type AssetBriefFit, type AssetBriefFrame, type AssetBriefItem, type AssetBriefMood, type AssetBriefPage, type AssetBriefPalette, type Assets, type Audience, type AuditChecks, type AuditDeckOptions, type AuditFinding, type AuditReport, BUILTIN_THEME_IDS, type BackgroundSpec, type BrandConfig, BrandConfigSchema, type BrandThemeFile, BrandThemeFileSchema, COMPONENT_TYPES, type Component, DEFAULT_NARRATIVE, type DeckSpec, DeckSpecSchema, type ExtractBrandThemeOptions, type Meta, NARRATIVE_PRESETS, type NarrativePreset, type NarrativeProfile, PACING_BUDGETS, PACING_VALUES, type Pacing, type PacingBudget, type PageBeat, type PageContent, type PageSpec, PageSpecSchema, type PageSpecType, PptwiseError, type PptxIR, PptxIRSchema, type PptxIRV3, PptxIRV3Schema, SPEC_PAGE_COUNT_RANGE, STRATEGY_DEFINITIONS, STRATEGY_VALUES, type Slide, type SpecValidateResult, type SpecValidationIssue, type Strategy, type StrategyDefinition, type StyleOverride, StyleOverrideSchema, type ThemeDefinition, type ThemeInfo, type ThemeRegistration, ThemeSchema, VERSION, type ValidateResult, type ValidationIssue, assembleDeck, auditDeck, buildAssetBrief, disassembleDeck, extractBrandTheme, formatIssues, formatSpecIssues, generatePptx, getInstalledThemeIds, getThemeDefinition, irJsonSchema, listThemes, migrateDeckPlanToSpec, migrateIrV3ToV4, parseBrandThemeFile, registerBrandThemeFile, registerTheme, renderSlideSvg, resolveNarrative, resolveSpecThemeId, specJsonSchema, styleJsonSchema, validateIr, validateSpec };
|