@bendyline/squisq 2.13.7 → 2.13.9
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/{chunk-DOKSRBW2.js → chunk-3BIKSQTM.js} +1 -1
- package/dist/{chunk-TTJZXUQA.js → chunk-L3VQQ3WT.js} +3 -1
- package/dist/{chunk-MWJSEKM3.js → chunk-QVNMPBS3.js} +182 -19
- package/dist/{chunk-NGQ5TJVX.js → chunk-R2J7CQJZ.js} +254 -207
- package/dist/{chunk-CJYN3MTX.js → chunk-VMKRN7TB.js} +2 -2
- package/dist/doc/index.d.ts +151 -2
- package/dist/doc/index.js +14 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +15 -5
- package/dist/narration/index.js +3 -3
- package/dist/recommend/index.js +1 -1
- package/dist/transform/index.js +3 -3
- package/package.json +1 -1
|
@@ -18,6 +18,196 @@ import {
|
|
|
18
18
|
walkMarkdownTree
|
|
19
19
|
} from "./chunk-L3KSFLTP.js";
|
|
20
20
|
|
|
21
|
+
// src/doc/standaloneAnnotation.ts
|
|
22
|
+
function parseAnnotationInner(inner) {
|
|
23
|
+
const tokens = tokenizeAttrTokens(inner.trim());
|
|
24
|
+
const firstIsParam = tokens.length > 0 && tokens[0].indexOf("=") > 0;
|
|
25
|
+
const template = firstIsParam || tokens.length === 0 ? void 0 : tokens[0];
|
|
26
|
+
const startIdx = firstIsParam ? 0 : 1;
|
|
27
|
+
const params = {};
|
|
28
|
+
for (let i = startIdx; i < tokens.length; i++) {
|
|
29
|
+
const kv = splitKeyValueToken(tokens[i]);
|
|
30
|
+
if (kv) params[kv.key] = kv.value;
|
|
31
|
+
}
|
|
32
|
+
return { template, params };
|
|
33
|
+
}
|
|
34
|
+
function parseStandaloneAnnotation(node) {
|
|
35
|
+
if (node.type !== "paragraph") return null;
|
|
36
|
+
const children = node.children ?? [];
|
|
37
|
+
if (children.length !== 1 || children[0].type !== "text") return null;
|
|
38
|
+
const text = children[0].value.trim();
|
|
39
|
+
const match = matchTrailingTemplateAnnotation(text);
|
|
40
|
+
if (!match || match.index !== 0) return null;
|
|
41
|
+
return parseAnnotationInner(match.inner);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/doc/mediaAnnotations.ts
|
|
45
|
+
var MEDIA_TEMPLATES = /* @__PURE__ */ new Set(["audio", "video", "media"]);
|
|
46
|
+
function isMediaAnnotationName(name) {
|
|
47
|
+
return name != null && MEDIA_TEMPLATES.has(name);
|
|
48
|
+
}
|
|
49
|
+
function time(raw) {
|
|
50
|
+
if (raw == null) return null;
|
|
51
|
+
return parseTimeSeconds(raw);
|
|
52
|
+
}
|
|
53
|
+
function videoPlacement(params) {
|
|
54
|
+
const explicit = params.placement ?? params.presentation;
|
|
55
|
+
if (explicit === "content") return "content";
|
|
56
|
+
if (explicit === "pip" || explicit === "picture-in-picture") return "picture-in-picture";
|
|
57
|
+
if (explicit === "overlay" || explicit === "full-frame") return "overlay";
|
|
58
|
+
if (params.pip === "" || params.pip === "true") return "picture-in-picture";
|
|
59
|
+
if (params.overlay === "" || params.overlay === "true") return "overlay";
|
|
60
|
+
return void 0;
|
|
61
|
+
}
|
|
62
|
+
function lockToBlock(raw) {
|
|
63
|
+
return raw !== "false" && raw !== "0";
|
|
64
|
+
}
|
|
65
|
+
function videoPipSize(raw) {
|
|
66
|
+
return raw === "small" || raw === "large" ? raw : void 0;
|
|
67
|
+
}
|
|
68
|
+
function videoPipShape(raw) {
|
|
69
|
+
return raw === "square" || raw === "wide" ? raw : void 0;
|
|
70
|
+
}
|
|
71
|
+
function videoPipPosition(raw) {
|
|
72
|
+
return raw === "top-left" || raw === "top-right" || raw === "bottom-left" || raw === "bottom-right" ? raw : void 0;
|
|
73
|
+
}
|
|
74
|
+
function toMediaClip(parsed, id) {
|
|
75
|
+
const { template, params } = parsed;
|
|
76
|
+
if (!template || !MEDIA_TEMPLATES.has(template)) return null;
|
|
77
|
+
const src = params.src;
|
|
78
|
+
if (!src) return null;
|
|
79
|
+
const kind = template === "video" ? "video" : "audio";
|
|
80
|
+
const anchor = params.anchor === "document" || params.span === "document" ? "document" : "block";
|
|
81
|
+
const clip = {
|
|
82
|
+
id,
|
|
83
|
+
src,
|
|
84
|
+
kind,
|
|
85
|
+
startAt: time(params.startAt ?? params.startTime) ?? 0,
|
|
86
|
+
anchor
|
|
87
|
+
};
|
|
88
|
+
const placement = kind === "video" ? videoPlacement(params) : void 0;
|
|
89
|
+
if (placement && placement !== "content") clip.placement = placement;
|
|
90
|
+
const pipSize = videoPipSize(params.pipSize);
|
|
91
|
+
const pipShape = videoPipShape(params.pipShape);
|
|
92
|
+
const pipPosition = videoPipPosition(params.pipPosition);
|
|
93
|
+
if (pipSize) clip.pipSize = pipSize;
|
|
94
|
+
if (pipShape) clip.pipShape = pipShape;
|
|
95
|
+
if (pipPosition) clip.pipPosition = pipPosition;
|
|
96
|
+
if (kind === "video" && placement && placement !== "content" && params.lockToBlock != null) {
|
|
97
|
+
const locked = lockToBlock(params.lockToBlock);
|
|
98
|
+
clip.lockToBlock = locked;
|
|
99
|
+
clip.anchor = locked ? "block" : "document";
|
|
100
|
+
if (locked) clip.startAt = 0;
|
|
101
|
+
}
|
|
102
|
+
const clipStart = time(params.clipStart);
|
|
103
|
+
const clipEnd = time(params.clipEnd);
|
|
104
|
+
if (clipStart != null) clip.clipStart = clipStart;
|
|
105
|
+
if (clipEnd != null) clip.clipEnd = clipEnd;
|
|
106
|
+
if (clip.lockToBlock === true) delete clip.clipEnd;
|
|
107
|
+
if (params.spillover === "true" || params.spillover === "") clip.spillover = true;
|
|
108
|
+
const edits = parseMediaEdits(mediaEditValuesFromParams(params));
|
|
109
|
+
if (edits) clip.edits = edits;
|
|
110
|
+
return clip;
|
|
111
|
+
}
|
|
112
|
+
function firstVideoElement(children) {
|
|
113
|
+
const visit = (nodes) => {
|
|
114
|
+
for (const child of nodes) {
|
|
115
|
+
if (child.type !== "htmlElement") continue;
|
|
116
|
+
if (child.tagName === "video") return child;
|
|
117
|
+
const nested = visit(child.children);
|
|
118
|
+
if (nested) return nested;
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
};
|
|
122
|
+
return visit(children);
|
|
123
|
+
}
|
|
124
|
+
function standaloneHtmlVideo(node) {
|
|
125
|
+
if (node.type === "htmlBlock") {
|
|
126
|
+
if (!/^\s*<video\b/i.test(node.rawHtml)) return null;
|
|
127
|
+
const element = firstVideoElement(node.htmlChildren);
|
|
128
|
+
return element ? { element, raw: node.rawHtml.trim() } : null;
|
|
129
|
+
}
|
|
130
|
+
if (node.type !== "paragraph" || !node.children.every((child) => child.type === "htmlInline")) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const raw = node.children.map((child) => child.type === "htmlInline" ? child.rawHtml : "").join("");
|
|
134
|
+
if (!/^\s*<video\b[\s\S]*<\/video>\s*$/i.test(raw)) return null;
|
|
135
|
+
for (const child of node.children) {
|
|
136
|
+
if (child.type !== "htmlInline") continue;
|
|
137
|
+
const element = firstVideoElement(child.htmlChildren);
|
|
138
|
+
if (element) return { element, raw: raw.trim() };
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
function isStandaloneHtmlVideo(node) {
|
|
143
|
+
return standaloneHtmlVideo(node) !== null;
|
|
144
|
+
}
|
|
145
|
+
function htmlVideoClip(node, id) {
|
|
146
|
+
const authored = standaloneHtmlVideo(node);
|
|
147
|
+
if (!authored) return null;
|
|
148
|
+
const { element } = authored;
|
|
149
|
+
const placement = videoPlacement({
|
|
150
|
+
placement: element.attributes["data-squisq-video-placement"] ?? ""
|
|
151
|
+
});
|
|
152
|
+
if (!placement || placement === "content") return null;
|
|
153
|
+
const src = element.attributes.src;
|
|
154
|
+
if (!src) return null;
|
|
155
|
+
const locked = lockToBlock(element.attributes["data-squisq-video-lock-to-block"]);
|
|
156
|
+
const clip = {
|
|
157
|
+
id,
|
|
158
|
+
src,
|
|
159
|
+
kind: "video",
|
|
160
|
+
placement,
|
|
161
|
+
lockToBlock: locked,
|
|
162
|
+
startAt: locked ? 0 : time(element.attributes["data-squisq-video-start-at"]) ?? 0,
|
|
163
|
+
anchor: locked ? "block" : "document"
|
|
164
|
+
};
|
|
165
|
+
const pipSize = videoPipSize(element.attributes["data-squisq-video-pip-size"]);
|
|
166
|
+
const pipShape = videoPipShape(element.attributes["data-squisq-video-pip-shape"]);
|
|
167
|
+
const pipPosition = videoPipPosition(element.attributes["data-squisq-video-pip-position"]);
|
|
168
|
+
if (pipSize) clip.pipSize = pipSize;
|
|
169
|
+
if (pipShape) clip.pipShape = pipShape;
|
|
170
|
+
if (pipPosition) clip.pipPosition = pipPosition;
|
|
171
|
+
const clipStart = time(element.attributes["data-squisq-video-clip-start"]);
|
|
172
|
+
const clipEnd = time(element.attributes["data-squisq-video-clip-end"]);
|
|
173
|
+
if (clipStart != null) clip.clipStart = clipStart;
|
|
174
|
+
if (!locked && clipEnd != null) clip.clipEnd = clipEnd;
|
|
175
|
+
const edits = parseMediaEdits(mediaEditValuesFromAttributes("video", element.attributes));
|
|
176
|
+
if (edits) clip.edits = edits;
|
|
177
|
+
return clip;
|
|
178
|
+
}
|
|
179
|
+
function extractMediaFromContents(contents, makeId, blockId) {
|
|
180
|
+
const media = [];
|
|
181
|
+
const documentMedia = [];
|
|
182
|
+
const remaining = [];
|
|
183
|
+
let index = 0;
|
|
184
|
+
let originalIndex = 0;
|
|
185
|
+
for (const node of contents ?? []) {
|
|
186
|
+
const parsed = parseStandaloneAnnotation(node);
|
|
187
|
+
const clip = parsed ? toMediaClip(parsed, "") : htmlVideoClip(node, "");
|
|
188
|
+
if (clip) {
|
|
189
|
+
clip.id = makeId(clip.src, index++);
|
|
190
|
+
const line = node.position?.start.line;
|
|
191
|
+
if (line != null) clip.sourceLine = line;
|
|
192
|
+
if (blockId !== void 0) {
|
|
193
|
+
const authoredHtml = standaloneHtmlVideo(node);
|
|
194
|
+
const rawText = node.type === "paragraph" && node.children?.[0]?.type === "text" ? node.children[0].value.trim() : authoredHtml?.raw;
|
|
195
|
+
clip.origin = {
|
|
196
|
+
blockId,
|
|
197
|
+
index: originalIndex,
|
|
198
|
+
...rawText !== void 0 ? { raw: rawText } : {},
|
|
199
|
+
...authoredHtml ? { format: "html" } : {}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
(clip.anchor === "document" ? documentMedia : media).push(clip);
|
|
203
|
+
} else {
|
|
204
|
+
remaining.push(node);
|
|
205
|
+
}
|
|
206
|
+
originalIndex++;
|
|
207
|
+
}
|
|
208
|
+
return { media, documentMedia, remaining };
|
|
209
|
+
}
|
|
210
|
+
|
|
21
211
|
// src/doc/asciiDiagram/chars.ts
|
|
22
212
|
function toCells(s) {
|
|
23
213
|
return Array.from(s);
|
|
@@ -690,6 +880,7 @@ function findRailLabels(grid, boxes) {
|
|
|
690
880
|
return out;
|
|
691
881
|
}
|
|
692
882
|
function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
|
|
883
|
+
var _a;
|
|
693
884
|
const H = grid.length;
|
|
694
885
|
const W = H > 0 ? grid[0].length : 0;
|
|
695
886
|
const cells = /* @__PURE__ */ new Map();
|
|
@@ -760,7 +951,7 @@ function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
|
|
|
760
951
|
const isCrossCell = (idx) => CROSS_CHARS.has(grid[Math.floor(idx / W)][idx % W]);
|
|
761
952
|
const stateKey = (idx, channel) => idx * 2 + channel;
|
|
762
953
|
const visited = /* @__PURE__ */ new Set();
|
|
763
|
-
const
|
|
954
|
+
const found = [];
|
|
764
955
|
const seeds = [];
|
|
765
956
|
for (const idx of cells.keys()) {
|
|
766
957
|
seeds.push([idx, 0]);
|
|
@@ -769,11 +960,13 @@ function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
|
|
|
769
960
|
for (const [seedIdx, seedChannel] of seeds) {
|
|
770
961
|
if (visited.has(stateKey(seedIdx, seedChannel))) continue;
|
|
771
962
|
const componentCells = /* @__PURE__ */ new Set();
|
|
963
|
+
const states = [];
|
|
772
964
|
const queue = [[seedIdx, seedChannel]];
|
|
773
965
|
visited.add(stateKey(seedIdx, seedChannel));
|
|
774
966
|
while (queue.length > 0) {
|
|
775
967
|
const [idx, channel] = queue.pop();
|
|
776
968
|
componentCells.add(idx);
|
|
969
|
+
states.push(stateKey(idx, channel));
|
|
777
970
|
const r = Math.floor(idx / W);
|
|
778
971
|
const c = idx % W;
|
|
779
972
|
const neighbors = isCrossCell(idx) && channel === 1 ? [
|
|
@@ -800,15 +993,19 @@ function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
|
|
|
800
993
|
}
|
|
801
994
|
}
|
|
802
995
|
}
|
|
803
|
-
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
996
|
+
found.push({ cells: [...componentCells].sort((a, b) => a - b), states });
|
|
997
|
+
}
|
|
998
|
+
found.sort((a, b) => a.cells[0] - b.cells[0]);
|
|
999
|
+
const componentOfState = /* @__PURE__ */ new Map();
|
|
1000
|
+
found.forEach(({ states }, i) => states.forEach((key) => componentOfState.set(key, i)));
|
|
1001
|
+
const nearestOwner = (r, c) => {
|
|
1002
|
+
const owners = perimeterOwners.get(r * W + c) ?? [];
|
|
1003
|
+
if (owners.length === 0) return null;
|
|
1004
|
+
return [...owners].sort(
|
|
1005
|
+
(a, b) => boxes[a].r0 - boxes[b].r0 || boxes[a].c0 - boxes[b].c0 || a - b
|
|
1006
|
+
)[0];
|
|
1007
|
+
};
|
|
1008
|
+
const attachmentsOf = (component) => {
|
|
812
1009
|
const inComponent = new Set(component);
|
|
813
1010
|
const endpoints = [];
|
|
814
1011
|
for (const idx of component) {
|
|
@@ -844,13 +1041,6 @@ function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
|
|
|
844
1041
|
attachmentsByBox.set(boxIdx, { boxIdx, isArrowEnd: info.arrow !== null });
|
|
845
1042
|
}
|
|
846
1043
|
}
|
|
847
|
-
const nearestOwner = (r, c) => {
|
|
848
|
-
const owners = perimeterOwners.get(r * W + c) ?? [];
|
|
849
|
-
if (owners.length === 0) return null;
|
|
850
|
-
return [...owners].sort(
|
|
851
|
-
(a, b) => boxes[a].r0 - boxes[b].r0 || boxes[a].c0 - boxes[b].c0 || a - b
|
|
852
|
-
)[0];
|
|
853
|
-
};
|
|
854
1044
|
for (const idx of component) {
|
|
855
1045
|
const r = Math.floor(idx / W);
|
|
856
1046
|
const c = idx % W;
|
|
@@ -899,6 +1089,53 @@ function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
|
|
|
899
1089
|
}
|
|
900
1090
|
}
|
|
901
1091
|
}
|
|
1092
|
+
return { byBox: attachmentsByBox, dangling };
|
|
1093
|
+
};
|
|
1094
|
+
const components = found.map(({ cells: componentCells }) => componentCells);
|
|
1095
|
+
const infos = components.map(attachmentsOf);
|
|
1096
|
+
const mergedInto = components.map((_, i) => i);
|
|
1097
|
+
for (const idx of cells.keys()) {
|
|
1098
|
+
if (!isCrossCell(idx)) continue;
|
|
1099
|
+
const across = componentOfState.get(stateKey(idx, 0));
|
|
1100
|
+
const along = componentOfState.get(stateKey(idx, 1));
|
|
1101
|
+
if (across === void 0 || along === void 0 || across === along) continue;
|
|
1102
|
+
const r = Math.floor(idx / W);
|
|
1103
|
+
const c = idx % W;
|
|
1104
|
+
for (const [trunk, bar, vertical] of [
|
|
1105
|
+
[along, across, true],
|
|
1106
|
+
[across, along, false]
|
|
1107
|
+
]) {
|
|
1108
|
+
if (mergedInto[trunk] !== trunk || mergedInto[bar] !== bar) continue;
|
|
1109
|
+
const trunkEnds = [...infos[trunk].byBox.values()];
|
|
1110
|
+
const barEnds = [...infos[bar].byBox.values()];
|
|
1111
|
+
const source = trunkEnds.find((a) => !a.isArrowEnd);
|
|
1112
|
+
const target = trunkEnds.find((a) => a.isArrowEnd);
|
|
1113
|
+
if (trunkEnds.length !== 2 || !source || !target || barEnds.length === 0) continue;
|
|
1114
|
+
const sideOf = (boxIdx) => {
|
|
1115
|
+
const b = boxes[boxIdx];
|
|
1116
|
+
const [lo, hi, at] = vertical ? [b.r0, b.r1, r] : [b.c0, b.c1, c];
|
|
1117
|
+
return hi < at ? -1 : lo > at ? 1 : 0;
|
|
1118
|
+
};
|
|
1119
|
+
const sourceSide = sideOf(source.boxIdx);
|
|
1120
|
+
if (sourceSide === 0 || sideOf(target.boxIdx) !== -sourceSide) continue;
|
|
1121
|
+
const fanOut = barEnds.every((a) => a.isArrowEnd && sideOf(a.boxIdx) === -sourceSide);
|
|
1122
|
+
const fanIn = barEnds.every((a) => !a.isArrowEnd && sideOf(a.boxIdx) === sourceSide);
|
|
1123
|
+
if (!fanOut && !fanIn) continue;
|
|
1124
|
+
for (const a of barEnds) infos[trunk].byBox.set(a.boxIdx, a);
|
|
1125
|
+
(_a = infos[trunk]).dangling || (_a.dangling = infos[bar].dangling);
|
|
1126
|
+
components[trunk] = [...components[trunk], ...components[bar]].sort((x, y) => x - y);
|
|
1127
|
+
mergedInto[bar] = trunk;
|
|
1128
|
+
break;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
const edges = [];
|
|
1132
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1133
|
+
let mergedParallel = false;
|
|
1134
|
+
const looseComponents = /* @__PURE__ */ new Set();
|
|
1135
|
+
const sideLabelCells = /* @__PURE__ */ new Set();
|
|
1136
|
+
for (const [componentIdx, component] of components.entries()) {
|
|
1137
|
+
if (mergedInto[componentIdx] !== componentIdx) continue;
|
|
1138
|
+
const { byBox: attachmentsByBox, dangling } = infos[componentIdx];
|
|
902
1139
|
const attachments = [...attachmentsByBox.values()].sort(
|
|
903
1140
|
(a, b) => boxes[a.boxIdx].r0 - boxes[b.boxIdx].r0 || boxes[a.boxIdx].c0 - boxes[b.boxIdx].c0
|
|
904
1141
|
);
|
|
@@ -2872,196 +3109,6 @@ function matchNumberHighlight(text) {
|
|
|
2872
3109
|
};
|
|
2873
3110
|
}
|
|
2874
3111
|
|
|
2875
|
-
// src/doc/standaloneAnnotation.ts
|
|
2876
|
-
function parseAnnotationInner(inner) {
|
|
2877
|
-
const tokens = tokenizeAttrTokens(inner.trim());
|
|
2878
|
-
const firstIsParam = tokens.length > 0 && tokens[0].indexOf("=") > 0;
|
|
2879
|
-
const template = firstIsParam || tokens.length === 0 ? void 0 : tokens[0];
|
|
2880
|
-
const startIdx = firstIsParam ? 0 : 1;
|
|
2881
|
-
const params = {};
|
|
2882
|
-
for (let i = startIdx; i < tokens.length; i++) {
|
|
2883
|
-
const kv = splitKeyValueToken(tokens[i]);
|
|
2884
|
-
if (kv) params[kv.key] = kv.value;
|
|
2885
|
-
}
|
|
2886
|
-
return { template, params };
|
|
2887
|
-
}
|
|
2888
|
-
function parseStandaloneAnnotation(node) {
|
|
2889
|
-
if (node.type !== "paragraph") return null;
|
|
2890
|
-
const children = node.children ?? [];
|
|
2891
|
-
if (children.length !== 1 || children[0].type !== "text") return null;
|
|
2892
|
-
const text = children[0].value.trim();
|
|
2893
|
-
const match = matchTrailingTemplateAnnotation(text);
|
|
2894
|
-
if (!match || match.index !== 0) return null;
|
|
2895
|
-
return parseAnnotationInner(match.inner);
|
|
2896
|
-
}
|
|
2897
|
-
|
|
2898
|
-
// src/doc/mediaAnnotations.ts
|
|
2899
|
-
var MEDIA_TEMPLATES = /* @__PURE__ */ new Set(["audio", "video", "media"]);
|
|
2900
|
-
function isMediaAnnotationName(name) {
|
|
2901
|
-
return name != null && MEDIA_TEMPLATES.has(name);
|
|
2902
|
-
}
|
|
2903
|
-
function time(raw) {
|
|
2904
|
-
if (raw == null) return null;
|
|
2905
|
-
return parseTimeSeconds(raw);
|
|
2906
|
-
}
|
|
2907
|
-
function videoPlacement(params) {
|
|
2908
|
-
const explicit = params.placement ?? params.presentation;
|
|
2909
|
-
if (explicit === "content") return "content";
|
|
2910
|
-
if (explicit === "pip" || explicit === "picture-in-picture") return "picture-in-picture";
|
|
2911
|
-
if (explicit === "overlay" || explicit === "full-frame") return "overlay";
|
|
2912
|
-
if (params.pip === "" || params.pip === "true") return "picture-in-picture";
|
|
2913
|
-
if (params.overlay === "" || params.overlay === "true") return "overlay";
|
|
2914
|
-
return void 0;
|
|
2915
|
-
}
|
|
2916
|
-
function lockToBlock(raw) {
|
|
2917
|
-
return raw !== "false" && raw !== "0";
|
|
2918
|
-
}
|
|
2919
|
-
function videoPipSize(raw) {
|
|
2920
|
-
return raw === "small" || raw === "large" ? raw : void 0;
|
|
2921
|
-
}
|
|
2922
|
-
function videoPipShape(raw) {
|
|
2923
|
-
return raw === "square" || raw === "wide" ? raw : void 0;
|
|
2924
|
-
}
|
|
2925
|
-
function videoPipPosition(raw) {
|
|
2926
|
-
return raw === "top-left" || raw === "top-right" || raw === "bottom-left" || raw === "bottom-right" ? raw : void 0;
|
|
2927
|
-
}
|
|
2928
|
-
function toMediaClip(parsed, id) {
|
|
2929
|
-
const { template, params } = parsed;
|
|
2930
|
-
if (!template || !MEDIA_TEMPLATES.has(template)) return null;
|
|
2931
|
-
const src = params.src;
|
|
2932
|
-
if (!src) return null;
|
|
2933
|
-
const kind = template === "video" ? "video" : "audio";
|
|
2934
|
-
const anchor = params.anchor === "document" || params.span === "document" ? "document" : "block";
|
|
2935
|
-
const clip = {
|
|
2936
|
-
id,
|
|
2937
|
-
src,
|
|
2938
|
-
kind,
|
|
2939
|
-
startAt: time(params.startAt ?? params.startTime) ?? 0,
|
|
2940
|
-
anchor
|
|
2941
|
-
};
|
|
2942
|
-
const placement = kind === "video" ? videoPlacement(params) : void 0;
|
|
2943
|
-
if (placement && placement !== "content") clip.placement = placement;
|
|
2944
|
-
const pipSize = videoPipSize(params.pipSize);
|
|
2945
|
-
const pipShape = videoPipShape(params.pipShape);
|
|
2946
|
-
const pipPosition = videoPipPosition(params.pipPosition);
|
|
2947
|
-
if (pipSize) clip.pipSize = pipSize;
|
|
2948
|
-
if (pipShape) clip.pipShape = pipShape;
|
|
2949
|
-
if (pipPosition) clip.pipPosition = pipPosition;
|
|
2950
|
-
if (kind === "video" && placement && placement !== "content" && params.lockToBlock != null) {
|
|
2951
|
-
const locked = lockToBlock(params.lockToBlock);
|
|
2952
|
-
clip.lockToBlock = locked;
|
|
2953
|
-
clip.anchor = locked ? "block" : "document";
|
|
2954
|
-
if (locked) clip.startAt = 0;
|
|
2955
|
-
}
|
|
2956
|
-
const clipStart = time(params.clipStart);
|
|
2957
|
-
const clipEnd = time(params.clipEnd);
|
|
2958
|
-
if (clipStart != null) clip.clipStart = clipStart;
|
|
2959
|
-
if (clipEnd != null) clip.clipEnd = clipEnd;
|
|
2960
|
-
if (clip.lockToBlock === true) delete clip.clipEnd;
|
|
2961
|
-
if (params.spillover === "true" || params.spillover === "") clip.spillover = true;
|
|
2962
|
-
const edits = parseMediaEdits(mediaEditValuesFromParams(params));
|
|
2963
|
-
if (edits) clip.edits = edits;
|
|
2964
|
-
return clip;
|
|
2965
|
-
}
|
|
2966
|
-
function firstVideoElement(children) {
|
|
2967
|
-
const visit = (nodes) => {
|
|
2968
|
-
for (const child of nodes) {
|
|
2969
|
-
if (child.type !== "htmlElement") continue;
|
|
2970
|
-
if (child.tagName === "video") return child;
|
|
2971
|
-
const nested = visit(child.children);
|
|
2972
|
-
if (nested) return nested;
|
|
2973
|
-
}
|
|
2974
|
-
return null;
|
|
2975
|
-
};
|
|
2976
|
-
return visit(children);
|
|
2977
|
-
}
|
|
2978
|
-
function standaloneHtmlVideo(node) {
|
|
2979
|
-
if (node.type === "htmlBlock") {
|
|
2980
|
-
if (!/^\s*<video\b/i.test(node.rawHtml)) return null;
|
|
2981
|
-
const element = firstVideoElement(node.htmlChildren);
|
|
2982
|
-
return element ? { element, raw: node.rawHtml.trim() } : null;
|
|
2983
|
-
}
|
|
2984
|
-
if (node.type !== "paragraph" || !node.children.every((child) => child.type === "htmlInline")) {
|
|
2985
|
-
return null;
|
|
2986
|
-
}
|
|
2987
|
-
const raw = node.children.map((child) => child.type === "htmlInline" ? child.rawHtml : "").join("");
|
|
2988
|
-
if (!/^\s*<video\b[\s\S]*<\/video>\s*$/i.test(raw)) return null;
|
|
2989
|
-
for (const child of node.children) {
|
|
2990
|
-
if (child.type !== "htmlInline") continue;
|
|
2991
|
-
const element = firstVideoElement(child.htmlChildren);
|
|
2992
|
-
if (element) return { element, raw: raw.trim() };
|
|
2993
|
-
}
|
|
2994
|
-
return null;
|
|
2995
|
-
}
|
|
2996
|
-
function isStandaloneHtmlVideo(node) {
|
|
2997
|
-
return standaloneHtmlVideo(node) !== null;
|
|
2998
|
-
}
|
|
2999
|
-
function htmlVideoClip(node, id) {
|
|
3000
|
-
const authored = standaloneHtmlVideo(node);
|
|
3001
|
-
if (!authored) return null;
|
|
3002
|
-
const { element } = authored;
|
|
3003
|
-
const placement = videoPlacement({
|
|
3004
|
-
placement: element.attributes["data-squisq-video-placement"] ?? ""
|
|
3005
|
-
});
|
|
3006
|
-
if (!placement || placement === "content") return null;
|
|
3007
|
-
const src = element.attributes.src;
|
|
3008
|
-
if (!src) return null;
|
|
3009
|
-
const locked = lockToBlock(element.attributes["data-squisq-video-lock-to-block"]);
|
|
3010
|
-
const clip = {
|
|
3011
|
-
id,
|
|
3012
|
-
src,
|
|
3013
|
-
kind: "video",
|
|
3014
|
-
placement,
|
|
3015
|
-
lockToBlock: locked,
|
|
3016
|
-
startAt: locked ? 0 : time(element.attributes["data-squisq-video-start-at"]) ?? 0,
|
|
3017
|
-
anchor: locked ? "block" : "document"
|
|
3018
|
-
};
|
|
3019
|
-
const pipSize = videoPipSize(element.attributes["data-squisq-video-pip-size"]);
|
|
3020
|
-
const pipShape = videoPipShape(element.attributes["data-squisq-video-pip-shape"]);
|
|
3021
|
-
const pipPosition = videoPipPosition(element.attributes["data-squisq-video-pip-position"]);
|
|
3022
|
-
if (pipSize) clip.pipSize = pipSize;
|
|
3023
|
-
if (pipShape) clip.pipShape = pipShape;
|
|
3024
|
-
if (pipPosition) clip.pipPosition = pipPosition;
|
|
3025
|
-
const clipStart = time(element.attributes["data-squisq-video-clip-start"]);
|
|
3026
|
-
const clipEnd = time(element.attributes["data-squisq-video-clip-end"]);
|
|
3027
|
-
if (clipStart != null) clip.clipStart = clipStart;
|
|
3028
|
-
if (!locked && clipEnd != null) clip.clipEnd = clipEnd;
|
|
3029
|
-
const edits = parseMediaEdits(mediaEditValuesFromAttributes("video", element.attributes));
|
|
3030
|
-
if (edits) clip.edits = edits;
|
|
3031
|
-
return clip;
|
|
3032
|
-
}
|
|
3033
|
-
function extractMediaFromContents(contents, makeId, blockId) {
|
|
3034
|
-
const media = [];
|
|
3035
|
-
const documentMedia = [];
|
|
3036
|
-
const remaining = [];
|
|
3037
|
-
let index = 0;
|
|
3038
|
-
let originalIndex = 0;
|
|
3039
|
-
for (const node of contents ?? []) {
|
|
3040
|
-
const parsed = parseStandaloneAnnotation(node);
|
|
3041
|
-
const clip = parsed ? toMediaClip(parsed, "") : htmlVideoClip(node, "");
|
|
3042
|
-
if (clip) {
|
|
3043
|
-
clip.id = makeId(clip.src, index++);
|
|
3044
|
-
const line = node.position?.start.line;
|
|
3045
|
-
if (line != null) clip.sourceLine = line;
|
|
3046
|
-
if (blockId !== void 0) {
|
|
3047
|
-
const authoredHtml = standaloneHtmlVideo(node);
|
|
3048
|
-
const rawText = node.type === "paragraph" && node.children?.[0]?.type === "text" ? node.children[0].value.trim() : authoredHtml?.raw;
|
|
3049
|
-
clip.origin = {
|
|
3050
|
-
blockId,
|
|
3051
|
-
index: originalIndex,
|
|
3052
|
-
...rawText !== void 0 ? { raw: rawText } : {},
|
|
3053
|
-
...authoredHtml ? { format: "html" } : {}
|
|
3054
|
-
};
|
|
3055
|
-
}
|
|
3056
|
-
(clip.anchor === "document" ? documentMedia : media).push(clip);
|
|
3057
|
-
} else {
|
|
3058
|
-
remaining.push(node);
|
|
3059
|
-
}
|
|
3060
|
-
originalIndex++;
|
|
3061
|
-
}
|
|
3062
|
-
return { media, documentMedia, remaining };
|
|
3063
|
-
}
|
|
3064
|
-
|
|
3065
3112
|
// src/doc/templateInputs.ts
|
|
3066
3113
|
var VIDEO_FILE_RE = /\.(?:webm|mp4|mov|m4v|ogv)(?:[?#].*)?$/i;
|
|
3067
3114
|
var INLINE_MEDIA_TAG_RE = /^<\/?(?:video|audio|source|track)\b/i;
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
flattenRenderableBlocks,
|
|
5
5
|
getPinnedBlockMeta,
|
|
6
6
|
markdownToDoc
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-L3VQQ3WT.js";
|
|
8
8
|
import {
|
|
9
9
|
deriveTemplateInputs,
|
|
10
10
|
extractEmbeddedVideos,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
isPictureParagraph,
|
|
19
19
|
isStandaloneHtmlVideo,
|
|
20
20
|
isTreeFence
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-R2J7CQJZ.js";
|
|
22
22
|
import {
|
|
23
23
|
extractContent,
|
|
24
24
|
mapElementToBlock,
|