@bendyline/squisq 2.13.9 → 2.13.10
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-BCrrYAuK.d.ts → Doc-DqYt_b2b.d.ts} +14 -1
- package/dist/{ImageEditDoc-CSuevovH.d.ts → ImageEditDoc-CXXiXVJ-.d.ts} +1 -1
- package/dist/{chunk-R2J7CQJZ.js → chunk-DIY3NBIS.js} +24 -11
- package/dist/{chunk-3BIKSQTM.js → chunk-FXQ7C2FF.js} +17 -1
- package/dist/{chunk-FTN6SGW5.js → chunk-HKHOFTGM.js} +10 -0
- package/dist/{chunk-VMKRN7TB.js → chunk-KRMAEYNM.js} +232 -59
- package/dist/{chunk-L3VQQ3WT.js → chunk-LWNT6M4N.js} +19 -14
- package/dist/{chunk-QVNMPBS3.js → chunk-WK6LEZ3U.js} +25 -9
- package/dist/doc/index.d.ts +14 -15
- package/dist/doc/index.js +7 -5
- 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 +7 -7
- package/dist/index.js +20 -6
- package/dist/jsonForm/index.d.ts +1 -1
- package/dist/{materializePageSection-FT1B5NOo.d.ts → materializePageSection-S2hxZ_lO.d.ts} +1 -1
- package/dist/mediaEdit/index.d.ts +2 -2
- package/dist/narration/index.d.ts +28 -2
- package/dist/narration/index.js +8 -4
- package/dist/recommend/index.js +1 -1
- package/dist/schemas/index.d.ts +4 -4
- package/dist/{themeLibrary-BWvtBQ42.d.ts → themeLibrary-CFJbeItn.d.ts} +1 -1
- package/dist/timing/index.d.ts +1 -1
- package/dist/transform/index.d.ts +43 -7
- package/dist/transform/index.js +11 -3
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
flattenRenderableBlocks,
|
|
5
5
|
getPinnedBlockMeta,
|
|
6
6
|
markdownToDoc
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LWNT6M4N.js";
|
|
8
8
|
import {
|
|
9
9
|
deriveTemplateInputs,
|
|
10
10
|
extractEmbeddedVideos,
|
|
@@ -17,8 +17,9 @@ import {
|
|
|
17
17
|
isPictureFence,
|
|
18
18
|
isPictureParagraph,
|
|
19
19
|
isStandaloneHtmlVideo,
|
|
20
|
-
isTreeFence
|
|
21
|
-
|
|
20
|
+
isTreeFence,
|
|
21
|
+
matchNumberHighlight
|
|
22
|
+
} from "./chunk-DIY3NBIS.js";
|
|
22
23
|
import {
|
|
23
24
|
extractContent,
|
|
24
25
|
mapElementToBlock,
|
|
@@ -57,12 +58,46 @@ import {
|
|
|
57
58
|
var PRESENTATION_KEY = "squisq-presentation";
|
|
58
59
|
var PRESENTATION_LAYOUTS = [
|
|
59
60
|
"title",
|
|
61
|
+
"divider",
|
|
60
62
|
"statement",
|
|
63
|
+
"emphasis",
|
|
64
|
+
"quote",
|
|
65
|
+
"stat",
|
|
66
|
+
"definition",
|
|
61
67
|
"list",
|
|
62
68
|
"comparison",
|
|
63
69
|
"steps",
|
|
64
70
|
"image"
|
|
65
71
|
];
|
|
72
|
+
var AUTHORED_PRESENTATION_LAYOUT = "authored";
|
|
73
|
+
var EMPHASIS_CHARACTERS = 60;
|
|
74
|
+
var spaced = (text3) => text3.replace(/\s+/gu, " ").trim();
|
|
75
|
+
function presentationStat(headline, points) {
|
|
76
|
+
for (const [index, line] of [headline, ...points].entries()) {
|
|
77
|
+
const match = matchNumberHighlight(line);
|
|
78
|
+
if (match) return { match, line, index: index - 1 };
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
function presentationLayoutFits(layout, headline, points, passage) {
|
|
83
|
+
switch (layout) {
|
|
84
|
+
case "list":
|
|
85
|
+
case "steps":
|
|
86
|
+
return points.length >= 2;
|
|
87
|
+
case "comparison":
|
|
88
|
+
return points.length === 2;
|
|
89
|
+
case "definition":
|
|
90
|
+
return points.length >= 1;
|
|
91
|
+
case "stat":
|
|
92
|
+
return presentationStat(headline, points) !== null;
|
|
93
|
+
case "emphasis":
|
|
94
|
+
return headline.length <= EMPHASIS_CHARACTERS;
|
|
95
|
+
case "quote":
|
|
96
|
+
return spaced(passage).includes(spaced(headline));
|
|
97
|
+
default:
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
66
101
|
var PRESENTATION_LIMITS = {
|
|
67
102
|
sourceCharacters: 4e4,
|
|
68
103
|
beats: 80,
|
|
@@ -100,12 +135,18 @@ function parsePresentationPlan(input) {
|
|
|
100
135
|
if (!record(beat) || !keys(
|
|
101
136
|
beat,
|
|
102
137
|
["id", "sourceStart", "sourceEnd", "layout", "headline", "points"],
|
|
103
|
-
["imageSrc", "media"]
|
|
104
|
-
) || !text(beat.id, 80) || ids.has(beat.id) || !Number.isInteger(beat.sourceStart) || !Number.isInteger(beat.sourceEnd) || typeof beat.sourceStart !== "number" || typeof beat.sourceEnd !== "number" || beat.sourceStart < end || beat.sourceEnd <= beat.sourceStart || beat.sourceEnd > value.sourceText.length || value.sourceText.slice(end, beat.sourceStart).trim() || !
|
|
138
|
+
["imageSrc", "media", "hidden"]
|
|
139
|
+
) || "hidden" in beat && beat.hidden !== true || !text(beat.id, 80) || ids.has(beat.id) || !Number.isInteger(beat.sourceStart) || !Number.isInteger(beat.sourceEnd) || typeof beat.sourceStart !== "number" || typeof beat.sourceEnd !== "number" || beat.sourceStart < end || beat.sourceEnd <= beat.sourceStart || beat.sourceEnd > value.sourceText.length || value.sourceText.slice(end, beat.sourceStart).trim() || !text(beat.headline, 110) || !Array.isArray(beat.points) || beat.points.length > 4 || !beat.points.every((point) => text(point, 180)))
|
|
105
140
|
return null;
|
|
106
|
-
if (
|
|
141
|
+
if (beat.layout === AUTHORED_PRESENTATION_LAYOUT) {
|
|
142
|
+
if (beat.points.length || "media" in beat) return null;
|
|
143
|
+
} else if (!PRESENTATION_LAYOUTS.includes(beat.layout) || !presentationLayoutFits(
|
|
144
|
+
beat.layout,
|
|
145
|
+
beat.headline,
|
|
146
|
+
beat.points,
|
|
147
|
+
value.sourceText.slice(beat.sourceStart, beat.sourceEnd)
|
|
148
|
+
))
|
|
107
149
|
return null;
|
|
108
|
-
if (beat.layout === "comparison" && beat.points.length !== 2) return null;
|
|
109
150
|
if (beat.layout === "image" ? !text(beat.imageSrc, 2048) : "imageSrc" in beat) return null;
|
|
110
151
|
if ("media" in beat && (!Array.isArray(beat.media) || !beat.media.length || beat.media.length > PRESENTATION_LIMITS.mediaPerBeat || new Set(beat.media).size !== beat.media.length || !beat.media.every((ref) => text(ref, 1100))))
|
|
111
152
|
return null;
|
|
@@ -119,7 +160,8 @@ function parsePresentationPlan(input) {
|
|
|
119
160
|
headline: beat.headline,
|
|
120
161
|
points: [...beat.points],
|
|
121
162
|
...beat.layout === "image" ? { imageSrc: beat.imageSrc } : {},
|
|
122
|
-
..."media" in beat ? { media: [...beat.media] } : {}
|
|
163
|
+
..."media" in beat ? { media: [...beat.media] } : {},
|
|
164
|
+
...beat.hidden === true ? { hidden: true } : {}
|
|
123
165
|
});
|
|
124
166
|
}
|
|
125
167
|
if (value.sourceText.slice(end).trim()) return null;
|
|
@@ -142,6 +184,9 @@ function serializePresentationPlan(plan) {
|
|
|
142
184
|
// src/transform/presentationHints.ts
|
|
143
185
|
var PRESENTATION_HINTS_KEY = "squisq-presentation-hints";
|
|
144
186
|
var DYNAMIC_PRESENTATION_STYLE = "dynamic-slides";
|
|
187
|
+
function presentationPassageKey(passage) {
|
|
188
|
+
return `${hashString(passage).toString(36)}-${passage.length.toString(36)}`;
|
|
189
|
+
}
|
|
145
190
|
function defaultPresentationHints() {
|
|
146
191
|
return { version: 1, density: "balanced", inbetweens: true, blocks: [] };
|
|
147
192
|
}
|
|
@@ -164,12 +209,14 @@ function parsePresentationHints(input) {
|
|
|
164
209
|
return null;
|
|
165
210
|
}
|
|
166
211
|
}
|
|
167
|
-
if (!record2(value) || !exact(value, ["version", "density", "inbetweens", "blocks"]) || value.version !== 1 || !["concise", "balanced", "detailed"].includes(String(value.density)) || typeof value.inbetweens !== "boolean" || !Array.isArray(value.blocks) || value.blocks.length > 80)
|
|
212
|
+
if (!record2(value) || !exact(value, ["version", "density", "inbetweens", "blocks"]) || value.version !== 1 || !["concise", "balanced", "detailed", "section"].includes(String(value.density)) || typeof value.inbetweens !== "boolean" || !Array.isArray(value.blocks) || value.blocks.length > 80)
|
|
168
213
|
return null;
|
|
169
214
|
const ids = /* @__PURE__ */ new Set();
|
|
170
215
|
const blocks = [];
|
|
171
216
|
for (const entry of value.blocks) {
|
|
172
|
-
if (!record2(entry) || !exact(entry, ["blockId"], ["layout", "inbetweens", "wording", "ai", "build"]) || !text2(entry.blockId, 1024) || ids.has(entry.blockId) || entry.layout !== void 0 && !PRESENTATION_LAYOUTS.includes(entry.layout) || entry.inbetweens !== void 0 && typeof entry.inbetweens !== "boolean")
|
|
217
|
+
if (!record2(entry) || !exact(entry, ["blockId"], ["layout", "inbetweens", "wording", "ai", "build", "hidden"]) || !text2(entry.blockId, 1024) || ids.has(entry.blockId) || entry.layout !== void 0 && entry.layout !== AUTHORED_PRESENTATION_LAYOUT && !PRESENTATION_LAYOUTS.includes(entry.layout) || entry.inbetweens !== void 0 && typeof entry.inbetweens !== "boolean" || entry.hidden !== void 0 && (!Array.isArray(entry.hidden) || !entry.hidden.length || entry.hidden.length > 80 || new Set(entry.hidden).size !== entry.hidden.length || !entry.hidden.every(
|
|
218
|
+
(key) => typeof key === "string" && /^[0-9a-z]{1,7}-[0-9a-z]{1,4}$/u.test(key)
|
|
219
|
+
)))
|
|
173
220
|
return null;
|
|
174
221
|
const hint = { blockId: entry.blockId };
|
|
175
222
|
if (entry.build !== void 0) {
|
|
@@ -179,11 +226,17 @@ function parsePresentationHints(input) {
|
|
|
179
226
|
}
|
|
180
227
|
if (entry.layout !== void 0) hint.layout = entry.layout;
|
|
181
228
|
if (entry.inbetweens !== void 0) hint.inbetweens = entry.inbetweens;
|
|
229
|
+
if (entry.hidden !== void 0) hint.hidden = [...entry.hidden];
|
|
182
230
|
if (entry.ai !== void 0) {
|
|
183
231
|
if (!Array.isArray(entry.ai) || entry.ai.length > 80) return null;
|
|
184
232
|
hint.ai = [];
|
|
185
233
|
for (const item of entry.ai) {
|
|
186
|
-
if (!record2(item) || !exact(item, ["source", "layout", "headline", "points"]) || !text2(item.source, 4e3) || !PRESENTATION_LAYOUTS.includes(item.layout) || !text2(item.headline, 110) || !Array.isArray(item.points) || item.points.length > 4 || !item.points.every((point) => text2(point, 180)) ||
|
|
234
|
+
if (!record2(item) || !exact(item, ["source", "layout", "headline", "points"]) || !text2(item.source, 4e3) || !PRESENTATION_LAYOUTS.includes(item.layout) || !text2(item.headline, 110) || !Array.isArray(item.points) || item.points.length > 4 || !item.points.every((point) => text2(point, 180)) || !presentationLayoutFits(
|
|
235
|
+
item.layout,
|
|
236
|
+
item.headline,
|
|
237
|
+
item.points,
|
|
238
|
+
item.source
|
|
239
|
+
))
|
|
187
240
|
return null;
|
|
188
241
|
hint.ai.push({
|
|
189
242
|
source: item.source,
|
|
@@ -895,15 +948,17 @@ function extractFeatureContents(contents, keepData = false) {
|
|
|
895
948
|
function withoutProse(record3) {
|
|
896
949
|
return record3 && Object.fromEntries(Object.entries(record3).filter(([key]) => !PROSE_KEYS.has(key)));
|
|
897
950
|
}
|
|
898
|
-
function typedMediaContents(block) {
|
|
951
|
+
function typedMediaContents(block, bodyMedia) {
|
|
899
952
|
const record3 = {
|
|
900
953
|
...block,
|
|
901
954
|
...block.templateData,
|
|
902
955
|
...coerceTemplateParams(block.template ?? "", block.templateOverrides ?? {}).input
|
|
903
956
|
};
|
|
904
957
|
const contents = [];
|
|
958
|
+
const seen = new Set(extractImages([...bodyMedia]).map((image) => image.src));
|
|
905
959
|
const addImage = (src, alt) => {
|
|
906
|
-
if (typeof src === "string" && src) {
|
|
960
|
+
if (typeof src === "string" && src && !seen.has(src)) {
|
|
961
|
+
seen.add(src);
|
|
907
962
|
contents.push({
|
|
908
963
|
type: "paragraph",
|
|
909
964
|
children: [{ type: "image", url: src, alt: typeof alt === "string" ? alt : "" }]
|
|
@@ -957,7 +1012,7 @@ function summarizeBlock(block, mode) {
|
|
|
957
1012
|
const contents = [
|
|
958
1013
|
...brief && !nativeFeature && !tableInputs ? [{ type: "paragraph", children: [{ type: "text", value: brief }] }] : [],
|
|
959
1014
|
...featureContents,
|
|
960
|
-
...typedMediaContents(block)
|
|
1015
|
+
...typedMediaContents(block, featureContents)
|
|
961
1016
|
];
|
|
962
1017
|
const base = {
|
|
963
1018
|
id: block.id,
|
|
@@ -1004,10 +1059,11 @@ function summarizeBlock(block, mode) {
|
|
|
1004
1059
|
};
|
|
1005
1060
|
}
|
|
1006
1061
|
function summarizeHighlight(block, source) {
|
|
1062
|
+
const features = extractFeatureContents(source.contents);
|
|
1007
1063
|
const summary = {
|
|
1008
1064
|
...block,
|
|
1009
1065
|
summaryMode: "brief",
|
|
1010
|
-
contents: [...
|
|
1066
|
+
contents: [...features, ...typedMediaContents(source, features)],
|
|
1011
1067
|
media: source.media
|
|
1012
1068
|
};
|
|
1013
1069
|
if (summary.template === "quote") return { ...summary, quote: briefText(summary.quote) };
|
|
@@ -1798,15 +1854,33 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
1798
1854
|
);
|
|
1799
1855
|
const beats = [];
|
|
1800
1856
|
const supportingOpeners = /* @__PURE__ */ new Set();
|
|
1801
|
-
const
|
|
1857
|
+
const quotes = /* @__PURE__ */ new Map();
|
|
1858
|
+
const perSection = hints.density === "section";
|
|
1859
|
+
const wordLimit = { concise: 28, balanced: 42, detailed: 64, section: Infinity }[hints.density];
|
|
1802
1860
|
for (const block of script.blocks) {
|
|
1803
1861
|
const source = script.sourceText.slice(block.charStart, block.charEnd);
|
|
1804
1862
|
const words = [...source.matchAll(/\S+/gu)];
|
|
1805
1863
|
const hint = hints.blocks.find((item) => item.blockId === block.blockId);
|
|
1806
1864
|
const wording = hint?.wording?.source === source ? hint.wording : void 0;
|
|
1807
|
-
const inbetweens = hint?.inbetweens ?? hints.inbetweens;
|
|
1865
|
+
const inbetweens = !perSection && (hint?.inbetweens ?? hints.inbetweens);
|
|
1808
1866
|
const heading = block.heading?.trim();
|
|
1809
1867
|
const headingEnd = block.charStart + (heading?.length ?? 0);
|
|
1868
|
+
if (hint?.layout === AUTHORED_PRESENTATION_LAYOUT) {
|
|
1869
|
+
if (!words.length) continue;
|
|
1870
|
+
const start = block.charStart + words[0].index;
|
|
1871
|
+
const last = words[words.length - 1];
|
|
1872
|
+
const end = block.charStart + last.index + last[0].length;
|
|
1873
|
+
beats.push({
|
|
1874
|
+
id: `beat-${beats.length + 1}`,
|
|
1875
|
+
sourceStart: start,
|
|
1876
|
+
sourceEnd: end,
|
|
1877
|
+
layout: AUTHORED_PRESENTATION_LAYOUT,
|
|
1878
|
+
headline: headlineText(heading || sentencesIn(script.sourceText, start, end)[0].text),
|
|
1879
|
+
points: []
|
|
1880
|
+
});
|
|
1881
|
+
continue;
|
|
1882
|
+
}
|
|
1883
|
+
const preferred = hint?.layout;
|
|
1810
1884
|
const chunks = chunkWords(words, wordLimit);
|
|
1811
1885
|
const images = sectionImages.get(block.blockId) ?? [];
|
|
1812
1886
|
const opensDeck = beats.length === 0;
|
|
@@ -1850,25 +1924,30 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
1850
1924
|
const custom = chunk === 0 ? wording : void 0;
|
|
1851
1925
|
if (custom?.headline) headline = custom.headline;
|
|
1852
1926
|
const pointsFor = (layout2) => custom?.points ?? (layout2 === "steps" ? stepPoints : textPoints);
|
|
1927
|
+
const quote = custom?.headline ? void 0 : body.find((sentence) => sentence.text.length <= 110)?.text;
|
|
1928
|
+
const headlineFor = (layout2) => layout2 === "quote" && quote ? quote : headline;
|
|
1853
1929
|
let layout = index === 0 ? "title" : textPoints.length >= 2 && index % 3 === 1 ? "list" : "statement";
|
|
1854
1930
|
if (sequence) layout = "steps";
|
|
1855
1931
|
else if (textPoints.length === 2 && /\b(versus|whereas|compared|instead)\b/iu.test(passage))
|
|
1856
1932
|
layout = "comparison";
|
|
1857
1933
|
if (image) layout = "image";
|
|
1858
|
-
if (
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1934
|
+
if (preferred && (preferred === "image" ? !!image : presentationLayoutFits(
|
|
1935
|
+
preferred,
|
|
1936
|
+
headlineFor(preferred),
|
|
1937
|
+
pointsFor(preferred),
|
|
1938
|
+
passage
|
|
1939
|
+
)))
|
|
1940
|
+
layout = preferred;
|
|
1863
1941
|
const beat = {
|
|
1864
1942
|
id: `beat-${index + 1}`,
|
|
1865
1943
|
sourceStart: start,
|
|
1866
1944
|
sourceEnd: end,
|
|
1867
1945
|
layout,
|
|
1868
|
-
headline,
|
|
1946
|
+
headline: headlineFor(layout),
|
|
1869
1947
|
points: pointsFor(layout),
|
|
1870
1948
|
...layout === "image" && image ? { imageSrc: image.src } : {}
|
|
1871
1949
|
};
|
|
1950
|
+
if (quote) quotes.set(beat.id, quote);
|
|
1872
1951
|
let split;
|
|
1873
1952
|
if (inbetweens && !custom?.points && layout === "steps" && sequence) {
|
|
1874
1953
|
if (shown.some((sentence) => sentence.end <= steps[0].start)) split = steps[0].start;
|
|
@@ -1909,6 +1988,15 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
1909
1988
|
throw new Error(
|
|
1910
1989
|
"This document has too many sections for one presentation. Split it into shorter documents."
|
|
1911
1990
|
);
|
|
1991
|
+
for (const block of script.blocks) {
|
|
1992
|
+
const hidden = hints.blocks.find((item) => item.blockId === block.blockId)?.hidden;
|
|
1993
|
+
if (!hidden) continue;
|
|
1994
|
+
for (const beat of beats)
|
|
1995
|
+
if (beat.sourceStart >= block.charStart && beat.sourceStart < block.charEnd && hidden.includes(
|
|
1996
|
+
presentationPassageKey(script.sourceText.slice(beat.sourceStart, beat.sourceEnd))
|
|
1997
|
+
))
|
|
1998
|
+
beat.hidden = true;
|
|
1999
|
+
}
|
|
1912
2000
|
const sectionMedia = collectPresentationMedia(
|
|
1913
2001
|
doc,
|
|
1914
2002
|
script.blocks.map((block) => block.blockId)
|
|
@@ -1917,8 +2005,9 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
1917
2005
|
const items = sectionMedia.get(block.blockId);
|
|
1918
2006
|
if (!items?.length) continue;
|
|
1919
2007
|
const own = beats.filter(
|
|
1920
|
-
(beat) => beat.sourceStart >= block.charStart && beat.sourceStart < block.charEnd
|
|
2008
|
+
(beat) => beat.sourceStart >= block.charStart && beat.sourceStart < block.charEnd && beat.layout !== AUTHORED_PRESENTATION_LAYOUT && !beat.hidden
|
|
1921
2009
|
);
|
|
2010
|
+
if (!own.length) continue;
|
|
1922
2011
|
const open = own.filter((beat) => beat !== beats[0] && beat.layout !== "image");
|
|
1923
2012
|
const slots = open.length ? open : own;
|
|
1924
2013
|
const shown = /* @__PURE__ */ new Set();
|
|
@@ -1939,27 +2028,33 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
1939
2028
|
closing.layout = "title";
|
|
1940
2029
|
let origin = "automatic";
|
|
1941
2030
|
for (const beat of beats) {
|
|
2031
|
+
if (beat.layout === AUTHORED_PRESENTATION_LAYOUT) continue;
|
|
1942
2032
|
const section = script.blocks.find(
|
|
1943
2033
|
(block) => beat.sourceStart >= block.charStart && beat.sourceStart < block.charEnd
|
|
1944
2034
|
);
|
|
1945
2035
|
const hint = hints.blocks.find((item) => item.blockId === section?.blockId);
|
|
1946
|
-
const
|
|
1947
|
-
|
|
1948
|
-
);
|
|
2036
|
+
const passage = script.sourceText.slice(beat.sourceStart, beat.sourceEnd);
|
|
2037
|
+
const cached = hint?.ai?.find((item) => item.source === passage);
|
|
1949
2038
|
if (cached && (cached.layout !== "image" || beat.imageSrc)) {
|
|
1950
2039
|
beat.headline = cached.headline;
|
|
1951
2040
|
beat.points = [...cached.points];
|
|
1952
2041
|
beat.layout = cached.layout;
|
|
1953
2042
|
origin = "ai";
|
|
1954
2043
|
}
|
|
1955
|
-
|
|
1956
|
-
|
|
2044
|
+
const preferred = hint?.layout === AUTHORED_PRESENTATION_LAYOUT ? void 0 : hint?.layout;
|
|
2045
|
+
if (preferred && !supportingOpeners.has(beat.id)) {
|
|
2046
|
+
const headline = preferred === "quote" && quotes.get(beat.id) || beat.headline;
|
|
2047
|
+
if (preferred === "image" ? !!beat.imageSrc : presentationLayoutFits(preferred, headline, beat.points, passage)) {
|
|
2048
|
+
beat.layout = preferred;
|
|
2049
|
+
beat.headline = headline;
|
|
2050
|
+
}
|
|
2051
|
+
}
|
|
1957
2052
|
if (section && beat.sourceStart === section.charStart && hint?.wording?.source === script.sourceText.slice(section.charStart, section.charEnd)) {
|
|
1958
2053
|
beat.headline = hint.wording.headline ?? beat.headline;
|
|
1959
2054
|
beat.points = hint.wording.points ?? beat.points;
|
|
1960
2055
|
}
|
|
1961
|
-
if (beat.media && beat.layout === "steps" &&
|
|
1962
|
-
if (
|
|
2056
|
+
if (beat.media && beat.layout === "steps" && preferred !== "steps") beat.layout = "list";
|
|
2057
|
+
if (beat.layout !== "image" && !presentationLayoutFits(beat.layout, beat.headline, beat.points, passage))
|
|
1963
2058
|
beat.layout = "statement";
|
|
1964
2059
|
if (beat.layout !== "image") delete beat.imageSrc;
|
|
1965
2060
|
}
|
|
@@ -2013,11 +2108,35 @@ function compilePresentationPlan(doc, plan) {
|
|
|
2013
2108
|
const bookmarks = (narration?.bookmarks ?? []).filter(
|
|
2014
2109
|
(word) => Number.isFinite(word.time) && word.time >= 0 && word.time <= duration && Number.isInteger(word.charOffset) && word.charOffset >= 0 && word.charOffset < script.sourceText.length
|
|
2015
2110
|
).sort((a, b) => a.charOffset - b.charOffset);
|
|
2111
|
+
const marks = (narration?.slides ?? []).filter(
|
|
2112
|
+
(mark) => Number.isFinite(mark.time) && mark.time >= 0 && mark.time <= duration && Number.isInteger(mark.charOffset) && mark.charOffset >= 0 && mark.charOffset < script.sourceText.length
|
|
2113
|
+
);
|
|
2114
|
+
const tokensBefore = (offset) => script.tokens.filter((token) => token.charOffset < offset).length;
|
|
2115
|
+
const markedTime = (offset) => {
|
|
2116
|
+
if (!narration || !marks.length) return void 0;
|
|
2117
|
+
const exact2 = marks.find((mark) => mark.charOffset === offset);
|
|
2118
|
+
if (exact2) return exact2.time;
|
|
2119
|
+
if (bookmarks.length) return void 0;
|
|
2120
|
+
const anchors = [
|
|
2121
|
+
{ charOffset: 0, time: narration.startTime },
|
|
2122
|
+
...[...marks].sort((a, b) => a.charOffset - b.charOffset),
|
|
2123
|
+
{ charOffset: script.sourceText.length, time: duration }
|
|
2124
|
+
];
|
|
2125
|
+
const after = anchors.findIndex((anchor) => anchor.charOffset > offset);
|
|
2126
|
+
const from = anchors[Math.max(0, after - 1)];
|
|
2127
|
+
const to = anchors[after] ?? from;
|
|
2128
|
+
const span = tokensBefore(to.charOffset) - tokensBefore(from.charOffset);
|
|
2129
|
+
const share = span > 0 ? (tokensBefore(offset) - tokensBefore(from.charOffset)) / span : 0;
|
|
2130
|
+
return from.time + share * Math.max(0, to.time - from.time);
|
|
2131
|
+
};
|
|
2016
2132
|
let previous = 0;
|
|
2017
2133
|
const starts = checked.beats.map((beat, index) => {
|
|
2018
2134
|
if (!index) return 0;
|
|
2019
2135
|
let time;
|
|
2020
|
-
|
|
2136
|
+
const marked = markedTime(beat.sourceStart);
|
|
2137
|
+
if (marked !== void 0) {
|
|
2138
|
+
time = marked;
|
|
2139
|
+
} else if (narration && bookmarks.length) {
|
|
2021
2140
|
time = bookmarks.find((word) => word.charOffset >= beat.sourceStart)?.time ?? duration;
|
|
2022
2141
|
} else {
|
|
2023
2142
|
const before = script.tokens.filter((token) => token.charOffset < beat.sourceStart).length;
|
|
@@ -2036,13 +2155,44 @@ function compilePresentationPlan(doc, plan) {
|
|
|
2036
2155
|
const section = sourceOf(beat)?.blockId;
|
|
2037
2156
|
if (section) sectionEnds.set(section, starts[index + 1] ?? duration);
|
|
2038
2157
|
});
|
|
2158
|
+
const shown = checked.beats.flatMap((beat, index) => beat.hidden ? [] : [index]);
|
|
2159
|
+
if (!shown.length) throw new Error("Every slide is hidden. Show at least one slide.");
|
|
2160
|
+
const windows = shown.map((index, position) => ({
|
|
2161
|
+
index,
|
|
2162
|
+
start: position ? starts[index] : 0,
|
|
2163
|
+
end: position + 1 < shown.length ? starts[shown[position + 1]] : duration
|
|
2164
|
+
})).filter((window) => window.end > window.start);
|
|
2165
|
+
const onScreen = (time) => windows.reduce((found, window) => window.start <= time ? window : found, windows[0]);
|
|
2039
2166
|
const clipsPlaced = /* @__PURE__ */ new Set();
|
|
2040
|
-
const
|
|
2041
|
-
const blocks = [];
|
|
2167
|
+
const sectionClips = /* @__PURE__ */ new Map();
|
|
2042
2168
|
checked.beats.forEach((beat, index) => {
|
|
2043
2169
|
const start = starts[index];
|
|
2044
2170
|
const end = starts[index + 1] ?? duration;
|
|
2045
|
-
|
|
2171
|
+
const source = sourceOf(beat);
|
|
2172
|
+
if (end <= start || !source || clipsPlaced.has(source.blockId) || !windows.length) return;
|
|
2173
|
+
clipsPlaced.add(source.blockId);
|
|
2174
|
+
const sectionEnd = sectionEnds.get(source.blockId) ?? end;
|
|
2175
|
+
const host = onScreen(start);
|
|
2176
|
+
const shift = (clip2) => start === host.start ? clip2 : { ...clip2, startAt: clip2.startAt + start - host.start };
|
|
2177
|
+
const clips = (authoredBlocks.find((block) => block.id === source.blockId)?.media ?? []).flatMap((clip2) => {
|
|
2178
|
+
if (clip2.spillover) return [shift(clip2)];
|
|
2179
|
+
const room = sectionEnd - start - clip2.startAt;
|
|
2180
|
+
if (room <= 0) return [];
|
|
2181
|
+
const clipStart = clip2.clipStart ?? 0;
|
|
2182
|
+
return [
|
|
2183
|
+
shift({
|
|
2184
|
+
...clip2,
|
|
2185
|
+
spillover: true,
|
|
2186
|
+
clipEnd: Math.min(clip2.clipEnd ?? Infinity, clipStart + room)
|
|
2187
|
+
})
|
|
2188
|
+
];
|
|
2189
|
+
});
|
|
2190
|
+
sectionClips.set(host.index, [...sectionClips.get(host.index) ?? [], ...clips]);
|
|
2191
|
+
});
|
|
2192
|
+
const mediaStarts = /* @__PURE__ */ new Map();
|
|
2193
|
+
const blocks = [];
|
|
2194
|
+
for (const { index, start, end } of windows) {
|
|
2195
|
+
const beat = checked.beats[index];
|
|
2046
2196
|
const source = sourceOf(beat);
|
|
2047
2197
|
const build = buildHints?.blocks.find((hint) => hint.blockId === source?.blockId)?.build ?? authoredBlocks.find((block2) => block2.id === source?.blockId)?.build;
|
|
2048
2198
|
const contents = (beat.media ?? []).flatMap((ref) => {
|
|
@@ -2051,26 +2201,8 @@ function compilePresentationPlan(doc, plan) {
|
|
|
2051
2201
|
const node = presentationMediaNode(media.get(ref), start - first);
|
|
2052
2202
|
return node ? [node] : [];
|
|
2053
2203
|
});
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
clipsPlaced.add(source.blockId);
|
|
2057
|
-
const sectionEnd = sectionEnds.get(source.blockId) ?? end;
|
|
2058
|
-
clips = (authoredBlocks.find((block2) => block2.id === source.blockId)?.media ?? []).flatMap(
|
|
2059
|
-
(clip2) => {
|
|
2060
|
-
if (clip2.spillover) return [clip2];
|
|
2061
|
-
const room = sectionEnd - start - clip2.startAt;
|
|
2062
|
-
if (room <= 0) return [];
|
|
2063
|
-
const clipStart = clip2.clipStart ?? 0;
|
|
2064
|
-
return [
|
|
2065
|
-
{
|
|
2066
|
-
...clip2,
|
|
2067
|
-
spillover: true,
|
|
2068
|
-
clipEnd: Math.min(clip2.clipEnd ?? Infinity, clipStart + room)
|
|
2069
|
-
}
|
|
2070
|
-
];
|
|
2071
|
-
}
|
|
2072
|
-
);
|
|
2073
|
-
}
|
|
2204
|
+
const authored = authoredBlocks.find((block2) => block2.id === source?.blockId);
|
|
2205
|
+
const clips = sectionClips.get(index) ?? [];
|
|
2074
2206
|
const base = {
|
|
2075
2207
|
...build ? { build } : {},
|
|
2076
2208
|
...contents.length ? { contents } : {},
|
|
@@ -2086,9 +2218,20 @@ function compilePresentationPlan(doc, plan) {
|
|
|
2086
2218
|
sourceCharOffset: beat.sourceStart,
|
|
2087
2219
|
transition: { type: "fade", duration: Math.min(0.3, (end - start) / 5) }
|
|
2088
2220
|
};
|
|
2089
|
-
|
|
2221
|
+
if (beat.layout === AUTHORED_PRESENTATION_LAYOUT) {
|
|
2222
|
+
if (!authored) throw new Error("A section shown as authored is no longer in the document.");
|
|
2223
|
+
const { children, media: _media, ...own } = authored;
|
|
2224
|
+
blocks.push({
|
|
2225
|
+
...own,
|
|
2226
|
+
...base,
|
|
2227
|
+
...children && isContainerTemplate(authored.template) ? { children } : {},
|
|
2228
|
+
transition: authored.transition ?? base.transition
|
|
2229
|
+
});
|
|
2230
|
+
continue;
|
|
2231
|
+
}
|
|
2232
|
+
const block = visualBlock(beat, beat.layout, base, index);
|
|
2090
2233
|
blocks.push(block);
|
|
2091
|
-
}
|
|
2234
|
+
}
|
|
2092
2235
|
return {
|
|
2093
2236
|
...doc,
|
|
2094
2237
|
blocks,
|
|
@@ -2099,11 +2242,37 @@ function compilePresentationPlan(doc, plan) {
|
|
|
2099
2242
|
audio: doc.audio.segments.some((segment) => segment.src) ? doc.audio : { segments: [{ src: "", name: "presentation-clock", startTime: 0, duration }] }
|
|
2100
2243
|
};
|
|
2101
2244
|
}
|
|
2102
|
-
function visualBlock(beat, base, index) {
|
|
2245
|
+
function visualBlock(beat, layout, base, index) {
|
|
2103
2246
|
const colorScheme = ["blue", "green", "orange"][index % 3];
|
|
2104
|
-
switch (
|
|
2247
|
+
switch (layout) {
|
|
2105
2248
|
case "title":
|
|
2106
2249
|
return { ...base, template: "title", title: beat.headline, subtitle: beat.points[0] ?? "" };
|
|
2250
|
+
case "divider":
|
|
2251
|
+
return { ...base, template: "sectionHeader", title: beat.headline, colorScheme };
|
|
2252
|
+
case "emphasis":
|
|
2253
|
+
return { ...base, template: "bigText", title: beat.headline };
|
|
2254
|
+
case "quote":
|
|
2255
|
+
return { ...base, template: "fullBleedQuote", text: beat.headline, colorScheme };
|
|
2256
|
+
case "stat": {
|
|
2257
|
+
const { match, line, index: at } = presentationStat(beat.headline, beat.points);
|
|
2258
|
+
const detail = beat.points.find((_, i) => i !== at) ?? (at < 0 ? void 0 : beat.headline);
|
|
2259
|
+
return {
|
|
2260
|
+
...base,
|
|
2261
|
+
template: "statHighlight",
|
|
2262
|
+
stat: match.value,
|
|
2263
|
+
description: line,
|
|
2264
|
+
...detail ? { detail } : {},
|
|
2265
|
+
colorScheme
|
|
2266
|
+
};
|
|
2267
|
+
}
|
|
2268
|
+
case "definition":
|
|
2269
|
+
return {
|
|
2270
|
+
...base,
|
|
2271
|
+
template: "definitionCard",
|
|
2272
|
+
term: beat.headline,
|
|
2273
|
+
definition: beat.points.join("\n\n"),
|
|
2274
|
+
colorScheme
|
|
2275
|
+
};
|
|
2107
2276
|
case "statement":
|
|
2108
2277
|
return {
|
|
2109
2278
|
...base,
|
|
@@ -2188,11 +2357,15 @@ function applySavedPresentation(doc) {
|
|
|
2188
2357
|
export {
|
|
2189
2358
|
PRESENTATION_KEY,
|
|
2190
2359
|
PRESENTATION_LAYOUTS,
|
|
2360
|
+
AUTHORED_PRESENTATION_LAYOUT,
|
|
2361
|
+
presentationStat,
|
|
2362
|
+
presentationLayoutFits,
|
|
2191
2363
|
PRESENTATION_LIMITS,
|
|
2192
2364
|
parsePresentationPlan,
|
|
2193
2365
|
serializePresentationPlan,
|
|
2194
2366
|
PRESENTATION_HINTS_KEY,
|
|
2195
2367
|
DYNAMIC_PRESENTATION_STYLE,
|
|
2368
|
+
presentationPassageKey,
|
|
2196
2369
|
defaultPresentationHints,
|
|
2197
2370
|
parsePresentationHints,
|
|
2198
2371
|
serializePresentationHints,
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
profileBlockContents,
|
|
33
33
|
renderMarkdownBlocksHtml,
|
|
34
34
|
treeToTemplateData
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-DIY3NBIS.js";
|
|
36
36
|
import {
|
|
37
37
|
anchorPoint,
|
|
38
38
|
base64ToUtf8,
|
|
@@ -3181,10 +3181,10 @@ function rightFeature(input, context) {
|
|
|
3181
3181
|
|
|
3182
3182
|
// src/doc/templates/mediaFeatureBlock.ts
|
|
3183
3183
|
function topFeature(input, context) {
|
|
3184
|
-
return contentBlock({ ...input, template: "content" }, context
|
|
3184
|
+
return contentBlock({ ...input, template: "content" }, context);
|
|
3185
3185
|
}
|
|
3186
3186
|
function bottomFeature(input, context) {
|
|
3187
|
-
return contentBlock({ ...input, template: "content" }, context
|
|
3187
|
+
return contentBlock({ ...input, template: "content" }, context);
|
|
3188
3188
|
}
|
|
3189
3189
|
function mediaOnly(input, context) {
|
|
3190
3190
|
return contentBlock({ ...input, template: "content" }, context);
|
|
@@ -4444,11 +4444,14 @@ function dataTable(input, context) {
|
|
|
4444
4444
|
const titleFontSize = themedFontSize(48, context, true);
|
|
4445
4445
|
const tableFontSize = themedFontSize(28, context, false);
|
|
4446
4446
|
const layers = [createBackgroundLayer("bg", themedSurfaceGradient(context, 170))];
|
|
4447
|
-
const
|
|
4448
|
-
|
|
4449
|
-
|
|
4447
|
+
const visibleRows = Math.min(resolvedRows.length, MAX_VISIBLE_ROWS);
|
|
4448
|
+
const hasHeader = resolvedHeaders.length > 0;
|
|
4449
|
+
const rowCount = Math.max(1, visibleRows + (hasHeader ? 1 : 0));
|
|
4450
|
+
const ruleHeight = (hasHeader ? 2 : 0) + Math.max(0, visibleRows - 1) + 2 + 1;
|
|
4451
|
+
const naturalTableHPct = Math.min(
|
|
4452
|
+
74,
|
|
4453
|
+
(rowCount * tableFontSize * 2.4 + ruleHeight) / viewport.height * 100
|
|
4450
4454
|
);
|
|
4451
|
-
const naturalTableHPct = Math.min(74, rowCount * tableFontSize * 2.4 / viewport.height * 100);
|
|
4452
4455
|
const titleBandPct = title ? titleFontSize * 2.2 * 100 / viewport.height : 0;
|
|
4453
4456
|
const groupTopPct = Math.max(8, (100 - titleBandPct - naturalTableHPct) / 2);
|
|
4454
4457
|
if (title) {
|
|
@@ -12445,13 +12448,15 @@ function resolveDocBuildTiming(doc, blocks) {
|
|
|
12445
12448
|
}
|
|
12446
12449
|
|
|
12447
12450
|
// src/doc/templates/contentBlock.ts
|
|
12448
|
-
function bodyNodes(context
|
|
12451
|
+
function bodyNodes(context) {
|
|
12449
12452
|
if (context.block?.summaryMode === "headings-and-features") return [];
|
|
12450
12453
|
return (context.block?.contents ?? []).filter(
|
|
12451
|
-
// Mermaid source
|
|
12452
|
-
// visual layers (a diagram, a player
|
|
12453
|
-
// loss-averse default noisy
|
|
12454
|
-
|
|
12454
|
+
// Mermaid source, hosted-video links and picture-only paragraphs are
|
|
12455
|
+
// already materialized as visual layers (a diagram, a player, the picture
|
|
12456
|
+
// itself). Repeating them as prose makes the loss-averse default noisy
|
|
12457
|
+
// without preserving any additional meaning — a pasted picture's alt text
|
|
12458
|
+
// is just its generated file name.
|
|
12459
|
+
(node) => !isMaterializedMediaNode(node) && !isPictureParagraph(node)
|
|
12455
12460
|
);
|
|
12456
12461
|
}
|
|
12457
12462
|
function listParagraphs(list, level = 0) {
|
|
@@ -12496,10 +12501,10 @@ function bodyFontSize(body, context) {
|
|
|
12496
12501
|
const base = body.length > 1800 ? 18 : body.length > 1100 ? 21 : body.length > 650 ? 24 : 28;
|
|
12497
12502
|
return themedFontSize(base, context, false);
|
|
12498
12503
|
}
|
|
12499
|
-
function contentBlock(input, context
|
|
12504
|
+
function contentBlock(input, context) {
|
|
12500
12505
|
const { theme } = context;
|
|
12501
12506
|
const title = input.title ?? context.block?.title ?? "";
|
|
12502
|
-
const markdown = bodyNodes(context
|
|
12507
|
+
const markdown = bodyNodes(context);
|
|
12503
12508
|
const paragraphs = completeBodyParagraphs(markdown);
|
|
12504
12509
|
const body = paragraphs.map(plainParagraphText).join("\n");
|
|
12505
12510
|
const builds = planContentBuilds(markdown, input.build ?? context.block?.build);
|