@openpresentation/opf 0.15.1 → 0.16.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/README.md +4 -0
- package/dist/{catalog-refs-BSfGELpt.d.ts → catalog-refs-_anZs-Qz.d.ts} +1 -1
- package/dist/{catalog-schemas-CinPh5WA.d.ts → catalog-schemas-BZCjgAxu.d.ts} +1 -1
- package/dist/catalog.d.ts +2 -2
- package/dist/catalog.js +609 -121
- package/dist/{chunk-5FTUIDUH.js → chunk-3XDRQYWZ.js} +1 -1
- package/dist/{chunk-O744SXXA.js → chunk-5PDN7BN6.js} +202 -95
- package/dist/{chunk-VGAOJEY7.js → chunk-5TO6I3GB.js} +1 -1
- package/dist/{chunk-3RKB4RDJ.js → chunk-5UEUAW57.js} +4 -2
- package/dist/{chunk-ZPU46TFA.js → chunk-6OR326EA.js} +1 -1
- package/dist/{chunk-UBFJ2QHH.js → chunk-BSYQDWT4.js} +12 -2
- package/dist/{chunk-3JG4YXWF.js → chunk-FQSIIADJ.js} +12 -5
- package/dist/chunk-K4DQQIT4.js +319 -0
- package/dist/chunk-KINQFU6X.js +51 -0
- package/dist/{chunk-374R35TJ.js → chunk-NAWQR7MN.js} +1 -1
- package/dist/{chunk-QDI75P2M.js → chunk-PX5AWL7Y.js} +141 -13
- package/dist/{chunk-U4J75TRG.js → chunk-SMLMI6IZ.js} +5 -2
- package/dist/{chunk-TWQJLI6E.js → chunk-UM24JFUE.js} +2 -2
- package/dist/{chunk-2CJPC4HI.js → chunk-WEDGVC5W.js} +185 -11
- package/dist/{composition-D2tghM82.d.ts → composition-D4ADF5c-.d.ts} +88 -9
- package/dist/composition.d.ts +2 -2
- package/dist/composition.js +1 -1
- package/dist/convert.d.ts +3 -3
- package/dist/convert.js +7 -7
- package/dist/data.d.ts +27 -10
- package/dist/data.js +2 -2
- package/dist/deck.d.ts +77 -0
- package/dist/deck.js +12 -0
- package/dist/diff.js +5 -5
- package/dist/docs.js +24 -24
- package/dist/examples.d.ts +1 -1
- package/dist/examples.js +2992 -748
- package/dist/format.js +2 -2
- package/dist/index.d.ts +9 -8
- package/dist/index.js +15 -13
- package/dist/markdown.d.ts +6 -7
- package/dist/markdown.js +7 -7
- package/dist/{pagination-wedbe7eq.d.ts → pagination-DzZPFheM.d.ts} +2 -2
- package/dist/pagination.d.ts +3 -3
- package/dist/pagination.js +4 -4
- package/dist/patch.js +4 -4
- package/dist/{presentation-CDKQVkyI.d.ts → presentation-COrFuj2g.d.ts} +16 -8
- package/dist/repo-readme.js +1 -1
- package/dist/schemas.d.ts +14 -0
- package/dist/schemas.js +1 -1
- package/dist/spec/catalogs/layouts/business-model-canvas.json +66 -1
- package/dist/spec/catalogs/layouts/capability-map.json +53 -3
- package/dist/spec/catalogs/layouts/chart-2x.json +32 -8
- package/dist/spec/catalogs/layouts/chart-3x-bottom-vertical-title-left.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x-left-title-center.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x-left.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x-right-title-center.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x-right.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x-top-vertical-title-left.json +16 -10
- package/dist/spec/catalogs/layouts/chart-3x.json +48 -12
- package/dist/spec/catalogs/layouts/dashboard.json +37 -5
- package/dist/spec/catalogs/layouts/image-2x.json +32 -8
- package/dist/spec/catalogs/layouts/image-3x.json +48 -12
- package/dist/spec/catalogs/layouts/index.json +1 -1
- package/dist/spec/catalogs/layouts/kpi-scorecard.json +48 -3
- package/dist/spec/catalogs/layouts/logic-tree.json +69 -0
- package/dist/spec/catalogs/layouts/market-size.json +26 -2
- package/dist/spec/catalogs/layouts/org-chart.json +53 -6
- package/dist/spec/catalogs/manifest.json +3 -3
- package/dist/spec/schemas/layout.schema.json +172 -5
- package/dist/spec/schemas/opf.schema.json +11 -6
- package/dist/types.d.ts +9 -31
- package/dist/{validation-types-BOcY9GTs.d.ts → validation-types-HxIgJfKx.d.ts} +2 -2
- package/dist/validator.d.ts +6 -6
- package/dist/validator.js +3 -3
- package/dist/yaml.d.ts +4 -4
- package/dist/yaml.js +8 -321
- package/package.json +5 -1
|
@@ -1771,6 +1771,75 @@ function readingRows(items) {
|
|
|
1771
1771
|
return rows3.map((row) => row.items.sort((a, b) => index.get(a) - index.get(b)));
|
|
1772
1772
|
}
|
|
1773
1773
|
|
|
1774
|
+
// src/layout-content.ts
|
|
1775
|
+
var LAYOUT_BODY_KINDS = ["text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
|
|
1776
|
+
var MAX_PLACEHOLDER_GROUP_DEPTH = 3;
|
|
1777
|
+
var bodyKinds = new Set(LAYOUT_BODY_KINDS);
|
|
1778
|
+
var record4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
1779
|
+
function isPlaceholderGroup(placeholder) {
|
|
1780
|
+
return record4(placeholder).type === "group";
|
|
1781
|
+
}
|
|
1782
|
+
function layoutSlots(layout, base = "layout.placeholders") {
|
|
1783
|
+
const walk2 = (entries, path, depth) => (Array.isArray(entries) ? entries : []).map((entry, index) => {
|
|
1784
|
+
const placeholder = record4(entry), slotPath = `${path}.${index}`;
|
|
1785
|
+
const type = typeof placeholder.type === "string" ? placeholder.type : "";
|
|
1786
|
+
if (type !== "group") {
|
|
1787
|
+
if (depth > 0 && !bodyKinds.has(type)) throw new RangeError(`${slotPath}: a placeholder group holds body regions only, not '${type}'.`);
|
|
1788
|
+
return { type, path: slotPath, depth, placeholder };
|
|
1789
|
+
}
|
|
1790
|
+
if (depth >= MAX_PLACEHOLDER_GROUP_DEPTH) throw new RangeError(`${slotPath}: placeholder groups nest at most ${MAX_PLACEHOLDER_GROUP_DEPTH} levels inside a layout record.`);
|
|
1791
|
+
if (!Array.isArray(placeholder.placeholders) || !placeholder.placeholders.length) throw new RangeError(`${slotPath}: a placeholder group needs at least one placeholder.`);
|
|
1792
|
+
return { type, path: slotPath, depth, placeholder, children: walk2(placeholder.placeholders, `${slotPath}.placeholders`, depth + 1) };
|
|
1793
|
+
});
|
|
1794
|
+
return walk2(layout?.placeholders, base, 0);
|
|
1795
|
+
}
|
|
1796
|
+
function layoutLeaves(layout) {
|
|
1797
|
+
const leaves = [];
|
|
1798
|
+
const visit = (slots) => {
|
|
1799
|
+
for (const slot of slots) slot.children ? visit(slot.children) : leaves.push({ type: slot.type, path: slot.path, depth: slot.depth, placeholder: slot.placeholder });
|
|
1800
|
+
};
|
|
1801
|
+
visit(layoutSlots(layout));
|
|
1802
|
+
return leaves;
|
|
1803
|
+
}
|
|
1804
|
+
function layoutStructure(layout) {
|
|
1805
|
+
const describe = (slots) => slots.map((slot) => {
|
|
1806
|
+
if (!slot.children) return slot.type;
|
|
1807
|
+
const mode = record4(slot.placeholder.composition).mode;
|
|
1808
|
+
return `${typeof mode === "string" && mode !== "auto" ? mode : "group"} (${describe(slot.children)})`;
|
|
1809
|
+
}).join(", ");
|
|
1810
|
+
return describe(layoutSlots(layout));
|
|
1811
|
+
}
|
|
1812
|
+
function hasPlaceholderGroups(layout) {
|
|
1813
|
+
return Array.isArray(layout?.placeholders) && layout.placeholders.some(isPlaceholderGroup);
|
|
1814
|
+
}
|
|
1815
|
+
function layoutContent(layout) {
|
|
1816
|
+
const heading = { title: false, subtitle: false, tag: false };
|
|
1817
|
+
const counts = /* @__PURE__ */ new Map();
|
|
1818
|
+
let count = 0;
|
|
1819
|
+
const visit = (entries, depth) => {
|
|
1820
|
+
for (const entry of Array.isArray(entries) ? entries : []) {
|
|
1821
|
+
const type = record4(entry).type;
|
|
1822
|
+
if (type === "group") {
|
|
1823
|
+
if (depth < MAX_PLACEHOLDER_GROUP_DEPTH) visit(record4(entry).placeholders, depth + 1);
|
|
1824
|
+
continue;
|
|
1825
|
+
}
|
|
1826
|
+
if (type === "title" || type === "subtitle" || type === "tag") {
|
|
1827
|
+
if (depth === 0) heading[type] = true;
|
|
1828
|
+
} else if (typeof type === "string" && bodyKinds.has(type)) {
|
|
1829
|
+
counts.set(type, (counts.get(type) ?? 0) + 1);
|
|
1830
|
+
count += 1;
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
};
|
|
1834
|
+
visit(layout?.placeholders, 0);
|
|
1835
|
+
let kind2 = "title", best = 0;
|
|
1836
|
+
for (const [candidate, total] of counts) if (total > best) {
|
|
1837
|
+
kind2 = candidate;
|
|
1838
|
+
best = total;
|
|
1839
|
+
}
|
|
1840
|
+
return { kind: kind2, count, heading };
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1774
1843
|
// src/direction.ts
|
|
1775
1844
|
var strongRtl = /[\u200F\u061C]|(?=\p{L})[\p{Script=Arabic}\p{Script=Hebrew}\p{Script=Syriac}\p{Script=Thaana}\p{Script=Nko}\p{Script=Adlam}\p{Script=Hanifi_Rohingya}\p{Script=Mandaic}\p{Script=Samaritan}\p{Script=Mende_Kikakui}\p{Script=Imperial_Aramaic}\p{Script=Phoenician}\p{Script=Kharoshthi}\p{Script=Old_South_Arabian}\p{Script=Old_North_Arabian}\p{Script=Avestan}\p{Script=Inscriptional_Parthian}\p{Script=Inscriptional_Pahlavi}\p{Script=Psalter_Pahlavi}\p{Script=Old_Turkic}\p{Script=Old_Hungarian}\p{Script=Nabataean}\p{Script=Palmyrene}\p{Script=Hatran}\p{Script=Manichaean}\p{Script=Sogdian}\p{Script=Old_Sogdian}\p{Script=Elymaic}\p{Script=Chorasmian}\p{Script=Yezidi}\p{Script=Cypriot}\p{Script=Lydian}\p{Script=Meroitic_Cursive}\p{Script=Meroitic_Hieroglyphs}\u{10F70}-\u{10FAF}\u{10D40}-\u{10D8F}]/u;
|
|
1776
1845
|
var strongLtr = /[\u200E\p{L}\p{Nl}]/u;
|
|
@@ -3283,8 +3352,8 @@ function codeSyntaxPalette(theme = {}, options = {}) {
|
|
|
3283
3352
|
return palette;
|
|
3284
3353
|
}
|
|
3285
3354
|
function codeSyntaxPaletteForScheme(scheme, options = {}) {
|
|
3286
|
-
const
|
|
3287
|
-
const pick = (role, slot, fallback) => normalize(
|
|
3355
|
+
const record7 = scheme && typeof scheme === "object" ? scheme : {};
|
|
3356
|
+
const pick = (role, slot, fallback) => normalize(record7[role]) ?? normalize(record7[slot]) ?? fallback;
|
|
3288
3357
|
return codeSyntaxPalette({ primary: pick("primary", "accent1", "#2563EB"), secondary: pick("secondary", "accent2", "#0F766E"), accent: pick("accent", "accent3", "#F59E0B") }, options);
|
|
3289
3358
|
}
|
|
3290
3359
|
|
|
@@ -3436,8 +3505,8 @@ var blend = (from, to, amount) => {
|
|
|
3436
3505
|
return toHex(a.map((value, index) => value + (b[index] - value) * amount));
|
|
3437
3506
|
};
|
|
3438
3507
|
function codeHighlightColors(scheme, palette = codeSyntaxPaletteForScheme(scheme)) {
|
|
3439
|
-
const
|
|
3440
|
-
const primary = normalize(
|
|
3508
|
+
const record7 = scheme && typeof scheme === "object" ? scheme : {};
|
|
3509
|
+
const primary = normalize(record7.primary) ?? normalize(record7.accent1) ?? "#2563EB";
|
|
3441
3510
|
const [hue, saturation] = toHsl(primary);
|
|
3442
3511
|
const tint = fromHsl(hue, Math.min(saturation, 0.7), 0.45);
|
|
3443
3512
|
const band = blend(CODE_PANEL_BACKGROUND, tint, CODE_HIGHLIGHT_BAND_TINT);
|
|
@@ -3634,7 +3703,7 @@ var CAPTION_FONT_RATIO = 0.6;
|
|
|
3634
3703
|
var CAPTION_MAX_RATIO = 0.35;
|
|
3635
3704
|
var FOOTNOTE_MAX_RATIO = 0.35;
|
|
3636
3705
|
var CAPTIONABLE_FIELDS = Object.freeze(["image", "chart", "table", "video"]);
|
|
3637
|
-
var
|
|
3706
|
+
var record5 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3638
3707
|
var isRecord3 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
3639
3708
|
var round = (value) => Math.round(value * 1e6) / 1e6 || value;
|
|
3640
3709
|
var regionKey = /^(top|middle|bottom|left|center|right)([+:]|$)/;
|
|
@@ -3642,7 +3711,7 @@ var TEXT_FIELDS = ["text", "items", "bullets"];
|
|
|
3642
3711
|
var HEADING_FIELDS = ["tag", "title", "subtitle"];
|
|
3643
3712
|
function annotationText(value) {
|
|
3644
3713
|
if (typeof value === "string") return value;
|
|
3645
|
-
if (Array.isArray(value)) return value.map((run) => typeof run === "string" ? run :
|
|
3714
|
+
if (Array.isArray(value)) return value.map((run) => typeof run === "string" ? run : record5(run).text ?? "").join("");
|
|
3646
3715
|
if (isRecord3(value) && value.text !== void 0) return annotationText(value.text);
|
|
3647
3716
|
return value === void 0 || value === null ? "" : String(value);
|
|
3648
3717
|
}
|
|
@@ -3674,7 +3743,7 @@ function walkCitationRuns(slide, basePath, visit) {
|
|
|
3674
3743
|
});
|
|
3675
3744
|
};
|
|
3676
3745
|
const host = (node, path, depth) => {
|
|
3677
|
-
const payload =
|
|
3746
|
+
const payload = record5(node);
|
|
3678
3747
|
if (Array.isArray(payload.blocks)) {
|
|
3679
3748
|
if (depth > 32) return;
|
|
3680
3749
|
payload.blocks.forEach((block, index) => {
|
|
@@ -3689,7 +3758,7 @@ function walkCitationRuns(slide, basePath, visit) {
|
|
|
3689
3758
|
}
|
|
3690
3759
|
if (isRecord3(payload.quote)) runs(payload.quote.text, `${path}.quote.text`);
|
|
3691
3760
|
};
|
|
3692
|
-
const value =
|
|
3761
|
+
const value = record5(slide);
|
|
3693
3762
|
for (const field of HEADING_FIELDS) runs(value[field], `${basePath}.${field}`);
|
|
3694
3763
|
const regions = Object.keys(value).filter((key) => regionKey.test(key)).sort();
|
|
3695
3764
|
if (regions.length) {
|
|
@@ -3706,7 +3775,7 @@ function walkCitationRuns(slide, basePath, visit) {
|
|
|
3706
3775
|
}
|
|
3707
3776
|
var citationMarkerText = (numbers) => numbers.join(",");
|
|
3708
3777
|
function referenceList(presentation) {
|
|
3709
|
-
const list =
|
|
3778
|
+
const list = record5(presentation).references;
|
|
3710
3779
|
return Array.isArray(list) ? list.filter((item) => isRecord3(item) && typeof item.id === "string") : [];
|
|
3711
3780
|
}
|
|
3712
3781
|
function numberSlide(slide, slideIndex, references, numbering) {
|
|
@@ -3739,7 +3808,7 @@ function numberSlide(slide, slideIndex, references, numbering) {
|
|
|
3739
3808
|
}
|
|
3740
3809
|
function collectCitations(presentation) {
|
|
3741
3810
|
const references = referenceList(presentation), numbering = { notes: [], byId: /* @__PURE__ */ new Map() }, slides = /* @__PURE__ */ new Map();
|
|
3742
|
-
const list =
|
|
3811
|
+
const list = record5(presentation).slides;
|
|
3743
3812
|
if (Array.isArray(list)) list.forEach((slide, index) => {
|
|
3744
3813
|
const result = numberSlide(slide, index, references, numbering);
|
|
3745
3814
|
if (result) slides.set(index, result);
|
|
@@ -3749,7 +3818,7 @@ function collectCitations(presentation) {
|
|
|
3749
3818
|
}
|
|
3750
3819
|
function slideCitations(slide, slideIndex, presentation) {
|
|
3751
3820
|
const references = referenceList(presentation), numbering = { notes: [], byId: /* @__PURE__ */ new Map() };
|
|
3752
|
-
const list =
|
|
3821
|
+
const list = record5(presentation).slides;
|
|
3753
3822
|
if (Array.isArray(list)) for (let index = 0; index < Math.min(slideIndex, list.length); index += 1) numberSlide(list[index], index, references, numbering);
|
|
3754
3823
|
return numberSlide(slide, slideIndex, references, numbering);
|
|
3755
3824
|
}
|
|
@@ -3812,35 +3881,12 @@ function referencesSlide(presentation, options = {}) {
|
|
|
3812
3881
|
return { title, items };
|
|
3813
3882
|
}
|
|
3814
3883
|
|
|
3815
|
-
// src/layout-content.ts
|
|
3816
|
-
var LAYOUT_BODY_KINDS = ["text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
|
|
3817
|
-
var bodyKinds = new Set(LAYOUT_BODY_KINDS);
|
|
3818
|
-
function layoutContent(record6) {
|
|
3819
|
-
const heading = { title: false, subtitle: false, tag: false };
|
|
3820
|
-
const counts = /* @__PURE__ */ new Map();
|
|
3821
|
-
let count = 0;
|
|
3822
|
-
for (const placeholder of Array.isArray(record6?.placeholders) ? record6.placeholders : []) {
|
|
3823
|
-
const type = placeholder?.type;
|
|
3824
|
-
if (type === "title" || type === "subtitle" || type === "tag") heading[type] = true;
|
|
3825
|
-
else if (typeof type === "string" && bodyKinds.has(type)) {
|
|
3826
|
-
counts.set(type, (counts.get(type) ?? 0) + 1);
|
|
3827
|
-
count += 1;
|
|
3828
|
-
}
|
|
3829
|
-
}
|
|
3830
|
-
let kind2 = "title", best = 0;
|
|
3831
|
-
for (const [candidate, total] of counts) if (total > best) {
|
|
3832
|
-
kind2 = candidate;
|
|
3833
|
-
best = total;
|
|
3834
|
-
}
|
|
3835
|
-
return { kind: kind2, count, heading };
|
|
3836
|
-
}
|
|
3837
|
-
|
|
3838
3884
|
// src/composition.ts
|
|
3839
3885
|
var MAX_COMPOSITION_DEPTH = 32;
|
|
3840
3886
|
var FALLBACK_CODE_FAMILY = "Roboto Mono";
|
|
3841
3887
|
var DEFAULT_FONT_FAMILIES = { heading: String(ENGINE_DEFAULT_FONT_SCHEME.major), body: String(ENGINE_DEFAULT_FONT_SCHEME.minor) };
|
|
3842
3888
|
function resolveFontFamilies(input) {
|
|
3843
|
-
const scheme =
|
|
3889
|
+
const scheme = record6(input);
|
|
3844
3890
|
const family = (value) => typeof value === "string" && value ? value : void 0;
|
|
3845
3891
|
const accent = family(scheme.accent);
|
|
3846
3892
|
return {
|
|
@@ -3911,6 +3957,12 @@ function translateTextFit(fit, dy) {
|
|
|
3911
3957
|
}
|
|
3912
3958
|
};
|
|
3913
3959
|
}
|
|
3960
|
+
var FIELD_KINDS = { text: "text", bullets: "text", items: "list", image: "image", video: "video", chart: "chart", table: "table", code: "code", metric: "metric", quote: "quote", timeline: "timeline" };
|
|
3961
|
+
function chartPrimaryLayout(side, kinds) {
|
|
3962
|
+
const first = side === "left" || side === "top";
|
|
3963
|
+
const group = { type: "group", composition: {}, placeholders: kinds.map((type) => ({ type })) };
|
|
3964
|
+
return { composition: { mode: side === "left" || side === "right" ? "row" : "column", weights: first ? [3, 2] : [2, 3] }, placeholders: first ? [{ type: "chart" }, group] : [group, { type: "chart" }] };
|
|
3965
|
+
}
|
|
3914
3966
|
var OPFCompositionError = class extends Error {
|
|
3915
3967
|
constructor(diagnostics, explanation) {
|
|
3916
3968
|
super("Slide content does not fit its composition.");
|
|
@@ -3926,7 +3978,7 @@ var fields = ["text", "items", "bullets", "image", "video", "chart", "table", "c
|
|
|
3926
3978
|
var headings = /* @__PURE__ */ new Set(["title", "subtitle", "tag"]);
|
|
3927
3979
|
var rows2 = ["top", "middle", "bottom"];
|
|
3928
3980
|
var columns = ["left", "center", "right"];
|
|
3929
|
-
var
|
|
3981
|
+
var record6 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3930
3982
|
var kind = (field) => field === "items" ? "list" : field === "bullets" ? "text" : field;
|
|
3931
3983
|
var round2 = (value) => Math.round(value * 1e6) / 1e6 || value;
|
|
3932
3984
|
var PLACEMENT_BAND = 0.5;
|
|
@@ -3940,13 +3992,13 @@ var imagePayload = (host) => {
|
|
|
3940
3992
|
for (const key of IMAGE_OPTION_KEYS) if (host[key] !== void 0) payload[key] = host[key];
|
|
3941
3993
|
return payload;
|
|
3942
3994
|
};
|
|
3943
|
-
var assetSource = (value) => typeof value === "string" ? value :
|
|
3995
|
+
var assetSource = (value) => typeof value === "string" ? value : record6(value).src;
|
|
3944
3996
|
var finite = (value, min, max) => typeof value === "number" && Number.isFinite(value) && value >= min && value <= max ? value : void 0;
|
|
3945
3997
|
var pathNumber = (value) => String(round2(value));
|
|
3946
3998
|
var IMAGE_SHAPES = { rectangle: "rect", rounded: "roundRect", circle: "ellipse", hexagon: "hexagon" };
|
|
3947
3999
|
var roundBox = (box) => ({ x: round2(box.x), y: round2(box.y), width: round2(box.width), height: round2(box.height) });
|
|
3948
4000
|
var imageFocus = (value) => {
|
|
3949
|
-
const focus =
|
|
4001
|
+
const focus = record6(value), x = finite(focus.x, 0, 1), y = finite(focus.y, 0, 1);
|
|
3950
4002
|
return x !== void 0 && y !== void 0 ? { x, y } : { x: 0.5, y: 0.5 };
|
|
3951
4003
|
};
|
|
3952
4004
|
function imageShape(kind2, box, cornerRadius = 1 / 6) {
|
|
@@ -3987,7 +4039,7 @@ function fitImage(frame, fit, aspect, focus = { x: 0.5, y: 0.5 }) {
|
|
|
3987
4039
|
}
|
|
3988
4040
|
function imageBackground(value) {
|
|
3989
4041
|
if (typeof value === "string") return IMAGE_SOURCE.test(value) ? { src: value, fit: "cover", focus: { x: 0.5, y: 0.5 } } : void 0;
|
|
3990
|
-
const background =
|
|
4042
|
+
const background = record6(value);
|
|
3991
4043
|
if (background.type !== "image" || typeof background.src !== "string" || !background.src) return void 0;
|
|
3992
4044
|
const opacity = finite(background.opacity, 0, 1);
|
|
3993
4045
|
return {
|
|
@@ -4002,11 +4054,11 @@ function imageBackground(value) {
|
|
|
4002
4054
|
}
|
|
4003
4055
|
function composeRecolor(value) {
|
|
4004
4056
|
if (value === "grayscale") return { type: "grayscale" };
|
|
4005
|
-
const duotone =
|
|
4057
|
+
const duotone = record6(value);
|
|
4006
4058
|
return duotone.dark !== void 0 && duotone.light !== void 0 ? { type: "duotone", dark: duotone.dark, light: duotone.light } : void 0;
|
|
4007
4059
|
}
|
|
4008
4060
|
function composeOverlay(value, frame, shape, path, mirrorSide, diagnostics) {
|
|
4009
|
-
const overlay =
|
|
4061
|
+
const overlay = record6(value), opacity = finite(overlay.opacity, 0, 1);
|
|
4010
4062
|
if (overlay.color === void 0 || opacity === void 0) return void 0;
|
|
4011
4063
|
const edge = IMAGE_EDGES.includes(overlay.edge) ? mirrorSide(overlay.edge) : void 0;
|
|
4012
4064
|
if (edge && shape.kind !== "rectangle") {
|
|
@@ -4031,7 +4083,7 @@ function composeImage(host, hostPath, region, frameArea, context) {
|
|
|
4031
4083
|
const focus = imageFocus(host.focus);
|
|
4032
4084
|
const shape = imageShape(kindName, box, finite(host.cornerRadius, 0, 0.5));
|
|
4033
4085
|
const result = { region: roundBox(region), box, fit, focus, shape };
|
|
4034
|
-
const border =
|
|
4086
|
+
const border = record6(host.border), borderWidth = finite(border.width, 0, 64);
|
|
4035
4087
|
if (border.color !== void 0 && borderWidth) result.border = { color: border.color, width: round2(borderWidth * scale) };
|
|
4036
4088
|
const opacity = finite(host.opacity, 0, 1);
|
|
4037
4089
|
if (opacity !== void 0 && opacity < 1) result.opacity = opacity;
|
|
@@ -4045,7 +4097,7 @@ function composeImage(host, hostPath, region, frameArea, context) {
|
|
|
4045
4097
|
return result;
|
|
4046
4098
|
}
|
|
4047
4099
|
function resolveBackgroundImage(slide, presentation, themeBackground, width, height, path, mirrorSide, diagnostics) {
|
|
4048
|
-
const own2 =
|
|
4100
|
+
const own2 = record6(slide.design), deck = record6(record6(presentation).design);
|
|
4049
4101
|
const [value, at3] = own2.background !== void 0 ? [own2.background, `${path}.design.background`] : deck.background !== void 0 ? [deck.background, "design.background"] : [themeBackground, "theme"];
|
|
4050
4102
|
const background = imageBackground(value);
|
|
4051
4103
|
if (!background) return void 0;
|
|
@@ -4056,7 +4108,7 @@ function resolveBackgroundImage(slide, presentation, themeBackground, width, hei
|
|
|
4056
4108
|
if (recolor) result.recolor = recolor;
|
|
4057
4109
|
const overlay = composeOverlay(background.overlay, box, imageShape("rectangle", box), `${at3}.overlay`, mirrorSide, diagnostics);
|
|
4058
4110
|
if (overlay) result.overlay = overlay;
|
|
4059
|
-
const aspect = background.fit === "tile" ? void 0 : intrinsicImageAspect(background.src,
|
|
4111
|
+
const aspect = background.fit === "tile" ? void 0 : intrinsicImageAspect(background.src, record6(presentation).assets);
|
|
4060
4112
|
if (aspect) result.picture = fitImage(box, background.fit, aspect, background.focus);
|
|
4061
4113
|
return result;
|
|
4062
4114
|
}
|
|
@@ -4077,10 +4129,10 @@ function resolveLogo(presentation, slide, options = {}) {
|
|
|
4077
4129
|
};
|
|
4078
4130
|
const pick = (value, path) => {
|
|
4079
4131
|
if (value === void 0 || value === null || value === false) return null;
|
|
4080
|
-
if (typeof value === "string" || typeof value === "object" && !Array.isArray(value) && "src" in
|
|
4132
|
+
if (typeof value === "string" || typeof value === "object" && !Array.isArray(value) && "src" in record6(value)) {
|
|
4081
4133
|
return usable(value) ? { source: value, path, variant: "default", slot } : null;
|
|
4082
4134
|
}
|
|
4083
|
-
const set2 =
|
|
4135
|
+
const set2 = record6(value);
|
|
4084
4136
|
if (!Object.keys(set2).some((key) => LOGO_SET_KEYS.has(key))) return null;
|
|
4085
4137
|
for (const key of chain) {
|
|
4086
4138
|
const variant = set2[key];
|
|
@@ -4088,16 +4140,16 @@ function resolveLogo(presentation, slide, options = {}) {
|
|
|
4088
4140
|
}
|
|
4089
4141
|
return null;
|
|
4090
4142
|
};
|
|
4091
|
-
const deck =
|
|
4092
|
-
const own2 = pick(
|
|
4143
|
+
const deck = record6(presentation), slideIndex = Number.isSafeInteger(options.slideIndex) && options.slideIndex >= 0 ? options.slideIndex : 0;
|
|
4144
|
+
const own2 = pick(record6(record6(slide).design).logo, `slides.${slideIndex}.design.logo`);
|
|
4093
4145
|
if (own2) return own2;
|
|
4094
|
-
const shared = pick(
|
|
4146
|
+
const shared = pick(record6(deck.design).logo, "design.logo");
|
|
4095
4147
|
if (shared) return shared;
|
|
4096
4148
|
const organizations = Array.isArray(deck.organization) ? deck.organization : [deck.organization];
|
|
4097
|
-
const primaryIndex = organizations.findIndex((item) =>
|
|
4149
|
+
const primaryIndex = organizations.findIndex((item) => record6(item).role === "primary");
|
|
4098
4150
|
const index = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
|
|
4099
4151
|
if (index < 0) return null;
|
|
4100
|
-
return pick(
|
|
4152
|
+
return pick(record6(organizations[index]).logo, Array.isArray(deck.organization) ? `organization.${index}.logo` : "organization.logo");
|
|
4101
4153
|
}
|
|
4102
4154
|
var webUrl = /^https?:\/\/\S+$/i;
|
|
4103
4155
|
function resolveSocialProfile(platform, value, owner = "organization") {
|
|
@@ -4115,8 +4167,8 @@ function resolveSocialProfile(platform, value, owner = "organization") {
|
|
|
4115
4167
|
return { text: display(url), href: encodeURI(url), resolved: true };
|
|
4116
4168
|
}
|
|
4117
4169
|
function layoutFurniture(input, options = {}) {
|
|
4118
|
-
const slide =
|
|
4119
|
-
const settings = { ...
|
|
4170
|
+
const slide = record6(input), width = options.width ?? 1280, height = options.height ?? 720, scale = Math.min(width, height) / 720;
|
|
4171
|
+
const settings = { ...record6(record6(options.layout).composition), ...record6(slide.composition) };
|
|
4120
4172
|
assertComposition(settings);
|
|
4121
4173
|
const furnitureRtl = (options.direction ?? resolveSlideDirection(options.presentation, options.slideIndex)) === "rtl";
|
|
4122
4174
|
const minimum = snapFontSizeUp((settings.minFontSize ?? 16) * scale), size = gridFontSize(13 * scale, minimum), padding = (options.textRasterPadding ?? 2) * scale;
|
|
@@ -4128,14 +4180,14 @@ function layoutFurniture(input, options = {}) {
|
|
|
4128
4180
|
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.");
|
|
4129
4181
|
const outlines = options.textMeasurement?.outlineBounds !== void 0, parts = [], diagnostics = [];
|
|
4130
4182
|
const sourceRoot = `slides.${options.slideIndex ?? 0}`, organizations = Array.isArray(options.presentation?.organization) ? options.presentation.organization : [options.presentation?.organization];
|
|
4131
|
-
const primaryIndex = organizations.findIndex((item) =>
|
|
4132
|
-
const organization =
|
|
4133
|
-
const speakers = Array.isArray(options.presentation?.speaker) ? options.presentation.speaker : [options.presentation?.speaker], speaker =
|
|
4183
|
+
const primaryIndex = organizations.findIndex((item) => record6(item).role === "primary"), organizationIndex = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
|
|
4184
|
+
const organization = record6(organizations[organizationIndex]), organizationRoot = Array.isArray(options.presentation?.organization) ? `organization.${organizationIndex}` : "organization", organizationPath = `${organizationRoot}.name`;
|
|
4185
|
+
const speakers = Array.isArray(options.presentation?.speaker) ? options.presentation.speaker : [options.presentation?.speaker], speaker = record6(speakers[0]), speakerRoot = Array.isArray(options.presentation?.speaker) ? "speaker.0" : "speaker";
|
|
4134
4186
|
const fontFamily = options.fontFamilies?.body ?? "sans-serif";
|
|
4135
4187
|
let headerBottom = 0, footerTop = height, configured = false;
|
|
4136
4188
|
const error = (path, message, code = "text-overflow") => diagnostics.push({ code, path, message });
|
|
4137
4189
|
for (const kind2 of ["header", "footer"]) {
|
|
4138
|
-
const local =
|
|
4190
|
+
const local = record6(slide.design)[kind2] !== void 0, value = local ? record6(slide.design)[kind2] : options.presentation?.design?.[kind2];
|
|
4139
4191
|
if (value === void 0 || value === false) continue;
|
|
4140
4192
|
const root = local ? `${sourceRoot}.design.${kind2}` : `design.${kind2}`;
|
|
4141
4193
|
if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Header/footer content must be an object or false.");
|
|
@@ -4143,7 +4195,7 @@ function layoutFurniture(input, options = {}) {
|
|
|
4143
4195
|
const zones = [];
|
|
4144
4196
|
for (const [index, zone] of ["left", "center", "right"].entries()) {
|
|
4145
4197
|
const side = furnitureRtl && zone !== "center" ? zone === "left" ? "right" : "left" : zone;
|
|
4146
|
-
const content =
|
|
4198
|
+
const content = record6(record6(value)[zone]), path = `${root}.${zone}`, x = width * (0.07 + (furnitureRtl ? 2 - index : index) * 0.3), zoneWidth = width * 0.26, zoneParts = [];
|
|
4147
4199
|
let y = 0;
|
|
4148
4200
|
const add = (field, text2, generated = false, sourcePath, extras = {}) => {
|
|
4149
4201
|
if (text2 === void 0) return;
|
|
@@ -4180,7 +4232,7 @@ function layoutFurniture(input, options = {}) {
|
|
|
4180
4232
|
y += box.height;
|
|
4181
4233
|
};
|
|
4182
4234
|
const imageBox = (source) => {
|
|
4183
|
-
const imageHeight = Math.max(32 * scale, Math.min(height * 0.05, 72 * scale)), imageWidth = Math.min(zoneWidth, imageHeight * (intrinsicImageAspect(source,
|
|
4235
|
+
const imageHeight = Math.max(32 * scale, Math.min(height * 0.05, 72 * scale)), imageWidth = Math.min(zoneWidth, imageHeight * (intrinsicImageAspect(source, record6(options.presentation).assets) ?? 1));
|
|
4184
4236
|
return { x: side === "left" ? x : side === "center" ? x + (zoneWidth - imageWidth) / 2 : x + zoneWidth - imageWidth, y, width: imageWidth, height: imageHeight };
|
|
4185
4237
|
};
|
|
4186
4238
|
if (content.logo === true) {
|
|
@@ -4206,7 +4258,7 @@ function layoutFurniture(input, options = {}) {
|
|
|
4206
4258
|
else error(`${path}.speaker`, "Generated speaker needs a named speaker in the presentation.", "unresolved-content");
|
|
4207
4259
|
}
|
|
4208
4260
|
if (content.socials === true) {
|
|
4209
|
-
const links = Object.entries(
|
|
4261
|
+
const links = Object.entries(record6(organization.socials)).filter(([, value2]) => typeof value2 === "string" && value2.trim()).map(([platform, value2]) => ({ platform, sourcePath: `${organizationRoot}.socials.${platform}`, ...resolveSocialProfile(platform, value2, "organization") }));
|
|
4210
4262
|
if (links.length) add("socials", links.map((link) => link.text).join("\n"), true, `${organizationRoot}.socials`, { links });
|
|
4211
4263
|
else error(`${path}.socials`, "Generated social profiles need a primary organization with socials.", "unresolved-content");
|
|
4212
4264
|
}
|
|
@@ -4755,19 +4807,19 @@ function fitSourceText(text2, box, size, minimum, step, measure, prose = false,
|
|
|
4755
4807
|
const layout = (fontSize) => {
|
|
4756
4808
|
const tabWidth = measure(" ", fontSize) * 4;
|
|
4757
4809
|
if (!Number.isFinite(tabWidth) || text2.includes(" ") && tabWidth <= 0) throw new RangeError("Text tabs require a positive finite measured space advance.");
|
|
4758
|
-
const measureLine = (start2, end2,
|
|
4810
|
+
const measureLine = (start2, end2, record7 = false) => {
|
|
4759
4811
|
let x = 0, offset = start2;
|
|
4760
4812
|
const segments = [];
|
|
4761
4813
|
for (const [index, segment2] of text2.slice(start2, end2).split(" ").entries()) {
|
|
4762
4814
|
if (index) {
|
|
4763
4815
|
const next = (Math.floor(x / tabWidth + 1e-9) + 1) * tabWidth;
|
|
4764
|
-
if (
|
|
4816
|
+
if (record7) segments.push({ kind: "tab", start: offset, end: offset + 1, x, width: next - x });
|
|
4765
4817
|
x = next;
|
|
4766
4818
|
offset++;
|
|
4767
4819
|
}
|
|
4768
4820
|
if (segment2) {
|
|
4769
4821
|
const advance = measure(segment2, fontSize);
|
|
4770
|
-
if (
|
|
4822
|
+
if (record7) segments.push({ kind: "text", start: offset, end: offset + segment2.length, x, width: advance });
|
|
4771
4823
|
x += advance;
|
|
4772
4824
|
offset += segment2.length;
|
|
4773
4825
|
}
|
|
@@ -5124,12 +5176,12 @@ function fitList(input, box, requestedSize = 25, minFontSize = 16, options = { s
|
|
|
5124
5176
|
function contentText(field, value) {
|
|
5125
5177
|
if (field === "text" || headings.has(field)) return flatten(value);
|
|
5126
5178
|
if (field === "items" || field === "bullets") return (Array.isArray(value) ? value : [value]).map((item) => {
|
|
5127
|
-
const entry =
|
|
5179
|
+
const entry = record6(item);
|
|
5128
5180
|
return `\u2022 ${flatten(item)}${entry.description ? `
|
|
5129
5181
|
${flatten(entry.description)}` : ""}`;
|
|
5130
5182
|
}).join("\n");
|
|
5131
|
-
if (field === "code") return flatten(
|
|
5132
|
-
if (field === "quote") return flatten(
|
|
5183
|
+
if (field === "code") return flatten(record6(value).source ?? value);
|
|
5184
|
+
if (field === "quote") return flatten(record6(value).text ?? value);
|
|
5133
5185
|
return void 0;
|
|
5134
5186
|
}
|
|
5135
5187
|
function layoutTable(value, box, options = {}) {
|
|
@@ -5200,7 +5252,7 @@ function flatten(value) {
|
|
|
5200
5252
|
if (value == null) return "";
|
|
5201
5253
|
if (typeof value !== "object") return String(value);
|
|
5202
5254
|
if (Array.isArray(value)) return value.map(flatten).join("");
|
|
5203
|
-
const item =
|
|
5255
|
+
const item = record6(value);
|
|
5204
5256
|
return flatten(item.text ?? item.value ?? item.source ?? JSON.stringify(value));
|
|
5205
5257
|
}
|
|
5206
5258
|
function regionParts(key) {
|
|
@@ -5256,7 +5308,7 @@ function assertComposition(value) {
|
|
|
5256
5308
|
if (value.overflow !== void 0 && !["warn", "error"].includes(value.overflow)) throw new RangeError("Invalid composition.overflow.");
|
|
5257
5309
|
}
|
|
5258
5310
|
function composeSlide(input, options = {}) {
|
|
5259
|
-
const slide =
|
|
5311
|
+
const slide = record6(input), layout = record6(options.layout);
|
|
5260
5312
|
const width = options.width ?? 1280, height = options.height ?? 720;
|
|
5261
5313
|
if (![width, height].every((value) => Number.isFinite(value) && value > 0)) throw new RangeError("Canvas dimensions must be finite and positive.");
|
|
5262
5314
|
const scale = Math.min(width, height) / 720;
|
|
@@ -5264,7 +5316,7 @@ function composeSlide(input, options = {}) {
|
|
|
5264
5316
|
const rtl = deckDirection === "rtl", textDirection = rtl ? "rtl" : void 0;
|
|
5265
5317
|
const hints = resolveDesignHints({ slide, layout, presentation: options.presentation, slideIndex: options.slideIndex, deck: { titleAlignment: options.titleAlignment, contentAlignment: options.contentAlignment, contentBox: options.contentBox } });
|
|
5266
5318
|
const hasCards = hints.contentBox ?? false;
|
|
5267
|
-
const composition = { ...
|
|
5319
|
+
const composition = { ...record6(layout.composition), ...record6(slide.composition) };
|
|
5268
5320
|
assertComposition(composition);
|
|
5269
5321
|
const padding = (composition.padding ?? 0.08) * Math.min(width, height);
|
|
5270
5322
|
const gap = (composition.gap ?? 1 / 30) * Math.min(width, height);
|
|
@@ -5345,16 +5397,16 @@ function composeSlide(input, options = {}) {
|
|
|
5345
5397
|
const mirrorSide = (side) => !rtl ? side : side === "left" ? "right" : side === "right" ? "left" : side;
|
|
5346
5398
|
const backgroundImage = resolveBackgroundImage(slide, options.presentation, options.themeBackground, width, height, path, mirrorSide, imageDiagnostics);
|
|
5347
5399
|
const regions = Object.keys(slide).filter((key) => regionParts(key)).sort();
|
|
5348
|
-
const assets =
|
|
5400
|
+
const assets = record6(options.presentation).assets;
|
|
5349
5401
|
const imageContext = (placement) => ({ fit: hints.imageFit, scale, mirrorSide, diagnostics: imageDiagnostics, assets, ...placement ? { placement } : {} });
|
|
5350
5402
|
const area = { left: 0, top: 0, right: width, bottom: height };
|
|
5351
|
-
const imagePlaceholders = (
|
|
5352
|
-
const topImages = regions.length ? [] : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => !Array.isArray(
|
|
5403
|
+
const imagePlaceholders = layoutLeaves(layout).flatMap((leaf) => leaf.type === "image" ? [{ placeholder: leaf.placeholder, path: leaf.path, depth: leaf.depth }] : []);
|
|
5404
|
+
const topImages = regions.length ? [] : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => !Array.isArray(record6(block).blocks) && record6(block).image !== void 0 ? [{ host: record6(block), hostPath: `${path}.blocks.${index}`, block: index }] : []) : slide.image !== void 0 ? [{ host: { type: "image", image: slide.image }, hostPath: path }] : [];
|
|
5353
5405
|
const placed = [], usedEdges = /* @__PURE__ */ new Set();
|
|
5354
5406
|
topImages.forEach((node, order) => {
|
|
5355
5407
|
const slot = imagePlaceholders[order];
|
|
5356
|
-
const own2 = node.block !== void 0 && node.host.placement !== void 0 ?
|
|
5357
|
-
const value = own2 ?? (slot?.placeholder.placement !== void 0 ?
|
|
5408
|
+
const own2 = node.block !== void 0 && node.host.placement !== void 0 ? record6(node.host.placement) : void 0;
|
|
5409
|
+
const value = own2 ?? (slot?.depth === 0 && slot.placeholder.placement !== void 0 ? record6(slot.placeholder.placement) : void 0);
|
|
5358
5410
|
if (!value || !IMAGE_EDGES.includes(value.edge)) return;
|
|
5359
5411
|
const edge = mirrorSide(value.edge);
|
|
5360
5412
|
if (usedEdges.has(edge)) return;
|
|
@@ -5367,7 +5419,7 @@ function composeSlide(input, options = {}) {
|
|
|
5367
5419
|
else if (edge === "right") area.right = region.x;
|
|
5368
5420
|
else if (edge === "top") area.top += band;
|
|
5369
5421
|
else area.bottom = region.y;
|
|
5370
|
-
const placement = { edge, size, inset: value.inset === true, path: own2 ? `${node.hostPath}.placement` :
|
|
5422
|
+
const placement = { edge, size, inset: value.inset === true, path: own2 ? `${node.hostPath}.placement` : `${slot.path}.placement` };
|
|
5371
5423
|
placed.push({ ...node, placement, region, slot: order });
|
|
5372
5424
|
});
|
|
5373
5425
|
const placedBlocks = new Set(placed.flatMap((entry) => entry.block !== void 0 ? [entry.block] : []));
|
|
@@ -5390,7 +5442,7 @@ function composeSlide(input, options = {}) {
|
|
|
5390
5442
|
const emptyPayload = (value) => value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
|
|
5391
5443
|
const emptyHost = (host) => emptyPayload(host.blocks) && fields.every((field) => emptyPayload(host[field]));
|
|
5392
5444
|
const flowBlocks = Array.isArray(slide.blocks) ? slide.blocks.filter((_, index) => !placedBlocks.has(index)) : slide.blocks;
|
|
5393
|
-
const hasBodyPayload = regions.some((key) => !emptyHost(
|
|
5445
|
+
const hasBodyPayload = regions.some((key) => !emptyHost(record6(slide[key]))) || !emptyPayload(flowBlocks) || fields.some((field) => !(placedRoot && field === "image") && !emptyPayload(slide[field]));
|
|
5394
5446
|
const isCover = !hasBodyPayload && (headingOnlyLayout || !hasLayoutRecord);
|
|
5395
5447
|
coverGroup = isCover;
|
|
5396
5448
|
let logo;
|
|
@@ -5457,7 +5509,7 @@ function composeSlide(input, options = {}) {
|
|
|
5457
5509
|
const collect = (host, basePath, depth = 0, ancestors = []) => {
|
|
5458
5510
|
if (Array.isArray(host.blocks)) {
|
|
5459
5511
|
if (depth >= MAX_COMPOSITION_DEPTH || ancestors.includes(host)) throw new RangeError(`Content groups must be acyclic and nest at most ${MAX_COMPOSITION_DEPTH} levels.`);
|
|
5460
|
-
const settings =
|
|
5512
|
+
const settings = record6(host.composition);
|
|
5461
5513
|
assertComposition(settings);
|
|
5462
5514
|
return [{
|
|
5463
5515
|
field: "blocks",
|
|
@@ -5466,7 +5518,7 @@ function composeSlide(input, options = {}) {
|
|
|
5466
5518
|
path: basePath,
|
|
5467
5519
|
payload: host,
|
|
5468
5520
|
composition: settings,
|
|
5469
|
-
children: host.blocks.flatMap((block, index) => collect(
|
|
5521
|
+
children: host.blocks.flatMap((block, index) => collect(record6(block), `${basePath}.blocks.${index}`, depth + 1, [...ancestors, host]))
|
|
5470
5522
|
}];
|
|
5471
5523
|
}
|
|
5472
5524
|
const captioned = host.caption !== void 0 ? fields.filter((field) => host[field] !== void 0 && CAPTIONABLE_FIELDS.includes(field)) : [];
|
|
@@ -5482,7 +5534,7 @@ function composeSlide(input, options = {}) {
|
|
|
5482
5534
|
}));
|
|
5483
5535
|
};
|
|
5484
5536
|
const regionsInReadingOrder = visualReadingOrder(regions.map((key) => ({ key, box: regionBox(regionParts(key), contentBox, gap) }))).map((entry) => entry.key);
|
|
5485
|
-
const pending = regions.length ? regionsInReadingOrder.flatMap((key) => collect(
|
|
5537
|
+
const pending = regions.length ? regionsInReadingOrder.flatMap((key) => collect(record6(slide[key]), `${path}.${key}`).map((item) => ({ ...item, region: regionParts(key) }))) : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => placedBlocks.has(index) ? [] : collect(record6(block), `${path}.blocks.${index}`)) : collect(placedRoot ? { ...slide, image: void 0 } : slide, path);
|
|
5486
5538
|
const groups = [], flows = [];
|
|
5487
5539
|
const decisions = options.explain ? [] : void 0;
|
|
5488
5540
|
const inheritedSettings = (parent, own2 = {}) => ({
|
|
@@ -5580,12 +5632,23 @@ function composeSlide(input, options = {}) {
|
|
|
5580
5632
|
};
|
|
5581
5633
|
const scoreNode = (node, box, settings, penalties) => {
|
|
5582
5634
|
if (!node.children) return leafScore(node, box, settings, penalties);
|
|
5583
|
-
const own2 = inheritedSettings(settings, node.composition), area2 = inset(box, own2);
|
|
5584
|
-
const cols = defaultColumns(
|
|
5585
|
-
const boxes = gridBoxes(
|
|
5635
|
+
const own2 = inheritedSettings(settings, node.composition), area2 = inset(box, own2), slotCount = Math.max(node.children.length, node.reserved ?? 0);
|
|
5636
|
+
const cols = defaultColumns(slotCount, area2, own2);
|
|
5637
|
+
const boxes = gridBoxes(slotCount, area2, cols, (own2.gap ?? 1 / 30) * Math.min(box.width, box.height), own2.weights ?? [], modeFor(own2) === "column");
|
|
5586
5638
|
return node.children.reduce((score, child, index) => score + scoreNode(child, boxes[index], own2, penalties), 0);
|
|
5587
5639
|
};
|
|
5588
|
-
const
|
|
5640
|
+
const slots = [];
|
|
5641
|
+
const emptySlots = (entries, boxes, settings) => entries.forEach((entry, index) => {
|
|
5642
|
+
const box = boxes[index];
|
|
5643
|
+
if (!box) return;
|
|
5644
|
+
slots.push({ path: entry.path, type: entry.type, depth: entry.depth, box: acceptedBox(box) });
|
|
5645
|
+
if (!entry.children) return;
|
|
5646
|
+
const own2 = inheritedSettings(settings, record6(entry.placeholder.composition)), inner = inset(box, own2);
|
|
5647
|
+
const cols = defaultColumns(entry.children.length, inner, own2);
|
|
5648
|
+
const mirror = (cell) => rtl ? { ...cell, x: inner.x + inner.width - (cell.x - inner.x) - cell.width } : cell;
|
|
5649
|
+
emptySlots(entry.children, gridBoxes(entry.children.length, inner, cols, (own2.gap ?? 1 / 30) * Math.min(box.width, box.height), own2.weights ?? [], modeFor(own2) === "column").map(mirror), own2);
|
|
5650
|
+
});
|
|
5651
|
+
const arrange = (nodes, area2, settings, reserved = 0, gapOverride, containerPath = path, recorded = true, template) => {
|
|
5589
5652
|
const count = Math.max(nodes.length, reserved);
|
|
5590
5653
|
if (!count) return;
|
|
5591
5654
|
const mode = modeFor(settings), localGap = (settings.gap ?? 1 / 30) * Math.min(area2.width, area2.height);
|
|
@@ -5597,9 +5660,9 @@ function composeSlide(input, options = {}) {
|
|
|
5597
5660
|
let best = Infinity;
|
|
5598
5661
|
for (let candidate = 1; candidate <= Math.min(count, settings.columns ?? 6); candidate++) {
|
|
5599
5662
|
const boxes2 = gridBoxes(count, area2, candidate, actualGap, settings.weights ?? [], false);
|
|
5600
|
-
const
|
|
5601
|
-
const penalties = candidates ? { cellProportions: 0, fontReduction: 0, textOverflow: 0, tableOverflow: 0, smallCells: 0, emptySlots } : void 0;
|
|
5602
|
-
const score = nodes.reduce((sum, node, i) => sum + scoreNode(node, boxes2[i], settings, penalties), 0) +
|
|
5663
|
+
const emptySlots2 = (Math.ceil(count / candidate) * candidate - count) * 2;
|
|
5664
|
+
const penalties = candidates ? { cellProportions: 0, fontReduction: 0, textOverflow: 0, tableOverflow: 0, smallCells: 0, emptySlots: emptySlots2 } : void 0;
|
|
5665
|
+
const score = nodes.reduce((sum, node, i) => sum + scoreNode(node, boxes2[i], settings, penalties), 0) + emptySlots2;
|
|
5603
5666
|
if (penalties && candidates) candidates.push({ columns: candidate, rows: Math.ceil(count / candidate), score, penalties });
|
|
5604
5667
|
if (score < best) {
|
|
5605
5668
|
best = score;
|
|
@@ -5617,13 +5680,15 @@ function composeSlide(input, options = {}) {
|
|
|
5617
5680
|
const grid = gridGeometry(count, area2, cols, actualGap, settings.weights ?? [], mode === "column");
|
|
5618
5681
|
const mirrored = (box) => rtl ? { ...box, x: area2.x + area2.width - (box.x - area2.x) - box.width } : box;
|
|
5619
5682
|
const boxes = grid.boxes.map(mirrored);
|
|
5683
|
+
if (template) emptySlots(template.slice(nodes.length), boxes.slice(nodes.length), settings);
|
|
5620
5684
|
if (recorded && !hasRegions) flows.push({ path: containerPath, box: { ...area2 }, composition: { ...settings }, columns: rtl ? grid.columns.map((track) => ({ offset: area2.width - track.offset - track.size, size: track.size })) : grid.columns, rows: grid.rows, gap: grid.gap, itemCount: nodes.length, slotCount: count });
|
|
5621
5685
|
nodes.forEach((node, index) => {
|
|
5622
5686
|
let box = node.region ? mirrored(regionBox(node.region, area2, actualGap)) : boxes[index];
|
|
5687
|
+
if (node.slot) slots.push({ path: node.slot.path, type: node.slot.type, depth: node.slot.depth, box: acceptedBox(box), ...node.slot.children ? {} : { content: node.path } });
|
|
5623
5688
|
if (node.children) {
|
|
5624
5689
|
const own2 = inheritedSettings(settings, node.composition), inner = inset(box, own2);
|
|
5625
5690
|
if (!node.synthetic) groups.push({ path: node.path, box, contentBox: inner, composition: own2 });
|
|
5626
|
-
arrange(node.children, inner, own2, 0, (own2.gap ?? 1 / 30) * Math.min(box.width, box.height), node.path, !node.synthetic);
|
|
5691
|
+
arrange(node.children, inner, own2, node.reserved ?? 0, (own2.gap ?? 1 / 30) * Math.min(box.width, box.height), node.path, !node.synthetic, node.slots);
|
|
5627
5692
|
} else {
|
|
5628
5693
|
const frameBox = hasCards ? acceptedBox(box) : void 0;
|
|
5629
5694
|
box = payloadBox(box);
|
|
@@ -5669,18 +5734,59 @@ function composeSlide(input, options = {}) {
|
|
|
5669
5734
|
if (placedSlots.size) {
|
|
5670
5735
|
for (let index = placeholders.length - 1; index >= 0; index--) if (placedSlots.has(placeholders[index])) placeholders.splice(index, 1);
|
|
5671
5736
|
}
|
|
5672
|
-
const ownMode =
|
|
5737
|
+
const ownMode = record6(slide.composition).mode;
|
|
5673
5738
|
const direction = hints.contentDirection;
|
|
5674
5739
|
const directionMode = direction === "vertical" ? "column" : direction === "horizontal" ? "row" : "auto";
|
|
5675
5740
|
const chartHint = hints.chartPrimary;
|
|
5676
5741
|
const chartSide = chartHint === "left" || chartHint === "right" || chartHint === "top" || chartHint === "bottom" ? chartHint : void 0;
|
|
5677
5742
|
const chartIndex = pending.findIndex((node) => !node.children && node.field === "chart");
|
|
5678
5743
|
const chartPrimary = chartSide !== void 0 && !ownMode && !regions.length && chartIndex >= 0 && pending.some((node) => node.children || node.field !== "chart") ? chartSide : void 0;
|
|
5679
|
-
const
|
|
5680
|
-
|
|
5744
|
+
const kindOf = (node) => node.children ? node.children[0] ? kindOf(node.children[0]) : "text" : FIELD_KINDS[node.field] ?? "text";
|
|
5745
|
+
const sugar = chartPrimary ? chartPrimaryLayout(chartPrimary, pending.filter((_, index) => index !== chartIndex).map(kindOf)) : void 0;
|
|
5746
|
+
const rootSettings = sugar ? { ...composition, ...sugar.composition, columns: void 0 } : { ...composition, mode: composition.mode ?? directionMode };
|
|
5747
|
+
const recordSlots = sugar ? [] : layoutSlots(layout).filter((slot) => !headings.has(slot.type) && !placedSlots.has(slot.placeholder));
|
|
5748
|
+
const templated = !sugar && !regions.length && recordSlots.some((slot) => slot.children) && pending.every((node) => !node.children);
|
|
5749
|
+
const fillSlots = (entries, queue, cursor, recordSlot) => {
|
|
5750
|
+
const nodes = [];
|
|
5751
|
+
for (const entry of entries) {
|
|
5752
|
+
if (cursor.next >= queue.length) break;
|
|
5753
|
+
if (!entry.children) {
|
|
5754
|
+
nodes.push({ ...queue[cursor.next++], ...recordSlot ? { slot: entry } : {} });
|
|
5755
|
+
continue;
|
|
5756
|
+
}
|
|
5757
|
+
const own2 = record6(entry.placeholder.composition);
|
|
5758
|
+
assertComposition(own2);
|
|
5759
|
+
const children = fillSlots(entry.children, queue, cursor, recordSlot);
|
|
5760
|
+
nodes.push({
|
|
5761
|
+
field: "blocks",
|
|
5762
|
+
type: "group",
|
|
5763
|
+
value: children.map((child) => child.payload),
|
|
5764
|
+
path,
|
|
5765
|
+
payload: {},
|
|
5766
|
+
children,
|
|
5767
|
+
composition: own2,
|
|
5768
|
+
synthetic: true,
|
|
5769
|
+
reserved: own2.mode ? 0 : entry.children.length,
|
|
5770
|
+
...recordSlot ? { slot: entry, slots: entry.children } : {}
|
|
5771
|
+
});
|
|
5772
|
+
}
|
|
5773
|
+
return nodes;
|
|
5774
|
+
};
|
|
5775
|
+
if (sugar) {
|
|
5681
5776
|
const primary = pending[chartIndex], rest = pending.filter((_, index) => index !== chartIndex);
|
|
5682
|
-
const
|
|
5683
|
-
arrange(
|
|
5777
|
+
const queue = chartPrimary === "left" || chartPrimary === "top" ? [primary, ...rest] : [...rest, primary];
|
|
5778
|
+
arrange(fillSlots(layoutSlots(sugar, "design.chartPrimary"), queue, { next: 0 }, false), contentBox, rootSettings, 0);
|
|
5779
|
+
} else if (templated) {
|
|
5780
|
+
const cursor = { next: 0 };
|
|
5781
|
+
const nodes = fillSlots(recordSlots, pending, cursor, true);
|
|
5782
|
+
arrange([...nodes, ...pending.slice(cursor.next)], contentBox, rootSettings, composition.mode ? 0 : placeholders.length, void 0, path, true, recordSlots);
|
|
5783
|
+
const order = /* @__PURE__ */ new Map();
|
|
5784
|
+
const number = (entries) => entries.forEach((entry) => {
|
|
5785
|
+
order.set(entry.path, order.size);
|
|
5786
|
+
if (entry.children) number(entry.children);
|
|
5787
|
+
});
|
|
5788
|
+
number(recordSlots);
|
|
5789
|
+
slots.sort((a, b) => order.get(a.path) - order.get(b.path));
|
|
5684
5790
|
} else arrange(pending, contentBox, rootSettings, composition.mode ? 0 : placeholders.length);
|
|
5685
5791
|
if (listBullet?.value === "image" && !bulletImage && items.some((item) => (item.field === "items" || item.field === "bullets") && item.payload.numbering === void 0)) {
|
|
5686
5792
|
diagnostics.push({ code: "unresolved-content", path: listBullet.path, message: "Picture bullets (listBullet: image) need design.logo or a primary organization logo; the marker glyph is drawn instead." });
|
|
@@ -5721,7 +5827,8 @@ function composeSlide(input, options = {}) {
|
|
|
5721
5827
|
} : void 0;
|
|
5722
5828
|
if (failures.length) throw new OPFCompositionError(failures, explanation);
|
|
5723
5829
|
diagnostics.push(...imageDiagnostics, ...numberingDiagnostics);
|
|
5724
|
-
|
|
5830
|
+
for (const slot of slots) for (const key of ["x", "y", "width", "height"]) slot.box[key] = round2(slot.box[key]);
|
|
5831
|
+
return { width, height, contentBox, items, groups, flows, ...slots.length ? { slots } : {}, diagnostics, composition, design: hints, ...furniture ? { furniture } : {}, ...backgroundImage ? { backgroundImage } : {}, ...logo ? { logo } : {}, ...rtl ? { direction: "rtl" } : {}, ...footnotes ? { footnotes } : {}, ...explanation ? { explanation } : {} };
|
|
5725
5832
|
}
|
|
5726
5833
|
function resolveCanvasDimensions(input) {
|
|
5727
5834
|
const presets = {
|
|
@@ -5736,7 +5843,7 @@ function resolveCanvasDimensions(input) {
|
|
|
5736
5843
|
letter: [11, 8.5],
|
|
5737
5844
|
a4: [11.69, 8.27]
|
|
5738
5845
|
};
|
|
5739
|
-
const value =
|
|
5846
|
+
const value = record6(input);
|
|
5740
5847
|
const preset = presets[typeof input === "string" ? input : value.preset] ?? presets.widescreen;
|
|
5741
5848
|
const width = (value.widthInches ?? preset[0]) * 96;
|
|
5742
5849
|
const height = (value.heightInches ?? preset[1]) * 96;
|
|
@@ -5744,4 +5851,4 @@ function resolveCanvasDimensions(input) {
|
|
|
5744
5851
|
return { width, height };
|
|
5745
5852
|
}
|
|
5746
5853
|
|
|
5747
|
-
export { CAPTIONABLE_FIELDS, CAPTION_FONT_RATIO, CAPTION_MAX_RATIO, CHART_HIGHLIGHT_MUTED_MIN_CONTRAST, CHART_HIGHLIGHT_MUTED_MIX, CHART_SERIES_MIN_DIFFERENCE, CHART_SERIES_MIN_LIGHTNESS_STEP, CHART_TYPES, CITATION_MARKER_RAISE, CITATION_MARKER_SCALE, CODE_HIGHLIGHT_LANGUAGES, CODE_HIGHLIGHT_MAX_LENGTH, CODE_PANEL_BACKGROUND, CODE_PANEL_FOREGROUND, CODE_SYNTAX_MIN_CONTRAST, DARK_BACKGROUND_LUMINANCE, DEFAULT_CHART_LABEL_SEPARATOR, DEFAULT_FURNITURE_DATE_FORMAT, DEFAULT_SLIDE_NUMBER_FORMAT, DEFAULT_VARIABLE_DATE_FORMAT, DESIGN_HINT_KEYS, ENGINE_DEFAULT_CHART_TYPES, ENGINE_DEFAULT_COLOR_SCHEME, ENGINE_DEFAULT_FONT_SCHEME, ENGINE_DEFAULT_THEME, FONT_SIZE_GRID_PER_PX, FOOTNOTE_MAX_RATIO, LANGUAGES, LAYOUT_BODY_KINDS, MAX_COMPOSITION_DEPTH, MAX_NUMBERING_LEVELS, MAX_NUMBERING_VALUE, MAX_ROMAN_VALUE, METRIC_TREND_MIN_CONTRAST, METRIC_TREND_SHAPES, NUMBERING_STYLES, NUMBERING_SUFFIXES, OPFCompositionError, OPFVariableError, PATTERN_PRESETS, PATTERN_PRESET_ALIASES, PATTERN_TILE_SIZE, PICTURE_BULLET_SCALE, SOCIAL_PLATFORMS, SURFACE_ALT_MIN_CONTRAST, SURFACE_ALT_MIX, TIMELINE_OUTLINE_MIN_CONTRAST, TIMELINE_STATUSES, TIMELINE_TEXT_MIN_CONTRAST, VARIABLE_KINDS, annotationText, captionSettings, chartColorForFill, chartHighlightColors, chartHighlightMarks, chartLabelText, chartNumber, chartNumberFixesByCell, chartOptionSupport, chartOptionTarget, chartPaletteForFill, citationMarkerText, codeHighlightBands, codeHighlightColors, codeHighlightLines, codeHighlightSlice, codeLineNumbers, codeLineRuns, codeSyntaxPalette, codeSyntaxPaletteForScheme, coerceVariableValue, collectCitations, colorContrast, composeSlide, datasetDiagnostics, defaultSlideBackground, fitImage, fitList, fitRichText, fitText, formatChartLabelNumber, formatChartLabelPercent, formatDataNumber, formatFurnitureDate, formatListNumber, formatSlideNumber, formatVariableNumber, fromExcelNumberFormat, hasContentVariables, imageBackground, imageShape, inlineChartData, inlineDatasets, inlineTableData, instantiateForValidation, intrinsicImageAspect, intrinsicImageSize, isDarkColor, isDatasetRef, isRecord, isTemplate, isXYChartType, layoutCaption, layoutCode, layoutContent, layoutFootnotes, layoutFurniture, layoutMetric, layoutQuote, layoutTable, layoutTimeline, layoutWatermark, listBuiltinVariables, listNumbers, listVariables, measureText, measureTextOutline, metricTrendColor, metricTrendMark, metricTrendPoints, normalizeHexColor, normalizeLanguageFamily, numberFormatError, numberingAtLevel, numberingFindings, numberingStyleDraws, paragraphDirection, paragraphDirectionAt, pathFor, patternBitmap, patternRuns, physicalAlignment, placeTextLines, promotedRegionKeys, readingRows, referencesSlide, resolveCanvasDimensions, resolveChartData, resolveChartOptions, resolveCodeLanguage, resolveColorRef, resolveColorRoles, resolveDesignHints, resolveDesignRecords, resolveFontFamilies, resolveFontScheme, resolveLogo, resolveNumbering, resolvePatternPreset, resolveScriptFonts, resolveSlideDirection, resolveSocialProfile, resolveTableData, resolveTextStyle, resolveVariables, scriptFontRole, sliceNumberedItems, slideCitations, snapFontSizeDown, snapFontSizeUp, suggestChartNumberFix, surfaceAltColor, tableCellDisplayValue, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, timelineMarkerShapes, timelineTextColor, toExcelNumberFormat, tokenizeCode, unusedDatasets, variableDeclarations, visitContentPayloads, visualReadingOrder, walkCitationRuns, wrapText };
|
|
5854
|
+
export { CAPTIONABLE_FIELDS, CAPTION_FONT_RATIO, CAPTION_MAX_RATIO, CHART_HIGHLIGHT_MUTED_MIN_CONTRAST, CHART_HIGHLIGHT_MUTED_MIX, CHART_SERIES_MIN_DIFFERENCE, CHART_SERIES_MIN_LIGHTNESS_STEP, CHART_TYPES, CITATION_MARKER_RAISE, CITATION_MARKER_SCALE, CODE_HIGHLIGHT_LANGUAGES, CODE_HIGHLIGHT_MAX_LENGTH, CODE_PANEL_BACKGROUND, CODE_PANEL_FOREGROUND, CODE_SYNTAX_MIN_CONTRAST, DARK_BACKGROUND_LUMINANCE, DEFAULT_CHART_LABEL_SEPARATOR, DEFAULT_FURNITURE_DATE_FORMAT, DEFAULT_SLIDE_NUMBER_FORMAT, DEFAULT_VARIABLE_DATE_FORMAT, DESIGN_HINT_KEYS, ENGINE_DEFAULT_CHART_TYPES, ENGINE_DEFAULT_COLOR_SCHEME, ENGINE_DEFAULT_FONT_SCHEME, ENGINE_DEFAULT_THEME, FONT_SIZE_GRID_PER_PX, FOOTNOTE_MAX_RATIO, LANGUAGES, LAYOUT_BODY_KINDS, MAX_COMPOSITION_DEPTH, MAX_NUMBERING_LEVELS, MAX_NUMBERING_VALUE, MAX_PLACEHOLDER_GROUP_DEPTH, MAX_ROMAN_VALUE, METRIC_TREND_MIN_CONTRAST, METRIC_TREND_SHAPES, NUMBERING_STYLES, NUMBERING_SUFFIXES, OPFCompositionError, OPFVariableError, PATTERN_PRESETS, PATTERN_PRESET_ALIASES, PATTERN_TILE_SIZE, PICTURE_BULLET_SCALE, SOCIAL_PLATFORMS, SURFACE_ALT_MIN_CONTRAST, SURFACE_ALT_MIX, TIMELINE_OUTLINE_MIN_CONTRAST, TIMELINE_STATUSES, TIMELINE_TEXT_MIN_CONTRAST, VARIABLE_KINDS, annotationText, captionSettings, chartColorForFill, chartHighlightColors, chartHighlightMarks, chartLabelText, chartNumber, chartNumberFixesByCell, chartOptionSupport, chartOptionTarget, chartPaletteForFill, chartPrimaryLayout, citationMarkerText, codeHighlightBands, codeHighlightColors, codeHighlightLines, codeHighlightSlice, codeLineNumbers, codeLineRuns, codeSyntaxPalette, codeSyntaxPaletteForScheme, coerceVariableValue, collectCitations, colorContrast, composeSlide, datasetDiagnostics, defaultSlideBackground, fitImage, fitList, fitRichText, fitText, formatChartLabelNumber, formatChartLabelPercent, formatDataNumber, formatFurnitureDate, formatListNumber, formatSlideNumber, formatVariableNumber, fromExcelNumberFormat, hasContentVariables, hasPlaceholderGroups, imageBackground, imageShape, inlineChartData, inlineDatasets, inlineTableData, instantiateForValidation, intrinsicImageAspect, intrinsicImageSize, isDarkColor, isDatasetRef, isPlaceholderGroup, isRecord, isTemplate, isXYChartType, layoutCaption, layoutCode, layoutContent, layoutFootnotes, layoutFurniture, layoutLeaves, layoutMetric, layoutQuote, layoutSlots, layoutStructure, layoutTable, layoutTimeline, layoutWatermark, listBuiltinVariables, listNumbers, listVariables, measureText, measureTextOutline, metricTrendColor, metricTrendMark, metricTrendPoints, normalizeHexColor, normalizeLanguageFamily, numberFormatError, numberingAtLevel, numberingFindings, numberingStyleDraws, paragraphDirection, paragraphDirectionAt, pathFor, patternBitmap, patternRuns, physicalAlignment, placeTextLines, promotedRegionKeys, readingRows, referencesSlide, resolveCanvasDimensions, resolveChartData, resolveChartOptions, resolveCodeLanguage, resolveColorRef, resolveColorRoles, resolveDesignHints, resolveDesignRecords, resolveFontFamilies, resolveFontScheme, resolveLogo, resolveNumbering, resolvePatternPreset, resolveScriptFonts, resolveSlideDirection, resolveSocialProfile, resolveTableData, resolveTextStyle, resolveVariables, scriptFontRole, sliceNumberedItems, slideCitations, snapFontSizeDown, snapFontSizeUp, suggestChartNumberFix, surfaceAltColor, tableCellDisplayValue, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, timelineMarkerShapes, timelineTextColor, toExcelNumberFormat, tokenizeCode, unusedDatasets, variableDeclarations, visitContentPayloads, visualReadingOrder, walkCitationRuns, wrapText };
|