@liustack/pptfast 0.8.0 → 0.11.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.
@@ -1,11 +1,44 @@
1
1
  import { z } from 'zod';
2
2
 
3
- declare const VERSION = "0.8.0";
3
+ declare const VERSION = "0.11.0";
4
4
 
5
5
  /** Error class thrown by pptfast's public API surface (validation, rendering, export). */
6
6
  declare class PptfastError extends Error {
7
7
  }
8
8
 
9
+ /**
10
+ * The v4 IR schema root: theme/meta/assets/brand/background/slide/narrative
11
+ * and the top-level `PptxIRSchema` a deck document parses against
12
+ * (`parsePptxIR`). The frozen v3 shape lives in `./legacy-v3.ts`, kept only
13
+ * for `migrateIrV3ToV4`'s input parsing (spec §9.3).
14
+ *
15
+ * **The `ComponentSchema` union below is a pure aggregator (src domain reorg
16
+ * wave 2, spec §4.3), same discipline as `src/svg/layouts/registry.ts`'s T1d
17
+ * precedent.** Every one of the 32 component schemas used to live here as a
18
+ * literal `z.object({...})` entry directly inside the `discriminatedUnion`
19
+ * array. Each now lives in its own `src/ir/components/<name>.ts` domain file
20
+ * instead (schema + field aliases + render-trait declaration together, spec
21
+ * §4.1) — imported below and referenced by name, in the exact union position
22
+ * its literal used to occupy, so "take one component away whole" is a
23
+ * single-file operation instead of an edit split across this file,
24
+ * `field-aliases.ts`, and `component-traits.ts`. This file's own job for
25
+ * components is now purely computational: import all 32, construct
26
+ * `ComponentSchema` via `z.discriminatedUnion`, and derive `COMPONENT_TYPES`
27
+ * from the result — never a hand-copied literal, never a re-export relay. A
28
+ * handful of schema fragments genuinely shared by ≥2 components (only the
29
+ * icon-name enum, as of this wave) live in `src/ir/components/shared.ts`
30
+ * instead of any one domain file; every other named sub-schema that reads as
31
+ * "shared" at a glance (e.g. `GanttItemSchema`, `PestQuadrantSchema`,
32
+ * `SankeyNodeSchema`/`SankeyLinkSchema`) turned out to be single-consumer and
33
+ * moved into its own component's domain file with it.
34
+ *
35
+ * The rest of this module — everything outside the `// ── Components` section
36
+ * — is unrelated to the component-domain split and was never in its scope:
37
+ * background/theme/meta/assets/brand/slide/narrative and the top-level
38
+ * `PptxIRSchema` are genuinely this file's own content, not aggregated from
39
+ * elsewhere.
40
+ */
41
+
9
42
  declare const BUILTIN_THEME_IDS: readonly ["consulting", "enterprise", "academic", "insight", "campaign", "bloom", "classroom", "ink", "tech", "runway", "journal", "luxe", "heritage"];
10
43
  declare const BackgroundSpecSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
11
44
  kind: z.ZodLiteral<"color">;
@@ -27,8 +60,8 @@ declare const BackgroundSpecSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
27
60
  opacity: z.ZodNumber;
28
61
  }, z.core.$strict>>;
29
62
  fit: z.ZodOptional<z.ZodEnum<{
30
- cover: "cover";
31
63
  contain: "contain";
64
+ cover: "cover";
32
65
  }>>;
33
66
  }, z.core.$strict>], "kind">;
34
67
  /**
@@ -129,9 +162,9 @@ declare const MetaSchema: z.ZodObject<{
129
162
  animation: z.ZodOptional<z.ZodObject<{
130
163
  transition: z.ZodOptional<z.ZodEnum<{
131
164
  push: "push";
165
+ none: "none";
132
166
  fade: "fade";
133
167
  wipe: "wipe";
134
- none: "none";
135
168
  }>>;
136
169
  elements: z.ZodOptional<z.ZodEnum<{
137
170
  none: "none";
@@ -329,8 +362,8 @@ declare const ComponentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
329
362
  tag: z.ZodOptional<z.ZodString>;
330
363
  tone: z.ZodOptional<z.ZodEnum<{
331
364
  info: "info";
332
- accent: "accent";
333
365
  neutral: "neutral";
366
+ accent: "accent";
334
367
  }>>;
335
368
  }, z.core.$strict>>;
336
369
  }, z.core.$strict>, z.ZodObject<{
@@ -345,9 +378,9 @@ declare const ComponentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
345
378
  type: z.ZodLiteral<"verdict_banner">;
346
379
  text: z.ZodString;
347
380
  tone: z.ZodEnum<{
348
- neutral: "neutral";
349
381
  positive: "positive";
350
382
  warning: "warning";
383
+ neutral: "neutral";
351
384
  }>;
352
385
  icon: z.ZodOptional<z.ZodEnum<{
353
386
  [x: string]: string;
@@ -364,8 +397,8 @@ declare const ComponentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
364
397
  asset_id: z.ZodString;
365
398
  caption: z.ZodOptional<z.ZodString>;
366
399
  fit: z.ZodDefault<z.ZodEnum<{
367
- cover: "cover";
368
400
  contain: "contain";
401
+ cover: "cover";
369
402
  }>>;
370
403
  }, z.core.$strict>, z.ZodObject<{
371
404
  type: z.ZodLiteral<"image_grid">;
@@ -521,30 +554,49 @@ declare const ComponentSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
521
554
  to: z.ZodString;
522
555
  value: z.ZodNumber;
523
556
  }, z.core.$strict>>;
557
+ }, z.core.$strict>, z.ZodObject<{
558
+ type: z.ZodLiteral<"data_table">;
559
+ columns: z.ZodArray<z.ZodObject<{
560
+ key: z.ZodString;
561
+ label: z.ZodString;
562
+ align: z.ZodOptional<z.ZodEnum<{
563
+ left: "left";
564
+ right: "right";
565
+ center: "center";
566
+ }>>;
567
+ }, z.core.$strict>>;
568
+ rows: z.ZodArray<z.ZodObject<{
569
+ cells: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
570
+ emphasis: z.ZodOptional<z.ZodEnum<{
571
+ highlight: "highlight";
572
+ total: "total";
573
+ }>>;
574
+ }, z.core.$strict>>;
575
+ source: z.ZodOptional<z.ZodString>;
524
576
  }, z.core.$strict>], "type">;
525
577
  /**
526
578
  * All 32 component `type` discriminant values, derived from `ComponentSchema`
527
579
  * itself (never hand-copied) so this list can't drift from the union above.
528
580
  * Typed as plain `readonly string[]` rather than `Component["type"][]` —
529
581
  * every consumer of this list (W5's plan `focus` vocabulary gate,
530
- * `src/plan/index.ts`) tests membership of an arbitrary author-supplied
582
+ * `src/spec/index.ts`) tests membership of an arbitrary author-supplied
531
583
  * string, and TS's `Array.includes` is invariant in its element type, so a
532
584
  * narrower literal-union type would reject that call at the caller.
533
585
  */
534
586
  declare const COMPONENT_TYPES: readonly string[];
535
587
  declare const SlideSchema: z.ZodObject<{
536
588
  type: z.ZodDefault<z.ZodEnum<{
589
+ content: "content";
537
590
  cover: "cover";
538
591
  chapter: "chapter";
539
- content: "content";
540
592
  ending: "ending";
541
593
  }>>;
542
594
  id: z.ZodOptional<z.ZodString>;
543
595
  placeholder: z.ZodOptional<z.ZodLiteral<true>>;
544
596
  layout: z.ZodOptional<z.ZodString>;
545
597
  beat: z.ZodOptional<z.ZodEnum<{
546
- anchor: "anchor";
547
598
  dense: "dense";
599
+ anchor: "anchor";
548
600
  breathing: "breathing";
549
601
  }>>;
550
602
  arrangement: z.ZodOptional<z.ZodEnum<{
@@ -743,8 +795,8 @@ declare const SlideSchema: z.ZodObject<{
743
795
  tag: z.ZodOptional<z.ZodString>;
744
796
  tone: z.ZodOptional<z.ZodEnum<{
745
797
  info: "info";
746
- accent: "accent";
747
798
  neutral: "neutral";
799
+ accent: "accent";
748
800
  }>>;
749
801
  }, z.core.$strict>>;
750
802
  }, z.core.$strict>, z.ZodObject<{
@@ -759,9 +811,9 @@ declare const SlideSchema: z.ZodObject<{
759
811
  type: z.ZodLiteral<"verdict_banner">;
760
812
  text: z.ZodString;
761
813
  tone: z.ZodEnum<{
762
- neutral: "neutral";
763
814
  positive: "positive";
764
815
  warning: "warning";
816
+ neutral: "neutral";
765
817
  }>;
766
818
  icon: z.ZodOptional<z.ZodEnum<{
767
819
  [x: string]: string;
@@ -778,8 +830,8 @@ declare const SlideSchema: z.ZodObject<{
778
830
  asset_id: z.ZodString;
779
831
  caption: z.ZodOptional<z.ZodString>;
780
832
  fit: z.ZodDefault<z.ZodEnum<{
781
- cover: "cover";
782
833
  contain: "contain";
834
+ cover: "cover";
783
835
  }>>;
784
836
  }, z.core.$strict>, z.ZodObject<{
785
837
  type: z.ZodLiteral<"image_grid">;
@@ -935,6 +987,25 @@ declare const SlideSchema: z.ZodObject<{
935
987
  to: z.ZodString;
936
988
  value: z.ZodNumber;
937
989
  }, z.core.$strict>>;
990
+ }, z.core.$strict>, z.ZodObject<{
991
+ type: z.ZodLiteral<"data_table">;
992
+ columns: z.ZodArray<z.ZodObject<{
993
+ key: z.ZodString;
994
+ label: z.ZodString;
995
+ align: z.ZodOptional<z.ZodEnum<{
996
+ left: "left";
997
+ right: "right";
998
+ center: "center";
999
+ }>>;
1000
+ }, z.core.$strict>>;
1001
+ rows: z.ZodArray<z.ZodObject<{
1002
+ cells: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
1003
+ emphasis: z.ZodOptional<z.ZodEnum<{
1004
+ highlight: "highlight";
1005
+ total: "total";
1006
+ }>>;
1007
+ }, z.core.$strict>>;
1008
+ source: z.ZodOptional<z.ZodString>;
938
1009
  }, z.core.$strict>], "type">>>;
939
1010
  background: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
940
1011
  kind: z.ZodLiteral<"color">;
@@ -956,8 +1027,8 @@ declare const SlideSchema: z.ZodObject<{
956
1027
  opacity: z.ZodNumber;
957
1028
  }, z.core.$strict>>;
958
1029
  fit: z.ZodOptional<z.ZodEnum<{
959
- cover: "cover";
960
1030
  contain: "contain";
1031
+ cover: "cover";
961
1032
  }>>;
962
1033
  }, z.core.$strict>], "kind">>;
963
1034
  decor: z.ZodOptional<z.ZodObject<{
@@ -1041,9 +1112,9 @@ declare const PptxIRSchema: z.ZodObject<{
1041
1112
  animation: z.ZodOptional<z.ZodObject<{
1042
1113
  transition: z.ZodOptional<z.ZodEnum<{
1043
1114
  push: "push";
1115
+ none: "none";
1044
1116
  fade: "fade";
1045
1117
  wipe: "wipe";
1046
- none: "none";
1047
1118
  }>>;
1048
1119
  elements: z.ZodOptional<z.ZodEnum<{
1049
1120
  none: "none";
@@ -1070,17 +1141,17 @@ declare const PptxIRSchema: z.ZodObject<{
1070
1141
  seed: z.ZodOptional<z.ZodNumber>;
1071
1142
  slides: z.ZodArray<z.ZodObject<{
1072
1143
  type: z.ZodDefault<z.ZodEnum<{
1144
+ content: "content";
1073
1145
  cover: "cover";
1074
1146
  chapter: "chapter";
1075
- content: "content";
1076
1147
  ending: "ending";
1077
1148
  }>>;
1078
1149
  id: z.ZodOptional<z.ZodString>;
1079
1150
  placeholder: z.ZodOptional<z.ZodLiteral<true>>;
1080
1151
  layout: z.ZodOptional<z.ZodString>;
1081
1152
  beat: z.ZodOptional<z.ZodEnum<{
1082
- anchor: "anchor";
1083
1153
  dense: "dense";
1154
+ anchor: "anchor";
1084
1155
  breathing: "breathing";
1085
1156
  }>>;
1086
1157
  arrangement: z.ZodOptional<z.ZodEnum<{
@@ -1279,8 +1350,8 @@ declare const PptxIRSchema: z.ZodObject<{
1279
1350
  tag: z.ZodOptional<z.ZodString>;
1280
1351
  tone: z.ZodOptional<z.ZodEnum<{
1281
1352
  info: "info";
1282
- accent: "accent";
1283
1353
  neutral: "neutral";
1354
+ accent: "accent";
1284
1355
  }>>;
1285
1356
  }, z.core.$strict>>;
1286
1357
  }, z.core.$strict>, z.ZodObject<{
@@ -1295,9 +1366,9 @@ declare const PptxIRSchema: z.ZodObject<{
1295
1366
  type: z.ZodLiteral<"verdict_banner">;
1296
1367
  text: z.ZodString;
1297
1368
  tone: z.ZodEnum<{
1298
- neutral: "neutral";
1299
1369
  positive: "positive";
1300
1370
  warning: "warning";
1371
+ neutral: "neutral";
1301
1372
  }>;
1302
1373
  icon: z.ZodOptional<z.ZodEnum<{
1303
1374
  [x: string]: string;
@@ -1314,8 +1385,8 @@ declare const PptxIRSchema: z.ZodObject<{
1314
1385
  asset_id: z.ZodString;
1315
1386
  caption: z.ZodOptional<z.ZodString>;
1316
1387
  fit: z.ZodDefault<z.ZodEnum<{
1317
- cover: "cover";
1318
1388
  contain: "contain";
1389
+ cover: "cover";
1319
1390
  }>>;
1320
1391
  }, z.core.$strict>, z.ZodObject<{
1321
1392
  type: z.ZodLiteral<"image_grid">;
@@ -1471,6 +1542,25 @@ declare const PptxIRSchema: z.ZodObject<{
1471
1542
  to: z.ZodString;
1472
1543
  value: z.ZodNumber;
1473
1544
  }, z.core.$strict>>;
1545
+ }, z.core.$strict>, z.ZodObject<{
1546
+ type: z.ZodLiteral<"data_table">;
1547
+ columns: z.ZodArray<z.ZodObject<{
1548
+ key: z.ZodString;
1549
+ label: z.ZodString;
1550
+ align: z.ZodOptional<z.ZodEnum<{
1551
+ left: "left";
1552
+ right: "right";
1553
+ center: "center";
1554
+ }>>;
1555
+ }, z.core.$strict>>;
1556
+ rows: z.ZodArray<z.ZodObject<{
1557
+ cells: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
1558
+ emphasis: z.ZodOptional<z.ZodEnum<{
1559
+ highlight: "highlight";
1560
+ total: "total";
1561
+ }>>;
1562
+ }, z.core.$strict>>;
1563
+ source: z.ZodOptional<z.ZodString>;
1474
1564
  }, z.core.$strict>], "type">>>;
1475
1565
  background: z.ZodOptional<z.ZodDiscriminatedUnion<[z.ZodObject<{
1476
1566
  kind: z.ZodLiteral<"color">;
@@ -1492,8 +1582,8 @@ declare const PptxIRSchema: z.ZodObject<{
1492
1582
  opacity: z.ZodNumber;
1493
1583
  }, z.core.$strict>>;
1494
1584
  fit: z.ZodOptional<z.ZodEnum<{
1495
- cover: "cover";
1496
1585
  contain: "contain";
1586
+ cover: "cover";
1497
1587
  }>>;
1498
1588
  }, z.core.$strict>], "kind">>;
1499
1589
  decor: z.ZodOptional<z.ZodObject<{
@@ -1611,18 +1701,32 @@ interface ValidateResult {
1611
1701
  * inherits this unchanged (`if (!v.ok) throw`) — it already only ever
1612
1702
  * blocked on `ok`, never inspected `errors`/`warnings` directly.
1613
1703
  *
1614
- * Before any of that, one deterministic alias pass runs
1615
- * ({@link normalizeComponentAliases}, W5 task 4) for the component
1616
- * field-name synonym rescue only (kpi `title`→`label`, quote
1617
- * `content`→`text`, …) a weak-model rescue for schema-internal synonym
1618
- * drift, scoped to `slides[]`. It only rewrites where the canonical key is
1619
- * absent, so the schema parse below never sees an alias as an "unrecognized
1620
- * key" in the first place. Purely informational: every rewrite is recorded
1621
- * as a human-readable `path: alias canonical` string and threaded onto
1622
- * `ValidateResult.normalized` on *every* return path below via
1623
- * `withNormalized`, success or failure alike — it never itself gates `ok`.
1704
+ * Before any of that, two deterministic pre-parse rewrite passes run, each
1705
+ * threading its rewrite notes onto `ValidateResult.normalized` on *every*
1706
+ * return path below via `withNormalized`, success or failure alike — neither
1707
+ * ever gates `ok` on its own:
1708
+ * - {@link normalizeComponentAliases} (W5 task 4): the component
1709
+ * field-name synonym rescue (kpi `title`→`label`, quote `content`→`text`,
1710
+ * …), scoped to `slides[]`. Only rewrites where the canonical key is
1711
+ * absent, so the schema parse below never sees an alias as an
1712
+ * "unrecognized key" in the first place.
1713
+ * - {@link normalizeNarrativeShape} (`./narrative`, T0b bench-evidence fix
1714
+ * 2 — see its own doc comment for the full rationale): the root-level
1715
+ * `narrative: {id: <preset>}` shape rescue. A model that just wrote
1716
+ * `theme: {id: "consulting"}` a few lines above pattern-matches the same
1717
+ * wrapper shape onto `narrative`; this rewrites it to the bare preset
1718
+ * string `resolveNarrative`'s string branch actually expects. Fires only
1719
+ * when `id` is the object's sole narrative-relevant key (none of
1720
+ * strategy/pacing/audience alongside it) — a mixed shape stays
1721
+ * unrescued, ambiguous, and hard-errors exactly as it did before this
1722
+ * pass existed.
1723
+ *
1724
+ * Both are the same class of fix — a weak-model *synonym* rescue (a name
1725
+ * drift for the component-alias pass, a *shape* drift for the narrative
1726
+ * pass) — which is the actual boundary the next paragraph's "no
1727
+ * old-vocabulary rescue" draws, not "no rewrite ever touches `narrative`."
1624
1728
  *
1625
- * There is deliberately no root/narrative-level alias pass (spec §16,
1729
+ * There is still deliberately no *old-vocabulary* rescue (spec §16,
1626
1730
  * reversing the now-superseded §15.4): a v4 document that still spells its
1627
1731
  * pre-rename vocabulary — `scenario` instead of `narrative`, `mode`/
1628
1732
  * `delivery` instead of `strategy`/`pacing`, or the old enum values
@@ -1632,21 +1736,24 @@ interface ValidateResult {
1632
1736
  * schema's `.strict()` parse below as an unrecognized key, and an old enum
1633
1737
  * value (or the axis-key names `mode`/`delivery` inside `narrative`, which
1634
1738
  * the schema itself leaves open) fails `resolveNarrative`'s own runtime
1635
- * check, listing the current values. `pptfast migrate` (`ir/migrate.ts`)
1636
- * remains the sanctioned bridge for a genuine v3 document — see the v3 hard
1637
- * reject below, which points there. Hard-erroring is not the same as
1638
- * leaving the error message unhelpful, though: the schema-parse branch below
1639
- * appends a rename hint to `scenario` and the rest of the documented v2/v3
1640
- * rename map (`blocks`/`variant`/`theme.override` `./ir/rename-hints.ts`,
1641
- * borrow-wave task 3) whenever the offending key matches one, and a generic
1642
- * "belongs inside components[]" hint for any other slide-level unrecognized
1643
- * key message-layer annotation only, never a second, silent rewrite path
1644
- * alongside {@link normalizeComponentAliases}.
1739
+ * check, listing the current values. `{id: <preset>}` was never a v3
1740
+ * `scenario` shape, so `normalizeNarrativeShape` above does not reopen this
1741
+ * door it rescues a shape weak models invent by analogy to `theme.id`, not
1742
+ * a shape the pre-rename vocabulary ever spoke. `pptfast migrate`
1743
+ * (`ir/migrate.ts`) remains the sanctioned bridge for a genuine v3 document —
1744
+ * see the v3 hard reject below, which points there. Hard-erroring is not the
1745
+ * same as leaving the error message unhelpful, though: the schema-parse
1746
+ * branch below appends a rename hint to `scenario` and the rest of the
1747
+ * documented v2/v3 rename map (`blocks`/`variant`/`theme.override`
1748
+ * `./ir/rename-hints.ts`, borrow-wave task 3) whenever the offending key
1749
+ * matches one, and a generic "belongs inside components[]" hint for any
1750
+ * other slide-level unrecognized key — message-layer annotation only, never
1751
+ * a second, silent rewrite path alongside the two passes above.
1645
1752
  *
1646
- * The component-alias pass only ever runs for a document already headed for
1647
- * the v4 schema — an explicit `version: "2"` or `version: "3"` is
1648
- * hard-rejected first, below, before the alias pass or any schema parse
1649
- * (spec §9.3: a v2/v3 document is never silently reinterpreted as v4).
1753
+ * Both pre-parse passes only ever run for a document already headed for the
1754
+ * v4 schema — an explicit `version: "2"` or `version: "3"` is hard-rejected
1755
+ * first, below, before either pass or any schema parse (spec §9.3: a v2/v3
1756
+ * document is never silently reinterpreted as v4).
1650
1757
  */
1651
1758
  declare function validateIr(input: unknown): ValidateResult;
1652
1759
  /**