@openpresentation/opf 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +18 -18
- package/dist/{catalog-refs-BSfGELpt.d.ts → catalog-refs-kAefsZWT.d.ts} +2 -1
- package/dist/{catalog-schemas-DoxA2BgY.d.ts → catalog-schemas-CC1d_h8s.d.ts} +3 -2
- package/dist/{chart-data-BnNqgnC-.d.ts → chart-data-Ci9s_NDN.d.ts} +2 -1
- package/dist/{chunk-LRTQXGJO.js → chunk-2CUCYENF.js} +523 -89
- package/dist/{chunk-4ZM5G3XX.js → chunk-5Q4IYLMW.js} +30 -14
- package/dist/{chunk-OSM3LZ2Y.js → chunk-BQUWRXTR.js} +4 -4
- package/dist/{chunk-4ACS57MG.js → chunk-CR72ZJ6W.js} +2 -2
- package/dist/{chunk-ZGTOZA2S.js → chunk-F6DCEGB3.js} +6 -6
- package/dist/{chunk-O3SA5SJ4.js → chunk-KELC4K62.js} +1 -1
- package/dist/{chunk-WJ4XTCOD.js → chunk-KXKN3W5Z.js} +3 -3
- package/dist/{chunk-TMREBZBQ.js → chunk-LLEXM7TQ.js} +3 -3
- package/dist/{chunk-GNKESMZT.js → chunk-MTFK7QEY.js} +6 -6
- package/dist/{chunk-JSHMFTSY.js → chunk-N77N4AOD.js} +1 -1
- package/dist/{chunk-7XUEKIXH.js → chunk-OAIAFXMS.js} +2 -2
- package/dist/{chunk-EO3JWEO5.js → chunk-P6PKYJTS.js} +1 -1
- package/dist/{chunk-353VBJ6K.js → chunk-PCU4XGKV.js} +5 -5
- package/dist/{chunk-SYW4BCGZ.js → chunk-SEZ4EPW6.js} +2 -2
- package/dist/{chunk-ABFDFZIW.js → chunk-TNUTRV6E.js} +1 -1
- package/dist/{chunk-CXPBU5W4.js → chunk-UOHWG4OS.js} +1 -1
- package/dist/{chunk-APLNGCEZ.js → chunk-VGGPAMP7.js} +2 -2
- package/dist/{chunk-PAGVSTVF.js → chunk-WPKCWQ6W.js} +149 -26
- package/dist/{chunk-KZPZRHL6.js → chunk-XZ23FORL.js} +6 -6
- package/dist/chunk-ZROVYWGU.js +1 -0
- package/dist/{composition-BGmpe5e4.d.ts → composition-C-hd_Ci3.d.ts} +84 -10
- package/dist/composition.d.ts +3 -3
- package/dist/composition.js +1 -1
- package/dist/conversion-XJTDWQ5W.js +24 -0
- package/dist/{conversion-8SQD4dqu.d.ts → conversion-hbZeS5kD.d.ts} +9 -8
- package/dist/convert.d.ts +6 -5
- package/dist/convert.js +7 -7
- package/dist/data.d.ts +4 -3
- package/dist/data.js +2 -2
- package/dist/{deck-report-BaKgPh_N.d.ts → deck-report-DQMsvyBI.d.ts} +5 -4
- package/dist/deck.d.ts +10 -9
- package/dist/deck.js +11 -11
- package/dist/diff.d.ts +3 -2
- package/dist/diff.js +4 -4
- package/dist/docs.d.ts +2 -1
- package/dist/docs.js +29 -17
- package/dist/examples.d.ts +3 -2
- package/dist/examples.js +90 -50
- package/dist/{explain-JSuESV-Y.d.ts → explain-iZeNOUc6.d.ts} +2 -1
- package/dist/{finding-Bh56sGtF.d.ts → finding-l9dlQ2NF.d.ts} +1 -1
- package/dist/font-policy.d.ts +2 -1
- package/dist/format.d.ts +2 -1
- package/dist/format.js +2 -2
- package/dist/ids.d.ts +3 -2
- package/dist/ids.js +4 -4
- package/dist/index.d.ts +38 -17
- package/dist/index.js +22 -22
- package/dist/markdown.d.ts +8 -7
- package/dist/markdown.js +8 -8
- package/dist/node-engine.d.ts +34 -11
- package/dist/node-engine.js +35 -29
- package/dist/{pagination-BsUTsQvk.d.ts → pagination-DyAKYpXu.d.ts} +4 -3
- package/dist/pagination.d.ts +4 -4
- package/dist/pagination.js +4 -4
- package/dist/patch.d.ts +4 -2
- package/dist/patch.js +3 -3
- package/dist/precompiled.d.ts +1 -1
- package/dist/precompiled.js +2 -2
- package/dist/{presentation-C-nHZyMw.d.ts → presentation-8jLSTFqL.d.ts} +10 -10
- package/dist/repo-readme.js +1 -1
- package/dist/schema-engine-ajv.js +1 -1
- package/dist/schema-engine-precompiled.js +2 -2
- package/dist/schema.d.ts +4 -3
- package/dist/schema.js +3 -3
- package/dist/schemas.d.ts +2 -1
- package/dist/schemas.js +1 -1
- package/dist/source.d.ts +5 -4
- package/dist/source.js +10 -10
- package/dist/spec/README.md +1 -1
- package/dist/spec/schemas/audience.schema.json +1 -0
- package/dist/spec/schemas/catalog-index.schema.json +1 -0
- package/dist/spec/schemas/catalog-manifest.schema.json +1 -0
- package/dist/spec/schemas/chart-type.schema.json +1 -0
- package/dist/spec/schemas/color-scheme.schema.json +1 -0
- package/dist/spec/schemas/finding.schema.json +1 -0
- package/dist/spec/schemas/font-scheme.schema.json +1 -0
- package/dist/spec/schemas/language.schema.json +1 -0
- package/dist/spec/schemas/layout-preview-index.schema.json +1 -0
- package/dist/spec/schemas/layout.schema.json +8 -6
- package/dist/spec/schemas/narrative.schema.json +1 -0
- package/dist/spec/schemas/opf.schema.json +8 -7
- package/dist/spec/schemas/purpose.schema.json +1 -0
- package/dist/spec/schemas/social-platform.schema.json +1 -0
- package/dist/spec/schemas/theme.schema.json +3 -1
- package/dist/spec/schemas/tone.schema.json +1 -0
- package/dist/spec-files.d.ts +2 -1
- package/dist/symbol-font-encodings.d.ts +2 -1
- package/dist/types.d.ts +10 -10
- package/dist/{validation-types-6_jEaHeE.d.ts → validation-types-mNmfcY9A.d.ts} +5 -4
- package/dist/validator.d.ts +8 -8
- package/dist/validator.js +3 -3
- package/dist/yaml.d.ts +8 -7
- package/dist/yaml.js +7 -7
- package/package.json +7 -7
- package/dist/chunk-GJO5NUVT.js +0 -1
- package/dist/conversion-LN6PFRZL.js +0 -24
|
@@ -2068,11 +2068,28 @@ var u32be = (b, i) => (at2(b, i) << 24 | at2(b, i + 1) << 16 | at2(b, i + 2) <<
|
|
|
2068
2068
|
var u16le = (b, i) => at2(b, i) | at2(b, i + 1) << 8;
|
|
2069
2069
|
var u24le = (b, i) => at2(b, i) | at2(b, i + 1) << 8 | at2(b, i + 2) << 16;
|
|
2070
2070
|
var ascii = (b, i, n) => String.fromCharCode(...b.subarray(i, i + n));
|
|
2071
|
+
function exifOrientation(b, start, end) {
|
|
2072
|
+
if (end > b.length || ascii(b, start, 4) !== "Exif" || at2(b, start + 4) !== 0) return void 0;
|
|
2073
|
+
const tiff = start + 6, little = ascii(b, tiff, 2) === "II";
|
|
2074
|
+
if (!little && ascii(b, tiff, 2) !== "MM") return void 0;
|
|
2075
|
+
const u16 = (index) => little ? u16le(b, index) : u16be(b, index);
|
|
2076
|
+
const u32 = (index) => little ? (u16le(b, index) | u16le(b, index + 2) << 16) >>> 0 : u32be(b, index);
|
|
2077
|
+
const directory = tiff + u32(tiff + 4);
|
|
2078
|
+
if (directory + 2 > end) return void 0;
|
|
2079
|
+
for (let entry = 0, count = u16(directory); entry < count && directory + 2 + entry * 12 + 12 <= end; entry++) {
|
|
2080
|
+
const at12 = directory + 2 + entry * 12;
|
|
2081
|
+
if (u16(at12) === 274) {
|
|
2082
|
+
const value = u16(at12 + 8);
|
|
2083
|
+
return value >= 1 && value <= 8 ? value : void 0;
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
2086
|
+
return void 0;
|
|
2087
|
+
}
|
|
2071
2088
|
function rasterDimensions(b) {
|
|
2072
2089
|
if (b.length >= 24 && u32be(b, 0) === 2303741511 && ascii(b, 12, 4) === "IHDR") return { width: u32be(b, 16), height: u32be(b, 20) };
|
|
2073
2090
|
if (b.length >= 10 && (ascii(b, 0, 6) === "GIF87a" || ascii(b, 0, 6) === "GIF89a")) return { width: u16le(b, 6), height: u16le(b, 8) };
|
|
2074
2091
|
if (b.length >= 4 && b[0] === 255 && b[1] === 216) {
|
|
2075
|
-
let i = 2;
|
|
2092
|
+
let i = 2, orientation = 1;
|
|
2076
2093
|
while (i + 9 < b.length) {
|
|
2077
2094
|
if (at2(b, i) !== 255) {
|
|
2078
2095
|
i++;
|
|
@@ -2087,7 +2104,11 @@ function rasterDimensions(b) {
|
|
|
2087
2104
|
i += 2;
|
|
2088
2105
|
continue;
|
|
2089
2106
|
}
|
|
2090
|
-
if (marker
|
|
2107
|
+
if (marker === 225) orientation = exifOrientation(b, i + 4, i + 2 + u16be(b, i + 2)) ?? orientation;
|
|
2108
|
+
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) {
|
|
2109
|
+
const height = u16be(b, i + 5), width = u16be(b, i + 7);
|
|
2110
|
+
return orientation >= 5 ? { width: height, height: width } : { width, height };
|
|
2111
|
+
}
|
|
2091
2112
|
i += 2 + u16be(b, i + 2);
|
|
2092
2113
|
}
|
|
2093
2114
|
return void 0;
|
|
@@ -2167,7 +2188,7 @@ var VALUES = {
|
|
|
2167
2188
|
contentDirection: ["horizontal", "vertical"],
|
|
2168
2189
|
chartPrimary: ["none", "top", "bottom", "left", "right"],
|
|
2169
2190
|
imageFit: ["cover", "contain", "stretch"],
|
|
2170
|
-
listBullet: ["character", "image"],
|
|
2191
|
+
listBullet: ["character", "image", "none"],
|
|
2171
2192
|
mirror: "boolean"
|
|
2172
2193
|
};
|
|
2173
2194
|
var themeKeys = new Set(THEME_DESIGN_KEYS);
|
|
@@ -2395,6 +2416,8 @@ function parse(layout) {
|
|
|
2395
2416
|
}
|
|
2396
2417
|
};
|
|
2397
2418
|
order(children);
|
|
2419
|
+
const stackAnchor = anchorOf(value.anchor);
|
|
2420
|
+
const stack = direction === "column" && children.length > 0 && children.every((node) => node.size === "auto") && stackAnchor !== void 0 && stackAnchor !== "top" ? stackAnchor : void 0;
|
|
2398
2421
|
const overflowRegion = typeof value.overflowRegion === "string" ? value.overflowRegion : regions.find((entry) => entry.role === "primary" && entry.flow !== "none")?.name;
|
|
2399
2422
|
return {
|
|
2400
2423
|
issues,
|
|
@@ -2406,7 +2429,8 @@ function parse(layout) {
|
|
|
2406
2429
|
regions,
|
|
2407
2430
|
...overflowRegion !== void 0 ? { overflowRegion } : {},
|
|
2408
2431
|
title: names.has("title"),
|
|
2409
|
-
subtitle: names.has("subtitle")
|
|
2432
|
+
subtitle: names.has("subtitle"),
|
|
2433
|
+
...stack ? { stack } : {}
|
|
2410
2434
|
}
|
|
2411
2435
|
};
|
|
2412
2436
|
}
|
|
@@ -2755,19 +2779,32 @@ function listColumnBreaks(heights, levels, count) {
|
|
|
2755
2779
|
return solve(0, count).breaks;
|
|
2756
2780
|
}
|
|
2757
2781
|
function allocateRows(rows3, total, gap) {
|
|
2758
|
-
const auto = rows3.map((row) => row.size === "auto" ? Math.max(0, Math.min(row.need, row.kind === "
|
|
2782
|
+
const auto = rows3.map((row) => row.size === "auto" ? Math.max(0, Math.min(row.need, row.kind === "heading" ? total / 2 : total)) : 0);
|
|
2759
2783
|
const visible = rows3.filter((row, index) => row.size !== "auto" || auto[index] > 0).length;
|
|
2760
2784
|
const headings2 = rows3.reduce((sum, row, index) => sum + (row.kind === "heading" ? auto[index] : 0), 0);
|
|
2761
2785
|
const space = Math.max(0, total - headings2 - Math.max(0, visible - 1) * gap);
|
|
2762
2786
|
const numeric = rows3.reduce((sum, row) => sum + (row.size === "auto" ? 0 : row.size), 0);
|
|
2763
2787
|
const numericNeed = rows3.reduce((sum, row) => sum + (row.size === "auto" ? 0 : Math.max(0, row.need)), 0);
|
|
2764
2788
|
const reserve = numeric > 0 ? Math.min(numericNeed, space / 2) : 0;
|
|
2765
|
-
const
|
|
2766
|
-
const
|
|
2767
|
-
const heights = rows3.map((row, index) => row.size === "auto" ? row.kind === "heading" ? auto[index] :
|
|
2789
|
+
const bodyRows = rows3.flatMap((row, index) => row.size === "auto" && row.kind !== "heading" ? [index] : []);
|
|
2790
|
+
const fitted = shareHeights(bodyRows.map((index) => auto[index]), bodyRows.map((index) => rows3[index].floor ?? 0), Math.max(0, space - reserve));
|
|
2791
|
+
const heights = rows3.map((row, index) => row.size === "auto" ? row.kind === "heading" ? auto[index] : fitted[bodyRows.indexOf(index)] : 0);
|
|
2768
2792
|
const rest = Math.max(0, space - heights.reduce((sum, height, index) => sum + (rows3[index].kind === "heading" ? 0 : height), 0));
|
|
2769
2793
|
return rows3.map((row, index) => row.size === "auto" ? heights[index] : numeric > 0 ? rest * row.size / numeric : 0);
|
|
2770
2794
|
}
|
|
2795
|
+
function shareHeights(needs, floors, total) {
|
|
2796
|
+
const space = Math.max(0, total);
|
|
2797
|
+
const need = needs.map((value) => Number.isFinite(value) ? Math.max(0, value) : 0);
|
|
2798
|
+
const floor = need.map((value, index) => Math.min(value, Math.max(0, Number.isFinite(floors[index]) ? floors[index] : 0)));
|
|
2799
|
+
const sum = (values) => values.reduce((a, b) => a + b, 0);
|
|
2800
|
+
const needed = sum(need), lowest = sum(floor);
|
|
2801
|
+
if (needed <= space) return need;
|
|
2802
|
+
if (lowest < space) {
|
|
2803
|
+
const give = (needed - space) / (needed - lowest);
|
|
2804
|
+
return need.map((value, index) => value - give * (value - floor[index]));
|
|
2805
|
+
}
|
|
2806
|
+
return lowest > 0 ? floor.map((value) => value * space / lowest) : need.map(() => 0);
|
|
2807
|
+
}
|
|
2771
2808
|
|
|
2772
2809
|
// src/direction.ts
|
|
2773
2810
|
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;
|
|
@@ -3354,6 +3391,93 @@ function resolveSlideDirection(presentation, slideIndex) {
|
|
|
3354
3391
|
}
|
|
3355
3392
|
}
|
|
3356
3393
|
|
|
3394
|
+
// src/quote-marks.ts
|
|
3395
|
+
var marks = (open, close) => ({ open, close });
|
|
3396
|
+
var ENGLISH = marks("\u201C", "\u201D");
|
|
3397
|
+
var GUILLEMETS = marks("\xAB", "\xBB");
|
|
3398
|
+
var LOW_HIGH = marks("\u201E", "\u201C");
|
|
3399
|
+
var LOW_RIGHT = marks("\u201E", "\u201D");
|
|
3400
|
+
var RIGHT_ONLY = marks("\u201D", "\u201D");
|
|
3401
|
+
var CORNER = marks("\u300C", "\u300D");
|
|
3402
|
+
var REVERSED = marks("\xBB", "\xAB");
|
|
3403
|
+
var QUOTE_MARKS = {
|
|
3404
|
+
en: ENGLISH,
|
|
3405
|
+
es: GUILLEMETS,
|
|
3406
|
+
fr: GUILLEMETS,
|
|
3407
|
+
de: LOW_HIGH,
|
|
3408
|
+
it: GUILLEMETS,
|
|
3409
|
+
pt: ENGLISH,
|
|
3410
|
+
nl: ENGLISH,
|
|
3411
|
+
ca: GUILLEMETS,
|
|
3412
|
+
gl: GUILLEMETS,
|
|
3413
|
+
eu: GUILLEMETS,
|
|
3414
|
+
sv: RIGHT_ONLY,
|
|
3415
|
+
fi: RIGHT_ONLY,
|
|
3416
|
+
da: REVERSED,
|
|
3417
|
+
nb: GUILLEMETS,
|
|
3418
|
+
nn: GUILLEMETS,
|
|
3419
|
+
no: GUILLEMETS,
|
|
3420
|
+
is: LOW_HIGH,
|
|
3421
|
+
pl: LOW_RIGHT,
|
|
3422
|
+
hu: LOW_RIGHT,
|
|
3423
|
+
ro: LOW_RIGHT,
|
|
3424
|
+
cs: LOW_HIGH,
|
|
3425
|
+
sk: LOW_HIGH,
|
|
3426
|
+
sl: LOW_HIGH,
|
|
3427
|
+
hr: LOW_HIGH,
|
|
3428
|
+
sr: LOW_HIGH,
|
|
3429
|
+
bg: LOW_HIGH,
|
|
3430
|
+
lt: LOW_HIGH,
|
|
3431
|
+
lv: LOW_HIGH,
|
|
3432
|
+
et: LOW_HIGH,
|
|
3433
|
+
ru: GUILLEMETS,
|
|
3434
|
+
uk: GUILLEMETS,
|
|
3435
|
+
el: GUILLEMETS,
|
|
3436
|
+
tr: ENGLISH,
|
|
3437
|
+
ga: ENGLISH,
|
|
3438
|
+
cy: ENGLISH,
|
|
3439
|
+
ja: CORNER,
|
|
3440
|
+
zh: ENGLISH,
|
|
3441
|
+
"zh-tw": CORNER,
|
|
3442
|
+
"zh-hk": CORNER,
|
|
3443
|
+
"zh-hant": CORNER,
|
|
3444
|
+
ko: ENGLISH,
|
|
3445
|
+
ar: GUILLEMETS,
|
|
3446
|
+
fa: GUILLEMETS,
|
|
3447
|
+
he: ENGLISH,
|
|
3448
|
+
ur: ENGLISH,
|
|
3449
|
+
hi: ENGLISH,
|
|
3450
|
+
th: ENGLISH,
|
|
3451
|
+
vi: ENGLISH,
|
|
3452
|
+
id: ENGLISH,
|
|
3453
|
+
ms: ENGLISH,
|
|
3454
|
+
"de-ch": GUILLEMETS,
|
|
3455
|
+
"fr-ch": GUILLEMETS,
|
|
3456
|
+
"pt-pt": GUILLEMETS
|
|
3457
|
+
};
|
|
3458
|
+
var ASCII_QUOTE_MARKS = marks('"', '"');
|
|
3459
|
+
function quoteMarksFor(tag) {
|
|
3460
|
+
if (tag === void 0 || tag === "") return ENGLISH;
|
|
3461
|
+
const lower = tag.toLowerCase().replaceAll("_", "-"), primary = lower.split("-")[0];
|
|
3462
|
+
return QUOTE_MARKS[lower] ?? QUOTE_MARKS[primary] ?? ASCII_QUOTE_MARKS;
|
|
3463
|
+
}
|
|
3464
|
+
function quoteLanguage(presentation, slideIndex) {
|
|
3465
|
+
if (presentation === null || typeof presentation !== "object" || presentation.language === void 0) return void 0;
|
|
3466
|
+
try {
|
|
3467
|
+
const resolved = resolveScriptFonts(presentation, Number.isInteger(slideIndex) ? { slideIndex } : {});
|
|
3468
|
+
return resolved.languageSource === "document" ? resolved.bcp47 : void 0;
|
|
3469
|
+
} catch {
|
|
3470
|
+
return void 0;
|
|
3471
|
+
}
|
|
3472
|
+
}
|
|
3473
|
+
var PAIRS = new Set(Object.values(QUOTE_MARKS).concat(ASCII_QUOTE_MARKS).map((entry) => entry.open + entry.close));
|
|
3474
|
+
function isWrappedInQuoteMarks(text2) {
|
|
3475
|
+
return text2.length >= 2 && PAIRS.has(text2[0] + text2.at(-1));
|
|
3476
|
+
}
|
|
3477
|
+
function unwrapQuoteMarks(text2) {
|
|
3478
|
+
return isWrappedInQuoteMarks(text2) ? text2.slice(1, -1) : text2;
|
|
3479
|
+
}
|
|
3480
|
+
|
|
3357
3481
|
// src/numbering.ts
|
|
3358
3482
|
var NUMBERING_STYLES = ["arabic", "roman-upper", "roman-lower", "alpha-upper", "alpha-lower"];
|
|
3359
3483
|
var NUMBERING_SUFFIXES = ["period", "paren", "paren-both"];
|
|
@@ -5340,7 +5464,7 @@ function fitImage(frame, fit, aspect, focus = { x: 0.5, y: 0.5 }) {
|
|
|
5340
5464
|
right: round2((image.x + width - frame.x - frame.width) / width),
|
|
5341
5465
|
bottom: round2((image.y + height - frame.y - frame.height) / height)
|
|
5342
5466
|
};
|
|
5343
|
-
for (const key of ["left", "top", "right", "bottom"]) if (
|
|
5467
|
+
for (const key of ["left", "top", "right", "bottom"]) if (Math.abs(crop[key]) < 1e-9) crop[key] = 0;
|
|
5344
5468
|
return { image: roundBox(image), crop };
|
|
5345
5469
|
}
|
|
5346
5470
|
function imageBackground(value) {
|
|
@@ -5375,17 +5499,29 @@ function composeOverlay(value, frame, shape, path, mirrorSide, diagnostics) {
|
|
|
5375
5499
|
const box = !edge ? frame : edge === "top" ? { ...frame, height: round2(frame.height * part) } : edge === "bottom" ? { ...frame, y: round2(frame.y + frame.height * (1 - part)), height: round2(frame.height * part) } : edge === "left" ? { ...frame, width: round2(frame.width * part) } : { ...frame, x: round2(frame.x + frame.width * (1 - part)), width: round2(frame.width * part) };
|
|
5376
5500
|
return { path, color: overlay.color, opacity, ...edge ? { edge } : {}, box, shape: edge ? imageShape("rectangle", box) : shape };
|
|
5377
5501
|
}
|
|
5502
|
+
function anchoredOffset(spare, anchor) {
|
|
5503
|
+
return Math.max(0, anchor === "middle" ? spare / 2 : anchor === "bottom" ? spare : 0);
|
|
5504
|
+
}
|
|
5505
|
+
function containedBox(cell, aspect, anchor) {
|
|
5506
|
+
const width = Math.min(cell.width, cell.height * aspect), height = width / aspect;
|
|
5507
|
+
return { x: cell.x + (cell.width - width) / 2, y: cell.y + anchoredOffset(cell.height - height, anchor), width, height };
|
|
5508
|
+
}
|
|
5378
5509
|
function composeImage(host, hostPath, region, frameArea, context) {
|
|
5379
5510
|
const kindName = Object.hasOwn(IMAGE_SHAPES, host.shape) ? host.shape : "rectangle";
|
|
5380
5511
|
const { scale: scale2 } = context;
|
|
5512
|
+
const fit = IMAGE_FITS.includes(host.fit) ? host.fit : context.fit ?? "cover";
|
|
5513
|
+
const pictureAspect = intrinsicImageAspect(host.image, context.assets);
|
|
5381
5514
|
let box = { ...frameArea };
|
|
5382
5515
|
const aspect = kindName === "circle" ? 1 : finite(host.aspectRatio, Number.MIN_VALUE, 10);
|
|
5383
5516
|
if (aspect) {
|
|
5384
5517
|
const frameWidth = Math.min(box.width, box.height * aspect), frameHeight = frameWidth / aspect;
|
|
5385
5518
|
box = { x: box.x + (box.width - frameWidth) / 2, y: box.y + (box.height - frameHeight) / 2, width: frameWidth, height: frameHeight };
|
|
5519
|
+
} else if (context.anchor && fit === "contain" && pictureAspect) {
|
|
5520
|
+
const frameWidth = Math.min(box.width, box.height * pictureAspect);
|
|
5521
|
+
box = { x: box.x + (box.width - frameWidth) / 2, y: box.y, width: frameWidth, height: frameWidth / pictureAspect };
|
|
5386
5522
|
}
|
|
5523
|
+
if (context.anchor && fit === "contain" && !aspect && box.height < frameArea.height) box.y = frameArea.y + anchoredOffset(frameArea.height - box.height, context.anchor);
|
|
5387
5524
|
box = roundBox(box);
|
|
5388
|
-
const fit = IMAGE_FITS.includes(host.fit) ? host.fit : context.fit ?? "cover";
|
|
5389
5525
|
const focus = imageFocus(host.focus);
|
|
5390
5526
|
const shape = imageShape(kindName, box, finite(host.cornerRadius, 0, 0.5));
|
|
5391
5527
|
const result = { region: roundBox(region), box, fit, focus, shape };
|
|
@@ -5398,7 +5534,6 @@ function composeImage(host, hostPath, region, frameArea, context) {
|
|
|
5398
5534
|
const overlay = composeOverlay(host.overlay, box, shape, `${hostPath}.overlay`, context.mirrorSide, context.diagnostics);
|
|
5399
5535
|
if (overlay) result.overlay = overlay;
|
|
5400
5536
|
if (context.placement) result.placement = context.placement;
|
|
5401
|
-
const pictureAspect = intrinsicImageAspect(host.image, context.assets);
|
|
5402
5537
|
if (pictureAspect) result.picture = fitImage(box, fit, pictureAspect, focus);
|
|
5403
5538
|
return result;
|
|
5404
5539
|
}
|
|
@@ -5622,7 +5757,72 @@ function layoutFurniture(input, options = {}) {
|
|
|
5622
5757
|
return { algorithm: "furniture-flow-v2", configured, textMeasurement: options.textMeasurement ? "provided" : "estimated", textOutlines: outlines ? "provided" : "unavailable", parts, headerBottom, footerTop, diagnostics, overflow: diagnostics.length > 0 };
|
|
5623
5758
|
}
|
|
5624
5759
|
var textSegments = new Intl.Segmenter("und", { granularity: "grapheme" });
|
|
5760
|
+
var PROSE_NOMINAL_SIZE = 28;
|
|
5761
|
+
var LIST_NOMINAL_SIZE = 32;
|
|
5762
|
+
var LEAD_NOMINAL_SIZE = 32;
|
|
5763
|
+
var TABLE_NOMINAL_SIZE = 25;
|
|
5764
|
+
var QUOTE_NOMINAL_SIZE = 40;
|
|
5765
|
+
var CODE_NOMINAL_SIZE = 22;
|
|
5766
|
+
var LEGACY_CODE_NOMINAL_SIZE = 18;
|
|
5767
|
+
var QUOTE_SOURCE_SEPARATOR = " \u2013 ";
|
|
5768
|
+
var PROSE_MEASURE_CHARS = 70;
|
|
5769
|
+
var AVERAGE_CHARACTER_EM = 0.5;
|
|
5625
5770
|
var WRAP_TOLERANCE = 0.01;
|
|
5771
|
+
var SENTENCE_END = /[.!?\u2026\u3002\uff01\uff1f]["'\u201d\u2019)\]\u00bb]*$/u;
|
|
5772
|
+
var CLAUSE_END = /[,;:\u2013\u2014\u060c\u061b\uff0c\u3001\uff1b\uff1a]["'\u201d\u2019)\]\u00bb]*$/u;
|
|
5773
|
+
var BALANCE_MAX_WORDS = 48;
|
|
5774
|
+
function balancedBreaks(text2, lines, widthOf, boxWidth) {
|
|
5775
|
+
const forced = /* @__PURE__ */ new Set();
|
|
5776
|
+
const paragraph = (group2) => {
|
|
5777
|
+
const count = group2.length;
|
|
5778
|
+
if (count < 2) return;
|
|
5779
|
+
const from = group2[0].start, to = group2.at(-1).end;
|
|
5780
|
+
const words = [...text2.slice(from, to).matchAll(/(?:[^\s]|\u00a0|\u202f|\ufeff)+/gu)].map((match) => ({ start: from + match.index, end: from + match.index + match[0].length, text: match[0] }));
|
|
5781
|
+
const total = words.length;
|
|
5782
|
+
if (total < count || total > BALANCE_MAX_WORDS) return;
|
|
5783
|
+
const cache2 = /* @__PURE__ */ new Map(), span = (first, last) => {
|
|
5784
|
+
const key = first * (BALANCE_MAX_WORDS + 1) + last;
|
|
5785
|
+
let value = cache2.get(key);
|
|
5786
|
+
if (value === void 0) {
|
|
5787
|
+
value = widthOf(words[first].start, words[last - 1].end);
|
|
5788
|
+
cache2.set(key, value);
|
|
5789
|
+
}
|
|
5790
|
+
return value;
|
|
5791
|
+
};
|
|
5792
|
+
const target = span(0, total) / count;
|
|
5793
|
+
if (!(target > 0)) return;
|
|
5794
|
+
const credit = (last) => last >= total ? 0 : SENTENCE_END.test(words[last - 1].text) ? 0.02 : CLAUSE_END.test(words[last - 1].text) ? 0.01 : 0;
|
|
5795
|
+
const best = Array.from({ length: count + 1 }, () => Array(total + 1).fill(Infinity)), from_ = Array.from({ length: count + 1 }, () => Array(total + 1).fill(-1));
|
|
5796
|
+
best[0][0] = 0;
|
|
5797
|
+
for (let line2 = 1; line2 <= count; line2++) for (let last = line2; last <= total - (count - line2); last++) for (let first = line2 - 1; first < last; first++) {
|
|
5798
|
+
const before = best[line2 - 1][first];
|
|
5799
|
+
if (before === Infinity) continue;
|
|
5800
|
+
const width = span(first, last);
|
|
5801
|
+
if (width > boxWidth + WRAP_TOLERANCE) continue;
|
|
5802
|
+
const cost = before + ((width - target) / target) ** 2 - credit(last);
|
|
5803
|
+
if (cost < best[line2][last]) {
|
|
5804
|
+
best[line2][last] = cost;
|
|
5805
|
+
from_[line2][last] = first;
|
|
5806
|
+
}
|
|
5807
|
+
}
|
|
5808
|
+
if (best[count][total] === Infinity) return;
|
|
5809
|
+
for (let line2 = count, last = total; line2 > 1; line2--) {
|
|
5810
|
+
const first = from_[line2][last];
|
|
5811
|
+
forced.add(words[first].start);
|
|
5812
|
+
last = first;
|
|
5813
|
+
}
|
|
5814
|
+
};
|
|
5815
|
+
let group = [];
|
|
5816
|
+
for (const line2 of lines) {
|
|
5817
|
+
group.push(line2);
|
|
5818
|
+
if (line2.hard) {
|
|
5819
|
+
paragraph(group);
|
|
5820
|
+
group = [];
|
|
5821
|
+
}
|
|
5822
|
+
}
|
|
5823
|
+
paragraph(group);
|
|
5824
|
+
return forced.size ? forced : void 0;
|
|
5825
|
+
}
|
|
5626
5826
|
var HANGING_SPACE = /[^\S\r\n\u00a0\u202f\ufeff]/u;
|
|
5627
5827
|
var SCRIPT_WIDTH_FACTORS = [
|
|
5628
5828
|
[/\p{Script=Tamil}/u, 1.53],
|
|
@@ -5646,11 +5846,11 @@ function measureText(text2, fontSize) {
|
|
|
5646
5846
|
function wrapText(text2, width, fontSize, measure = measureText) {
|
|
5647
5847
|
return fitSourceText(text2, { width, height: Number.MAX_VALUE }, fontSize, fontSize, 1, measure, true, false).lines;
|
|
5648
5848
|
}
|
|
5649
|
-
function fitText(text2, box, requestedSize =
|
|
5849
|
+
function fitText(text2, box, requestedSize = PROSE_NOMINAL_SIZE, minFontSize = 16, measure = measureText, direction, balance = false) {
|
|
5650
5850
|
if (![box.width, box.height, requestedSize, minFontSize].every(Number.isFinite) || box.width <= 0 || box.height <= 0 || requestedSize <= 0 || minFontSize <= 0) {
|
|
5651
5851
|
throw new RangeError("Text dimensions and font sizes must be finite and positive.");
|
|
5652
5852
|
}
|
|
5653
|
-
return fitSourceText(text2, box, Math.max(requestedSize, minFontSize), minFontSize, 1, measure, true, true, direction);
|
|
5853
|
+
return fitSourceText(text2, box, Math.max(requestedSize, minFontSize), minFontSize, 1, measure, true, true, direction, balance);
|
|
5654
5854
|
}
|
|
5655
5855
|
var FONT_SIZE_GRID_PER_PX = 75;
|
|
5656
5856
|
var FONT_GRID_EPSILON = 1e-6;
|
|
@@ -5675,11 +5875,11 @@ function fitAtSizes(layout, requested, minimum, step = 1, snap = true) {
|
|
|
5675
5875
|
}
|
|
5676
5876
|
var PHOTO_RATIO = 3;
|
|
5677
5877
|
var PHOTO_GAP = 0.75;
|
|
5678
|
-
function quoteBodyRuns(runs) {
|
|
5679
|
-
if (!runs.length) return [
|
|
5878
|
+
function quoteBodyRuns(runs, marks2) {
|
|
5879
|
+
if (!runs.length) return [marks2.open + marks2.close];
|
|
5680
5880
|
const last = runs.length - 1;
|
|
5681
5881
|
return runs.map((run, index) => {
|
|
5682
|
-
const before = index === 0 ?
|
|
5882
|
+
const before = index === 0 ? marks2.open : "", after = index === last ? marks2.close : "";
|
|
5683
5883
|
return typeof run === "string" ? before + run + after : { ...run, text: before + run.text + after };
|
|
5684
5884
|
});
|
|
5685
5885
|
}
|
|
@@ -5714,23 +5914,24 @@ function layoutQuote(value, box, options = {}) {
|
|
|
5714
5914
|
for (const field of ["attribution", "role", "source"]) {
|
|
5715
5915
|
const text2 = quote[field];
|
|
5716
5916
|
if (!text2) continue;
|
|
5717
|
-
if (footer) footer += field === "role" ? "\n" :
|
|
5917
|
+
if (footer) footer += field === "role" ? "\n" : QUOTE_SOURCE_SEPARATOR;
|
|
5718
5918
|
footerSources.push(source(`${path}.${field}`, text2, footer.length));
|
|
5719
5919
|
footer += text2;
|
|
5720
5920
|
}
|
|
5721
5921
|
const hasPhoto = photoValue !== void 0, hasFooter = footer !== "", hasBlock = hasPhoto || hasFooter;
|
|
5722
5922
|
const photoPath = `${path}.photo`, rtl = options.direction === "rtl";
|
|
5723
5923
|
const bodyPath = shorthand ? path : `${path}.text`;
|
|
5924
|
+
const marks2 = quoteMarksFor(options.language);
|
|
5724
5925
|
const body = add(
|
|
5725
5926
|
"body",
|
|
5726
|
-
|
|
5727
|
-
[source(bodyPath, quoteText,
|
|
5927
|
+
`${marks2.open}${quoteText}${marks2.close}`,
|
|
5928
|
+
[source(bodyPath, quoteText, marks2.open.length)],
|
|
5728
5929
|
{ x: box.x + 18, y: box.y + 18, width: box.width - 36, height: box.height - (hasBlock ? 94 : 36) },
|
|
5729
|
-
|
|
5930
|
+
QUOTE_NOMINAL_SIZE,
|
|
5730
5931
|
options.fontFamilies?.accent ?? options.fontFamilies?.heading ?? "sans-serif",
|
|
5731
5932
|
600,
|
|
5732
5933
|
bodyPath,
|
|
5733
|
-
richBody ? quoteBodyRuns(richBody) : void 0
|
|
5934
|
+
richBody ? quoteBodyRuns(richBody, marks2) : void 0
|
|
5734
5935
|
);
|
|
5735
5936
|
const attribution = hasFooter ? add(
|
|
5736
5937
|
"footer",
|
|
@@ -5852,7 +6053,7 @@ function layoutMetric(value, box, options = {}) {
|
|
|
5852
6053
|
const sourceValue = metric[role];
|
|
5853
6054
|
if (sourceValue === void 0) continue;
|
|
5854
6055
|
const text2 = String(sourceValue), path = scalar ? sourcePath : `${sourcePath}.${role}`;
|
|
5855
|
-
const nominal = role === "value" ?
|
|
6056
|
+
const nominal = (role === "value" ? 76 : role === "description" ? 20 : role === "trend" ? 18 : 23) * scale2;
|
|
5856
6057
|
const requestedStyle = { fontFamily: (role === "value" ? options.fontFamilies?.heading : options.fontFamilies?.body) ?? "sans-serif", fontWeight: role === "value" ? 800 : role === "description" ? 400 : 500, italic: false, path };
|
|
5857
6058
|
const part = {
|
|
5858
6059
|
role,
|
|
@@ -6167,9 +6368,9 @@ function layoutTimeline(value, box, options = {}) {
|
|
|
6167
6368
|
function fitCodeText(text2, box, size, minimum, step, measure, direction) {
|
|
6168
6369
|
return fitSourceText(text2, box, size, minimum, step, measure, false, true, direction);
|
|
6169
6370
|
}
|
|
6170
|
-
function fitSourceText(text2, box, size, minimum, step, measure, prose = false, snap = true, direction) {
|
|
6371
|
+
function fitSourceText(text2, box, size, minimum, step, measure, prose = false, snap = true, direction, balance = false) {
|
|
6171
6372
|
const directionAt = direction === "rtl" ? paragraphDirectionAt(text2, "rtl") : void 0;
|
|
6172
|
-
const layout = (fontSize) => {
|
|
6373
|
+
const layout = (fontSize, forced) => {
|
|
6173
6374
|
const tabWidth = measure(" ", fontSize) * 4;
|
|
6174
6375
|
if (!Number.isFinite(tabWidth) || text2.includes(" ") && tabWidth <= 0) throw new RangeError("Text tabs require a positive finite measured space advance.");
|
|
6175
6376
|
const measureLine = (start2, end2, record8 = false) => {
|
|
@@ -6210,6 +6411,7 @@ function fitSourceText(text2, box, size, minimum, step, measure, prose = false,
|
|
|
6210
6411
|
push(a, b, "hard");
|
|
6211
6412
|
continue;
|
|
6212
6413
|
}
|
|
6414
|
+
if (forced?.has(a) && end > start && /\S/u.test(text2.slice(start, end))) push(a, a, "soft");
|
|
6213
6415
|
if (width(start, b) <= box.width + WRAP_TOLERANCE) {
|
|
6214
6416
|
end = b;
|
|
6215
6417
|
continue;
|
|
@@ -6247,7 +6449,22 @@ function fitSourceText(text2, box, size, minimum, step, measure, prose = false,
|
|
|
6247
6449
|
overflow: sourceLines.length * lineHeight > box.height + 0.01 || sourceLines.some((line2) => line2.width > box.width + 0.01)
|
|
6248
6450
|
};
|
|
6249
6451
|
};
|
|
6250
|
-
|
|
6452
|
+
const balanced = (fontSize) => {
|
|
6453
|
+
const greedy = layout(fontSize);
|
|
6454
|
+
if (!balance || greedy.overflow || greedy.sourceLines.length < 2) return greedy;
|
|
6455
|
+
const widthOf = (start, end) => {
|
|
6456
|
+
let x = 0;
|
|
6457
|
+
for (const [index, segment2] of text2.slice(start, end).split(" ").entries()) {
|
|
6458
|
+
if (index) x = (Math.floor(x / (measure(" ", fontSize) * 4) + 1e-9) + 1) * measure(" ", fontSize) * 4;
|
|
6459
|
+
if (segment2) x += measure(segment2, fontSize);
|
|
6460
|
+
}
|
|
6461
|
+
return x;
|
|
6462
|
+
};
|
|
6463
|
+
const forced = balancedBreaks(text2, greedy.sourceLines.map((line2) => ({ start: line2.start, end: line2.end, hard: line2.boundary !== "soft" })), widthOf, box.width);
|
|
6464
|
+
const result = forced ? layout(fontSize, forced) : greedy;
|
|
6465
|
+
return result.sourceLines.length === greedy.sourceLines.length && !result.overflow ? result : greedy;
|
|
6466
|
+
};
|
|
6467
|
+
return fitAtSizes(balance ? balanced : layout, size, minimum, step, snap);
|
|
6251
6468
|
}
|
|
6252
6469
|
function layoutCode(value, box, options = {}) {
|
|
6253
6470
|
const shorthand = typeof value === "string", code = shorthand ? { source: value } : value;
|
|
@@ -6270,7 +6487,7 @@ function layoutCode(value, box, options = {}) {
|
|
|
6270
6487
|
sources: generated ? [] : [{ path: partPath, start: 0, end: text2.length }],
|
|
6271
6488
|
generated,
|
|
6272
6489
|
box: { ...inner },
|
|
6273
|
-
requestedFontSize: gridFontSize((role === "body" ?
|
|
6490
|
+
requestedFontSize: gridFontSize((role === "body" ? CODE_NOMINAL_SIZE : 14) * scale2, minimum),
|
|
6274
6491
|
minFontSize: minimum,
|
|
6275
6492
|
requestedStyle,
|
|
6276
6493
|
style: resolveTextStyle({ ...requestedStyle }, options.textMeasurement)
|
|
@@ -6283,7 +6500,16 @@ function layoutCode(value, box, options = {}) {
|
|
|
6283
6500
|
if (!parts.length) add("language", "code", path, true);
|
|
6284
6501
|
const body = add("body", code.source, shorthand ? path : `${path}.source`), headers = parts.filter((part) => part !== body);
|
|
6285
6502
|
const usable2 = (area2) => [area2.x, area2.y, area2.width, area2.height].every(Number.isFinite) && area2.width > 0 && area2.height > 0;
|
|
6286
|
-
const
|
|
6503
|
+
const measureCode = textWidthMeasurer(body.style, options.textMeasurement);
|
|
6504
|
+
const fit = (part, area2, size = part.requestedFontSize, floor = minimum) => {
|
|
6505
|
+
if (!usable2(area2)) return void 0;
|
|
6506
|
+
const wanted = fitCodeText(part.text, area2, size, floor, scale2, textWidthMeasurer(part.style, options.textMeasurement));
|
|
6507
|
+
const wraps = (value2) => value2.sourceLines.filter((line2) => line2.boundary === "soft").length;
|
|
6508
|
+
const legacy = gridFontSize(LEGACY_CODE_NOMINAL_SIZE * scale2, minimum);
|
|
6509
|
+
if (part.role !== "body" || part.requestedFontSize <= legacy || !wraps(wanted)) return wanted;
|
|
6510
|
+
const earlier = fitCodeText(part.text, area2, legacy, floor, scale2, measureCode);
|
|
6511
|
+
return !earlier.overflow && wraps(earlier) < wraps(wanted) ? earlier : wanted;
|
|
6512
|
+
};
|
|
6287
6513
|
if (usable2(inner)) {
|
|
6288
6514
|
const combinations = headers.reduce((choices, part) => choices.flatMap((choice) => [.../* @__PURE__ */ new Set([part.requestedFontSize, minimum])].map((size) => [...choice, { part, size }])), [[]]);
|
|
6289
6515
|
let selected;
|
|
@@ -6306,6 +6532,7 @@ function layoutCode(value, box, options = {}) {
|
|
|
6306
6532
|
part.box = box2;
|
|
6307
6533
|
part.fit = fit2;
|
|
6308
6534
|
}
|
|
6535
|
+
if (selected && !selected.overflow && body.fit) body.box = { ...body.box, height: Math.min(body.box.height, body.fit.lines.length * body.fit.lineHeight) };
|
|
6309
6536
|
}
|
|
6310
6537
|
const report = (reason, part, roles, message) => diagnostics.push({ code: "text-overflow", reason, path: part.path, parts: roles, message });
|
|
6311
6538
|
for (const part of parts) {
|
|
@@ -6323,9 +6550,11 @@ function layoutCode(value, box, options = {}) {
|
|
|
6323
6550
|
}
|
|
6324
6551
|
}
|
|
6325
6552
|
if (diagnostics.length && options.overflow === "error") throw new OPFCompositionError(diagnostics);
|
|
6326
|
-
|
|
6553
|
+
const bottom = body.fit && !body.fit.overflow ? body.box.y + body.box.height + 18 : box.y + box.height;
|
|
6554
|
+
const bounds = { x: box.x, y: box.y, width: box.width, height: Math.min(box.height, Math.max(bottom - box.y, 0)) };
|
|
6555
|
+
return { bounds, algorithm: "code-flow-v1", textMeasurement: options.textMeasurement ? "provided" : "estimated", parts, diagnostics, overflow: diagnostics.length > 0 };
|
|
6327
6556
|
}
|
|
6328
|
-
function fitRichText(input, box, requestedSize =
|
|
6557
|
+
function fitRichText(input, box, requestedSize = PROSE_NOMINAL_SIZE, minFontSize = 16, options = { style: { fontFamily: "sans-serif", fontWeight: 400 } }) {
|
|
6329
6558
|
if (![box.width, box.height, requestedSize, minFontSize].every((value) => Number.isFinite(value) && value > 0)) throw new RangeError("Rich text dimensions and font sizes must be finite and positive.");
|
|
6330
6559
|
const layout = richTextLayouter(input, box, requestedSize, options, minFontSize);
|
|
6331
6560
|
return fitAtSizes(layout, requestedSize, richMinimum(input, requestedSize, minFontSize));
|
|
@@ -6342,7 +6571,7 @@ function richMinimum(input, requested, minimum) {
|
|
|
6342
6571
|
return visible ? floor : minimum;
|
|
6343
6572
|
}
|
|
6344
6573
|
function richTextLayouter(input, box, requestedSize, options, minimum = 0) {
|
|
6345
|
-
let offset = 0;
|
|
6574
|
+
let offset = 0, lastWidth = () => 0, lastRanges = [];
|
|
6346
6575
|
const source = input.map((value, runIndex) => {
|
|
6347
6576
|
const run = typeof value === "string" ? { text: value } : value;
|
|
6348
6577
|
if (typeof run?.text !== "string" || run.fontSize !== void 0 && (!Number.isFinite(run.fontSize) || run.fontSize <= 0)) throw new RangeError("Rich text runs need text and a positive finite font size.");
|
|
@@ -6356,7 +6585,7 @@ function richTextLayouter(input, box, requestedSize, options, minimum = 0) {
|
|
|
6356
6585
|
const whole = source.map((entry) => entry.run.text).join("");
|
|
6357
6586
|
const paint = (raw) => raw >= minimum - 1e-6 ? gridFontSize(raw, minimum) : snapFontSizeDown(raw);
|
|
6358
6587
|
const directionAt = options.direction === "rtl" ? paragraphDirectionAt(whole, "rtl") : void 0;
|
|
6359
|
-
const
|
|
6588
|
+
const build = (rawFontSize, forced) => {
|
|
6360
6589
|
const fontSize = paint(rawFontSize), ratio = rawFontSize / requestedSize;
|
|
6361
6590
|
const fragments = (start, end) => {
|
|
6362
6591
|
let x = 0;
|
|
@@ -6411,6 +6640,7 @@ function richTextLayouter(input, box, requestedSize, options, minimum = 0) {
|
|
|
6411
6640
|
lineEnd = end;
|
|
6412
6641
|
continue;
|
|
6413
6642
|
}
|
|
6643
|
+
if (forced?.has(start) && lineEnd > lineStart && /\S/u.test(whole.slice(lineStart, lineEnd))) push(start);
|
|
6414
6644
|
if (width(lineStart, end) <= box.width + WRAP_TOLERANCE) {
|
|
6415
6645
|
lineEnd = end;
|
|
6416
6646
|
continue;
|
|
@@ -6454,7 +6684,7 @@ function richTextLayouter(input, box, requestedSize, options, minimum = 0) {
|
|
|
6454
6684
|
y += height;
|
|
6455
6685
|
}
|
|
6456
6686
|
}
|
|
6457
|
-
|
|
6687
|
+
const fit = {
|
|
6458
6688
|
lines: ranges.map((range) => whole.slice(range.start, range.end)),
|
|
6459
6689
|
fontSize,
|
|
6460
6690
|
lineHeight: Math.max(fontSize * 1.22, ...richLines.map((line2) => line2.height)),
|
|
@@ -6463,12 +6693,22 @@ function richTextLayouter(input, box, requestedSize, options, minimum = 0) {
|
|
|
6463
6693
|
overflow: y > box.height + 0.01 || richLines.some((line2) => line2.width > box.width + 0.01),
|
|
6464
6694
|
...directionAt ? { directions: ranges.map((range) => directionAt(range.start)) } : {}
|
|
6465
6695
|
};
|
|
6696
|
+
lastWidth = width;
|
|
6697
|
+
lastRanges = ranges;
|
|
6698
|
+
return fit;
|
|
6699
|
+
};
|
|
6700
|
+
const layout = (rawFontSize) => {
|
|
6701
|
+
const greedy = build(rawFontSize);
|
|
6702
|
+
if (!options.balance || greedy.overflow || greedy.richLines.length < 2) return greedy;
|
|
6703
|
+
const forced = balancedBreaks(whole, lastRanges.map((range) => ({ start: range.start, end: range.end, hard: /^[\r\n]/.test(whole.slice(range.end, range.end + 1)) || range.end >= whole.length })), lastWidth, box.width);
|
|
6704
|
+
const result = forced ? build(rawFontSize, forced) : greedy;
|
|
6705
|
+
return result.richLines.length === greedy.richLines.length && !result.overflow ? result : greedy;
|
|
6466
6706
|
};
|
|
6467
6707
|
return layout;
|
|
6468
6708
|
}
|
|
6469
6709
|
var PICTURE_BULLET_SCALE = 0.65;
|
|
6470
6710
|
function contentNominalSize(field) {
|
|
6471
|
-
return field === "items" || field === "bullets" ?
|
|
6711
|
+
return field === "items" || field === "bullets" ? LIST_NOMINAL_SIZE : field === "table" ? TABLE_NOMINAL_SIZE : PROSE_NOMINAL_SIZE;
|
|
6472
6712
|
}
|
|
6473
6713
|
function fitList(input, box, requestedSize = contentNominalSize("items"), minFontSize = 16, options = { style: { fontFamily: "sans-serif", fontWeight: 400 } }) {
|
|
6474
6714
|
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.");
|
|
@@ -6493,10 +6733,11 @@ function fitList(input, box, requestedSize = contentNominalSize("items"), minFon
|
|
|
6493
6733
|
const entries = [], lines = [], directions = [];
|
|
6494
6734
|
const markerStyles = numbers ? source.map((item) => resolveTextStyle(markerStyleFor(item), options.textMeasurement)) : [];
|
|
6495
6735
|
const markerWidths = numbers ? numbers.map((number, index) => textWidthMeasurer(markerStyles[index], options.textMeasurement)(number.text, fontSize)) : [];
|
|
6736
|
+
const none = options.bullet === "none" && !numbers;
|
|
6496
6737
|
const hanging = numbers ? Math.max(fontSize * 1.1, Math.max(0, ...markerWidths) + fontSize * 0.3) : fontSize * 1.1;
|
|
6497
6738
|
for (const item of source) {
|
|
6498
6739
|
const rtl = item.direction === "rtl";
|
|
6499
|
-
const indent = hanging, offset = Math.min(box.width, item.level *
|
|
6740
|
+
const indent = none ? 0 : hanging, offset = Math.min(box.width, item.level * hanging), x = rtl ? box.x : box.x + offset + indent, width = Math.max(1, rtl ? box.width - offset - indent : box.x + box.width - x);
|
|
6500
6741
|
if (offset + indent >= box.width) overflow = true;
|
|
6501
6742
|
const textBox = { x, y, width, height: box.height };
|
|
6502
6743
|
const style = { ...options.style, path: item.textPath };
|
|
@@ -6517,7 +6758,7 @@ function fitList(input, box, requestedSize = contentNominalSize("items"), minFon
|
|
|
6517
6758
|
}
|
|
6518
6759
|
overflow ||= text2.overflow || !!description?.overflow;
|
|
6519
6760
|
const number = numbers?.[item.index];
|
|
6520
|
-
const marker = { text: number ? number.text : ["\u2022", "\u25E6", "\u25AA"][item.level % 3], x: rtl ? box.x + box.width - offset : box.x + offset, y: textBox.y + (text2.richLines[0]?.baseline ?? fontSize), fontSize, style: number ? markerStyles[item.index] : resolveTextStyle(style, options.textMeasurement), indent, ...number ? { number, width: markerWidths[item.index] } : {}, ...rtl ? { anchor: "end" } : {} }, side = fontSize * PICTURE_BULLET_SCALE;
|
|
6761
|
+
const marker = { text: number ? number.text : none ? "" : ["\u2022", "\u25E6", "\u25AA"][item.level % 3], x: rtl ? box.x + box.width - offset : box.x + offset, y: textBox.y + (text2.richLines[0]?.baseline ?? fontSize), fontSize, style: number ? markerStyles[item.index] : resolveTextStyle(style, options.textMeasurement), indent, ...number ? { number, width: markerWidths[item.index] } : {}, ...none ? { none: true } : {}, ...rtl ? { anchor: "end" } : {} }, side = fontSize * PICTURE_BULLET_SCALE;
|
|
6521
6762
|
entries.push({
|
|
6522
6763
|
index: item.index,
|
|
6523
6764
|
level: item.level,
|
|
@@ -6531,7 +6772,7 @@ function fitList(input, box, requestedSize = contentNominalSize("items"), minFon
|
|
|
6531
6772
|
descriptionBox,
|
|
6532
6773
|
marker,
|
|
6533
6774
|
...item.direction ? { direction: item.direction } : {},
|
|
6534
|
-
...options.bulletImage && !number ? { bulletImage: options.bulletImage, bulletBox: { x: rtl ? marker.x - side : marker.x, y: marker.y - side, width: side, height: side } } : {}
|
|
6775
|
+
...options.bulletImage && !number && !none ? { bulletImage: options.bulletImage, bulletBox: { x: rtl ? marker.x - side : marker.x, y: marker.y - side, width: side, height: side } } : {}
|
|
6535
6776
|
});
|
|
6536
6777
|
if (item.index < source.length - 1) y += fontSize * 0.28;
|
|
6537
6778
|
}
|
|
@@ -6798,14 +7039,15 @@ function composeSlide(input, options = {}) {
|
|
|
6798
7039
|
const minSize = snapFontSizeUp((composition.minFontSize ?? 16) * scale2);
|
|
6799
7040
|
const rasterPadding = (options.textRasterPadding ?? 1) * scale2;
|
|
6800
7041
|
if (!Number.isFinite(rasterPadding) || rasterPadding < 0) throw new RangeError("Text raster padding must be finite and nonnegative.");
|
|
6801
|
-
let
|
|
6802
|
-
const alignmentFor = (field) => (field === "title" || (field === "tag" ||
|
|
7042
|
+
let subtitleInGroup = true;
|
|
7043
|
+
const alignmentFor = (field) => (field === "title" || (field === "tag" || subtitleInGroup && field === "subtitle") && hints.sources.contentAlignment !== "slide" ? hints.titleAlignment : hints.contentAlignment) ?? (field === "metric" ? "center" : "left");
|
|
6803
7044
|
const styleFor = (field, path2) => resolveTextStyle({
|
|
6804
7045
|
fontFamily: (field === "title" ? options.fontFamilies?.heading : field === "code" ? options.fontFamilies?.code : field === "tag" ? options.fontFamilies?.accent ?? options.fontFamilies?.body : options.fontFamilies?.body) ?? (field === "code" ? "monospace" : "sans-serif"),
|
|
6805
7046
|
fontWeight: field === "title" ? 700 : 400,
|
|
6806
7047
|
path: path2
|
|
6807
7048
|
}, options.textMeasurement);
|
|
6808
7049
|
const listBullet = hints.listBullet !== void 0 ? { value: hints.listBullet, path: hints.paths.listBullet } : void 0;
|
|
7050
|
+
const noListBullet = listBullet?.value === "none";
|
|
6809
7051
|
const bulletImage = listBullet?.value === "image" ? (() => {
|
|
6810
7052
|
const resolved = resolveLogo(options.presentation, slide, { shape: "icon", onDark: options.darkBackground, slideIndex: options.slideIndex });
|
|
6811
7053
|
return resolved ? { source: resolved.source, path: resolved.path } : void 0;
|
|
@@ -6816,13 +7058,14 @@ function composeSlide(input, options = {}) {
|
|
|
6816
7058
|
const richOptions = (style) => ({ style, textMeasurement: options.textMeasurement, ...options.fontFamilies?.code ? { codeFontFamily: options.fontFamilies.code } : {}, ...citationMarker ? { citationMarker } : {}, ...rtl ? { direction: "rtl" } : {} });
|
|
6817
7059
|
const fitPlacedText = (field, value, text2, box, size, minimum, path2, explicitAlignment) => {
|
|
6818
7060
|
const style = styleFor(field, path2), rich = (field === "text" || headings.has(field)) && Array.isArray(value);
|
|
6819
|
-
|
|
7061
|
+
const balance = field === "title" || field === "subtitle", textOptions = balance ? { ...richOptions(style), balance } : richOptions(style);
|
|
7062
|
+
if (!options.textMeasurement?.outlineBounds) return rich ? fitRichText(value, box, size, minimum, textOptions) : fitText(text2, box, size, minimum, textWidthMeasurer(style, options.textMeasurement), textDirection, balance);
|
|
6820
7063
|
const alignment = explicitAlignment ?? alignmentFor(field);
|
|
6821
|
-
const richLayout = rich ? richTextLayouter(value, box, size,
|
|
7064
|
+
const richLayout = rich ? richTextLayouter(value, box, size, textOptions, minimum) : void 0;
|
|
6822
7065
|
const measure = textWidthMeasurer(style, options.textMeasurement), floor = snapFontSizeUp(rich ? richMinimum(value, size, minimum) : minimum), start = Math.max(size, floor);
|
|
6823
7066
|
for (let trial = 0; trial <= 64; trial++) {
|
|
6824
7067
|
const raw = start - trial * scale2, last = trial === 64 || raw <= floor, fontSize = last ? floor : gridFontSize(raw, floor);
|
|
6825
|
-
const fit = richLayout ? richLayout(fontSize) : fitText(text2, box, fontSize, fontSize, measure, textDirection);
|
|
7068
|
+
const fit = richLayout ? richLayout(fontSize) : fitText(text2, box, fontSize, fontSize, measure, textDirection, balance);
|
|
6826
7069
|
const richLines = "richLines" in fit ? fit.richLines : void 0;
|
|
6827
7070
|
const lines = richLines ? richLines.map((line2) => {
|
|
6828
7071
|
let outline = null;
|
|
@@ -6864,7 +7107,7 @@ function composeSlide(input, options = {}) {
|
|
|
6864
7107
|
}
|
|
6865
7108
|
throw new Error("Text placement did not evaluate its bounded floor trial.");
|
|
6866
7109
|
};
|
|
6867
|
-
const fitContent = (field, value, text2, box, size, minimum, path2, numbering) => field === "text" ? fitPlacedText(field, value, text2, box, size, minimum, path2) : field === "items" || field === "bullets" ? fitList(value, box, size, minimum, { ...richOptions(styleFor(field, path2)), ...numbering !== void 0 ? { numbering } : bulletImage ? { bulletImage } : {} }) : fitText(text2, box, size, minimum, widthFor(field, path2), field === "code" ? void 0 : textDirection);
|
|
7110
|
+
const fitContent = (field, value, text2, box, size, minimum, path2, numbering) => field === "text" ? fitPlacedText(field, value, text2, box, size, minimum, path2) : field === "items" || field === "bullets" ? fitList(value, box, size, minimum, { ...richOptions(styleFor(field, path2)), ...numbering !== void 0 ? { numbering } : bulletImage ? { bulletImage } : noListBullet ? { bullet: "none" } : {} }) : fitText(text2, box, size, minimum, widthFor(field, path2), field === "code" ? void 0 : textDirection);
|
|
6868
7111
|
const path = `slides.${options.slideIndex ?? 0}`;
|
|
6869
7112
|
const annotationFit = (value, box, requestedSize, minFontSize, fitPath, alignment) => fitPlacedText("text", value, annotationText(value), box, requestedSize, minFontSize, fitPath, alignment);
|
|
6870
7113
|
const annotationOptions = { scale: scale2, minFontSize: minSize, fit: annotationFit, textStyle: (fitPath) => styleFor("text", fitPath) };
|
|
@@ -6873,7 +7116,7 @@ function composeSlide(input, options = {}) {
|
|
|
6873
7116
|
const backgroundImage = resolveBackgroundImage(slide, options.presentation, options.themeBackground, width, height, path, mirrorSide, imageDiagnostics);
|
|
6874
7117
|
const regions = Object.keys(slide).filter((key) => regionParts(key)).sort();
|
|
6875
7118
|
const assets = record7(options.presentation).assets;
|
|
6876
|
-
const imageContext = (placement) => ({ fit: hints.imageFit, scale: scale2, mirrorSide, diagnostics: imageDiagnostics, assets, ...placement ? { placement } : {} });
|
|
7119
|
+
const imageContext = (placement, anchor) => ({ fit: hints.imageFit ?? (!placement && autoComposition() ? "contain" : void 0), scale: scale2, mirrorSide, diagnostics: imageDiagnostics, assets, ...placement ? { placement } : {}, ...anchor ? { anchor } : {} });
|
|
6877
7120
|
const area2 = { left: 0, top: 0, right: width, bottom: height };
|
|
6878
7121
|
const topImages = regions.length ? [] : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => !Array.isArray(record7(block).blocks) && record7(block).image !== void 0 ? [{ host: record7(block), hostPath: `${path}.blocks.${index}`, block: index }] : []) : slide.image !== void 0 ? [{ host: { type: "image", image: slide.image }, hostPath: path }] : [];
|
|
6879
7122
|
const placed = [], usedEdges = /* @__PURE__ */ new Set();
|
|
@@ -6915,8 +7158,9 @@ function composeSlide(input, options = {}) {
|
|
|
6915
7158
|
const flowBlocks = Array.isArray(slide.blocks) ? slide.blocks.filter((_, index) => !placedBlocks.has(index)) : slide.blocks;
|
|
6916
7159
|
const hasBodyPayload = regions.some((key) => !emptyHost(record7(slide[key]))) || !emptyPayload(flowBlocks) || fields.some((field) => !(placedRoot && field === "image") && !emptyPayload(slide[field]));
|
|
6917
7160
|
const useTemplate = template !== void 0 && !regions.length;
|
|
7161
|
+
const autoComposition = () => !hasLayoutRecord && !regions.length;
|
|
6918
7162
|
const isCover = !hasBodyPayload && (useTemplate || !hasLayoutRecord);
|
|
6919
|
-
|
|
7163
|
+
subtitleInGroup = !(useTemplate && template?.subtitle === true);
|
|
6920
7164
|
let logo;
|
|
6921
7165
|
if (isCover && options[LAYOUT_MASTER] !== true) {
|
|
6922
7166
|
const resolved = resolveLogo(options.presentation, slide, { shape: "full", onDark: options.darkBackground, slideIndex: options.slideIndex });
|
|
@@ -6931,7 +7175,7 @@ function composeSlide(input, options = {}) {
|
|
|
6931
7175
|
const headingItems = [];
|
|
6932
7176
|
for (const field of useTemplate ? [] : ["tag", "title", "subtitle"]) {
|
|
6933
7177
|
if (!slide[field] || Array.isArray(slide[field]) && !annotationText(slide[field])) continue;
|
|
6934
|
-
const requested = (field === "title" ? 54 : field === "tag" ? 16 :
|
|
7178
|
+
const requested = (field === "title" ? 54 : field === "tag" ? 16 : PROSE_NOMINAL_SIZE) * scale2;
|
|
6935
7179
|
const maxHeight = Math.max(height * (field === "title" ? 0.26 : field === "subtitle" ? 0.12 : 0.045), minSize * 1.22 + 2 * rasterPadding);
|
|
6936
7180
|
const box = { x: area2.left + padding, y, width: area2.right - area2.left - padding * 2, height: maxHeight };
|
|
6937
7181
|
const text2 = fitPlacedText(field, slide[field], annotationText(slide[field]), box, requested, minSize, `${path}.${field}`);
|
|
@@ -7008,6 +7252,8 @@ function composeSlide(input, options = {}) {
|
|
|
7008
7252
|
const regionsInReadingOrder = visualReadingOrder(regions.map((key) => ({ key, box: regionBox(regionParts(key), contentBox, gap) }))).map((entry) => entry.key);
|
|
7009
7253
|
const pending = regions.length ? regionsInReadingOrder.flatMap((key) => collect(record7(slide[key]), `${path}.${key}`).map((item) => ({ ...item, region: regionParts(key) }))) : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => placedBlocks.has(index) ? [] : collect(record7(block), `${path}.blocks.${index}`)) : collect(placedRoot ? { ...slide, image: void 0 } : slide, path);
|
|
7010
7254
|
const groups = [], flows = [];
|
|
7255
|
+
const peerSets = [];
|
|
7256
|
+
const range = (from, to) => Array.from({ length: to - from }, (_, index) => from + index);
|
|
7011
7257
|
const decisions = options.explain ? [] : void 0;
|
|
7012
7258
|
const inheritedSettings = (parent, own3 = {}) => ({
|
|
7013
7259
|
minFontSize: parent.minFontSize,
|
|
@@ -7024,6 +7270,11 @@ function composeSlide(input, options = {}) {
|
|
|
7024
7270
|
const frame = acceptedBox(box), padding2 = Math.min(12 * scale2, frame.width / 4, frame.height / 4);
|
|
7025
7271
|
return acceptedBox({ x: frame.x + padding2, y: frame.y + padding2, width: frame.width - 2 * padding2, height: frame.height - 2 * padding2 });
|
|
7026
7272
|
};
|
|
7273
|
+
let languageTag = null;
|
|
7274
|
+
const deckLanguage = () => {
|
|
7275
|
+
if (languageTag === null) languageTag = quoteLanguage(options.presentation, options.slideIndex);
|
|
7276
|
+
return languageTag;
|
|
7277
|
+
};
|
|
7027
7278
|
const measureQuote = (node, box, settings) => layoutQuote(node.value, acceptedBox(box), {
|
|
7028
7279
|
fontFamilies: options.fontFamilies,
|
|
7029
7280
|
textMeasurement: options.textMeasurement,
|
|
@@ -7031,7 +7282,8 @@ function composeSlide(input, options = {}) {
|
|
|
7031
7282
|
minFontSize: settings.minFontSize,
|
|
7032
7283
|
path: node.path,
|
|
7033
7284
|
direction: textDirection,
|
|
7034
|
-
...citationMarker ? { citationMarker } : {}
|
|
7285
|
+
...citationMarker ? { citationMarker } : {},
|
|
7286
|
+
...deckLanguage() !== void 0 ? { language: deckLanguage() } : {}
|
|
7035
7287
|
});
|
|
7036
7288
|
const measureCode = (node, box, settings) => layoutCode(node.value, acceptedBox(box), {
|
|
7037
7289
|
fontFamilies: options.fontFamilies,
|
|
@@ -7060,14 +7312,21 @@ function composeSlide(input, options = {}) {
|
|
|
7060
7312
|
direction: textDirection
|
|
7061
7313
|
});
|
|
7062
7314
|
const captionOf = (node, box) => node.caption !== void 0 && node.captionPath ? layoutCaption(node.caption, box, node.captionPath, annotationOptions) : void 0;
|
|
7315
|
+
const wholePictureAspect = (node) => {
|
|
7316
|
+
const host = node.host;
|
|
7317
|
+
if (node.field !== "image" || !host || !autoComposition() || host.aspectRatio !== void 0 || host.shape === "circle") return void 0;
|
|
7318
|
+
const fit = IMAGE_FITS.includes(host.fit) ? host.fit : hints.imageFit ?? "contain";
|
|
7319
|
+
return fit === "contain" ? intrinsicImageAspect(host.image, assets) : void 0;
|
|
7320
|
+
};
|
|
7063
7321
|
const leafScore = (node, box, settings, penalties) => {
|
|
7064
7322
|
box = payloadBox(box);
|
|
7065
7323
|
const captioned = captionOf(node, box);
|
|
7066
7324
|
if (captioned) box = captioned.mediaBox;
|
|
7067
7325
|
const text2 = contentText(node.field, node.value);
|
|
7068
|
-
|
|
7326
|
+
const proportions = Math.abs(Math.log(box.width / box.height / (wholePictureAspect(node) ?? 1.6)));
|
|
7327
|
+
let score = proportions + (captioned?.overflow ? 1e3 : 0);
|
|
7069
7328
|
if (penalties) {
|
|
7070
|
-
penalties.cellProportions +=
|
|
7329
|
+
penalties.cellProportions += proportions;
|
|
7071
7330
|
if (captioned?.overflow) penalties.textOverflow += 1e3;
|
|
7072
7331
|
}
|
|
7073
7332
|
if (node.field === "quote" || node.field === "code" || node.field === "metric" || node.field === "timeline") {
|
|
@@ -7079,8 +7338,9 @@ function composeSlide(input, options = {}) {
|
|
|
7079
7338
|
penalties.textOverflow += internal.overflow ? 1e3 : 0;
|
|
7080
7339
|
}
|
|
7081
7340
|
} else if (text2) {
|
|
7082
|
-
const
|
|
7083
|
-
const
|
|
7341
|
+
const prose = proseMeasure(node, box.width);
|
|
7342
|
+
const fit = fitContent(node.field, node.value, text2, { ...box, width: prose.width }, prose.size, snapFontSizeUp((settings.minFontSize ?? 16) * scale2), node.path, node.payload.numbering);
|
|
7343
|
+
const reduction = Math.max(0, snapFontSizeDown(prose.size) - fit.fontSize) / scale2;
|
|
7084
7344
|
score += reduction + (fit.overflow ? 1e3 : 0);
|
|
7085
7345
|
if (penalties) {
|
|
7086
7346
|
penalties.fontReduction += reduction;
|
|
@@ -7109,6 +7369,74 @@ function composeSlide(input, options = {}) {
|
|
|
7109
7369
|
const boxes = gridBoxes(slotCount, area3, cols, (own3.gap ?? 1 / 30) * Math.min(box.width, box.height), own3.weights ?? [], modeFor(own3) === "column");
|
|
7110
7370
|
return node.children.reduce((score, child, index) => score + scoreNode(child, boxes[index], own3, penalties), 0);
|
|
7111
7371
|
};
|
|
7372
|
+
const contentSized = /* @__PURE__ */ new WeakSet();
|
|
7373
|
+
const stackedBoxes = (nodes, area3, requestedGap, settings, cards = hasCards, anchor = "top") => {
|
|
7374
|
+
const between = Math.max(0, Math.min(requestedGap, area3.width / 2, area3.height / (nodes.length * 2)));
|
|
7375
|
+
const space = Math.max(0, area3.height - between * (nodes.length - 1)), share = space / nodes.length;
|
|
7376
|
+
const elastic = nodes.map((node) => !measuredNode(node)), stretch = elastic.filter(Boolean).length;
|
|
7377
|
+
const needs = nodes.map((node, index) => elastic[index] ? share : naturalHeight(node, area3.width, cards, void 0, settings));
|
|
7378
|
+
const floors = nodes.map((node, index) => elastic[index] ? share : naturalHeight(node, area3.width, cards, void 0, settings, true));
|
|
7379
|
+
let heights = shareHeights(needs, floors, space);
|
|
7380
|
+
const textual = nodes.every((node) => !node.children && node.caption === void 0 && (node.field === "text" || node.field === "items" || node.field === "bullets"));
|
|
7381
|
+
if (textual && nodes.length > 1 && needs.reduce((sum, size) => sum + size, 0) > space + 1e-6) {
|
|
7382
|
+
const floor = snapFontSizeUp((settings.minFontSize ?? 16) * scale2), start = Math.max(...nodes.map((node) => proseMeasure(node, area3.width).size));
|
|
7383
|
+
for (let size = start; ; size -= scale2) {
|
|
7384
|
+
const trial = Math.max(floor, snapFontSizeDown(size));
|
|
7385
|
+
const natural = nodes.map((node) => naturalHeight(node, area3.width, cards, void 0, settings, false, Math.min(trial, proseMeasure(node, area3.width).size)));
|
|
7386
|
+
if (natural.reduce((sum, height2) => sum + height2, 0) <= space + 1e-6) {
|
|
7387
|
+
heights = natural;
|
|
7388
|
+
break;
|
|
7389
|
+
}
|
|
7390
|
+
if (trial <= floor) break;
|
|
7391
|
+
}
|
|
7392
|
+
}
|
|
7393
|
+
if (stretch && heights.some((size, index) => elastic[index] && size < share - 1e-9)) {
|
|
7394
|
+
const measured = nodes.flatMap((_, index) => elastic[index] ? [] : [index]);
|
|
7395
|
+
const rest = shareHeights(measured.map((index) => needs[index]), measured.map((index) => floors[index]), space - stretch * share);
|
|
7396
|
+
heights = nodes.map((_, index) => elastic[index] ? share : rest[measured.indexOf(index)]);
|
|
7397
|
+
}
|
|
7398
|
+
const spare = space - heights.reduce((sum, size) => sum + size, 0);
|
|
7399
|
+
if (stretch && spare > 0) heights = heights.map((size, index) => elastic[index] ? size + spare / stretch : size);
|
|
7400
|
+
const used = heights.reduce((sum, size) => sum + size, 0) + between * (nodes.length - 1);
|
|
7401
|
+
nodes.forEach((node, index) => {
|
|
7402
|
+
if (!node.children && !elastic[index] && heights[index] >= needs[index] - 1e-6) contentSized.add(node);
|
|
7403
|
+
});
|
|
7404
|
+
let y2 = area3.y + Math.max(0, anchor === "middle" ? (area3.height - used) / 2 : anchor === "bottom" ? area3.height - used : 0);
|
|
7405
|
+
return heights.map((size) => {
|
|
7406
|
+
const box = { x: area3.x, y: y2, width: area3.width, height: size };
|
|
7407
|
+
y2 += size + between;
|
|
7408
|
+
return box;
|
|
7409
|
+
});
|
|
7410
|
+
};
|
|
7411
|
+
const WEIGHTED_DEMAND_RATIO = 2.5, WEIGHTED_SHARES = [0.55, 0.6, 0.65, 0.7];
|
|
7412
|
+
const autoRowWeights = (nodes, count, cols, area3, rowGap, settings) => {
|
|
7413
|
+
if (!autoComposition() || settings.weights?.length || count < 2 || count > 3 || cols !== count || nodes.length !== count) return void 0;
|
|
7414
|
+
const equal = gridGeometry(count, area3, cols, rowGap, [], false).boxes;
|
|
7415
|
+
const wholeWidths = nodes.map((node, index) => {
|
|
7416
|
+
const aspect = node.caption === void 0 ? wholePictureAspect(node) : void 0;
|
|
7417
|
+
return aspect === void 0 ? void 0 : Math.min(equal[index].width, equal[index].height * aspect);
|
|
7418
|
+
});
|
|
7419
|
+
const media = wholeWidths.flatMap((width2, index) => width2 !== void 0 && width2 < equal[index].width - scale2 ? [index] : []);
|
|
7420
|
+
const others = nodes.flatMap((_, index) => wholeWidths[index] === void 0 ? [index] : []);
|
|
7421
|
+
if (media.length && others.length) {
|
|
7422
|
+
const freed = media.reduce((sum, index) => sum + equal[index].width - wholeWidths[index], 0);
|
|
7423
|
+
return nodes.map((_, index) => media.includes(index) ? wholeWidths[index] : equal[index].width + freed / others.length);
|
|
7424
|
+
}
|
|
7425
|
+
const prose = (node) => !node.children && node.caption === void 0 && (node.field === "text" || node.field === "items" || node.field === "bullets");
|
|
7426
|
+
if (count !== 2 || !nodes.every(prose)) return void 0;
|
|
7427
|
+
const need = (node, width2) => naturalHeight(node, width2, hasCards, void 0, settings);
|
|
7428
|
+
const heights = nodes.map((node, index) => need(node, equal[index].width));
|
|
7429
|
+
const long = heights[0] >= heights[1] ? 0 : 1, short = 1 - long;
|
|
7430
|
+
if (heights[long] < WEIGHTED_DEMAND_RATIO * heights[short]) return void 0;
|
|
7431
|
+
const total = equal[0].width + equal[1].width, line2 = contentNominalSize(nodes[short].field) * scale2 * 1.3;
|
|
7432
|
+
let best;
|
|
7433
|
+
for (const share of WEIGHTED_SHARES) {
|
|
7434
|
+
const longHeight = need(nodes[long], total * share), shortHeight = need(nodes[short], total * (1 - share));
|
|
7435
|
+
if (shortHeight > heights[short] + line2 || longHeight > heights[long] - line2 * 0.5) continue;
|
|
7436
|
+
if (!best || longHeight < best.height - 1e-6) best = { share, height: longHeight };
|
|
7437
|
+
}
|
|
7438
|
+
return best ? long === 0 ? [best.share, 1 - best.share] : [1 - best.share, best.share] : void 0;
|
|
7439
|
+
};
|
|
7112
7440
|
const arrange = (nodes, area3, settings, reserved2 = 0, gapOverride, containerPath = path, recorded = true) => {
|
|
7113
7441
|
const count = Math.max(nodes.length, reserved2);
|
|
7114
7442
|
if (!count) return;
|
|
@@ -7116,7 +7444,12 @@ function composeSlide(input, options = {}) {
|
|
|
7116
7444
|
const actualGap = gapOverride ?? (settings === rootSettings ? gap : localGap);
|
|
7117
7445
|
let cols = defaultColumns(count, area3, settings);
|
|
7118
7446
|
const hasRegions = nodes.some((node) => node.region);
|
|
7447
|
+
if (!hasRegions && (mode === "auto" || nodes.length === 1)) for (const node of nodes) {
|
|
7448
|
+
node.auto = true;
|
|
7449
|
+
node.lone = nodes.length === 1 && reserved2 === 0;
|
|
7450
|
+
}
|
|
7119
7451
|
const candidates = decisions && recorded ? [] : void 0;
|
|
7452
|
+
const stacks = !hasRegions && count === nodes.length && count > 1 && !(mode === "column" && settings.weights?.length);
|
|
7120
7453
|
if (mode === "auto" && !hasRegions) {
|
|
7121
7454
|
let best = Infinity;
|
|
7122
7455
|
for (let candidate = 1; candidate <= Math.min(count, settings.columns ?? 6); candidate++) {
|
|
@@ -7138,14 +7471,24 @@ function composeSlide(input, options = {}) {
|
|
|
7138
7471
|
...hasRegions ? {} : { selectedColumns: cols },
|
|
7139
7472
|
candidates: candidates ?? []
|
|
7140
7473
|
});
|
|
7141
|
-
const grid = gridGeometry(count, area3, cols, actualGap, settings.weights ?? [], mode === "column");
|
|
7474
|
+
const grid = gridGeometry(count, area3, cols, actualGap, (mode === "auto" && !hasRegions ? autoRowWeights(nodes, count, cols, area3, actualGap, settings) : void 0) ?? settings.weights ?? [], mode === "column");
|
|
7475
|
+
if (cols === 1 && stacks) {
|
|
7476
|
+
grid.boxes = stackedBoxes(nodes, area3, actualGap, settings);
|
|
7477
|
+
grid.rows = grid.boxes.map((box) => ({ offset: box.y - area3.y, size: box.height }));
|
|
7478
|
+
}
|
|
7142
7479
|
const mirrored = (box) => rtl ? { ...box, x: area3.x + area3.width - (box.x - area3.x) - box.width } : box;
|
|
7143
7480
|
const boxes = grid.boxes.map(mirrored);
|
|
7144
7481
|
if (recorded && !hasRegions) flows.push({ path: containerPath, box: { ...area3 }, composition: { ...settings }, columns: rtl ? grid.columns.map((track) => ({ offset: area3.width - track.offset - track.size, size: track.size })) : grid.columns, rows: grid.rows, gap: grid.gap, itemCount: nodes.length, slotCount: count });
|
|
7482
|
+
const rowItems = /* @__PURE__ */ new Map(), stack = [];
|
|
7145
7483
|
nodes.forEach((node, index) => {
|
|
7146
7484
|
const box = node.region ? mirrored(regionBox(node.region, area3, actualGap)) : boxes[index];
|
|
7485
|
+
const first = items.length;
|
|
7147
7486
|
placeNode(node, box, settings);
|
|
7487
|
+
if (!hasRegions && cols > 1 && !node.children) rowItems.set(Math.floor(index / cols), [...rowItems.get(Math.floor(index / cols)) ?? [], ...range(first, items.length)]);
|
|
7488
|
+
else if (!hasRegions && cols === 1 && stacks && !node.children) stack.push(...range(first, items.length));
|
|
7148
7489
|
});
|
|
7490
|
+
for (const set2 of rowItems.values()) peerSets.push(set2);
|
|
7491
|
+
if (stack.length > 1) peerSets.push(stack);
|
|
7149
7492
|
};
|
|
7150
7493
|
let regionTag, templateCell = false;
|
|
7151
7494
|
const composeChart = (node, box, settings) => {
|
|
@@ -7153,7 +7496,15 @@ function composeSlide(input, options = {}) {
|
|
|
7153
7496
|
const valueAxis = chartValueAxis(node.value, resolved, { width: box.width, height: box.height, scale: scale2, minFontSize: settings.minFontSize });
|
|
7154
7497
|
return valueAxis ? { valueAxis } : void 0;
|
|
7155
7498
|
};
|
|
7156
|
-
const
|
|
7499
|
+
const VIDEO_ASPECT = 16 / 9, CHART_MAX_ASPECT_RATIO = 3 / 4;
|
|
7500
|
+
const settleCaption = (caption, frame, anchor) => {
|
|
7501
|
+
if (caption.position === "above" || anchor !== "top") return;
|
|
7502
|
+
const target = round2(frame.y + frame.height + caption.fontSize * 0.4), dy = target - caption.box.y;
|
|
7503
|
+
if (dy >= -0.01) return;
|
|
7504
|
+
caption.box = { ...caption.box, y: target };
|
|
7505
|
+
caption.fit = translateTextFit(caption.fit, dy);
|
|
7506
|
+
};
|
|
7507
|
+
const placeNode = (node, box, settings, cards = hasCards, listColumns, metricReferenceHeight, anchor = "top") => {
|
|
7157
7508
|
if (node.children) {
|
|
7158
7509
|
const own3 = inheritedSettings(settings, node.composition), inner = inset(box, own3);
|
|
7159
7510
|
if (!node.synthetic) groups.push({ path: node.path, box, contentBox: inner, composition: own3 });
|
|
@@ -7175,8 +7526,24 @@ function composeSlide(input, options = {}) {
|
|
|
7175
7526
|
const timelineLayout = node.field === "timeline" ? measureTimeline(node, box, settings) : void 0;
|
|
7176
7527
|
const internal = quoteLayout ?? codeLayout ?? metricLayout ?? timelineLayout, body = internal?.parts.find((part) => part.role === "body" || part.role === "value");
|
|
7177
7528
|
const columns2 = textValue !== void 0 && !internal ? listColumnsFor(node, box, settings, listColumns) : void 0;
|
|
7178
|
-
const
|
|
7179
|
-
const
|
|
7529
|
+
const floorSize = snapFontSizeUp((settings.minFontSize ?? 16) * scale2);
|
|
7530
|
+
const prose = textValue !== void 0 && !internal ? proseMeasure(node, box.width) : void 0, wholeBox = box;
|
|
7531
|
+
if (prose && prose.width < box.width - 0.5) {
|
|
7532
|
+
const side = alignmentFor(node.field), atEnd = rtl ? side === "left" : side === "right";
|
|
7533
|
+
box = { ...box, x: side === "center" ? box.x + (box.width - prose.width) / 2 : atEnd ? box.x + box.width - prose.width : box.x, width: prose.width };
|
|
7534
|
+
}
|
|
7535
|
+
let text2 = internal ? body?.fit : columns2 ? columns2.length > 1 ? mergeListColumns(columns2) : columns2[0].text : textValue !== void 0 ? fitContent(node.field, node.value, textValue, box, prose?.size ?? contentNominalSize(node.field) * scale2, floorSize, node.path, node.payload.numbering) : void 0;
|
|
7536
|
+
if (prose && box !== wholeBox && text2 && textValue !== void 0) {
|
|
7537
|
+
const wide = fitContent(node.field, node.value, textValue, wholeBox, prose.size, floorSize, node.path, node.payload.numbering);
|
|
7538
|
+
if (wide.fontSize > text2.fontSize + 1e-9 || text2.overflow && !wide.overflow) {
|
|
7539
|
+
text2 = wide;
|
|
7540
|
+
box = wholeBox;
|
|
7541
|
+
}
|
|
7542
|
+
}
|
|
7543
|
+
if (node.field === "video") box = roundBox(containedBox(box, VIDEO_ASPECT, anchor));
|
|
7544
|
+
else if (node.field === "chart" && !templateCell && modeFor(settings) === "auto" && box.height > box.width * CHART_MAX_ASPECT_RATIO) box = roundBox({ ...box, height: box.width * CHART_MAX_ASPECT_RATIO });
|
|
7545
|
+
const image = node.field === "image" ? composeImage(node.host ?? {}, node.hostPath ?? node.path, box, box, imageContext(void 0, anchor)) : void 0;
|
|
7546
|
+
if (caption) settleCaption(caption, image?.box ?? box, anchor);
|
|
7180
7547
|
const chart = node.field === "chart" ? composeChart(node, box, settings) : void 0;
|
|
7181
7548
|
items.push({
|
|
7182
7549
|
path: node.path,
|
|
@@ -7184,7 +7551,7 @@ function composeSlide(input, options = {}) {
|
|
|
7184
7551
|
type: node.type,
|
|
7185
7552
|
value: node.value,
|
|
7186
7553
|
payload: node.payload,
|
|
7187
|
-
box: internal ? acceptedBox(box) : box,
|
|
7554
|
+
box: codeLayout && !codeLayout.overflow ? { ...acceptedBox(box), height: Math.min(acceptedBox(box).height, round2(codeLayout.bounds.height)) } : internal ? acceptedBox(box) : box,
|
|
7188
7555
|
...image ? { image } : {},
|
|
7189
7556
|
...chart ? { chart } : {},
|
|
7190
7557
|
...frameBox ? { frameBox } : {},
|
|
@@ -7201,7 +7568,7 @@ function composeSlide(input, options = {}) {
|
|
|
7201
7568
|
...regionTag !== void 0 ? { region: regionTag } : {},
|
|
7202
7569
|
...columns2 && columns2.length > 1 ? { listColumns: columns2 } : {}
|
|
7203
7570
|
});
|
|
7204
|
-
if (box.width < 100 * scale2 || !templateCell && box.height < 60 * scale2) diagnostics.push({ code: "small-cell", path: node.path, message: "Content cell is too small for comfortable reading; use fewer blocks or a different composition." });
|
|
7571
|
+
if (box.width < 100 * scale2 || !templateCell && !contentSized.has(node) && box.height < 60 * scale2) diagnostics.push({ code: "small-cell", path: node.path, message: "Content cell is too small for comfortable reading; use fewer blocks or a different composition." });
|
|
7205
7572
|
};
|
|
7206
7573
|
const listColumnsFor = (node, box, settings, regionMode) => {
|
|
7207
7574
|
if (node.field !== "items" && node.field !== "bullets") return void 0;
|
|
@@ -7212,7 +7579,7 @@ function composeSlide(input, options = {}) {
|
|
|
7212
7579
|
if (mode === void 0 || mode === 1) return void 0;
|
|
7213
7580
|
const start = contentNominalSize(node.field) * scale2, floor = snapFontSizeUp((settings.minFontSize ?? 16) * scale2);
|
|
7214
7581
|
const numbering = node.payload.numbering;
|
|
7215
|
-
const listOptions = { ...richOptions(styleFor(node.field, node.path)), ...numbering !== void 0 ? { numbering } : bulletImage ? { bulletImage } : {} };
|
|
7582
|
+
const listOptions = { ...richOptions(styleFor(node.field, node.path)), ...numbering !== void 0 ? { numbering } : bulletImage ? { bulletImage } : noListBullet ? { bullet: "none" } : {} };
|
|
7216
7583
|
const columnGap = (count2) => Math.min(gap, box.width / (count2 * 2));
|
|
7217
7584
|
const columnBoxes = (count2) => {
|
|
7218
7585
|
const between = columnGap(count2), columnWidth = (box.width - between * (count2 - 1)) / count2;
|
|
@@ -7248,7 +7615,7 @@ function composeSlide(input, options = {}) {
|
|
|
7248
7615
|
const size = Math.min(...shrunk.map((column) => column.text.fontSize));
|
|
7249
7616
|
return shrunk.map((column) => ({ ...column, text: renumber(fitList(chunk(column.start, column.end), column.box, size, size, listOptions), column.start) }));
|
|
7250
7617
|
};
|
|
7251
|
-
const LONG_LINES = 6, LONG_CODE_LINES = 12, startSize =
|
|
7618
|
+
const LONG_LINES = 6, LONG_CODE_LINES = 12, startSize = PROSE_NOMINAL_SIZE * scale2;
|
|
7252
7619
|
const estimatedLines = (value, cellWidth, size) => flatten(value).split("\n").reduce((sum, paragraph) => sum + Math.max(1, wrapText(paragraph, Math.max(1, cellWidth), size).length), 0);
|
|
7253
7620
|
const isLong = (node, cellWidth) => {
|
|
7254
7621
|
if (node.children) return node.children.some((child) => isLong(child, cellWidth));
|
|
@@ -7272,22 +7639,37 @@ function composeSlide(input, options = {}) {
|
|
|
7272
7639
|
if (node.field === "code") return String(typeof node.value === "string" ? node.value : record7(node.value).source ?? "").split("\n").length > LONG_CODE_LINES;
|
|
7273
7640
|
return false;
|
|
7274
7641
|
};
|
|
7275
|
-
const
|
|
7642
|
+
const proseMeasure = (node, cellWidth) => {
|
|
7643
|
+
const role = contentNominalSize(node.field) * scale2;
|
|
7644
|
+
if (node.field !== "text" || node.children || !node.auto) return { size: role, width: cellWidth };
|
|
7645
|
+
const linesAt = (width2, size) => estimatedLines(node.value, width2, size);
|
|
7646
|
+
const measureAt = (size) => Math.min(cellWidth, PROSE_MEASURE_CHARS * AVERAGE_CHARACTER_EM * size);
|
|
7647
|
+
const lead = LEAD_NOMINAL_SIZE * scale2;
|
|
7648
|
+
if (node.lone && lead > role && linesAt(measureAt(lead), lead) <= 2) return { size: lead, width: linesAt(cellWidth, lead) <= 1 ? cellWidth : measureAt(lead) };
|
|
7649
|
+
return { size: role, width: linesAt(cellWidth, role) <= 1 ? cellWidth : measureAt(role) };
|
|
7650
|
+
};
|
|
7651
|
+
const MEASURED_FIELDS = /* @__PURE__ */ new Set(["text", "items", "bullets", "quote", "metric", "code"]);
|
|
7652
|
+
const measuredNode = (node) => node.children ? node.children.length > 0 && node.children.every(measuredNode) : MEASURED_FIELDS.has(node.field);
|
|
7653
|
+
const naturalHeight = (node, cellWidth, cards, metricReferenceHeight, naturalSettings = composition, atFloor = false, sizeOverride) => {
|
|
7276
7654
|
const pad = cards ? 2 * Math.min(12 * scale2, cellWidth / 4) : 0, inner = Math.max(scale2, cellWidth - pad);
|
|
7277
|
-
if (node.children) return node.children.reduce((sum, child) => sum + naturalHeight(child, cellWidth, false), 0) + gap * Math.max(0, node.children.length - 1) + pad;
|
|
7655
|
+
if (node.children) return node.children.reduce((sum, child) => sum + naturalHeight(child, cellWidth, false, void 0, naturalSettings, atFloor), 0) + gap * Math.max(0, node.children.length - 1) + pad;
|
|
7656
|
+
const floorSize = snapFontSizeUp((naturalSettings.minFontSize ?? 16) * scale2);
|
|
7278
7657
|
let content;
|
|
7279
7658
|
if (node.field === "text" || node.field === "items" || node.field === "bullets") {
|
|
7280
|
-
const
|
|
7281
|
-
const fit = fitContent(node.field, node.value, contentText(node.field, node.value) ?? "", { x: 0, y: 0, width: inner, height: 1e6 }, size, size, node.path, node.payload.numbering);
|
|
7282
|
-
content = "height" in fit && typeof fit.height === "number" ? fit.height : fit.lines.length * fit.lineHeight;
|
|
7659
|
+
const prose = proseMeasure(node, inner), size = sizeOverride ?? (atFloor ? floorSize : prose.size);
|
|
7660
|
+
const fit = fitContent(node.field, node.value, contentText(node.field, node.value) ?? "", { x: 0, y: 0, width: atFloor || sizeOverride !== void 0 ? inner : prose.width, height: 1e6 }, size, size, node.path, node.payload.numbering);
|
|
7661
|
+
content = Math.max("height" in fit && typeof fit.height === "number" ? fit.height : fit.lines.length * fit.lineHeight, fit.placement?.height ?? 0);
|
|
7283
7662
|
} else if (node.field === "quote") content = measureQuote(node, { x: 0, y: 0, width: inner, height: 1e6 }, naturalSettings).bounds.height + 18;
|
|
7284
|
-
else if (node.field === "code")
|
|
7285
|
-
|
|
7663
|
+
else if (node.field === "code") {
|
|
7664
|
+
const code = measureCode(node, { x: 0, y: 0, width: inner, height: 1e6 }, naturalSettings), source = code.parts.find((part) => part.role === "body");
|
|
7665
|
+
content = source?.fit ? source.box.y + source.fit.lines.length * source.fit.lineHeight + 18 : 1e6;
|
|
7666
|
+
} else if (node.field === "metric") content = measureMetric(node, { x: 0, y: 0, width: inner, height: metricReferenceHeight === void 0 ? 1e6 : Math.max(scale2, metricReferenceHeight - pad) }, naturalSettings).bounds.height;
|
|
7286
7667
|
else if (node.field === "timeline") content = 170 * scale2;
|
|
7287
7668
|
else if (node.field === "table") {
|
|
7288
7669
|
const value = record7(node.value);
|
|
7289
7670
|
content = ((Array.isArray(value.rows) ? value.rows.length : 4) + 1) * 36 * scale2;
|
|
7290
7671
|
} else content = inner / 1.6;
|
|
7672
|
+
if (atFloor && !(node.field === "text" || node.field === "items" || node.field === "bullets")) content *= Math.min(1, floorSize / startSize);
|
|
7291
7673
|
return content + (node.caption !== void 0 ? 32 * scale2 : 0) + pad;
|
|
7292
7674
|
};
|
|
7293
7675
|
const templateRegions = [], headingAreas = [];
|
|
@@ -7302,6 +7684,13 @@ function composeSlide(input, options = {}) {
|
|
|
7302
7684
|
return parts.length === 1 ? parts[0] : { field: "blocks", type: "group", value: parts.map((part) => part.payload), path: bound.path, payload: {}, children: parts, composition: { mode: "column" }, synthetic: true };
|
|
7303
7685
|
};
|
|
7304
7686
|
const contents = new Map(binding.regions.map((entry) => [entry.name, [...entry.blocks, ...entry.overflow].map(unitOf)]));
|
|
7687
|
+
for (const region of plan2.regions) {
|
|
7688
|
+
const units = contents.get(region.name) ?? [];
|
|
7689
|
+
if (region.flow === "auto") for (const unit of units) {
|
|
7690
|
+
unit.auto = true;
|
|
7691
|
+
unit.lone = units.length === 1;
|
|
7692
|
+
}
|
|
7693
|
+
}
|
|
7305
7694
|
const BELOW = "(below)";
|
|
7306
7695
|
const belowUnits = binding.below.map(unitOf);
|
|
7307
7696
|
const belowRegion = { name: BELOW, accepts: [], role: "supporting", flow: "auto", max: belowUnits.length, bleed: false, listColumns: 1, anchor: "top", empty: "collapse" };
|
|
@@ -7340,7 +7729,7 @@ function composeSlide(input, options = {}) {
|
|
|
7340
7729
|
const list = [];
|
|
7341
7730
|
let top = y2;
|
|
7342
7731
|
for (const field of fields2) {
|
|
7343
|
-
const requested = (field === "title" ? 54 : field === "tag" ? 16 :
|
|
7732
|
+
const requested = (field === "title" ? 54 : field === "tag" ? 16 : PROSE_NOMINAL_SIZE) * scale2;
|
|
7344
7733
|
const maxHeight = Math.max(height * (field === "title" ? 0.26 : field === "subtitle" ? 0.12 : 0.045), minSize * 1.22 + 2 * rasterPadding);
|
|
7345
7734
|
const box = { x, y: top, width: areaWidth, height: maxHeight };
|
|
7346
7735
|
const text2 = fitPlacedText(field, slide[field], annotationText(slide[field]), box, requested, minSize, `${path}.${field}`);
|
|
@@ -7361,33 +7750,35 @@ function composeSlide(input, options = {}) {
|
|
|
7361
7750
|
const cellWidth = (cell.width - gap2 * (shape.columns - 1)) / shape.columns - (cards ? 2 * Math.min(12 * scale2, cell.width / 4) : 0);
|
|
7362
7751
|
return units.some((unit) => isLong(unit, cellWidth)) ? "column" : "grid";
|
|
7363
7752
|
};
|
|
7364
|
-
const regionNeed = (name, areaWidth) => {
|
|
7753
|
+
const regionNeed = (name, areaWidth, atFloor = false) => {
|
|
7365
7754
|
const units = unitsOf(name), region = name === BELOW ? belowRegion : regionOf.get(name);
|
|
7366
|
-
if (!units.length) return region.empty === "keep" ? 2 * startSize * 1.22 + (hasCards && !region.bleed ? 2 * Math.min(12 * scale2, areaWidth / 4) : 0) : 0;
|
|
7755
|
+
if (!units.length) return region.empty === "keep" && !atFloor ? 2 * (region.flow === "auto" ? LEAD_NOMINAL_SIZE * scale2 : startSize) * 1.22 + (hasCards && !region.bleed ? 2 * Math.min(12 * scale2, areaWidth / 4) : 0) : 0;
|
|
7367
7756
|
const shape = flowShape(arrangementOf(region, units, { width: areaWidth, height: areaWidth / 4 }), units.length, true);
|
|
7368
7757
|
const cellWidth = (areaWidth - gap2 * (shape.columns - 1)) / shape.columns, cards = hasCards && !region.bleed;
|
|
7369
7758
|
let total = 0, index = 0;
|
|
7370
7759
|
for (const count of shape.perRow) {
|
|
7371
7760
|
let row = 0;
|
|
7372
|
-
for (let k = 0; k < count; k++) row = Math.max(row, naturalHeight(units[index++], cellWidth, cards));
|
|
7761
|
+
for (let k = 0; k < count; k++) row = Math.max(row, naturalHeight(units[index++], cellWidth, cards, void 0, composition, atFloor));
|
|
7373
7762
|
total += row;
|
|
7374
7763
|
}
|
|
7375
7764
|
return total + gap2 * Math.max(0, shape.rows - 1);
|
|
7376
7765
|
};
|
|
7377
7766
|
const areaNeed = (name, rect) => name === "title" ? groupHeight(headingItemsAt(titleFields, 0, 0, spanWidth(rect))) : name === "subtitle" ? groupHeight(headingItemsAt(subtitleFields, 0, 0, spanWidth(rect))) : regionNeed(name, spanWidth(rect));
|
|
7378
7767
|
const demands = rowSizes.map((size, row) => {
|
|
7379
|
-
let need = 0, heading = false, below = false;
|
|
7768
|
+
let need = 0, floor = 0, heading = false, below = false;
|
|
7380
7769
|
for (const [name, rect] of rects) {
|
|
7381
|
-
|
|
7770
|
+
const autoSpan = size === "auto" && rect.rowSpan > 1 && rect.row === row && rowSizes.slice(rect.row, rect.row + rect.rowSpan).every((entry) => entry === "auto");
|
|
7771
|
+
if (size === "auto" ? rect.row !== row || rect.rowSpan !== 1 && !autoSpan : row < rect.row || row >= rect.row + rect.rowSpan) continue;
|
|
7382
7772
|
if (size !== "auto" && rect.rowSpan > 1 && rowSizes.slice(rect.row, rect.row + rect.rowSpan).some((entry) => entry === "auto")) continue;
|
|
7383
|
-
const value = areaNeed(name, rect) / rect.rowSpan;
|
|
7773
|
+
const value = areaNeed(name, rect) / (autoSpan ? 1 : rect.rowSpan);
|
|
7774
|
+
if (size === "auto" && name !== "title" && name !== "subtitle") floor = Math.max(floor, regionNeed(name, spanWidth(rect), true));
|
|
7384
7775
|
if (value > need) {
|
|
7385
7776
|
need = value;
|
|
7386
7777
|
heading = name === "title" || name === "subtitle";
|
|
7387
7778
|
below = name === BELOW;
|
|
7388
7779
|
}
|
|
7389
7780
|
}
|
|
7390
|
-
return { size, need, kind: heading ? "heading" : below ? "below" : "body" };
|
|
7781
|
+
return { size, need, ...size === "auto" && !heading ? { floor } : {}, kind: heading ? "heading" : below ? "below" : "body" };
|
|
7391
7782
|
});
|
|
7392
7783
|
const heights = allocateRows(demands, frame.height, gap2);
|
|
7393
7784
|
const rowY = [];
|
|
@@ -7395,9 +7786,11 @@ function composeSlide(input, options = {}) {
|
|
|
7395
7786
|
rowY.push(size > 0 || !heights.slice(0, row).some((above) => above > 0) ? y2 : y2 - gap2);
|
|
7396
7787
|
return size > 0 ? y2 + size + gap2 : y2;
|
|
7397
7788
|
}, 0);
|
|
7789
|
+
const stackUsed = heights.reduce((sum, size) => sum + size, 0) + gap2 * Math.max(0, heights.filter((size) => size > 0).length - 1);
|
|
7790
|
+
const stackShift = plan2.stack === void 0 ? 0 : Math.max(0, frame.height - stackUsed) * (plan2.stack === "middle" ? 0.5 : 1);
|
|
7398
7791
|
const logical = (rect) => {
|
|
7399
|
-
const last = rect.row + rect.rowSpan - 1, y2 = frame.y + rowY[rect.row];
|
|
7400
|
-
return { x: frame.x + columnX[rect.column], y: y2, width: spanWidth(rect), height: Math.max(0, frame.y + rowY[last] + heights[last] - y2) };
|
|
7792
|
+
const last = rect.row + rect.rowSpan - 1, y2 = frame.y + stackShift + rowY[rect.row];
|
|
7793
|
+
return { x: frame.x + columnX[rect.column], y: y2, width: spanWidth(rect), height: Math.max(0, frame.y + stackShift + rowY[last] + heights[last] - y2) };
|
|
7401
7794
|
};
|
|
7402
7795
|
const flip = hints.mirror === true !== rtl;
|
|
7403
7796
|
const physical = (cell) => flip ? { ...cell, x: frame.x + frame.width - (cell.x - frame.x) - cell.width } : cell;
|
|
@@ -7454,18 +7847,8 @@ function composeSlide(input, options = {}) {
|
|
|
7454
7847
|
const arrangement = arrangementOf(region, units, cell);
|
|
7455
7848
|
let boxes = flowCells(flowShape(arrangement, units.length, cell.width >= cell.height), cell, gap2).cells;
|
|
7456
7849
|
const referenceHeights = boxes.map((box) => box.height);
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
const used = naturals.reduce((a, b) => a + b, 0) + gap2 * (units.length - 1);
|
|
7460
|
-
if (used < cell.height) {
|
|
7461
|
-
let y2 = cell.y + (region.anchor === "middle" ? (cell.height - used) / 2 : cell.height - used);
|
|
7462
|
-
boxes = naturals.map((size) => {
|
|
7463
|
-
const next = { x: cell.x, y: y2, width: cell.width, height: size };
|
|
7464
|
-
y2 += size + gap2;
|
|
7465
|
-
return next;
|
|
7466
|
-
});
|
|
7467
|
-
}
|
|
7468
|
-
}
|
|
7850
|
+
const stacked = arrangement === "column" && !(units.length === 1 && region.anchor === "top");
|
|
7851
|
+
if (stacked) boxes = stackedBoxes(units, cell, gap2, settings, cards, region.anchor);
|
|
7469
7852
|
if ((arrangement === "grid" || arrangement === "row") && region.anchor !== "top") {
|
|
7470
7853
|
const naturals = boxes.map((box, index) => {
|
|
7471
7854
|
const unit = units[index];
|
|
@@ -7480,22 +7863,44 @@ function composeSlide(input, options = {}) {
|
|
|
7480
7863
|
});
|
|
7481
7864
|
}
|
|
7482
7865
|
if (rtl) boxes = boxes.map((box) => ({ ...box, x: cell.x + cell.width - (box.x - cell.x) - box.width }));
|
|
7866
|
+
const shape = flowShape(arrangement, units.length, cell.width >= cell.height), rowItems = shape.perRow.map(() => []);
|
|
7867
|
+
const rowOf = (index) => {
|
|
7868
|
+
let row = 0;
|
|
7869
|
+
for (let seen = shape.perRow[0] ?? 0; index >= seen; seen += shape.perRow[++row] ?? Infinity) ;
|
|
7870
|
+
return row;
|
|
7871
|
+
};
|
|
7872
|
+
const stack = [];
|
|
7483
7873
|
units.forEach((unit, index) => {
|
|
7484
|
-
|
|
7874
|
+
const first = items.length;
|
|
7875
|
+
placeNode(unit, boxes[index], settings, cards, region.listColumns, region.anchor === "top" || stacked ? void 0 : referenceHeights[index], region.anchor);
|
|
7876
|
+
if (!unit.children) {
|
|
7877
|
+
rowItems[rowOf(index)]?.push(...range(first, items.length));
|
|
7878
|
+
leafItems.push(...range(first, items.length));
|
|
7879
|
+
stack.push(...range(first, items.length));
|
|
7880
|
+
}
|
|
7485
7881
|
});
|
|
7882
|
+
if (arrangement !== "column") peerSets.push(...rowItems.filter((_, row) => (shape.perRow[row] ?? 0) > 1));
|
|
7883
|
+
else if (stacked && stack.length > 1) peerSets.push(stack);
|
|
7486
7884
|
return arrangement;
|
|
7487
7885
|
} finally {
|
|
7488
7886
|
regionTag = void 0;
|
|
7489
7887
|
templateCell = false;
|
|
7490
7888
|
}
|
|
7491
7889
|
};
|
|
7890
|
+
const bands = /* @__PURE__ */ new Map();
|
|
7891
|
+
let leafItems = [];
|
|
7492
7892
|
for (const region of plan2.regions) {
|
|
7493
7893
|
const units = unitsOf(region.name), bound = binding.regions.find((entry) => entry.name === region.name);
|
|
7494
7894
|
const rect = rects.get(region.name);
|
|
7495
7895
|
let cell = physical(logical(rect ?? ownRects.get(region.name)));
|
|
7496
7896
|
const areaBox = region.bleed && rect ? roundBox(cell) : void 0;
|
|
7497
7897
|
if (region.bleed && rect) cell = bleed(cell);
|
|
7898
|
+
leafItems = [];
|
|
7498
7899
|
const arrangement = units.length && rect ? placeRegion(region, units, cell) : void 0;
|
|
7900
|
+
if (arrangement && rect) {
|
|
7901
|
+
const band = `${rect.row}:${rect.rowSpan}:${region.role}`;
|
|
7902
|
+
bands.set(band, [...bands.get(band) ?? [], leafItems]);
|
|
7903
|
+
}
|
|
7499
7904
|
templateRegions.push({
|
|
7500
7905
|
name: region.name,
|
|
7501
7906
|
box: roundBox(cell),
|
|
@@ -7512,8 +7917,36 @@ function composeSlide(input, options = {}) {
|
|
|
7512
7917
|
...areaBox ? { areaBox } : {}
|
|
7513
7918
|
});
|
|
7514
7919
|
}
|
|
7920
|
+
for (const members of bands.values()) if (members.length > 1) peerSets.push(members.flat());
|
|
7515
7921
|
if (belowUnits.length) placeRegion(belowRegion, belowUnits, physical(logical(rects.get(BELOW))));
|
|
7516
7922
|
};
|
|
7923
|
+
const sharePeerSizes = () => {
|
|
7924
|
+
const parent = /* @__PURE__ */ new Map();
|
|
7925
|
+
const find = (index) => {
|
|
7926
|
+
let root = index;
|
|
7927
|
+
while (parent.has(root) && parent.get(root) !== root) root = parent.get(root);
|
|
7928
|
+
parent.set(index, root);
|
|
7929
|
+
return root;
|
|
7930
|
+
};
|
|
7931
|
+
for (const set2 of peerSets) for (const index of set2) parent.set(find(index), find(set2[0]));
|
|
7932
|
+
const kindOf = (item) => !item.text || item.quoteLayout || item.codeLayout || item.metricLayout || item.timelineLayout || item.listColumns ? void 0 : item.field === "text" ? "text" : item.field === "items" || item.field === "bullets" ? "list" : void 0;
|
|
7933
|
+
const sets = /* @__PURE__ */ new Map();
|
|
7934
|
+
for (const index of parent.keys()) {
|
|
7935
|
+
const item = items[index], kind2 = item && kindOf(item);
|
|
7936
|
+
if (kind2) sets.set(`${find(index)}:${kind2}`, [...sets.get(`${find(index)}:${kind2}`) ?? [], index]);
|
|
7937
|
+
}
|
|
7938
|
+
for (const members of sets.values()) {
|
|
7939
|
+
if (members.length < 2) continue;
|
|
7940
|
+
const size = Math.min(...members.map((index) => items[index].text.fontSize));
|
|
7941
|
+
for (const index of members) {
|
|
7942
|
+
const item = items[index];
|
|
7943
|
+
if (item.text.fontSize <= size + 1e-9) continue;
|
|
7944
|
+
const text2 = contentText(item.field, item.value) ?? "";
|
|
7945
|
+
const refit = fitContent(item.field, item.value, text2, item.box, size, snapFontSizeUp((item.composition.minFontSize ?? 16) * scale2), item.path, item.payload.numbering);
|
|
7946
|
+
if (!refit.overflow && Math.abs(refit.fontSize - size) < 1e-9) item.text = refit;
|
|
7947
|
+
}
|
|
7948
|
+
}
|
|
7949
|
+
};
|
|
7517
7950
|
const ownMode = record7(slide.composition).mode;
|
|
7518
7951
|
const direction = hints.contentDirection;
|
|
7519
7952
|
const directionMode = direction === "vertical" ? "column" : direction === "horizontal" ? "row" : "auto";
|
|
@@ -7529,6 +7962,7 @@ function composeSlide(input, options = {}) {
|
|
|
7529
7962
|
const support = { field: "blocks", type: "group", value: rest.map((node) => node.payload), path, payload: {}, children: rest, composition: {}, synthetic: true };
|
|
7530
7963
|
arrange(firstChart ? [primary, support] : [support, primary], contentBox, rootSettings, 0);
|
|
7531
7964
|
} else arrange(pending, contentBox, rootSettings, 0);
|
|
7965
|
+
sharePeerSizes();
|
|
7532
7966
|
if (listBullet?.value === "image" && !bulletImage && items.some((item) => (item.field === "items" || item.field === "bullets") && item.payload.numbering === void 0)) {
|
|
7533
7967
|
diagnostics.push({ code: "unresolved-content", path: listBullet.path, message: "Picture bullets (listBullet: image) need an organization logo (the primary organization, or the one design.logo names); the marker glyph is drawn instead." });
|
|
7534
7968
|
}
|
|
@@ -7591,4 +8025,4 @@ function resolveCanvasDimensions(input) {
|
|
|
7591
8025
|
return { width, height };
|
|
7592
8026
|
}
|
|
7593
8027
|
|
|
7594
|
-
export { AUTO_LAYOUT, CAPTIONABLE_FIELDS, CAPTION_FONT_RATIO, CAPTION_MAX_RATIO, CATALOG_GROUP_PATTERN, CATALOG_REFERENCE_PATTERN, CHART_HIGHLIGHT_MUTED_MIN_CONTRAST, CHART_HIGHLIGHT_MUTED_MIX, CHART_LEAD_MIN_CONTRAST, CHART_MAX_INTERVALS, CHART_MIN_TICK_SPACING_PX, CHART_SERIES_MIN_DIFFERENCE, CHART_SERIES_MIN_LIGHTNESS_STEP, CHART_SERIES_TIER_SIZE, CHART_SERIES_TINT_MIX, CHART_TEXT_FLOOR_PX, CHART_TEXT_PX, 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_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, FURNITURE_GAP, FURNITURE_IMAGE_SHARE, FURNITURE_ZONE_GUTTER, HEADING_AREAS, LANGUAGES, LAYOUT_BODY_KINDS, LOGO_SHAPES, MAX_COMPOSITION_DEPTH, MAX_NUMBERING_LEVELS, MAX_NUMBERING_VALUE, MAX_REGION_BLOCKS, MAX_REGION_DEPTH, MAX_REGION_ENTRIES, MAX_ROMAN_VALUE, MAX_TEMPLATE_TRACKS, METRIC_TREND_MIN_CONTRAST, METRIC_TREND_SHAPES, METRIC_VALUE_MIN_CONTRAST, NEUTRAL_SHARES, NUMBERING_STYLES, NUMBERING_SUFFIXES, OPFCatalogsOptionError, OPFCompositionError, OPFLayoutTemplateError, OPFUnresolvedReferenceError, OPFVariableError, PATTERN_PRESETS, PATTERN_PRESET_ALIASES, PATTERN_TILE_SIZE, PICTURE_BULLET_SCALE, PROMOTED_REGION_KEY, REGION_ANCHORS, REGION_FLOWS, REGION_KINDS, REGION_ROLES, RESERVED_REGION_NAMES, SLIDE_SCOPED_BUILTINS, SOCIAL_PLATFORMS, SURFACE_ALT_MIN_CONTRAST, SURFACE_ALT_MIX, THEME_DESIGN_KEYS, TIMELINE_OUTLINE_MIN_CONTRAST, TIMELINE_STATUSES, TIMELINE_TEXT_MIN_CONTRAST, VARIABLE_KINDS, allocateRows, annotationText, applyLuminance, bindRegions, blockKind, captionSettings, catalogGroupDeclared, catalogGroupSource, catalogKinds, catalogRecords, catalogReferenceSites, chartColorForFill, chartHighlightColors, chartHighlightMarks, chartIntervalsFor, chartLabelText, chartLeadFromScheme, chartNumber, chartNumberFixesByCell, chartOptionSupport, chartOptionTarget, chartPaletteForFill, chartSeriesPalette, chartTextSize, chartValueAxis, checkCatalogsOption, citationMarkerText, clrMapAttributes, codeHighlightBands, codeHighlightColors, codeHighlightLines, codeHighlightSlice, codeLineNumbers, codeLineRuns, codeSyntaxPalette, codeSyntaxPaletteForRoles, codeSyntaxPaletteForScheme, coerceVariableValue, collectCitations, colorContrast, colorMapFor, composeLayoutAreas, composeSlide, datasetDiagnostics, defaultSlideBackground, dottedPath, embeddedCopy, fitImage, fitList, fitRichText, fitText, formatChartLabelNumber, formatChartLabelPercent, formatDataNumber, formatFurnitureDate, formatListNumber, formatVariableNumber, fromExcelNumberFormat, gridFlowShape, hasContentVariables, imageBackground, imageShape, inlineChartData, inlineDatasets, inlineTableData, instantiateForValidation, intrinsicImageAspect, intrinsicImageSize, isColorVariant, isDarkColor, isDatasetRef, isLayoutTemplate, isRecord, isTemplate, isXYChartType, layoutCaption, layoutCode, layoutContent, layoutEntries, layoutFootnotes, layoutFurniture, layoutMetric, layoutQuote, layoutRegion, layoutStructure, layoutTable, layoutTemplate, layoutTemplateIssues, layoutTimeline, layoutWatermark, listBuiltinVariables, listColumnBreaks, listNumbers, listVariables, maxIntervalsFor, measureText, measureTextOutline, metricTrendColor, metricTrendMark, metricTrendPoints, metricValueColor, niceScale, normalizeColorVariant, normalizeHexColor, normalizeLanguageFamily, numberFormatError, numberingAtLevel, numberingFindings, numberingStyleDraws, paragraphDirection, paragraphDirectionAt, parseReference, pathFor, patternBitmap, patternRuns, physicalAlignment, placeTextLines, placedImageBlocks, pointerPath, promotedRegionKeys, provenanceOf, readableSchemeColor, readingRows, recordReferenceSites, referencesSlide, regionAccepts, regionRoleRank, registeredCatalog, resolveCanvasDimensions, resolveChartColors, resolveChartData, resolveChartOptions, resolveCodeLanguage, resolveColorRef, resolveColorRoles, resolveDesignHints, resolveDesignRecords, resolveFontFamilies, resolveFontScheme, resolveLogo, resolveNumbering, resolvePatternPreset, resolveReference, resolveScriptFonts, resolveSlideDirection, resolveSlideVariables, resolveSocialProfile, resolveTableData, resolveTextStyle, resolveVariables, rootNodes, scriptFontRole, sliceNumberedItems, slideCitations, slideTokenSpans, snapFontSizeDown, snapFontSizeUp, stackCategoryValues, suggestChartNumberFix, surfaceAltColor, tableCellDisplayValue, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, timelineMarkerShapes, timelineTextColor, toExcelNumberFormat, tokenizeCode, unresolvedReference, unusedDatasets, usesSlideBuiltin, variableDeclarations, visitContentPayloads, visualReadingOrder, walkCitationRuns, wrapText };
|
|
8028
|
+
export { ASCII_QUOTE_MARKS, AUTO_LAYOUT, CAPTIONABLE_FIELDS, CAPTION_FONT_RATIO, CAPTION_MAX_RATIO, CATALOG_GROUP_PATTERN, CATALOG_REFERENCE_PATTERN, CHART_HIGHLIGHT_MUTED_MIN_CONTRAST, CHART_HIGHLIGHT_MUTED_MIX, CHART_LEAD_MIN_CONTRAST, CHART_MAX_INTERVALS, CHART_MIN_TICK_SPACING_PX, CHART_SERIES_MIN_DIFFERENCE, CHART_SERIES_MIN_LIGHTNESS_STEP, CHART_SERIES_TIER_SIZE, CHART_SERIES_TINT_MIX, CHART_TEXT_FLOOR_PX, CHART_TEXT_PX, CHART_TYPES, CITATION_MARKER_RAISE, CITATION_MARKER_SCALE, CODE_HIGHLIGHT_LANGUAGES, CODE_HIGHLIGHT_MAX_LENGTH, CODE_NOMINAL_SIZE, CODE_PANEL_BACKGROUND, CODE_PANEL_FOREGROUND, CODE_SYNTAX_MIN_CONTRAST, DARK_BACKGROUND_LUMINANCE, DEFAULT_CHART_LABEL_SEPARATOR, DEFAULT_FURNITURE_DATE_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, FURNITURE_GAP, FURNITURE_IMAGE_SHARE, FURNITURE_ZONE_GUTTER, HEADING_AREAS, LANGUAGES, LAYOUT_BODY_KINDS, LEAD_NOMINAL_SIZE, LIST_NOMINAL_SIZE, LOGO_SHAPES, MAX_COMPOSITION_DEPTH, MAX_NUMBERING_LEVELS, MAX_NUMBERING_VALUE, MAX_REGION_BLOCKS, MAX_REGION_DEPTH, MAX_REGION_ENTRIES, MAX_ROMAN_VALUE, MAX_TEMPLATE_TRACKS, METRIC_TREND_MIN_CONTRAST, METRIC_TREND_SHAPES, METRIC_VALUE_MIN_CONTRAST, NEUTRAL_SHARES, NUMBERING_STYLES, NUMBERING_SUFFIXES, OPFCatalogsOptionError, OPFCompositionError, OPFLayoutTemplateError, OPFUnresolvedReferenceError, OPFVariableError, PATTERN_PRESETS, PATTERN_PRESET_ALIASES, PATTERN_TILE_SIZE, PICTURE_BULLET_SCALE, PROMOTED_REGION_KEY, PROSE_NOMINAL_SIZE, QUOTE_MARKS, QUOTE_NOMINAL_SIZE, QUOTE_SOURCE_SEPARATOR, REGION_ANCHORS, REGION_FLOWS, REGION_KINDS, REGION_ROLES, RESERVED_REGION_NAMES, SLIDE_SCOPED_BUILTINS, SOCIAL_PLATFORMS, SURFACE_ALT_MIN_CONTRAST, SURFACE_ALT_MIX, TABLE_NOMINAL_SIZE, THEME_DESIGN_KEYS, TIMELINE_OUTLINE_MIN_CONTRAST, TIMELINE_STATUSES, TIMELINE_TEXT_MIN_CONTRAST, VARIABLE_KINDS, allocateRows, annotationText, applyLuminance, bindRegions, blockKind, captionSettings, catalogGroupDeclared, catalogGroupSource, catalogKinds, catalogRecords, catalogReferenceSites, chartColorForFill, chartHighlightColors, chartHighlightMarks, chartIntervalsFor, chartLabelText, chartLeadFromScheme, chartNumber, chartNumberFixesByCell, chartOptionSupport, chartOptionTarget, chartPaletteForFill, chartSeriesPalette, chartTextSize, chartValueAxis, checkCatalogsOption, citationMarkerText, clrMapAttributes, codeHighlightBands, codeHighlightColors, codeHighlightLines, codeHighlightSlice, codeLineNumbers, codeLineRuns, codeSyntaxPalette, codeSyntaxPaletteForRoles, codeSyntaxPaletteForScheme, coerceVariableValue, collectCitations, colorContrast, colorMapFor, composeLayoutAreas, composeSlide, datasetDiagnostics, defaultSlideBackground, dottedPath, embeddedCopy, fitImage, fitList, fitRichText, fitText, formatChartLabelNumber, formatChartLabelPercent, formatDataNumber, formatFurnitureDate, formatListNumber, formatVariableNumber, fromExcelNumberFormat, gridFlowShape, hasContentVariables, imageBackground, imageShape, inlineChartData, inlineDatasets, inlineTableData, instantiateForValidation, intrinsicImageAspect, intrinsicImageSize, isColorVariant, isDarkColor, isDatasetRef, isLayoutTemplate, isRecord, isTemplate, isWrappedInQuoteMarks, isXYChartType, layoutCaption, layoutCode, layoutContent, layoutEntries, layoutFootnotes, layoutFurniture, layoutMetric, layoutQuote, layoutRegion, layoutStructure, layoutTable, layoutTemplate, layoutTemplateIssues, layoutTimeline, layoutWatermark, listBuiltinVariables, listColumnBreaks, listNumbers, listVariables, maxIntervalsFor, measureText, measureTextOutline, metricTrendColor, metricTrendMark, metricTrendPoints, metricValueColor, niceScale, normalizeColorVariant, normalizeHexColor, normalizeLanguageFamily, numberFormatError, numberingAtLevel, numberingFindings, numberingStyleDraws, paragraphDirection, paragraphDirectionAt, parseReference, pathFor, patternBitmap, patternRuns, physicalAlignment, placeTextLines, placedImageBlocks, pointerPath, promotedRegionKeys, provenanceOf, quoteLanguage, quoteMarksFor, readableSchemeColor, readingRows, recordReferenceSites, referencesSlide, regionAccepts, regionRoleRank, registeredCatalog, resolveCanvasDimensions, resolveChartColors, resolveChartData, resolveChartOptions, resolveCodeLanguage, resolveColorRef, resolveColorRoles, resolveDesignHints, resolveDesignRecords, resolveFontFamilies, resolveFontScheme, resolveLogo, resolveNumbering, resolvePatternPreset, resolveReference, resolveScriptFonts, resolveSlideDirection, resolveSlideVariables, resolveSocialProfile, resolveTableData, resolveTextStyle, resolveVariables, rootNodes, scriptFontRole, shareHeights, sliceNumberedItems, slideCitations, slideTokenSpans, snapFontSizeDown, snapFontSizeUp, stackCategoryValues, suggestChartNumberFix, surfaceAltColor, tableCellDisplayValue, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, timelineMarkerShapes, timelineTextColor, toExcelNumberFormat, tokenizeCode, unresolvedReference, unusedDatasets, unwrapQuoteMarks, usesSlideBuiltin, variableDeclarations, visitContentPayloads, visualReadingOrder, walkCitationRuns, wrapText };
|