@bendyline/squisq 2.13.13 → 2.13.15
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-BhvotZx_.d.ts → Doc-C_Sh49ot.d.ts} +59 -6
- package/dist/{ImageEditDoc-D8hYio6b.d.ts → ImageEditDoc-Sqw3Tw-R.d.ts} +1 -1
- package/dist/{chunk-OIQ2GO2O.js → chunk-2CB37BOU.js} +1 -1
- package/dist/{chunk-CTT4XAGO.js → chunk-4HQ7QZKB.js} +2289 -630
- package/dist/chunk-C7DKMO4H.js +88 -0
- package/dist/{chunk-C4SB3NN4.js → chunk-DDJHIZED.js} +1 -1
- package/dist/{chunk-TCGGJUKC.js → chunk-FYP7GNER.js} +93 -15
- package/dist/chunk-N3FQSUVT.js +515 -0
- package/dist/{chunk-SGNWO7OF.js → chunk-OFE5RZWW.js} +490 -24
- package/dist/{chunk-YQQWE4HG.js → chunk-OJCAKUHW.js} +192 -260
- package/dist/{chunk-7MS26OXD.js → chunk-UDPPWYYM.js} +6 -0
- package/dist/{chunk-5DFFVW75.js → chunk-Y34KYMAS.js} +1 -1
- package/dist/doc/index.d.ts +337 -22
- package/dist/doc/index.js +56 -8
- 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 +8 -8
- package/dist/index.js +127 -21
- package/dist/jsonForm/index.d.ts +1 -1
- package/dist/markdown/index.js +3 -3
- package/dist/{materializePageSection-CWxou4mX.d.ts → materializePageSection-Dmf-rf1b.d.ts} +121 -8
- package/dist/mediaEdit/index.d.ts +2 -2
- package/dist/narration/index.d.ts +1 -1
- package/dist/narration/index.js +4 -4
- package/dist/recommend/index.d.ts +129 -2
- package/dist/recommend/index.js +11 -3
- package/dist/schemas/index.d.ts +4 -4
- package/dist/{themeLibrary-BIYE6aLw.d.ts → themeLibrary-B4VLovhW.d.ts} +1 -1
- package/dist/timing/index.d.ts +66 -2
- package/dist/timing/index.js +12 -0
- package/dist/transform/index.d.ts +173 -16
- package/dist/transform/index.js +55 -16
- package/package.json +1 -1
- package/dist/chunk-FCB6JLWB.js +0 -125
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AUTHORED_PRESENTATION_LAYOUT,
|
|
3
|
+
PRESENTATION_KEY,
|
|
4
|
+
PRESENTATION_LAYOUTS,
|
|
5
|
+
PRESENTATION_LIMITS,
|
|
2
6
|
buildNarrationScript,
|
|
3
7
|
buildSourceText,
|
|
4
8
|
coerceTemplateParams,
|
|
5
9
|
conceptBuildStepTexts,
|
|
10
|
+
conceptTemplate,
|
|
6
11
|
flattenRenderableBlocks,
|
|
7
12
|
getPinnedBlockMeta,
|
|
8
|
-
markdownToDoc
|
|
9
|
-
|
|
13
|
+
markdownToDoc,
|
|
14
|
+
parsePresentationPlan,
|
|
15
|
+
presentationBeatExtras,
|
|
16
|
+
presentationLayoutFits,
|
|
17
|
+
presentationStat
|
|
18
|
+
} from "./chunk-4HQ7QZKB.js";
|
|
10
19
|
import {
|
|
11
20
|
deriveTemplateInputs,
|
|
21
|
+
extractConceptItems,
|
|
12
22
|
extractEmbeddedVideos,
|
|
13
23
|
extractImages,
|
|
14
24
|
isAsciiDiagramFence,
|
|
@@ -20,8 +30,9 @@ import {
|
|
|
20
30
|
isPictureParagraph,
|
|
21
31
|
isStandaloneHtmlVideo,
|
|
22
32
|
isTreeFence,
|
|
23
|
-
matchNumberHighlight
|
|
24
|
-
|
|
33
|
+
matchNumberHighlight,
|
|
34
|
+
shapeIsStated
|
|
35
|
+
} from "./chunk-OFE5RZWW.js";
|
|
25
36
|
import {
|
|
26
37
|
extractContent,
|
|
27
38
|
mapElementToBlock,
|
|
@@ -34,10 +45,10 @@ import {
|
|
|
34
45
|
} from "./chunk-JNUNNQ74.js";
|
|
35
46
|
import {
|
|
36
47
|
parseMarkdown
|
|
37
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-DDJHIZED.js";
|
|
38
49
|
import {
|
|
39
50
|
isContainerTemplate
|
|
40
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-UDPPWYYM.js";
|
|
41
52
|
import {
|
|
42
53
|
extractPlainText,
|
|
43
54
|
findBlockVideoEmbed,
|
|
@@ -59,142 +70,6 @@ import {
|
|
|
59
70
|
hashString
|
|
60
71
|
} from "./chunk-XRW6P7IF.js";
|
|
61
72
|
|
|
62
|
-
// src/transform/presentationPlan.ts
|
|
63
|
-
var PRESENTATION_KEY = "squisq-presentation";
|
|
64
|
-
var PRESENTATION_LAYOUTS = [
|
|
65
|
-
"title",
|
|
66
|
-
"divider",
|
|
67
|
-
"statement",
|
|
68
|
-
"emphasis",
|
|
69
|
-
"quote",
|
|
70
|
-
"stat",
|
|
71
|
-
"definition",
|
|
72
|
-
"list",
|
|
73
|
-
"comparison",
|
|
74
|
-
"steps",
|
|
75
|
-
"image",
|
|
76
|
-
"cards",
|
|
77
|
-
"process",
|
|
78
|
-
"cycle",
|
|
79
|
-
"layers"
|
|
80
|
-
];
|
|
81
|
-
var AUTHORED_PRESENTATION_LAYOUT = "authored";
|
|
82
|
-
var EMPHASIS_CHARACTERS = 60;
|
|
83
|
-
var spaced = (text3) => text3.replace(/\s+/gu, " ").trim();
|
|
84
|
-
function presentationStat(headline, points) {
|
|
85
|
-
for (const [index, line] of [headline, ...points].entries()) {
|
|
86
|
-
const match = matchNumberHighlight(line);
|
|
87
|
-
if (match) return { match, line, index: index - 1 };
|
|
88
|
-
}
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
function presentationLayoutFits(layout, headline, points, passage) {
|
|
92
|
-
switch (layout) {
|
|
93
|
-
case "list":
|
|
94
|
-
case "steps":
|
|
95
|
-
case "cards":
|
|
96
|
-
case "process":
|
|
97
|
-
return points.length >= 2;
|
|
98
|
-
case "cycle":
|
|
99
|
-
case "layers":
|
|
100
|
-
return points.length >= 3;
|
|
101
|
-
case "comparison":
|
|
102
|
-
return points.length === 2;
|
|
103
|
-
case "definition":
|
|
104
|
-
return points.length >= 1;
|
|
105
|
-
case "stat":
|
|
106
|
-
return presentationStat(headline, points) !== null;
|
|
107
|
-
case "emphasis":
|
|
108
|
-
return headline.length <= EMPHASIS_CHARACTERS;
|
|
109
|
-
case "quote":
|
|
110
|
-
return spaced(passage).includes(spaced(headline));
|
|
111
|
-
default:
|
|
112
|
-
return true;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
var PRESENTATION_LIMITS = {
|
|
116
|
-
sourceCharacters: 4e4,
|
|
117
|
-
beats: 80,
|
|
118
|
-
serializedCharacters: 16e4,
|
|
119
|
-
mediaPerBeat: 4
|
|
120
|
-
};
|
|
121
|
-
function record(value) {
|
|
122
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
123
|
-
}
|
|
124
|
-
function keys(value, required, optional = []) {
|
|
125
|
-
return required.every((key) => Object.prototype.hasOwnProperty.call(value, key)) && Object.keys(value).every((key) => required.includes(key) || optional.includes(key));
|
|
126
|
-
}
|
|
127
|
-
function text(value, max) {
|
|
128
|
-
return typeof value === "string" && value.trim().length > 0 && value.length <= max && !Array.from(value).some((character) => {
|
|
129
|
-
const code = character.charCodeAt(0);
|
|
130
|
-
return code < 32 && code !== 9 && code !== 10 && code !== 13;
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
function parsePresentationPlan(input) {
|
|
134
|
-
let value = input;
|
|
135
|
-
if (typeof value === "string") {
|
|
136
|
-
if (value.length > PRESENTATION_LIMITS.serializedCharacters) return null;
|
|
137
|
-
try {
|
|
138
|
-
value = JSON.parse(value);
|
|
139
|
-
} catch {
|
|
140
|
-
return null;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (!record(value) || !keys(value, ["version", "sourceText", "origin", "beats"]) || value.version !== 1 || !text(value.sourceText, PRESENTATION_LIMITS.sourceCharacters) || typeof value.origin !== "string" || !["automatic", "ai"].includes(value.origin) || !Array.isArray(value.beats) || !value.beats.length || value.beats.length > PRESENTATION_LIMITS.beats)
|
|
144
|
-
return null;
|
|
145
|
-
const beats = [];
|
|
146
|
-
const ids = /* @__PURE__ */ new Set();
|
|
147
|
-
let end = 0;
|
|
148
|
-
for (const beat of value.beats) {
|
|
149
|
-
if (!record(beat) || !keys(
|
|
150
|
-
beat,
|
|
151
|
-
["id", "sourceStart", "sourceEnd", "layout", "headline", "points"],
|
|
152
|
-
["imageSrc", "media", "hidden"]
|
|
153
|
-
) || "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)))
|
|
154
|
-
return null;
|
|
155
|
-
if (beat.layout === AUTHORED_PRESENTATION_LAYOUT) {
|
|
156
|
-
if (beat.points.length || "media" in beat) return null;
|
|
157
|
-
} else if (!PRESENTATION_LAYOUTS.includes(beat.layout) || !presentationLayoutFits(
|
|
158
|
-
beat.layout,
|
|
159
|
-
beat.headline,
|
|
160
|
-
beat.points,
|
|
161
|
-
value.sourceText.slice(beat.sourceStart, beat.sourceEnd)
|
|
162
|
-
))
|
|
163
|
-
return null;
|
|
164
|
-
if (beat.layout === "image" ? !text(beat.imageSrc, 2048) : "imageSrc" in beat) return null;
|
|
165
|
-
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))))
|
|
166
|
-
return null;
|
|
167
|
-
ids.add(beat.id);
|
|
168
|
-
end = beat.sourceEnd;
|
|
169
|
-
beats.push({
|
|
170
|
-
id: beat.id,
|
|
171
|
-
sourceStart: beat.sourceStart,
|
|
172
|
-
sourceEnd: beat.sourceEnd,
|
|
173
|
-
layout: beat.layout,
|
|
174
|
-
headline: beat.headline,
|
|
175
|
-
points: [...beat.points],
|
|
176
|
-
...beat.layout === "image" ? { imageSrc: beat.imageSrc } : {},
|
|
177
|
-
..."media" in beat ? { media: [...beat.media] } : {},
|
|
178
|
-
...beat.hidden === true ? { hidden: true } : {}
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
if (value.sourceText.slice(end).trim()) return null;
|
|
182
|
-
return {
|
|
183
|
-
version: 1,
|
|
184
|
-
sourceText: value.sourceText,
|
|
185
|
-
origin: value.origin,
|
|
186
|
-
beats
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
function serializePresentationPlan(plan) {
|
|
190
|
-
const parsed = parsePresentationPlan(plan);
|
|
191
|
-
if (!parsed) throw new Error("The presentation plan is invalid.");
|
|
192
|
-
const result = JSON.stringify(parsed);
|
|
193
|
-
if (result.length > PRESENTATION_LIMITS.serializedCharacters)
|
|
194
|
-
throw new Error("The presentation plan is too large.");
|
|
195
|
-
return result;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
73
|
// src/transform/presentationHints.ts
|
|
199
74
|
var PRESENTATION_HINTS_KEY = "squisq-presentation-hints";
|
|
200
75
|
var DYNAMIC_PRESENTATION_STYLE = "dynamic-slides";
|
|
@@ -204,13 +79,13 @@ function presentationPassageKey(passage) {
|
|
|
204
79
|
function defaultPresentationHints() {
|
|
205
80
|
return { version: 1, density: "balanced", inbetweens: true, blocks: [] };
|
|
206
81
|
}
|
|
207
|
-
function
|
|
82
|
+
function record(value) {
|
|
208
83
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
209
84
|
}
|
|
210
85
|
function exact(value, required, optional = []) {
|
|
211
86
|
return required.every((key) => Object.prototype.hasOwnProperty.call(value, key)) && Object.keys(value).every((key) => required.includes(key) || optional.includes(key));
|
|
212
87
|
}
|
|
213
|
-
function
|
|
88
|
+
function text(value, max) {
|
|
214
89
|
return typeof value === "string" && !!value.trim() && value.length <= max && [...value].every((char) => char.charCodeAt(0) >= 32 || ["\n", "\r", " "].includes(char));
|
|
215
90
|
}
|
|
216
91
|
function parsePresentationHints(input) {
|
|
@@ -223,12 +98,12 @@ function parsePresentationHints(input) {
|
|
|
223
98
|
return null;
|
|
224
99
|
}
|
|
225
100
|
}
|
|
226
|
-
if (!
|
|
101
|
+
if (!record(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)
|
|
227
102
|
return null;
|
|
228
103
|
const ids = /* @__PURE__ */ new Set();
|
|
229
104
|
const blocks = [];
|
|
230
105
|
for (const entry of value.blocks) {
|
|
231
|
-
if (!
|
|
106
|
+
if (!record(entry) || !exact(entry, ["blockId"], ["layout", "inbetweens", "wording", "ai", "build", "hidden"]) || !text(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(
|
|
232
107
|
(key) => typeof key === "string" && /^[0-9a-z]{1,7}-[0-9a-z]{1,4}$/u.test(key)
|
|
233
108
|
)))
|
|
234
109
|
return null;
|
|
@@ -245,7 +120,10 @@ function parsePresentationHints(input) {
|
|
|
245
120
|
if (!Array.isArray(entry.ai) || entry.ai.length > 80) return null;
|
|
246
121
|
hint.ai = [];
|
|
247
122
|
for (const item of entry.ai) {
|
|
248
|
-
if (!
|
|
123
|
+
if (!record(item) || !exact(item, ["source", "layout", "headline", "points"], ["center", "xAxis", "yAxis"]) || !text(item.source, 4e3) || !PRESENTATION_LAYOUTS.includes(item.layout) || !text(item.headline, 110) || !Array.isArray(item.points) || item.points.length > PRESENTATION_LIMITS.points || !item.points.every((point) => text(point, 180)) || // An extra is saved only on the layout that draws it, as it will be set.
|
|
124
|
+
["center", "xAxis", "yAxis"].some(
|
|
125
|
+
(key) => key in item && item[key] !== presentationBeatExtras(String(item.layout), item)[key]
|
|
126
|
+
) || !presentationLayoutFits(
|
|
249
127
|
item.layout,
|
|
250
128
|
item.headline,
|
|
251
129
|
item.points,
|
|
@@ -256,13 +134,14 @@ function parsePresentationHints(input) {
|
|
|
256
134
|
source: item.source,
|
|
257
135
|
layout: item.layout,
|
|
258
136
|
headline: item.headline,
|
|
259
|
-
points: [...item.points]
|
|
137
|
+
points: [...item.points],
|
|
138
|
+
...presentationBeatExtras(String(item.layout), item)
|
|
260
139
|
});
|
|
261
140
|
}
|
|
262
141
|
}
|
|
263
142
|
if (entry.wording !== void 0) {
|
|
264
143
|
const wording = entry.wording;
|
|
265
|
-
if (!
|
|
144
|
+
if (!record(wording) || !exact(wording, ["source"], ["headline", "points"]) || !text(wording.source, 4e4) || wording.headline === void 0 && wording.points === void 0 || wording.headline !== void 0 && !text(wording.headline, 110) || wording.points !== void 0 && (!Array.isArray(wording.points) || wording.points.length > PRESENTATION_LIMITS.points || !wording.points.every((point) => text(point, 180))))
|
|
266
145
|
return null;
|
|
267
146
|
hint.wording = {
|
|
268
147
|
source: wording.source,
|
|
@@ -589,13 +468,13 @@ function maskNonProse(stripped, contents) {
|
|
|
589
468
|
let masked = stripped;
|
|
590
469
|
let cursor = 0;
|
|
591
470
|
for (const node of contents) {
|
|
592
|
-
const
|
|
593
|
-
if (!
|
|
594
|
-
const at = stripped.indexOf(
|
|
471
|
+
const text2 = stripMarkdown(extractPlainText(node));
|
|
472
|
+
if (!text2) continue;
|
|
473
|
+
const at = stripped.indexOf(text2, cursor);
|
|
595
474
|
if (at < 0) continue;
|
|
596
|
-
cursor = at +
|
|
475
|
+
cursor = at + text2.length;
|
|
597
476
|
if (PROSE_NODE_TYPES.has(node.type)) continue;
|
|
598
|
-
masked = masked.slice(0, at) +
|
|
477
|
+
masked = masked.slice(0, at) + text2.replace(/\S/g, " ") + masked.slice(cursor);
|
|
599
478
|
}
|
|
600
479
|
return masked;
|
|
601
480
|
}
|
|
@@ -897,8 +776,8 @@ var PROSE_KEYS = /* @__PURE__ */ new Set([
|
|
|
897
776
|
"quote",
|
|
898
777
|
"text"
|
|
899
778
|
]);
|
|
900
|
-
function briefText(
|
|
901
|
-
const normalized =
|
|
779
|
+
function briefText(text2) {
|
|
780
|
+
const normalized = text2.replace(/\s+/g, " ").trim();
|
|
902
781
|
const sentence = normalized.match(/^.*?[.!?](?:["'”’])?(?=\s|$)/)?.[0] ?? normalized;
|
|
903
782
|
const words = sentence.split(/\s+/).filter(Boolean);
|
|
904
783
|
let brief = words.slice(0, 24).join(" ");
|
|
@@ -959,11 +838,11 @@ function extractFeatureContents(contents, keepData = false) {
|
|
|
959
838
|
for (const node of contents ?? []) visit(node);
|
|
960
839
|
return features;
|
|
961
840
|
}
|
|
962
|
-
function withoutProse(
|
|
963
|
-
return
|
|
841
|
+
function withoutProse(record2) {
|
|
842
|
+
return record2 && Object.fromEntries(Object.entries(record2).filter(([key]) => !PROSE_KEYS.has(key)));
|
|
964
843
|
}
|
|
965
844
|
function typedMediaContents(block, bodyMedia) {
|
|
966
|
-
const
|
|
845
|
+
const record2 = {
|
|
967
846
|
...block,
|
|
968
847
|
...block.templateData,
|
|
969
848
|
...coerceTemplateParams(block.template ?? "", block.templateOverrides ?? {}).input
|
|
@@ -979,23 +858,23 @@ function typedMediaContents(block, bodyMedia) {
|
|
|
979
858
|
});
|
|
980
859
|
}
|
|
981
860
|
};
|
|
982
|
-
addImage(
|
|
861
|
+
addImage(record2.imageSrc, record2.imageAlt);
|
|
983
862
|
for (const key of ["accentImage", "backgroundImage"]) {
|
|
984
|
-
const image =
|
|
863
|
+
const image = record2[key];
|
|
985
864
|
if (image && typeof image === "object") {
|
|
986
865
|
const data = image;
|
|
987
866
|
addImage(data.src, data.alt);
|
|
988
867
|
}
|
|
989
868
|
}
|
|
990
|
-
if (Array.isArray(
|
|
991
|
-
for (const image of
|
|
869
|
+
if (Array.isArray(record2.images)) {
|
|
870
|
+
for (const image of record2.images) {
|
|
992
871
|
if (image && typeof image === "object") {
|
|
993
872
|
const data = image;
|
|
994
873
|
addImage(data.src, data.alt);
|
|
995
874
|
}
|
|
996
875
|
}
|
|
997
876
|
}
|
|
998
|
-
if (typeof
|
|
877
|
+
if (typeof record2.videoSrc === "string" && record2.videoSrc) {
|
|
999
878
|
const htmlChildren = [
|
|
1000
879
|
{
|
|
1001
880
|
type: "htmlElement",
|
|
@@ -1003,8 +882,8 @@ function typedMediaContents(block, bodyMedia) {
|
|
|
1003
882
|
selfClosing: false,
|
|
1004
883
|
children: [],
|
|
1005
884
|
attributes: {
|
|
1006
|
-
src:
|
|
1007
|
-
...typeof
|
|
885
|
+
src: record2.videoSrc,
|
|
886
|
+
...typeof record2.posterSrc === "string" ? { poster: record2.posterSrc } : {}
|
|
1008
887
|
}
|
|
1009
888
|
}
|
|
1010
889
|
];
|
|
@@ -1636,21 +1515,21 @@ function standaloneImagePool(images, content) {
|
|
|
1636
1515
|
...available.filter((image) => accents.has(image.src))
|
|
1637
1516
|
];
|
|
1638
1517
|
}
|
|
1639
|
-
function chunkNarration(
|
|
1640
|
-
if (count <= 1) return [
|
|
1518
|
+
function chunkNarration(text2, count) {
|
|
1519
|
+
if (count <= 1) return [text2];
|
|
1641
1520
|
const sentences = [];
|
|
1642
1521
|
const boundary = /[.!?]["'’”)\]]*\s+/g;
|
|
1643
1522
|
let start = 0;
|
|
1644
1523
|
let match;
|
|
1645
|
-
while ((match = boundary.exec(
|
|
1524
|
+
while ((match = boundary.exec(text2)) !== null) {
|
|
1646
1525
|
const end = match.index + match[0].length;
|
|
1647
|
-
const sentence =
|
|
1526
|
+
const sentence = text2.slice(start, end).trim();
|
|
1648
1527
|
if (sentence) sentences.push(sentence);
|
|
1649
1528
|
start = end;
|
|
1650
1529
|
}
|
|
1651
|
-
const tail =
|
|
1530
|
+
const tail = text2.slice(start).trim();
|
|
1652
1531
|
if (tail) sentences.push(tail);
|
|
1653
|
-
if (sentences.length < 2) return [
|
|
1532
|
+
if (sentences.length < 2) return [text2];
|
|
1654
1533
|
const chunkCount = Math.min(count, sentences.length);
|
|
1655
1534
|
const words = sentences.map((sentence) => sentence.split(/\s+/).length);
|
|
1656
1535
|
const totalWords = words.reduce((sum, n) => sum + n, 0);
|
|
@@ -1721,6 +1600,51 @@ function videoBlock(video, index, segmentId, duration) {
|
|
|
1721
1600
|
};
|
|
1722
1601
|
}
|
|
1723
1602
|
|
|
1603
|
+
// src/transform/conceptReveal.ts
|
|
1604
|
+
function stems(text2) {
|
|
1605
|
+
return (text2.toLowerCase().match(/[\p{L}\p{N}][\p{L}\p{N}'-]*/gu) ?? []).filter((word) => word.length >= 4).map((word) => word.slice(0, 5));
|
|
1606
|
+
}
|
|
1607
|
+
function matchPointsToSentences(points, sourceText, start, end) {
|
|
1608
|
+
const passage = sourceText.slice(start, end);
|
|
1609
|
+
const sentences = [...passage.matchAll(/[^.!?\n]+[.!?]*/gu)].map((match) => ({
|
|
1610
|
+
offset: start + match.index,
|
|
1611
|
+
words: new Set(stems(match[0]))
|
|
1612
|
+
}));
|
|
1613
|
+
let last = -1;
|
|
1614
|
+
const offsets = [];
|
|
1615
|
+
for (const point of points) {
|
|
1616
|
+
const words = stems(point);
|
|
1617
|
+
let best;
|
|
1618
|
+
for (const sentence of sentences) {
|
|
1619
|
+
const shared = words.filter((word) => sentence.words.has(word)).length;
|
|
1620
|
+
if (shared > (best?.shared ?? 1)) best = { offset: sentence.offset, shared };
|
|
1621
|
+
}
|
|
1622
|
+
if (!best || best.offset < last) return void 0;
|
|
1623
|
+
offsets.push(last = best.offset);
|
|
1624
|
+
}
|
|
1625
|
+
return offsets;
|
|
1626
|
+
}
|
|
1627
|
+
function conceptBuildSpec() {
|
|
1628
|
+
return { mode: "items", effect: "fadeInUp", previous: "keep" };
|
|
1629
|
+
}
|
|
1630
|
+
function conceptRevealTiming(template, items, itemTimes, start, end) {
|
|
1631
|
+
const build = conceptBuildSpec();
|
|
1632
|
+
const steps = conceptBuildStepTexts(template, items);
|
|
1633
|
+
if (!itemTimes || itemTimes.length !== steps.length) return { build };
|
|
1634
|
+
const lead = Math.min(0.5, (end - start) / 8);
|
|
1635
|
+
const starts = itemTimes.map(
|
|
1636
|
+
(time) => Math.min(Math.max(0, end - start - 0.1), Math.max(lead, time - start))
|
|
1637
|
+
);
|
|
1638
|
+
starts[0] = Math.min(starts[0], Math.max(lead, Math.min(1, (end - start) / 6)));
|
|
1639
|
+
return {
|
|
1640
|
+
build,
|
|
1641
|
+
buildTiming: {
|
|
1642
|
+
sourceText: buildSourceText(steps.map((text2, index) => ({ id: `build-${index}`, text: text2 }))),
|
|
1643
|
+
starts
|
|
1644
|
+
}
|
|
1645
|
+
};
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1724
1648
|
// src/transform/presentationMedia.ts
|
|
1725
1649
|
function presentationBlockImages(doc) {
|
|
1726
1650
|
const own = /* @__PURE__ */ new Map();
|
|
@@ -1810,6 +1734,7 @@ function presentationMediaNode(item, elapsed) {
|
|
|
1810
1734
|
|
|
1811
1735
|
// src/transform/presentationPlanner.ts
|
|
1812
1736
|
var SENTENCE_END = /[.!?][”"')\]]?$/u;
|
|
1737
|
+
var ABBREVIATION = /(?:^|[\s(“"‘'])(?:\p{Lu}|(?:\p{Lu}\.)+\p{Lu}|Mr|Mrs|Ms|Mx|Dr|Prof|Sr|Jr|St|Mt|Ft|Gen|Col|Lt|Capt|Sgt|Cmdr|Adm|Gov|Sen|Rep|Rev|Hon|vs|etc|e\.g|i\.e|cf|ca|approx|est|No|Fig|Inc|Ltd|Co|Corp)\.$/u;
|
|
1813
1738
|
var SENTENCE_START = /^[\p{Lu}\p{N}"“‘'([]/u;
|
|
1814
1739
|
var SEQUENCE_CUE = /^(?:(?:first|second|third|fourth)(?:ly)?|then|next|after\b|afterwards|at that point|eventually|finally|lastly)\b|^\d+[.)]\s/iu;
|
|
1815
1740
|
var ORDINAL_OPENER = /^(?:(?:first|second|third|fourth)(?:ly)?|then|next|after that|afterwards|finally|lastly),?\s+/iu;
|
|
@@ -1817,19 +1742,19 @@ function stagePoint(sentence) {
|
|
|
1817
1742
|
const rest = sentence.replace(ORDINAL_OPENER, "");
|
|
1818
1743
|
return pointText(rest === sentence ? sentence : `${rest[0].toUpperCase()}${rest.slice(1)}`);
|
|
1819
1744
|
}
|
|
1820
|
-
var CYCLE_CUE = /\b(?:cycles?|cyclical|repeats?|over and over|again and again|loop)\b/iu;
|
|
1821
1745
|
var DEFINES = /^(?:the |an? )?((?:[\p{Lu}][\p{L}'’-]*|[\p{Ll}][\p{L}'’-]*)(?: [\p{L}'’()-]+){0,3}?) (?:is|are|was|were) (?:an? |the )?(.{12,})$/u;
|
|
1822
1746
|
var PRONOUN = /^(?:it|its|this|that|these|those|there|they|their|he|his|she|her|we|our|you|your|i|my|which|one|each|some|to|so|but|and|or)$/iu;
|
|
1823
1747
|
function labelledPoint(sentence) {
|
|
1824
1748
|
const match = sentence.replace(/\s+/gu, " ").trim().match(DEFINES);
|
|
1825
|
-
|
|
1749
|
+
const clauses = match && /[,;]\s+(?:and\s+)?[^,;]*?\s(?:is|are|was|were)\s/u.test(match[2]);
|
|
1750
|
+
if (match && !clauses && !PRONOUN.test(match[1].split(" ")[0])) {
|
|
1826
1751
|
const label = match[1];
|
|
1827
1752
|
return clip(`${label[0].toUpperCase()}${label.slice(1)}: ${match[2]}`, Infinity, 160);
|
|
1828
1753
|
}
|
|
1829
1754
|
return clip(sentence, Infinity, 160);
|
|
1830
1755
|
}
|
|
1831
|
-
function clip(
|
|
1832
|
-
const clean =
|
|
1756
|
+
function clip(text2, words, characters) {
|
|
1757
|
+
const clean = text2.replace(/\s+/gu, " ").trim();
|
|
1833
1758
|
const parts = clean.split(" ");
|
|
1834
1759
|
let result = parts.length > words ? parts.slice(0, words).join(" ") : clean;
|
|
1835
1760
|
if (result.length > characters - 1) {
|
|
@@ -1839,13 +1764,13 @@ function clip(text3, words, characters) {
|
|
|
1839
1764
|
}
|
|
1840
1765
|
return result === clean ? clean : result.replace(/[\s,;:–—-]+$/u, "") + "\u2026";
|
|
1841
1766
|
}
|
|
1842
|
-
var headlineText = (
|
|
1843
|
-
var pointText = (
|
|
1844
|
-
var captionText = (
|
|
1767
|
+
var headlineText = (text2) => clip(text2, 12, 110);
|
|
1768
|
+
var pointText = (text2) => clip(text2, Infinity, 180);
|
|
1769
|
+
var captionText = (text2) => clip(text2, 18, 110);
|
|
1845
1770
|
var FEATURE_POINTS = 2;
|
|
1846
1771
|
var FEATURE_POINT_CHARACTERS = 100;
|
|
1847
|
-
function featurePointText(
|
|
1848
|
-
const clean =
|
|
1772
|
+
function featurePointText(text2) {
|
|
1773
|
+
const clean = text2.replace(/\s+/gu, " ").trim();
|
|
1849
1774
|
if (clean.length <= FEATURE_POINT_CHARACTERS) return clean;
|
|
1850
1775
|
const head = clean.slice(0, FEATURE_POINT_CHARACTERS);
|
|
1851
1776
|
const clause = Math.max(
|
|
@@ -1859,19 +1784,30 @@ function sentencesIn(sourceText, start, end) {
|
|
|
1859
1784
|
let cursor = 0;
|
|
1860
1785
|
const add = (to) => {
|
|
1861
1786
|
const raw = passage.slice(cursor, to);
|
|
1862
|
-
const
|
|
1863
|
-
if (!
|
|
1864
|
-
const from = start + cursor + raw.indexOf(
|
|
1865
|
-
sentences.push({ text:
|
|
1787
|
+
const text2 = raw.trim();
|
|
1788
|
+
if (!text2) return;
|
|
1789
|
+
const from = start + cursor + raw.indexOf(text2);
|
|
1790
|
+
sentences.push({ text: text2, start: from, end: from + text2.length });
|
|
1866
1791
|
};
|
|
1867
1792
|
for (const match of passage.matchAll(/(?<=[.!?][”"')\]]?)\s+(?=[\p{Lu}\p{N}"“‘'([])|\n+/gu)) {
|
|
1793
|
+
if (!match[0].includes("\n") && ABBREVIATION.test(passage.slice(cursor, match.index))) continue;
|
|
1868
1794
|
add(match.index);
|
|
1869
1795
|
cursor = match.index + match[0].length;
|
|
1870
1796
|
}
|
|
1871
1797
|
add(passage.length);
|
|
1872
1798
|
return sentences;
|
|
1873
1799
|
}
|
|
1874
|
-
var
|
|
1800
|
+
var STAT_SENTENCE_CHARACTERS = 120;
|
|
1801
|
+
var STAT_SPACING = 3;
|
|
1802
|
+
var YEAR = /^(?:1\d{3}|20\d{2})$/u;
|
|
1803
|
+
function strikingFigure(sentence) {
|
|
1804
|
+
if (sentence.length > STAT_SENTENCE_CHARACTERS) return void 0;
|
|
1805
|
+
const value = matchNumberHighlight(sentence)?.value.trim();
|
|
1806
|
+
if (!value || YEAR.test(value)) return void 0;
|
|
1807
|
+
return /[%‰$€£¥×,]|\d\s?(?:[xKMB]|million|billion|thousand|percent|times)\b/iu.test(value) || /\d{4,}/u.test(value) ? value : void 0;
|
|
1808
|
+
}
|
|
1809
|
+
var EMPHASIS_SENTENCE_CHARACTERS = 60;
|
|
1810
|
+
var comparable = (text2) => text2.toLowerCase().replace(/\s+/gu, " ").replace(/[\s….!?,;:]+$/u, "").trim();
|
|
1875
1811
|
function repeats(sentence, headline) {
|
|
1876
1812
|
const body = comparable(sentence);
|
|
1877
1813
|
const head = comparable(headline);
|
|
@@ -1879,7 +1815,7 @@ function repeats(sentence, headline) {
|
|
|
1879
1815
|
}
|
|
1880
1816
|
function chunkWords(words, limit) {
|
|
1881
1817
|
const chunks = [];
|
|
1882
|
-
const ends = (count) => SENTENCE_END.test(words[count - 1][0]) && (count >= words.length || SENTENCE_START.test(words[count][0]));
|
|
1818
|
+
const ends = (count) => SENTENCE_END.test(words[count - 1][0]) && (count >= words.length || SENTENCE_START.test(words[count][0]) && !ABBREVIATION.test(words[count - 1][0]));
|
|
1883
1819
|
let first = 0;
|
|
1884
1820
|
while (first < words.length) {
|
|
1885
1821
|
let last = Math.min(first + limit, words.length);
|
|
@@ -1889,6 +1825,8 @@ function chunkWords(words, limit) {
|
|
|
1889
1825
|
const reach = Math.min(words.length, first + Math.ceil(limit * 1.5));
|
|
1890
1826
|
for (let cursor = last + 1; cursor <= reach && !cut; cursor++) if (ends(cursor)) cut = cursor;
|
|
1891
1827
|
if (cut) last = cut;
|
|
1828
|
+
if (words.length - last < limit / 2 && words.length - first <= Math.ceil(limit * 1.5))
|
|
1829
|
+
last = words.length;
|
|
1892
1830
|
}
|
|
1893
1831
|
chunks.push([first, last]);
|
|
1894
1832
|
first = last;
|
|
@@ -1913,11 +1851,11 @@ function featureSpans(sourceText, from, to, items) {
|
|
|
1913
1851
|
let cursor = from;
|
|
1914
1852
|
for (const item of items) {
|
|
1915
1853
|
if (item.kind === "image") continue;
|
|
1916
|
-
const
|
|
1917
|
-
const at =
|
|
1918
|
-
if (at < 0 || at +
|
|
1919
|
-
spans.push([at, at +
|
|
1920
|
-
cursor = at +
|
|
1854
|
+
const text2 = extractPlainText(item.node).trim();
|
|
1855
|
+
const at = text2 ? sourceText.indexOf(text2, cursor) : -1;
|
|
1856
|
+
if (at < 0 || at + text2.length > to) continue;
|
|
1857
|
+
spans.push([at, at + text2.length]);
|
|
1858
|
+
cursor = at + text2.length;
|
|
1921
1859
|
}
|
|
1922
1860
|
return spans;
|
|
1923
1861
|
}
|
|
@@ -1938,7 +1876,14 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
1938
1876
|
doc,
|
|
1939
1877
|
script.blocks.map((block) => block.blockId)
|
|
1940
1878
|
);
|
|
1879
|
+
const drawnLists = new Set(
|
|
1880
|
+
flattenRenderableBlocks(doc.blocks).filter(
|
|
1881
|
+
(block) => !!conceptTemplate(block.template ?? "") && block.contents?.length === 1 && block.contents[0].type === "list"
|
|
1882
|
+
).map((block) => block.id)
|
|
1883
|
+
);
|
|
1941
1884
|
const beats = [];
|
|
1885
|
+
let lastStat = -Infinity;
|
|
1886
|
+
let lastEmphasis = -Infinity;
|
|
1942
1887
|
const supportingOpeners = /* @__PURE__ */ new Set();
|
|
1943
1888
|
const quotes = /* @__PURE__ */ new Map();
|
|
1944
1889
|
const perSection = hints.density === "section";
|
|
@@ -1951,7 +1896,7 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
1951
1896
|
const inbetweens = !perSection && (hint?.inbetweens ?? hints.inbetweens);
|
|
1952
1897
|
const heading = block.heading?.trim();
|
|
1953
1898
|
const headingEnd = block.charStart + (heading?.length ?? 0);
|
|
1954
|
-
if (hint?.layout === AUTHORED_PRESENTATION_LAYOUT) {
|
|
1899
|
+
if (hint?.layout === AUTHORED_PRESENTATION_LAYOUT || hint?.layout === void 0 && !wording && drawnLists.has(block.blockId)) {
|
|
1955
1900
|
if (!words.length) continue;
|
|
1956
1901
|
const start = block.charStart + words[0].index;
|
|
1957
1902
|
const last = words[words.length - 1];
|
|
@@ -2034,13 +1979,23 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
2034
1979
|
const cardPoints = shown.slice(0, 4).map((item) => labelledPoint(item.text));
|
|
2035
1980
|
const custom = chunk === 0 ? wording : void 0;
|
|
2036
1981
|
if (custom?.headline) headline = custom.headline;
|
|
2037
|
-
const pointsFor = (layout2) => custom?.points ?? (["steps", "process", "cycle"].includes(layout2) ? stepPoints : layout2 === "cards" ? cardPoints : textPoints);
|
|
1982
|
+
const pointsFor = (layout2) => custom?.points ?? (["steps", "process", "cycle"].includes(layout2) ? stepPoints : layout2 === "cards" ? cardPoints : layout2 === "stat" && statPoints ? statPoints : layout2 === "emphasis" && takeaway ? [] : textPoints);
|
|
2038
1983
|
const quote = custom?.headline ? void 0 : body.find((sentence) => sentence.text.length <= 110)?.text;
|
|
2039
|
-
const headlineFor = (layout2) => layout2 === "quote" && quote ? quote : headline;
|
|
1984
|
+
const headlineFor = (layout2) => layout2 === "quote" && quote ? quote : layout2 === "emphasis" && takeaway ? headlineText(takeaway) : headline;
|
|
2040
1985
|
let layout = index === 0 ? "title" : textPoints.length >= 2 ? "cards" : "statement";
|
|
2041
|
-
if (sequence)
|
|
1986
|
+
if (sequence)
|
|
1987
|
+
layout = steps.length >= 3 && shapeIsStated("cycle", { heading, passage: prose, items: stepPoints }) ? "cycle" : "steps";
|
|
2042
1988
|
else if (textPoints.length === 2 && /\b(versus|whereas|compared|instead)\b/iu.test(prose))
|
|
2043
1989
|
layout = "comparison";
|
|
1990
|
+
const figureLine = !sequence && !custom && index > 0 && index - lastStat >= STAT_SPACING ? shown.find((sentence) => strikingFigure(sentence.text)) : void 0;
|
|
1991
|
+
const statPoints = figureLine ? [
|
|
1992
|
+
pointText(figureLine.text),
|
|
1993
|
+
...shown.filter((sentence) => sentence !== figureLine && !strikingFigure(sentence.text)).slice(0, 1).map((item) => pointText(item.text))
|
|
1994
|
+
] : void 0;
|
|
1995
|
+
if (statPoints && !matchNumberHighlight(headline) && presentationLayoutFits("stat", headline, statPoints, passage))
|
|
1996
|
+
layout = "stat";
|
|
1997
|
+
const takeaway = layout === "statement" && !!heading && chunk > 0 && index - lastEmphasis >= 2 && shown.length === 1 && shown[0].text.length <= EMPHASIS_SENTENCE_CHARACTERS ? shown[0].text : void 0;
|
|
1998
|
+
if (takeaway) layout = "emphasis";
|
|
2044
1999
|
if (image) layout = "image";
|
|
2045
2000
|
if (preferred && (preferred === "image" ? !!image : presentationLayoutFits(
|
|
2046
2001
|
preferred,
|
|
@@ -2059,6 +2014,8 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
2059
2014
|
...layout === "image" && image?.src ? { imageSrc: image.src } : {}
|
|
2060
2015
|
};
|
|
2061
2016
|
if (quote) quotes.set(beat.id, quote);
|
|
2017
|
+
if (beat.layout === "stat") lastStat = index;
|
|
2018
|
+
if (beat.layout === "emphasis") lastEmphasis = index;
|
|
2062
2019
|
let split;
|
|
2063
2020
|
if (inbetweens && !custom?.points && layout === "steps" && sequence) {
|
|
2064
2021
|
if (shown.some((sentence) => sentence.end <= steps[0].start)) split = steps[0].start;
|
|
@@ -2132,6 +2089,7 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
2132
2089
|
beat.headline = cached.headline;
|
|
2133
2090
|
beat.points = [...cached.points];
|
|
2134
2091
|
beat.layout = cached.layout;
|
|
2092
|
+
Object.assign(beat, presentationBeatExtras(cached.layout, cached));
|
|
2135
2093
|
suggested.add(beat.id);
|
|
2136
2094
|
origin = "ai";
|
|
2137
2095
|
}
|
|
@@ -2189,56 +2147,14 @@ function createPresentationPlan(doc, hints = defaultPresentationHints()) {
|
|
|
2189
2147
|
))
|
|
2190
2148
|
beat.layout = "statement";
|
|
2191
2149
|
}
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
return CONCEPT_TEMPLATES.find((name) => name === template);
|
|
2199
|
-
}
|
|
2200
|
-
function stems(text3) {
|
|
2201
|
-
return (text3.toLowerCase().match(/[\p{L}\p{N}][\p{L}\p{N}'-]*/gu) ?? []).filter((word) => word.length >= 4).map((word) => word.slice(0, 5));
|
|
2202
|
-
}
|
|
2203
|
-
function matchPointsToSentences(points, sourceText, start, end) {
|
|
2204
|
-
const passage = sourceText.slice(start, end);
|
|
2205
|
-
const sentences = [...passage.matchAll(/[^.!?\n]+[.!?]*/gu)].map((match) => ({
|
|
2206
|
-
offset: start + match.index,
|
|
2207
|
-
words: new Set(stems(match[0]))
|
|
2208
|
-
}));
|
|
2209
|
-
let last = -1;
|
|
2210
|
-
const offsets = [];
|
|
2211
|
-
for (const point of points) {
|
|
2212
|
-
const words = stems(point);
|
|
2213
|
-
let best;
|
|
2214
|
-
for (const sentence of sentences) {
|
|
2215
|
-
const shared = words.filter((word) => sentence.words.has(word)).length;
|
|
2216
|
-
if (shared > (best?.shared ?? 1)) best = { offset: sentence.offset, shared };
|
|
2217
|
-
}
|
|
2218
|
-
if (!best || best.offset < last) return void 0;
|
|
2219
|
-
offsets.push(last = best.offset);
|
|
2150
|
+
for (const beat of beats) {
|
|
2151
|
+
const extras = presentationBeatExtras(beat.layout, beat);
|
|
2152
|
+
delete beat.center;
|
|
2153
|
+
delete beat.xAxis;
|
|
2154
|
+
delete beat.yAxis;
|
|
2155
|
+
Object.assign(beat, extras);
|
|
2220
2156
|
}
|
|
2221
|
-
return
|
|
2222
|
-
}
|
|
2223
|
-
function conceptBuildSpec() {
|
|
2224
|
-
return { mode: "items", effect: "fadeInUp", previous: "keep" };
|
|
2225
|
-
}
|
|
2226
|
-
function conceptRevealTiming(template, items, itemTimes, start, end) {
|
|
2227
|
-
const build = conceptBuildSpec();
|
|
2228
|
-
const steps = conceptBuildStepTexts(template, items);
|
|
2229
|
-
if (!itemTimes || itemTimes.length !== steps.length) return { build };
|
|
2230
|
-
const lead = Math.min(0.5, (end - start) / 8);
|
|
2231
|
-
const starts = itemTimes.map(
|
|
2232
|
-
(time) => Math.min(Math.max(0, end - start - 0.1), Math.max(lead, time - start))
|
|
2233
|
-
);
|
|
2234
|
-
starts[0] = Math.min(starts[0], Math.max(lead, Math.min(1, (end - start) / 6)));
|
|
2235
|
-
return {
|
|
2236
|
-
build,
|
|
2237
|
-
buildTiming: {
|
|
2238
|
-
sourceText: buildSourceText(steps.map((text3, index) => ({ id: `build-${index}`, text: text3 }))),
|
|
2239
|
-
starts
|
|
2240
|
-
}
|
|
2241
|
-
};
|
|
2157
|
+
return { version: 1, sourceText: script.sourceText, origin, beats };
|
|
2242
2158
|
}
|
|
2243
2159
|
|
|
2244
2160
|
// src/transform/presentationCompiler.ts
|
|
@@ -2397,11 +2313,15 @@ function compilePresentationPlan(doc, plan) {
|
|
|
2397
2313
|
if (beat.layout === AUTHORED_PRESENTATION_LAYOUT) {
|
|
2398
2314
|
if (!authored) throw new Error("A section shown as authored is no longer in the document.");
|
|
2399
2315
|
const { children, media: _media, ...own } = authored;
|
|
2316
|
+
const drawn = conceptTemplate(authored.template ?? "");
|
|
2317
|
+
const given = authored.templateData?.items;
|
|
2318
|
+
const items = drawn && !build ? Array.isArray(given) ? given.map((item) => String(item ?? "")) : extractConceptItems(authored.contents) : [];
|
|
2400
2319
|
blocks.push({
|
|
2401
2320
|
...own,
|
|
2402
2321
|
...base,
|
|
2403
2322
|
...children && isContainerTemplate(authored.template) ? { children } : {},
|
|
2404
|
-
transition: authored.transition ?? base.transition
|
|
2323
|
+
transition: authored.transition ?? base.transition,
|
|
2324
|
+
...drawn && items.length ? conceptReveal(drawn, { ...beat, points: items }, start, end, script.sourceText, timeAt) : {}
|
|
2405
2325
|
});
|
|
2406
2326
|
continue;
|
|
2407
2327
|
}
|
|
@@ -2437,9 +2357,9 @@ function conceptReveal(template, beat, start, end, sourceText, timeAt) {
|
|
|
2437
2357
|
return conceptRevealTiming(template, beat.points, offsets?.map(timeAt), start, end);
|
|
2438
2358
|
}
|
|
2439
2359
|
function tableFeatureBlock(beat, layout, base, features) {
|
|
2440
|
-
const paragraph = (
|
|
2360
|
+
const paragraph = (text2) => ({
|
|
2441
2361
|
type: "paragraph",
|
|
2442
|
-
children: [{ type: "text", value:
|
|
2362
|
+
children: [{ type: "text", value: text2 }]
|
|
2443
2363
|
});
|
|
2444
2364
|
const words = ["list", "steps", "comparison"].includes(layout) && beat.points.length > 1 ? [
|
|
2445
2365
|
{
|
|
@@ -2516,6 +2436,28 @@ function visualBlock(beat, layout, base, index) {
|
|
|
2516
2436
|
return { ...base, template: "cycle", title: beat.headline, items: beat.points };
|
|
2517
2437
|
case "layers":
|
|
2518
2438
|
return { ...base, template: "layers", title: beat.headline, items: beat.points };
|
|
2439
|
+
case "stats":
|
|
2440
|
+
case "pyramid":
|
|
2441
|
+
case "funnel":
|
|
2442
|
+
case "venn":
|
|
2443
|
+
return { ...base, template: layout, title: beat.headline, items: beat.points };
|
|
2444
|
+
case "hub":
|
|
2445
|
+
return {
|
|
2446
|
+
...base,
|
|
2447
|
+
template: "hub",
|
|
2448
|
+
title: beat.headline,
|
|
2449
|
+
items: beat.points,
|
|
2450
|
+
...beat.center ? { center: beat.center } : {}
|
|
2451
|
+
};
|
|
2452
|
+
case "matrix":
|
|
2453
|
+
return {
|
|
2454
|
+
...base,
|
|
2455
|
+
template: "matrix",
|
|
2456
|
+
title: beat.headline,
|
|
2457
|
+
items: beat.points,
|
|
2458
|
+
...beat.xAxis ? { xAxis: beat.xAxis } : {},
|
|
2459
|
+
...beat.yAxis ? { yAxis: beat.yAxis } : {}
|
|
2460
|
+
};
|
|
2519
2461
|
}
|
|
2520
2462
|
}
|
|
2521
2463
|
function applySavedPresentation(doc) {
|
|
@@ -2547,14 +2489,6 @@ function applySavedPresentation(doc) {
|
|
|
2547
2489
|
}
|
|
2548
2490
|
|
|
2549
2491
|
export {
|
|
2550
|
-
PRESENTATION_KEY,
|
|
2551
|
-
PRESENTATION_LAYOUTS,
|
|
2552
|
-
AUTHORED_PRESENTATION_LAYOUT,
|
|
2553
|
-
presentationStat,
|
|
2554
|
-
presentationLayoutFits,
|
|
2555
|
-
PRESENTATION_LIMITS,
|
|
2556
|
-
parsePresentationPlan,
|
|
2557
|
-
serializePresentationPlan,
|
|
2558
2492
|
PRESENTATION_HINTS_KEY,
|
|
2559
2493
|
DYNAMIC_PRESENTATION_STYLE,
|
|
2560
2494
|
presentationPassageKey,
|
|
@@ -2573,13 +2507,11 @@ export {
|
|
|
2573
2507
|
allocateTiming,
|
|
2574
2508
|
applyTransform,
|
|
2575
2509
|
transformNarratedSegment,
|
|
2576
|
-
collectPresentationMedia,
|
|
2577
|
-
createPresentationPlan,
|
|
2578
|
-
CONCEPT_TEMPLATES,
|
|
2579
|
-
conceptTemplate,
|
|
2580
2510
|
matchPointsToSentences,
|
|
2581
2511
|
conceptBuildSpec,
|
|
2582
2512
|
conceptRevealTiming,
|
|
2513
|
+
collectPresentationMedia,
|
|
2514
|
+
createPresentationPlan,
|
|
2583
2515
|
compilePresentationPlan,
|
|
2584
2516
|
applySavedPresentation
|
|
2585
2517
|
};
|