@bendyline/squisq 2.13.1 → 2.13.3

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.
Files changed (35) hide show
  1. package/dist/{Doc-C7iCmmmF.d.ts → Doc-BPhdJFS_.d.ts} +53 -2
  2. package/dist/{ImageEditDoc-CxRHe41J.d.ts → ImageEditDoc-DDx-sw_S.d.ts} +1 -1
  3. package/dist/{chunk-ITLJQG7Z.js → chunk-5FUBK3DK.js} +527 -266
  4. package/dist/{chunk-HE3HQZWU.js → chunk-6NWVLLMI.js} +104 -1
  5. package/dist/{chunk-3A6YM375.js → chunk-D3JQMZUT.js} +8 -8
  6. package/dist/chunk-DOOUVVOM.js +78 -0
  7. package/dist/{chunk-2LTALYXX.js → chunk-F3LRTRST.js} +15 -10
  8. package/dist/{chunk-5SVFLLOD.js → chunk-ISVJ42I3.js} +3 -0
  9. package/dist/{chunk-7ZXCS3UU.js → chunk-JFJZ4NS6.js} +2 -2
  10. package/dist/{chunk-V4USYYYO.js → chunk-JOBMPMY5.js} +1 -1
  11. package/dist/{chunk-HGCIIXHP.js → chunk-POZCKPCO.js} +235 -4
  12. package/dist/{chunk-DCO5GYVW.js → chunk-VX7MPZOK.js} +5 -5
  13. package/dist/doc/index.d.ts +100 -15
  14. package/dist/doc/index.js +15 -7
  15. package/dist/fence/index.d.ts +1 -1
  16. package/dist/generate/index.d.ts +1 -1
  17. package/dist/imageEdit/index.d.ts +3 -3
  18. package/dist/index.d.ts +5 -5
  19. package/dist/index.js +26 -18
  20. package/dist/jsonForm/index.d.ts +1 -1
  21. package/dist/jsonForm/index.js +1 -1
  22. package/dist/markdown/index.js +11 -12
  23. package/dist/{materializePageSection-_5uQrEYP.d.ts → materializePageSection-DnQi-0TA.d.ts} +1 -1
  24. package/dist/mediaEdit/index.d.ts +2 -2
  25. package/dist/narration/index.d.ts +1 -1
  26. package/dist/narration/index.js +5 -5
  27. package/dist/recommend/index.js +3 -2
  28. package/dist/schemas/index.d.ts +4 -4
  29. package/dist/schemas/index.js +1 -1
  30. package/dist/{themeLibrary-DsntZLoa.d.ts → themeLibrary-DM7eSK1w.d.ts} +1 -1
  31. package/dist/timing/index.d.ts +1 -1
  32. package/dist/transform/index.d.ts +2 -2
  33. package/dist/transform/index.js +6 -6
  34. package/package.json +1 -1
  35. package/dist/chunk-Y25EJEZN.js +0 -178
@@ -2331,6 +2331,101 @@ function svgIslandDataUrl(island, options = {}) {
2331
2331
  return url;
2332
2332
  }
2333
2333
 
2334
+ // src/markdown/attrTokens.ts
2335
+ var DQ_RUN = `"(?:[^"\\\\]|\\\\.)*"`;
2336
+ var SQ_RUN = `'(?:[^'\\\\]|\\\\.)*'`;
2337
+ var TEMPLATE_STRICT_RE = new RegExp(
2338
+ `\\s*\\{\\[((?:[^\\]"']|${DQ_RUN}|${SQ_RUN})*)\\]\\}[\\s\\]}]*$`
2339
+ );
2340
+ var TEMPLATE_LEGACY_RE = /\s*\{\[([^\]]*)\]\}[\s\]}]*$/;
2341
+ var PANDOC_STRICT_RE = new RegExp(`\\s*\\{(?!\\[)((?:[^}"']|${DQ_RUN}|${SQ_RUN})*)\\}\\s*$`);
2342
+ var PANDOC_LEGACY_RE = /\s*\{(?!\[)([^}]*)\}\s*$/;
2343
+ function matchTrailing(text, strict, legacy) {
2344
+ const m = strict.exec(text) ?? legacy.exec(text);
2345
+ return m ? { inner: m[1], index: m.index } : null;
2346
+ }
2347
+ function matchTrailingTemplateAnnotation(text) {
2348
+ return matchTrailing(text, TEMPLATE_STRICT_RE, TEMPLATE_LEGACY_RE);
2349
+ }
2350
+ function matchTrailingPandocAttr(text) {
2351
+ return matchTrailing(text, PANDOC_STRICT_RE, PANDOC_LEGACY_RE);
2352
+ }
2353
+ var WHITESPACE_RE = /\s/;
2354
+ function tokenizeAttrTokens(input) {
2355
+ const tokens = [];
2356
+ let i = 0;
2357
+ const n = input.length;
2358
+ while (i < n) {
2359
+ while (i < n && WHITESPACE_RE.test(input[i])) i++;
2360
+ if (i >= n) break;
2361
+ let token = "";
2362
+ while (i < n && !WHITESPACE_RE.test(input[i])) {
2363
+ const ch = input[i];
2364
+ const atValueStart = token === "" || token.endsWith("=");
2365
+ if ((ch === '"' || ch === "'") && atValueStart) {
2366
+ token += ch;
2367
+ i++;
2368
+ while (i < n && input[i] !== ch) {
2369
+ if (input[i] === "\\" && i + 1 < n && (input[i + 1] === ch || input[i + 1] === "\\")) {
2370
+ token += input[i] + input[i + 1];
2371
+ i += 2;
2372
+ } else {
2373
+ token += input[i];
2374
+ i++;
2375
+ }
2376
+ }
2377
+ if (i < n && input[i] === ch) {
2378
+ token += ch;
2379
+ i++;
2380
+ }
2381
+ } else {
2382
+ token += ch;
2383
+ i++;
2384
+ }
2385
+ }
2386
+ if (token) tokens.push(token);
2387
+ }
2388
+ return tokens;
2389
+ }
2390
+ var DQ_UNESCAPE_RE = /\\([\\"])/g;
2391
+ var SQ_UNESCAPE_RE = /\\([\\'])/g;
2392
+ function unquoteAttrValue(raw) {
2393
+ if (raw.length >= 2) {
2394
+ const q = raw[0];
2395
+ if ((q === '"' || q === "'") && raw.endsWith(q)) {
2396
+ const body = raw.slice(1, -1);
2397
+ return body.replace(q === '"' ? DQ_UNESCAPE_RE : SQ_UNESCAPE_RE, "$1");
2398
+ }
2399
+ }
2400
+ return raw;
2401
+ }
2402
+ function splitKeyValueToken(token) {
2403
+ const eqIdx = token.indexOf("=");
2404
+ if (eqIdx <= 0) return null;
2405
+ return { key: token.slice(0, eqIdx), value: unquoteAttrValue(token.slice(eqIdx + 1)) };
2406
+ }
2407
+ var NEEDS_QUOTING_RE = /[\s"'[\]{}]/;
2408
+ var DQ_ESCAPE_RE = /[\\"]/g;
2409
+ var SQ_ESCAPE_RE = /[\\']/g;
2410
+ function needsQuoting(value) {
2411
+ return value === "" || NEEDS_QUOTING_RE.test(value);
2412
+ }
2413
+ function quoteAttrValue(value) {
2414
+ if (!needsQuoting(value)) return value;
2415
+ if (value.includes('"') && !value.includes("'")) {
2416
+ return `'${value.replace(SQ_ESCAPE_RE, (ch) => `\\${ch}`)}'`;
2417
+ }
2418
+ return `"${value.replace(DQ_ESCAPE_RE, (ch) => `\\${ch}`)}"`;
2419
+ }
2420
+ function serializeAnnotation(template, params) {
2421
+ const parts = [];
2422
+ if (template) parts.push(template);
2423
+ for (const [key, value] of Object.entries(params ?? {})) {
2424
+ parts.push(`${key}=${quoteAttrValue(value)}`);
2425
+ }
2426
+ return `{[${parts.join(" ")}]}`;
2427
+ }
2428
+
2334
2429
  export {
2335
2430
  mediaKindForUrl,
2336
2431
  parseHtmlToNodes,
@@ -2373,5 +2468,13 @@ export {
2373
2468
  svgSourceFromDataUrl,
2374
2469
  parseSvgIsland,
2375
2470
  svgIslandMarkup,
2376
- svgIslandDataUrl
2471
+ svgIslandDataUrl,
2472
+ matchTrailingTemplateAnnotation,
2473
+ matchTrailingPandocAttr,
2474
+ tokenizeAttrTokens,
2475
+ unquoteAttrValue,
2476
+ splitKeyValueToken,
2477
+ needsQuoting,
2478
+ quoteAttrValue,
2479
+ serializeAnnotation
2377
2480
  };
@@ -1,17 +1,17 @@
1
1
  import {
2
- isReservedAnnotationToken,
2
+ isReservedAnnotationToken
3
+ } from "./chunk-DOOUVVOM.js";
4
+ import {
5
+ coerceAnnotationValues,
3
6
  matchTrailingPandocAttr,
4
7
  matchTrailingTemplateAnnotation,
8
+ parseFrontmatter,
9
+ parseHtmlToNodes,
5
10
  quoteAttrValue,
11
+ sanitizeUrl,
6
12
  splitKeyValueToken,
7
13
  tokenizeAttrTokens
8
- } from "./chunk-Y25EJEZN.js";
9
- import {
10
- coerceAnnotationValues,
11
- parseFrontmatter,
12
- parseHtmlToNodes,
13
- sanitizeUrl
14
- } from "./chunk-HE3HQZWU.js";
14
+ } from "./chunk-6NWVLLMI.js";
15
15
  import {
16
16
  resolveIcon
17
17
  } from "./chunk-CZ7AUSLI.js";
@@ -0,0 +1,78 @@
1
+ // src/doc/templates/templateNames.ts
2
+ var TEMPLATE_ALIASES = Object.freeze({
3
+ titleBlock: "title",
4
+ quoteBlock: "quote",
5
+ mapBlock: "map",
6
+ listBlock: "list",
7
+ diagramBlock: "diagram",
8
+ diagramNode: "diagram"
9
+ });
10
+ function resolveTemplateName(name) {
11
+ return TEMPLATE_ALIASES[name] ?? name;
12
+ }
13
+ var TABLE_FED_TEMPLATES = /* @__PURE__ */ new Set([
14
+ "dataTable",
15
+ "barChart",
16
+ "columnChart",
17
+ "pieChart",
18
+ "donutChart",
19
+ "lineChart",
20
+ "areaChart",
21
+ "scatterChart"
22
+ ]);
23
+ var CONTAINER_TEMPLATES = /* @__PURE__ */ new Set(["diagram", "drawing", "layout"]);
24
+ function isContainerTemplate(name) {
25
+ return !!name && CONTAINER_TEMPLATES.has(resolveTemplateName(name));
26
+ }
27
+ var TEMPLATE_TOKEN_NAMES = /* @__PURE__ */ new Set([
28
+ "title",
29
+ "sectionHeader",
30
+ "bigText",
31
+ "transcript",
32
+ "content",
33
+ "statHighlight",
34
+ "quote",
35
+ "factCard",
36
+ "twoColumn",
37
+ "dateEvent",
38
+ "imageWithCaption",
39
+ "leftFeature",
40
+ "rightFeature",
41
+ "topFeature",
42
+ "bottomFeature",
43
+ "mediaOnly",
44
+ "map",
45
+ "fullBleedQuote",
46
+ "list",
47
+ "photoGrid",
48
+ "definitionCard",
49
+ "comparisonBar",
50
+ "pullQuote",
51
+ "videoWithCaption",
52
+ "videoPullQuote",
53
+ "dataTable",
54
+ "barChart",
55
+ "columnChart",
56
+ "pieChart",
57
+ "donutChart",
58
+ "lineChart",
59
+ "areaChart",
60
+ "scatterChart",
61
+ "diagram",
62
+ "tree",
63
+ "timeline",
64
+ "layout",
65
+ "drawing"
66
+ ]);
67
+ function isReservedAnnotationToken(token) {
68
+ return TEMPLATE_TOKEN_NAMES.has(resolveTemplateName(token));
69
+ }
70
+
71
+ export {
72
+ TEMPLATE_ALIASES,
73
+ resolveTemplateName,
74
+ TABLE_FED_TEMPLATES,
75
+ CONTAINER_TEMPLATES,
76
+ isContainerTemplate,
77
+ isReservedAnnotationToken
78
+ };
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-FTN6SGW5.js";
4
4
  import {
5
5
  applySavedPresentation
6
- } from "./chunk-DCO5GYVW.js";
6
+ } from "./chunk-VX7MPZOK.js";
7
7
  import {
8
8
  SHAPE_NAMES,
9
9
  buildChartData,
@@ -25,14 +25,13 @@ import {
25
25
  nearestName,
26
26
  normalizeShapeKind,
27
27
  parseDataFence,
28
- parseStandaloneAnnotation,
29
28
  placeLayersInRect,
30
29
  readCustomThemesFromFrontmatter,
31
30
  resolvePersistentLayers,
32
31
  templateRegistry,
33
32
  writeCustomTemplatesToFrontmatter,
34
33
  writeCustomThemesToFrontmatter
35
- } from "./chunk-ITLJQG7Z.js";
34
+ } from "./chunk-5FUBK3DK.js";
36
35
  import {
37
36
  ASCII_TREE_VOCAB,
38
37
  ASCII_VOCAB,
@@ -51,10 +50,11 @@ import {
51
50
  isPictureFence,
52
51
  isVert,
53
52
  parseAsciiDiagram,
53
+ parseStandaloneAnnotation,
54
54
  toCells,
55
55
  toGrid,
56
56
  traceBoxes
57
- } from "./chunk-HGCIIXHP.js";
57
+ } from "./chunk-POZCKPCO.js";
58
58
  import {
59
59
  iconMarker
60
60
  } from "./chunk-7ZAAICW4.js";
@@ -87,14 +87,13 @@ import {
87
87
  } from "./chunk-L7QZORLB.js";
88
88
  import {
89
89
  parseMarkdown
90
- } from "./chunk-3A6YM375.js";
90
+ } from "./chunk-D3JQMZUT.js";
91
91
  import {
92
92
  TABLE_FED_TEMPLATES,
93
93
  TEMPLATE_ALIASES,
94
94
  isContainerTemplate,
95
- resolveTemplateName,
96
- serializeAnnotation
97
- } from "./chunk-Y25EJEZN.js";
95
+ resolveTemplateName
96
+ } from "./chunk-DOOUVVOM.js";
98
97
  import {
99
98
  KNOWN_BLOCK_META_KEYS,
100
99
  coerceAnnotationValues,
@@ -104,8 +103,9 @@ import {
104
103
  isVideoEmbedUrl,
105
104
  parseHtmlToNodes,
106
105
  parseVideoEmbedUrl,
107
- readFrontmatterThemeId
108
- } from "./chunk-HE3HQZWU.js";
106
+ readFrontmatterThemeId,
107
+ serializeAnnotation
108
+ } from "./chunk-6NWVLLMI.js";
109
109
  import {
110
110
  BUILD_PARAM_KEYS,
111
111
  buildSpecParams
@@ -1630,6 +1630,11 @@ var sectionExtractors = {
1630
1630
  imageWithCaption,
1631
1631
  leftFeature,
1632
1632
  rightFeature,
1633
+ // A page reads top to bottom, so a media-led slide is its prose section:
1634
+ // the heading and body, with the body's media inline where it was written.
1635
+ topFeature: content,
1636
+ bottomFeature: content,
1637
+ mediaOnly: content,
1633
1638
  map,
1634
1639
  fullBleedQuote,
1635
1640
  list,
@@ -306,6 +306,9 @@ function validateStartBlock(value, issues) {
306
306
  optionalString(value, "heroSrc", "startBlock.heroSrc", issues);
307
307
  optionalString(value, "heroAlt", "startBlock.heroAlt", issues);
308
308
  optionalString(value, "subtitle", "startBlock.subtitle", issues);
309
+ if (value.coverStyle !== void 0 && value.coverStyle !== "scrim" && value.coverStyle !== "frosted") {
310
+ add(issues, "startBlock.coverStyle", 'must be "scrim" or "frosted"', value.coverStyle);
311
+ }
309
312
  }
310
313
  function validateCaptions(value, issues) {
311
314
  if (!isRecord(value)) {
@@ -3,14 +3,14 @@ import {
3
3
  parseMarkdown,
4
4
  remarkWikiLinks,
5
5
  toMdast
6
- } from "./chunk-3A6YM375.js";
6
+ } from "./chunk-D3JQMZUT.js";
7
7
  import {
8
8
  formatFrontmatterYaml,
9
9
  getChildren,
10
10
  splitFrontmatterBlock,
11
11
  stringifyHtmlNodes,
12
12
  walkMarkdownTree
13
- } from "./chunk-HE3HQZWU.js";
13
+ } from "./chunk-6NWVLLMI.js";
14
14
 
15
15
  // src/markdown/stringify.ts
16
16
  import { unified } from "unified";
@@ -8,7 +8,7 @@ import {
8
8
  expectedSyllablesAt,
9
9
  flattenRenderableBlocks,
10
10
  wordPosAtExpectedSyllables
11
- } from "./chunk-ITLJQG7Z.js";
11
+ } from "./chunk-5FUBK3DK.js";
12
12
 
13
13
  // src/narration/types.ts
14
14
  var DEFAULT_FEATURE_CONFIG = Object.freeze({
@@ -1,14 +1,22 @@
1
+ import {
2
+ mediaEditValuesFromAttributes,
3
+ mediaEditValuesFromParams,
4
+ parseMediaEdits
5
+ } from "./chunk-L7QZORLB.js";
1
6
  import {
2
7
  extractPlainText,
3
8
  findBlockVideoEmbed,
4
9
  findNodesByType,
5
10
  isSvgIslandLang,
6
11
  isVideoEmbedUrl,
12
+ matchTrailingTemplateAnnotation,
7
13
  mediaKindForUrl,
8
14
  parseTimeSeconds,
9
15
  sanitizeUrl,
16
+ splitKeyValueToken,
17
+ tokenizeAttrTokens,
10
18
  walkMarkdownTree
11
- } from "./chunk-HE3HQZWU.js";
19
+ } from "./chunk-6NWVLLMI.js";
12
20
 
13
21
  // src/doc/asciiDiagram/chars.ts
14
22
  function toCells(s) {
@@ -2864,8 +2872,199 @@ function matchNumberHighlight(text) {
2864
2872
  };
2865
2873
  }
2866
2874
 
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
+
2867
3065
  // src/doc/templateInputs.ts
2868
3066
  var VIDEO_FILE_RE = /\.(?:webm|mp4|mov|m4v|ogv)(?:[?#].*)?$/i;
3067
+ var INLINE_MEDIA_TAG_RE = /^<\/?(?:video|audio|source|track)\b/i;
2869
3068
  function extractHostedVideos(contents, limit = Infinity) {
2870
3069
  const found = [];
2871
3070
  const seen = /* @__PURE__ */ new Set();
@@ -2888,7 +3087,26 @@ function isPictureFence(node) {
2888
3087
  }
2889
3088
  function isMaterializedMediaNode(node) {
2890
3089
  if (node.type === "code") return isPictureFence(node);
2891
- return findBlockVideoEmbed(node) !== null;
3090
+ return findBlockVideoEmbed(node) !== null || isStandaloneHtmlVideo(node);
3091
+ }
3092
+ function isPictureParagraph(node) {
3093
+ if (node.type !== "paragraph") return false;
3094
+ let pictures = 0;
3095
+ for (const child of node.children) {
3096
+ if (child.type === "image") {
3097
+ if (!VIDEO_FILE_RE.test(child.url) && mediaKindForUrl(child.url)) return false;
3098
+ pictures += 1;
3099
+ } else if (child.type === "htmlInline") {
3100
+ const elements = child.htmlChildren.filter(
3101
+ (html) => html.type === "htmlElement"
3102
+ );
3103
+ if (!elements.length || !elements.every((html) => html.tagName === "img")) return false;
3104
+ pictures += elements.length;
3105
+ } else if (child.type !== "break" && !(child.type === "text" && !child.value.trim())) {
3106
+ return false;
3107
+ }
3108
+ }
3109
+ return pictures > 0;
2892
3110
  }
2893
3111
  function extractBodyPlainText(contents) {
2894
3112
  if (!contents || contents.length === 0) return "";
@@ -2942,7 +3160,7 @@ function renderInlineHtml(nodes) {
2942
3160
  case "inlineIcon":
2943
3161
  return `<i class="fa-${node.family} fa-${node.name}" aria-hidden="true"></i>`;
2944
3162
  case "htmlInline":
2945
- return escapeInlineHtml(node.rawHtml);
3163
+ return INLINE_MEDIA_TAG_RE.test(node.rawHtml.trim()) ? "" : escapeInlineHtml(node.rawHtml);
2946
3164
  }
2947
3165
  }).join("");
2948
3166
  }
@@ -3659,7 +3877,9 @@ function profileBlockContents(nodes) {
3659
3877
  }
3660
3878
  var UNIVERSAL_DEFAULTS = ["title", "sectionHeader", "content", "factCard", "twoColumn"];
3661
3879
  function recommendedNamesForProfile(profile) {
3662
- if (profile.hasCompoundBody) return ["content"];
3880
+ if (profile.hasCompoundBody) {
3881
+ return profile.hasImage || profile.hasVideo ? ["content", "topFeature", "bottomFeature"] : ["content"];
3882
+ }
3663
3883
  const names = /* @__PURE__ */ new Set();
3664
3884
  let anyContentSignal = false;
3665
3885
  if (profile.hasAsciiDiagram) {
@@ -3679,11 +3899,17 @@ function recommendedNamesForProfile(profile) {
3679
3899
  names.add("imageWithCaption");
3680
3900
  names.add("leftFeature");
3681
3901
  names.add("rightFeature");
3902
+ names.add("topFeature");
3903
+ names.add("bottomFeature");
3904
+ names.add("mediaOnly");
3682
3905
  if (profile.imageCount >= 2) names.add("photoGrid");
3683
3906
  }
3684
3907
  if (profile.hasVideo) {
3685
3908
  anyContentSignal = true;
3686
3909
  names.add("videoWithCaption");
3910
+ names.add("topFeature");
3911
+ names.add("bottomFeature");
3912
+ names.add("mediaOnly");
3687
3913
  if (profile.hasBlockquote) names.add("videoPullQuote");
3688
3914
  }
3689
3915
  if (profile.hasBlockquote) {
@@ -3748,6 +3974,10 @@ function recommendTemplatesForBlock(profile, allNames) {
3748
3974
  }
3749
3975
 
3750
3976
  export {
3977
+ parseAnnotationInner,
3978
+ parseStandaloneAnnotation,
3979
+ isMediaAnnotationName,
3980
+ extractMediaFromContents,
3751
3981
  toCells,
3752
3982
  cellWidth,
3753
3983
  isHoriz,
@@ -3799,6 +4029,7 @@ export {
3799
4029
  extractHostedVideos,
3800
4030
  isPictureFence,
3801
4031
  isMaterializedMediaNode,
4032
+ isPictureParagraph,
3802
4033
  extractBodyPlainText,
3803
4034
  extractListItems,
3804
4035
  renderMarkdownBlocksHtml,
@@ -4,7 +4,7 @@ import {
4
4
  flattenRenderableBlocks,
5
5
  getPinnedBlockMeta,
6
6
  markdownToDoc
7
- } from "./chunk-ITLJQG7Z.js";
7
+ } from "./chunk-5FUBK3DK.js";
8
8
  import {
9
9
  deriveTemplateInputs,
10
10
  extractImages,
@@ -12,7 +12,7 @@ import {
12
12
  isAsciiTimelineFence,
13
13
  isPictureFence,
14
14
  isTreeFence
15
- } from "./chunk-HGCIIXHP.js";
15
+ } from "./chunk-POZCKPCO.js";
16
16
  import {
17
17
  extractContent,
18
18
  mapElementToBlock,
@@ -24,15 +24,15 @@ import {
24
24
  } from "./chunk-WNEH3BZP.js";
25
25
  import {
26
26
  parseMarkdown
27
- } from "./chunk-3A6YM375.js";
27
+ } from "./chunk-D3JQMZUT.js";
28
28
  import {
29
29
  isContainerTemplate
30
- } from "./chunk-Y25EJEZN.js";
30
+ } from "./chunk-DOOUVVOM.js";
31
31
  import {
32
32
  extractPlainText,
33
33
  getChildren,
34
34
  stringifyHtmlNodes
35
- } from "./chunk-HE3HQZWU.js";
35
+ } from "./chunk-6NWVLLMI.js";
36
36
  import {
37
37
  parseBuildSpec
38
38
  } from "./chunk-P53Z4RYC.js";