@openpresentation/opf 0.10.1 → 0.11.1
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-DoVmvDr7.d.ts → catalogs-DJ-B5ZyD.d.ts} +79 -9
- package/dist/catalogs.d.ts +2 -2
- package/dist/catalogs.js +1 -1
- package/dist/{chunk-PQJRDNA6.js → chunk-6UPHKXI5.js} +381 -34
- package/dist/{chunk-TU7I3KSB.js → chunk-7LF37SG3.js} +7400 -5422
- package/dist/{chunk-EWJNRHXA.js → chunk-BP6WMSSS.js} +3 -3
- package/dist/{chunk-FHGJX5QK.js → chunk-KWIOQ3QR.js} +73 -32
- package/dist/{chunk-D3GQIREP.js → chunk-LTSDDBNW.js} +558 -52
- package/dist/{chunk-ZIL7MGZU.js → chunk-M4GTWRK7.js} +333 -102
- package/dist/chunk-NPYN4TZ5.js +3516 -0
- package/dist/{chunk-RS5GZ5RW.js → chunk-SDETQV7Y.js} +161 -0
- package/dist/composition-DzLwY-Mi.d.ts +887 -0
- package/dist/composition.d.ts +1 -676
- package/dist/composition.js +1 -1
- package/dist/docs.js +80 -20
- package/dist/examples.d.ts +1 -1
- package/dist/examples.js +11 -11
- package/dist/font-policy.d.ts +123 -0
- package/dist/font-policy.js +1 -0
- package/dist/index.d.ts +184 -4
- package/dist/index.js +473 -7
- package/dist/lint.d.ts +3 -3
- package/dist/lint.js +5 -5
- package/dist/pagination.d.ts +6 -2
- package/dist/pagination.js +5 -5
- package/dist/{presentation-BMTdX6O1.d.ts → presentation-bceTClm8.d.ts} +297 -30
- package/dist/repo-readme.js +1 -1
- package/dist/{schemas-BYe5y8-i.d.ts → schemas-X_NniU4A.d.ts} +8 -0
- package/dist/schemas.d.ts +1 -1
- package/dist/schemas.js +1 -1
- package/dist/spec/catalogs/audiences/academic.json +24 -0
- package/dist/spec/catalogs/audiences/all-hands.json +3 -1
- package/dist/spec/catalogs/audiences/board.json +3 -1
- package/dist/spec/catalogs/audiences/customer.json +25 -0
- package/dist/spec/catalogs/audiences/executive.json +24 -0
- package/dist/spec/catalogs/audiences/general-public.json +25 -0
- package/dist/spec/catalogs/audiences/index.json +73 -1
- package/dist/spec/catalogs/audiences/internal-team.json +25 -0
- package/dist/spec/catalogs/audiences/investor.json +25 -0
- package/dist/spec/catalogs/audiences/marketing.json +25 -0
- package/dist/spec/catalogs/audiences/media.json +24 -0
- package/dist/spec/catalogs/audiences/partner.json +25 -0
- package/dist/spec/catalogs/audiences/regulatory.json +25 -0
- package/dist/spec/catalogs/audiences/sales.json +25 -0
- package/dist/spec/catalogs/audiences/technical.json +25 -0
- package/dist/spec/catalogs/chart-types/100pct-bullet-bar-2x.json +5 -0
- package/dist/spec/catalogs/chart-types/100pct-bullet-bar-3x.json +5 -0
- package/dist/spec/catalogs/chart-types/100pct-bullet-bar.json +5 -0
- package/dist/spec/catalogs/chart-types/100pct-bullet-column-2x.json +5 -0
- package/dist/spec/catalogs/chart-types/100pct-bullet-column-3x.json +5 -0
- package/dist/spec/catalogs/chart-types/100pct-bullet-column.json +5 -0
- package/dist/spec/catalogs/chart-types/100pct-progress-bar.json +10 -0
- package/dist/spec/catalogs/chart-types/100pct-stacked-area-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/100pct-stacked-area-3x.json +6 -1
- package/dist/spec/catalogs/chart-types/100pct-stacked-bar-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/100pct-stacked-bar-3x.json +6 -1
- package/dist/spec/catalogs/chart-types/100pct-stacked-column-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/100pct-stacked-column-3x.json +6 -1
- package/dist/spec/catalogs/chart-types/area.json +5 -0
- package/dist/spec/catalogs/chart-types/australia.json +10 -0
- package/dist/spec/catalogs/chart-types/bar.json +5 -0
- package/dist/spec/catalogs/chart-types/box-and-whisker-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/box-and-whisker-3x.json +10 -0
- package/dist/spec/catalogs/chart-types/box-and-whisker.json +5 -0
- package/dist/spec/catalogs/chart-types/bullet-bar-2x.json +5 -0
- package/dist/spec/catalogs/chart-types/bullet-bar-3x.json +5 -0
- package/dist/spec/catalogs/chart-types/bullet-bar.json +5 -0
- package/dist/spec/catalogs/chart-types/bullet-column-2x.json +5 -0
- package/dist/spec/catalogs/chart-types/bullet-column-3x.json +5 -0
- package/dist/spec/catalogs/chart-types/bullet-column.json +5 -0
- package/dist/spec/catalogs/chart-types/canada.json +10 -0
- package/dist/spec/catalogs/chart-types/clustered-bar-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/clustered-column.json +10 -0
- package/dist/spec/catalogs/chart-types/column.json +5 -0
- package/dist/spec/catalogs/chart-types/dot-plot-2x.json +5 -0
- package/dist/spec/catalogs/chart-types/dot-plot-3x.json +5 -0
- package/dist/spec/catalogs/chart-types/dot-plot-4x.json +5 -0
- package/dist/spec/catalogs/chart-types/dot-plot-5x.json +5 -0
- package/dist/spec/catalogs/chart-types/dot-plot-6x.json +5 -0
- package/dist/spec/catalogs/chart-types/dot-plot.json +5 -0
- package/dist/spec/catalogs/chart-types/doughnut.json +5 -0
- package/dist/spec/catalogs/chart-types/dumbbell.json +5 -0
- package/dist/spec/catalogs/chart-types/filled-radar.json +5 -0
- package/dist/spec/catalogs/chart-types/funnel.json +5 -0
- package/dist/spec/catalogs/chart-types/histogram.json +5 -0
- package/dist/spec/catalogs/chart-types/index.json +333 -233
- package/dist/spec/catalogs/chart-types/line-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/line-3x.json +10 -0
- package/dist/spec/catalogs/chart-types/line-with-high-low-and-markers.json +5 -0
- package/dist/spec/catalogs/chart-types/line-with-high-low.json +5 -0
- package/dist/spec/catalogs/chart-types/line-with-markers-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/line-with-markers-3x.json +10 -0
- package/dist/spec/catalogs/chart-types/line-with-markers.json +5 -0
- package/dist/spec/catalogs/chart-types/line.json +5 -0
- package/dist/spec/catalogs/chart-types/pareto.json +9 -14
- package/dist/spec/catalogs/chart-types/pie.json +5 -0
- package/dist/spec/catalogs/chart-types/radar-with-markers.json +5 -0
- package/dist/spec/catalogs/chart-types/radar.json +5 -0
- package/dist/spec/catalogs/chart-types/scatter.json +5 -0
- package/dist/spec/catalogs/chart-types/sparkline-2x.json +5 -0
- package/dist/spec/catalogs/chart-types/sparkline-3x.json +5 -0
- package/dist/spec/catalogs/chart-types/sparkline-4x.json +5 -0
- package/dist/spec/catalogs/chart-types/sparkline-5x.json +5 -0
- package/dist/spec/catalogs/chart-types/sparkline-6x.json +5 -0
- package/dist/spec/catalogs/chart-types/sparkline.json +5 -0
- package/dist/spec/catalogs/chart-types/stacked-area-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/stacked-area-3x.json +6 -1
- package/dist/spec/catalogs/chart-types/stacked-bar-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/stacked-bar-3x.json +6 -1
- package/dist/spec/catalogs/chart-types/stacked-column-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/stacked-column-3x.json +6 -1
- package/dist/spec/catalogs/chart-types/stacked-line-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/stacked-line-3x.json +6 -1
- package/dist/spec/catalogs/chart-types/stacked-line-with-markers-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/stacked-line-with-markers-3x.json +6 -1
- package/dist/spec/catalogs/chart-types/treemap-2x.json +10 -0
- package/dist/spec/catalogs/chart-types/treemap-3x.json +10 -0
- package/dist/spec/catalogs/chart-types/treemap.json +5 -0
- package/dist/spec/catalogs/chart-types/united-kingdom.json +10 -0
- package/dist/spec/catalogs/chart-types/united-states.json +10 -0
- package/dist/spec/catalogs/chart-types/waterfall.json +5 -0
- package/dist/spec/catalogs/chart-types/world.json +6 -1
- package/dist/spec/catalogs/font-schemes/consolas.json +3 -0
- package/dist/spec/catalogs/font-schemes/courier-new.json +3 -0
- package/dist/spec/catalogs/languages/afrikaans.json +3 -0
- package/dist/spec/catalogs/languages/albanian.json +3 -0
- package/dist/spec/catalogs/languages/amharic.json +3 -0
- package/dist/spec/catalogs/languages/arabic.json +3 -0
- package/dist/spec/catalogs/languages/armenian.json +3 -0
- package/dist/spec/catalogs/languages/aymara.json +3 -0
- package/dist/spec/catalogs/languages/azerbaijani.json +3 -0
- package/dist/spec/catalogs/languages/bengali.json +3 -0
- package/dist/spec/catalogs/languages/berber-latin.json +3 -0
- package/dist/spec/catalogs/languages/bosnian-latin.json +3 -0
- package/dist/spec/catalogs/languages/bulgarian.json +3 -0
- package/dist/spec/catalogs/languages/catalan.json +3 -0
- package/dist/spec/catalogs/languages/cebuano.json +3 -0
- package/dist/spec/catalogs/languages/chinese-simplified.json +3 -0
- package/dist/spec/catalogs/languages/chinese-traditional.json +3 -0
- package/dist/spec/catalogs/languages/chittagonian.json +3 -0
- package/dist/spec/catalogs/languages/croatian.json +3 -0
- package/dist/spec/catalogs/languages/czech.json +3 -0
- package/dist/spec/catalogs/languages/danish.json +3 -0
- package/dist/spec/catalogs/languages/dutch.json +3 -0
- package/dist/spec/catalogs/languages/english-au.json +3 -0
- package/dist/spec/catalogs/languages/english-ca.json +3 -0
- package/dist/spec/catalogs/languages/english-gb.json +3 -0
- package/dist/spec/catalogs/languages/english-in.json +3 -0
- package/dist/spec/catalogs/languages/english-us.json +3 -0
- package/dist/spec/catalogs/languages/english.json +3 -0
- package/dist/spec/catalogs/languages/estonian.json +3 -0
- package/dist/spec/catalogs/languages/filipino.json +3 -0
- package/dist/spec/catalogs/languages/finnish.json +3 -0
- package/dist/spec/catalogs/languages/french.json +3 -0
- package/dist/spec/catalogs/languages/fulfulde.json +3 -0
- package/dist/spec/catalogs/languages/galician.json +3 -0
- package/dist/spec/catalogs/languages/georgian.json +3 -0
- package/dist/spec/catalogs/languages/german.json +3 -0
- package/dist/spec/catalogs/languages/greek.json +3 -0
- package/dist/spec/catalogs/languages/gujarati.json +3 -0
- package/dist/spec/catalogs/languages/hausa.json +3 -0
- package/dist/spec/catalogs/languages/hebrew.json +3 -0
- package/dist/spec/catalogs/languages/hindi.json +3 -0
- package/dist/spec/catalogs/languages/hungarian.json +3 -0
- package/dist/spec/catalogs/languages/igbo.json +3 -0
- package/dist/spec/catalogs/languages/indonesian.json +3 -0
- package/dist/spec/catalogs/languages/italian.json +3 -0
- package/dist/spec/catalogs/languages/japanese.json +3 -0
- package/dist/spec/catalogs/languages/kannada.json +3 -0
- package/dist/spec/catalogs/languages/kazakh.json +3 -0
- package/dist/spec/catalogs/languages/khmer.json +3 -0
- package/dist/spec/catalogs/languages/kinyarwanda.json +3 -0
- package/dist/spec/catalogs/languages/korean.json +3 -0
- package/dist/spec/catalogs/languages/kurmanji.json +3 -0
- package/dist/spec/catalogs/languages/latvian.json +3 -0
- package/dist/spec/catalogs/languages/lithuanian.json +3 -0
- package/dist/spec/catalogs/languages/macedonian.json +3 -0
- package/dist/spec/catalogs/languages/malagasy.json +3 -0
- package/dist/spec/catalogs/languages/malay.json +3 -0
- package/dist/spec/catalogs/languages/malayalam.json +3 -0
- package/dist/spec/catalogs/languages/maori.json +3 -0
- package/dist/spec/catalogs/languages/marathi.json +3 -0
- package/dist/spec/catalogs/languages/mongolian.json +3 -0
- package/dist/spec/catalogs/languages/nepali.json +3 -0
- package/dist/spec/catalogs/languages/norwegian.json +3 -0
- package/dist/spec/catalogs/languages/odia.json +3 -0
- package/dist/spec/catalogs/languages/oromo.json +3 -0
- package/dist/spec/catalogs/languages/pashto.json +3 -0
- package/dist/spec/catalogs/languages/persian.json +3 -0
- package/dist/spec/catalogs/languages/polish.json +3 -0
- package/dist/spec/catalogs/languages/portuguese.json +3 -0
- package/dist/spec/catalogs/languages/punjabi-gurmukhi.json +3 -0
- package/dist/spec/catalogs/languages/punjabi-shahmukhi.json +3 -0
- package/dist/spec/catalogs/languages/romanian.json +3 -0
- package/dist/spec/catalogs/languages/russian.json +3 -0
- package/dist/spec/catalogs/languages/serbian-cyrillic.json +3 -0
- package/dist/spec/catalogs/languages/serbian-latin.json +3 -0
- package/dist/spec/catalogs/languages/shona.json +3 -0
- package/dist/spec/catalogs/languages/slovak.json +3 -0
- package/dist/spec/catalogs/languages/slovenian.json +3 -0
- package/dist/spec/catalogs/languages/somali.json +3 -0
- package/dist/spec/catalogs/languages/spanish.json +3 -0
- package/dist/spec/catalogs/languages/swahili.json +3 -0
- package/dist/spec/catalogs/languages/swedish.json +3 -0
- package/dist/spec/catalogs/languages/tagalog.json +3 -0
- package/dist/spec/catalogs/languages/tajik.json +3 -0
- package/dist/spec/catalogs/languages/tamil.json +3 -0
- package/dist/spec/catalogs/languages/telugu.json +3 -0
- package/dist/spec/catalogs/languages/thai.json +3 -0
- package/dist/spec/catalogs/languages/turkish.json +3 -0
- package/dist/spec/catalogs/languages/ukrainian.json +3 -0
- package/dist/spec/catalogs/languages/urdu.json +3 -0
- package/dist/spec/catalogs/languages/uzbek-latin.json +3 -0
- package/dist/spec/catalogs/languages/vietnamese-quoc-ngu.json +3 -0
- package/dist/spec/catalogs/languages/xhosa.json +3 -0
- package/dist/spec/catalogs/languages/yoruba.json +3 -0
- package/dist/spec/catalogs/languages/zulu.json +3 -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/change-story.json +64 -0
- 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/data-story.json +66 -0
- 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/heros-journey.json +64 -0
- package/dist/spec/catalogs/narratives/index.json +81 -0
- 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/pyramid-principle.json +48 -0
- 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/situation-complication-resolution.json +56 -0
- package/dist/spec/catalogs/narratives/sparkline.json +56 -0
- package/dist/spec/catalogs/narratives/star-method.json +56 -0
- 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/vision-roadmap.json +65 -0
- package/dist/spec/catalogs/narratives/weekly-progress.json +10 -10
- package/dist/spec/catalogs/narratives/what-so-what-now-what.json +48 -0
- package/dist/spec/openapi.yaml +5 -0
- package/dist/spec/reference/engine-defaults.json +2 -2
- package/dist/spec/reference/font-policy.json +3435 -0
- package/dist/spec/reference/font-policy.schema.json +328 -0
- package/dist/spec/schemas/chart-type.schema.json +51 -11
- package/dist/spec/schemas/font-scheme.schema.json +91 -1
- package/dist/spec/schemas/language.schema.json +10 -5
- package/dist/spec/schemas/opf.schema.json +241 -32
- 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 +6 -2
|
@@ -35,7 +35,184 @@ function tableRowBoundaries(value) {
|
|
|
35
35
|
return [...allowed];
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// src/furniture-fields.ts
|
|
39
|
+
var DEFAULT_FURNITURE_DATE_FORMAT = "M/d/yyyy";
|
|
40
|
+
var DEFAULT_SLIDE_NUMBER_FORMAT = "{current}";
|
|
41
|
+
var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
|
42
|
+
var weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
|
43
|
+
var tokenWidths = { y: [1, 2, 4], M: [1, 2, 3, 4], d: [1, 2], E: [1, 2, 3, 4] };
|
|
44
|
+
function parseFurnitureDateFormat(pattern) {
|
|
45
|
+
if (!pattern) return "dateFormat must not be empty.";
|
|
46
|
+
const tokens = [];
|
|
47
|
+
const literal = (text) => {
|
|
48
|
+
const last = tokens[tokens.length - 1];
|
|
49
|
+
if (last?.kind === "literal") last.text += text;
|
|
50
|
+
else tokens.push({ kind: "literal", text });
|
|
51
|
+
};
|
|
52
|
+
for (let index = 0; index < pattern.length; ) {
|
|
53
|
+
const character = pattern.charAt(index);
|
|
54
|
+
if (character === "'") {
|
|
55
|
+
if (pattern[index + 1] === "'") {
|
|
56
|
+
literal("'");
|
|
57
|
+
index += 2;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
let end = index + 1, text = "";
|
|
61
|
+
for (; ; ) {
|
|
62
|
+
if (end >= pattern.length) return "dateFormat has an unterminated quoted literal.";
|
|
63
|
+
if (pattern[end] === "'") {
|
|
64
|
+
if (pattern[end + 1] === "'") {
|
|
65
|
+
text += "'";
|
|
66
|
+
end += 2;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
text += pattern[end];
|
|
72
|
+
end++;
|
|
73
|
+
}
|
|
74
|
+
literal(text);
|
|
75
|
+
index = end + 1;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (/[A-Za-z]/.test(character)) {
|
|
79
|
+
let end = index;
|
|
80
|
+
while (pattern[end] === character) end++;
|
|
81
|
+
const width = end - index;
|
|
82
|
+
if (!tokenWidths[character]?.includes(width)) return `dateFormat token '${pattern.slice(index, end)}' is not supported; use yyyy, yy, MMMM, MMM, MM, M, dd, d, EEEE or EEE, and quote literal letters.`;
|
|
83
|
+
tokens.push({ kind: "field", letter: character, width });
|
|
84
|
+
index = end;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
literal(character);
|
|
88
|
+
index++;
|
|
89
|
+
}
|
|
90
|
+
return tokens;
|
|
91
|
+
}
|
|
92
|
+
function parseIsoDate(value) {
|
|
93
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value);
|
|
94
|
+
if (!match) return null;
|
|
95
|
+
const year = Number(match[1]), month = Number(match[2]), day = Number(match[3]);
|
|
96
|
+
const date = new Date(Date.UTC(2e3, month - 1, day));
|
|
97
|
+
date.setUTCFullYear(year);
|
|
98
|
+
if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) return null;
|
|
99
|
+
return { year, month, day };
|
|
100
|
+
}
|
|
101
|
+
function formatFurnitureDate(iso, pattern) {
|
|
102
|
+
const date = parseIsoDate(iso);
|
|
103
|
+
if (!date) return { error: `'${iso}' is not an ISO YYYY-MM-DD calendar date.` };
|
|
104
|
+
const tokens = parseFurnitureDateFormat(pattern);
|
|
105
|
+
if (typeof tokens === "string") return { error: tokens };
|
|
106
|
+
const utc = new Date(Date.UTC(2e3, date.month - 1, date.day));
|
|
107
|
+
utc.setUTCFullYear(date.year);
|
|
108
|
+
const pad = (value, width) => String(value).padStart(width, "0");
|
|
109
|
+
let text = "";
|
|
110
|
+
for (const token of tokens) {
|
|
111
|
+
if (token.kind === "literal") {
|
|
112
|
+
text += token.text;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const { letter, width } = token;
|
|
116
|
+
if (letter === "y") text += width === 2 ? pad(date.year % 100, 2) : width === 4 ? pad(date.year, 4) : String(date.year);
|
|
117
|
+
else if (letter === "M") {
|
|
118
|
+
const name = months[date.month - 1] ?? "";
|
|
119
|
+
text += width >= 3 ? width === 4 ? name : name.slice(0, 3) : pad(date.month, width);
|
|
120
|
+
} else if (letter === "d") text += pad(date.day, width);
|
|
121
|
+
else {
|
|
122
|
+
const name = weekdays[utc.getUTCDay()] ?? "";
|
|
123
|
+
text += width === 4 ? name : name.slice(0, 3);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return { text };
|
|
127
|
+
}
|
|
128
|
+
function formatSlideNumber(format, current, total) {
|
|
129
|
+
if (!format.includes("{current}")) return { error: "slideNumberFormat must contain {current}." };
|
|
130
|
+
if (format.includes("{total}") && total === void 0) return { error: "slideNumberFormat uses {total}, which needs the rendered slide count." };
|
|
131
|
+
let text = "";
|
|
132
|
+
const fields2 = [];
|
|
133
|
+
for (const piece of format.split(/(\{current\}|\{total\})/)) {
|
|
134
|
+
if (piece === "{current}") {
|
|
135
|
+
const value = String(current);
|
|
136
|
+
fields2.push({ type: "slideNumber", start: text.length, end: text.length + value.length });
|
|
137
|
+
text += value;
|
|
138
|
+
} else if (piece === "{total}") text += String(total);
|
|
139
|
+
else text += piece;
|
|
140
|
+
}
|
|
141
|
+
return { text, fields: fields2 };
|
|
142
|
+
}
|
|
143
|
+
|
|
38
144
|
// src/color.ts
|
|
145
|
+
var schemeColorSlots = /* @__PURE__ */ new Set([
|
|
146
|
+
"accent1",
|
|
147
|
+
"accent2",
|
|
148
|
+
"accent3",
|
|
149
|
+
"accent4",
|
|
150
|
+
"accent5",
|
|
151
|
+
"accent6",
|
|
152
|
+
"dark1",
|
|
153
|
+
"dark2",
|
|
154
|
+
"light1",
|
|
155
|
+
"light2",
|
|
156
|
+
"hyperlink",
|
|
157
|
+
"followedHyperlink"
|
|
158
|
+
]);
|
|
159
|
+
var schemeColorRoles = /* @__PURE__ */ new Set([
|
|
160
|
+
"primary",
|
|
161
|
+
"secondary",
|
|
162
|
+
"accent",
|
|
163
|
+
"background",
|
|
164
|
+
"surface",
|
|
165
|
+
"text",
|
|
166
|
+
"textSecondary"
|
|
167
|
+
]);
|
|
168
|
+
var defaultRoleSlots = {
|
|
169
|
+
primary: "accent1",
|
|
170
|
+
secondary: "accent2",
|
|
171
|
+
accent: "accent3",
|
|
172
|
+
background: "light1",
|
|
173
|
+
surface: "light2",
|
|
174
|
+
text: "dark1",
|
|
175
|
+
textSecondary: "dark2"
|
|
176
|
+
};
|
|
177
|
+
function normalizeHexColor(value) {
|
|
178
|
+
if (typeof value !== "string") return void 0;
|
|
179
|
+
let hex = value.trim();
|
|
180
|
+
if (/^#[0-9a-f]{3}$/i.test(hex)) hex = `#${[...hex.slice(1)].map((char) => char + char).join("")}`;
|
|
181
|
+
if (/^#[0-9a-f]{6}([0-9a-f]{2})?$/i.test(hex)) return hex.length === 9 ? `#${hex.slice(1, 7).toUpperCase()}` : hex.toUpperCase();
|
|
182
|
+
return void 0;
|
|
183
|
+
}
|
|
184
|
+
function schemeSlot(colorScheme, slot, fallback) {
|
|
185
|
+
return normalizeHexColor(colorScheme[slot]) ?? fallback;
|
|
186
|
+
}
|
|
187
|
+
function resolveVariable(variables, id, fallback) {
|
|
188
|
+
const entry = variables[id];
|
|
189
|
+
if (typeof entry === "string") return normalizeHexColor(entry) ?? fallback;
|
|
190
|
+
if (entry && typeof entry === "object" && entry.type === "color") {
|
|
191
|
+
return normalizeHexColor(entry.value) ?? fallback;
|
|
192
|
+
}
|
|
193
|
+
return fallback;
|
|
194
|
+
}
|
|
195
|
+
function resolveColorRef(reference, options) {
|
|
196
|
+
const { colorScheme, roles, variables = {}, fallback } = options;
|
|
197
|
+
const literal = normalizeHexColor(reference);
|
|
198
|
+
if (literal) return literal;
|
|
199
|
+
if (reference.startsWith("var:")) {
|
|
200
|
+
const id = reference.slice("var:".length);
|
|
201
|
+
if (/^[a-z][a-z0-9-]*$/.test(id)) return resolveVariable(variables, id, fallback);
|
|
202
|
+
return fallback;
|
|
203
|
+
}
|
|
204
|
+
if (schemeColorRoles.has(reference)) {
|
|
205
|
+
const roleKey = reference;
|
|
206
|
+
const fromRoles = roles?.[roleKey];
|
|
207
|
+
if (fromRoles) return normalizeHexColor(fromRoles) ?? fallback;
|
|
208
|
+
const fromScheme = normalizeHexColor(colorScheme[reference]);
|
|
209
|
+
if (fromScheme) return fromScheme;
|
|
210
|
+
const slot = defaultRoleSlots[reference];
|
|
211
|
+
return slot ? schemeSlot(colorScheme, slot, fallback) : fallback;
|
|
212
|
+
}
|
|
213
|
+
if (schemeColorSlots.has(reference)) return schemeSlot(colorScheme, reference, fallback);
|
|
214
|
+
return fallback;
|
|
215
|
+
}
|
|
39
216
|
function luminance(value) {
|
|
40
217
|
if (typeof value !== "string") return void 0;
|
|
41
218
|
let hex = value.trim();
|
|
@@ -76,13 +253,25 @@ function chartColorForFill(fill, preferred) {
|
|
|
76
253
|
|
|
77
254
|
// src/composition.ts
|
|
78
255
|
var MAX_COMPOSITION_DEPTH = 32;
|
|
256
|
+
var FALLBACK_CODE_FAMILY = "Roboto Mono";
|
|
257
|
+
var DEFAULT_FONT_SCHEME = "aptos";
|
|
258
|
+
var DEFAULT_FONT_FAMILIES = { heading: "Aptos Display", body: "Aptos" };
|
|
259
|
+
function resolveFontSchemeReference(reference, lookup, path = "design.fontScheme") {
|
|
260
|
+
const overrides = typeof reference === "object" && reference !== null && !Array.isArray(reference) ? reference : void 0;
|
|
261
|
+
const id = typeof reference === "string" ? reference : typeof overrides?.id === "string" ? overrides.id : void 0;
|
|
262
|
+
const found = id === void 0 ? void 0 : lookup(id);
|
|
263
|
+
const base = record2(found ?? lookup(DEFAULT_FONT_SCHEME));
|
|
264
|
+
const scheme = overrides ? { ...base, ...overrides } : { ...base };
|
|
265
|
+
if (id === void 0 || found !== void 0) return { scheme };
|
|
266
|
+
return { scheme, diagnostic: { code: "unresolved-font-scheme", path, id, fallback: DEFAULT_FONT_SCHEME, message: `Font scheme '${id}' is not in the inline or bundled catalogs; using the default font scheme '${DEFAULT_FONT_SCHEME}'.` } };
|
|
267
|
+
}
|
|
79
268
|
function resolveFontFamilies(input) {
|
|
80
269
|
const scheme = record2(input);
|
|
81
270
|
const family = (value) => typeof value === "string" ? value : record2(value).family;
|
|
82
271
|
return {
|
|
83
|
-
heading: family(scheme.heading) ?? scheme.major ?? scheme.minor ??
|
|
84
|
-
body: family(scheme.body) ?? scheme.minor ?? scheme.major ??
|
|
85
|
-
code: family(scheme.code) ??
|
|
272
|
+
heading: family(scheme.heading) ?? scheme.major ?? scheme.minor ?? DEFAULT_FONT_FAMILIES.heading,
|
|
273
|
+
body: family(scheme.body) ?? scheme.minor ?? scheme.major ?? DEFAULT_FONT_FAMILIES.body,
|
|
274
|
+
code: family(scheme.code) ?? FALLBACK_CODE_FAMILY
|
|
86
275
|
};
|
|
87
276
|
}
|
|
88
277
|
function resolveTextStyle(style, measurement) {
|
|
@@ -148,6 +337,106 @@ var columns = ["left", "center", "right"];
|
|
|
148
337
|
var record2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
149
338
|
var kind = (field) => field === "items" ? "list" : field === "bullets" ? "text" : field;
|
|
150
339
|
var round = (value) => Math.round(value * 1e6) / 1e6 || value;
|
|
340
|
+
var SLIDE_IMAGE_POSITIONS = ["background", "top", "bottom", "left", "right"];
|
|
341
|
+
var SLIDE_IMAGE_BAND = 0.5;
|
|
342
|
+
var assetSource = (value) => typeof value === "string" ? value : record2(value).src;
|
|
343
|
+
var finite = (value, min, max) => typeof value === "number" && Number.isFinite(value) && value >= min && value <= max ? value : void 0;
|
|
344
|
+
var pathNumber = (value) => String(round(value));
|
|
345
|
+
var SLIDE_IMAGE_SHAPES = { rectangle: "rect", rounded: "roundRect", circle: "ellipse", hexagon: "hexagon" };
|
|
346
|
+
function slideImageShape(kind2, box, cornerRadius = 1 / 6) {
|
|
347
|
+
const { x, y, width: w, height: h } = box, r = x + w, b = y + h, ss = Math.min(w, h), n = pathNumber;
|
|
348
|
+
const rect = `M${n(x)} ${n(y)}H${n(r)}V${n(b)}H${n(x)}Z`;
|
|
349
|
+
if (kind2 === "rounded") {
|
|
350
|
+
const adj = Math.round(Math.min(0.5, Math.max(0, cornerRadius)) * 1e5), radius = ss * adj / 1e5;
|
|
351
|
+
const path = radius <= 0 ? rect : `M${n(x)} ${n(y + radius)}A${n(radius)} ${n(radius)} 0 0 1 ${n(x + radius)} ${n(y)}H${n(r - radius)}A${n(radius)} ${n(radius)} 0 0 1 ${n(r)} ${n(y + radius)}V${n(b - radius)}A${n(radius)} ${n(radius)} 0 0 1 ${n(r - radius)} ${n(b)}H${n(x + radius)}A${n(radius)} ${n(radius)} 0 0 1 ${n(x)} ${n(b - radius)}Z`;
|
|
352
|
+
return { kind: kind2, preset: "roundRect", adjust: { adj }, path };
|
|
353
|
+
}
|
|
354
|
+
if (kind2 === "circle") {
|
|
355
|
+
const cy = y + h / 2;
|
|
356
|
+
return { kind: kind2, preset: "ellipse", adjust: {}, path: `M${n(x)} ${n(cy)}A${n(w / 2)} ${n(h / 2)} 0 1 1 ${n(r)} ${n(cy)}A${n(w / 2)} ${n(h / 2)} 0 1 1 ${n(x)} ${n(cy)}Z` };
|
|
357
|
+
}
|
|
358
|
+
if (kind2 === "hexagon") {
|
|
359
|
+
const adj = 25e3, vf = 115470, a = Math.min(Math.max(adj, 0), 5e4 * w / ss);
|
|
360
|
+
const x1 = ss * a / 1e5, x2 = r - x1, vc = y + h / 2, dy1 = h / 2 * vf / 1e5 * Math.sin(Math.PI / 3);
|
|
361
|
+
return { kind: kind2, preset: "hexagon", adjust: { adj, vf }, path: `M${n(x)} ${n(vc)}L${n(x + x1)} ${n(vc - dy1)}L${n(x2)} ${n(vc - dy1)}L${n(r)} ${n(vc)}L${n(x2)} ${n(vc + dy1)}L${n(x + x1)} ${n(vc + dy1)}Z` };
|
|
362
|
+
}
|
|
363
|
+
return { kind: "rectangle", preset: "rect", adjust: {}, path: rect };
|
|
364
|
+
}
|
|
365
|
+
function resolveSlideImage(slide, layout, presentation, width, height, path, padding, scale, diagnostics) {
|
|
366
|
+
const own = record2(slide.design), deck = record2(record2(presentation).design);
|
|
367
|
+
const local = own.slideImage !== void 0;
|
|
368
|
+
const configured = local ? own.slideImage : deck.slideImage;
|
|
369
|
+
if (!configured || typeof configured !== "object" && typeof configured !== "string") return void 0;
|
|
370
|
+
const treatment = typeof configured === "object" && !Array.isArray(configured) && "position" in configured ? record2(configured) : void 0;
|
|
371
|
+
const alignment = typeof layout.slideImageAlignment === "string" ? layout.slideImageAlignment.toLowerCase() : void 0;
|
|
372
|
+
const position = treatment ? treatment.position : SLIDE_IMAGE_POSITIONS.find((value2) => value2 === alignment) ?? "background";
|
|
373
|
+
if (!SLIDE_IMAGE_POSITIONS.includes(position)) return void 0;
|
|
374
|
+
const designSource = treatment ? treatment.src : configured;
|
|
375
|
+
const root = slide.image, sameSource = root !== void 0 && designSource !== void 0 && assetSource(root) === assetSource(designSource);
|
|
376
|
+
if (!local && layout.slideImage !== true && !sameSource) return void 0;
|
|
377
|
+
const replacesContent = root !== void 0 && (designSource === void 0 || sameSource);
|
|
378
|
+
const value = replacesContent ? root : designSource;
|
|
379
|
+
const source = assetSource(value);
|
|
380
|
+
if (typeof source !== "string" || !source) return void 0;
|
|
381
|
+
const t = treatment ?? {};
|
|
382
|
+
const fill = t.fill === "crop" || t.fill === "fit" ? t.fill : (own.imageFill ?? deck.imageFill) === "fit" ? "fit" : "crop";
|
|
383
|
+
const share = finite(t.size, 0.1, 0.9) ?? SLIDE_IMAGE_BAND;
|
|
384
|
+
const band = { width: round(width * share), height: round(height * share) };
|
|
385
|
+
const region = position === "left" ? { x: 0, y: 0, width: band.width, height } : position === "right" ? { x: round(width - band.width), y: 0, width: band.width, height } : position === "top" ? { x: 0, y: 0, width, height: band.height } : position === "bottom" ? { x: 0, y: round(height - band.height), width, height: band.height } : { x: 0, y: 0, width, height };
|
|
386
|
+
const designPath = local ? `${path}.design.slideImage` : "design.slideImage";
|
|
387
|
+
const kind2 = Object.hasOwn(SLIDE_IMAGE_SHAPES, t.shape) ? t.shape : "rectangle";
|
|
388
|
+
let box = t.inset === true ? { x: region.x + padding, y: region.y + padding, width: Math.max(scale, region.width - 2 * padding), height: Math.max(scale, region.height - 2 * padding) } : { ...region };
|
|
389
|
+
const aspect = kind2 === "circle" ? 1 : finite(t.aspectRatio, Number.MIN_VALUE, 10);
|
|
390
|
+
if (aspect) {
|
|
391
|
+
const frameWidth = Math.min(box.width, box.height * aspect), frameHeight = frameWidth / aspect;
|
|
392
|
+
box = { x: box.x + (box.width - frameWidth) / 2, y: box.y + (box.height - frameHeight) / 2, width: frameWidth, height: frameHeight };
|
|
393
|
+
}
|
|
394
|
+
box = { x: round(box.x), y: round(box.y), width: round(box.width), height: round(box.height) };
|
|
395
|
+
const result = {
|
|
396
|
+
path: designPath,
|
|
397
|
+
sourcePath: replacesContent ? `${path}.image` : designPath,
|
|
398
|
+
value,
|
|
399
|
+
position,
|
|
400
|
+
fill,
|
|
401
|
+
region,
|
|
402
|
+
box,
|
|
403
|
+
replacesContent,
|
|
404
|
+
shape: slideImageShape(kind2, box, finite(t.cornerRadius, 0, 0.5))
|
|
405
|
+
};
|
|
406
|
+
if (typeof t.alt === "string") result.alt = t.alt;
|
|
407
|
+
const border = record2(t.border), borderWidth = finite(border.width, 0, 64);
|
|
408
|
+
if (border.color !== void 0 && borderWidth) result.border = { color: border.color, width: round(borderWidth * scale) };
|
|
409
|
+
const opacity = finite(t.opacity, 0, 1);
|
|
410
|
+
if (opacity !== void 0 && opacity < 1) result.opacity = opacity;
|
|
411
|
+
if (t.recolor === "grayscale") result.recolor = { type: "grayscale" };
|
|
412
|
+
else if (record2(t.recolor).dark !== void 0 && record2(t.recolor).light !== void 0) result.recolor = { type: "duotone", dark: t.recolor.dark, light: t.recolor.light };
|
|
413
|
+
const overlay = record2(t.overlay), overlayOpacity = finite(overlay.opacity, 0, 1);
|
|
414
|
+
if (overlay.color !== void 0 && overlayOpacity !== void 0) {
|
|
415
|
+
const edge = ["top", "bottom", "left", "right"].includes(overlay.edge) ? overlay.edge : void 0;
|
|
416
|
+
if (edge && kind2 !== "rectangle") diagnostics.push({ code: "unsupported-image-treatment", path: `${designPath}.overlay.edge`, message: "An edge overlay needs a rectangle frame; a band cannot follow a rounded, circular or hexagonal mask as one native shape. Remove edge or use shape rectangle." });
|
|
417
|
+
else {
|
|
418
|
+
const part = finite(overlay.size, 0.05, 1) ?? 0.3;
|
|
419
|
+
const bandBox = !edge ? box : edge === "top" ? { ...box, height: round(box.height * part) } : edge === "bottom" ? { ...box, y: round(box.y + box.height * (1 - part)), height: round(box.height * part) } : edge === "left" ? { ...box, width: round(box.width * part) } : { ...box, x: round(box.x + box.width * (1 - part)), width: round(box.width * part) };
|
|
420
|
+
result.overlay = { color: overlay.color, opacity: overlayOpacity, box: bandBox, shape: edge ? slideImageShape("rectangle", bandBox) : result.shape };
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return result;
|
|
424
|
+
}
|
|
425
|
+
var webUrl = /^https?:\/\/\S+$/i;
|
|
426
|
+
function resolveSocialProfile(platform, value, records = [], owner = "organization") {
|
|
427
|
+
const raw = String(value).trim().replace(/\s+/gu, " ");
|
|
428
|
+
const display = (url2) => url2.replace(/^https:\/\//i, "");
|
|
429
|
+
if (webUrl.test(raw)) return { text: display(raw), href: raw, resolved: false };
|
|
430
|
+
const platformRecord = records.find((item) => item?.id === platform);
|
|
431
|
+
const base = typeof platformRecord?.baseUrl === "string" && webUrl.test(platformRecord.baseUrl) ? `${platformRecord.baseUrl.replace(/\/+$/u, "")}/{handle}` : void 0;
|
|
432
|
+
const pattern = (owner === "organization" ? platformRecord?.companyUrlPattern : void 0) ?? platformRecord?.profileUrlPattern ?? base;
|
|
433
|
+
const prefix = platformRecord?.handlePrefix ?? "";
|
|
434
|
+
const handle = prefix && raw.startsWith(prefix) ? raw.slice(prefix.length) : raw;
|
|
435
|
+
if (!handle || typeof pattern !== "string" || !pattern.includes("{handle}")) return { text: raw, resolved: false };
|
|
436
|
+
const url = pattern.split("{handle}").join(handle);
|
|
437
|
+
if (!webUrl.test(url)) return { text: raw, resolved: false };
|
|
438
|
+
return { text: display(url), href: encodeURI(url), resolved: true };
|
|
439
|
+
}
|
|
151
440
|
function layoutFurniture(input, options = {}) {
|
|
152
441
|
const slide = record2(input), width = options.width ?? 1280, height = options.height ?? 720, scale = Math.min(width, height) / 720;
|
|
153
442
|
const settings = { ...record2(record2(options.layout).composition), ...record2(slide.composition) };
|
|
@@ -156,10 +445,14 @@ function layoutFurniture(input, options = {}) {
|
|
|
156
445
|
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.");
|
|
157
446
|
const number = options.slideNumber ?? (options.slideIndex ?? 0) + 1;
|
|
158
447
|
if (!Number.isSafeInteger(number) || number < 1) throw new RangeError("Displayed slide number must be a positive safe integer.");
|
|
448
|
+
const presentationSlides = options.presentation?.slides, slideCount = options.slideCount ?? (Array.isArray(presentationSlides) && presentationSlides.length ? presentationSlides.length : void 0);
|
|
449
|
+
if (slideCount !== void 0 && (!Number.isSafeInteger(slideCount) || slideCount < 1)) throw new RangeError("Displayed slide count must be a positive safe integer.");
|
|
450
|
+
if (options.date !== void 0 && (typeof options.date !== "string" || !parseIsoDate(options.date))) throw new RangeError("The furniture date option must be an ISO YYYY-MM-DD calendar date.");
|
|
159
451
|
const outlines = options.textMeasurement?.outlineBounds !== void 0, parts = [], diagnostics = [];
|
|
160
452
|
const sourceRoot = `slides.${options.slideIndex ?? 0}`, organizations = Array.isArray(options.presentation?.organization) ? options.presentation.organization : [options.presentation?.organization];
|
|
161
453
|
const primaryIndex = organizations.findIndex((item) => record2(item).role === "primary"), organizationIndex = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
|
|
162
|
-
const organization = record2(organizations[organizationIndex]),
|
|
454
|
+
const organization = record2(organizations[organizationIndex]), organizationRoot = Array.isArray(options.presentation?.organization) ? `organization.${organizationIndex}` : "organization", organizationPath = `${organizationRoot}.name`;
|
|
455
|
+
const inlinePlatforms = record2(record2(options.presentation?.catalogs).socialPlatforms).records, platformRecords = [...Array.isArray(inlinePlatforms) ? inlinePlatforms : [], ...options.socialPlatforms ?? []];
|
|
163
456
|
const fontFamily = options.fonts?.body ?? "sans-serif";
|
|
164
457
|
let headerBottom = 0, footerTop = height, configured = false;
|
|
165
458
|
const error = (path, message, code = "text-overflow") => diagnostics.push({ code, path, message });
|
|
@@ -173,7 +466,7 @@ function layoutFurniture(input, options = {}) {
|
|
|
173
466
|
for (const [index, zone] of ["left", "center", "right"].entries()) {
|
|
174
467
|
const content = record2(record2(value)[zone]), path = `${root}.${zone}`, x = width * (0.07 + index * 0.3), zoneWidth = width * 0.26, zoneParts = [];
|
|
175
468
|
let y = 0;
|
|
176
|
-
const add = (field, text, generated = false, sourcePath) => {
|
|
469
|
+
const add = (field, text, generated = false, sourcePath, extras = {}) => {
|
|
177
470
|
if (text === void 0) return;
|
|
178
471
|
if (typeof text !== "string") throw new TypeError(`Furniture field ${path}.${field} requires string content.`);
|
|
179
472
|
const partPath = `${path}.${field}`, style = resolveTextStyle({ fontFamily, fontWeight: 400, italic: false, path: partPath }, options.textMeasurement);
|
|
@@ -203,7 +496,7 @@ function layoutFurniture(input, options = {}) {
|
|
|
203
496
|
if (!Number.isFinite(partHeight)) throw new RangeError("Furniture exceeds finite layout coordinates.");
|
|
204
497
|
const box = { x, y, width: zoneWidth, height: Math.max(scale, partHeight) }, placement = outlines ? placeTextLines(ink, box, zone, padding) : void 0;
|
|
205
498
|
const accepted = { ...fit, ...placement ? { placement } : {}, overflow: fit.overflow || !!placement?.overflow };
|
|
206
|
-
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 });
|
|
499
|
+
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, ...extras.fields?.length ? { fields: extras.fields } : {}, ...extras.links?.length ? { links: extras.links } : {} });
|
|
207
500
|
if (accepted.overflow) error(partPath, "Repeated text exceeds its zone at the selected readability floor; change the furniture or slide design.");
|
|
208
501
|
y += box.height;
|
|
209
502
|
};
|
|
@@ -217,13 +510,37 @@ function layoutFurniture(input, options = {}) {
|
|
|
217
510
|
if (typeof organization.name === "string") add("organization", organization.name, true, organizationPath);
|
|
218
511
|
else error(`${path}.organization`, "Generated organization name needs a named organization in the presentation.", "unresolved-content");
|
|
219
512
|
}
|
|
513
|
+
if (content.socials === true) {
|
|
514
|
+
const links = Object.entries(record2(organization.socials)).filter(([, value2]) => typeof value2 === "string" && value2.trim()).map(([platform, value2]) => ({ platform, sourcePath: `${organizationRoot}.socials.${platform}`, ...resolveSocialProfile(platform, value2, platformRecords, "organization") }));
|
|
515
|
+
if (links.length) add("socials", links.map((link) => link.text).join("\n"), true, `${organizationRoot}.socials`, { links });
|
|
516
|
+
else error(`${path}.socials`, "Generated social profiles need a primary organization with socials.", "unresolved-content");
|
|
517
|
+
}
|
|
220
518
|
if (content.section === true) {
|
|
221
519
|
if (typeof slide.section === "string") add("section", slide.section, true, `${sourceRoot}.section`);
|
|
222
520
|
else error(`${path}.section`, "Generated section needs a literal slide section.", "unresolved-content");
|
|
223
521
|
}
|
|
224
|
-
|
|
225
|
-
if (content.
|
|
226
|
-
|
|
522
|
+
for (const setting of ["slideNumberFormat", "dateFormat"]) if (content[setting] !== void 0 && typeof content[setting] !== "string") throw new TypeError(`Furniture setting ${path}.${setting} requires a string.`);
|
|
523
|
+
if (content.slideNumber === true) {
|
|
524
|
+
const resolved = formatSlideNumber(content.slideNumberFormat ?? DEFAULT_SLIDE_NUMBER_FORMAT, number, slideCount);
|
|
525
|
+
if ("error" in resolved) error(`${path}.slideNumberFormat`, resolved.error, "unresolved-content");
|
|
526
|
+
else add("slideNumber", resolved.text, true, void 0, { fields: resolved.fields });
|
|
527
|
+
}
|
|
528
|
+
if (content.date === true) {
|
|
529
|
+
const format = content.dateFormat ?? DEFAULT_FURNITURE_DATE_FORMAT;
|
|
530
|
+
if (options.date === void 0) error(`${path}.date`, "A current date needs a host-supplied ISO date option. For fixed content use a literal date, or an ISO date with dateFormat.", "unresolved-content");
|
|
531
|
+
else {
|
|
532
|
+
const resolved = formatFurnitureDate(options.date, format);
|
|
533
|
+
if ("error" in resolved) error(`${path}.dateFormat`, resolved.error, "unresolved-content");
|
|
534
|
+
else add("date", resolved.text, true, void 0, { fields: [{ type: "date", start: 0, end: resolved.text.length, format }] });
|
|
535
|
+
}
|
|
536
|
+
} else if (typeof content.date === "string") {
|
|
537
|
+
if (content.dateFormat === void 0) add("date", content.date);
|
|
538
|
+
else {
|
|
539
|
+
const resolved = formatFurnitureDate(content.date, content.dateFormat);
|
|
540
|
+
if ("error" in resolved) error(`${path}.${parseIsoDate(content.date) ? "dateFormat" : "date"}`, resolved.error, "unresolved-content");
|
|
541
|
+
else add("date", resolved.text, true, `${path}.date`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
227
544
|
zones.push(zoneParts);
|
|
228
545
|
}
|
|
229
546
|
const tallest = Math.max(0, ...zones.map((zone) => zone.reduce((sum, part) => sum + part.box.height, 0)));
|
|
@@ -860,9 +1177,24 @@ function richTextLayouter(input, box, requestedSize, options) {
|
|
|
860
1177
|
const text = whole.slice(a, b), normalSize = (entry.run.fontSize !== void 0 ? entry.run.fontSize * 4 / 3 : requestedSize) * ratio;
|
|
861
1178
|
const script = entry.run.superscript || entry.run.subscript;
|
|
862
1179
|
const size = normalSize * (script ? 0.7 : 1), baselineShift = entry.run.superscript ? -normalSize * 0.35 : entry.run.subscript ? normalSize * 0.2 : 0;
|
|
863
|
-
const
|
|
864
|
-
|
|
865
|
-
|
|
1180
|
+
const measure = textWidthMeasurer(entry.style, options.textMeasurement);
|
|
1181
|
+
let cursor = 0;
|
|
1182
|
+
for (const [index, segment] of text.split(" ").entries()) {
|
|
1183
|
+
if (index) {
|
|
1184
|
+
const tabStart = a + cursor, tabWidth = measure(" ", size) * 4;
|
|
1185
|
+
if (!Number.isFinite(tabWidth) || tabWidth <= 0) throw new RangeError("Rich text tabs require a positive finite measured space advance.");
|
|
1186
|
+
const next = (Math.floor(x / tabWidth + 1e-9) + 1) * tabWidth;
|
|
1187
|
+
result.push({ kind: "tab", text: " ", runIndex: entry.runIndex, start: tabStart - entry.start, end: tabStart - entry.start + 1, x, width: next - x, fontSize: size, baselineShift, style: entry.style, run: entry.run });
|
|
1188
|
+
x = next;
|
|
1189
|
+
cursor++;
|
|
1190
|
+
}
|
|
1191
|
+
if (segment) {
|
|
1192
|
+
const width2 = measure(segment, size), segmentStart = a + cursor;
|
|
1193
|
+
result.push({ text: segment, runIndex: entry.runIndex, start: segmentStart - entry.start, end: segmentStart - entry.start + segment.length, x, width: width2, fontSize: size, baselineShift, style: entry.style, run: entry.run });
|
|
1194
|
+
x += width2;
|
|
1195
|
+
cursor += segment.length;
|
|
1196
|
+
}
|
|
1197
|
+
}
|
|
866
1198
|
}
|
|
867
1199
|
return result;
|
|
868
1200
|
};
|
|
@@ -1117,6 +1449,7 @@ function composeSlide(input, options = {}) {
|
|
|
1117
1449
|
const minSize = (composition.minFontSize ?? 16) * scale;
|
|
1118
1450
|
const rasterPadding = (options.textRasterPadding ?? 1) * scale;
|
|
1119
1451
|
if (!Number.isFinite(rasterPadding) || rasterPadding < 0) throw new RangeError("Text raster padding must be finite and nonnegative.");
|
|
1452
|
+
const alignmentFor = (field) => (field === "title" ? record2(slide.design).titleAlignment ?? options.titleAlignment : record2(slide.design).contentAlignment ?? options.contentAlignment) ?? "left";
|
|
1120
1453
|
const styleFor = (field, path2) => resolveTextStyle({
|
|
1121
1454
|
fontFamily: (field === "title" ? options.fonts?.heading : field === "code" ? options.fonts?.code : options.fonts?.body) ?? (field === "code" ? "monospace" : "sans-serif"),
|
|
1122
1455
|
fontWeight: field === "title" ? 700 : 400,
|
|
@@ -1126,7 +1459,7 @@ function composeSlide(input, options = {}) {
|
|
|
1126
1459
|
const fitPlacedText = (field, value, text, box, size, minimum, path2) => {
|
|
1127
1460
|
const style = styleFor(field, path2), rich = field === "text" && Array.isArray(value);
|
|
1128
1461
|
if (!options.textMeasurement?.outlineBounds) return rich ? fitRichText(value, box, size, minimum, { style, textMeasurement: options.textMeasurement }) : fitText(text, box, size, minimum, textWidthMeasurer(style, options.textMeasurement));
|
|
1129
|
-
const alignment = (field
|
|
1462
|
+
const alignment = alignmentFor(field);
|
|
1130
1463
|
const richLayout = rich ? richTextLayouter(value, box, size, { style, textMeasurement: options.textMeasurement }) : void 0;
|
|
1131
1464
|
const measure = textWidthMeasurer(style, options.textMeasurement), floor = rich ? richMinimum(value, size, minimum) : minimum, start = Math.max(size, floor);
|
|
1132
1465
|
for (let trial = 0; trial <= 64; trial++) {
|
|
@@ -1136,6 +1469,7 @@ function composeSlide(input, options = {}) {
|
|
|
1136
1469
|
const lines = richLines ? richLines.map((line) => {
|
|
1137
1470
|
let outline = null;
|
|
1138
1471
|
for (const fragment of line.fragments) {
|
|
1472
|
+
if (fragment.kind === "tab") continue;
|
|
1139
1473
|
const bounds = measureTextOutline(fragment.text, fragment.fontSize, fragment.style, options.textMeasurement);
|
|
1140
1474
|
if (!bounds) continue;
|
|
1141
1475
|
const next = { ...bounds, x: fragment.x + bounds.x, y: fragment.baselineShift + bounds.y };
|
|
@@ -1174,25 +1508,32 @@ function composeSlide(input, options = {}) {
|
|
|
1174
1508
|
};
|
|
1175
1509
|
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));
|
|
1176
1510
|
const path = `slides.${options.slideIndex ?? 0}`;
|
|
1511
|
+
const slideImageDiagnostics = [];
|
|
1512
|
+
const slideImage = resolveSlideImage(slide, layout, options.presentation, width, height, path, padding, scale, slideImageDiagnostics);
|
|
1513
|
+
const area = { left: 0, top: 0, right: width, bottom: height };
|
|
1514
|
+
if (slideImage?.position === "left") area.left = slideImage.region.width;
|
|
1515
|
+
else if (slideImage?.position === "right") area.right = slideImage.region.x;
|
|
1516
|
+
else if (slideImage?.position === "top") area.top = slideImage.region.height;
|
|
1517
|
+
else if (slideImage?.position === "bottom") area.bottom = slideImage.region.y;
|
|
1177
1518
|
const items = [], diagnostics = [];
|
|
1178
1519
|
const measuredFurniture = layoutFurniture(slide, options);
|
|
1179
1520
|
const furniture = measuredFurniture.configured || measuredFurniture.diagnostics.length ? measuredFurniture : void 0;
|
|
1180
1521
|
if (furniture) diagnostics.push(...furniture.diagnostics);
|
|
1181
|
-
const bodyBottom = Math.min(
|
|
1182
|
-
let y = Math.max(padding, furniture?.headerBottom ? furniture.headerBottom + gap * 0.5 : padding);
|
|
1522
|
+
const bodyBottom = Math.min(area.bottom - padding, furniture && furniture.footerTop < height ? furniture.footerTop - gap * 0.5 : height - padding);
|
|
1523
|
+
let y = Math.max(area.top + padding, furniture?.headerBottom ? furniture.headerBottom + gap * 0.5 : padding);
|
|
1183
1524
|
for (const field of ["tag", "title", "subtitle"]) {
|
|
1184
1525
|
if (!slide[field]) continue;
|
|
1185
1526
|
const requested = (field === "title" ? 54 : field === "tag" ? 16 : 25) * scale;
|
|
1186
1527
|
const maxHeight = Math.max(height * (field === "title" ? 0.26 : field === "subtitle" ? 0.12 : 0.045), minSize * 1.22 + 2 * rasterPadding);
|
|
1187
|
-
const box = { x: padding, y, width:
|
|
1528
|
+
const box = { x: area.left + padding, y, width: area.right - area.left - padding * 2, height: maxHeight };
|
|
1188
1529
|
const text = fitPlacedText(field, slide[field], String(slide[field]), box, requested, minSize, `${path}.${field}`);
|
|
1189
1530
|
box.height = Math.min(maxHeight, Math.max(text.lines.length * text.lineHeight, text.placement?.height ?? 0));
|
|
1190
1531
|
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." });
|
|
1191
|
-
items.push({ path: `${path}.${field}`, field, type: "text", value: slide[field], payload: { text: slide[field] }, box, text, textStyle: styleFor(field, `${path}.${field}`), composition });
|
|
1532
|
+
items.push({ path: `${path}.${field}`, field, type: "text", value: slide[field], payload: { text: slide[field] }, box, text, textStyle: styleFor(field, `${path}.${field}`), composition, alignment: alignmentFor(field) });
|
|
1192
1533
|
y += box.height + gap * 0.5;
|
|
1193
1534
|
}
|
|
1194
1535
|
if (items.length) y += gap * 0.5;
|
|
1195
|
-
const contentBox = { x: padding, y, width:
|
|
1536
|
+
const contentBox = { x: area.left + padding, y, width: area.right - area.left - padding * 2, height: Math.max(scale, bodyBottom - y) };
|
|
1196
1537
|
const collect = (host, basePath, depth = 0, ancestors = []) => {
|
|
1197
1538
|
if (Array.isArray(host.blocks)) {
|
|
1198
1539
|
if (depth >= MAX_COMPOSITION_DEPTH || ancestors.includes(host)) throw new RangeError(`Content groups must be acyclic and nest at most ${MAX_COMPOSITION_DEPTH} levels.`);
|
|
@@ -1211,7 +1552,7 @@ function composeSlide(input, options = {}) {
|
|
|
1211
1552
|
return fields.filter((field) => host[field] !== void 0).map((field) => ({ field, type: host.type ?? kind(field), value: host[field], path: `${basePath}.${field}`, payload: { type: host.type ?? kind(field), [field]: host[field] } }));
|
|
1212
1553
|
};
|
|
1213
1554
|
const regions = Object.keys(slide).filter((key) => regionParts(key)).sort();
|
|
1214
|
-
const pending = regions.length ? regions.flatMap((key) => collect(record2(slide[key]), `${path}.${key}`).map((item) => ({ ...item, region: regionParts(key) }))) : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => collect(record2(block), `${path}.blocks.${index}`)) : collect(slide, path);
|
|
1555
|
+
const pending = regions.length ? regions.flatMap((key) => collect(record2(slide[key]), `${path}.${key}`).map((item) => ({ ...item, region: regionParts(key) }))) : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => collect(record2(block), `${path}.blocks.${index}`)) : collect(slideImage?.replacesContent ? { ...slide, image: void 0 } : slide, path);
|
|
1215
1556
|
const groups = [], flows = [];
|
|
1216
1557
|
const decisions = options.explain ? [] : void 0;
|
|
1217
1558
|
const inheritedSettings = (parent, own = {}) => ({
|
|
@@ -1250,7 +1591,7 @@ function composeSlide(input, options = {}) {
|
|
|
1250
1591
|
minFontSize: settings.minFontSize,
|
|
1251
1592
|
path: node.path,
|
|
1252
1593
|
textRasterPadding: options.textRasterPadding,
|
|
1253
|
-
align:
|
|
1594
|
+
align: alignmentFor("metric")
|
|
1254
1595
|
});
|
|
1255
1596
|
const measureTimeline = (node, box, settings) => layoutTimeline(node.value, acceptedBox(box), {
|
|
1256
1597
|
fonts: options.fonts,
|
|
@@ -1293,29 +1634,29 @@ function composeSlide(input, options = {}) {
|
|
|
1293
1634
|
return score;
|
|
1294
1635
|
};
|
|
1295
1636
|
const modeFor = (settings) => settings.mode ?? "auto";
|
|
1296
|
-
const defaultColumns = (count,
|
|
1637
|
+
const defaultColumns = (count, area2, settings) => {
|
|
1297
1638
|
const mode = modeFor(settings);
|
|
1298
|
-
return mode === "column" ? 1 : mode === "row" ? Math.max(1, count) : settings.columns ?? Math.max(1, Math.min(count, Math.ceil(Math.sqrt(count *
|
|
1639
|
+
return mode === "column" ? 1 : mode === "row" ? Math.max(1, count) : settings.columns ?? Math.max(1, Math.min(count, Math.ceil(Math.sqrt(count * area2.width / area2.height / 1.6))));
|
|
1299
1640
|
};
|
|
1300
1641
|
const scoreNode = (node, box, settings, penalties) => {
|
|
1301
1642
|
if (!node.children) return leafScore(node, box, settings, penalties);
|
|
1302
|
-
const own = inheritedSettings(settings, node.composition),
|
|
1303
|
-
const cols = defaultColumns(node.children.length,
|
|
1304
|
-
const boxes = gridBoxes(node.children.length,
|
|
1643
|
+
const own = inheritedSettings(settings, node.composition), area2 = inset(box, own);
|
|
1644
|
+
const cols = defaultColumns(node.children.length, area2, own);
|
|
1645
|
+
const boxes = gridBoxes(node.children.length, area2, cols, (own.gap ?? 1 / 30) * Math.min(box.width, box.height), own.weights ?? [], modeFor(own) === "column");
|
|
1305
1646
|
return node.children.reduce((score, child, index) => score + scoreNode(child, boxes[index], own, penalties), 0);
|
|
1306
1647
|
};
|
|
1307
|
-
const arrange = (nodes,
|
|
1648
|
+
const arrange = (nodes, area2, settings, reserved = 0, gapOverride, containerPath = path) => {
|
|
1308
1649
|
const count = Math.max(nodes.length, reserved);
|
|
1309
1650
|
if (!count) return;
|
|
1310
|
-
const mode = modeFor(settings), localGap = (settings.gap ?? 1 / 30) * Math.min(
|
|
1651
|
+
const mode = modeFor(settings), localGap = (settings.gap ?? 1 / 30) * Math.min(area2.width, area2.height);
|
|
1311
1652
|
const actualGap = gapOverride ?? (settings === rootSettings ? gap : localGap);
|
|
1312
|
-
let cols = defaultColumns(count,
|
|
1653
|
+
let cols = defaultColumns(count, area2, settings);
|
|
1313
1654
|
const hasRegions = nodes.some((node) => node.region);
|
|
1314
1655
|
const candidates = decisions ? [] : void 0;
|
|
1315
1656
|
if (mode === "auto" && !hasRegions) {
|
|
1316
1657
|
let best = Infinity;
|
|
1317
1658
|
for (let candidate = 1; candidate <= Math.min(count, settings.columns ?? 6); candidate++) {
|
|
1318
|
-
const boxes2 = gridBoxes(count,
|
|
1659
|
+
const boxes2 = gridBoxes(count, area2, candidate, actualGap, settings.weights ?? [], false);
|
|
1319
1660
|
const emptySlots = (Math.ceil(count / candidate) * candidate - count) * 2;
|
|
1320
1661
|
const penalties = candidates ? { cellProportions: 0, fontReduction: 0, textOverflow: 0, tableOverflow: 0, smallCells: 0, emptySlots } : void 0;
|
|
1321
1662
|
const score = nodes.reduce((sum, node, i) => sum + scoreNode(node, boxes2[i], settings, penalties), 0) + emptySlots;
|
|
@@ -1333,11 +1674,11 @@ function composeSlide(input, options = {}) {
|
|
|
1333
1674
|
...hasRegions ? {} : { selectedColumns: cols },
|
|
1334
1675
|
candidates: candidates ?? []
|
|
1335
1676
|
});
|
|
1336
|
-
const grid = gridGeometry(count,
|
|
1677
|
+
const grid = gridGeometry(count, area2, cols, actualGap, settings.weights ?? [], mode === "column");
|
|
1337
1678
|
const boxes = grid.boxes;
|
|
1338
|
-
if (!nodes.some((node) => node.region)) flows.push({ path: containerPath, box: { ...
|
|
1679
|
+
if (!nodes.some((node) => node.region)) flows.push({ path: containerPath, box: { ...area2 }, composition: { ...settings }, columns: grid.columns, rows: grid.rows, gap: grid.gap, itemCount: nodes.length, slotCount: count });
|
|
1339
1680
|
nodes.forEach((node, index) => {
|
|
1340
|
-
let box = node.region ? regionBox(node.region,
|
|
1681
|
+
let box = node.region ? regionBox(node.region, area2, actualGap) : boxes[index];
|
|
1341
1682
|
if (node.children) {
|
|
1342
1683
|
const own = inheritedSettings(settings, node.composition), inner = inset(box, own);
|
|
1343
1684
|
groups.push({ path: node.path, box, contentBox: inner, composition: own });
|
|
@@ -1363,6 +1704,7 @@ function composeSlide(input, options = {}) {
|
|
|
1363
1704
|
text,
|
|
1364
1705
|
textStyle: body?.style ?? styleFor(node.field, node.path),
|
|
1365
1706
|
composition: settings,
|
|
1707
|
+
alignment: alignmentFor(node.field),
|
|
1366
1708
|
...quoteLayout ? { quoteLayout } : {},
|
|
1367
1709
|
...codeLayout ? { codeLayout } : {},
|
|
1368
1710
|
...metricLayout ? { metricLayout } : {},
|
|
@@ -1373,6 +1715,10 @@ function composeSlide(input, options = {}) {
|
|
|
1373
1715
|
});
|
|
1374
1716
|
};
|
|
1375
1717
|
const placeholders = Array.isArray(layout.placeholders) ? layout.placeholders.filter((p) => !headings.has(p.type)) : [];
|
|
1718
|
+
if (slideImage?.replacesContent) {
|
|
1719
|
+
const picture = placeholders.findIndex((p) => p.type === "picture");
|
|
1720
|
+
if (picture >= 0) placeholders.splice(picture, 1);
|
|
1721
|
+
}
|
|
1376
1722
|
const rootSettings = { ...composition, mode: composition.mode ?? (layout.slideLayoutDirection === "Vertical" ? "column" : layout.slideLayoutDirection === "Horizontal" ? "row" : "auto") };
|
|
1377
1723
|
arrange(pending, contentBox, rootSettings, composition.mode ? 0 : placeholders.length);
|
|
1378
1724
|
for (const item of items) {
|
|
@@ -1406,7 +1752,8 @@ function composeSlide(input, options = {}) {
|
|
|
1406
1752
|
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)
|
|
1407
1753
|
} : void 0;
|
|
1408
1754
|
if (failures.length) throw new OPFCompositionError(failures, explanation);
|
|
1409
|
-
|
|
1755
|
+
diagnostics.push(...slideImageDiagnostics);
|
|
1756
|
+
return { width, height, contentBox, items, groups, flows, diagnostics, composition, ...furniture ? { furniture } : {}, ...slideImage ? { slideImage } : {}, ...explanation ? { explanation } : {} };
|
|
1410
1757
|
}
|
|
1411
1758
|
function resolveCanvasDimensions(input) {
|
|
1412
1759
|
const presets = {
|
|
@@ -1426,4 +1773,4 @@ function resolveCanvasDimensions(input) {
|
|
|
1426
1773
|
return { width, height };
|
|
1427
1774
|
}
|
|
1428
1775
|
|
|
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 };
|
|
1776
|
+
export { DEFAULT_FONT_SCHEME, DEFAULT_FURNITURE_DATE_FORMAT, DEFAULT_SLIDE_NUMBER_FORMAT, MAX_COMPOSITION_DEPTH, OPFCompositionError, chartColorForFill, colorContrast, composeSlide, fitList, fitRichText, fitText, formatFurnitureDate, formatSlideNumber, layoutCode, layoutFurniture, layoutMetric, layoutQuote, layoutTable, layoutTimeline, measureText, measureTextOutline, normalizeHexColor, placeTextLines, resolveCanvasDimensions, resolveColorRef, resolveFontFamilies, resolveFontSchemeReference, resolveSocialProfile, resolveTextStyle, slideImageShape, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, wrapText };
|