@segnavia/format 0.37.0 → 0.39.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.
Files changed (66) hide show
  1. package/dist/board-edit.d.ts +2 -1
  2. package/dist/board-geometry.d.ts +2 -1
  3. package/dist/board-section-grid.d.ts +2 -1
  4. package/dist/board-sections.d.ts +2 -1
  5. package/dist/board.d.ts +8 -8
  6. package/dist/board.js +15 -11
  7. package/dist/book-exports.d.ts +4 -0
  8. package/dist/book-section.d.ts +225 -3
  9. package/dist/book-section.js +82 -17
  10. package/dist/book.d.ts +878 -416
  11. package/dist/book.js +236 -37
  12. package/dist/cover.d.ts +337 -0
  13. package/dist/cover.js +100 -0
  14. package/dist/deck-from-slides.d.ts +23 -4
  15. package/dist/deck.d.ts +144 -42
  16. package/dist/deck.js +22 -24
  17. package/dist/dependency-policy.d.ts +12 -0
  18. package/dist/dependency-policy.js +42 -0
  19. package/dist/direction.d.ts +1 -1
  20. package/dist/font-collection.d.ts +8 -0
  21. package/dist/font-collection.js +191 -0
  22. package/dist/font-face.d.ts +8 -0
  23. package/dist/font-face.js +24 -0
  24. package/dist/font-refusal.d.ts +5 -0
  25. package/dist/font-refusal.js +9 -0
  26. package/dist/font-signature.d.ts +5 -0
  27. package/dist/font-signature.js +13 -0
  28. package/dist/fonts.d.ts +6 -1
  29. package/dist/fonts.js +3 -1
  30. package/dist/geometry.d.ts +20 -0
  31. package/dist/geometry.js +18 -0
  32. package/dist/image-fit.d.ts +10 -0
  33. package/dist/image-fit.js +10 -0
  34. package/dist/imposition-marks.d.ts +1 -1
  35. package/dist/imposition-schema.d.ts +185 -0
  36. package/dist/imposition-schema.js +122 -0
  37. package/dist/imposition.d.ts +8 -6
  38. package/dist/index.d.ts +29 -1797
  39. package/dist/index.js +30 -210
  40. package/dist/json-schemas.d.ts +1860 -0
  41. package/dist/json-schemas.js +43 -0
  42. package/dist/local-font-limits.d.ts +15 -0
  43. package/dist/local-font-limits.js +24 -0
  44. package/dist/media.d.ts +152 -0
  45. package/dist/media.js +119 -0
  46. package/dist/note-series.d.ts +70 -0
  47. package/dist/note-series.js +153 -0
  48. package/dist/page.d.ts +174 -0
  49. package/dist/page.js +37 -0
  50. package/dist/paper.d.ts +2 -1
  51. package/dist/paper.js +2 -1
  52. package/dist/placement-cycle.d.ts +5 -0
  53. package/dist/placement-cycle.js +30 -0
  54. package/dist/placement-refusal.d.ts +5 -0
  55. package/dist/placement-refusal.js +6 -0
  56. package/dist/placement.d.ts +76 -0
  57. package/dist/placement.js +100 -0
  58. package/dist/print.d.ts +72 -0
  59. package/dist/print.js +38 -0
  60. package/dist/printed-page-imposition.d.ts +2 -1
  61. package/dist/printed-pages.d.ts +14 -0
  62. package/dist/printed-pages.js +14 -1
  63. package/dist/shots-used.d.ts +0 -1
  64. package/dist/shots-used.js +2 -2
  65. package/dist/slots.d.ts +13 -13
  66. package/package.json +1 -1
package/dist/cover.js ADDED
@@ -0,0 +1,100 @@
1
+ import { sheetMm } from "./paper.js";
2
+ import { Print } from "./print.js";
3
+ import { Page } from "./page.js";
4
+ import { z } from "zod";
5
+ //#region src/cover.ts
6
+ const COVER_SHEET = {
7
+ width: 160,
8
+ height: 100
9
+ };
10
+ const COVER_DRAWING_VERSION = 1;
11
+ const COVER_PRINT = {
12
+ paper: {
13
+ width: COVER_SHEET.width,
14
+ height: COVER_SHEET.height,
15
+ unit: "mm"
16
+ },
17
+ orientation: "landscape"
18
+ };
19
+ const Cover = z.object({
20
+ page: Page,
21
+ id: z.string().optional(),
22
+ name: z.string().optional()
23
+ }).transform((cover) => ({
24
+ ...cover,
25
+ page: {
26
+ ...cover.page,
27
+ print: cover.page.print ?? Print.parse(COVER_PRINT)
28
+ }
29
+ })).superRefine((cover, ctx) => {
30
+ const print = cover.page.print;
31
+ if (print.bleed !== 0) ctx.addIssue({
32
+ code: "custom",
33
+ path: [
34
+ "page",
35
+ "print",
36
+ "bleed"
37
+ ],
38
+ message: "page.print.bleed must be 0; remove bleed from the cover"
39
+ });
40
+ if (print.safe !== 0) ctx.addIssue({
41
+ code: "custom",
42
+ path: [
43
+ "page",
44
+ "print",
45
+ "safe"
46
+ ],
47
+ message: "page.print.safe must be 0; remove the safe area from the cover"
48
+ });
49
+ if (print.marks) ctx.addIssue({
50
+ code: "custom",
51
+ path: [
52
+ "page",
53
+ "print",
54
+ "marks"
55
+ ],
56
+ message: "page.print.marks must be false; remove marks from the cover"
57
+ });
58
+ if (cover.page.scripts !== "refuse") ctx.addIssue({
59
+ code: "custom",
60
+ path: ["page", "scripts"],
61
+ message: "page.scripts must be 'refuse'; refuse scripts on the cover"
62
+ });
63
+ });
64
+ function canonicalValue(value) {
65
+ if (Array.isArray(value)) return value.filter((item) => item !== void 0).map(canonicalValue);
66
+ if (value === null || typeof value !== "object") return value;
67
+ return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== void 0).sort(([left], [right]) => compareText(left, right)).map(([key, entry]) => [key, canonicalValue(entry)]));
68
+ }
69
+ function compareText(left, right) {
70
+ return left < right ? -1 : left > right ? 1 : 0;
71
+ }
72
+ function canonicalJson(value) {
73
+ return JSON.stringify(canonicalValue(value));
74
+ }
75
+ function orderedMotifs(motifs) {
76
+ return [...motifs].sort((left, right) => compareText(left.key, right.key) || compareText(left.revision, right.revision) || compareText(canonicalJson(left), canonicalJson(right)));
77
+ }
78
+ async function digestCoverMaterial(material) {
79
+ const { id: _pageId, ...page } = material.page;
80
+ const canonical = canonicalJson({
81
+ ...material,
82
+ page,
83
+ fonts: [...material.fonts].sort(),
84
+ motifs: orderedMotifs(material.motifs)
85
+ });
86
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(canonical));
87
+ return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
88
+ }
89
+ function coverDigest(cover, inputs) {
90
+ return digestCoverMaterial({
91
+ page: cover.page,
92
+ sheet: sheetMm(cover.page.print),
93
+ drawingVersion: 1,
94
+ stamp: inputs.stamp,
95
+ fonts: inputs.fonts ?? [],
96
+ motifs: inputs.motifs ?? []
97
+ });
98
+ }
99
+ //#endregion
100
+ export { COVER_DRAWING_VERSION, COVER_SHEET, Cover, coverDigest, digestCoverMaterial };
@@ -88,6 +88,25 @@ export declare function deckFromSlides(rows: SlideRow[], options: DeckFromSlides
88
88
  alt: string;
89
89
  fit?: "width" | "contain" | "cover" | "focus" | undefined;
90
90
  frame?: boolean | undefined;
91
+ } | {
92
+ media: {
93
+ kind: "deck" | "page" | "paper" | "book" | "media" | "shot";
94
+ address: string;
95
+ page?: string | number | undefined;
96
+ box?: "media" | "bleed" | "crop" | "trim" | "art" | undefined;
97
+ crop?: {
98
+ top?: string | undefined;
99
+ right?: string | undefined;
100
+ bottom?: string | undefined;
101
+ left?: string | undefined;
102
+ } | undefined;
103
+ fit?: "width" | "contain" | "cover" | "focus" | undefined;
104
+ alt?: {
105
+ text: string;
106
+ lang?: string | undefined;
107
+ dir?: "auto" | "ltr" | "rtl" | undefined;
108
+ } | undefined;
109
+ };
91
110
  };
92
111
  notes?: string | undefined;
93
112
  narration?: {
@@ -106,7 +125,7 @@ export declare function deckFromSlides(rows: SlideRow[], options: DeckFromSlides
106
125
  untilWord?: number | undefined;
107
126
  }[];
108
127
  lang?: string | undefined;
109
- dir?: "ltr" | "rtl" | "auto" | undefined;
128
+ dir?: "auto" | "ltr" | "rtl" | undefined;
110
129
  voice?: string | undefined;
111
130
  } | undefined;
112
131
  beforeMs?: number | undefined;
@@ -114,18 +133,18 @@ export declare function deckFromSlides(rows: SlideRow[], options: DeckFromSlides
114
133
  holdMs?: number | undefined;
115
134
  printAtMs?: number | undefined;
116
135
  }[];
117
- dir?: "ltr" | "rtl" | "auto" | undefined;
136
+ dir?: "auto" | "ltr" | "rtl" | undefined;
118
137
  lang?: string | undefined;
119
138
  transition?: {
120
139
  kind: "none" | "fade" | "slide";
121
140
  duration: number;
122
141
  } | undefined;
123
- playback?: "continuous" | "segmented" | undefined;
142
+ playback?: "segmented" | "continuous" | undefined;
124
143
  captions?: "on" | "off" | "viewer" | undefined;
125
144
  slots?: {
126
145
  key: string;
127
146
  label: string;
128
- type: "text" | "phone" | "email" | "link" | "qr" | "image";
147
+ type: "text" | "image" | "phone" | "email" | "link" | "qr";
129
148
  required: boolean;
130
149
  overflow: "refuse" | "shrink" | "truncate" | "wrap";
131
150
  placeholder?: string | undefined;
package/dist/deck.d.ts CHANGED
@@ -1,29 +1,7 @@
1
+ import { Box, Point, Size } from "./geometry.js";
2
+ import { ImageFit } from "./image-fit.js";
1
3
  import { z } from "zod";
2
4
  //#region src/deck.d.ts
3
- export declare const Size: z.ZodObject<{
4
- width: z.ZodNumber;
5
- height: z.ZodNumber;
6
- }, z.core.$strip>;
7
- export type Size = z.infer<typeof Size>;
8
- export declare const Box: z.ZodObject<{
9
- x: z.ZodNumber;
10
- y: z.ZodNumber;
11
- width: z.ZodNumber;
12
- height: z.ZodNumber;
13
- }, z.core.$strip>;
14
- export type Box = z.infer<typeof Box>;
15
- export declare const Point: z.ZodObject<{
16
- x: z.ZodNumber;
17
- y: z.ZodNumber;
18
- }, z.core.$strip>;
19
- export type Point = z.infer<typeof Point>;
20
- export declare const ImageFit: z.ZodEnum<{
21
- width: "width";
22
- contain: "contain";
23
- cover: "cover";
24
- focus: "focus";
25
- }>;
26
- export type ImageFit = z.infer<typeof ImageFit>;
27
5
  export declare const Annotation: z.ZodObject<{
28
6
  ring: z.ZodNullable<z.ZodObject<{
29
7
  x: z.ZodNumber;
@@ -163,9 +141,9 @@ export declare const Narration: z.ZodObject<{
163
141
  text: z.ZodString;
164
142
  lang: z.ZodOptional<z.ZodString>;
165
143
  dir: z.ZodOptional<z.ZodEnum<{
144
+ auto: "auto";
166
145
  ltr: "ltr";
167
146
  rtl: "rtl";
168
- auto: "auto";
169
147
  }>>;
170
148
  voice: z.ZodOptional<z.ZodString>;
171
149
  words: z.ZodArray<z.ZodObject<{
@@ -183,7 +161,7 @@ export declare const Narration: z.ZodObject<{
183
161
  }, z.core.$strip>>>;
184
162
  }, z.core.$strip>;
185
163
  export type Narration = z.infer<typeof Narration>;
186
- export declare const SlideContent: z.ZodDiscriminatedUnion<[z.ZodObject<{
164
+ export declare const SlideContent: z.ZodUnion<readonly [z.ZodDiscriminatedUnion<[z.ZodObject<{
187
165
  kind: z.ZodLiteral<"html">;
188
166
  html: z.ZodString;
189
167
  }, z.core.$strip>, z.ZodObject<{
@@ -265,11 +243,52 @@ export declare const SlideContent: z.ZodDiscriminatedUnion<[z.ZodObject<{
265
243
  focus: "focus";
266
244
  }>>;
267
245
  frame: z.ZodOptional<z.ZodBoolean>;
268
- }, z.core.$strip>], "kind">;
246
+ }, z.core.$strip>], "kind">, z.ZodObject<{
247
+ media: z.ZodObject<{
248
+ kind: z.ZodEnum<{
249
+ deck: "deck";
250
+ page: "page";
251
+ paper: "paper";
252
+ book: "book";
253
+ media: "media";
254
+ shot: "shot";
255
+ }>;
256
+ address: z.ZodString;
257
+ page: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
258
+ box: z.ZodOptional<z.ZodEnum<{
259
+ media: "media";
260
+ bleed: "bleed";
261
+ crop: "crop";
262
+ trim: "trim";
263
+ art: "art";
264
+ }>>;
265
+ crop: z.ZodOptional<z.ZodObject<{
266
+ top: z.ZodOptional<z.ZodString>;
267
+ right: z.ZodOptional<z.ZodString>;
268
+ bottom: z.ZodOptional<z.ZodString>;
269
+ left: z.ZodOptional<z.ZodString>;
270
+ }, z.core.$strip>>;
271
+ fit: z.ZodOptional<z.ZodEnum<{
272
+ width: "width";
273
+ contain: "contain";
274
+ cover: "cover";
275
+ focus: "focus";
276
+ }>>;
277
+ alt: z.ZodOptional<z.ZodObject<{
278
+ text: z.ZodString;
279
+ lang: z.ZodOptional<z.ZodString>;
280
+ dir: z.ZodOptional<z.ZodEnum<{
281
+ auto: "auto";
282
+ ltr: "ltr";
283
+ rtl: "rtl";
284
+ }>>;
285
+ }, z.core.$strip>>;
286
+ }, z.core.$strip>;
287
+ }, z.core.$strip>]>;
269
288
  export type SlideContent = z.infer<typeof SlideContent>;
270
289
  export declare const Slide: z.ZodObject<{
271
290
  id: z.ZodString;
272
- content: z.ZodDiscriminatedUnion<[z.ZodObject<{
291
+ content: z.ZodUnion<readonly [z.ZodDiscriminatedUnion<[z.ZodObject<{
273
292
  kind: z.ZodLiteral<"html">;
274
293
  html: z.ZodString;
275
294
  }, z.core.$strip>, z.ZodObject<{
@@ -351,15 +370,56 @@ export declare const Slide: z.ZodObject<{
351
370
  focus: "focus";
352
371
  }>>;
353
372
  frame: z.ZodOptional<z.ZodBoolean>;
354
- }, z.core.$strip>], "kind">;
373
+ }, z.core.$strip>], "kind">, z.ZodObject<{
374
+ media: z.ZodObject<{
375
+ kind: z.ZodEnum<{
376
+ deck: "deck";
377
+ page: "page";
378
+ paper: "paper";
379
+ book: "book";
380
+ media: "media";
381
+ shot: "shot";
382
+ }>;
383
+ address: z.ZodString;
384
+ page: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
385
+ box: z.ZodOptional<z.ZodEnum<{
386
+ media: "media";
387
+ bleed: "bleed";
388
+ crop: "crop";
389
+ trim: "trim";
390
+ art: "art";
391
+ }>>;
392
+ crop: z.ZodOptional<z.ZodObject<{
393
+ top: z.ZodOptional<z.ZodString>;
394
+ right: z.ZodOptional<z.ZodString>;
395
+ bottom: z.ZodOptional<z.ZodString>;
396
+ left: z.ZodOptional<z.ZodString>;
397
+ }, z.core.$strip>>;
398
+ fit: z.ZodOptional<z.ZodEnum<{
399
+ width: "width";
400
+ contain: "contain";
401
+ cover: "cover";
402
+ focus: "focus";
403
+ }>>;
404
+ alt: z.ZodOptional<z.ZodObject<{
405
+ text: z.ZodString;
406
+ lang: z.ZodOptional<z.ZodString>;
407
+ dir: z.ZodOptional<z.ZodEnum<{
408
+ auto: "auto";
409
+ ltr: "ltr";
410
+ rtl: "rtl";
411
+ }>>;
412
+ }, z.core.$strip>>;
413
+ }, z.core.$strip>;
414
+ }, z.core.$strip>]>;
355
415
  notes: z.ZodOptional<z.ZodString>;
356
416
  narration: z.ZodOptional<z.ZodObject<{
357
417
  text: z.ZodString;
358
418
  lang: z.ZodOptional<z.ZodString>;
359
419
  dir: z.ZodOptional<z.ZodEnum<{
420
+ auto: "auto";
360
421
  ltr: "ltr";
361
422
  rtl: "rtl";
362
- auto: "auto";
363
423
  }>>;
364
424
  voice: z.ZodOptional<z.ZodString>;
365
425
  words: z.ZodArray<z.ZodObject<{
@@ -389,9 +449,9 @@ export declare const DECK_SIZE: {
389
449
  export declare const PLAYBACK_MODES: readonly ["segmented", "continuous"];
390
450
  export type PlaybackMode = (typeof PLAYBACK_MODES)[number];
391
451
  export declare const Playback: z.ZodUnion<readonly [z.ZodEnum<{
392
- continuous: "continuous";
393
452
  segmented: "segmented";
394
- }>, z.ZodPipe<z.ZodLiteral<"step">, z.ZodTransform<"continuous" | "segmented", "step">>]>;
453
+ continuous: "continuous";
454
+ }>, z.ZodPipe<z.ZodLiteral<"step">, z.ZodTransform<"segmented" | "continuous", "step">>]>;
395
455
  export declare function parsePlayback(value: unknown): PlaybackMode | undefined;
396
456
  export declare function annotationCueIssues(narration: Slide['narration'], annotations: number): string[];
397
457
  export declare const Deck: z.ZodObject<{
@@ -416,9 +476,9 @@ export declare const Deck: z.ZodObject<{
416
476
  sandboxed: "sandboxed";
417
477
  }>>;
418
478
  dir: z.ZodOptional<z.ZodEnum<{
479
+ auto: "auto";
419
480
  ltr: "ltr";
420
481
  rtl: "rtl";
421
- auto: "auto";
422
482
  }>>;
423
483
  lang: z.ZodOptional<z.ZodString>;
424
484
  transition: z.ZodOptional<z.ZodObject<{
@@ -430,9 +490,9 @@ export declare const Deck: z.ZodObject<{
430
490
  duration: z.ZodDefault<z.ZodNumber>;
431
491
  }, z.core.$strip>>;
432
492
  playback: z.ZodOptional<z.ZodUnion<readonly [z.ZodEnum<{
433
- continuous: "continuous";
434
493
  segmented: "segmented";
435
- }>, z.ZodPipe<z.ZodLiteral<"step">, z.ZodTransform<"continuous" | "segmented", "step">>]>>;
494
+ continuous: "continuous";
495
+ }>, z.ZodPipe<z.ZodLiteral<"step">, z.ZodTransform<"segmented" | "continuous", "step">>]>>;
436
496
  captions: z.ZodOptional<z.ZodEnum<{
437
497
  on: "on";
438
498
  off: "off";
@@ -443,11 +503,11 @@ export declare const Deck: z.ZodObject<{
443
503
  label: z.ZodString;
444
504
  type: z.ZodEnum<{
445
505
  text: "text";
506
+ image: "image";
446
507
  phone: "phone";
447
508
  email: "email";
448
509
  link: "link";
449
510
  qr: "qr";
450
- image: "image";
451
511
  }>;
452
512
  required: z.ZodDefault<z.ZodBoolean>;
453
513
  placeholder: z.ZodOptional<z.ZodString>;
@@ -461,7 +521,7 @@ export declare const Deck: z.ZodObject<{
461
521
  }, z.core.$strip>, z.ZodTransform<{
462
522
  key: string;
463
523
  label: string;
464
- type: "text" | "phone" | "email" | "link" | "qr" | "image";
524
+ type: "text" | "image" | "phone" | "email" | "link" | "qr";
465
525
  required: boolean;
466
526
  overflow: "refuse" | "shrink" | "truncate" | "wrap";
467
527
  placeholder?: string | undefined;
@@ -469,7 +529,7 @@ export declare const Deck: z.ZodObject<{
469
529
  }, {
470
530
  key: string;
471
531
  label: string;
472
- type: "text" | "phone" | "email" | "link" | "qr" | "image";
532
+ type: "text" | "image" | "phone" | "email" | "link" | "qr";
473
533
  required: boolean;
474
534
  overflow: "refuse" | "shrink" | "truncate" | "wrap";
475
535
  placeholder?: string | undefined;
@@ -477,7 +537,7 @@ export declare const Deck: z.ZodObject<{
477
537
  }>>>>;
478
538
  slides: z.ZodArray<z.ZodObject<{
479
539
  id: z.ZodString;
480
- content: z.ZodDiscriminatedUnion<[z.ZodObject<{
540
+ content: z.ZodUnion<readonly [z.ZodDiscriminatedUnion<[z.ZodObject<{
481
541
  kind: z.ZodLiteral<"html">;
482
542
  html: z.ZodString;
483
543
  }, z.core.$strip>, z.ZodObject<{
@@ -559,15 +619,56 @@ export declare const Deck: z.ZodObject<{
559
619
  focus: "focus";
560
620
  }>>;
561
621
  frame: z.ZodOptional<z.ZodBoolean>;
562
- }, z.core.$strip>], "kind">;
622
+ }, z.core.$strip>], "kind">, z.ZodObject<{
623
+ media: z.ZodObject<{
624
+ kind: z.ZodEnum<{
625
+ deck: "deck";
626
+ page: "page";
627
+ paper: "paper";
628
+ book: "book";
629
+ media: "media";
630
+ shot: "shot";
631
+ }>;
632
+ address: z.ZodString;
633
+ page: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
634
+ box: z.ZodOptional<z.ZodEnum<{
635
+ media: "media";
636
+ bleed: "bleed";
637
+ crop: "crop";
638
+ trim: "trim";
639
+ art: "art";
640
+ }>>;
641
+ crop: z.ZodOptional<z.ZodObject<{
642
+ top: z.ZodOptional<z.ZodString>;
643
+ right: z.ZodOptional<z.ZodString>;
644
+ bottom: z.ZodOptional<z.ZodString>;
645
+ left: z.ZodOptional<z.ZodString>;
646
+ }, z.core.$strip>>;
647
+ fit: z.ZodOptional<z.ZodEnum<{
648
+ width: "width";
649
+ contain: "contain";
650
+ cover: "cover";
651
+ focus: "focus";
652
+ }>>;
653
+ alt: z.ZodOptional<z.ZodObject<{
654
+ text: z.ZodString;
655
+ lang: z.ZodOptional<z.ZodString>;
656
+ dir: z.ZodOptional<z.ZodEnum<{
657
+ auto: "auto";
658
+ ltr: "ltr";
659
+ rtl: "rtl";
660
+ }>>;
661
+ }, z.core.$strip>>;
662
+ }, z.core.$strip>;
663
+ }, z.core.$strip>]>;
563
664
  notes: z.ZodOptional<z.ZodString>;
564
665
  narration: z.ZodOptional<z.ZodObject<{
565
666
  text: z.ZodString;
566
667
  lang: z.ZodOptional<z.ZodString>;
567
668
  dir: z.ZodOptional<z.ZodEnum<{
669
+ auto: "auto";
568
670
  ltr: "ltr";
569
671
  rtl: "rtl";
570
- auto: "auto";
571
672
  }>>;
572
673
  voice: z.ZodOptional<z.ZodString>;
573
674
  words: z.ZodArray<z.ZodObject<{
@@ -647,4 +748,5 @@ export interface DeckLimits {
647
748
  maxNotesBytes?: number;
648
749
  }
649
750
  export declare function exceedsLimits(deck: Deck, limits: DeckLimits): string[];
650
- //#endregion
751
+ //#endregion
752
+ export { Box, ImageFit, Point, Size };
package/dist/deck.js CHANGED
@@ -1,30 +1,13 @@
1
1
  import { Direction } from "./direction.js";
2
+ import { Box, Point, Size } from "./geometry.js";
3
+ import { ImageFit } from "./image-fit.js";
4
+ import { Placement, PlacementShape } from "./placement.js";
2
5
  import { Scripts } from "./scripts.js";
3
6
  import { Slots } from "./slots.js";
4
7
  import { SlideTiming, slideTimingIssues } from "./timing.js";
5
8
  import { Transition } from "./transition.js";
6
9
  import { z } from "zod";
7
10
  //#region src/deck.ts
8
- const Size = z.object({
9
- width: z.number().int().positive(),
10
- height: z.number().int().positive()
11
- });
12
- const Box = z.object({
13
- x: z.number(),
14
- y: z.number(),
15
- width: z.number(),
16
- height: z.number()
17
- });
18
- const Point = z.object({
19
- x: z.number(),
20
- y: z.number()
21
- });
22
- const ImageFit = z.enum([
23
- "contain",
24
- "cover",
25
- "width",
26
- "focus"
27
- ]);
28
11
  const Annotation = z.object({
29
12
  ring: Box.nullable(),
30
13
  badge: z.object({
@@ -77,7 +60,7 @@ const Narration = z.object({
77
60
  live: z.boolean().default(false),
78
61
  cues: z.array(Cue).default([])
79
62
  });
80
- const SlideContent = z.discriminatedUnion("kind", [
63
+ const DirectSlideContent = z.discriminatedUnion("kind", [
81
64
  z.object({
82
65
  kind: z.literal("html"),
83
66
  html: z.string()
@@ -107,6 +90,7 @@ const SlideContent = z.discriminatedUnion("kind", [
107
90
  frame: z.boolean().optional()
108
91
  })
109
92
  ]);
93
+ const SlideContent = z.union([DirectSlideContent, z.object({ media: PlacementShape })]);
110
94
  const Slide = z.object({
111
95
  id: z.string(),
112
96
  content: SlideContent,
@@ -153,18 +137,32 @@ function annotationCueIssues(narration, annotations) {
153
137
  function cueIssues(slide) {
154
138
  const narration = slide.narration;
155
139
  if (!narration) return [];
156
- const annotations = slide.content.kind === "shot" ? slide.content.shot.annotations.length : null;
140
+ const annotations = "kind" in slide.content && slide.content.kind === "shot" ? slide.content.shot.annotations.length : null;
157
141
  const words = narration.live ? null : narration.words.length;
158
142
  const issues = [];
159
143
  for (const cue of narration.cues) {
160
144
  for (const word of [cue.word, cue.untilWord]) if (word !== void 0 && words !== null && word >= words) issues.push(`a cue names word ${word}, but the narration has ${words} words`);
161
- if (slide.content.kind !== "shot" && slide.content.kind !== "shot-ref") issues.push("a cue names an annotation, but only a shot carries annotations");
145
+ if (!("kind" in slide.content) || slide.content.kind !== "shot" && slide.content.kind !== "shot-ref") issues.push("a cue names an annotation, but only a shot carries annotations");
162
146
  }
163
147
  if (annotations !== null) issues.push(...annotationCueIssues(narration, annotations));
164
148
  return issues;
165
149
  }
166
150
  const Deck = DeckShape.superRefine((deck, ctx) => {
167
151
  deck.slides.forEach((slide, index) => {
152
+ if ("media" in slide.content) try {
153
+ Placement.parse(slide.content.media, "deck");
154
+ } catch (error) {
155
+ ctx.addIssue({
156
+ code: "custom",
157
+ path: [
158
+ "slides",
159
+ index,
160
+ "content",
161
+ "media"
162
+ ],
163
+ message: error instanceof Error ? error.message : String(error)
164
+ });
165
+ }
168
166
  for (const message of cueIssues(slide)) ctx.addIssue({
169
167
  code: "custom",
170
168
  path: [
@@ -211,7 +209,7 @@ function exceedsLimits(deck, limits) {
211
209
  const bytes = (text) => new TextEncoder().encode(text).length;
212
210
  if (limits.maxSlides !== void 0 && deck.slides.length > limits.maxSlides) reasons.push(`the deck has ${deck.slides.length} slides; the limit is ${limits.maxSlides}`);
213
211
  deck.slides.forEach((slide, index) => {
214
- if (limits.maxSlideBytes !== void 0 && slide.content.kind === "html" && bytes(slide.content.html) > limits.maxSlideBytes) reasons.push(`slide ${index + 1} is ${bytes(slide.content.html)} bytes; the limit is ${limits.maxSlideBytes}`);
212
+ if (limits.maxSlideBytes !== void 0 && "kind" in slide.content && slide.content.kind === "html" && bytes(slide.content.html) > limits.maxSlideBytes) reasons.push(`slide ${index + 1} is ${bytes(slide.content.html)} bytes; the limit is ${limits.maxSlideBytes}`);
215
213
  if (limits.maxNotesBytes !== void 0 && slide.notes && bytes(slide.notes) > limits.maxNotesBytes) reasons.push(`slide ${index + 1} has ${bytes(slide.notes)} bytes of notes; the limit is ${limits.maxNotesBytes}`);
216
214
  });
217
215
  return reasons;
@@ -0,0 +1,12 @@
1
+ //#region src/dependency-policy.d.ts
2
+ export type DependencyDecision = {
3
+ allowed: true;
4
+ origin: string;
5
+ } | {
6
+ allowed: false;
7
+ reason: string;
8
+ };
9
+ export declare function originSet(values: Iterable<string> | undefined, bare?: boolean): Set<string>;
10
+ export declare const dependencyOriginSet: (values: Iterable<string> | undefined) => Set<string>;
11
+ export declare function dependencyDecision(value: string, approved: ReadonlySet<string>): DependencyDecision;
12
+ //#endregion
@@ -0,0 +1,42 @@
1
+ //#region src/dependency-policy.ts
2
+ const PACKAGE_PATHS = {
3
+ "https://cdn.jsdelivr.net": /^\/npm\/(?:@[^/]+\/)?[^/@]+@(\d+\.\d+\.\d+)(?:\/|$)/,
4
+ "https://unpkg.com": /^\/(?:@[^/]+\/)?[^/@]+@(\d+\.\d+\.\d+)(?:\/|$)/,
5
+ "https://cdnjs.cloudflare.com": /^\/ajax\/libs\/[^/]+\/(\d+\.\d+\.\d+)(?:\/|$)/
6
+ };
7
+ function originSet(values, bare = false) {
8
+ const result = /* @__PURE__ */ new Set();
9
+ for (const value of values ?? []) try {
10
+ const url = new URL(value);
11
+ if (url.protocol === "https:" && (!bare || url.pathname === "/" && !url.search && !url.hash)) result.add(url.origin.toLowerCase());
12
+ } catch {}
13
+ return result;
14
+ }
15
+ const dependencyOriginSet = (values) => originSet(values, true);
16
+ function dependencyDecision(value, approved) {
17
+ let url;
18
+ try {
19
+ url = new URL(value);
20
+ } catch {
21
+ return {
22
+ allowed: false,
23
+ reason: `${JSON.stringify(value)} is not an absolute https URL; an absolute URL at an approved origin clears this refusal`
24
+ };
25
+ }
26
+ const origin = url.origin.toLowerCase();
27
+ if (url.protocol !== "https:" || !approved.has(origin)) return {
28
+ allowed: false,
29
+ reason: `${url.href} is not at an approved dependency origin; add ${origin} to dependencyOrigins to clear this refusal`
30
+ };
31
+ const shape = PACKAGE_PATHS[origin];
32
+ if (shape && !shape.test(url.pathname)) return {
33
+ allowed: false,
34
+ reason: `${url.href} does not name an exact x.y.z package version; use an exact version to clear this refusal`
35
+ };
36
+ return {
37
+ allowed: true,
38
+ origin
39
+ };
40
+ }
41
+ //#endregion
42
+ export { dependencyDecision, dependencyOriginSet, originSet };
@@ -1,9 +1,9 @@
1
1
  import { z } from "zod";
2
2
  //#region src/direction.d.ts
3
3
  export declare const Direction: z.ZodEnum<{
4
+ auto: "auto";
4
5
  ltr: "ltr";
5
6
  rtl: "rtl";
6
- auto: "auto";
7
7
  }>;
8
8
  export declare const TextDirection: z.ZodEnum<{
9
9
  ltr: "ltr";
@@ -0,0 +1,8 @@
1
+ //#region src/font-collection.d.ts
2
+ export type ExtractedFontFace = {
3
+ data: Uint8Array;
4
+ format: 'truetype' | 'opentype';
5
+ };
6
+ export declare function collectionFaces(bytes: Uint8Array): string[];
7
+ export declare function extractFace(bytes: Uint8Array, postscriptName: string): ExtractedFontFace;
8
+ //#endregion