@openpresentation/opf 0.10.1 → 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.
Files changed (70) hide show
  1. package/dist/{catalogs-DoVmvDr7.d.ts → catalogs-atkOF4Vy.d.ts} +2 -2
  2. package/dist/catalogs.d.ts +2 -2
  3. package/dist/catalogs.js +1 -1
  4. package/dist/{chunk-TU7I3KSB.js → chunk-6FU2KICU.js} +306 -306
  5. package/dist/{chunk-ZIL7MGZU.js → chunk-CHKJ4QHQ.js} +223 -73
  6. package/dist/{chunk-EWJNRHXA.js → chunk-EQHZ3ZO4.js} +3 -3
  7. package/dist/{chunk-PQJRDNA6.js → chunk-FTWNWFIV.js} +72 -1
  8. package/dist/{chunk-FHGJX5QK.js → chunk-FWA5XB45.js} +33 -12
  9. package/dist/{chunk-D3GQIREP.js → chunk-GN52EE3P.js} +133 -12
  10. package/dist/composition-Tv9Wm3Oh.d.ts +691 -0
  11. package/dist/composition.d.ts +1 -676
  12. package/dist/composition.js +1 -1
  13. package/dist/docs.js +38 -8
  14. package/dist/examples.d.ts +1 -1
  15. package/dist/index.d.ts +65 -4
  16. package/dist/index.js +204 -6
  17. package/dist/lint.d.ts +3 -3
  18. package/dist/lint.js +5 -5
  19. package/dist/pagination.d.ts +2 -2
  20. package/dist/pagination.js +5 -5
  21. package/dist/{presentation-BMTdX6O1.d.ts → presentation-Ct42Mitb.d.ts} +51 -8
  22. package/dist/repo-readme.js +1 -1
  23. package/dist/{schemas-BYe5y8-i.d.ts → schemas-CiVmUT2p.d.ts} +6 -0
  24. package/dist/schemas.d.ts +1 -1
  25. package/dist/schemas.js +1 -1
  26. package/dist/spec/catalogs/narratives/board-meeting.json +21 -21
  27. package/dist/spec/catalogs/narratives/business-narrative.json +8 -8
  28. package/dist/spec/catalogs/narratives/business-review.json +12 -12
  29. package/dist/spec/catalogs/narratives/capacity-planning.json +8 -8
  30. package/dist/spec/catalogs/narratives/challenge-resolution.json +7 -7
  31. package/dist/spec/catalogs/narratives/classic-story.json +7 -7
  32. package/dist/spec/catalogs/narratives/company-intro.json +9 -9
  33. package/dist/spec/catalogs/narratives/conference-talk.json +1 -1
  34. package/dist/spec/catalogs/narratives/early-startup-pitch.json +12 -12
  35. package/dist/spec/catalogs/narratives/educate.json +9 -9
  36. package/dist/spec/catalogs/narratives/employee-review.json +8 -8
  37. package/dist/spec/catalogs/narratives/failure-analysis.json +10 -10
  38. package/dist/spec/catalogs/narratives/focus.json +12 -12
  39. package/dist/spec/catalogs/narratives/golden-circle.json +1 -1
  40. package/dist/spec/catalogs/narratives/innovation.json +9 -9
  41. package/dist/spec/catalogs/narratives/justice.json +11 -11
  42. package/dist/spec/catalogs/narratives/marketing-strategy.json +11 -11
  43. package/dist/spec/catalogs/narratives/performance-improvement-plan.json +8 -8
  44. package/dist/spec/catalogs/narratives/performance-review.json +11 -11
  45. package/dist/spec/catalogs/narratives/persuade.json +7 -7
  46. package/dist/spec/catalogs/narratives/persuasive-sales.json +8 -8
  47. package/dist/spec/catalogs/narratives/pitch-deck.json +3 -3
  48. package/dist/spec/catalogs/narratives/problem-solution.json +2 -2
  49. package/dist/spec/catalogs/narratives/product-launch.json +10 -10
  50. package/dist/spec/catalogs/narratives/project-proposal.json +10 -10
  51. package/dist/spec/catalogs/narratives/qbr.json +3 -3
  52. package/dist/spec/catalogs/narratives/rags-to-riches.json +7 -7
  53. package/dist/spec/catalogs/narratives/reveal.json +8 -8
  54. package/dist/spec/catalogs/narratives/scqa.json +1 -1
  55. package/dist/spec/catalogs/narratives/status-update.json +6 -6
  56. package/dist/spec/catalogs/narratives/strategic-advisory.json +7 -7
  57. package/dist/spec/catalogs/narratives/strategic-narrative.json +1 -1
  58. package/dist/spec/catalogs/narratives/survey-analysis.json +10 -10
  59. package/dist/spec/catalogs/narratives/survival-story.json +10 -10
  60. package/dist/spec/catalogs/narratives/transformation-arc.json +1 -1
  61. package/dist/spec/catalogs/narratives/trend-analysis.json +7 -7
  62. package/dist/spec/catalogs/narratives/underdog-victory.json +8 -8
  63. package/dist/spec/catalogs/narratives/venture-pitch.json +12 -12
  64. package/dist/spec/catalogs/narratives/weekly-progress.json +10 -10
  65. package/dist/spec/openapi.yaml +5 -0
  66. package/dist/spec/schemas/opf.schema.json +83 -12
  67. package/dist/types.d.ts +3 -3
  68. package/dist/validator.d.ts +7 -4
  69. package/dist/validator.js +4 -4
  70. package/package.json +1 -1
@@ -1,9 +1,89 @@
1
- import { MAX_COMPOSITION_DEPTH, tableGrid } from './chunk-PQJRDNA6.js';
2
- import { schemas, schemaEntries } from './chunk-D3GQIREP.js';
3
- import { catalogSchemaNames } from './chunk-TU7I3KSB.js';
1
+ import { MAX_COMPOSITION_DEPTH, tableGrid } from './chunk-FTWNWFIV.js';
2
+ import { schemas, schemaEntries } from './chunk-GN52EE3P.js';
3
+ import { catalogSchemaNames } from './chunk-6FU2KICU.js';
4
4
  import Ajv2020 from 'ajv/dist/2020.js';
5
5
  import addFormats from 'ajv-formats';
6
6
 
7
+ // src/content-walk.ts
8
+ function isRecord(value) {
9
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10
+ }
11
+ function pathFor(parentPath, key) {
12
+ return parentPath === "/" ? `/${key}` : `${parentPath}/${key.replaceAll("~", "~0").replaceAll("/", "~1")}`;
13
+ }
14
+ var bareIdPattern = /^[a-z0-9][a-z0-9-]*$/;
15
+ var promotedRegionKeys = [
16
+ "left",
17
+ "center",
18
+ "right",
19
+ "left+center",
20
+ "center+right",
21
+ "left+center+right",
22
+ "top",
23
+ "middle",
24
+ "bottom",
25
+ "top+middle",
26
+ "middle+bottom",
27
+ "top+middle+bottom",
28
+ "top:left",
29
+ "top:center",
30
+ "top:right",
31
+ "top:left+center",
32
+ "top:center+right",
33
+ "top:left+center+right",
34
+ "middle:left",
35
+ "middle:center",
36
+ "middle:right",
37
+ "middle:left+center",
38
+ "middle:center+right",
39
+ "middle:left+center+right",
40
+ "bottom:left",
41
+ "bottom:center",
42
+ "bottom:right",
43
+ "bottom:left+center",
44
+ "bottom:center+right",
45
+ "bottom:left+center+right",
46
+ "top+middle:left",
47
+ "top+middle:center",
48
+ "top+middle:right",
49
+ "top+middle:left+center",
50
+ "top+middle:center+right",
51
+ "top+middle:left+center+right",
52
+ "middle+bottom:left",
53
+ "middle+bottom:center",
54
+ "middle+bottom:right",
55
+ "middle+bottom:left+center",
56
+ "middle+bottom:center+right",
57
+ "middle+bottom:left+center+right",
58
+ "top+middle+bottom:left",
59
+ "top+middle+bottom:center",
60
+ "top+middle+bottom:right",
61
+ "top+middle+bottom:left+center",
62
+ "top+middle+bottom:center+right",
63
+ "top+middle+bottom:left+center+right"
64
+ ];
65
+ function visitContentPayloads(slide, slidePath, visit) {
66
+ const walk = (payload, path, depth, ancestors) => {
67
+ visit(payload, path);
68
+ if (!Array.isArray(payload.blocks) || depth >= MAX_COMPOSITION_DEPTH || ancestors.includes(payload)) return;
69
+ const nested = [...ancestors, payload];
70
+ const blocksPath = pathFor(path, "blocks");
71
+ payload.blocks.forEach((block, index) => {
72
+ if (isRecord(block)) walk(block, `${blocksPath}/${index}`, depth + 1, nested);
73
+ });
74
+ };
75
+ if (Array.isArray(slide.blocks)) {
76
+ const blocksPath = pathFor(slidePath, "blocks");
77
+ slide.blocks.forEach((block, index) => {
78
+ if (isRecord(block)) walk(block, `${blocksPath}/${index}`, 0, []);
79
+ });
80
+ }
81
+ for (const key of promotedRegionKeys) {
82
+ const region = slide[key];
83
+ if (isRecord(region)) walk(region, pathFor(slidePath, key), 0, []);
84
+ }
85
+ }
86
+
7
87
  // src/generated/catalog-ids.ts
8
88
  var catalogIds = {
9
89
  audiences: [
@@ -466,56 +546,6 @@ var OPFValidationError = class extends Error {
466
546
  var schemaNameByCatalogKind = catalogSchemaNames;
467
547
  var ajv;
468
548
  var dynamicSchemaCache = /* @__PURE__ */ new WeakMap();
469
- var promotedRegionKeys = [
470
- "left",
471
- "center",
472
- "right",
473
- "left+center",
474
- "center+right",
475
- "left+center+right",
476
- "top",
477
- "middle",
478
- "bottom",
479
- "top+middle",
480
- "middle+bottom",
481
- "top+middle+bottom",
482
- "top:left",
483
- "top:center",
484
- "top:right",
485
- "top:left+center",
486
- "top:center+right",
487
- "top:left+center+right",
488
- "middle:left",
489
- "middle:center",
490
- "middle:right",
491
- "middle:left+center",
492
- "middle:center+right",
493
- "middle:left+center+right",
494
- "bottom:left",
495
- "bottom:center",
496
- "bottom:right",
497
- "bottom:left+center",
498
- "bottom:center+right",
499
- "bottom:left+center+right",
500
- "top+middle:left",
501
- "top+middle:center",
502
- "top+middle:right",
503
- "top+middle:left+center",
504
- "top+middle:center+right",
505
- "top+middle:left+center+right",
506
- "middle+bottom:left",
507
- "middle+bottom:center",
508
- "middle+bottom:right",
509
- "middle+bottom:left+center",
510
- "middle+bottom:center+right",
511
- "middle+bottom:left+center+right",
512
- "top+middle+bottom:left",
513
- "top+middle+bottom:center",
514
- "top+middle+bottom:right",
515
- "top+middle+bottom:left+center",
516
- "top+middle+bottom:center+right",
517
- "top+middle+bottom:left+center+right"
518
- ];
519
549
  var promotedRegionKeySet = new Set(promotedRegionKeys);
520
550
  var rootPayloadFields = [
521
551
  "type",
@@ -655,18 +685,12 @@ function semanticIssue(path, message, params = {}) {
655
685
  params
656
686
  };
657
687
  }
658
- function isRecord(value) {
659
- return typeof value === "object" && value !== null && !Array.isArray(value);
660
- }
661
688
  function hasOwn(value, key) {
662
689
  return Object.hasOwn(value, key);
663
690
  }
664
691
  function isEnUkTag(value) {
665
692
  return typeof value === "string" && value.toLowerCase() === "en-uk";
666
693
  }
667
- function pathFor(parentPath, key) {
668
- return parentPath === "/" ? `/${key}` : `${parentPath}/${key.replaceAll("~", "~0").replaceAll("/", "~1")}`;
669
- }
670
694
  function presentFields(value, fields) {
671
695
  return fields.filter((field) => hasOwn(value, field));
672
696
  }
@@ -839,27 +863,32 @@ function validatePresentationSemantics(value) {
839
863
  replacement: "en-GB"
840
864
  }));
841
865
  }
842
- const slideIds = /* @__PURE__ */ new Set();
866
+ const documentIds = /* @__PURE__ */ new Map();
843
867
  value.slides.forEach((slide, index) => {
844
868
  if (isRecord(slide)) {
869
+ const slidePath = `/slides/${index}`;
845
870
  if (typeof slide.id === "string") {
846
- if (slideIds.has(slide.id)) issues.push(semanticIssue(`/slides/${index}/id`, "slide ids must be unique within a presentation", { id: slide.id }));
847
- slideIds.add(slide.id);
871
+ const seen = documentIds.get(slide.id);
872
+ if (seen === "slide") issues.push(semanticIssue(`${slidePath}/id`, "slide ids must be unique within a presentation", { id: slide.id }));
873
+ else if (seen === "payload") issues.push(semanticIssue(`${slidePath}/id`, "slide id duplicates a content payload id; ids must be unique among slide and payload ids within a presentation", { id: slide.id }));
874
+ else documentIds.set(slide.id, "slide");
848
875
  }
849
- issues.push(...validateSlideRegions(slide, `/slides/${index}`));
850
- const visitTables = (node, path) => {
851
- if (isRecord(node.table)) for (const issue of tableGrid(node.table).issues) issues.push(semanticIssue(pathFor(path, "table") + issue.path.slice(5).replaceAll(".", "/"), issue.message));
852
- if (Array.isArray(node.blocks)) node.blocks.forEach((block, i) => {
853
- if (isRecord(block)) visitTables(block, `${path}/blocks/${i}`);
854
- });
855
- for (const key of promotedRegionKeys) if (isRecord(node[key])) visitTables(node[key], pathFor(path, key));
876
+ visitContentPayloads(slide, slidePath, (payload, path) => {
877
+ if (typeof payload.id === "string") {
878
+ if (documentIds.has(payload.id)) issues.push(semanticIssue(`${path}/id`, "content payload ids must be unique among slide and payload ids within a presentation", { id: payload.id }));
879
+ else documentIds.set(payload.id, "payload");
880
+ }
881
+ });
882
+ issues.push(...validateSlideRegions(slide, slidePath));
883
+ const payloadTableIssues = (payload, path) => {
884
+ if (isRecord(payload.table)) for (const issue of tableGrid(payload.table).issues) issues.push(semanticIssue(pathFor(path, "table") + issue.path.slice(5).replaceAll(".", "/"), issue.message));
856
885
  };
857
- visitTables(slide, `/slides/${index}`);
886
+ payloadTableIssues(slide, slidePath);
887
+ visitContentPayloads(slide, slidePath, payloadTableIssues);
858
888
  }
859
889
  });
860
890
  return issues;
861
891
  }
862
- var bareIdPattern = /^[a-z0-9][a-z0-9-]*$/;
863
892
  function inlineCatalogEntry(context, kind) {
864
893
  const catalogsField = context.document.catalogs;
865
894
  if (!isRecord(catalogsField)) {
@@ -878,7 +907,7 @@ function unknownIdWarning(kind, value, path, context) {
878
907
  if (Array.isArray(entry.records) && entry.records.some((record) => isRecord(record) && record.id === value)) {
879
908
  return void 0;
880
909
  }
881
- if (typeof entry.source === "string") {
910
+ if (typeof entry.source === "string" || Array.isArray(entry.source) && entry.source.length > 0) {
882
911
  return void 0;
883
912
  }
884
913
  }
@@ -932,6 +961,126 @@ function chartTypeWarnings(payload, path, context) {
932
961
  }
933
962
  return issues;
934
963
  }
964
+ var cellBorderEdges = ["top", "right", "bottom", "left"];
965
+ var variableIdPattern = /^[a-z][a-z0-9-]*$/;
966
+ var hexColorPattern = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
967
+ var schemeColorNames = /* @__PURE__ */ new Set([
968
+ "accent1",
969
+ "accent2",
970
+ "accent3",
971
+ "accent4",
972
+ "accent5",
973
+ "accent6",
974
+ "dark1",
975
+ "dark2",
976
+ "light1",
977
+ "light2",
978
+ "hyperlink",
979
+ "followedHyperlink",
980
+ "primary",
981
+ "secondary",
982
+ "accent",
983
+ "background",
984
+ "surface",
985
+ "text",
986
+ "textSecondary"
987
+ ]);
988
+ function variableReferenceWarnings(value) {
989
+ if (!Array.isArray(value.slides)) {
990
+ return [];
991
+ }
992
+ const variables = isRecord(value.variables) ? value.variables : {};
993
+ const issues = [];
994
+ const colorRef = (entry, path) => {
995
+ if (typeof entry !== "string" || !entry.startsWith("var:")) return;
996
+ const id = entry.slice("var:".length);
997
+ if (!variableIdPattern.test(id) || hasOwn(variables, id)) return;
998
+ issues.push(semanticIssue(path, `unknown variable '${id}'; declare it in the top-level variables map`, { id }));
999
+ };
1000
+ const runColor = (entry, path) => {
1001
+ if (typeof entry !== "string") return;
1002
+ if (hexColorPattern.test(entry) || schemeColorNames.has(entry)) return;
1003
+ if (entry.startsWith("var:") && variableIdPattern.test(entry.slice("var:".length))) {
1004
+ colorRef(entry, path);
1005
+ return;
1006
+ }
1007
+ issues.push(semanticIssue(
1008
+ path,
1009
+ `run color '${entry}' is not a hex color, a color-scheme name, or a 'var:' reference; renderers fall back to the theme color`,
1010
+ { color: entry }
1011
+ ));
1012
+ };
1013
+ const richText = (entry, path) => {
1014
+ if (!Array.isArray(entry)) return;
1015
+ entry.forEach((run, index) => {
1016
+ if (isRecord(run)) runColor(run.color, `${path}/${index}/color`);
1017
+ });
1018
+ };
1019
+ const cellStyle = (style, path) => {
1020
+ if (!isRecord(style)) return;
1021
+ colorRef(style.fill, pathFor(path, "fill"));
1022
+ colorRef(style.color, pathFor(path, "color"));
1023
+ if (!isRecord(style.borders)) return;
1024
+ const bordersPath = pathFor(path, "borders");
1025
+ for (const edge of cellBorderEdges) {
1026
+ const border = style.borders[edge];
1027
+ if (isRecord(border)) colorRef(border.color, `${pathFor(bordersPath, edge)}/color`);
1028
+ }
1029
+ };
1030
+ const tableCell = (cell, path) => {
1031
+ if (Array.isArray(cell)) {
1032
+ richText(cell, path);
1033
+ return;
1034
+ }
1035
+ if (!isRecord(cell)) return;
1036
+ richText(cell.value, pathFor(path, "value"));
1037
+ cellStyle(cell.style, pathFor(path, "style"));
1038
+ };
1039
+ const table = (node, path) => {
1040
+ if (!isRecord(node)) return;
1041
+ if (Array.isArray(node.columns)) {
1042
+ const columnsPath = pathFor(path, "columns");
1043
+ node.columns.forEach((column, index) => {
1044
+ tableCell(column, `${columnsPath}/${index}`);
1045
+ });
1046
+ }
1047
+ if (Array.isArray(node.rows)) {
1048
+ const rowsPath = pathFor(path, "rows");
1049
+ node.rows.forEach((row, rowIndex) => {
1050
+ if (!Array.isArray(row)) return;
1051
+ row.forEach((cell, cellIndex) => {
1052
+ tableCell(cell, `${rowsPath}/${rowIndex}/${cellIndex}`);
1053
+ });
1054
+ });
1055
+ }
1056
+ };
1057
+ const textEntries = (entries, path) => {
1058
+ if (!Array.isArray(entries)) return;
1059
+ entries.forEach((entry, index) => {
1060
+ const entryPath = `${path}/${index}`;
1061
+ if (Array.isArray(entry)) {
1062
+ richText(entry, entryPath);
1063
+ return;
1064
+ }
1065
+ if (!isRecord(entry)) return;
1066
+ richText(entry.text, pathFor(entryPath, "text"));
1067
+ richText(entry.description, pathFor(entryPath, "description"));
1068
+ });
1069
+ };
1070
+ const payload = (node, path) => {
1071
+ richText(node.text, pathFor(path, "text"));
1072
+ textEntries(node.items, pathFor(path, "items"));
1073
+ textEntries(node.bullets, pathFor(path, "bullets"));
1074
+ table(node.table, pathFor(path, "table"));
1075
+ };
1076
+ value.slides.forEach((slide, index) => {
1077
+ if (!isRecord(slide)) return;
1078
+ const slidePath = `/slides/${index}`;
1079
+ payload(slide, slidePath);
1080
+ visitContentPayloads(slide, slidePath, payload);
1081
+ });
1082
+ return issues;
1083
+ }
935
1084
  function presentationReferenceWarnings(value) {
936
1085
  if (!isRecord(value) || !Array.isArray(value.slides)) {
937
1086
  return [];
@@ -942,6 +1091,7 @@ function presentationReferenceWarnings(value) {
942
1091
  pushIfDefined(issues, unknownIdWarning("narratives", value.narrative, "/narrative", context));
943
1092
  }
944
1093
  issues.push(...designReferenceWarnings(value.design, "/design", context));
1094
+ issues.push(...variableReferenceWarnings(value));
945
1095
  value.slides.forEach((slide, index) => {
946
1096
  if (!isRecord(slide)) {
947
1097
  return;
@@ -1057,4 +1207,4 @@ function assertValidCatalogRecord(kind, value) {
1057
1207
  assertValid(value, kind);
1058
1208
  }
1059
1209
 
1060
- export { OPFValidationError, assertValid, assertValidCatalogRecord, assertValidPresentation, validate, validateCatalogRecord, validatePresentation, validationDefinition };
1210
+ export { OPFValidationError, assertValid, assertValidCatalogRecord, assertValidPresentation, bareIdPattern, isRecord, promotedRegionKeys, validate, validateCatalogRecord, validatePresentation, validationDefinition, visitContentPayloads };
@@ -1,6 +1,6 @@
1
- import { validatePresentation, validationDefinition, validateCatalogRecord } from './chunk-ZIL7MGZU.js';
2
- import { schemas, schemaEntries } from './chunk-D3GQIREP.js';
3
- import { catalogKinds, catalogEntries, catalogSchemaNames } from './chunk-TU7I3KSB.js';
1
+ import { validatePresentation, validationDefinition, validateCatalogRecord } from './chunk-CHKJ4QHQ.js';
2
+ import { schemas, schemaEntries } from './chunk-GN52EE3P.js';
3
+ import { catalogKinds, catalogEntries, catalogSchemaNames } from './chunk-6FU2KICU.js';
4
4
  import { parseTree, printParseErrorCode, getNodePath } from 'jsonc-parser';
5
5
 
6
6
  var own = (value, key) => Object.hasOwn(value, key);
@@ -36,6 +36,77 @@ function tableRowBoundaries(value) {
36
36
  }
37
37
 
38
38
  // src/color.ts
39
+ var schemeColorSlots = /* @__PURE__ */ new Set([
40
+ "accent1",
41
+ "accent2",
42
+ "accent3",
43
+ "accent4",
44
+ "accent5",
45
+ "accent6",
46
+ "dark1",
47
+ "dark2",
48
+ "light1",
49
+ "light2",
50
+ "hyperlink",
51
+ "followedHyperlink"
52
+ ]);
53
+ var schemeColorRoles = /* @__PURE__ */ new Set([
54
+ "primary",
55
+ "secondary",
56
+ "accent",
57
+ "background",
58
+ "surface",
59
+ "text",
60
+ "textSecondary"
61
+ ]);
62
+ var defaultRoleSlots = {
63
+ primary: "accent1",
64
+ secondary: "accent2",
65
+ accent: "accent3",
66
+ background: "light1",
67
+ surface: "light2",
68
+ text: "dark1",
69
+ textSecondary: "dark2"
70
+ };
71
+ function normalizeHexColor(value) {
72
+ if (typeof value !== "string") return void 0;
73
+ let hex = value.trim();
74
+ if (/^#[0-9a-f]{3}$/i.test(hex)) hex = `#${[...hex.slice(1)].map((char) => char + char).join("")}`;
75
+ if (/^#[0-9a-f]{6}([0-9a-f]{2})?$/i.test(hex)) return hex.length === 9 ? `#${hex.slice(1, 7).toUpperCase()}` : hex.toUpperCase();
76
+ return void 0;
77
+ }
78
+ function schemeSlot(colorScheme, slot, fallback) {
79
+ return normalizeHexColor(colorScheme[slot]) ?? fallback;
80
+ }
81
+ function resolveVariable(variables, id, fallback) {
82
+ const entry = variables[id];
83
+ if (typeof entry === "string") return normalizeHexColor(entry) ?? fallback;
84
+ if (entry && typeof entry === "object" && entry.type === "color") {
85
+ return normalizeHexColor(entry.value) ?? fallback;
86
+ }
87
+ return fallback;
88
+ }
89
+ function resolveColorRef(reference, options) {
90
+ const { colorScheme, roles, variables = {}, fallback } = options;
91
+ const literal = normalizeHexColor(reference);
92
+ if (literal) return literal;
93
+ if (reference.startsWith("var:")) {
94
+ const id = reference.slice("var:".length);
95
+ if (/^[a-z][a-z0-9-]*$/.test(id)) return resolveVariable(variables, id, fallback);
96
+ return fallback;
97
+ }
98
+ if (schemeColorRoles.has(reference)) {
99
+ const roleKey = reference;
100
+ const fromRoles = roles?.[roleKey];
101
+ if (fromRoles) return normalizeHexColor(fromRoles) ?? fallback;
102
+ const fromScheme = normalizeHexColor(colorScheme[reference]);
103
+ if (fromScheme) return fromScheme;
104
+ const slot = defaultRoleSlots[reference];
105
+ return slot ? schemeSlot(colorScheme, slot, fallback) : fallback;
106
+ }
107
+ if (schemeColorSlots.has(reference)) return schemeSlot(colorScheme, reference, fallback);
108
+ return fallback;
109
+ }
39
110
  function luminance(value) {
40
111
  if (typeof value !== "string") return void 0;
41
112
  let hex = value.trim();
@@ -1426,4 +1497,4 @@ function resolveCanvasDimensions(input) {
1426
1497
  return { width, height };
1427
1498
  }
1428
1499
 
1429
- export { MAX_COMPOSITION_DEPTH, OPFCompositionError, chartColorForFill, colorContrast, composeSlide, fitList, fitRichText, fitText, layoutCode, layoutFurniture, layoutMetric, layoutQuote, layoutTable, layoutTimeline, measureText, measureTextOutline, placeTextLines, resolveCanvasDimensions, resolveFontFamilies, resolveTextStyle, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, wrapText };
1500
+ export { MAX_COMPOSITION_DEPTH, OPFCompositionError, chartColorForFill, colorContrast, composeSlide, fitList, fitRichText, fitText, layoutCode, layoutFurniture, layoutMetric, layoutQuote, layoutTable, layoutTimeline, measureText, measureTextOutline, normalizeHexColor, placeTextLines, resolveCanvasDimensions, resolveColorRef, resolveFontFamilies, resolveTextStyle, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, wrapText };
@@ -1,6 +1,6 @@
1
- import { assertValidPresentation } from './chunk-ZIL7MGZU.js';
2
- import { resolveFontFamilies, resolveCanvasDimensions, composeSlide, tableRowBoundaries } from './chunk-PQJRDNA6.js';
3
- import { catalogs } from './chunk-TU7I3KSB.js';
1
+ import { assertValidPresentation, visitContentPayloads } from './chunk-CHKJ4QHQ.js';
2
+ import { resolveFontFamilies, resolveCanvasDimensions, composeSlide, tableRowBoundaries } from './chunk-FTWNWFIV.js';
3
+ import { catalogs } from './chunk-6FU2KICU.js';
4
4
 
5
5
  // src/pagination.ts
6
6
  var OPFPaginationError = class extends Error {
@@ -16,6 +16,13 @@ var contentFields = /* @__PURE__ */ new Set(["text", "items", "bullets", "image"
16
16
  var headingFields = /* @__PURE__ */ new Set(["title", "subtitle", "tag"]);
17
17
  var isRecord = (v) => !!v && typeof v === "object" && !Array.isArray(v);
18
18
  var clone = (value) => structuredClone(value);
19
+ var slideIds = (slide) => {
20
+ const ids = typeof slide.id === "string" ? [slide.id] : [];
21
+ visitContentPayloads(slide, "", (payload) => {
22
+ if (typeof payload.id === "string") ids.push(payload.id);
23
+ });
24
+ return ids;
25
+ };
19
26
  var textOf = (value) => typeof value === "string" ? value : Array.isArray(value) ? value.map(textOf).join("") : value?.text ?? "";
20
27
  var graphemes = new Intl.Segmenter("und", { granularity: "grapheme" });
21
28
  function sliceRichText(value, start, end) {
@@ -105,7 +112,26 @@ function paginateSlide(input, options = {}) {
105
112
  const slides = [], pages = [];
106
113
  let selected = /* @__PURE__ */ new Map();
107
114
  const reservedIds = new Set(options.reservedIds ?? []);
108
- if (typeof source.id === "string") reservedIds.add(source.id);
115
+ for (const id of slideIds(source)) reservedIds.add(id);
116
+ const emittedIds = /* @__PURE__ */ new Set();
117
+ const pageId = (base, pageIndex) => {
118
+ if (!emittedIds.has(base)) {
119
+ emittedIds.add(base);
120
+ return base;
121
+ }
122
+ let suffix = pageIndex + 1, id = `${base}--${suffix}`;
123
+ while (reservedIds.has(id)) id = `${base}--${++suffix}`;
124
+ reservedIds.add(id);
125
+ emittedIds.add(id);
126
+ return id;
127
+ };
128
+ const assignPageIds = (slide, pageIndex) => {
129
+ const assign = (node) => {
130
+ if (typeof node.id === "string") node.id = pageId(node.id, pageIndex);
131
+ };
132
+ assign(slide);
133
+ visitContentPayloads(slide, "", assign);
134
+ };
109
135
  const project = (portions, pageIndex) => {
110
136
  const mappings = [];
111
137
  const visit = (node, path, out, root = false) => {
@@ -151,12 +177,7 @@ function paginateSlide(input, options = {}) {
151
177
  const { slide, mappings } = project(selected, slides.length);
152
178
  const issues = geometry(slide, slides.length).diagnostics;
153
179
  if (issues.length) throw new OPFPaginationError("A continuation page does not fit at its final page number. No partial result was returned.", issues);
154
- if (slides.length && typeof source.id === "string") {
155
- let suffix = slides.length + 1, id = `${source.id}--${suffix}`;
156
- while (reservedIds.has(id)) id = `${source.id}--${++suffix}`;
157
- slide.id = id;
158
- reservedIds.add(id);
159
- }
180
+ assignPageIds(slide, slides.length);
160
181
  assertValidPresentation({ slides: [slide] });
161
182
  slides.push(slide);
162
183
  pages.push({ slideIndex: sourceIndex + slides.length - 1, mappings, ...initial.furniture ? { repeatedMappings: repeatedMappings(slides.length - 1) } : {} });
@@ -215,7 +236,7 @@ function paginatePresentation(input, options = {}) {
215
236
  const maxSlides = options.maxSlides ?? 100;
216
237
  if (!Number.isInteger(maxSlides) || maxSlides < 1 || maxSlides > 1e4) throw new RangeError("maxSlides must be an integer between 1 and 10000.");
217
238
  const output = [], pages = [];
218
- const reservedIds = presentation.slides.map((slide) => slide.id).filter(Boolean);
239
+ const reservedIds = presentation.slides.flatMap((slide) => slideIds(slide));
219
240
  const resolve = (kind, id) => presentation.catalogs?.[kind]?.records?.find((record) => record.id === id) ?? catalogs[kind].find((record) => record.id === id);
220
241
  presentation.slides.forEach((slide, index) => {
221
242
  const overrides = options.slideOptions?.(slide, index) ?? {};
@@ -236,7 +257,7 @@ function paginatePresentation(input, options = {}) {
236
257
  pages.push({ sourceSlideIndex: index, slideIndex: outputStart + pageIndex, mappings: page.mappings.map(remap), ...page.repeatedMappings ? { repeatedMappings: page.repeatedMappings.map(remap) } : {} });
237
258
  });
238
259
  output.push(...result.slides);
239
- reservedIds.push(...result.slides.map((slide2) => slide2.id).filter(Boolean));
260
+ reservedIds.push(...result.slides.flatMap((slide2) => slideIds(slide2)));
240
261
  });
241
262
  presentation.slides = output;
242
263
  assertValidPresentation(presentation);