@openpresentation/opf 0.11.2 → 0.11.4
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-DJ-B5ZyD.d.ts → catalogs-CUClB3nl.d.ts} +202 -5
- package/dist/catalogs.d.ts +1 -1
- package/dist/catalogs.js +1 -1
- package/dist/{chunk-BVLWFMDX.js → chunk-3H2U7FDR.js} +224 -26
- package/dist/{chunk-K7IWYODS.js → chunk-3OJN7QAW.js} +17 -4
- package/dist/{chunk-7LF37SG3.js → chunk-AEUSVEUY.js} +4915 -1640
- package/dist/{chunk-DJRZMGKY.js → chunk-FDCWQHWO.js} +143 -68
- package/dist/{chunk-SDETQV7Y.js → chunk-HJL64ETN.js} +505 -0
- package/dist/{chunk-LTSDDBNW.js → chunk-KJKASEPE.js} +262 -23
- package/dist/{chunk-SMYEM3HV.js → chunk-NSVVQ52O.js} +7 -6
- package/dist/{chunk-KZ6BT5UG.js → chunk-RXNFDGPC.js} +5 -5
- package/dist/{composition-DzLwY-Mi.d.ts → composition-Dl-d9FRj.d.ts} +93 -6
- package/dist/composition.d.ts +1 -1
- package/dist/composition.js +1 -1
- package/dist/docs.js +21 -15
- package/dist/examples.d.ts +1 -1
- package/dist/font-policy.js +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +11 -11
- package/dist/lint.d.ts +2 -2
- package/dist/lint.js +5 -5
- package/dist/pagination.d.ts +1 -1
- package/dist/pagination.js +5 -5
- package/dist/{presentation-bceTClm8.d.ts → presentation-j5PVrqfV.d.ts} +41 -29
- package/dist/repo-readme.js +1 -1
- package/dist/schemas.js +1 -1
- package/dist/spec/README.md +3 -2
- package/dist/spec/catalogs/audiences/index.json +2 -0
- package/dist/spec/catalogs/chart-types/box-and-whisker.json +101 -49
- package/dist/spec/catalogs/chart-types/histogram.json +130 -108
- package/dist/spec/catalogs/chart-types/index.json +2 -0
- package/dist/spec/catalogs/chart-types/pareto.json +22 -106
- package/dist/spec/catalogs/color-schemes/black-and-white.json +10 -1
- package/dist/spec/catalogs/color-schemes/bold-red.json +10 -1
- package/dist/spec/catalogs/color-schemes/boost.json +10 -1
- package/dist/spec/catalogs/color-schemes/burnt-orange.json +10 -1
- package/dist/spec/catalogs/color-schemes/cool-horizon.json +10 -1
- package/dist/spec/catalogs/color-schemes/corporate-blue.json +10 -1
- package/dist/spec/catalogs/color-schemes/deep-purple.json +10 -1
- package/dist/spec/catalogs/color-schemes/forest-green.json +10 -1
- package/dist/spec/catalogs/color-schemes/golden-yellow.json +10 -1
- package/dist/spec/catalogs/color-schemes/index.json +2 -0
- package/dist/spec/catalogs/color-schemes/luxury.json +10 -1
- package/dist/spec/catalogs/color-schemes/pastel-red.json +10 -1
- package/dist/spec/catalogs/color-schemes/slate-gray.json +10 -1
- package/dist/spec/catalogs/color-schemes/steel-blue.json +10 -1
- package/dist/spec/catalogs/color-schemes/vibes.json +10 -1
- package/dist/spec/catalogs/font-schemes/angsana-new.json +2 -1
- package/dist/spec/catalogs/font-schemes/aparajita.json +2 -1
- package/dist/spec/catalogs/font-schemes/aptos.json +2 -1
- package/dist/spec/catalogs/font-schemes/arabic-typesetting.json +2 -1
- package/dist/spec/catalogs/font-schemes/arial.json +2 -1
- package/dist/spec/catalogs/font-schemes/batang.json +2 -1
- package/dist/spec/catalogs/font-schemes/bookman.json +2 -1
- package/dist/spec/catalogs/font-schemes/calibri.json +2 -1
- package/dist/spec/catalogs/font-schemes/century-schoolbook.json +2 -1
- package/dist/spec/catalogs/font-schemes/consolas.json +2 -1
- package/dist/spec/catalogs/font-schemes/constantia.json +2 -1
- package/dist/spec/catalogs/font-schemes/courier-new.json +2 -1
- package/dist/spec/catalogs/font-schemes/daunpenh.json +2 -1
- package/dist/spec/catalogs/font-schemes/david.json +2 -1
- package/dist/spec/catalogs/font-schemes/dilleniaupc.json +2 -1
- package/dist/spec/catalogs/font-schemes/fangsong.json +2 -1
- package/dist/spec/catalogs/font-schemes/garamond.json +2 -1
- package/dist/spec/catalogs/font-schemes/gautami.json +2 -1
- package/dist/spec/catalogs/font-schemes/georgia.json +2 -1
- package/dist/spec/catalogs/font-schemes/gisha.json +2 -1
- package/dist/spec/catalogs/font-schemes/grandview.json +2 -1
- package/dist/spec/catalogs/font-schemes/gungsuh.json +2 -1
- package/dist/spec/catalogs/font-schemes/impact.json +2 -1
- package/dist/spec/catalogs/font-schemes/index.json +236 -234
- package/dist/spec/catalogs/font-schemes/kalinga.json +2 -1
- package/dist/spec/catalogs/font-schemes/kartika.json +2 -1
- package/dist/spec/catalogs/font-schemes/khmer-ui.json +2 -1
- package/dist/spec/catalogs/font-schemes/latha.json +2 -1
- package/dist/spec/catalogs/font-schemes/lucida-sans.json +2 -1
- package/dist/spec/catalogs/font-schemes/malgun-gothic.json +2 -1
- package/dist/spec/catalogs/font-schemes/mangal.json +2 -1
- package/dist/spec/catalogs/font-schemes/meiryo.json +2 -1
- package/dist/spec/catalogs/font-schemes/microsoft-jhenghei.json +2 -1
- package/dist/spec/catalogs/font-schemes/microsoft-yahei.json +2 -1
- package/dist/spec/catalogs/font-schemes/mingliu.json +2 -1
- package/dist/spec/catalogs/font-schemes/miriam.json +2 -1
- package/dist/spec/catalogs/font-schemes/montserrat.json +2 -1
- package/dist/spec/catalogs/font-schemes/ms-mincho.json +2 -1
- package/dist/spec/catalogs/font-schemes/nirmala-ui.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-naksh-arabic.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-nastaliq-urdu.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-arabic.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-armenian.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-bengali.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-devangari.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-ethiopic.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-georgian.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-gujarati.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-gurmukhi.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-hebrew.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-jp.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-kannada.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-khmer.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-kr.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-malayalam.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-mongolian.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-oriya.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-sc.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-tamil.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-tc.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-telugu.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans-thai.json +2 -1
- package/dist/spec/catalogs/font-schemes/noto-sans.json +2 -1
- package/dist/spec/catalogs/font-schemes/nyala.json +2 -1
- package/dist/spec/catalogs/font-schemes/open-sans.json +2 -1
- package/dist/spec/catalogs/font-schemes/pmingliu.json +2 -1
- package/dist/spec/catalogs/font-schemes/poppins.json +2 -1
- package/dist/spec/catalogs/font-schemes/pt-serif.json +2 -1
- package/dist/spec/catalogs/font-schemes/raavi.json +2 -1
- package/dist/spec/catalogs/font-schemes/raleway.json +2 -1
- package/dist/spec/catalogs/font-schemes/roboto.json +2 -1
- package/dist/spec/catalogs/font-schemes/rockwell.json +2 -1
- package/dist/spec/catalogs/font-schemes/sakkal-majalla.json +2 -1
- package/dist/spec/catalogs/font-schemes/seaford.json +2 -1
- package/dist/spec/catalogs/font-schemes/segoe-ui-light.json +2 -1
- package/dist/spec/catalogs/font-schemes/segoe-ui.json +2 -1
- package/dist/spec/catalogs/font-schemes/shonar-bangla.json +2 -1
- package/dist/spec/catalogs/font-schemes/shruti.json +2 -1
- package/dist/spec/catalogs/font-schemes/simsun.json +2 -1
- package/dist/spec/catalogs/font-schemes/skeena.json +2 -1
- package/dist/spec/catalogs/font-schemes/sylfaen.json +2 -1
- package/dist/spec/catalogs/font-schemes/tahoma.json +2 -1
- package/dist/spec/catalogs/font-schemes/tenorite.json +2 -1
- package/dist/spec/catalogs/font-schemes/times-new-roman.json +2 -1
- package/dist/spec/catalogs/font-schemes/traditional-arabic.json +2 -1
- package/dist/spec/catalogs/font-schemes/trebuchet-ms.json +2 -1
- package/dist/spec/catalogs/font-schemes/tunga.json +2 -1
- package/dist/spec/catalogs/font-schemes/verdana.json +2 -1
- package/dist/spec/catalogs/font-schemes/vrinda.json +2 -1
- package/dist/spec/catalogs/font-schemes/yu-gothic.json +2 -1
- package/dist/spec/catalogs/languages/index.json +2 -0
- package/dist/spec/catalogs/layouts/action-plan.json +35 -0
- package/dist/spec/catalogs/layouts/agenda.json +35 -0
- package/dist/spec/catalogs/layouts/appendix-index.json +38 -0
- package/dist/spec/catalogs/layouts/architecture-stack.json +35 -0
- package/dist/spec/catalogs/layouts/assumptions-dependencies.json +35 -0
- package/dist/spec/catalogs/layouts/before-after.json +41 -0
- package/dist/spec/catalogs/layouts/benchmark-target-table.json +35 -0
- package/dist/spec/catalogs/layouts/bullet-list.json +38 -0
- package/dist/spec/catalogs/layouts/business-model-canvas.json +35 -0
- package/dist/spec/catalogs/layouts/capability-map.json +35 -0
- package/dist/spec/catalogs/layouts/case-study.json +35 -0
- package/dist/spec/catalogs/layouts/chapter-recap.json +35 -0
- package/dist/spec/catalogs/layouts/circular-lifecycle.json +35 -0
- package/dist/spec/catalogs/layouts/comparison.json +41 -0
- package/dist/spec/catalogs/layouts/competitive-landscape.json +35 -0
- package/dist/spec/catalogs/layouts/customer-journey.json +35 -0
- package/dist/spec/catalogs/layouts/customer-logos.json +38 -0
- package/dist/spec/catalogs/layouts/dashboard.json +41 -0
- package/dist/spec/catalogs/layouts/data-visualization.json +45 -0
- package/dist/spec/catalogs/layouts/decision-tree.json +35 -0
- package/dist/spec/catalogs/layouts/detailed-data-table.json +41 -0
- package/dist/spec/catalogs/layouts/ecosystem-map.json +35 -0
- package/dist/spec/catalogs/layouts/executive-decision.json +38 -0
- package/dist/spec/catalogs/layouts/executive-summary.json +38 -0
- package/dist/spec/catalogs/layouts/faq.json +35 -0
- package/dist/spec/catalogs/layouts/feature-comparison-matrix.json +35 -0
- package/dist/spec/catalogs/layouts/forecast-scenario.json +45 -0
- package/dist/spec/catalogs/layouts/funnel-pyramid.json +38 -0
- package/dist/spec/catalogs/layouts/gantt-project-plan.json +38 -0
- package/dist/spec/catalogs/layouts/geographic-map.json +35 -0
- package/dist/spec/catalogs/layouts/heatmap-cohort.json +38 -0
- package/dist/spec/catalogs/layouts/hub-and-spoke.json +35 -0
- package/dist/spec/catalogs/layouts/icon-grid.json +35 -0
- package/dist/spec/catalogs/layouts/image-focus.json +35 -0
- package/dist/spec/catalogs/layouts/index.json +352 -0
- package/dist/spec/catalogs/layouts/key-takeaway.json +32 -0
- package/dist/spec/catalogs/layouts/kpi-scorecard.json +44 -0
- package/dist/spec/catalogs/layouts/logic-tree.json +35 -0
- package/dist/spec/catalogs/layouts/market-size.json +35 -0
- package/dist/spec/catalogs/layouts/matrix-quadrant.json +48 -0
- package/dist/spec/catalogs/layouts/network-dependency-map.json +35 -0
- package/dist/spec/catalogs/layouts/one-column-explainer.json +35 -0
- package/dist/spec/catalogs/layouts/org-chart.json +45 -0
- package/dist/spec/catalogs/layouts/persona-grid.json +35 -0
- package/dist/spec/catalogs/layouts/photo-grid.json +48 -0
- package/dist/spec/catalogs/layouts/pricing-table.json +35 -0
- package/dist/spec/catalogs/layouts/process-flow.json +35 -0
- package/dist/spec/catalogs/layouts/product-feature.json +35 -0
- package/dist/spec/catalogs/layouts/pros-cons.json +41 -0
- package/dist/spec/catalogs/layouts/qa-discussion.json +38 -0
- package/dist/spec/catalogs/layouts/quote-highlight.json +35 -0
- package/dist/spec/catalogs/layouts/raci-matrix.json +35 -0
- package/dist/spec/catalogs/layouts/risk-heatmap.json +35 -0
- package/dist/spec/catalogs/layouts/roadmap.json +35 -0
- package/dist/spec/catalogs/layouts/screenshot-walkthrough.json +35 -0
- package/dist/spec/catalogs/layouts/section-divider.json +35 -0
- package/dist/spec/catalogs/layouts/single-message-statement.json +32 -0
- package/dist/spec/catalogs/layouts/stats-metrics.json +45 -0
- package/dist/spec/catalogs/layouts/status-rag.json +35 -0
- package/dist/spec/catalogs/layouts/swimlane-process.json +35 -0
- package/dist/spec/catalogs/layouts/swot-analysis.json +48 -0
- package/dist/spec/catalogs/layouts/team-bio.json +35 -0
- package/dist/spec/catalogs/layouts/testimonial-grid.json +44 -0
- package/dist/spec/catalogs/layouts/thank-you-cta.json +35 -0
- package/dist/spec/catalogs/layouts/three-column.json +45 -0
- package/dist/spec/catalogs/layouts/timeline.json +38 -0
- package/dist/spec/catalogs/layouts/title-slide.json +35 -0
- package/dist/spec/catalogs/layouts/two-column.json +42 -0
- package/dist/spec/catalogs/layouts/venn-overlap.json +35 -0
- package/dist/spec/catalogs/layouts/waterfall-bridge.json +45 -0
- package/dist/spec/catalogs/layouts/wheel-radial.json +35 -0
- package/dist/spec/catalogs/manifest.json +111 -0
- package/dist/spec/catalogs/narratives/index.json +746 -144
- package/dist/spec/catalogs/purposes/index.json +2 -0
- package/dist/spec/catalogs/social-platforms/index.json +2 -1
- package/dist/spec/catalogs/themes/index.json +10 -8
- package/dist/spec/catalogs/tones/index.json +2 -0
- package/dist/spec/reference/font-policy.json +5 -5
- package/dist/spec/schemas/audience.schema.json +21 -0
- package/dist/spec/schemas/catalog-index.schema.json +40 -3
- package/dist/spec/schemas/catalog-manifest.schema.json +83 -0
- package/dist/spec/schemas/chart-type.schema.json +5 -0
- package/dist/spec/schemas/color-scheme.schema.json +21 -0
- package/dist/spec/schemas/font-scheme.schema.json +21 -0
- package/dist/spec/schemas/language.schema.json +21 -0
- package/dist/spec/schemas/layout.schema.json +21 -0
- package/dist/spec/schemas/narrative.schema.json +21 -0
- package/dist/spec/schemas/opf.schema.json +22 -18
- package/dist/spec/schemas/purpose.schema.json +21 -0
- package/dist/spec/schemas/social-platform.schema.json +26 -5
- package/dist/spec/schemas/theme.schema.json +21 -0
- package/dist/spec/schemas/tone.schema.json +21 -0
- package/dist/spec-files.d.ts +2 -2
- package/dist/spec-files.js +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/validator.d.ts +2 -2
- package/dist/validator.js +4 -4
- package/package.json +1 -1
|
@@ -35,6 +35,114 @@ function tableRowBoundaries(value) {
|
|
|
35
35
|
return [...allowed];
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// src/image-aspect.ts
|
|
39
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
40
|
+
function sourceOf(value) {
|
|
41
|
+
if (typeof value === "string") return value;
|
|
42
|
+
return isRecord(value) && typeof value.src === "string" ? value.src : void 0;
|
|
43
|
+
}
|
|
44
|
+
var PREFIX_BYTES = 64 * 1024;
|
|
45
|
+
var JPEG_PREFIX_BYTES = 1024 * 1024;
|
|
46
|
+
function dataBytes(uri, limit) {
|
|
47
|
+
const match = /^data:([^;,]*)((?:;[^;,]*)*),/i.exec(uri);
|
|
48
|
+
if (!match) return void 0;
|
|
49
|
+
const type = (match[1] ?? "").toLowerCase(), start = match[0].length;
|
|
50
|
+
try {
|
|
51
|
+
if (/;base64/i.test(match[2] ?? "")) {
|
|
52
|
+
const chars = Math.ceil(limit / 3) * 4, text = uri.slice(start, start + chars + chars / 8).replace(/\s+/g, "").slice(0, chars);
|
|
53
|
+
return { type, bytes: Uint8Array.from(atob(text.slice(0, text.length - text.length % 4)), (char) => char.charCodeAt(0)) };
|
|
54
|
+
}
|
|
55
|
+
const prefix = uri.slice(start, start + limit).replace(/%[0-9a-f]?$/i, "");
|
|
56
|
+
return { type, bytes: new TextEncoder().encode(decodeURIComponent(prefix)) };
|
|
57
|
+
} catch {
|
|
58
|
+
return void 0;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
var at = (b, i) => b[i] ?? 0;
|
|
62
|
+
var u16be = (b, i) => at(b, i) << 8 | at(b, i + 1);
|
|
63
|
+
var u32be = (b, i) => (at(b, i) << 24 | at(b, i + 1) << 16 | at(b, i + 2) << 8 | at(b, i + 3)) >>> 0;
|
|
64
|
+
var u16le = (b, i) => at(b, i) | at(b, i + 1) << 8;
|
|
65
|
+
var u24le = (b, i) => at(b, i) | at(b, i + 1) << 8 | at(b, i + 2) << 16;
|
|
66
|
+
var ascii = (b, i, n) => String.fromCharCode(...b.subarray(i, i + n));
|
|
67
|
+
function rasterDimensions(b) {
|
|
68
|
+
if (b.length >= 24 && u32be(b, 0) === 2303741511 && ascii(b, 12, 4) === "IHDR") return { width: u32be(b, 16), height: u32be(b, 20) };
|
|
69
|
+
if (b.length >= 10 && (ascii(b, 0, 6) === "GIF87a" || ascii(b, 0, 6) === "GIF89a")) return { width: u16le(b, 6), height: u16le(b, 8) };
|
|
70
|
+
if (b.length >= 4 && b[0] === 255 && b[1] === 216) {
|
|
71
|
+
let i = 2;
|
|
72
|
+
while (i + 9 < b.length) {
|
|
73
|
+
if (at(b, i) !== 255) {
|
|
74
|
+
i++;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
const marker = at(b, i + 1);
|
|
78
|
+
if (marker === 255) {
|
|
79
|
+
i++;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (marker === 216 || marker === 1 || marker >= 208 && marker <= 215) {
|
|
83
|
+
i += 2;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) return { height: u16be(b, i + 5), width: u16be(b, i + 7) };
|
|
87
|
+
i += 2 + u16be(b, i + 2);
|
|
88
|
+
}
|
|
89
|
+
return void 0;
|
|
90
|
+
}
|
|
91
|
+
if (b.length >= 30 && ascii(b, 0, 4) === "RIFF" && ascii(b, 8, 4) === "WEBP") {
|
|
92
|
+
const chunk = ascii(b, 12, 4);
|
|
93
|
+
if (chunk === "VP8X") return { width: u24le(b, 24) + 1, height: u24le(b, 27) + 1 };
|
|
94
|
+
if (chunk === "VP8L" && at(b, 20) === 47) {
|
|
95
|
+
const bits = u16le(b, 21) | u16le(b, 23) << 16;
|
|
96
|
+
return { width: (bits & 16383) + 1, height: (bits >>> 14 & 16383) + 1 };
|
|
97
|
+
}
|
|
98
|
+
if (chunk === "VP8 ") return { width: u16le(b, 26) & 16383, height: u16le(b, 28) & 16383 };
|
|
99
|
+
}
|
|
100
|
+
return void 0;
|
|
101
|
+
}
|
|
102
|
+
function svgDimensions(text) {
|
|
103
|
+
const root = /<svg\b([^>]*)>/i.exec(text)?.[1];
|
|
104
|
+
if (root === void 0) return void 0;
|
|
105
|
+
const attribute = (name) => new RegExp(`\\s${name}\\s*=\\s*["']([^"']*)["']`, "i").exec(root)?.[1];
|
|
106
|
+
const length = (value) => {
|
|
107
|
+
const match = value && /^\s*([0-9]*\.?[0-9]+)\s*(px|pt|in|cm|mm|em)?\s*$/i.exec(value);
|
|
108
|
+
return match ? Number(match[1]) : void 0;
|
|
109
|
+
};
|
|
110
|
+
const width = length(attribute("width")), height = length(attribute("height"));
|
|
111
|
+
if (width && height) return { width, height };
|
|
112
|
+
const box = attribute("viewBox")?.trim().split(/[\s,]+/).map(Number);
|
|
113
|
+
if (box && box.length === 4 && box.every(Number.isFinite)) {
|
|
114
|
+
const [, , width2 = 0, height2 = 0] = box;
|
|
115
|
+
if (width2 > 0 && height2 > 0) return { width: width2, height: height2 };
|
|
116
|
+
}
|
|
117
|
+
return void 0;
|
|
118
|
+
}
|
|
119
|
+
var cache = /* @__PURE__ */ new Map();
|
|
120
|
+
var CACHE_ENTRIES = 64;
|
|
121
|
+
function readAspect(source) {
|
|
122
|
+
const first = dataBytes(source, PREFIX_BYTES);
|
|
123
|
+
if (!first) return void 0;
|
|
124
|
+
let dimensions;
|
|
125
|
+
if (first.type.startsWith("image/svg")) dimensions = svgDimensions(new TextDecoder().decode(first.bytes));
|
|
126
|
+
else {
|
|
127
|
+
dimensions = rasterDimensions(first.bytes);
|
|
128
|
+
if (!dimensions && first.bytes.length >= 2 && first.bytes[0] === 255 && first.bytes[1] === 216) {
|
|
129
|
+
const more = dataBytes(source, JPEG_PREFIX_BYTES);
|
|
130
|
+
if (more) dimensions = rasterDimensions(more.bytes);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return dimensions && dimensions.width > 0 && dimensions.height > 0 ? dimensions.width / dimensions.height : void 0;
|
|
134
|
+
}
|
|
135
|
+
function intrinsicImageAspect(value, assets) {
|
|
136
|
+
let source = sourceOf(value);
|
|
137
|
+
for (let hop = 0; source?.startsWith("asset:") && hop < 8; hop++) source = sourceOf(isRecord(assets) ? assets[source.slice(6)] : void 0);
|
|
138
|
+
if (!source?.startsWith("data:")) return void 0;
|
|
139
|
+
if (cache.has(source)) return cache.get(source);
|
|
140
|
+
const aspect = readAspect(source);
|
|
141
|
+
if (cache.size >= CACHE_ENTRIES) cache.delete(cache.keys().next().value);
|
|
142
|
+
cache.set(source, aspect);
|
|
143
|
+
return aspect;
|
|
144
|
+
}
|
|
145
|
+
|
|
38
146
|
// src/furniture-fields.ts
|
|
39
147
|
var DEFAULT_FURNITURE_DATE_FORMAT = "M/d/yyyy";
|
|
40
148
|
var DEFAULT_SLIDE_NUMBER_FORMAT = "{current}";
|
|
@@ -268,10 +376,12 @@ function resolveFontSchemeReference(reference, lookup, path = "design.fontScheme
|
|
|
268
376
|
function resolveFontFamilies(input) {
|
|
269
377
|
const scheme = record2(input);
|
|
270
378
|
const family = (value) => typeof value === "string" ? value : record2(value).family;
|
|
379
|
+
const accent = family(scheme.accent);
|
|
271
380
|
return {
|
|
272
381
|
heading: family(scheme.heading) ?? scheme.major ?? scheme.minor ?? DEFAULT_FONT_FAMILIES.heading,
|
|
273
382
|
body: family(scheme.body) ?? scheme.minor ?? scheme.major ?? DEFAULT_FONT_FAMILIES.body,
|
|
274
|
-
code: family(scheme.code) ?? FALLBACK_CODE_FAMILY
|
|
383
|
+
code: family(scheme.code) ?? FALLBACK_CODE_FAMILY,
|
|
384
|
+
...typeof accent === "string" && accent ? { accent } : {}
|
|
275
385
|
};
|
|
276
386
|
}
|
|
277
387
|
function resolveTextStyle(style, measurement) {
|
|
@@ -438,6 +548,45 @@ function resolveSlideImage(slide, layout, presentation, width, height, path, pad
|
|
|
438
548
|
}
|
|
439
549
|
return result;
|
|
440
550
|
}
|
|
551
|
+
var LOGO_LOCKUP_CHAINS = {
|
|
552
|
+
dark: ["light", "default", "stackedLight", "stacked", "wordmarkLight", "wordmark", "iconLight", "icon", "dark", "stackedDark", "wordmarkDark", "iconDark"],
|
|
553
|
+
light: ["dark", "default", "stackedDark", "stacked", "wordmarkDark", "wordmark", "iconDark", "icon", "light", "stackedLight", "wordmarkLight", "iconLight"]
|
|
554
|
+
};
|
|
555
|
+
var LOGO_SET_KEYS = new Set(LOGO_LOCKUP_CHAINS.dark);
|
|
556
|
+
function resolveLogo(presentation, slide, options = {}) {
|
|
557
|
+
const slot = options.slot === "icon" || options.slot === "stacked" ? options.slot : "lockup";
|
|
558
|
+
if (options.slot !== void 0 && slot !== options.slot) throw new RangeError("Logo slot must be lockup, icon or stacked.");
|
|
559
|
+
const tone = options.onDark === true ? "dark" : "light";
|
|
560
|
+
const lockup = LOGO_LOCKUP_CHAINS[tone];
|
|
561
|
+
const chain = slot === "icon" ? [tone === "dark" ? "iconLight" : "iconDark", "icon", ...lockup] : slot === "stacked" ? [tone === "dark" ? "stackedLight" : "stackedDark", "stacked", ...lockup] : lockup;
|
|
562
|
+
const usable = (value) => {
|
|
563
|
+
const source = assetSource(value);
|
|
564
|
+
return typeof source === "string" && source.length > 0;
|
|
565
|
+
};
|
|
566
|
+
const pick = (value, path) => {
|
|
567
|
+
if (value === void 0 || value === null || value === false) return null;
|
|
568
|
+
if (typeof value === "string" || typeof value === "object" && !Array.isArray(value) && "src" in record2(value)) {
|
|
569
|
+
return usable(value) ? { source: value, path, variant: "default", slot } : null;
|
|
570
|
+
}
|
|
571
|
+
const set = record2(value);
|
|
572
|
+
if (!Object.keys(set).some((key) => LOGO_SET_KEYS.has(key))) return null;
|
|
573
|
+
for (const key of chain) {
|
|
574
|
+
const variant = set[key];
|
|
575
|
+
if (variant !== void 0 && usable(variant)) return { source: variant, path: `${path}.${key}`, variant: key, slot };
|
|
576
|
+
}
|
|
577
|
+
return null;
|
|
578
|
+
};
|
|
579
|
+
const deck = record2(presentation), slideIndex = Number.isSafeInteger(options.slideIndex) && options.slideIndex >= 0 ? options.slideIndex : 0;
|
|
580
|
+
const own = pick(record2(record2(slide).design).logo, `slides.${slideIndex}.design.logo`);
|
|
581
|
+
if (own) return own;
|
|
582
|
+
const shared = pick(record2(deck.design).logo, "design.logo");
|
|
583
|
+
if (shared) return shared;
|
|
584
|
+
const organizations = Array.isArray(deck.organization) ? deck.organization : [deck.organization];
|
|
585
|
+
const primaryIndex = organizations.findIndex((item) => record2(item).role === "primary");
|
|
586
|
+
const index = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
|
|
587
|
+
if (index < 0) return null;
|
|
588
|
+
return pick(record2(organizations[index]).logo, Array.isArray(deck.organization) ? `organization.${index}.logo` : "organization.logo");
|
|
589
|
+
}
|
|
441
590
|
var webUrl = /^https?:\/\/\S+$/i;
|
|
442
591
|
function resolveSocialProfile(platform, value, records = [], owner = "organization") {
|
|
443
592
|
const raw = String(value).trim().replace(/\s+/gu, " ");
|
|
@@ -516,8 +665,20 @@ function layoutFurniture(input, options = {}) {
|
|
|
516
665
|
if (accepted.overflow) error(partPath, "Repeated text exceeds its zone at the selected readability floor; change the furniture or slide design.");
|
|
517
666
|
y += box.height;
|
|
518
667
|
};
|
|
668
|
+
const imageBox = (source) => {
|
|
669
|
+
const imageHeight = Math.max(32 * scale, Math.min(height * 0.05, 72 * scale)), imageWidth = Math.min(zoneWidth, imageHeight * (intrinsicImageAspect(source, record2(options.presentation).assets) ?? 1));
|
|
670
|
+
return { x: zone === "left" ? x : zone === "center" ? x + (zoneWidth - imageWidth) / 2 : x + zoneWidth - imageWidth, y, width: imageWidth, height: imageHeight };
|
|
671
|
+
};
|
|
672
|
+
if (content.logo === true) {
|
|
673
|
+
const resolved = resolveLogo(options.presentation, slide, { slot: "icon", onDark: options.darkBackground, slideIndex: options.slideIndex });
|
|
674
|
+
if (resolved) {
|
|
675
|
+
const box = imageBox(resolved.source);
|
|
676
|
+
zoneParts.push({ type: "image", kind: kind2, zone, field: "logo", path: `${path}.logo`, sourcePath: resolved.path, generated: true, image: resolved.source, box, alignment: zone });
|
|
677
|
+
y += box.height;
|
|
678
|
+
} else error(`${path}.logo`, "Generated logo needs design.logo or a primary organization logo.", "unresolved-content");
|
|
679
|
+
}
|
|
519
680
|
if (content.image !== void 0) {
|
|
520
|
-
const box =
|
|
681
|
+
const box = imageBox(content.image);
|
|
521
682
|
zoneParts.push({ type: "image", kind: kind2, zone, field: "image", path: `${path}.image`, sourcePath: `${path}.image`, generated: false, image: content.image, box, alignment: zone });
|
|
522
683
|
y += box.height;
|
|
523
684
|
}
|
|
@@ -644,7 +805,7 @@ function layoutQuote(value, box, options = {}) {
|
|
|
644
805
|
[source(bodyPath, quote.text, 1)],
|
|
645
806
|
{ x: box.x + 18, y: box.y + 18, width: box.width - 36, height: box.height - (footer ? 94 : 36) },
|
|
646
807
|
28,
|
|
647
|
-
options.fonts?.heading ?? "sans-serif",
|
|
808
|
+
options.fonts?.accent ?? options.fonts?.heading ?? "sans-serif",
|
|
648
809
|
600,
|
|
649
810
|
bodyPath
|
|
650
811
|
);
|
|
@@ -780,15 +941,15 @@ function layoutMetric(value, box, options = {}) {
|
|
|
780
941
|
const width = Math.max(...lineInk(part, fit).map((line) => Math.max(line.width, line.outline ? line.outline.x + line.outline.width : 0) - Math.min(0, line.outline?.x ?? 0)));
|
|
781
942
|
return width > 0 ? width + 2 * rasterPadding : 0;
|
|
782
943
|
};
|
|
783
|
-
const
|
|
944
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
784
945
|
const measure = (part, size, width) => {
|
|
785
946
|
const key = JSON.stringify([part.role, size, width]);
|
|
786
|
-
let fit =
|
|
947
|
+
let fit = cache2.get(key);
|
|
787
948
|
if (!fit) {
|
|
788
949
|
fit = fitCodeText(part.text, { ...box, width: hasOutlines ? Math.max(Number.MIN_VALUE, width - 2 * rasterPadding) : width }, size, size, scale, textWidthMeasurer(part.style, options.textMeasurement));
|
|
789
950
|
fit = place(part, fit, width);
|
|
790
951
|
if (!Number.isFinite(occupied(fit))) throw new RangeError("Metric text layout exceeds finite coordinates.");
|
|
791
|
-
|
|
952
|
+
cache2.set(key, fit);
|
|
792
953
|
}
|
|
793
954
|
return fit;
|
|
794
955
|
};
|
|
@@ -904,10 +1065,10 @@ function layoutTimeline(value, box, options = {}) {
|
|
|
904
1065
|
const metadata = [], events = timeline.events.map(() => []);
|
|
905
1066
|
for (const part of source) if (part.eventIndex === void 0) metadata.push(part);
|
|
906
1067
|
else events[part.eventIndex].push(part);
|
|
907
|
-
const
|
|
1068
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
908
1069
|
const measure = (part, size, width, alignment) => {
|
|
909
1070
|
const key = JSON.stringify([part.path, size, width, alignment]);
|
|
910
|
-
let measured =
|
|
1071
|
+
let measured = cache2.get(key);
|
|
911
1072
|
if (measured) return measured;
|
|
912
1073
|
const fit = fitText(part.text, { width: Math.max(Number.MIN_VALUE, width - (outlines ? 2 * padding : 0)), height: Number.MAX_VALUE }, size, size, textWidthMeasurer(part.style, options.textMeasurement));
|
|
913
1074
|
const ink = fit.sourceLines.map((line, index) => {
|
|
@@ -930,7 +1091,7 @@ function layoutTimeline(value, box, options = {}) {
|
|
|
930
1091
|
const height = placement?.height ?? fit.sourceLines.length * fit.lineHeight;
|
|
931
1092
|
if (!Number.isFinite(height)) throw new RangeError("Timeline text exceeds finite layout coordinates.");
|
|
932
1093
|
measured = { fit, ink, height };
|
|
933
|
-
|
|
1094
|
+
cache2.set(key, measured);
|
|
934
1095
|
return measured;
|
|
935
1096
|
};
|
|
936
1097
|
let selected, attempts = 0;
|
|
@@ -1267,6 +1428,7 @@ function richTextLayouter(input, box, requestedSize, options) {
|
|
|
1267
1428
|
};
|
|
1268
1429
|
return layout;
|
|
1269
1430
|
}
|
|
1431
|
+
var PICTURE_BULLET_SCALE = 0.65;
|
|
1270
1432
|
function fitList(input, box, requestedSize = 25, minFontSize = 16, options = { style: { fontFamily: "sans-serif", fontWeight: 400 } }) {
|
|
1271
1433
|
if (!Array.isArray(input) || ![box.width, box.height, requestedSize, minFontSize].every((value) => Number.isFinite(value) && value > 0)) throw new RangeError("List content, dimensions and font sizes must be valid.");
|
|
1272
1434
|
const source = input.map((value, index) => {
|
|
@@ -1300,6 +1462,7 @@ function fitList(input, box, requestedSize = 25, minFontSize = 16, options = { s
|
|
|
1300
1462
|
y += description.height;
|
|
1301
1463
|
}
|
|
1302
1464
|
overflow ||= text.overflow || !!description?.overflow;
|
|
1465
|
+
const marker = { text: ["\u2022", "\u25E6", "\u25AA"][item.level % 3], x: box.x + offset, y: textBox.y + (text.richLines[0]?.baseline ?? fontSize), fontSize, style: resolveTextStyle(style, options.textMeasurement), indent }, side = fontSize * PICTURE_BULLET_SCALE;
|
|
1303
1466
|
entries.push({
|
|
1304
1467
|
index: item.index,
|
|
1305
1468
|
level: item.level,
|
|
@@ -1311,7 +1474,8 @@ function fitList(input, box, requestedSize = 25, minFontSize = 16, options = { s
|
|
|
1311
1474
|
textBox,
|
|
1312
1475
|
description,
|
|
1313
1476
|
descriptionBox,
|
|
1314
|
-
marker
|
|
1477
|
+
marker,
|
|
1478
|
+
...options.bulletImage ? { bulletImage: options.bulletImage, bulletBox: { x: marker.x, y: marker.y - side, width: side, height: side } } : {}
|
|
1315
1479
|
});
|
|
1316
1480
|
if (item.index < source.length - 1) y += fontSize * 0.28;
|
|
1317
1481
|
}
|
|
@@ -1465,12 +1629,20 @@ function composeSlide(input, options = {}) {
|
|
|
1465
1629
|
const minSize = (composition.minFontSize ?? 16) * scale;
|
|
1466
1630
|
const rasterPadding = (options.textRasterPadding ?? 1) * scale;
|
|
1467
1631
|
if (!Number.isFinite(rasterPadding) || rasterPadding < 0) throw new RangeError("Text raster padding must be finite and nonnegative.");
|
|
1468
|
-
|
|
1632
|
+
let coverGroup = false;
|
|
1633
|
+
const alignmentFor = (field) => (field === "title" || coverGroup && (field === "tag" || field === "subtitle") && record2(slide.design).contentAlignment === void 0 ? record2(slide.design).titleAlignment ?? options.titleAlignment : record2(slide.design).contentAlignment ?? options.contentAlignment) ?? "left";
|
|
1469
1634
|
const styleFor = (field, path2) => resolveTextStyle({
|
|
1470
|
-
fontFamily: (field === "title" ? options.fonts?.heading : field === "code" ? options.fonts?.code : options.fonts?.body) ?? (field === "code" ? "monospace" : "sans-serif"),
|
|
1635
|
+
fontFamily: (field === "title" ? options.fonts?.heading : field === "code" ? options.fonts?.code : field === "tag" ? options.fonts?.accent ?? options.fonts?.body : options.fonts?.body) ?? (field === "code" ? "monospace" : "sans-serif"),
|
|
1471
1636
|
fontWeight: field === "title" ? 700 : 400,
|
|
1472
1637
|
path: path2
|
|
1473
1638
|
}, options.textMeasurement);
|
|
1639
|
+
const slideDesign = record2(slide.design), deckDesign = record2(record2(options.presentation).design);
|
|
1640
|
+
const designHint = (field) => slideDesign[field] !== void 0 ? { value: slideDesign[field], path: `slides.${options.slideIndex ?? 0}.design.${field}` } : deckDesign[field] !== void 0 ? { value: deckDesign[field], path: `design.${field}` } : void 0;
|
|
1641
|
+
const listBullet = designHint("listBullet");
|
|
1642
|
+
const bulletImage = listBullet?.value === "image" ? (() => {
|
|
1643
|
+
const resolved = resolveLogo(options.presentation, slide, { slot: "icon", onDark: options.darkBackground, slideIndex: options.slideIndex });
|
|
1644
|
+
return resolved ? { source: resolved.source, path: resolved.path } : void 0;
|
|
1645
|
+
})() : void 0;
|
|
1474
1646
|
const widthFor = (field, path2) => textWidthMeasurer(styleFor(field, path2), options.textMeasurement);
|
|
1475
1647
|
const fitPlacedText = (field, value, text, box, size, minimum, path2) => {
|
|
1476
1648
|
const style = styleFor(field, path2), rich = field === "text" && Array.isArray(value);
|
|
@@ -1522,7 +1694,7 @@ function composeSlide(input, options = {}) {
|
|
|
1522
1694
|
}
|
|
1523
1695
|
throw new Error("Text placement did not evaluate its bounded floor trial.");
|
|
1524
1696
|
};
|
|
1525
|
-
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));
|
|
1697
|
+
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, ...bulletImage ? { bulletImage } : {} }) : fitText(text, box, size, minimum, widthFor(field, path2));
|
|
1526
1698
|
const path = `slides.${options.slideIndex ?? 0}`;
|
|
1527
1699
|
const slideImageDiagnostics = [];
|
|
1528
1700
|
const slideImage = resolveSlideImage(slide, layout, options.presentation, width, height, path, padding, scale, slideImageDiagnostics);
|
|
@@ -1544,7 +1716,17 @@ function composeSlide(input, options = {}) {
|
|
|
1544
1716
|
const emptyHost = (host) => emptyPayload(host.blocks) && fields.every((field) => emptyPayload(host[field]));
|
|
1545
1717
|
const hasBodyPayload = regions.some((key) => !emptyHost(record2(slide[key]))) || !emptyPayload(slide.blocks) || fields.some((field) => !emptyPayload(slide[field]));
|
|
1546
1718
|
const isCover = !hasBodyPayload && (headingOnlyLayout || !layout.id && !layoutPlaceholders.some((placeholder) => !headings.has(placeholder.type ?? "")));
|
|
1547
|
-
|
|
1719
|
+
coverGroup = isCover;
|
|
1720
|
+
let logo;
|
|
1721
|
+
if (isCover) {
|
|
1722
|
+
const resolved = resolveLogo(options.presentation, slide, { slot: "lockup", onDark: options.darkBackground, slideIndex: options.slideIndex });
|
|
1723
|
+
if (resolved) {
|
|
1724
|
+
const logoHeight = 56 * scale;
|
|
1725
|
+
const box = { x: round(area.left + padding), y: round(headingTop), width: round(Math.max(scale, Math.min(4 * logoHeight, area.right - area.left - 2 * padding))), height: round(logoHeight) };
|
|
1726
|
+
logo = { box, slot: "lockup", path: resolved.path, source: resolved.source, variant: resolved.variant, anchor: "left" };
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
let y = logo ? logo.box.y + logo.box.height + gap : headingTop;
|
|
1548
1730
|
const headingItems = [];
|
|
1549
1731
|
for (const field of ["tag", "title", "subtitle"]) {
|
|
1550
1732
|
if (!slide[field]) continue;
|
|
@@ -1681,14 +1863,14 @@ function composeSlide(input, options = {}) {
|
|
|
1681
1863
|
const boxes = gridBoxes(node.children.length, area2, cols, (own.gap ?? 1 / 30) * Math.min(box.width, box.height), own.weights ?? [], modeFor(own) === "column");
|
|
1682
1864
|
return node.children.reduce((score, child, index) => score + scoreNode(child, boxes[index], own, penalties), 0);
|
|
1683
1865
|
};
|
|
1684
|
-
const arrange = (nodes, area2, settings, reserved = 0, gapOverride, containerPath = path) => {
|
|
1866
|
+
const arrange = (nodes, area2, settings, reserved = 0, gapOverride, containerPath = path, recorded = true) => {
|
|
1685
1867
|
const count = Math.max(nodes.length, reserved);
|
|
1686
1868
|
if (!count) return;
|
|
1687
1869
|
const mode = modeFor(settings), localGap = (settings.gap ?? 1 / 30) * Math.min(area2.width, area2.height);
|
|
1688
1870
|
const actualGap = gapOverride ?? (settings === rootSettings ? gap : localGap);
|
|
1689
1871
|
let cols = defaultColumns(count, area2, settings);
|
|
1690
1872
|
const hasRegions = nodes.some((node) => node.region);
|
|
1691
|
-
const candidates = decisions ? [] : void 0;
|
|
1873
|
+
const candidates = decisions && recorded ? [] : void 0;
|
|
1692
1874
|
if (mode === "auto" && !hasRegions) {
|
|
1693
1875
|
let best = Infinity;
|
|
1694
1876
|
for (let candidate = 1; candidate <= Math.min(count, settings.columns ?? 6); candidate++) {
|
|
@@ -1703,22 +1885,22 @@ function composeSlide(input, options = {}) {
|
|
|
1703
1885
|
}
|
|
1704
1886
|
}
|
|
1705
1887
|
}
|
|
1706
|
-
decisions?.push({
|
|
1888
|
+
if (recorded) decisions?.push({
|
|
1707
1889
|
path: containerPath,
|
|
1708
1890
|
mode: hasRegions ? "regions" : mode,
|
|
1709
|
-
reason: hasRegions ? "promoted-regions" : mode === "auto" ? "lowest-score" : "configured-mode",
|
|
1891
|
+
reason: hasRegions ? "promoted-regions" : settings === rootSettings && chartPrimary ? "chart-primary" : mode === "auto" ? "lowest-score" : "configured-mode",
|
|
1710
1892
|
...hasRegions ? {} : { selectedColumns: cols },
|
|
1711
1893
|
candidates: candidates ?? []
|
|
1712
1894
|
});
|
|
1713
1895
|
const grid = gridGeometry(count, area2, cols, actualGap, settings.weights ?? [], mode === "column");
|
|
1714
1896
|
const boxes = grid.boxes;
|
|
1715
|
-
if (
|
|
1897
|
+
if (recorded && !hasRegions) flows.push({ path: containerPath, box: { ...area2 }, composition: { ...settings }, columns: grid.columns, rows: grid.rows, gap: grid.gap, itemCount: nodes.length, slotCount: count });
|
|
1716
1898
|
nodes.forEach((node, index) => {
|
|
1717
1899
|
let box = node.region ? regionBox(node.region, area2, actualGap) : boxes[index];
|
|
1718
1900
|
if (node.children) {
|
|
1719
1901
|
const own = inheritedSettings(settings, node.composition), inner = inset(box, own);
|
|
1720
|
-
groups.push({ path: node.path, box, contentBox: inner, composition: own });
|
|
1721
|
-
arrange(node.children, inner, own, 0, (own.gap ?? 1 / 30) * Math.min(box.width, box.height), node.path);
|
|
1902
|
+
if (!node.synthetic) groups.push({ path: node.path, box, contentBox: inner, composition: own });
|
|
1903
|
+
arrange(node.children, inner, own, 0, (own.gap ?? 1 / 30) * Math.min(box.width, box.height), node.path, !node.synthetic);
|
|
1722
1904
|
} else {
|
|
1723
1905
|
const frameBox = hasCards ? acceptedBox(box) : void 0;
|
|
1724
1906
|
box = payloadBox(box);
|
|
@@ -1744,7 +1926,8 @@ function composeSlide(input, options = {}) {
|
|
|
1744
1926
|
...quoteLayout ? { quoteLayout } : {},
|
|
1745
1927
|
...codeLayout ? { codeLayout } : {},
|
|
1746
1928
|
...metricLayout ? { metricLayout } : {},
|
|
1747
|
-
...timelineLayout ? { timelineLayout } : {}
|
|
1929
|
+
...timelineLayout ? { timelineLayout } : {},
|
|
1930
|
+
...bulletImage && (node.field === "items" || node.field === "bullets") ? { bulletImage } : {}
|
|
1748
1931
|
});
|
|
1749
1932
|
if (box.width < 100 * scale || box.height < 60 * scale) diagnostics.push({ code: "small-cell", path: node.path, message: "Content cell is too small for comfortable reading; use fewer blocks or a different composition." });
|
|
1750
1933
|
}
|
|
@@ -1755,8 +1938,23 @@ function composeSlide(input, options = {}) {
|
|
|
1755
1938
|
const picture = placeholders.findIndex((p) => p.type === "picture");
|
|
1756
1939
|
if (picture >= 0) placeholders.splice(picture, 1);
|
|
1757
1940
|
}
|
|
1758
|
-
const
|
|
1759
|
-
|
|
1941
|
+
const ownMode = record2(slide.composition).mode;
|
|
1942
|
+
const direction = designHint("contentDirection")?.value;
|
|
1943
|
+
const directionMode = direction === "vertical" ? "column" : direction === "horizontal" ? "row" : void 0;
|
|
1944
|
+
const layoutDirectionMode = layout.slideLayoutDirection === "Vertical" ? "column" : layout.slideLayoutDirection === "Horizontal" ? "row" : "auto";
|
|
1945
|
+
const chartHint = designHint("chartPrimary")?.value ?? (typeof layout.contentTypeChartPrimary === "string" ? layout.contentTypeChartPrimary.toLowerCase() : void 0);
|
|
1946
|
+
const chartSide = chartHint === "left" || chartHint === "right" || chartHint === "top" || chartHint === "bottom" ? chartHint : void 0;
|
|
1947
|
+
const chartIndex = pending.findIndex((node) => !node.children && node.field === "chart");
|
|
1948
|
+
const chartPrimary = chartSide !== void 0 && !ownMode && !regions.length && chartIndex >= 0 && pending.some((node) => node.children || node.field !== "chart") ? chartSide : void 0;
|
|
1949
|
+
const rootSettings = chartPrimary ? { ...composition, mode: chartPrimary === "left" || chartPrimary === "right" ? "row" : "column", columns: void 0, weights: chartPrimary === "left" || chartPrimary === "top" ? [3, 2] : [2, 3] } : { ...composition, mode: composition.mode ?? directionMode ?? layoutDirectionMode };
|
|
1950
|
+
if (chartPrimary) {
|
|
1951
|
+
const primary = pending[chartIndex], rest = pending.filter((_, index) => index !== chartIndex);
|
|
1952
|
+
const container = { field: "blocks", type: "group", value: rest.map((node) => node.payload), path, payload: {}, children: rest, composition: {}, synthetic: true };
|
|
1953
|
+
arrange(chartPrimary === "left" || chartPrimary === "top" ? [primary, container] : [container, primary], contentBox, rootSettings, 0);
|
|
1954
|
+
} else arrange(pending, contentBox, rootSettings, composition.mode ? 0 : placeholders.length);
|
|
1955
|
+
if (listBullet?.value === "image" && !bulletImage && items.some((item) => item.field === "items" || item.field === "bullets")) {
|
|
1956
|
+
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." });
|
|
1957
|
+
}
|
|
1760
1958
|
for (const item of items) {
|
|
1761
1959
|
for (const key of ["x", "y", "width", "height"]) item.box[key] = round(item.box[key]);
|
|
1762
1960
|
if (item.field === "table" && tableOverflows(item.value, item.box, scale, item.composition, options, item.path)) diagnostics.push({ code: "text-overflow", path: item.path, message: "Table cells do not fit; use fewer rows, fewer columns, or split the table across slides." });
|
|
@@ -1789,7 +1987,7 @@ function composeSlide(input, options = {}) {
|
|
|
1789
1987
|
} : void 0;
|
|
1790
1988
|
if (failures.length) throw new OPFCompositionError(failures, explanation);
|
|
1791
1989
|
diagnostics.push(...slideImageDiagnostics);
|
|
1792
|
-
return { width, height, contentBox, items, groups, flows, diagnostics, composition, ...furniture ? { furniture } : {}, ...slideImage ? { slideImage } : {}, ...explanation ? { explanation } : {} };
|
|
1990
|
+
return { width, height, contentBox, items, groups, flows, diagnostics, composition, ...furniture ? { furniture } : {}, ...slideImage ? { slideImage } : {}, ...logo ? { logo } : {}, ...explanation ? { explanation } : {} };
|
|
1793
1991
|
}
|
|
1794
1992
|
function resolveCanvasDimensions(input) {
|
|
1795
1993
|
const presets = {
|
|
@@ -1809,4 +2007,4 @@ function resolveCanvasDimensions(input) {
|
|
|
1809
2007
|
return { width, height };
|
|
1810
2008
|
}
|
|
1811
2009
|
|
|
1812
|
-
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 };
|
|
2010
|
+
export { DEFAULT_FONT_SCHEME, DEFAULT_FURNITURE_DATE_FORMAT, DEFAULT_SLIDE_NUMBER_FORMAT, MAX_COMPOSITION_DEPTH, OPFCompositionError, PICTURE_BULLET_SCALE, chartColorForFill, colorContrast, composeSlide, fitList, fitRichText, fitText, formatFurnitureDate, formatSlideNumber, layoutCode, layoutFurniture, layoutMetric, layoutQuote, layoutTable, layoutTimeline, measureText, measureTextOutline, normalizeHexColor, placeTextLines, resolveCanvasDimensions, resolveColorRef, resolveFontFamilies, resolveFontSchemeReference, resolveLogo, resolveSocialProfile, resolveTextStyle, slideImageShape, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, wrapText };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { validatePresentation, validationDefinition, validateCatalogRecord } from './chunk-
|
|
2
|
-
import { schemas, schemaEntries } from './chunk-
|
|
3
|
-
import { catalogKinds, catalogEntries, catalogSchemaNames } from './chunk-
|
|
1
|
+
import { validatePresentation, validationDefinition, validateCatalogRecord } from './chunk-FDCWQHWO.js';
|
|
2
|
+
import { schemas, schemaEntries } from './chunk-KJKASEPE.js';
|
|
3
|
+
import { catalogKinds, catalogEntries, catalogSchemaNames } from './chunk-AEUSVEUY.js';
|
|
4
4
|
import { parseTree, printParseErrorCode, getNodePath } from 'jsonc-parser';
|
|
5
5
|
|
|
6
6
|
var own = (value, key) => Object.hasOwn(value, key);
|
|
@@ -447,7 +447,20 @@ function lintPresentation(document, options = {}) {
|
|
|
447
447
|
}
|
|
448
448
|
}
|
|
449
449
|
for (const issue of validation.warnings) {
|
|
450
|
-
const kind = issue.params.kind, id = issue.params.id;
|
|
450
|
+
const kind = issue.params.kind, id = issue.params.id, replacedBy = issue.params.replacedBy;
|
|
451
|
+
if (typeof replacedBy === "string" && typeof id === "string") {
|
|
452
|
+
const target = catalogs.get(kind)?.get(replacedBy);
|
|
453
|
+
diagnostics.push({
|
|
454
|
+
...schemaDiagnostic(issue),
|
|
455
|
+
ruleId: "opf/deprecated-catalog-id",
|
|
456
|
+
severity: "warning",
|
|
457
|
+
message: `Deprecated ${kind} catalog id ${JSON.stringify(id)}; use ${JSON.stringify(replacedBy)} instead.`,
|
|
458
|
+
help: "The deprecated id still resolves to its original record, so nothing breaks. Switch to the replacement when you next edit this reference.",
|
|
459
|
+
lookup: ["opf", "catalog", kind],
|
|
460
|
+
...target ? { suggestions: [target] } : {}
|
|
461
|
+
});
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
451
464
|
if (seen.has(issue.path) || typeof id === "string" && catalogs.get(kind)?.has(id))
|
|
452
465
|
continue;
|
|
453
466
|
diagnostics.push({
|