@bendyline/squisq 2.13.2 → 2.13.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Doc-CYTLtFEu.d.ts → Doc-DnRFE0EI.d.ts} +40 -2
- package/dist/{ImageEditDoc-DZ4k_O10.d.ts → ImageEditDoc-CadNz387.d.ts} +1 -1
- package/dist/{chunk-HE3HQZWU.js → chunk-6NWVLLMI.js} +104 -1
- package/dist/{chunk-56TW6HE6.js → chunk-BITSNRJH.js} +15 -10
- package/dist/{chunk-3A6YM375.js → chunk-D3JQMZUT.js} +8 -8
- package/dist/chunk-DOOUVVOM.js +78 -0
- package/dist/{chunk-FUQYQWQR.js → chunk-DRHJD6U4.js} +5 -5
- package/dist/{chunk-2GN67Q2T.js → chunk-FIPRGGXD.js} +1 -1
- package/dist/{chunk-YY3OQ3MI.js → chunk-J2NFT7GH.js} +475 -342
- package/dist/{chunk-7ZXCS3UU.js → chunk-JFJZ4NS6.js} +2 -2
- package/dist/{chunk-HGCIIXHP.js → chunk-POZCKPCO.js} +235 -4
- package/dist/doc/index.d.ts +134 -14
- package/dist/doc/index.js +17 -7
- package/dist/fence/index.d.ts +1 -1
- package/dist/generate/index.d.ts +1 -1
- package/dist/imageEdit/index.d.ts +3 -3
- package/dist/index.d.ts +5 -5
- package/dist/index.js +27 -17
- package/dist/jsonForm/index.d.ts +1 -1
- package/dist/markdown/index.js +11 -12
- package/dist/{materializePageSection-CDps_xUd.d.ts → materializePageSection-D84uA6Vk.d.ts} +1 -1
- package/dist/mediaEdit/index.d.ts +2 -2
- package/dist/narration/index.d.ts +1 -1
- package/dist/narration/index.js +5 -5
- package/dist/recommend/index.js +3 -2
- package/dist/schemas/index.d.ts +4 -4
- package/dist/{themeLibrary-CMm_jh3a.d.ts → themeLibrary-in0fafp4.d.ts} +1 -1
- package/dist/timing/index.d.ts +1 -1
- package/dist/transform/index.d.ts +2 -2
- package/dist/transform/index.js +6 -6
- package/package.json +1 -1
- package/dist/chunk-Y25EJEZN.js +0 -178
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
extractEmbeddedVideos,
|
|
11
11
|
extractHostedVideos,
|
|
12
12
|
extractImages,
|
|
13
|
+
extractMediaFromContents,
|
|
13
14
|
extractRichListItems,
|
|
14
15
|
extractTableFromContents,
|
|
15
16
|
isEligibleAsciiFenceLang,
|
|
@@ -19,15 +20,19 @@ import {
|
|
|
19
20
|
isExplicitTimelineLang,
|
|
20
21
|
isExplicitTreeLang,
|
|
21
22
|
isMaterializedMediaNode,
|
|
23
|
+
isMediaAnnotationName,
|
|
22
24
|
isPictureFence,
|
|
25
|
+
isPictureParagraph,
|
|
23
26
|
markdownBlockSeparatorLines,
|
|
27
|
+
parseAnnotationInner,
|
|
24
28
|
parseAsciiDiagram,
|
|
25
29
|
parseAsciiTimeline,
|
|
30
|
+
parseStandaloneAnnotation,
|
|
26
31
|
pickAutoTemplate,
|
|
27
32
|
profileBlockContents,
|
|
28
33
|
renderMarkdownBlocksHtml,
|
|
29
34
|
treeToTemplateData
|
|
30
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-POZCKPCO.js";
|
|
31
36
|
import {
|
|
32
37
|
anchorPoint,
|
|
33
38
|
base64ToUtf8,
|
|
@@ -58,33 +63,25 @@ import {
|
|
|
58
63
|
validateTheme,
|
|
59
64
|
withAlpha
|
|
60
65
|
} from "./chunk-WNEH3BZP.js";
|
|
61
|
-
import {
|
|
62
|
-
mediaEditValuesFromAttributes,
|
|
63
|
-
mediaEditValuesFromParams,
|
|
64
|
-
parseMediaEdits
|
|
65
|
-
} from "./chunk-L7QZORLB.js";
|
|
66
66
|
import {
|
|
67
67
|
TABLE_FED_TEMPLATES,
|
|
68
68
|
isContainerTemplate,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
splitKeyValueToken,
|
|
72
|
-
tokenizeAttrTokens
|
|
73
|
-
} from "./chunk-Y25EJEZN.js";
|
|
69
|
+
resolveTemplateName
|
|
70
|
+
} from "./chunk-DOOUVVOM.js";
|
|
74
71
|
import {
|
|
75
72
|
KNOWN_BLOCK_META_KEYS,
|
|
76
73
|
coerceAnnotationValues,
|
|
77
74
|
extractPlainText,
|
|
78
75
|
isSvgIslandLang,
|
|
79
76
|
isVideoEmbedUrl,
|
|
77
|
+
matchTrailingTemplateAnnotation,
|
|
80
78
|
mediaKindForUrl,
|
|
81
79
|
parseNumber,
|
|
82
80
|
parseSvgIsland,
|
|
83
|
-
parseTimeSeconds,
|
|
84
81
|
parseVideoEmbedUrl,
|
|
85
82
|
readFrontmatterThemeId,
|
|
86
83
|
walkMarkdownTree
|
|
87
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-6NWVLLMI.js";
|
|
88
85
|
import {
|
|
89
86
|
resolveBlockTransition
|
|
90
87
|
} from "./chunk-P53Z4RYC.js";
|
|
@@ -1292,6 +1289,131 @@ function sectionHeader(input, context) {
|
|
|
1292
1289
|
return layers;
|
|
1293
1290
|
}
|
|
1294
1291
|
|
|
1292
|
+
// src/doc/utils/textMetrics.ts
|
|
1293
|
+
var AVERAGE_CHAR_WIDTH_EM = 0.62;
|
|
1294
|
+
var BOLD_CHAR_WIDTH_EM = 0.66;
|
|
1295
|
+
function estimateTextWidth(text, fontSize, charWidthEm = AVERAGE_CHAR_WIDTH_EM) {
|
|
1296
|
+
return text.length * fontSize * charWidthEm;
|
|
1297
|
+
}
|
|
1298
|
+
var DISPLAY_CHAR_EM = {
|
|
1299
|
+
space: 0.27,
|
|
1300
|
+
narrowLower: 0.36,
|
|
1301
|
+
wideLower: 0.86,
|
|
1302
|
+
lower: 0.57,
|
|
1303
|
+
narrowUpper: 0.4,
|
|
1304
|
+
wideUpper: 0.95,
|
|
1305
|
+
upper: 0.7,
|
|
1306
|
+
digit: 0.57,
|
|
1307
|
+
punct: 0.34,
|
|
1308
|
+
other: 0.62
|
|
1309
|
+
};
|
|
1310
|
+
function displayCharEm(ch) {
|
|
1311
|
+
if (ch === " ") return DISPLAY_CHAR_EM.space;
|
|
1312
|
+
if ("fijlrt".includes(ch)) return DISPLAY_CHAR_EM.narrowLower;
|
|
1313
|
+
if (ch === "m" || ch === "w") return DISPLAY_CHAR_EM.wideLower;
|
|
1314
|
+
if (ch >= "a" && ch <= "z") return DISPLAY_CHAR_EM.lower;
|
|
1315
|
+
if (ch === "I" || ch === "J") return DISPLAY_CHAR_EM.narrowUpper;
|
|
1316
|
+
if (ch === "M" || ch === "W") return DISPLAY_CHAR_EM.wideUpper;
|
|
1317
|
+
if (ch >= "A" && ch <= "Z") return DISPLAY_CHAR_EM.upper;
|
|
1318
|
+
if (ch >= "0" && ch <= "9") return DISPLAY_CHAR_EM.digit;
|
|
1319
|
+
if (".,:;-/'\u2019!?()".includes(ch)) return DISPLAY_CHAR_EM.punct;
|
|
1320
|
+
return DISPLAY_CHAR_EM.other;
|
|
1321
|
+
}
|
|
1322
|
+
function estimateDisplayTextWidth(text, fontSize) {
|
|
1323
|
+
let em = 0;
|
|
1324
|
+
for (const ch of text.normalize("NFD").replace(/\p{M}/gu, "")) em += displayCharEm(ch);
|
|
1325
|
+
return em * fontSize;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
// src/doc/templates/frostedPlate.ts
|
|
1329
|
+
var FROSTED_PAD_X_EM = 0.45;
|
|
1330
|
+
var FROSTED_PAD_Y_EM = 0.3;
|
|
1331
|
+
var FROSTED_RADIUS_EM = 0.3;
|
|
1332
|
+
var FROSTED_BLUR_SHARE = 0.0167;
|
|
1333
|
+
var FROSTED_TINT_UNDER_LIGHT_TEXT = "rgba(12, 12, 14, 0.26)";
|
|
1334
|
+
var FROSTED_TINT_UNDER_DARK_TEXT = "rgba(250, 250, 250, 0.5)";
|
|
1335
|
+
var FROSTED_BACKDROP_CONTRAST = 0.65;
|
|
1336
|
+
function frostedUnderLightText(context) {
|
|
1337
|
+
return relativeLuminance(context.theme.colors.text) > 0.5;
|
|
1338
|
+
}
|
|
1339
|
+
function frostedBlurPx(context) {
|
|
1340
|
+
const { width, height } = context.viewport;
|
|
1341
|
+
return Math.round(FROSTED_BLUR_SHARE * Math.min(width, height));
|
|
1342
|
+
}
|
|
1343
|
+
function pct(value, total) {
|
|
1344
|
+
return `${Math.round(value / total * 1e4) / 100}%`;
|
|
1345
|
+
}
|
|
1346
|
+
function frostedPlateLayer(id, plate, context) {
|
|
1347
|
+
const { viewport } = context;
|
|
1348
|
+
const lightText = frostedUnderLightText(context);
|
|
1349
|
+
return {
|
|
1350
|
+
type: "shape",
|
|
1351
|
+
id,
|
|
1352
|
+
content: {
|
|
1353
|
+
shape: "rect",
|
|
1354
|
+
fill: lightText ? FROSTED_TINT_UNDER_LIGHT_TEXT : FROSTED_TINT_UNDER_DARK_TEXT,
|
|
1355
|
+
borderRadius: Math.round(plate.radius),
|
|
1356
|
+
backdropBlur: frostedBlurPx(context),
|
|
1357
|
+
...lightText ? { backdropContrast: FROSTED_BACKDROP_CONTRAST } : {}
|
|
1358
|
+
},
|
|
1359
|
+
position: {
|
|
1360
|
+
x: pct(plate.x, viewport.width),
|
|
1361
|
+
y: pct(plate.y, viewport.height),
|
|
1362
|
+
width: pct(plate.width, viewport.width),
|
|
1363
|
+
height: pct(plate.height, viewport.height)
|
|
1364
|
+
}
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
var INK_EM = {
|
|
1368
|
+
xHeight: 0.45,
|
|
1369
|
+
capital: 0.67,
|
|
1370
|
+
ascent: 0.71,
|
|
1371
|
+
accentedCapital: 0.8,
|
|
1372
|
+
descent: 0.2,
|
|
1373
|
+
comma: 0.155
|
|
1374
|
+
};
|
|
1375
|
+
function opticalCentreShiftEm(lines) {
|
|
1376
|
+
const first = (lines[0] ?? "").normalize("NFD");
|
|
1377
|
+
const last = lines[lines.length - 1] ?? "";
|
|
1378
|
+
const top = /[A-Z]\p{M}/u.test(first) ? INK_EM.accentedCapital : /[bdfhklt]|[a-z]\p{M}/u.test(first) ? INK_EM.ascent : /[A-Z0-9]/.test(first) ? INK_EM.capital : INK_EM.xHeight;
|
|
1379
|
+
const bottom = /[gjpqyQ]/.test(last) ? INK_EM.descent : /[,;]/.test(last) ? INK_EM.comma : 0;
|
|
1380
|
+
return Math.round(((top - bottom) / 2 - INK_EM.xHeight / 2) * 1e3) / 1e3;
|
|
1381
|
+
}
|
|
1382
|
+
function wrapDisplayLine(line, fontSize, maxWidth) {
|
|
1383
|
+
const lines = [];
|
|
1384
|
+
let current = "";
|
|
1385
|
+
for (const word of line.trim().split(/\s+/).filter(Boolean)) {
|
|
1386
|
+
const candidate = current ? `${current} ${word}` : word;
|
|
1387
|
+
if (!current || estimateDisplayTextWidth(candidate, fontSize) <= maxWidth) {
|
|
1388
|
+
current = candidate;
|
|
1389
|
+
} else {
|
|
1390
|
+
lines.push(current);
|
|
1391
|
+
current = word;
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
if (current) lines.push(current);
|
|
1395
|
+
return lines.length > 0 ? lines : [""];
|
|
1396
|
+
}
|
|
1397
|
+
function balancedDisplayLines(line, fontSize, maxWidth) {
|
|
1398
|
+
const greedy = wrapDisplayLine(line, fontSize, maxWidth);
|
|
1399
|
+
if (greedy.length < 2) return greedy;
|
|
1400
|
+
let lo = Math.max(
|
|
1401
|
+
...line.split(/\s+/).filter(Boolean).map((word) => estimateDisplayTextWidth(word, fontSize))
|
|
1402
|
+
);
|
|
1403
|
+
let hi = maxWidth;
|
|
1404
|
+
if (lo >= hi) return greedy;
|
|
1405
|
+
while (hi - lo > 0.5) {
|
|
1406
|
+
const mid = (lo + hi) / 2;
|
|
1407
|
+
if (wrapDisplayLine(line, fontSize, mid).length <= greedy.length) hi = mid;
|
|
1408
|
+
else lo = mid;
|
|
1409
|
+
}
|
|
1410
|
+
return wrapDisplayLine(line, fontSize, hi);
|
|
1411
|
+
}
|
|
1412
|
+
function frostedTitleBoxWidth(lines, fontSize, textWidth) {
|
|
1413
|
+
const longestChars = Math.max(...lines.map((line) => line.length));
|
|
1414
|
+
return Math.max(textWidth, longestChars * fontSize * 0.5 + 1);
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1295
1417
|
// src/doc/templates/bigText.ts
|
|
1296
1418
|
var BIG_TEXT_LINE_HEIGHT = 1.05;
|
|
1297
1419
|
var BIG_TEXT_WIDTH_FRACTION = 0.92;
|
|
@@ -1341,6 +1463,65 @@ function fitBigTextSize(title, viewport, heightFraction = BIG_TEXT_HEIGHT_FRACTI
|
|
|
1341
1463
|
}
|
|
1342
1464
|
return Math.floor(low);
|
|
1343
1465
|
}
|
|
1466
|
+
var BIG_TEXT_FROSTED_WIDTH_FRACTION = 0.9;
|
|
1467
|
+
var BIG_TEXT_FROSTED_HEIGHT_SHARE = 0.45;
|
|
1468
|
+
function frostedBigTextLayout(displayTitle, viewport, band = BIG_TEXT_BANDS.center) {
|
|
1469
|
+
const maxPlateWidth = viewport.width * BIG_TEXT_FROSTED_WIDTH_FRACTION;
|
|
1470
|
+
const maxPlateHeight = Math.min(
|
|
1471
|
+
viewport.height * band.height,
|
|
1472
|
+
Math.min(viewport.width, viewport.height) * BIG_TEXT_FROSTED_HEIGHT_SHARE
|
|
1473
|
+
);
|
|
1474
|
+
const wrapAt = (size) => {
|
|
1475
|
+
const column2 = maxPlateWidth - 2 * FROSTED_PAD_X_EM * size;
|
|
1476
|
+
const lines2 = displayTitle.split("\n").flatMap((line) => balancedDisplayLines(line, size, Math.max(1, column2)));
|
|
1477
|
+
const width2 = Math.max(...lines2.map((line) => estimateDisplayTextWidth(line, size)));
|
|
1478
|
+
return { lines: lines2, width: width2, column: column2 };
|
|
1479
|
+
};
|
|
1480
|
+
const fits = (size) => {
|
|
1481
|
+
const { lines: lines2, width: width2, column: column2 } = wrapAt(size);
|
|
1482
|
+
const height = (lines2.length * BIG_TEXT_LINE_HEIGHT + 2 * FROSTED_PAD_Y_EM) * size;
|
|
1483
|
+
return width2 <= column2 && height <= maxPlateHeight;
|
|
1484
|
+
};
|
|
1485
|
+
let low = BIG_TEXT_MIN_PX;
|
|
1486
|
+
let high = maxPlateHeight / (BIG_TEXT_LINE_HEIGHT + 2 * FROSTED_PAD_Y_EM);
|
|
1487
|
+
if (high > low && fits(low)) {
|
|
1488
|
+
for (let i = 0; i < 24; i += 1) {
|
|
1489
|
+
const mid = (low + high) / 2;
|
|
1490
|
+
if (fits(mid)) low = mid;
|
|
1491
|
+
else high = mid;
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
const fontSize = Math.floor(low);
|
|
1495
|
+
const { lines, width, column } = wrapAt(fontSize);
|
|
1496
|
+
const textWidth = Math.min(width, column);
|
|
1497
|
+
const textHeight = lines.length * fontSize * BIG_TEXT_LINE_HEIGHT;
|
|
1498
|
+
const padX = FROSTED_PAD_X_EM * fontSize;
|
|
1499
|
+
const padY = FROSTED_PAD_Y_EM * fontSize;
|
|
1500
|
+
const plateWidth = textWidth + 2 * padX;
|
|
1501
|
+
const plateHeight = textHeight + 2 * padY;
|
|
1502
|
+
const cx = viewport.width / 2;
|
|
1503
|
+
const cy = viewport.height * band.y;
|
|
1504
|
+
return {
|
|
1505
|
+
fontSize,
|
|
1506
|
+
lines,
|
|
1507
|
+
plate: {
|
|
1508
|
+
x: cx - plateWidth / 2,
|
|
1509
|
+
y: cy - plateHeight / 2,
|
|
1510
|
+
width: plateWidth,
|
|
1511
|
+
height: plateHeight,
|
|
1512
|
+
radius: FROSTED_RADIUS_EM * fontSize
|
|
1513
|
+
},
|
|
1514
|
+
// As on the frosted cover, the box spans the padding: shrink-to-fit measures the
|
|
1515
|
+
// font's whole ascent and descent, more than a line of display type.
|
|
1516
|
+
title: {
|
|
1517
|
+
cx,
|
|
1518
|
+
cy,
|
|
1519
|
+
width: frostedTitleBoxWidth(lines, fontSize, textWidth),
|
|
1520
|
+
height: plateHeight
|
|
1521
|
+
},
|
|
1522
|
+
baselineShift: opticalCentreShiftEm(lines)
|
|
1523
|
+
};
|
|
1524
|
+
}
|
|
1344
1525
|
function bigTextBloom(background, centerY = 0.5) {
|
|
1345
1526
|
return `radial-gradient(ellipse at 50% ${Math.round(centerY * 100)}%, ${withAlpha(background, 0.92)} 0%, ${withAlpha(background, 0.78)} 38%, ${withAlpha(background, 0.32)} 66%, ${withAlpha(background, 0)} 88%)`;
|
|
1346
1527
|
}
|
|
@@ -1350,27 +1531,28 @@ function bigText(input, context) {
|
|
|
1350
1531
|
const band = BIG_TEXT_BANDS[input.placement ?? "center"] ?? BIG_TEXT_BANDS.center;
|
|
1351
1532
|
const treatment = themedImageTreatment(context, input.imageTreatment);
|
|
1352
1533
|
const displayTitle = title.toUpperCase();
|
|
1534
|
+
const frosted = input.backdrop === "frosted" && !!imageSrc;
|
|
1353
1535
|
const titleFontSize = fitBigTextSize(displayTitle, viewport, band.height);
|
|
1354
1536
|
const layers = [];
|
|
1355
1537
|
if (imageSrc) {
|
|
1356
|
-
layers.push(
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
...treatment ? { treatment } : {}
|
|
1365
|
-
},
|
|
1366
|
-
position: { x: 0, y: 0, width: "100%", height: "100%" },
|
|
1367
|
-
animation: mapAmbientMotion(ambientMotion, 8) ?? {
|
|
1368
|
-
type: "slowZoom",
|
|
1369
|
-
duration: 8,
|
|
1370
|
-
direction: "in"
|
|
1371
|
-
}
|
|
1538
|
+
layers.push({
|
|
1539
|
+
type: "image",
|
|
1540
|
+
id: "bigtext-image",
|
|
1541
|
+
content: {
|
|
1542
|
+
src: imageSrc,
|
|
1543
|
+
alt: imageAlt || title,
|
|
1544
|
+
fit: "cover",
|
|
1545
|
+
...treatment ? { treatment } : {}
|
|
1372
1546
|
},
|
|
1373
|
-
{
|
|
1547
|
+
position: { x: 0, y: 0, width: "100%", height: "100%" },
|
|
1548
|
+
animation: mapAmbientMotion(ambientMotion, 8) ?? {
|
|
1549
|
+
type: "slowZoom",
|
|
1550
|
+
duration: 8,
|
|
1551
|
+
direction: "in"
|
|
1552
|
+
}
|
|
1553
|
+
});
|
|
1554
|
+
if (!frosted) {
|
|
1555
|
+
layers.push({
|
|
1374
1556
|
type: "shape",
|
|
1375
1557
|
id: "bigtext-bloom",
|
|
1376
1558
|
content: {
|
|
@@ -1378,8 +1560,8 @@ function bigText(input, context) {
|
|
|
1378
1560
|
fill: bigTextBloom(theme.colors.background, band.y)
|
|
1379
1561
|
},
|
|
1380
1562
|
position: { x: 0, y: 0, width: "100%", height: "100%" }
|
|
1381
|
-
}
|
|
1382
|
-
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1383
1565
|
} else {
|
|
1384
1566
|
layers.push(
|
|
1385
1567
|
{
|
|
@@ -1402,6 +1584,38 @@ function bigText(input, context) {
|
|
|
1402
1584
|
}
|
|
1403
1585
|
);
|
|
1404
1586
|
}
|
|
1587
|
+
if (frosted) {
|
|
1588
|
+
const layout = frostedBigTextLayout(displayTitle, viewport, band);
|
|
1589
|
+
const lightText = frostedUnderLightText(context);
|
|
1590
|
+
layers.push(frostedPlateLayer("bigtext-plate", layout.plate, context), {
|
|
1591
|
+
type: "text",
|
|
1592
|
+
id: "bigtext-title",
|
|
1593
|
+
content: {
|
|
1594
|
+
text: layout.lines.join("\n"),
|
|
1595
|
+
style: {
|
|
1596
|
+
fontSize: layout.fontSize,
|
|
1597
|
+
fontFamily: getThemeFont(context, "title"),
|
|
1598
|
+
fontWeight: "bold",
|
|
1599
|
+
color: theme.colors.text,
|
|
1600
|
+
textAlign: "center",
|
|
1601
|
+
verticalAlign: "middle",
|
|
1602
|
+
lineHeight: BIG_TEXT_LINE_HEIGHT,
|
|
1603
|
+
baselineShift: layout.baselineShift,
|
|
1604
|
+
shadow: lightText,
|
|
1605
|
+
shrinkToFit: true
|
|
1606
|
+
}
|
|
1607
|
+
},
|
|
1608
|
+
position: {
|
|
1609
|
+
x: "50%",
|
|
1610
|
+
y: pct(layout.title.cy, viewport.height),
|
|
1611
|
+
anchor: "center",
|
|
1612
|
+
width: pct(layout.title.width, viewport.width),
|
|
1613
|
+
height: pct(layout.title.height, viewport.height)
|
|
1614
|
+
},
|
|
1615
|
+
animation: motionEntrance(context, { type: "fadeIn", duration: 1 })
|
|
1616
|
+
});
|
|
1617
|
+
return layers;
|
|
1618
|
+
}
|
|
1405
1619
|
layers.push({
|
|
1406
1620
|
type: "text",
|
|
1407
1621
|
id: "bigtext-title",
|
|
@@ -2965,6 +3179,17 @@ function rightFeature(input, context) {
|
|
|
2965
3179
|
return buildFeatureLayers(input, context, "right");
|
|
2966
3180
|
}
|
|
2967
3181
|
|
|
3182
|
+
// src/doc/templates/mediaFeatureBlock.ts
|
|
3183
|
+
function topFeature(input, context) {
|
|
3184
|
+
return contentBlock({ ...input, template: "content" }, context, { omitPictures: true });
|
|
3185
|
+
}
|
|
3186
|
+
function bottomFeature(input, context) {
|
|
3187
|
+
return contentBlock({ ...input, template: "content" }, context, { omitPictures: true });
|
|
3188
|
+
}
|
|
3189
|
+
function mediaOnly(input, context) {
|
|
3190
|
+
return contentBlock({ ...input, template: "content" }, context);
|
|
3191
|
+
}
|
|
3192
|
+
|
|
2968
3193
|
// src/doc/templates/mapBlock.ts
|
|
2969
3194
|
function mapBlock(input, context) {
|
|
2970
3195
|
const {
|
|
@@ -5524,6 +5749,30 @@ var BLOCK_MEDIA_LAYOUT_POLICIES = {
|
|
|
5524
5749
|
additionalMediaLayout: "overlay-inset",
|
|
5525
5750
|
unconsumedMedia: "retain-native-layout"
|
|
5526
5751
|
},
|
|
5752
|
+
topFeature: {
|
|
5753
|
+
summary: "Body media spans the full width across the top; the heading and complete body take a band below sized to the text. Without media it is a content slide.",
|
|
5754
|
+
noMedia: "template-default",
|
|
5755
|
+
ownership: "native-slot",
|
|
5756
|
+
nativeLayout: "feature-top",
|
|
5757
|
+
additionalMediaLayout: "overlay-inset",
|
|
5758
|
+
unconsumedMedia: "retain-native-layout"
|
|
5759
|
+
},
|
|
5760
|
+
bottomFeature: {
|
|
5761
|
+
summary: "The heading and complete body take a band across the top sized to the text; body media spans the full width below. Without media it is a content slide.",
|
|
5762
|
+
noMedia: "template-default",
|
|
5763
|
+
ownership: "native-slot",
|
|
5764
|
+
nativeLayout: "feature-bottom",
|
|
5765
|
+
additionalMediaLayout: "overlay-inset",
|
|
5766
|
+
unconsumedMedia: "retain-native-layout"
|
|
5767
|
+
},
|
|
5768
|
+
mediaOnly: {
|
|
5769
|
+
summary: "Body media fills the whole slide with no text; without media the heading and body render as a content slide.",
|
|
5770
|
+
noMedia: "template-default",
|
|
5771
|
+
ownership: "native-slot",
|
|
5772
|
+
nativeLayout: "full-frame",
|
|
5773
|
+
additionalMediaLayout: "overlay-inset",
|
|
5774
|
+
unconsumedMedia: "retain-native-layout"
|
|
5775
|
+
},
|
|
5527
5776
|
map: {
|
|
5528
5777
|
summary: "The map canvas is the primary visual; other media must not reflow its geography.",
|
|
5529
5778
|
noMedia: "intrinsic-visual",
|
|
@@ -6198,12 +6447,144 @@ function leastObstructedMediaRect(layers, viewport) {
|
|
|
6198
6447
|
return score < bestScore ? candidate : best;
|
|
6199
6448
|
});
|
|
6200
6449
|
}
|
|
6450
|
+
var MEDIA_BANDS = {
|
|
6451
|
+
"feature-top": "top",
|
|
6452
|
+
"feature-bottom": "bottom",
|
|
6453
|
+
"full-frame": "full"
|
|
6454
|
+
};
|
|
6455
|
+
var BLOCK_GAP_EM = 0.55;
|
|
6456
|
+
function textLayer(layers, id) {
|
|
6457
|
+
const layer = layers.find((candidate) => candidate.id === id);
|
|
6458
|
+
return layer?.type === "text" ? layer : void 0;
|
|
6459
|
+
}
|
|
6460
|
+
function mediaBandLayout(layers, viewport, band, aspect) {
|
|
6461
|
+
const backdrop = layers.filter((layer) => isFullViewportBackground(layer, viewport));
|
|
6462
|
+
const title = textLayer(layers, "title");
|
|
6463
|
+
const body = textLayer(layers, "body");
|
|
6464
|
+
if (band === "full" || !title && !body) {
|
|
6465
|
+
return { layers: backdrop, mediaRect: rect(viewport, 0, 0, 1, 1), framed: false };
|
|
6466
|
+
}
|
|
6467
|
+
const { width, height } = viewport;
|
|
6468
|
+
const unit = Math.min(width, height);
|
|
6469
|
+
const margin = unit * 0.045;
|
|
6470
|
+
const gap = unit * 0.03;
|
|
6471
|
+
const innerGap = title && body ? unit * 0.02 : 0;
|
|
6472
|
+
const textWidth = width - margin * 2;
|
|
6473
|
+
const maxBandHeight = height * (body ? 0.4 : 0.2);
|
|
6474
|
+
const titleLineHeight = title?.content.style.lineHeight ?? 1.15;
|
|
6475
|
+
const titleBaseSize = Math.max(
|
|
6476
|
+
title?.content.style.fontSize ?? 0,
|
|
6477
|
+
Math.round((body?.content.style.fontSize ?? 0) * 1.2)
|
|
6478
|
+
);
|
|
6479
|
+
const titleWrapWidth = title ? Math.min(
|
|
6480
|
+
textWidth * 0.86,
|
|
6481
|
+
fitWrapWidth(
|
|
6482
|
+
title.content.text,
|
|
6483
|
+
titleBaseSize,
|
|
6484
|
+
textWidth,
|
|
6485
|
+
title.content.style.fontFamily ?? ""
|
|
6486
|
+
)
|
|
6487
|
+
) : textWidth;
|
|
6488
|
+
const titleFit = title ? fitProse({
|
|
6489
|
+
text: title.content.text,
|
|
6490
|
+
baseFontSize: titleBaseSize,
|
|
6491
|
+
minFontSize: Math.min(titleBaseSize, unit * 0.03),
|
|
6492
|
+
maxWidthPx: titleWrapWidth,
|
|
6493
|
+
maxHeightPx: body ? maxBandHeight * 0.35 : maxBandHeight,
|
|
6494
|
+
lineHeight: titleLineHeight
|
|
6495
|
+
}) : void 0;
|
|
6496
|
+
const titleHeight = titleFit?.heightPx ?? 0;
|
|
6497
|
+
const bodyRoom = maxBandHeight - titleHeight - innerGap;
|
|
6498
|
+
const bodyLineHeight = body?.content.style.lineHeight ?? 1.35;
|
|
6499
|
+
const blockGaps = body ? (body.content.text.match(/\n[^\S\n]*\n/g) ?? []).length : 0;
|
|
6500
|
+
const bodyBaseSize = body?.content.style.fontSize ?? 0;
|
|
6501
|
+
const headroomLines = 1;
|
|
6502
|
+
const bodyText3 = body?.content.text.replace(/\n[^\S\n]*\n/g, "\n") ?? "";
|
|
6503
|
+
const bodyFit = body ? fitProse({
|
|
6504
|
+
text: bodyText3,
|
|
6505
|
+
baseFontSize: bodyBaseSize,
|
|
6506
|
+
minFontSize: Math.min(bodyBaseSize, unit * 0.016),
|
|
6507
|
+
// HTML wraps on real glyphs; wide ones (CJK, emoji) fill lines in
|
|
6508
|
+
// half the characters the estimate assumes, so count lines narrower.
|
|
6509
|
+
maxWidthPx: fitWrapWidth(
|
|
6510
|
+
bodyText3,
|
|
6511
|
+
bodyBaseSize,
|
|
6512
|
+
textWidth,
|
|
6513
|
+
body.content.style.fontFamily ?? ""
|
|
6514
|
+
),
|
|
6515
|
+
maxHeightPx: bodyRoom - (blockGaps * BLOCK_GAP_EM + headroomLines * bodyLineHeight) * bodyBaseSize,
|
|
6516
|
+
lineHeight: bodyLineHeight
|
|
6517
|
+
}) : void 0;
|
|
6518
|
+
const bodyHeight = bodyFit ? Math.min(
|
|
6519
|
+
bodyRoom,
|
|
6520
|
+
bodyFit.heightPx + (blockGaps * BLOCK_GAP_EM + headroomLines * bodyLineHeight) * bodyFit.fontSize
|
|
6521
|
+
) : 0;
|
|
6522
|
+
const bandHeight = titleHeight + innerGap + bodyHeight;
|
|
6523
|
+
const roomForMedia = height - margin - gap - bandHeight;
|
|
6524
|
+
const mediaHeight = aspect && Number.isFinite(aspect) && aspect > 0 ? Math.min(roomForMedia, width / aspect) : roomForMedia;
|
|
6525
|
+
const offset = (roomForMedia - mediaHeight) / 2;
|
|
6526
|
+
const mediaTop = band === "top" ? offset : margin + offset + bandHeight + gap;
|
|
6527
|
+
const bandTop = band === "top" ? mediaTop + mediaHeight + gap : margin + offset;
|
|
6528
|
+
const placed = [...backdrop];
|
|
6529
|
+
if (title && titleFit) {
|
|
6530
|
+
placed.push({
|
|
6531
|
+
...title,
|
|
6532
|
+
position: {
|
|
6533
|
+
x: margin,
|
|
6534
|
+
y: bandTop,
|
|
6535
|
+
width: titleWrapWidth,
|
|
6536
|
+
height: titleHeight,
|
|
6537
|
+
anchor: "top-left"
|
|
6538
|
+
},
|
|
6539
|
+
content: {
|
|
6540
|
+
...title.content,
|
|
6541
|
+
style: {
|
|
6542
|
+
...title.content.style,
|
|
6543
|
+
fontSize: titleFit.fontSize,
|
|
6544
|
+
lineHeight: titleLineHeight,
|
|
6545
|
+
...titleFit.maxLines ? { maxLines: titleFit.maxLines } : {}
|
|
6546
|
+
}
|
|
6547
|
+
}
|
|
6548
|
+
});
|
|
6549
|
+
}
|
|
6550
|
+
if (body && bodyFit) {
|
|
6551
|
+
placed.push({
|
|
6552
|
+
...body,
|
|
6553
|
+
position: {
|
|
6554
|
+
x: margin,
|
|
6555
|
+
y: bandTop + titleHeight + innerGap,
|
|
6556
|
+
width: textWidth,
|
|
6557
|
+
height: bodyHeight,
|
|
6558
|
+
anchor: "top-left"
|
|
6559
|
+
},
|
|
6560
|
+
content: {
|
|
6561
|
+
...body.content,
|
|
6562
|
+
style: {
|
|
6563
|
+
...body.content.style,
|
|
6564
|
+
fontSize: bodyFit.fontSize,
|
|
6565
|
+
lineHeight: bodyLineHeight,
|
|
6566
|
+
...bodyFit.maxLines ? { maxLines: bodyFit.maxLines } : {}
|
|
6567
|
+
}
|
|
6568
|
+
}
|
|
6569
|
+
});
|
|
6570
|
+
}
|
|
6571
|
+
return {
|
|
6572
|
+
layers: placed,
|
|
6573
|
+
mediaRect: { x: 0, y: mediaTop, width, height: mediaHeight },
|
|
6574
|
+
framed: false
|
|
6575
|
+
};
|
|
6576
|
+
}
|
|
6201
6577
|
function resolveSupplementalMediaLayout(layers, template, viewport, mediaCount, aspectRatios, featureOptions = {}) {
|
|
6202
6578
|
const policy = getBlockMediaLayoutPolicy(template);
|
|
6203
6579
|
const shape = mediaShape(mediaCount, aspectRatios);
|
|
6204
6580
|
const alreadyOwnsMedia = layers.some(
|
|
6205
6581
|
(layer) => layer.type === "image" || layer.type === "video" || layer.type === "videoEmbed" || layer.type === "map" || layer.type === "mermaid" || layer.type === "svg"
|
|
6206
6582
|
);
|
|
6583
|
+
const band = policy?.nativeLayout ? MEDIA_BANDS[policy.nativeLayout] : void 0;
|
|
6584
|
+
if (band && !alreadyOwnsMedia) {
|
|
6585
|
+
const aspect = mediaCount === 1 ? featureOptions.knownAspectRatios?.[0] : void 0;
|
|
6586
|
+
return mediaBandLayout(layers, viewport, band, aspect);
|
|
6587
|
+
}
|
|
6207
6588
|
if (!alreadyOwnsMedia && (policy?.nativeLayout === "feature-left" || policy?.nativeLayout === "feature-right")) {
|
|
6208
6589
|
const { position } = featureMediaSlot(
|
|
6209
6590
|
policy.nativeLayout === "feature-left" ? "left" : "right",
|
|
@@ -6878,42 +7259,6 @@ function treeBlock(input, context) {
|
|
|
6878
7259
|
return layers;
|
|
6879
7260
|
}
|
|
6880
7261
|
|
|
6881
|
-
// src/doc/utils/textMetrics.ts
|
|
6882
|
-
var AVERAGE_CHAR_WIDTH_EM = 0.62;
|
|
6883
|
-
var BOLD_CHAR_WIDTH_EM = 0.66;
|
|
6884
|
-
function estimateTextWidth(text, fontSize, charWidthEm = AVERAGE_CHAR_WIDTH_EM) {
|
|
6885
|
-
return text.length * fontSize * charWidthEm;
|
|
6886
|
-
}
|
|
6887
|
-
var DISPLAY_CHAR_EM = {
|
|
6888
|
-
space: 0.27,
|
|
6889
|
-
narrowLower: 0.36,
|
|
6890
|
-
wideLower: 0.86,
|
|
6891
|
-
lower: 0.57,
|
|
6892
|
-
narrowUpper: 0.4,
|
|
6893
|
-
wideUpper: 0.95,
|
|
6894
|
-
upper: 0.7,
|
|
6895
|
-
digit: 0.57,
|
|
6896
|
-
punct: 0.34,
|
|
6897
|
-
other: 0.62
|
|
6898
|
-
};
|
|
6899
|
-
function displayCharEm(ch) {
|
|
6900
|
-
if (ch === " ") return DISPLAY_CHAR_EM.space;
|
|
6901
|
-
if ("fijlrt".includes(ch)) return DISPLAY_CHAR_EM.narrowLower;
|
|
6902
|
-
if (ch === "m" || ch === "w") return DISPLAY_CHAR_EM.wideLower;
|
|
6903
|
-
if (ch >= "a" && ch <= "z") return DISPLAY_CHAR_EM.lower;
|
|
6904
|
-
if (ch === "I" || ch === "J") return DISPLAY_CHAR_EM.narrowUpper;
|
|
6905
|
-
if (ch === "M" || ch === "W") return DISPLAY_CHAR_EM.wideUpper;
|
|
6906
|
-
if (ch >= "A" && ch <= "Z") return DISPLAY_CHAR_EM.upper;
|
|
6907
|
-
if (ch >= "0" && ch <= "9") return DISPLAY_CHAR_EM.digit;
|
|
6908
|
-
if (".,:;-/'\u2019!?()".includes(ch)) return DISPLAY_CHAR_EM.punct;
|
|
6909
|
-
return DISPLAY_CHAR_EM.other;
|
|
6910
|
-
}
|
|
6911
|
-
function estimateDisplayTextWidth(text, fontSize) {
|
|
6912
|
-
let em = 0;
|
|
6913
|
-
for (const ch of text.normalize("NFD").replace(/\p{M}/gu, "")) em += displayCharEm(ch);
|
|
6914
|
-
return em * fontSize;
|
|
6915
|
-
}
|
|
6916
|
-
|
|
6917
7262
|
// src/doc/templates/timelineBlock.ts
|
|
6918
7263
|
var clamp01 = (value) => Math.max(0, Math.min(1, value));
|
|
6919
7264
|
var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
@@ -7802,7 +8147,7 @@ function shapeLayers(s, x, y, w, h, context, defaultStroke, defaultFill, fontAdj
|
|
|
7802
8147
|
const fill = s.fill ?? defaultFill;
|
|
7803
8148
|
if (s.kind === "text") {
|
|
7804
8149
|
out.push(
|
|
7805
|
-
|
|
8150
|
+
textLayer2(
|
|
7806
8151
|
`shape-${s.id}`,
|
|
7807
8152
|
s.text ?? s.label ?? "",
|
|
7808
8153
|
x + w / 2,
|
|
@@ -7861,7 +8206,7 @@ function shapeLayers(s, x, y, w, h, context, defaultStroke, defaultFill, fontAdj
|
|
|
7861
8206
|
}
|
|
7862
8207
|
if (s.label) {
|
|
7863
8208
|
out.push(
|
|
7864
|
-
|
|
8209
|
+
textLayer2(
|
|
7865
8210
|
`shape-label-${s.id}`,
|
|
7866
8211
|
s.label,
|
|
7867
8212
|
x + w / 2,
|
|
@@ -7876,7 +8221,7 @@ function shapeLayers(s, x, y, w, h, context, defaultStroke, defaultFill, fontAdj
|
|
|
7876
8221
|
}
|
|
7877
8222
|
if (s.sublabel) {
|
|
7878
8223
|
out.push(
|
|
7879
|
-
|
|
8224
|
+
textLayer2(
|
|
7880
8225
|
`shape-sublabel-${s.id}`,
|
|
7881
8226
|
s.sublabel,
|
|
7882
8227
|
x + w / 2,
|
|
@@ -7891,7 +8236,7 @@ function shapeLayers(s, x, y, w, h, context, defaultStroke, defaultFill, fontAdj
|
|
|
7891
8236
|
}
|
|
7892
8237
|
return out;
|
|
7893
8238
|
}
|
|
7894
|
-
function
|
|
8239
|
+
function textLayer2(id, text, cx, cy, width, context, color, bold, fontAdj) {
|
|
7895
8240
|
return {
|
|
7896
8241
|
type: "text",
|
|
7897
8242
|
id,
|
|
@@ -8436,6 +8781,9 @@ var templateRegistry = {
|
|
|
8436
8781
|
imageWithCaption,
|
|
8437
8782
|
leftFeature,
|
|
8438
8783
|
rightFeature,
|
|
8784
|
+
topFeature,
|
|
8785
|
+
bottomFeature,
|
|
8786
|
+
mediaOnly,
|
|
8439
8787
|
map: mapBlock,
|
|
8440
8788
|
fullBleedQuote,
|
|
8441
8789
|
list: listBlock,
|
|
@@ -8754,6 +9102,9 @@ var TEMPLATE_INPUT_DESCRIPTORS = {
|
|
|
8754
9102
|
],
|
|
8755
9103
|
leftFeature: FEATURE_DESCRIPTORS(),
|
|
8756
9104
|
rightFeature: FEATURE_DESCRIPTORS(),
|
|
9105
|
+
topFeature: [{ key: "title", description: "Heading shown with the body under the media" }],
|
|
9106
|
+
bottomFeature: [{ key: "title", description: "Heading shown with the body above the media" }],
|
|
9107
|
+
mediaOnly: [{ key: "title", description: "Heading, shown only when the block has no media" }],
|
|
8757
9108
|
map: [
|
|
8758
9109
|
{
|
|
8759
9110
|
key: "center",
|
|
@@ -9450,11 +9801,13 @@ function appendRichContentLayers(layers, block, theme, viewport, mediaAspectRati
|
|
|
9450
9801
|
const timedLayers = applyEmbeddedVideoTiming(layers, block);
|
|
9451
9802
|
const items = collectRichMediaItems(timedLayers, block);
|
|
9452
9803
|
if (items.length === 0) return timedLayers;
|
|
9453
|
-
const
|
|
9804
|
+
const knownAspects = items.map((item) => {
|
|
9454
9805
|
const key = item.kind === "image" || item.kind === "video" ? item.src : item.kind === "mermaid" ? item.source : void 0;
|
|
9455
9806
|
const intrinsic = key ? mediaAspectRatios?.[key] : void 0;
|
|
9456
|
-
|
|
9807
|
+
if (intrinsic && Number.isFinite(intrinsic) && intrinsic > 0) return intrinsic;
|
|
9808
|
+
return item.kind === "video" ? void 0 : item.aspectRatio;
|
|
9457
9809
|
});
|
|
9810
|
+
const aspects = items.map((item, index) => knownAspects[index] ?? item.aspectRatio);
|
|
9458
9811
|
const layout = block.summaryLayout === "feature" ? resolveFeatureSummaryLayout(timedLayers, viewport, aspects) : resolveSupplementalMediaLayout(
|
|
9459
9812
|
timedLayers,
|
|
9460
9813
|
block.template ? resolveTemplateName(block.template) : void 0,
|
|
@@ -9463,7 +9816,8 @@ function appendRichContentLayers(layers, block, theme, viewport, mediaAspectRati
|
|
|
9463
9816
|
aspects,
|
|
9464
9817
|
{
|
|
9465
9818
|
summaryFeature: block.summaryMode === "headings-and-features" && !timedLayers.some((layer) => layer.id === "feature-body"),
|
|
9466
|
-
stackColumns: createTemplateContext(theme, 0, 1, viewport).layout.stackColumns
|
|
9819
|
+
stackColumns: createTemplateContext(theme, 0, 1, viewport).layout.stackColumns,
|
|
9820
|
+
knownAspectRatios: knownAspects
|
|
9467
9821
|
}
|
|
9468
9822
|
);
|
|
9469
9823
|
const cells = gridCells(layout.mediaRect, items.length, viewport, layout.framed);
|
|
@@ -9625,6 +9979,18 @@ var TEMPLATE_METADATA = {
|
|
|
9625
9979
|
label: "Right Feature",
|
|
9626
9980
|
description: "Image on the right, title and body text stacked on the left."
|
|
9627
9981
|
},
|
|
9982
|
+
topFeature: {
|
|
9983
|
+
label: "Top Feature",
|
|
9984
|
+
description: "Image or video across the full width at the top, title and body text below."
|
|
9985
|
+
},
|
|
9986
|
+
bottomFeature: {
|
|
9987
|
+
label: "Bottom Feature",
|
|
9988
|
+
description: "Title and body text at the top, image or video across the full width below."
|
|
9989
|
+
},
|
|
9990
|
+
mediaOnly: {
|
|
9991
|
+
label: "Media Only",
|
|
9992
|
+
description: "The image or video fills the slide, with no title, text or caption."
|
|
9993
|
+
},
|
|
9628
9994
|
map: {
|
|
9629
9995
|
label: "Map",
|
|
9630
9996
|
description: "Embeds an interactive map centered on a geographic location."
|
|
@@ -9790,6 +10156,24 @@ var TEMPLATE_AUTHORING_METADATA = {
|
|
|
9790
10156
|
safeForContentFirst: false,
|
|
9791
10157
|
placement: "heading"
|
|
9792
10158
|
},
|
|
10159
|
+
topFeature: {
|
|
10160
|
+
role: "media",
|
|
10161
|
+
bodyPolicy: "complete",
|
|
10162
|
+
safeForContentFirst: false,
|
|
10163
|
+
placement: "heading"
|
|
10164
|
+
},
|
|
10165
|
+
bottomFeature: {
|
|
10166
|
+
role: "media",
|
|
10167
|
+
bodyPolicy: "complete",
|
|
10168
|
+
safeForContentFirst: false,
|
|
10169
|
+
placement: "heading"
|
|
10170
|
+
},
|
|
10171
|
+
mediaOnly: {
|
|
10172
|
+
role: "media",
|
|
10173
|
+
bodyPolicy: "ignored",
|
|
10174
|
+
safeForContentFirst: false,
|
|
10175
|
+
placement: "heading"
|
|
10176
|
+
},
|
|
9793
10177
|
map: {
|
|
9794
10178
|
role: "spatial",
|
|
9795
10179
|
bodyPolicy: "structured",
|
|
@@ -9953,53 +10337,8 @@ function coverScrimGradient(background) {
|
|
|
9953
10337
|
var FROSTED_LINE_HEIGHT = 1.12;
|
|
9954
10338
|
var FROSTED_MAX_LINES = 3;
|
|
9955
10339
|
var FROSTED_SQUARE_SHARE = 0.9;
|
|
9956
|
-
var FROSTED_PAD_X_EM = 0.45;
|
|
9957
|
-
var FROSTED_PAD_Y_EM = 0.3;
|
|
9958
|
-
var FROSTED_RADIUS_EM = 0.3;
|
|
9959
|
-
var FROSTED_BLUR_SHARE = 0.0167;
|
|
9960
10340
|
var FROSTED_BOTTOM_MARGIN_PCT = { wide: 7, tall: 17 };
|
|
9961
|
-
var FROSTED_TINT_UNDER_LIGHT_TEXT = "rgba(12, 12, 14, 0.26)";
|
|
9962
|
-
var FROSTED_TINT_UNDER_DARK_TEXT = "rgba(250, 250, 250, 0.5)";
|
|
9963
|
-
var FROSTED_BACKDROP_CONTRAST = 0.65;
|
|
9964
10341
|
var COVER_SUBTITLE_BASE_PX = 40;
|
|
9965
|
-
var INK_EM = { xHeight: 0.45, ascent: 0.71, accentedCapital: 0.8, descent: 0.165 };
|
|
9966
|
-
function opticalCentreShiftEm(lines) {
|
|
9967
|
-
const first = (lines[0] ?? "").normalize("NFD");
|
|
9968
|
-
const last = lines[lines.length - 1] ?? "";
|
|
9969
|
-
const top = /[A-Z]\p{M}/u.test(first) ? INK_EM.accentedCapital : /[A-Zbdfhklt0-9]|[a-z]\p{M}/u.test(first) ? INK_EM.ascent : INK_EM.xHeight;
|
|
9970
|
-
const bottom = /[gjpqyQ,;]/.test(last) ? INK_EM.descent : 0;
|
|
9971
|
-
return Math.round(((top - bottom) / 2 - INK_EM.xHeight / 2) * 1e3) / 1e3;
|
|
9972
|
-
}
|
|
9973
|
-
function wrapDisplayLine(line, fontSize, maxWidth) {
|
|
9974
|
-
const lines = [];
|
|
9975
|
-
let current = "";
|
|
9976
|
-
for (const word of line.trim().split(/\s+/).filter(Boolean)) {
|
|
9977
|
-
const candidate = current ? `${current} ${word}` : word;
|
|
9978
|
-
if (!current || estimateDisplayTextWidth(candidate, fontSize) <= maxWidth) {
|
|
9979
|
-
current = candidate;
|
|
9980
|
-
} else {
|
|
9981
|
-
lines.push(current);
|
|
9982
|
-
current = word;
|
|
9983
|
-
}
|
|
9984
|
-
}
|
|
9985
|
-
if (current) lines.push(current);
|
|
9986
|
-
return lines.length > 0 ? lines : [""];
|
|
9987
|
-
}
|
|
9988
|
-
function balancedDisplayLines(line, fontSize, maxWidth) {
|
|
9989
|
-
const greedy = wrapDisplayLine(line, fontSize, maxWidth);
|
|
9990
|
-
if (greedy.length < 2) return greedy;
|
|
9991
|
-
let lo = Math.max(
|
|
9992
|
-
...line.split(/\s+/).filter(Boolean).map((word) => estimateDisplayTextWidth(word, fontSize))
|
|
9993
|
-
);
|
|
9994
|
-
let hi = maxWidth;
|
|
9995
|
-
if (lo >= hi) return greedy;
|
|
9996
|
-
while (hi - lo > 0.5) {
|
|
9997
|
-
const mid = (lo + hi) / 2;
|
|
9998
|
-
if (wrapDisplayLine(line, fontSize, mid).length <= greedy.length) hi = mid;
|
|
9999
|
-
else lo = mid;
|
|
10000
|
-
}
|
|
10001
|
-
return wrapDisplayLine(line, fontSize, hi);
|
|
10002
|
-
}
|
|
10003
10342
|
function frostedCoverLayout(title, subtitle, context) {
|
|
10004
10343
|
const { width: frameW, height: frameH } = context.viewport;
|
|
10005
10344
|
const shortSide = Math.min(frameW, frameH);
|
|
@@ -10043,8 +10382,6 @@ function frostedCoverLayout(title, subtitle, context) {
|
|
|
10043
10382
|
const plateBottom = frameH * (1 - marginPct / 100);
|
|
10044
10383
|
const plateY = plateBottom - plateHeight;
|
|
10045
10384
|
const cx = frameW / 2;
|
|
10046
|
-
const longestChars = Math.max(...lines.map((line) => line.length));
|
|
10047
|
-
const titleBoxWidth = Math.max(textWidth, longestChars * fontSize * 0.5 + 1);
|
|
10048
10385
|
return {
|
|
10049
10386
|
fontSize,
|
|
10050
10387
|
lines,
|
|
@@ -10061,7 +10398,7 @@ function frostedCoverLayout(title, subtitle, context) {
|
|
|
10061
10398
|
title: {
|
|
10062
10399
|
cx,
|
|
10063
10400
|
cy: plateY + padY + textHeight / 2,
|
|
10064
|
-
width:
|
|
10401
|
+
width: frostedTitleBoxWidth(lines, fontSize, textWidth),
|
|
10065
10402
|
height: textHeight + 2 * padY
|
|
10066
10403
|
},
|
|
10067
10404
|
...sub ? {
|
|
@@ -10078,35 +10415,15 @@ function frostedCoverLayout(title, subtitle, context) {
|
|
|
10078
10415
|
}
|
|
10079
10416
|
} : {},
|
|
10080
10417
|
baselineShift: opticalCentreShiftEm(lines),
|
|
10081
|
-
blur:
|
|
10418
|
+
blur: frostedBlurPx(context)
|
|
10082
10419
|
};
|
|
10083
10420
|
}
|
|
10084
|
-
function pct(value, total) {
|
|
10085
|
-
return `${Math.round(value / total * 1e4) / 100}%`;
|
|
10086
|
-
}
|
|
10087
10421
|
function frostedCoverLayers(input, context) {
|
|
10088
10422
|
const { theme, viewport } = context;
|
|
10089
10423
|
const layout = frostedCoverLayout(input.title, input.subtitle, context);
|
|
10090
|
-
const lightText =
|
|
10091
|
-
const { plate } = layout;
|
|
10424
|
+
const lightText = frostedUnderLightText(context);
|
|
10092
10425
|
const layers = [
|
|
10093
|
-
|
|
10094
|
-
type: "shape",
|
|
10095
|
-
id: "cover-plate",
|
|
10096
|
-
content: {
|
|
10097
|
-
shape: "rect",
|
|
10098
|
-
fill: lightText ? FROSTED_TINT_UNDER_LIGHT_TEXT : FROSTED_TINT_UNDER_DARK_TEXT,
|
|
10099
|
-
borderRadius: Math.round(plate.radius),
|
|
10100
|
-
backdropBlur: layout.blur,
|
|
10101
|
-
...lightText ? { backdropContrast: FROSTED_BACKDROP_CONTRAST } : {}
|
|
10102
|
-
},
|
|
10103
|
-
position: {
|
|
10104
|
-
x: pct(plate.x, viewport.width),
|
|
10105
|
-
y: pct(plate.y, viewport.height),
|
|
10106
|
-
width: pct(plate.width, viewport.width),
|
|
10107
|
-
height: pct(plate.height, viewport.height)
|
|
10108
|
-
}
|
|
10109
|
-
},
|
|
10426
|
+
frostedPlateLayer("cover-plate", layout.plate, context),
|
|
10110
10427
|
{
|
|
10111
10428
|
type: "text",
|
|
10112
10429
|
id: "cover-title",
|
|
@@ -10896,193 +11213,6 @@ function extractTableData(table) {
|
|
|
10896
11213
|
};
|
|
10897
11214
|
}
|
|
10898
11215
|
|
|
10899
|
-
// src/doc/standaloneAnnotation.ts
|
|
10900
|
-
function parseAnnotationInner(inner) {
|
|
10901
|
-
const tokens = tokenizeAttrTokens(inner.trim());
|
|
10902
|
-
const firstIsParam = tokens.length > 0 && tokens[0].indexOf("=") > 0;
|
|
10903
|
-
const template = firstIsParam || tokens.length === 0 ? void 0 : tokens[0];
|
|
10904
|
-
const startIdx = firstIsParam ? 0 : 1;
|
|
10905
|
-
const params = {};
|
|
10906
|
-
for (let i = startIdx; i < tokens.length; i++) {
|
|
10907
|
-
const kv = splitKeyValueToken(tokens[i]);
|
|
10908
|
-
if (kv) params[kv.key] = kv.value;
|
|
10909
|
-
}
|
|
10910
|
-
return { template, params };
|
|
10911
|
-
}
|
|
10912
|
-
function parseStandaloneAnnotation(node) {
|
|
10913
|
-
if (node.type !== "paragraph") return null;
|
|
10914
|
-
const children = node.children ?? [];
|
|
10915
|
-
if (children.length !== 1 || children[0].type !== "text") return null;
|
|
10916
|
-
const text = children[0].value.trim();
|
|
10917
|
-
const match = matchTrailingTemplateAnnotation(text);
|
|
10918
|
-
if (!match || match.index !== 0) return null;
|
|
10919
|
-
return parseAnnotationInner(match.inner);
|
|
10920
|
-
}
|
|
10921
|
-
|
|
10922
|
-
// src/doc/mediaAnnotations.ts
|
|
10923
|
-
var MEDIA_TEMPLATES = /* @__PURE__ */ new Set(["audio", "video", "media"]);
|
|
10924
|
-
function isMediaAnnotationName(name) {
|
|
10925
|
-
return name != null && MEDIA_TEMPLATES.has(name);
|
|
10926
|
-
}
|
|
10927
|
-
function time(raw) {
|
|
10928
|
-
if (raw == null) return null;
|
|
10929
|
-
return parseTimeSeconds(raw);
|
|
10930
|
-
}
|
|
10931
|
-
function videoPlacement(params) {
|
|
10932
|
-
const explicit = params.placement ?? params.presentation;
|
|
10933
|
-
if (explicit === "content") return "content";
|
|
10934
|
-
if (explicit === "pip" || explicit === "picture-in-picture") return "picture-in-picture";
|
|
10935
|
-
if (explicit === "overlay" || explicit === "full-frame") return "overlay";
|
|
10936
|
-
if (params.pip === "" || params.pip === "true") return "picture-in-picture";
|
|
10937
|
-
if (params.overlay === "" || params.overlay === "true") return "overlay";
|
|
10938
|
-
return void 0;
|
|
10939
|
-
}
|
|
10940
|
-
function lockToBlock(raw) {
|
|
10941
|
-
return raw !== "false" && raw !== "0";
|
|
10942
|
-
}
|
|
10943
|
-
function videoPipSize(raw) {
|
|
10944
|
-
return raw === "small" || raw === "large" ? raw : void 0;
|
|
10945
|
-
}
|
|
10946
|
-
function videoPipShape(raw) {
|
|
10947
|
-
return raw === "square" || raw === "wide" ? raw : void 0;
|
|
10948
|
-
}
|
|
10949
|
-
function videoPipPosition(raw) {
|
|
10950
|
-
return raw === "top-left" || raw === "top-right" || raw === "bottom-left" || raw === "bottom-right" ? raw : void 0;
|
|
10951
|
-
}
|
|
10952
|
-
function toMediaClip(parsed, id) {
|
|
10953
|
-
const { template, params } = parsed;
|
|
10954
|
-
if (!template || !MEDIA_TEMPLATES.has(template)) return null;
|
|
10955
|
-
const src = params.src;
|
|
10956
|
-
if (!src) return null;
|
|
10957
|
-
const kind = template === "video" ? "video" : "audio";
|
|
10958
|
-
const anchor = params.anchor === "document" || params.span === "document" ? "document" : "block";
|
|
10959
|
-
const clip = {
|
|
10960
|
-
id,
|
|
10961
|
-
src,
|
|
10962
|
-
kind,
|
|
10963
|
-
startAt: time(params.startAt ?? params.startTime) ?? 0,
|
|
10964
|
-
anchor
|
|
10965
|
-
};
|
|
10966
|
-
const placement = kind === "video" ? videoPlacement(params) : void 0;
|
|
10967
|
-
if (placement && placement !== "content") clip.placement = placement;
|
|
10968
|
-
const pipSize = videoPipSize(params.pipSize);
|
|
10969
|
-
const pipShape = videoPipShape(params.pipShape);
|
|
10970
|
-
const pipPosition = videoPipPosition(params.pipPosition);
|
|
10971
|
-
if (pipSize) clip.pipSize = pipSize;
|
|
10972
|
-
if (pipShape) clip.pipShape = pipShape;
|
|
10973
|
-
if (pipPosition) clip.pipPosition = pipPosition;
|
|
10974
|
-
if (kind === "video" && placement && placement !== "content" && params.lockToBlock != null) {
|
|
10975
|
-
const locked = lockToBlock(params.lockToBlock);
|
|
10976
|
-
clip.lockToBlock = locked;
|
|
10977
|
-
clip.anchor = locked ? "block" : "document";
|
|
10978
|
-
if (locked) clip.startAt = 0;
|
|
10979
|
-
}
|
|
10980
|
-
const clipStart = time(params.clipStart);
|
|
10981
|
-
const clipEnd = time(params.clipEnd);
|
|
10982
|
-
if (clipStart != null) clip.clipStart = clipStart;
|
|
10983
|
-
if (clipEnd != null) clip.clipEnd = clipEnd;
|
|
10984
|
-
if (clip.lockToBlock === true) delete clip.clipEnd;
|
|
10985
|
-
if (params.spillover === "true" || params.spillover === "") clip.spillover = true;
|
|
10986
|
-
const edits = parseMediaEdits(mediaEditValuesFromParams(params));
|
|
10987
|
-
if (edits) clip.edits = edits;
|
|
10988
|
-
return clip;
|
|
10989
|
-
}
|
|
10990
|
-
function firstVideoElement(children) {
|
|
10991
|
-
const visit = (nodes) => {
|
|
10992
|
-
for (const child of nodes) {
|
|
10993
|
-
if (child.type !== "htmlElement") continue;
|
|
10994
|
-
if (child.tagName === "video") return child;
|
|
10995
|
-
const nested = visit(child.children);
|
|
10996
|
-
if (nested) return nested;
|
|
10997
|
-
}
|
|
10998
|
-
return null;
|
|
10999
|
-
};
|
|
11000
|
-
return visit(children);
|
|
11001
|
-
}
|
|
11002
|
-
function standaloneHtmlVideo(node) {
|
|
11003
|
-
if (node.type === "htmlBlock") {
|
|
11004
|
-
if (!/^\s*<video\b/i.test(node.rawHtml)) return null;
|
|
11005
|
-
const element = firstVideoElement(node.htmlChildren);
|
|
11006
|
-
return element ? { element, raw: node.rawHtml.trim() } : null;
|
|
11007
|
-
}
|
|
11008
|
-
if (node.type !== "paragraph" || !node.children.every((child) => child.type === "htmlInline")) {
|
|
11009
|
-
return null;
|
|
11010
|
-
}
|
|
11011
|
-
const raw = node.children.map((child) => child.type === "htmlInline" ? child.rawHtml : "").join("");
|
|
11012
|
-
if (!/^\s*<video\b[\s\S]*<\/video>\s*$/i.test(raw)) return null;
|
|
11013
|
-
for (const child of node.children) {
|
|
11014
|
-
if (child.type !== "htmlInline") continue;
|
|
11015
|
-
const element = firstVideoElement(child.htmlChildren);
|
|
11016
|
-
if (element) return { element, raw: raw.trim() };
|
|
11017
|
-
}
|
|
11018
|
-
return null;
|
|
11019
|
-
}
|
|
11020
|
-
function htmlVideoClip(node, id) {
|
|
11021
|
-
const authored = standaloneHtmlVideo(node);
|
|
11022
|
-
if (!authored) return null;
|
|
11023
|
-
const { element } = authored;
|
|
11024
|
-
const placement = videoPlacement({
|
|
11025
|
-
placement: element.attributes["data-squisq-video-placement"] ?? ""
|
|
11026
|
-
});
|
|
11027
|
-
if (!placement || placement === "content") return null;
|
|
11028
|
-
const src = element.attributes.src;
|
|
11029
|
-
if (!src) return null;
|
|
11030
|
-
const locked = lockToBlock(element.attributes["data-squisq-video-lock-to-block"]);
|
|
11031
|
-
const clip = {
|
|
11032
|
-
id,
|
|
11033
|
-
src,
|
|
11034
|
-
kind: "video",
|
|
11035
|
-
placement,
|
|
11036
|
-
lockToBlock: locked,
|
|
11037
|
-
startAt: locked ? 0 : time(element.attributes["data-squisq-video-start-at"]) ?? 0,
|
|
11038
|
-
anchor: locked ? "block" : "document"
|
|
11039
|
-
};
|
|
11040
|
-
const pipSize = videoPipSize(element.attributes["data-squisq-video-pip-size"]);
|
|
11041
|
-
const pipShape = videoPipShape(element.attributes["data-squisq-video-pip-shape"]);
|
|
11042
|
-
const pipPosition = videoPipPosition(element.attributes["data-squisq-video-pip-position"]);
|
|
11043
|
-
if (pipSize) clip.pipSize = pipSize;
|
|
11044
|
-
if (pipShape) clip.pipShape = pipShape;
|
|
11045
|
-
if (pipPosition) clip.pipPosition = pipPosition;
|
|
11046
|
-
const clipStart = time(element.attributes["data-squisq-video-clip-start"]);
|
|
11047
|
-
const clipEnd = time(element.attributes["data-squisq-video-clip-end"]);
|
|
11048
|
-
if (clipStart != null) clip.clipStart = clipStart;
|
|
11049
|
-
if (!locked && clipEnd != null) clip.clipEnd = clipEnd;
|
|
11050
|
-
const edits = parseMediaEdits(mediaEditValuesFromAttributes("video", element.attributes));
|
|
11051
|
-
if (edits) clip.edits = edits;
|
|
11052
|
-
return clip;
|
|
11053
|
-
}
|
|
11054
|
-
function extractMediaFromContents(contents, makeId, blockId) {
|
|
11055
|
-
const media = [];
|
|
11056
|
-
const documentMedia = [];
|
|
11057
|
-
const remaining = [];
|
|
11058
|
-
let index = 0;
|
|
11059
|
-
let originalIndex = 0;
|
|
11060
|
-
for (const node of contents ?? []) {
|
|
11061
|
-
const parsed = parseStandaloneAnnotation(node);
|
|
11062
|
-
const clip = parsed ? toMediaClip(parsed, "") : htmlVideoClip(node, "");
|
|
11063
|
-
if (clip) {
|
|
11064
|
-
clip.id = makeId(clip.src, index++);
|
|
11065
|
-
const line = node.position?.start.line;
|
|
11066
|
-
if (line != null) clip.sourceLine = line;
|
|
11067
|
-
if (blockId !== void 0) {
|
|
11068
|
-
const authoredHtml = standaloneHtmlVideo(node);
|
|
11069
|
-
const rawText = node.type === "paragraph" && node.children?.[0]?.type === "text" ? node.children[0].value.trim() : authoredHtml?.raw;
|
|
11070
|
-
clip.origin = {
|
|
11071
|
-
blockId,
|
|
11072
|
-
index: originalIndex,
|
|
11073
|
-
...rawText !== void 0 ? { raw: rawText } : {},
|
|
11074
|
-
...authoredHtml ? { format: "html" } : {}
|
|
11075
|
-
};
|
|
11076
|
-
}
|
|
11077
|
-
(clip.anchor === "document" ? documentMedia : media).push(clip);
|
|
11078
|
-
} else {
|
|
11079
|
-
remaining.push(node);
|
|
11080
|
-
}
|
|
11081
|
-
originalIndex++;
|
|
11082
|
-
}
|
|
11083
|
-
return { media, documentMedia, remaining };
|
|
11084
|
-
}
|
|
11085
|
-
|
|
11086
11216
|
// src/doc/annotationBlocks.ts
|
|
11087
11217
|
function applyBlockMeta(block, m) {
|
|
11088
11218
|
if (m.build) block.build = m.build;
|
|
@@ -12084,7 +12214,7 @@ function resolveBuildTimeline(steps, spec, duration, timing) {
|
|
|
12084
12214
|
let consumed = 0;
|
|
12085
12215
|
let previous = 0;
|
|
12086
12216
|
const matched = timing?.sourceText === buildSourceText(steps) && timing.starts.length === steps.length && timing.starts.every(
|
|
12087
|
-
(
|
|
12217
|
+
(time, i) => Number.isFinite(time) && time >= 0 && (i === 0 || time >= timing.starts[i - 1])
|
|
12088
12218
|
);
|
|
12089
12219
|
const starts = steps.map((_, i) => {
|
|
12090
12220
|
const automatic = intro + Math.max(0, latest - intro) * consumed / Math.max(1, total);
|
|
@@ -12101,15 +12231,15 @@ function resolveBuildTimeline(steps, spec, duration, timing) {
|
|
|
12101
12231
|
);
|
|
12102
12232
|
return { starts, entrance, compressed: steps.length > 0 && end < steps.length * 0.8 };
|
|
12103
12233
|
}
|
|
12104
|
-
function buildCursorAtTime(timeline,
|
|
12234
|
+
function buildCursorAtTime(timeline, time) {
|
|
12105
12235
|
let revealed = 0;
|
|
12106
12236
|
for (const start of timeline.starts) {
|
|
12107
|
-
if (
|
|
12237
|
+
if (time < start) break;
|
|
12108
12238
|
revealed++;
|
|
12109
12239
|
}
|
|
12110
12240
|
return {
|
|
12111
12241
|
revealed,
|
|
12112
|
-
progress: revealed === 0 ? 0 : timeline.entrance === 0 ? 1 : Math.min(1, Math.max(0, (
|
|
12242
|
+
progress: revealed === 0 ? 0 : timeline.entrance === 0 ? 1 : Math.min(1, Math.max(0, (time - timeline.starts[revealed - 1]) / timeline.entrance))
|
|
12113
12243
|
};
|
|
12114
12244
|
}
|
|
12115
12245
|
function buildTargetState(index, steps, cursor, spec, motion = true) {
|
|
@@ -12180,13 +12310,13 @@ function resolveDocBuildTiming(doc, blocks) {
|
|
|
12180
12310
|
}
|
|
12181
12311
|
|
|
12182
12312
|
// src/doc/templates/contentBlock.ts
|
|
12183
|
-
function bodyNodes(context) {
|
|
12313
|
+
function bodyNodes(context, omitPictures) {
|
|
12184
12314
|
if (context.block?.summaryMode === "headings-and-features") return [];
|
|
12185
12315
|
return (context.block?.contents ?? []).filter(
|
|
12186
12316
|
// Mermaid source and hosted-video links are already materialized as
|
|
12187
12317
|
// visual layers (a diagram, a player). Repeating them as prose makes the
|
|
12188
12318
|
// loss-averse default noisy without preserving any additional meaning.
|
|
12189
|
-
(node) => !isMaterializedMediaNode(node)
|
|
12319
|
+
(node) => !isMaterializedMediaNode(node) && !(omitPictures && isPictureParagraph(node))
|
|
12190
12320
|
);
|
|
12191
12321
|
}
|
|
12192
12322
|
function listParagraphs(list, level = 0) {
|
|
@@ -12231,10 +12361,10 @@ function bodyFontSize(body, context) {
|
|
|
12231
12361
|
const base = body.length > 1800 ? 18 : body.length > 1100 ? 21 : body.length > 650 ? 24 : 28;
|
|
12232
12362
|
return themedFontSize(base, context, false);
|
|
12233
12363
|
}
|
|
12234
|
-
function contentBlock(input, context) {
|
|
12364
|
+
function contentBlock(input, context, options = {}) {
|
|
12235
12365
|
const { theme } = context;
|
|
12236
12366
|
const title = input.title ?? context.block?.title ?? "";
|
|
12237
|
-
const markdown = bodyNodes(context);
|
|
12367
|
+
const markdown = bodyNodes(context, options.omitPictures === true);
|
|
12238
12368
|
const paragraphs = completeBodyParagraphs(markdown);
|
|
12239
12369
|
const body = paragraphs.map(plainParagraphText).join("\n");
|
|
12240
12370
|
const builds = planContentBuilds(markdown, input.build ?? context.block?.build);
|
|
@@ -12322,6 +12452,7 @@ export {
|
|
|
12322
12452
|
adjustY,
|
|
12323
12453
|
sectionHeader,
|
|
12324
12454
|
fitBigTextSize,
|
|
12455
|
+
frostedBigTextLayout,
|
|
12325
12456
|
bigText,
|
|
12326
12457
|
contentBlock,
|
|
12327
12458
|
parseStatNumber,
|
|
@@ -12336,6 +12467,9 @@ export {
|
|
|
12336
12467
|
imageWithCaption,
|
|
12337
12468
|
leftFeature,
|
|
12338
12469
|
rightFeature,
|
|
12470
|
+
topFeature,
|
|
12471
|
+
bottomFeature,
|
|
12472
|
+
mediaOnly,
|
|
12339
12473
|
mapBlock,
|
|
12340
12474
|
fullBleedQuote,
|
|
12341
12475
|
listBlock,
|
|
@@ -12392,7 +12526,6 @@ export {
|
|
|
12392
12526
|
parseYamlSubset,
|
|
12393
12527
|
findFirstTable,
|
|
12394
12528
|
extractTableData,
|
|
12395
|
-
parseStandaloneAnnotation,
|
|
12396
12529
|
getPinnedBlockMeta,
|
|
12397
12530
|
markdownToDoc,
|
|
12398
12531
|
flattenBlocks,
|