@bendyline/squisq 2.11.16 → 2.11.17

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 (36) hide show
  1. package/dist/{Doc-Bd2kdzuy.d.ts → Doc-CXx1WL8G.d.ts} +27 -2
  2. package/dist/{ImageEditDoc-C3HOltpW.d.ts → ImageEditDoc-BVLXI-Zd.d.ts} +1 -1
  3. package/dist/{chunk-NC6LD6D3.js → chunk-54RU7TBZ.js} +34 -7
  4. package/dist/{chunk-C3NAY5YP.js → chunk-A5QJJZ5S.js} +8 -5
  5. package/dist/{chunk-HVJ6VFDX.js → chunk-GB7OFYUK.js} +4 -0
  6. package/dist/{chunk-IFJPPI63.js → chunk-KNC4ZBQC.js} +5 -5
  7. package/dist/{chunk-WMXQDP2C.js → chunk-L7IIFWWW.js} +109 -14
  8. package/dist/{chunk-ANH2OZ2M.js → chunk-LJZHC6GN.js} +146 -11
  9. package/dist/{chunk-IRVXZUVU.js → chunk-MY46W5O5.js} +2 -2
  10. package/dist/{chunk-GDHXT5Q7.js → chunk-PGWYC3S2.js} +2 -2
  11. package/dist/{chunk-5W7F46OO.js → chunk-PNXBDMNS.js} +1 -1
  12. package/dist/{chunk-X7BNDUNI.js → chunk-Q6ELOAOQ.js} +383 -1
  13. package/dist/{chunk-TMOHAFYE.js → chunk-WSFXV5BT.js} +17 -0
  14. package/dist/doc/index.d.ts +35 -7
  15. package/dist/doc/index.js +11 -7
  16. package/dist/fence/index.d.ts +1 -1
  17. package/dist/generate/index.d.ts +1 -1
  18. package/dist/imageEdit/index.d.ts +3 -3
  19. package/dist/index.d.ts +6 -6
  20. package/dist/index.js +35 -11
  21. package/dist/jsonForm/index.d.ts +1 -1
  22. package/dist/jsonForm/index.js +1 -1
  23. package/dist/markdown/index.d.ts +170 -4
  24. package/dist/markdown/index.js +24 -4
  25. package/dist/{materializePageSection-FRv9whYy.d.ts → materializePageSection-BX1uOAlN.d.ts} +6 -1
  26. package/dist/mediaEdit/index.d.ts +2 -2
  27. package/dist/narration/index.d.ts +1 -1
  28. package/dist/narration/index.js +6 -6
  29. package/dist/recommend/index.js +2 -2
  30. package/dist/schemas/index.d.ts +4 -4
  31. package/dist/schemas/index.js +1 -1
  32. package/dist/{themeLibrary-BbF3EKWM.d.ts → themeLibrary-Bnq_x-db.d.ts} +1 -1
  33. package/dist/timing/index.d.ts +1 -1
  34. package/dist/transform/index.d.ts +2 -2
  35. package/dist/transform/index.js +6 -6
  36. package/package.json +1 -1
@@ -2620,7 +2620,7 @@ interface Block {
2620
2620
  * A visual element within a block.
2621
2621
  * Layers are composited back-to-front (first layer is background).
2622
2622
  */
2623
- type Layer = ImageLayer | TextLayer | ShapeLayer | PathLayer | MapLayer | VideoLayer | TableLayer | TreeLayer | MermaidLayer;
2623
+ type Layer = ImageLayer | TextLayer | ShapeLayer | PathLayer | MapLayer | VideoLayer | VideoEmbedLayer | TableLayer | TreeLayer | MermaidLayer;
2624
2624
  interface BaseLayer {
2625
2625
  /** Unique identifier for this layer */
2626
2626
  id: string;
@@ -2885,6 +2885,31 @@ interface VideoLayer extends BaseLayer {
2885
2885
  license?: string;
2886
2886
  };
2887
2887
  }
2888
+ /**
2889
+ * Hosted video layer — the YouTube / Vimeo / Loom / Dailymotion / Wistia
2890
+ * player for a paragraph that is only a link to the video's page.
2891
+ *
2892
+ * Carries the page URL, never a player URL: renderers re-derive the iframe
2893
+ * `src` with `parseVideoEmbedUrl` (`@bendyline/squisq/markdown`), so an
2894
+ * authored layer cannot smuggle in an arbitrary frame, and a URL that is not a
2895
+ * supported video renders nothing. The player keeps the video's aspect ratio
2896
+ * (16:9, or 9:16 for Shorts), letterboxed within the layer's bounds.
2897
+ *
2898
+ * Unlike {@link VideoLayer} this is not a clip on the document timeline: it
2899
+ * does not follow play/pause, is never sought by frame capture, and adds no
2900
+ * audio to exports. Live players appear only where a viewer can use them (the
2901
+ * player's current slide); thumbnails, exports and frame capture draw a
2902
+ * poster instead.
2903
+ */
2904
+ interface VideoEmbedLayer extends BaseLayer {
2905
+ type: 'videoEmbed';
2906
+ content: {
2907
+ /** The video's page URL — any form `parseVideoEmbedUrl` recognizes. */
2908
+ url: string;
2909
+ /** Names the player for assistive tech and labels the poster. */
2910
+ title?: string;
2911
+ };
2912
+ }
2888
2913
  /**
2889
2914
  * Table layer - renders a data table with themed styling.
2890
2915
  * Uses foreignObject inside SVG for HTML-based table layout.
@@ -3277,4 +3302,4 @@ declare function getBlockAtTime(blocks: Block[], time: number): Block | null;
3277
3302
  */
3278
3303
  declare function getCaptionAtTime(captions: CaptionTrack | undefined, time: number): CaptionPhrase | null;
3279
3304
 
3280
- export { type FullBleedQuoteInput as $, type AccentImage as A, type BarChartInput as B, type CaptionPhrase as C, type CustomTemplateValidationError as D, type CustomTemplateValidationResult as E, DARK_SURFACE as F, DEFAULT_DOC_FONT as G, DEFAULT_TITLE_FONT as H, type DataTableInput as I, type DateEventInput as J, type DeepPartial as K, type DefinitionCardInput as L, type DiagramBlockInput as M, type DiagramEdgeAnchor as N, type DiagramTemplateEdge as O, type DiagramTemplateNode as P, type Doc as Q, type DocBlock as R, type DocDiagnostic as S, type DonutChartInput as T, type DrawingBlockInput as U, FRONTMATTER_CUSTOM_TEMPLATES_KEY as V, FRONTMATTER_CUSTOM_THEMES_KEY as W, FRONTMATTER_MOTION_KEY as X, type FactCardInput as Y, type FontFamily as Z, type FontFamilyKind as _, type AccentPosition as a, type PersistentLayerTemplate as a$, type GradientBackgroundConfig as a0, type ImageBackgroundConfig as a1, type ImageLayer as a2, type ImageTreatment as a3, type ImageWithCaptionInput as a4, LIGHT_SURFACE as a5, type Layer as a6, type LayerRepeat as a7, type LayoutHints as a8, type LeftFeatureInput as a9, PAGE_EMPHASES as aA, PAGE_EYEBROWS as aB, PAGE_HEADING_CASES as aC, PAGE_HEADING_SCALES as aD, PAGE_HEADING_UNDERLINES as aE, PAGE_HERO_STYLES as aF, PAGE_IMAGE_FRAMINGS as aG, PAGE_NUMERAL_STYLES as aH, PAGE_PATTERNS as aI, PAGE_QUOTE_MARKS as aJ, PAGE_SECTION_KINDS as aK, PAGE_SECTION_SPACINGS as aL, PAGE_SHADOWS as aM, PAGE_VARIANTS as aN, type PageAccentRotation as aO, type PageBackground as aP, type PageDesignFamily as aQ, type PageEmphasis as aR, type PageHeadingTreatment as aS, type PageSectionKind as aT, type PageSectionOverride as aU, type PageTokens as aV, type PageVariant as aW, type PathLayer as aX, type PatternBackgroundConfig as aY, type PersistentLayer as aZ, type PersistentLayerConfig as a_, type LineChartInput as aa, type LinearGradient as ab, type ListBlockInput as ac, MOTION_PROFILES as ad, type MapBlockInput as ae, type MapLayer as af, type MapMarker as ag, type MapTileStyle as ah, type MarkerStyle as ai, type MediaClip as aj, type MediaCrop as ak, type MediaCut as al, type MediaEdits as am, type MediaScheduleOptions as an, type MermaidLayer as ao, type MotionEntrance as ap, type MotionOrigin as aq, type MotionProfile as ar, type MotionProfileName as as, type MotionSpec as at, type MotionState as au, PAGE_ACCENT_STRATEGIES as av, PAGE_BACKGROUNDS as aw, PAGE_BACKGROUND_RHYTHMS as ax, PAGE_DESIGN_FAMILIES as ay, PAGE_DIVIDERS as az, type AmbientGradientConfig as b, type ViewportConfig as b$, type PersistentLayerTemplateConfig as b0, type PersistentLayerTemplateType as b1, type PhotoGridInput as b2, type PieChartInput as b3, type PipStyle as b4, type Position as b5, type ProgressIndicatorConfig as b6, type PromotedBodyAnnotation as b7, type PullQuoteInput as b8, type QuoteBlockInput as b9, type ThemeRegistry as bA, type ThemeSchemaVersion as bB, type ThemeSeedColors as bC, type ThemeStyle as bD, type ThemeTypography as bE, type TimelineBlockInput as bF, type TimelineTemplateEvent as bG, type TimelineTemplateLink as bH, type TimelineTemplateTrack as bI, type TitleBlockInput as bJ, type TitleCaptionConfig as bK, type TranscriptBlockInput as bL, type TreeBlockInput as bM, type TreeLayer as bN, type TreeLayerItem as bO, type TreeLayerStyle as bP, type TreeTemplateItem as bQ, type TwoColumnInput as bR, VIEWPORT_PRESETS as bS, type VideoLayer as bT, type VideoPipPosition as bU, type VideoPipShape as bV, type VideoPipSize as bW, type VideoPlacement as bX, type VideoPresentation as bY, type VideoPullQuoteInput as bZ, type VideoWithCaptionInput as b_, type RawLayersInput as ba, type RenderStyle as bb, type RightFeatureInput as bc, type ScatterChartInput as bd, type ScheduledClip as be, type SectionHeaderInput as bf, type ShapeFilter as bg, type ShapeLayer as bh, type ShapePattern as bi, type SolidBackgroundConfig as bj, type StartBlockConfig as bk, type StatHighlightInput as bl, type SurfaceScheme as bm, THEME_SCHEMA_VERSION as bn, type TableLayer as bo, type TableLayerStyle as bp, type TemplateBlock as bq, type TemplateContext as br, type TemplateFunction as bs, type TemplateRegistry as bt, type TextLayer as bu, type TextStyle as bv, type Theme as bw, type ThemeColorPalette as bx, type ThemeColorScheme as by, type ThemePageStyle as bz, type Animation as c, type ViewportOrientation as c0, type ViewportPreset as c1, type VignetteConfig as c2, applySurface as c3, calculateDuration as c4, calculateFontScale as c5, createTemplateContext as c6, createTheme as c7, createThemeRegistry as c8, getAspectRatioString as c9, type MediaEditParamKey as cA, type MediaEditParamValues as cB, type MediaFxOp as cC, formatMediaNumber as cD, hasRenderableFx as cE, mediaEditHtmlAttribute as cF, mediaEditValuesFromAttributes as cG, mediaEditValuesFromParams as cH, mediaRenderKey as cI, normalizeMediaCrop as cJ, normalizeMediaCuts as cK, parseMediaCrop as cL, parseMediaCuts as cM, parseMediaEdits as cN, parseMediaFx as cO, serializeMediaCrop as cP, serializeMediaCuts as cQ, serializeMediaEdits as cR, serializeMediaFx as cS, getBlockAtTime as ca, getCaptionAtTime as cb, getDocPlaybackDuration as cc, getLayoutHints as cd, getSafeTextBounds as ce, getSegmentAtTime as cf, getTwoColumnPositions as cg, getViewport as ch, getViewportOrientation as ci, isCustomTemplateDefinition as cj, isMotionProfileName as ck, isPersistentLayerTemplate as cl, isTemplateBlock as cm, scaledFontSize$1 as cn, readFrontmatterMotion as co, resolveMediaSchedule as cp, resolveMotionForDoc as cq, resolveMotionProfile as cr, scaledFontSize as cs, scheduleMediaClip as ct, validateCustomTemplateDefinition as cu, type MediaFxOpId as cv, type MediaFxChain as cw, MEDIA_EDIT_PARAMS as cx, MEDIA_FX_ORDER as cy, MEDIA_FX_SPECS as cz, type AnimationType as d, type AreaChartInput as e, type AudioBookmark as f, type AudioSegment as g, type AudioTimingData as h, type AudioTrack as i, type BigTextInput as j, type Block as k, type BlockConnection as l, type BorderStyle as m, type CaptionTrack as n, type CaptionWord as o, type ChartBaseFields as p, type ChartTemplateInput as q, type ColorScheme as r, type ColumnChartInput as s, type ComparisonBarInput as t, type ContentBlockInput as u, type CornerBrandingConfig as v, type CountUpSpec as w, type CreateTemplateContextOptions as x, type CustomTemplateDefinition as y, type CustomTemplateLayer as z };
3305
+ export { type FullBleedQuoteInput as $, type AccentImage as A, type BarChartInput as B, type CaptionPhrase as C, type CustomTemplateValidationError as D, type CustomTemplateValidationResult as E, DARK_SURFACE as F, DEFAULT_DOC_FONT as G, DEFAULT_TITLE_FONT as H, type DataTableInput as I, type DateEventInput as J, type DeepPartial as K, type DefinitionCardInput as L, type DiagramBlockInput as M, type DiagramEdgeAnchor as N, type DiagramTemplateEdge as O, type DiagramTemplateNode as P, type Doc as Q, type DocBlock as R, type DocDiagnostic as S, type DonutChartInput as T, type DrawingBlockInput as U, FRONTMATTER_CUSTOM_TEMPLATES_KEY as V, FRONTMATTER_CUSTOM_THEMES_KEY as W, FRONTMATTER_MOTION_KEY as X, type FactCardInput as Y, type FontFamily as Z, type FontFamilyKind as _, type AccentPosition as a, type PersistentLayerTemplate as a$, type GradientBackgroundConfig as a0, type ImageBackgroundConfig as a1, type ImageLayer as a2, type ImageTreatment as a3, type ImageWithCaptionInput as a4, LIGHT_SURFACE as a5, type Layer as a6, type LayerRepeat as a7, type LayoutHints as a8, type LeftFeatureInput as a9, PAGE_EMPHASES as aA, PAGE_EYEBROWS as aB, PAGE_HEADING_CASES as aC, PAGE_HEADING_SCALES as aD, PAGE_HEADING_UNDERLINES as aE, PAGE_HERO_STYLES as aF, PAGE_IMAGE_FRAMINGS as aG, PAGE_NUMERAL_STYLES as aH, PAGE_PATTERNS as aI, PAGE_QUOTE_MARKS as aJ, PAGE_SECTION_KINDS as aK, PAGE_SECTION_SPACINGS as aL, PAGE_SHADOWS as aM, PAGE_VARIANTS as aN, type PageAccentRotation as aO, type PageBackground as aP, type PageDesignFamily as aQ, type PageEmphasis as aR, type PageHeadingTreatment as aS, type PageSectionKind as aT, type PageSectionOverride as aU, type PageTokens as aV, type PageVariant as aW, type PathLayer as aX, type PatternBackgroundConfig as aY, type PersistentLayer as aZ, type PersistentLayerConfig as a_, type LineChartInput as aa, type LinearGradient as ab, type ListBlockInput as ac, MOTION_PROFILES as ad, type MapBlockInput as ae, type MapLayer as af, type MapMarker as ag, type MapTileStyle as ah, type MarkerStyle as ai, type MediaClip as aj, type MediaCrop as ak, type MediaCut as al, type MediaEdits as am, type MediaScheduleOptions as an, type MermaidLayer as ao, type MotionEntrance as ap, type MotionOrigin as aq, type MotionProfile as ar, type MotionProfileName as as, type MotionSpec as at, type MotionState as au, PAGE_ACCENT_STRATEGIES as av, PAGE_BACKGROUNDS as aw, PAGE_BACKGROUND_RHYTHMS as ax, PAGE_DESIGN_FAMILIES as ay, PAGE_DIVIDERS as az, type AmbientGradientConfig as b, type VideoWithCaptionInput as b$, type PersistentLayerTemplateConfig as b0, type PersistentLayerTemplateType as b1, type PhotoGridInput as b2, type PieChartInput as b3, type PipStyle as b4, type Position as b5, type ProgressIndicatorConfig as b6, type PromotedBodyAnnotation as b7, type PullQuoteInput as b8, type QuoteBlockInput as b9, type ThemeRegistry as bA, type ThemeSchemaVersion as bB, type ThemeSeedColors as bC, type ThemeStyle as bD, type ThemeTypography as bE, type TimelineBlockInput as bF, type TimelineTemplateEvent as bG, type TimelineTemplateLink as bH, type TimelineTemplateTrack as bI, type TitleBlockInput as bJ, type TitleCaptionConfig as bK, type TranscriptBlockInput as bL, type TreeBlockInput as bM, type TreeLayer as bN, type TreeLayerItem as bO, type TreeLayerStyle as bP, type TreeTemplateItem as bQ, type TwoColumnInput as bR, VIEWPORT_PRESETS as bS, type VideoEmbedLayer as bT, type VideoLayer as bU, type VideoPipPosition as bV, type VideoPipShape as bW, type VideoPipSize as bX, type VideoPlacement as bY, type VideoPresentation as bZ, type VideoPullQuoteInput as b_, type RawLayersInput as ba, type RenderStyle as bb, type RightFeatureInput as bc, type ScatterChartInput as bd, type ScheduledClip as be, type SectionHeaderInput as bf, type ShapeFilter as bg, type ShapeLayer as bh, type ShapePattern as bi, type SolidBackgroundConfig as bj, type StartBlockConfig as bk, type StatHighlightInput as bl, type SurfaceScheme as bm, THEME_SCHEMA_VERSION as bn, type TableLayer as bo, type TableLayerStyle as bp, type TemplateBlock as bq, type TemplateContext as br, type TemplateFunction as bs, type TemplateRegistry as bt, type TextLayer as bu, type TextStyle as bv, type Theme as bw, type ThemeColorPalette as bx, type ThemeColorScheme as by, type ThemePageStyle as bz, type Animation as c, type ViewportConfig as c0, type ViewportOrientation as c1, type ViewportPreset as c2, type VignetteConfig as c3, applySurface as c4, calculateDuration as c5, calculateFontScale as c6, createTemplateContext as c7, createTheme as c8, createThemeRegistry as c9, MEDIA_FX_SPECS as cA, type MediaEditParamKey as cB, type MediaEditParamValues as cC, type MediaFxOp as cD, formatMediaNumber as cE, hasRenderableFx as cF, mediaEditHtmlAttribute as cG, mediaEditValuesFromAttributes as cH, mediaEditValuesFromParams as cI, mediaRenderKey as cJ, normalizeMediaCrop as cK, normalizeMediaCuts as cL, parseMediaCrop as cM, parseMediaCuts as cN, parseMediaEdits as cO, parseMediaFx as cP, serializeMediaCrop as cQ, serializeMediaCuts as cR, serializeMediaEdits as cS, serializeMediaFx as cT, getAspectRatioString as ca, getBlockAtTime as cb, getCaptionAtTime as cc, getDocPlaybackDuration as cd, getLayoutHints as ce, getSafeTextBounds as cf, getSegmentAtTime as cg, getTwoColumnPositions as ch, getViewport as ci, getViewportOrientation as cj, isCustomTemplateDefinition as ck, isMotionProfileName as cl, isPersistentLayerTemplate as cm, isTemplateBlock as cn, scaledFontSize$1 as co, readFrontmatterMotion as cp, resolveMediaSchedule as cq, resolveMotionForDoc as cr, resolveMotionProfile as cs, scaledFontSize as ct, scheduleMediaClip as cu, validateCustomTemplateDefinition as cv, type MediaFxOpId as cw, type MediaFxChain as cx, MEDIA_EDIT_PARAMS as cy, MEDIA_FX_ORDER as cz, type AnimationType as d, type AreaChartInput as e, type AudioBookmark as f, type AudioSegment as g, type AudioTimingData as h, type AudioTrack as i, type BigTextInput as j, type Block as k, type BlockConnection as l, type BorderStyle as m, type CaptionTrack as n, type CaptionWord as o, type ChartBaseFields as p, type ChartTemplateInput as q, type ColorScheme as r, type ColumnChartInput as s, type ComparisonBarInput as t, type ContentBlockInput as u, type CornerBrandingConfig as v, type CountUpSpec as w, type CreateTemplateContextOptions as x, type CustomTemplateDefinition as y, type CustomTemplateLayer as z };
@@ -1,4 +1,4 @@
1
- import { a2 as ImageLayer, bu as TextLayer, bh as ShapeLayer, aX as PathLayer } from './Doc-Bd2kdzuy.js';
1
+ import { a2 as ImageLayer, bu as TextLayer, bh as ShapeLayer, aX as PathLayer } from './Doc-CXx1WL8G.js';
2
2
 
3
3
  /**
4
4
  * ImageEditDoc — JSON document describing a layered, editable image.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  buildNarrationScript,
3
3
  parseNarrationTimingJson
4
- } from "./chunk-5W7F46OO.js";
4
+ } from "./chunk-PNXBDMNS.js";
5
5
  import {
6
6
  SHAPE_NAMES,
7
7
  buildChartData,
@@ -32,7 +32,7 @@ import {
32
32
  templateRegistry,
33
33
  writeCustomTemplatesToFrontmatter,
34
34
  writeCustomThemesToFrontmatter
35
- } from "./chunk-WMXQDP2C.js";
35
+ } from "./chunk-L7IIFWWW.js";
36
36
  import {
37
37
  ASCII_TREE_VOCAB,
38
38
  ASCII_VOCAB,
@@ -49,7 +49,7 @@ import {
49
49
  toCells,
50
50
  toGrid,
51
51
  traceBoxes
52
- } from "./chunk-C3NAY5YP.js";
52
+ } from "./chunk-A5QJJZ5S.js";
53
53
  import {
54
54
  iconMarker
55
55
  } from "./chunk-7ZAAICW4.js";
@@ -82,7 +82,7 @@ import {
82
82
  } from "./chunk-L7QZORLB.js";
83
83
  import {
84
84
  parseMarkdown
85
- } from "./chunk-GDHXT5Q7.js";
85
+ } from "./chunk-PGWYC3S2.js";
86
86
  import {
87
87
  KNOWN_BLOCK_META_KEYS,
88
88
  TABLE_FED_TEMPLATES,
@@ -91,13 +91,16 @@ import {
91
91
  isContainerTemplate,
92
92
  resolveTemplateName,
93
93
  serializeAnnotation
94
- } from "./chunk-TMOHAFYE.js";
94
+ } from "./chunk-WSFXV5BT.js";
95
95
  import {
96
96
  extractPlainText,
97
+ findBlockVideoEmbed,
97
98
  getChildren,
99
+ isVideoEmbedUrl,
98
100
  parseHtmlToNodes,
101
+ parseVideoEmbedUrl,
99
102
  readFrontmatterThemeId
100
- } from "./chunk-X7BNDUNI.js";
103
+ } from "./chunk-Q6ELOAOQ.js";
101
104
  import {
102
105
  buildCaptionTrack
103
106
  } from "./chunk-4OQFLZ6G.js";
@@ -894,6 +897,9 @@ function getTemplateDefaults(templateName, headingText, block) {
894
897
  return deriveTemplateInputs(templateName, headingText, block.contents) ?? {
895
898
  items: ["Item 1", "Item 2", "Item 3"]
896
899
  };
900
+ case "videoWithCaption":
901
+ case "videoPullQuote":
902
+ return deriveTemplateInputs(templateName, headingText, block.contents) ?? {};
897
903
  case "definitionCard":
898
904
  return { term: headingText, definition: body || headingText };
899
905
  case "dateEvent":
@@ -1467,6 +1473,20 @@ var pullQuote = (input) => {
1467
1473
  };
1468
1474
  var videoWithCaption = (input) => {
1469
1475
  const v = input;
1476
+ if (isVideoEmbedUrl(v.videoSrc)) {
1477
+ return {
1478
+ kind: "media-figure",
1479
+ variant: "video",
1480
+ slots: {
1481
+ media: {
1482
+ type: "videoEmbed",
1483
+ url: v.videoSrc,
1484
+ ...v.videoAlt ? { title: v.videoAlt } : {}
1485
+ },
1486
+ caption: v.caption
1487
+ }
1488
+ };
1489
+ }
1470
1490
  return {
1471
1491
  kind: "media-figure",
1472
1492
  variant: "video",
@@ -1665,8 +1685,14 @@ function markdownNodeContainsMedia(value) {
1665
1685
  function unconsumedRichContent(block, draft, widgetFenceLangs) {
1666
1686
  if (!block.contents || block.contents.length === 0) return void 0;
1667
1687
  const templateHasMedia = Boolean(draft.slots.media) || Boolean(draft.slots.items?.some((item) => item.media !== void 0));
1688
+ const media = draft.slots.media;
1689
+ const playedVideo = media?.type === "videoEmbed" ? parseVideoEmbedUrl(media.url)?.watchUrl ?? media.url : null;
1690
+ const isUnplayedVideo = (node) => {
1691
+ const video = findBlockVideoEmbed(node);
1692
+ return video !== null && video.embed.watchUrl !== playedVideo;
1693
+ };
1668
1694
  const markdown = block.contents.filter(
1669
- (node) => isWidgetFence(node, widgetFenceLangs) || !templateHasMedia && markdownNodeContainsMedia(node)
1695
+ (node) => isWidgetFence(node, widgetFenceLangs) || !templateHasMedia && markdownNodeContainsMedia(node) || isUnplayedVideo(node)
1670
1696
  );
1671
1697
  if (markdown.length === 0) return void 0;
1672
1698
  return {
@@ -2369,6 +2395,7 @@ var PAGE_BASE_CSS = `
2369
2395
  /* \u2500\u2500 Media figure \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
2370
2396
  .squisq-page-figure { margin: 0; }
2371
2397
  .squisq-page-figure img, .squisq-page-figure video { width: 100%; display: block; }
2398
+ .squisq-page-figure .squisq-video-embed { max-width: none; margin: 0; }
2372
2399
  .squisq-page-figure figcaption { margin-top: 0.9em; font-size: 0.9rem; color: var(--squisq-page-text-muted); text-align: center; }
2373
2400
  .squisq-page-media-credit { font-size: 0.78rem; opacity: 0.75; }
2374
2401
 
@@ -1,8 +1,10 @@
1
1
  import {
2
2
  extractPlainText,
3
3
  findNodesByType,
4
+ isVideoEmbedUrl,
5
+ mediaKindForUrl,
4
6
  walkMarkdownTree
5
- } from "./chunk-X7BNDUNI.js";
7
+ } from "./chunk-Q6ELOAOQ.js";
6
8
 
7
9
  // src/doc/asciiDiagram/chars.ts
8
10
  function toCells(s) {
@@ -2483,7 +2485,6 @@ var DATE_PATTERNS = [
2483
2485
  /\b\d{4}s\b/,
2484
2486
  /\b\d{1,2}(st|nd|rd|th)\s+century\b/i
2485
2487
  ];
2486
- var VIDEO_HOST_RE = /(youtube\.com|youtu\.be|vimeo\.com|wistia\.|loom\.com)/i;
2487
2488
  function htmlElementsByTag(root, tagNames) {
2488
2489
  const blocks = findNodesByType(root, "htmlBlock");
2489
2490
  const inline = findNodesByType(root, "htmlInline");
@@ -2508,7 +2509,9 @@ function profileBlockContents(nodes) {
2508
2509
  let hasTable = false;
2509
2510
  const plainParts = [];
2510
2511
  for (const node of nodes) {
2511
- imageCount += findNodesByType(node, "image").length;
2512
+ imageCount += findNodesByType(node, "image").filter(
2513
+ (img) => !mediaKindForUrl(img.url ?? "")
2514
+ ).length;
2512
2515
  imageCount += findNodesByType(node, "imageReference").length;
2513
2516
  if (findNodesByType(node, "blockquote").length > 0) hasBlockquote = true;
2514
2517
  if (findNodesByType(node, "list").length > 0) hasList = true;
@@ -2526,7 +2529,7 @@ function profileBlockContents(nodes) {
2526
2529
  break;
2527
2530
  }
2528
2531
  const src = el.attributes.src || el.attributes.href || "";
2529
- if (VIDEO_HOST_RE.test(src)) {
2532
+ if (isVideoEmbedUrl(src)) {
2530
2533
  hasVideo = true;
2531
2534
  break;
2532
2535
  }
@@ -2534,7 +2537,7 @@ function profileBlockContents(nodes) {
2534
2537
  if (!hasVideo) {
2535
2538
  const links = findNodesByType(root, "link");
2536
2539
  for (const link of links) {
2537
- if (link.url && VIDEO_HOST_RE.test(link.url)) {
2540
+ if (isVideoEmbedUrl(link.url)) {
2538
2541
  hasVideo = true;
2539
2542
  break;
2540
2543
  }
@@ -57,6 +57,7 @@ var LAYER_TYPES = /* @__PURE__ */ new Set([
57
57
  "path",
58
58
  "map",
59
59
  "video",
60
+ "videoEmbed",
60
61
  "table",
61
62
  "tree",
62
63
  "mermaid"
@@ -199,6 +200,9 @@ function validateLayerContent(type, content, path, issues) {
199
200
  requiredFiniteNumber(content, "clipStart", `${path}.clipStart`, issues, { min: 0 });
200
201
  requiredFiniteNumber(content, "clipEnd", `${path}.clipEnd`, issues, { min: 0 });
201
202
  break;
203
+ case "videoEmbed":
204
+ requiredString(content, "url", `${path}.url`, issues);
205
+ break;
202
206
  case "table":
203
207
  requiredStringArray(content, "headers", `${path}.headers`, issues);
204
208
  validateStringRows(content.rows, `${path}.rows`, issues);
@@ -8,27 +8,27 @@ import {
8
8
  deriveTemplateInputs,
9
9
  flattenRenderableBlocks,
10
10
  markdownToDoc
11
- } from "./chunk-WMXQDP2C.js";
11
+ } from "./chunk-L7IIFWWW.js";
12
12
  import {
13
13
  isAsciiDiagramFence,
14
14
  isAsciiTimelineFence,
15
15
  isTreeFence
16
- } from "./chunk-C3NAY5YP.js";
16
+ } from "./chunk-A5QJJZ5S.js";
17
17
  import {
18
18
  cloneAndFreezeData,
19
19
  isTemplateBlock
20
20
  } from "./chunk-PFH3WV6J.js";
21
21
  import {
22
22
  parseMarkdown
23
- } from "./chunk-GDHXT5Q7.js";
23
+ } from "./chunk-PGWYC3S2.js";
24
24
  import {
25
25
  isContainerTemplate
26
- } from "./chunk-TMOHAFYE.js";
26
+ } from "./chunk-WSFXV5BT.js";
27
27
  import {
28
28
  extractPlainText,
29
29
  getChildren,
30
30
  stringifyHtmlNodes
31
- } from "./chunk-X7BNDUNI.js";
31
+ } from "./chunk-Q6ELOAOQ.js";
32
32
  import {
33
33
  estimateTimeFromText
34
34
  } from "./chunk-GHOPHGOK.js";
@@ -13,7 +13,7 @@ import {
13
13
  parseAsciiTimeline,
14
14
  pickAutoTemplate,
15
15
  profileBlockContents
16
- } from "./chunk-C3NAY5YP.js";
16
+ } from "./chunk-A5QJJZ5S.js";
17
17
  import {
18
18
  anchorPoint,
19
19
  base64ToUtf8,
@@ -61,12 +61,16 @@ import {
61
61
  sanitizeUrl,
62
62
  splitKeyValueToken,
63
63
  tokenizeAttrTokens
64
- } from "./chunk-TMOHAFYE.js";
64
+ } from "./chunk-WSFXV5BT.js";
65
65
  import {
66
66
  extractPlainText,
67
+ findBlockVideoEmbed,
68
+ isVideoEmbedUrl,
69
+ mediaKindForUrl,
70
+ parseVideoEmbedUrl,
67
71
  readFrontmatterThemeId,
68
72
  walkMarkdownTree
69
- } from "./chunk-X7BNDUNI.js";
73
+ } from "./chunk-Q6ELOAOQ.js";
70
74
  import {
71
75
  resolveBlockTransition
72
76
  } from "./chunk-4VOD55SX.js";
@@ -1574,9 +1578,29 @@ function findFirstList(contents) {
1574
1578
 
1575
1579
  // src/doc/templateInputs.ts
1576
1580
  var VIDEO_FILE_RE = /\.(?:webm|mp4|mov|m4v|ogv)(?:[?#].*)?$/i;
1581
+ function extractHostedVideos(contents, limit = Infinity) {
1582
+ const found = [];
1583
+ const seen = /* @__PURE__ */ new Set();
1584
+ for (const node of contents ?? []) {
1585
+ if (found.length >= limit) break;
1586
+ const video = findBlockVideoEmbed(node);
1587
+ if (!video || seen.has(video.embed.watchUrl)) continue;
1588
+ seen.add(video.embed.watchUrl);
1589
+ found.push({
1590
+ url: video.embed.watchUrl,
1591
+ title: video.title,
1592
+ aspectRatio: video.embed.aspectRatio
1593
+ });
1594
+ }
1595
+ return found;
1596
+ }
1597
+ function isMaterializedMediaNode(node) {
1598
+ if (node.type === "code") return node.lang?.trim().toLowerCase() === "mermaid";
1599
+ return findBlockVideoEmbed(node) !== null;
1600
+ }
1577
1601
  function extractBodyPlainText(contents) {
1578
1602
  if (!contents || contents.length === 0) return "";
1579
- return contents.filter((node) => !(node.type === "code" && node.lang?.trim().toLowerCase() === "mermaid")).map((n) => extractPlainText(n)).join("\n").trim();
1603
+ return contents.filter((node) => !isMaterializedMediaNode(node)).map((n) => extractPlainText(n)).join("\n").trim();
1580
1604
  }
1581
1605
  function extractListItems(contents) {
1582
1606
  return extractRichListItems(contents).map((item) => item.text);
@@ -1750,7 +1774,9 @@ function extractImages(contents, limit = Infinity) {
1750
1774
  if (!node || typeof node !== "object") return;
1751
1775
  const n = node;
1752
1776
  if (n.type === "image" && typeof n.url === "string" && n.url) {
1753
- found.push({ src: n.url, alt: typeof n.alt === "string" ? n.alt : "" });
1777
+ if (!mediaKindForUrl(n.url)) {
1778
+ found.push({ src: n.url, alt: typeof n.alt === "string" ? n.alt : "" });
1779
+ }
1754
1780
  return;
1755
1781
  }
1756
1782
  if ((n.type === "htmlBlock" || n.type === "htmlInline") && Array.isArray(n.htmlChildren)) {
@@ -1951,7 +1977,7 @@ function autoTemplatePreservesContent(templateName, contents) {
1951
1977
  }
1952
1978
  case "videoWithCaption": {
1953
1979
  const videos = extractEmbeddedVideos(nodes);
1954
- if (videos.length !== 1) return false;
1980
+ if (videos.length + extractHostedVideos(nodes).length !== 1) return false;
1955
1981
  const bodyText3 = normalizeCoverageText(extractBodyPlainText(nodes));
1956
1982
  return bodyText3 === normalizeCoverageText(videos[0]?.alt ?? "");
1957
1983
  }
@@ -2097,7 +2123,17 @@ function deriveTemplateInputs(templateName, headingText, contents, options = {})
2097
2123
  }
2098
2124
  case "videoWithCaption": {
2099
2125
  const video = extractFirstEmbeddedVideo(contents);
2100
- if (!video) return placeholders ? { caption: headingText } : null;
2126
+ if (!video) {
2127
+ const hosted = extractHostedVideos(contents, 1)[0];
2128
+ if (hosted) {
2129
+ return {
2130
+ videoSrc: hosted.url,
2131
+ videoAlt: hosted.title || headingText,
2132
+ caption: headingText
2133
+ };
2134
+ }
2135
+ return placeholders ? { caption: headingText } : null;
2136
+ }
2101
2137
  return {
2102
2138
  videoSrc: video.src,
2103
2139
  posterSrc: video.posterSrc,
@@ -2160,10 +2196,10 @@ function deriveTemplateInputs(templateName, headingText, contents, options = {})
2160
2196
  function bodyNodes(context) {
2161
2197
  if (context.block?.summaryMode === "headings-and-features") return [];
2162
2198
  return (context.block?.contents ?? []).filter(
2163
- // Mermaid source is already materialized as a visual layer. Repeating the
2164
- // fence text as prose makes the loss-averse default noisy without
2165
- // preserving any additional authored meaning.
2166
- (node) => !(node.type === "code" && node.lang?.trim().toLowerCase() === "mermaid")
2199
+ // Mermaid source and hosted-video links are already materialized as
2200
+ // visual layers (a diagram, a player). Repeating them as prose makes the
2201
+ // loss-averse default noisy without preserving any additional meaning.
2202
+ (node) => !isMaterializedMediaNode(node)
2167
2203
  );
2168
2204
  }
2169
2205
  function plainListText(list, depth = 0) {
@@ -4579,6 +4615,37 @@ function videoWithCaption(input, context) {
4579
4615
  const resolvedClipEnd = Math.max(clipStart, clipEnd ?? clipStart + Math.max(0, input.duration));
4580
4616
  const captionFontSize = themedFontSize(30, context, false);
4581
4617
  const creditFontSize = themedFontSize(16, context, false);
4618
+ if (isVideoEmbedUrl(videoSrc)) {
4619
+ const layers2 = [
4620
+ createBackgroundLayer("bg", theme.colors.background),
4621
+ {
4622
+ type: "videoEmbed",
4623
+ id: "bg-video",
4624
+ content: { url: videoSrc, ...videoAlt ? { title: videoAlt } : {} },
4625
+ position: caption ? { x: "4%", y: "4%", width: "92%", height: "78%" } : { x: "4%", y: "4%", width: "92%", height: "92%" }
4626
+ }
4627
+ ];
4628
+ if (caption) {
4629
+ layers2.push({
4630
+ type: "text",
4631
+ id: "caption",
4632
+ content: {
4633
+ text: caption,
4634
+ style: {
4635
+ fontSize: captionFontSize,
4636
+ fontFamily: getThemeFont(context, "body"),
4637
+ color: theme.colors.text,
4638
+ textAlign: "center",
4639
+ lineHeight: 1.18,
4640
+ maxLines: 2
4641
+ }
4642
+ },
4643
+ position: { x: "50%", y: "90%", anchor: "center", width: "84%" },
4644
+ animation: { type: "fadeIn", duration: 1.5, delay: 0.5 }
4645
+ });
4646
+ }
4647
+ return layers2;
4648
+ }
4582
4649
  const layers = [
4583
4650
  // Background video clip
4584
4651
  {
@@ -5668,7 +5735,7 @@ function resolveSupplementalMediaLayout(layers, template, viewport, mediaCount,
5668
5735
  const policy = getBlockMediaLayoutPolicy(template);
5669
5736
  const shape = mediaShape(mediaCount, aspectRatios);
5670
5737
  const alreadyOwnsMedia = layers.some(
5671
- (layer) => layer.type === "image" || layer.type === "video" || layer.type === "map" || layer.type === "mermaid"
5738
+ (layer) => layer.type === "image" || layer.type === "video" || layer.type === "videoEmbed" || layer.type === "map" || layer.type === "mermaid"
5672
5739
  );
5673
5740
  if (!alreadyOwnsMedia && (policy?.nativeLayout === "feature-left" || policy?.nativeLayout === "feature-right")) {
5674
5741
  const { position } = featureMediaSlot(
@@ -9921,6 +9988,9 @@ function collectRichMediaItems(layers, block) {
9921
9988
  const existingMermaid = new Set(
9922
9989
  layers.filter((layer) => layer.type === "mermaid").map((layer) => layer.content.source)
9923
9990
  );
9991
+ const existingEmbeds = new Set(
9992
+ layers.filter((layer) => layer.type === "videoEmbed").map((layer) => parseVideoEmbedUrl(layer.content.url)?.watchUrl ?? layer.content.url)
9993
+ );
9924
9994
  const embeddedVideos = extractEmbeddedVideos(block.contents);
9925
9995
  const videos = embeddedVideos.filter((video) => !existingVideos.has(video.src));
9926
9996
  const videoSources = new Set(embeddedVideos.map((video) => video.src));
@@ -9931,6 +10001,9 @@ function collectRichMediaItems(layers, block) {
9931
10001
  return true;
9932
10002
  });
9933
10003
  const sources = mermaidSources(block).filter((source) => !existingMermaid.has(source));
10004
+ const hosted = extractHostedVideos(block.contents).filter(
10005
+ (video) => !existingEmbeds.has(video.url)
10006
+ );
9934
10007
  return [
9935
10008
  ...images.map(
9936
10009
  (image) => ({
@@ -9952,6 +10025,14 @@ function collectRichMediaItems(layers, block) {
9952
10025
  ...video.clipEnd != null ? { clipEnd: video.clipEnd } : {}
9953
10026
  })
9954
10027
  ),
10028
+ ...hosted.map(
10029
+ (video) => ({
10030
+ kind: "videoEmbed",
10031
+ url: video.url,
10032
+ title: video.title,
10033
+ aspectRatio: video.aspectRatio
10034
+ })
10035
+ ),
9955
10036
  ...sources.map((source) => ({ kind: "mermaid", source, aspectRatio: 16 / 9 })),
9956
10037
  ...embeddedSpatialMedia(block)
9957
10038
  ];
@@ -10023,6 +10104,17 @@ function richMediaLayers(item, position, block, theme, kindIndex) {
10023
10104
  }
10024
10105
  ];
10025
10106
  }
10107
+ if (item.kind === "videoEmbed") {
10108
+ const title = item.title || block.title;
10109
+ return [
10110
+ {
10111
+ id: `${block.id}-video-embed-${kindIndex}`,
10112
+ type: "videoEmbed",
10113
+ position,
10114
+ content: { url: item.url, ...title ? { title } : {} }
10115
+ }
10116
+ ];
10117
+ }
10026
10118
  if (item.kind === "mermaid") {
10027
10119
  return [
10028
10120
  {
@@ -10107,6 +10199,7 @@ function appendRichContentLayers(layers, block, theme, viewport, mediaAspectRati
10107
10199
  const counters = {
10108
10200
  image: 0,
10109
10201
  video: 0,
10202
+ videoEmbed: 0,
10110
10203
  mermaid: 0,
10111
10204
  spatial: 0
10112
10205
  };
@@ -12272,7 +12365,7 @@ function getBlockBodyText2(block) {
12272
12365
  if (!block.contents || block.contents.length === 0) return "";
12273
12366
  const tmpl = resolveTemplateName(block.template ?? "");
12274
12367
  const consumedFence = tmpl === "diagram" && block.templateData !== void 0 && "nodes" in block.templateData || tmpl === "timeline" && block.templateData !== void 0 && "tracks" in block.templateData || tmpl === "tree" && block.templateData !== void 0 && "items" in block.templateData;
12275
- return block.contents.filter((node) => !(consumedFence && node.type === "code")).map((node) => extractPlainText(node)).join("\n").trim();
12368
+ return block.contents.filter((node) => !(consumedFence && node.type === "code")).filter((node) => findBlockVideoEmbed(node) === null).map((node) => extractPlainText(node)).join("\n").trim();
12276
12369
  }
12277
12370
  var MAX_PHRASE_WORDS = 12;
12278
12371
  function splitIntoSentences(text) {
@@ -12334,7 +12427,7 @@ function findFirstHtmlImage(nodes) {
12334
12427
  function findFirstImage(node) {
12335
12428
  if (node.type === "image") {
12336
12429
  const img = node;
12337
- return { url: img.url, alt: img.alt };
12430
+ return mediaKindForUrl(img.url) ? void 0 : { url: img.url, alt: img.alt };
12338
12431
  }
12339
12432
  if (node.type === "htmlBlock" || node.type === "htmlInline") {
12340
12433
  const html = node;
@@ -12434,6 +12527,8 @@ export {
12434
12527
  treeFromTemplateData,
12435
12528
  treeFromMarkdownList,
12436
12529
  findFirstList,
12530
+ extractHostedVideos,
12531
+ isMaterializedMediaNode,
12437
12532
  extractBodyPlainText,
12438
12533
  extractListItems,
12439
12534
  renderMarkdownBlocksHtml,