@openpresentation/opf 0.10.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.
- package/dist/{catalogs-HCTav5Wv.d.ts → catalogs-atkOF4Vy.d.ts} +7 -7
- package/dist/catalogs.d.ts +2 -2
- package/dist/catalogs.js +1 -1
- package/dist/{chunk-TWMRZ43O.js → chunk-6FU2KICU.js} +365 -327
- package/dist/{chunk-GCB6LGJM.js → chunk-CHKJ4QHQ.js} +225 -73
- package/dist/{chunk-NPOKUFEX.js → chunk-EQHZ3ZO4.js} +3 -3
- package/dist/{chunk-BAWLYSUN.js → chunk-FTWNWFIV.js} +180 -6
- package/dist/{chunk-TK3QHM3U.js → chunk-FWA5XB45.js} +54 -21
- package/dist/{chunk-GQSK3T7X.js → chunk-GN52EE3P.js} +146 -16
- package/dist/{chunk-OZULJBSG.js → chunk-RS5GZ5RW.js} +14 -0
- package/dist/composition-Tv9Wm3Oh.d.ts +691 -0
- package/dist/composition.d.ts +1 -624
- package/dist/composition.js +1 -1
- package/dist/docs.js +59 -11
- package/dist/examples.d.ts +1 -1
- package/dist/index.d.ts +65 -4
- package/dist/index.js +205 -7
- package/dist/lint.d.ts +3 -3
- package/dist/lint.js +5 -5
- package/dist/pagination.d.ts +4 -2
- package/dist/pagination.js +5 -5
- package/dist/{presentation-BMTdX6O1.d.ts → presentation-Ct42Mitb.d.ts} +51 -8
- package/dist/repo-readme.js +1 -1
- package/dist/{schemas-BYe5y8-i.d.ts → schemas-CiVmUT2p.d.ts} +6 -0
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.js +1 -1
- package/dist/spec/catalogs/layouts/extract/canonical.json +45 -21
- package/dist/spec/catalogs/layouts/index.json +10 -0
- package/dist/spec/catalogs/layouts/number-1x.json +1 -1
- package/dist/spec/catalogs/layouts/number-2x.json +2 -2
- package/dist/spec/catalogs/layouts/number-3x.json +3 -3
- package/dist/spec/catalogs/layouts/number-4x.json +4 -4
- package/dist/spec/catalogs/layouts/number-5x.json +5 -5
- package/dist/spec/catalogs/layouts/number-6x.json +6 -6
- package/dist/spec/catalogs/layouts/quote-1x.json +13 -0
- package/dist/spec/catalogs/layouts/timeline-1x.json +13 -0
- package/dist/spec/catalogs/narratives/board-meeting.json +21 -21
- package/dist/spec/catalogs/narratives/business-narrative.json +8 -8
- package/dist/spec/catalogs/narratives/business-review.json +12 -12
- package/dist/spec/catalogs/narratives/capacity-planning.json +8 -8
- package/dist/spec/catalogs/narratives/challenge-resolution.json +7 -7
- package/dist/spec/catalogs/narratives/classic-story.json +7 -7
- package/dist/spec/catalogs/narratives/company-intro.json +9 -9
- package/dist/spec/catalogs/narratives/conference-talk.json +1 -1
- package/dist/spec/catalogs/narratives/early-startup-pitch.json +12 -12
- package/dist/spec/catalogs/narratives/educate.json +9 -9
- package/dist/spec/catalogs/narratives/employee-review.json +8 -8
- package/dist/spec/catalogs/narratives/failure-analysis.json +10 -10
- package/dist/spec/catalogs/narratives/focus.json +12 -12
- package/dist/spec/catalogs/narratives/golden-circle.json +1 -1
- package/dist/spec/catalogs/narratives/innovation.json +9 -9
- package/dist/spec/catalogs/narratives/justice.json +11 -11
- package/dist/spec/catalogs/narratives/marketing-strategy.json +11 -11
- package/dist/spec/catalogs/narratives/performance-improvement-plan.json +8 -8
- package/dist/spec/catalogs/narratives/performance-review.json +11 -11
- package/dist/spec/catalogs/narratives/persuade.json +7 -7
- package/dist/spec/catalogs/narratives/persuasive-sales.json +8 -8
- package/dist/spec/catalogs/narratives/pitch-deck.json +3 -3
- package/dist/spec/catalogs/narratives/problem-solution.json +2 -2
- package/dist/spec/catalogs/narratives/product-launch.json +10 -10
- package/dist/spec/catalogs/narratives/project-proposal.json +10 -10
- package/dist/spec/catalogs/narratives/qbr.json +3 -3
- package/dist/spec/catalogs/narratives/rags-to-riches.json +7 -7
- package/dist/spec/catalogs/narratives/reveal.json +8 -8
- package/dist/spec/catalogs/narratives/scqa.json +1 -1
- package/dist/spec/catalogs/narratives/status-update.json +6 -6
- package/dist/spec/catalogs/narratives/strategic-advisory.json +7 -7
- package/dist/spec/catalogs/narratives/strategic-narrative.json +1 -1
- package/dist/spec/catalogs/narratives/survey-analysis.json +10 -10
- package/dist/spec/catalogs/narratives/survival-story.json +10 -10
- package/dist/spec/catalogs/narratives/transformation-arc.json +1 -1
- package/dist/spec/catalogs/narratives/trend-analysis.json +7 -7
- package/dist/spec/catalogs/narratives/underdog-victory.json +8 -8
- package/dist/spec/catalogs/narratives/venture-pitch.json +12 -12
- package/dist/spec/catalogs/narratives/weekly-progress.json +10 -10
- package/dist/spec/openapi.yaml +5 -0
- package/dist/spec/schemas/layout.schema.json +12 -3
- package/dist/spec/schemas/narrative.schema.json +1 -1
- package/dist/spec/schemas/opf.schema.json +83 -12
- package/dist/spec-files.d.ts +1 -1
- package/dist/spec-files.js +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/validator.d.ts +7 -4
- package/dist/validator.js +4 -4
- package/package.json +1 -1
|
@@ -1,9 +1,89 @@
|
|
|
1
|
-
import { MAX_COMPOSITION_DEPTH, tableGrid } from './chunk-
|
|
2
|
-
import { schemas, schemaEntries } from './chunk-
|
|
3
|
-
import { catalogSchemaNames } from './chunk-
|
|
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: [
|
|
@@ -67,10 +147,12 @@ var catalogIds = {
|
|
|
67
147
|
"number-4x",
|
|
68
148
|
"number-5x",
|
|
69
149
|
"number-6x",
|
|
150
|
+
"quote-1x",
|
|
70
151
|
"table-1x",
|
|
71
152
|
"text-1x",
|
|
72
153
|
"text-2x",
|
|
73
154
|
"text-3x",
|
|
155
|
+
"timeline-1x",
|
|
74
156
|
"title",
|
|
75
157
|
"title-subtitle"
|
|
76
158
|
],
|
|
@@ -464,56 +546,6 @@ var OPFValidationError = class extends Error {
|
|
|
464
546
|
var schemaNameByCatalogKind = catalogSchemaNames;
|
|
465
547
|
var ajv;
|
|
466
548
|
var dynamicSchemaCache = /* @__PURE__ */ new WeakMap();
|
|
467
|
-
var promotedRegionKeys = [
|
|
468
|
-
"left",
|
|
469
|
-
"center",
|
|
470
|
-
"right",
|
|
471
|
-
"left+center",
|
|
472
|
-
"center+right",
|
|
473
|
-
"left+center+right",
|
|
474
|
-
"top",
|
|
475
|
-
"middle",
|
|
476
|
-
"bottom",
|
|
477
|
-
"top+middle",
|
|
478
|
-
"middle+bottom",
|
|
479
|
-
"top+middle+bottom",
|
|
480
|
-
"top:left",
|
|
481
|
-
"top:center",
|
|
482
|
-
"top:right",
|
|
483
|
-
"top:left+center",
|
|
484
|
-
"top:center+right",
|
|
485
|
-
"top:left+center+right",
|
|
486
|
-
"middle:left",
|
|
487
|
-
"middle:center",
|
|
488
|
-
"middle:right",
|
|
489
|
-
"middle:left+center",
|
|
490
|
-
"middle:center+right",
|
|
491
|
-
"middle:left+center+right",
|
|
492
|
-
"bottom:left",
|
|
493
|
-
"bottom:center",
|
|
494
|
-
"bottom:right",
|
|
495
|
-
"bottom:left+center",
|
|
496
|
-
"bottom:center+right",
|
|
497
|
-
"bottom:left+center+right",
|
|
498
|
-
"top+middle:left",
|
|
499
|
-
"top+middle:center",
|
|
500
|
-
"top+middle:right",
|
|
501
|
-
"top+middle:left+center",
|
|
502
|
-
"top+middle:center+right",
|
|
503
|
-
"top+middle:left+center+right",
|
|
504
|
-
"middle+bottom:left",
|
|
505
|
-
"middle+bottom:center",
|
|
506
|
-
"middle+bottom:right",
|
|
507
|
-
"middle+bottom:left+center",
|
|
508
|
-
"middle+bottom:center+right",
|
|
509
|
-
"middle+bottom:left+center+right",
|
|
510
|
-
"top+middle+bottom:left",
|
|
511
|
-
"top+middle+bottom:center",
|
|
512
|
-
"top+middle+bottom:right",
|
|
513
|
-
"top+middle+bottom:left+center",
|
|
514
|
-
"top+middle+bottom:center+right",
|
|
515
|
-
"top+middle+bottom:left+center+right"
|
|
516
|
-
];
|
|
517
549
|
var promotedRegionKeySet = new Set(promotedRegionKeys);
|
|
518
550
|
var rootPayloadFields = [
|
|
519
551
|
"type",
|
|
@@ -653,18 +685,12 @@ function semanticIssue(path, message, params = {}) {
|
|
|
653
685
|
params
|
|
654
686
|
};
|
|
655
687
|
}
|
|
656
|
-
function isRecord(value) {
|
|
657
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
658
|
-
}
|
|
659
688
|
function hasOwn(value, key) {
|
|
660
689
|
return Object.hasOwn(value, key);
|
|
661
690
|
}
|
|
662
691
|
function isEnUkTag(value) {
|
|
663
692
|
return typeof value === "string" && value.toLowerCase() === "en-uk";
|
|
664
693
|
}
|
|
665
|
-
function pathFor(parentPath, key) {
|
|
666
|
-
return parentPath === "/" ? `/${key}` : `${parentPath}/${key.replaceAll("~", "~0").replaceAll("/", "~1")}`;
|
|
667
|
-
}
|
|
668
694
|
function presentFields(value, fields) {
|
|
669
695
|
return fields.filter((field) => hasOwn(value, field));
|
|
670
696
|
}
|
|
@@ -837,27 +863,32 @@ function validatePresentationSemantics(value) {
|
|
|
837
863
|
replacement: "en-GB"
|
|
838
864
|
}));
|
|
839
865
|
}
|
|
840
|
-
const
|
|
866
|
+
const documentIds = /* @__PURE__ */ new Map();
|
|
841
867
|
value.slides.forEach((slide, index) => {
|
|
842
868
|
if (isRecord(slide)) {
|
|
869
|
+
const slidePath = `/slides/${index}`;
|
|
843
870
|
if (typeof slide.id === "string") {
|
|
844
|
-
|
|
845
|
-
|
|
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");
|
|
846
875
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
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));
|
|
854
885
|
};
|
|
855
|
-
|
|
886
|
+
payloadTableIssues(slide, slidePath);
|
|
887
|
+
visitContentPayloads(slide, slidePath, payloadTableIssues);
|
|
856
888
|
}
|
|
857
889
|
});
|
|
858
890
|
return issues;
|
|
859
891
|
}
|
|
860
|
-
var bareIdPattern = /^[a-z0-9][a-z0-9-]*$/;
|
|
861
892
|
function inlineCatalogEntry(context, kind) {
|
|
862
893
|
const catalogsField = context.document.catalogs;
|
|
863
894
|
if (!isRecord(catalogsField)) {
|
|
@@ -876,7 +907,7 @@ function unknownIdWarning(kind, value, path, context) {
|
|
|
876
907
|
if (Array.isArray(entry.records) && entry.records.some((record) => isRecord(record) && record.id === value)) {
|
|
877
908
|
return void 0;
|
|
878
909
|
}
|
|
879
|
-
if (typeof entry.source === "string") {
|
|
910
|
+
if (typeof entry.source === "string" || Array.isArray(entry.source) && entry.source.length > 0) {
|
|
880
911
|
return void 0;
|
|
881
912
|
}
|
|
882
913
|
}
|
|
@@ -930,6 +961,126 @@ function chartTypeWarnings(payload, path, context) {
|
|
|
930
961
|
}
|
|
931
962
|
return issues;
|
|
932
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
|
+
}
|
|
933
1084
|
function presentationReferenceWarnings(value) {
|
|
934
1085
|
if (!isRecord(value) || !Array.isArray(value.slides)) {
|
|
935
1086
|
return [];
|
|
@@ -940,6 +1091,7 @@ function presentationReferenceWarnings(value) {
|
|
|
940
1091
|
pushIfDefined(issues, unknownIdWarning("narratives", value.narrative, "/narrative", context));
|
|
941
1092
|
}
|
|
942
1093
|
issues.push(...designReferenceWarnings(value.design, "/design", context));
|
|
1094
|
+
issues.push(...variableReferenceWarnings(value));
|
|
943
1095
|
value.slides.forEach((slide, index) => {
|
|
944
1096
|
if (!isRecord(slide)) {
|
|
945
1097
|
return;
|
|
@@ -1055,4 +1207,4 @@ function assertValidCatalogRecord(kind, value) {
|
|
|
1055
1207
|
assertValid(value, kind);
|
|
1056
1208
|
}
|
|
1057
1209
|
|
|
1058
|
-
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-
|
|
2
|
-
import { schemas, schemaEntries } from './chunk-
|
|
3
|
-
import { catalogKinds, catalogEntries, catalogSchemaNames } from './chunk-
|
|
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();
|
|
@@ -146,8 +217,105 @@ var headings = /* @__PURE__ */ new Set(["title", "subtitle", "tag"]);
|
|
|
146
217
|
var rows = ["top", "middle", "bottom"];
|
|
147
218
|
var columns = ["left", "center", "right"];
|
|
148
219
|
var record2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
149
|
-
var kind = (field) => field === "items"
|
|
220
|
+
var kind = (field) => field === "items" ? "list" : field === "bullets" ? "text" : field;
|
|
150
221
|
var round = (value) => Math.round(value * 1e6) / 1e6 || value;
|
|
222
|
+
function layoutFurniture(input, options = {}) {
|
|
223
|
+
const slide = record2(input), width = options.width ?? 1280, height = options.height ?? 720, scale = Math.min(width, height) / 720;
|
|
224
|
+
const settings = { ...record2(record2(options.layout).composition), ...record2(slide.composition) };
|
|
225
|
+
assertComposition(settings);
|
|
226
|
+
const minimum = (settings.minFontSize ?? 16) * scale, size = Math.max(13 * scale, minimum), padding = (options.textRasterPadding ?? 2) * scale;
|
|
227
|
+
if (![width, height, scale, minimum, padding].every(Number.isFinite) || width <= 0 || height <= 0 || minimum <= 0 || padding < 0) throw new RangeError("Furniture requires finite positive dimensions and nonnegative raster padding.");
|
|
228
|
+
const number = options.slideNumber ?? (options.slideIndex ?? 0) + 1;
|
|
229
|
+
if (!Number.isSafeInteger(number) || number < 1) throw new RangeError("Displayed slide number must be a positive safe integer.");
|
|
230
|
+
const outlines = options.textMeasurement?.outlineBounds !== void 0, parts = [], diagnostics = [];
|
|
231
|
+
const sourceRoot = `slides.${options.slideIndex ?? 0}`, organizations = Array.isArray(options.presentation?.organization) ? options.presentation.organization : [options.presentation?.organization];
|
|
232
|
+
const primaryIndex = organizations.findIndex((item) => record2(item).role === "primary"), organizationIndex = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
|
|
233
|
+
const organization = record2(organizations[organizationIndex]), organizationPath = Array.isArray(options.presentation?.organization) ? `organization.${organizationIndex}.name` : "organization.name";
|
|
234
|
+
const fontFamily = options.fonts?.body ?? "sans-serif";
|
|
235
|
+
let headerBottom = 0, footerTop = height, configured = false;
|
|
236
|
+
const error = (path, message, code = "text-overflow") => diagnostics.push({ code, path, message });
|
|
237
|
+
for (const kind2 of ["header", "footer"]) {
|
|
238
|
+
const local = record2(slide.design)[kind2] !== void 0, value = local ? record2(slide.design)[kind2] : options.presentation?.design?.[kind2];
|
|
239
|
+
if (value === void 0 || value === false) continue;
|
|
240
|
+
const root = local ? `${sourceRoot}.design.${kind2}` : `design.${kind2}`;
|
|
241
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Header/footer content must be an object or false.");
|
|
242
|
+
configured = true;
|
|
243
|
+
const zones = [];
|
|
244
|
+
for (const [index, zone] of ["left", "center", "right"].entries()) {
|
|
245
|
+
const content = record2(record2(value)[zone]), path = `${root}.${zone}`, x = width * (0.07 + index * 0.3), zoneWidth = width * 0.26, zoneParts = [];
|
|
246
|
+
let y = 0;
|
|
247
|
+
const add = (field, text, generated = false, sourcePath) => {
|
|
248
|
+
if (text === void 0) return;
|
|
249
|
+
if (typeof text !== "string") throw new TypeError(`Furniture field ${path}.${field} requires string content.`);
|
|
250
|
+
const partPath = `${path}.${field}`, style = resolveTextStyle({ fontFamily, fontWeight: 400, italic: false, path: partPath }, options.textMeasurement);
|
|
251
|
+
const fit = fitText(text, { width: Math.max(Number.MIN_VALUE, zoneWidth - (outlines ? 2 * padding : 0)), height: Number.MAX_VALUE }, size, size, textWidthMeasurer(style, options.textMeasurement));
|
|
252
|
+
const ink = fit.sourceLines.map((line, index2) => {
|
|
253
|
+
let outline = null;
|
|
254
|
+
if (outlines) {
|
|
255
|
+
for (const segment of line.segments) if (segment.kind === "text") {
|
|
256
|
+
const bounds = measureTextOutline(text.slice(segment.start, segment.end), size, style, options.textMeasurement);
|
|
257
|
+
if (bounds) {
|
|
258
|
+
const next = { ...bounds, x: bounds.x + segment.x };
|
|
259
|
+
if (!outline) outline = next;
|
|
260
|
+
else {
|
|
261
|
+
const right = Math.max(outline.x + outline.width, next.x + next.width), bottom = Math.max(outline.y + outline.height, next.y + next.height);
|
|
262
|
+
outline.x = Math.min(outline.x, next.x);
|
|
263
|
+
outline.y = Math.min(outline.y, next.y);
|
|
264
|
+
outline.width = right - outline.x;
|
|
265
|
+
outline.height = bottom - outline.y;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return { width: line.width, y: index2 * fit.lineHeight, baseline: size + index2 * fit.lineHeight, height: fit.lineHeight, outline };
|
|
271
|
+
});
|
|
272
|
+
const natural = outlines ? placeTextLines(ink, { x, y, width: zoneWidth, height: Number.MAX_VALUE }, zone, padding) : void 0;
|
|
273
|
+
const partHeight = natural?.height ?? fit.sourceLines.length * fit.lineHeight;
|
|
274
|
+
if (!Number.isFinite(partHeight)) throw new RangeError("Furniture exceeds finite layout coordinates.");
|
|
275
|
+
const box = { x, y, width: zoneWidth, height: Math.max(scale, partHeight) }, placement = outlines ? placeTextLines(ink, box, zone, padding) : void 0;
|
|
276
|
+
const accepted = { ...fit, ...placement ? { placement } : {}, overflow: fit.overflow || !!placement?.overflow };
|
|
277
|
+
zoneParts.push({ type: "text", kind: kind2, zone, field, path: partPath, sourcePath: sourcePath ?? (!generated ? partPath : void 0), generated, text, style, requestedFontSize: 13 * scale, minFontSize: minimum, box, alignment: zone, fit: accepted });
|
|
278
|
+
if (accepted.overflow) error(partPath, "Repeated text exceeds its zone at the selected readability floor; change the furniture or slide design.");
|
|
279
|
+
y += box.height;
|
|
280
|
+
};
|
|
281
|
+
if (content.image !== void 0) {
|
|
282
|
+
const box = { x, y, width: zoneWidth, height: Math.max(32 * scale, Math.min(height * 0.05, 72 * scale)) };
|
|
283
|
+
zoneParts.push({ type: "image", kind: kind2, zone, field: "image", path: `${path}.image`, sourcePath: `${path}.image`, generated: false, image: content.image, box, alignment: zone });
|
|
284
|
+
y += box.height;
|
|
285
|
+
}
|
|
286
|
+
add("text", content.text);
|
|
287
|
+
if (content.organization === true) {
|
|
288
|
+
if (typeof organization.name === "string") add("organization", organization.name, true, organizationPath);
|
|
289
|
+
else error(`${path}.organization`, "Generated organization name needs a named organization in the presentation.", "unresolved-content");
|
|
290
|
+
}
|
|
291
|
+
if (content.section === true) {
|
|
292
|
+
if (typeof slide.section === "string") add("section", slide.section, true, `${sourceRoot}.section`);
|
|
293
|
+
else error(`${path}.section`, "Generated section needs a literal slide section.", "unresolved-content");
|
|
294
|
+
}
|
|
295
|
+
if (content.slideNumber === true) add("slideNumber", String(number), true);
|
|
296
|
+
if (content.date === true) error(`${path}.date`, "Use a literal date string for deterministic header/footer content.", "unresolved-content");
|
|
297
|
+
else if (typeof content.date === "string") add("date", content.date);
|
|
298
|
+
zones.push(zoneParts);
|
|
299
|
+
}
|
|
300
|
+
const tallest = Math.max(0, ...zones.map((zone) => zone.reduce((sum, part) => sum + part.box.height, 0)));
|
|
301
|
+
if (!tallest) continue;
|
|
302
|
+
const top = kind2 === "header" ? height * 0.025 : Math.max(height * 0.025, height - height * 0.04 - tallest);
|
|
303
|
+
if (kind2 === "header") headerBottom = top + tallest;
|
|
304
|
+
else footerTop = top;
|
|
305
|
+
for (const zone of zones) for (const part of zone) {
|
|
306
|
+
part.box.y += top;
|
|
307
|
+
if (part.type === "text" && part.fit.placement) for (const line of part.fit.placement.lines) {
|
|
308
|
+
line.y += top;
|
|
309
|
+
line.baseline += top;
|
|
310
|
+
if (line.outline) line.outline.y += top;
|
|
311
|
+
}
|
|
312
|
+
if (part.box.y + part.box.height > height - height * 0.04 + 0.01) error(part.path, "Repeated header/footer content extends beyond the usable slide height. Change its content or design before pagination.");
|
|
313
|
+
parts.push(part);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (headerBottom > footerTop + 0.01) error(parts.find((part) => part.kind === "footer")?.path ?? sourceRoot, "Header and footer content overlap; repeated content cannot be repaired by splitting body content.");
|
|
317
|
+
return { algorithm: "furniture-flow-v2", configured, textMeasurement: options.textMeasurement ? "provided" : "estimated", textOutlines: outlines ? "provided" : "unavailable", parts, headerBottom, footerTop, diagnostics, overflow: diagnostics.length > 0 };
|
|
318
|
+
}
|
|
151
319
|
var textSegments = new Intl.Segmenter("und", { granularity: "grapheme" });
|
|
152
320
|
function measureText(text, fontSize) {
|
|
153
321
|
let units = 0;
|
|
@@ -1078,7 +1246,11 @@ function composeSlide(input, options = {}) {
|
|
|
1078
1246
|
const fitContent = (field, value, text, box, size, minimum, path2) => field === "text" ? fitPlacedText(field, value, text, box, size, minimum, path2) : field === "items" || field === "bullets" ? fitList(value, box, size, minimum, { style: styleFor(field, path2), textMeasurement: options.textMeasurement }) : fitText(text, box, size, minimum, widthFor(field, path2));
|
|
1079
1247
|
const path = `slides.${options.slideIndex ?? 0}`;
|
|
1080
1248
|
const items = [], diagnostics = [];
|
|
1081
|
-
|
|
1249
|
+
const measuredFurniture = layoutFurniture(slide, options);
|
|
1250
|
+
const furniture = measuredFurniture.configured || measuredFurniture.diagnostics.length ? measuredFurniture : void 0;
|
|
1251
|
+
if (furniture) diagnostics.push(...furniture.diagnostics);
|
|
1252
|
+
const bodyBottom = Math.min(height - padding, furniture && furniture.footerTop < height ? furniture.footerTop - gap * 0.5 : height - padding);
|
|
1253
|
+
let y = Math.max(padding, furniture?.headerBottom ? furniture.headerBottom + gap * 0.5 : padding);
|
|
1082
1254
|
for (const field of ["tag", "title", "subtitle"]) {
|
|
1083
1255
|
if (!slide[field]) continue;
|
|
1084
1256
|
const requested = (field === "title" ? 54 : field === "tag" ? 16 : 25) * scale;
|
|
@@ -1086,11 +1258,12 @@ function composeSlide(input, options = {}) {
|
|
|
1086
1258
|
const box = { x: padding, y, width: width - padding * 2, height: maxHeight };
|
|
1087
1259
|
const text = fitPlacedText(field, slide[field], String(slide[field]), box, requested, minSize, `${path}.${field}`);
|
|
1088
1260
|
box.height = Math.min(maxHeight, Math.max(text.lines.length * text.lineHeight, text.placement?.height ?? 0));
|
|
1261
|
+
if (furniture && box.y + box.height > bodyBottom + 0.01) diagnostics.push({ code: "text-overflow", path: `${path}.${field}`, message: "Repeated furniture leaves too little room for this heading. Change the header/footer or slide design." });
|
|
1089
1262
|
items.push({ path: `${path}.${field}`, field, type: "text", value: slide[field], payload: { text: slide[field] }, box, text, textStyle: styleFor(field, `${path}.${field}`), composition });
|
|
1090
1263
|
y += box.height + gap * 0.5;
|
|
1091
1264
|
}
|
|
1092
1265
|
if (items.length) y += gap * 0.5;
|
|
1093
|
-
const contentBox = { x: padding, y, width: width - padding * 2, height: Math.max(scale,
|
|
1266
|
+
const contentBox = { x: padding, y, width: width - padding * 2, height: Math.max(scale, bodyBottom - y) };
|
|
1094
1267
|
const collect = (host, basePath, depth = 0, ancestors = []) => {
|
|
1095
1268
|
if (Array.isArray(host.blocks)) {
|
|
1096
1269
|
if (depth >= MAX_COMPOSITION_DEPTH || ancestors.includes(host)) throw new RangeError(`Content groups must be acyclic and nest at most ${MAX_COMPOSITION_DEPTH} levels.`);
|
|
@@ -1285,6 +1458,7 @@ function composeSlide(input, options = {}) {
|
|
|
1285
1458
|
for (const group of groups) for (const box of [group.box, group.contentBox]) for (const key of ["x", "y", "width", "height"]) box[key] = round(box[key]);
|
|
1286
1459
|
const strictPaths = new Set(items.filter((item) => item.composition.overflow === "error").map((item) => item.path));
|
|
1287
1460
|
const failures = diagnostics.filter((diagnostic) => {
|
|
1461
|
+
if (composition.overflow === "error") return true;
|
|
1288
1462
|
let path2 = diagnostic.path;
|
|
1289
1463
|
while (path2) {
|
|
1290
1464
|
if (strictPaths.has(path2)) return true;
|
|
@@ -1295,7 +1469,7 @@ function composeSlide(input, options = {}) {
|
|
|
1295
1469
|
return false;
|
|
1296
1470
|
});
|
|
1297
1471
|
const explanation = decisions ? {
|
|
1298
|
-
algorithm: "grid-score-
|
|
1472
|
+
algorithm: "grid-score-v9",
|
|
1299
1473
|
textMeasurement: options.textMeasurement ? "provided" : "estimated",
|
|
1300
1474
|
textOutlines: options.textMeasurement?.outlineBounds ? "provided" : "unavailable",
|
|
1301
1475
|
textRasterPadding: rasterPadding,
|
|
@@ -1303,7 +1477,7 @@ function composeSlide(input, options = {}) {
|
|
|
1303
1477
|
unmeasuredPayloads: items.filter((item) => !headings.has(item.field) && !item.quoteLayout && !item.codeLayout && !item.metricLayout && !item.timelineLayout && !["text", "items", "bullets", "table"].includes(item.field)).map((item) => item.path)
|
|
1304
1478
|
} : void 0;
|
|
1305
1479
|
if (failures.length) throw new OPFCompositionError(failures, explanation);
|
|
1306
|
-
return { width, height, contentBox, items, groups, flows, diagnostics, composition, ...explanation ? { explanation } : {} };
|
|
1480
|
+
return { width, height, contentBox, items, groups, flows, diagnostics, composition, ...furniture ? { furniture } : {}, ...explanation ? { explanation } : {} };
|
|
1307
1481
|
}
|
|
1308
1482
|
function resolveCanvasDimensions(input) {
|
|
1309
1483
|
const presets = {
|
|
@@ -1323,4 +1497,4 @@ function resolveCanvasDimensions(input) {
|
|
|
1323
1497
|
return { width, height };
|
|
1324
1498
|
}
|
|
1325
1499
|
|
|
1326
|
-
export { MAX_COMPOSITION_DEPTH, OPFCompositionError, chartColorForFill, colorContrast, composeSlide, fitList, fitRichText, fitText, layoutCode, 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 };
|