@bendyline/squisq 2.13.9 → 2.13.11

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.
@@ -2396,6 +2396,8 @@ interface Doc {
2396
2396
  duration: number;
2397
2397
  bookmarks: AudioBookmark[];
2398
2398
  builds?: BuildAdvance[];
2399
+ /** When the presenter first showed each presentation slide during the take. */
2400
+ slides?: PresentationSlideMark[];
2399
2401
  };
2400
2402
  /** Projection-only guard: never compile an accepted plan twice. */
2401
2403
  presentationApplied?: boolean;
@@ -3443,6 +3445,17 @@ interface AudioBookmark {
3443
3445
  /** The word text at this position */
3444
3446
  textFragment?: string;
3445
3447
  }
3448
+ /**
3449
+ * A presentation slide the presenter put on screen while recording, keyed by
3450
+ * where its passage begins in the narration script. Unlike a bookmark it marks
3451
+ * a click, not a spoken word.
3452
+ */
3453
+ interface PresentationSlideMark {
3454
+ /** Character offset in the narration script where the slide's passage begins. */
3455
+ charOffset: number;
3456
+ /** Seconds: take-relative in a timing sidecar, document time once applied. */
3457
+ time: number;
3458
+ }
3446
3459
  /**
3447
3460
  * Timing data for an audio segment, typically from a `.timing.json` file
3448
3461
  * generated alongside TTS audio. Contains the source text and per-word
@@ -3473,4 +3486,4 @@ declare function getBlockAtTime(blocks: Block[], time: number): Block | null;
3473
3486
  */
3474
3487
  declare function getCaptionAtTime(captions: CaptionTrack | undefined, time: number): CaptionPhrase | null;
3475
3488
 
3476
- export { type FontFamilyKind as $, type AccentImage as A, type BarChartInput as B, type CaptionPhrase as C, type CustomTemplateLayer as D, type CustomTemplateValidationError as E, type CustomTemplateValidationResult as F, DARK_SURFACE as G, DEFAULT_DOC_FONT as H, DEFAULT_TITLE_FONT as I, type DataTableInput as J, type DateEventInput as K, type DeepPartial as L, type DefinitionCardInput as M, type DiagramBlockInput as N, type DiagramEdgeAnchor as O, type DiagramTemplateEdge as P, type DiagramTemplateNode as Q, type Doc as R, type DocBlock as S, type DocDiagnostic as T, type DonutChartInput as U, type DrawingBlockInput as V, FRONTMATTER_CUSTOM_TEMPLATES_KEY as W, FRONTMATTER_CUSTOM_THEMES_KEY as X, FRONTMATTER_MOTION_KEY as Y, type FactCardInput as Z, type FontFamily as _, type AccentPosition as a, type PersistentLayer as a$, type FullBleedQuoteInput as a0, type GradientBackgroundConfig as a1, type ImageBackgroundConfig as a2, type ImageLayer as a3, type ImageTreatment as a4, type ImageWithCaptionInput as a5, LIGHT_SURFACE as a6, type Layer as a7, type LayerRepeat as a8, type LayoutHints as a9, PAGE_DESIGN_FAMILIES as aA, PAGE_DIVIDERS as aB, PAGE_EMPHASES as aC, PAGE_EYEBROWS as aD, PAGE_HEADING_CASES as aE, PAGE_HEADING_SCALES as aF, PAGE_HEADING_UNDERLINES as aG, PAGE_HERO_STYLES as aH, PAGE_IMAGE_FRAMINGS as aI, PAGE_NUMERAL_STYLES as aJ, PAGE_PATTERNS as aK, PAGE_QUOTE_MARKS as aL, PAGE_SECTION_KINDS as aM, PAGE_SECTION_SPACINGS as aN, PAGE_SHADOWS as aO, PAGE_VARIANTS as aP, type PageAccentRotation as aQ, type PageBackground as aR, type PageDesignFamily as aS, type PageEmphasis as aT, type PageHeadingTreatment as aU, type PageSectionKind as aV, type PageSectionOverride as aW, type PageTokens as aX, type PageVariant as aY, type PathLayer as aZ, type PatternBackgroundConfig as a_, type LeftFeatureInput as aa, type LineChartInput as ab, type LinearGradient as ac, type ListBlockInput as ad, MOTION_PROFILES as ae, type MapBlockInput as af, type MapLayer as ag, type MapMarker as ah, type MapTileStyle as ai, type MarkerStyle as aj, type MediaClip as ak, type MediaCrop as al, type MediaCut as am, type MediaEdits as an, type MediaOnlyInput as ao, type MediaScheduleOptions as ap, type MermaidLayer as aq, type MotionEntrance as ar, type MotionOrigin as as, type MotionProfile as at, type MotionProfileName as au, type MotionSpec as av, type MotionState as aw, PAGE_ACCENT_STRATEGIES as ax, PAGE_BACKGROUNDS as ay, PAGE_BACKGROUND_RHYTHMS as az, type AmbientGradientConfig as b, type VideoLayer as b$, type PersistentLayerConfig as b0, type PersistentLayerTemplate as b1, type PersistentLayerTemplateConfig as b2, type PersistentLayerTemplateType as b3, type PhotoGridInput as b4, type PieChartInput as b5, type PipStyle as b6, type Position as b7, type ProgressIndicatorConfig as b8, type PromotedBodyAnnotation as b9, type TextParagraphList as bA, type TextStyle as bB, type Theme as bC, type ThemeColorPalette as bD, type ThemeColorScheme as bE, type ThemePageStyle as bF, type ThemeRegistry as bG, type ThemeSchemaVersion as bH, type ThemeSeedColors as bI, type ThemeStyle as bJ, type ThemeTypography as bK, type TimelineBlockInput as bL, type TimelineTemplateEvent as bM, type TimelineTemplateLink as bN, type TimelineTemplateTrack as bO, type TitleBlockInput as bP, type TitleCaptionConfig as bQ, type TopFeatureInput as bR, type TranscriptBlockInput as bS, type TreeBlockInput as bT, type TreeLayer as bU, type TreeLayerItem as bV, type TreeLayerStyle as bW, type TreeTemplateItem as bX, type TwoColumnInput as bY, VIEWPORT_PRESETS as bZ, type VideoEmbedLayer as b_, type PullQuoteInput as ba, type QuoteBlockInput as bb, type RawLayersInput as bc, type RenderStyle as bd, type RightFeatureInput as be, type ScatterChartInput as bf, type ScheduledClip as bg, type SectionHeaderInput as bh, type ShapeFilter as bi, type ShapeLayer as bj, type ShapePattern as bk, type SolidBackgroundConfig as bl, type StartBlockConfig as bm, type StatHighlightInput as bn, type SurfaceScheme as bo, type SvgLayer as bp, THEME_SCHEMA_VERSION as bq, type TableLayer as br, type TableLayerStyle as bs, type TemplateBlock as bt, type TemplateContext as bu, type TemplateFunction as bv, type TemplateRegistry as bw, type TextFlow as bx, type TextLayer as by, type TextParagraph as bz, type Animation as c, type VideoPipPosition as c0, type VideoPipShape as c1, type VideoPipSize as c2, type VideoPlacement as c3, type VideoPresentation as c4, type VideoPullQuoteInput as c5, type VideoWithCaptionInput as c6, type ViewportConfig as c7, type ViewportOrientation as c8, type ViewportPreset as c9, scaledFontSize as cA, scheduleMediaClip as cB, validateCustomTemplateDefinition as cC, type MediaFxOpId as cD, type MediaFxChain as cE, MEDIA_EDIT_PARAMS as cF, MEDIA_FX_ORDER as cG, MEDIA_FX_SPECS as cH, type MediaEditParamKey as cI, type MediaEditParamValues as cJ, type MediaFxOp as cK, formatMediaNumber as cL, hasRenderableFx as cM, mediaEditHtmlAttribute as cN, mediaEditValuesFromAttributes as cO, mediaEditValuesFromParams as cP, mediaRenderKey as cQ, normalizeMediaCrop as cR, normalizeMediaCuts as cS, parseMediaCrop as cT, parseMediaCuts as cU, parseMediaEdits as cV, parseMediaFx as cW, serializeMediaCrop as cX, serializeMediaCuts as cY, serializeMediaEdits as cZ, serializeMediaFx as c_, type VignetteConfig as ca, applySurface as cb, calculateDuration as cc, calculateFontScale as cd, createTemplateContext as ce, createTheme as cf, createThemeRegistry as cg, getAspectRatioString as ch, getBlockAtTime as ci, getCaptionAtTime as cj, getDocPlaybackDuration as ck, getLayoutHints as cl, getSafeTextBounds as cm, getSegmentAtTime as cn, getTwoColumnPositions as co, getViewport as cp, getViewportOrientation as cq, isCustomTemplateDefinition as cr, isMotionProfileName as cs, isPersistentLayerTemplate as ct, isTemplateBlock as cu, scaledFontSize$1 as cv, readFrontmatterMotion as cw, resolveMediaSchedule as cx, resolveMotionForDoc as cy, resolveMotionProfile 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 BottomFeatureInput as n, type CaptionTrack as o, type CaptionWord as p, type ChartBaseFields as q, type ChartTemplateInput as r, type ColorScheme as s, type ColumnChartInput as t, type ComparisonBarInput as u, type ContentBlockInput as v, type CornerBrandingConfig as w, type CountUpSpec as x, type CreateTemplateContextOptions as y, type CustomTemplateDefinition as z };
3489
+ export { type FontFamilyKind as $, type AccentImage as A, type BarChartInput as B, type CaptionPhrase as C, type CustomTemplateLayer as D, type CustomTemplateValidationError as E, type CustomTemplateValidationResult as F, DARK_SURFACE as G, DEFAULT_DOC_FONT as H, DEFAULT_TITLE_FONT as I, type DataTableInput as J, type DateEventInput as K, type DeepPartial as L, type DefinitionCardInput as M, type DiagramBlockInput as N, type DiagramEdgeAnchor as O, type DiagramTemplateEdge as P, type DiagramTemplateNode as Q, type Doc as R, type DocBlock as S, type DocDiagnostic as T, type DonutChartInput as U, type DrawingBlockInput as V, FRONTMATTER_CUSTOM_TEMPLATES_KEY as W, FRONTMATTER_CUSTOM_THEMES_KEY as X, FRONTMATTER_MOTION_KEY as Y, type FactCardInput as Z, type FontFamily as _, type AccentPosition as a, type PersistentLayer as a$, type FullBleedQuoteInput as a0, type GradientBackgroundConfig as a1, type ImageBackgroundConfig as a2, type ImageLayer as a3, type ImageTreatment as a4, type ImageWithCaptionInput as a5, LIGHT_SURFACE as a6, type Layer as a7, type LayerRepeat as a8, type LayoutHints as a9, PAGE_DESIGN_FAMILIES as aA, PAGE_DIVIDERS as aB, PAGE_EMPHASES as aC, PAGE_EYEBROWS as aD, PAGE_HEADING_CASES as aE, PAGE_HEADING_SCALES as aF, PAGE_HEADING_UNDERLINES as aG, PAGE_HERO_STYLES as aH, PAGE_IMAGE_FRAMINGS as aI, PAGE_NUMERAL_STYLES as aJ, PAGE_PATTERNS as aK, PAGE_QUOTE_MARKS as aL, PAGE_SECTION_KINDS as aM, PAGE_SECTION_SPACINGS as aN, PAGE_SHADOWS as aO, PAGE_VARIANTS as aP, type PageAccentRotation as aQ, type PageBackground as aR, type PageDesignFamily as aS, type PageEmphasis as aT, type PageHeadingTreatment as aU, type PageSectionKind as aV, type PageSectionOverride as aW, type PageTokens as aX, type PageVariant as aY, type PathLayer as aZ, type PatternBackgroundConfig as a_, type LeftFeatureInput as aa, type LineChartInput as ab, type LinearGradient as ac, type ListBlockInput as ad, MOTION_PROFILES as ae, type MapBlockInput as af, type MapLayer as ag, type MapMarker as ah, type MapTileStyle as ai, type MarkerStyle as aj, type MediaClip as ak, type MediaCrop as al, type MediaCut as am, type MediaEdits as an, type MediaOnlyInput as ao, type MediaScheduleOptions as ap, type MermaidLayer as aq, type MotionEntrance as ar, type MotionOrigin as as, type MotionProfile as at, type MotionProfileName as au, type MotionSpec as av, type MotionState as aw, PAGE_ACCENT_STRATEGIES as ax, PAGE_BACKGROUNDS as ay, PAGE_BACKGROUND_RHYTHMS as az, type AmbientGradientConfig as b, type VideoEmbedLayer as b$, type PersistentLayerConfig as b0, type PersistentLayerTemplate as b1, type PersistentLayerTemplateConfig as b2, type PersistentLayerTemplateType as b3, type PhotoGridInput as b4, type PieChartInput as b5, type PipStyle as b6, type Position as b7, type PresentationSlideMark as b8, type ProgressIndicatorConfig as b9, type TextParagraph as bA, type TextParagraphList as bB, type TextStyle as bC, type Theme as bD, type ThemeColorPalette as bE, type ThemeColorScheme as bF, type ThemePageStyle as bG, type ThemeRegistry as bH, type ThemeSchemaVersion as bI, type ThemeSeedColors as bJ, type ThemeStyle as bK, type ThemeTypography as bL, type TimelineBlockInput as bM, type TimelineTemplateEvent as bN, type TimelineTemplateLink as bO, type TimelineTemplateTrack as bP, type TitleBlockInput as bQ, type TitleCaptionConfig as bR, type TopFeatureInput as bS, type TranscriptBlockInput as bT, type TreeBlockInput as bU, type TreeLayer as bV, type TreeLayerItem as bW, type TreeLayerStyle as bX, type TreeTemplateItem as bY, type TwoColumnInput as bZ, VIEWPORT_PRESETS as b_, type PromotedBodyAnnotation as ba, type PullQuoteInput as bb, type QuoteBlockInput as bc, type RawLayersInput as bd, type RenderStyle as be, type RightFeatureInput as bf, type ScatterChartInput as bg, type ScheduledClip as bh, type SectionHeaderInput as bi, type ShapeFilter as bj, type ShapeLayer as bk, type ShapePattern as bl, type SolidBackgroundConfig as bm, type StartBlockConfig as bn, type StatHighlightInput as bo, type SurfaceScheme as bp, type SvgLayer as bq, THEME_SCHEMA_VERSION as br, type TableLayer as bs, type TableLayerStyle as bt, type TemplateBlock as bu, type TemplateContext as bv, type TemplateFunction as bw, type TemplateRegistry as bx, type TextFlow as by, type TextLayer as bz, type Animation as c, serializeMediaFx as c$, type VideoLayer as c0, type VideoPipPosition as c1, type VideoPipShape as c2, type VideoPipSize as c3, type VideoPlacement as c4, type VideoPresentation as c5, type VideoPullQuoteInput as c6, type VideoWithCaptionInput as c7, type ViewportConfig as c8, type ViewportOrientation as c9, resolveMotionProfile as cA, scaledFontSize as cB, scheduleMediaClip as cC, validateCustomTemplateDefinition as cD, type MediaFxOpId as cE, type MediaFxChain as cF, MEDIA_EDIT_PARAMS as cG, MEDIA_FX_ORDER as cH, MEDIA_FX_SPECS as cI, type MediaEditParamKey as cJ, type MediaEditParamValues as cK, type MediaFxOp as cL, formatMediaNumber as cM, hasRenderableFx as cN, mediaEditHtmlAttribute as cO, mediaEditValuesFromAttributes as cP, mediaEditValuesFromParams as cQ, mediaRenderKey as cR, normalizeMediaCrop as cS, normalizeMediaCuts as cT, parseMediaCrop as cU, parseMediaCuts as cV, parseMediaEdits as cW, parseMediaFx as cX, serializeMediaCrop as cY, serializeMediaCuts as cZ, serializeMediaEdits as c_, type ViewportPreset as ca, type VignetteConfig as cb, applySurface as cc, calculateDuration as cd, calculateFontScale as ce, createTemplateContext as cf, createTheme as cg, createThemeRegistry as ch, getAspectRatioString as ci, getBlockAtTime as cj, getCaptionAtTime as ck, getDocPlaybackDuration as cl, getLayoutHints as cm, getSafeTextBounds as cn, getSegmentAtTime as co, getTwoColumnPositions as cp, getViewport as cq, getViewportOrientation as cr, isCustomTemplateDefinition as cs, isMotionProfileName as ct, isPersistentLayerTemplate as cu, isTemplateBlock as cv, scaledFontSize$1 as cw, readFrontmatterMotion as cx, resolveMediaSchedule as cy, resolveMotionForDoc 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 BottomFeatureInput as n, type CaptionTrack as o, type CaptionWord as p, type ChartBaseFields as q, type ChartTemplateInput as r, type ColorScheme as s, type ColumnChartInput as t, type ComparisonBarInput as u, type ContentBlockInput as v, type CornerBrandingConfig as w, type CountUpSpec as x, type CreateTemplateContextOptions as y, type CustomTemplateDefinition as z };
@@ -1,4 +1,4 @@
1
- import { a3 as ImageLayer, by as TextLayer, bj as ShapeLayer, aZ as PathLayer } from './Doc-BCrrYAuK.js';
1
+ import { a3 as ImageLayer, bz as TextLayer, bk as ShapeLayer, aZ as PathLayer } from './Doc-DqYt_b2b.js';
2
2
 
3
3
  /**
4
4
  * ImageEditDoc — JSON document describing a layered, editable image.
@@ -7,6 +7,7 @@ import {
7
7
  extractPlainText,
8
8
  findBlockVideoEmbed,
9
9
  findNodesByType,
10
+ isHtmlLineBreak,
10
11
  isSvgIslandLang,
11
12
  isVideoEmbedUrl,
12
13
  matchTrailingTemplateAnnotation,
@@ -744,6 +745,7 @@ function findRailLabels(grid, boxes) {
744
745
  for (let c = Math.max(0, box.c0); c <= Math.min(W - 1, box.c1); c++) inBox[r * W + c] = 1;
745
746
  }
746
747
  }
748
+ const boxCell = maskedCell(inBox, W, H);
747
749
  const at = (r, c) => r >= 0 && r < H && c >= 0 && c < W ? grid[r][c] : " ";
748
750
  const joins = (ch) => isLineChar(ch) || isJunction(ch) || isPlus(ch) || isAnyCorner(ch);
749
751
  const vertJoins = (ch) => {
@@ -771,7 +773,7 @@ function findRailLabels(grid, boxes) {
771
773
  if (ch === " ") return false;
772
774
  if (arrowDirection(ch) !== null) return true;
773
775
  const ascii = asciiArrowDirection(ch);
774
- if (ascii !== null && asciiArrowGate(grid, r, c, ascii)) return true;
776
+ if (ascii !== null && asciiArrowGate(grid, r, c, ascii, boxCell)) return true;
775
777
  if (!isLineChar(ch)) return false;
776
778
  if (routingRow[r]) return true;
777
779
  const vert = vertJoins(at(r - 1, c)) || vertJoins(at(r + 1, c));
@@ -883,6 +885,7 @@ function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
883
885
  var _a;
884
886
  const H = grid.length;
885
887
  const W = H > 0 ? grid[0].length : 0;
888
+ const boxCell = maskedCell(mask, W, H);
886
889
  const cells = /* @__PURE__ */ new Map();
887
890
  for (let r = 0; r < H; r++) {
888
891
  for (let c = 0; c < W; c++) {
@@ -895,7 +898,7 @@ function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
895
898
  continue;
896
899
  }
897
900
  const asc = asciiArrowDirection(ch);
898
- if (asc && asciiArrowGate(grid, r, c, asc)) {
901
+ if (asc && asciiArrowGate(grid, r, c, asc, boxCell)) {
899
902
  cells.set(idx, { arrow: asc });
900
903
  continue;
901
904
  }
@@ -925,12 +928,12 @@ function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
925
928
  break;
926
929
  }
927
930
  if (isHoriz(gch)) {
928
- if (horizRunReachesStructure(grid, mask, r, g, W)) break;
931
+ if (horizRunReachesStructure(grid, mask, r, g, W, boxCell)) break;
929
932
  while (g < W && isHoriz(grid[r][g])) g++;
930
933
  sawText = true;
931
934
  continue;
932
935
  }
933
- if (isStructuralInGap(grid, r, g)) {
936
+ if (isStructuralInGap(grid, r, g, boxCell)) {
934
937
  failed = true;
935
938
  break;
936
939
  }
@@ -1259,28 +1262,38 @@ function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
1259
1262
  for (const idx of sideLabelCells) edgeCells.add(idx);
1260
1263
  return { edges, edgeCells };
1261
1264
  }
1262
- function horizRunReachesStructure(grid, mask, r, c, W) {
1265
+ function horizRunReachesStructure(grid, mask, r, c, W, isBoxCell) {
1263
1266
  let end = c;
1264
1267
  while (end < W && isHoriz(grid[r][end]) && !mask[r * W + end]) end++;
1265
1268
  if (end >= W || mask[r * W + end]) return true;
1266
1269
  const ch = grid[r][end];
1267
1270
  if (isLineChar(ch) || arrowDirection(ch) !== null) return true;
1268
1271
  const asc = asciiArrowDirection(ch);
1269
- return asc !== null && asciiArrowGate(grid, r, end, asc);
1272
+ return asc !== null && asciiArrowGate(grid, r, end, asc, isBoxCell);
1270
1273
  }
1271
- function isStructuralInGap(grid, r, c) {
1274
+ function isStructuralInGap(grid, r, c, isBoxCell) {
1272
1275
  const ch = grid[r][c];
1273
1276
  if (arrowDirection(ch) !== null) return true;
1274
1277
  const asc = asciiArrowDirection(ch);
1275
- if (asc !== null && asciiArrowGate(grid, r, c, asc)) return true;
1278
+ if (asc !== null && asciiArrowGate(grid, r, c, asc, isBoxCell)) return true;
1276
1279
  if (!isLineChar(ch)) return false;
1277
1280
  const isDrawing = (x) => x !== void 0 && (isLineChar(x) || arrowDirection(x) !== null);
1278
1281
  return isDrawing(grid[r - 1]?.[c]) || isDrawing(grid[r + 1]?.[c]);
1279
1282
  }
1280
- function asciiArrowGate(grid, r, c, dir) {
1281
- const behind = dir === "down" ? grid[r - 1]?.[c] : dir === "up" ? grid[r + 1]?.[c] : dir === "right" ? grid[r]?.[c - 1] : grid[r]?.[c + 1];
1283
+ function asciiArrowGate(grid, r, c, dir, isBoxCell) {
1284
+ const [br, bc] = dir === "down" ? [r - 1, c] : dir === "up" ? [r + 1, c] : dir === "right" ? [r, c - 1] : [r, c + 1];
1285
+ const behind = grid[br]?.[bc];
1282
1286
  if (behind === void 0) return false;
1283
- return dir === "down" || dir === "up" ? isVert(behind) : isHoriz(behind);
1287
+ if (dir === "down" || dir === "up" ? isVert(behind) : isHoriz(behind)) return true;
1288
+ if (!isBoxCell || !isPlus(behind) || isBoxCell(br, bc)) return false;
1289
+ const line = (lr, lc, test) => {
1290
+ const ch = grid[lr]?.[lc];
1291
+ return ch !== void 0 && test(ch) && !isBoxCell(lr, lc);
1292
+ };
1293
+ return line(br, bc - 1, isHoriz) || line(br, bc + 1, isHoriz) || line(br - 1, bc, isVert) || line(br + 1, bc, isVert);
1294
+ }
1295
+ function maskedCell(mask, W, H) {
1296
+ return (r, c) => r >= 0 && r < H && c >= 0 && c < W && mask[r * W + c] === 1;
1284
1297
  }
1285
1298
  function snapEndpoint(r, c, arrow, perimeterOwners, boxes, W, H) {
1286
1299
  const ownersAt = (rr, cc) => {
@@ -3207,6 +3220,7 @@ function renderInlineHtml(nodes) {
3207
3220
  case "inlineIcon":
3208
3221
  return `<i class="fa-${node.family} fa-${node.name}" aria-hidden="true"></i>`;
3209
3222
  case "htmlInline":
3223
+ if (isHtmlLineBreak(node.rawHtml)) return "<br>";
3210
3224
  return INLINE_MEDIA_TAG_RE.test(node.rawHtml.trim()) ? "" : escapeInlineHtml(node.rawHtml);
3211
3225
  }
3212
3226
  }).join("");
@@ -4021,6 +4035,7 @@ function recommendTemplatesForBlock(profile, allNames) {
4021
4035
  }
4022
4036
 
4023
4037
  export {
4038
+ matchNumberHighlight,
4024
4039
  parseAnnotationInner,
4025
4040
  parseStandaloneAnnotation,
4026
4041
  isMediaAnnotationName,
@@ -9,7 +9,7 @@ import {
9
9
  expectedSyllablesAt,
10
10
  flattenRenderableBlocks,
11
11
  wordPosAtExpectedSyllables
12
- } from "./chunk-L3VQQ3WT.js";
12
+ } from "./chunk-SKGMNBQX.js";
13
13
 
14
14
  // src/narration/types.ts
15
15
  var DEFAULT_FEATURE_CONFIG = Object.freeze({
@@ -1177,6 +1177,13 @@ function recordSlideShown(log, blockId, atMs) {
1177
1177
  const floor = log.length > 0 ? log[log.length - 1].atMs : 0;
1178
1178
  return [...log, { blockId, atMs: Math.max(atMs, floor, 0) }];
1179
1179
  }
1180
+ var EMPTY_SLIDE_MARK_LOG = Object.freeze([]);
1181
+ function recordSlideMark(log, charOffset, atMs) {
1182
+ if (!Number.isInteger(charOffset) || charOffset < 0 || !Number.isFinite(atMs)) return log;
1183
+ if (log.some((entry) => entry.charOffset === charOffset)) return log;
1184
+ const floor = log.length > 0 ? log[log.length - 1].atMs : 0;
1185
+ return [...log, { charOffset, atMs: Math.max(atMs, floor, 0) }];
1186
+ }
1180
1187
  function clampDuration(durationSec) {
1181
1188
  return Number.isFinite(durationSec) && durationSec >= 0 ? durationSec : 0;
1182
1189
  }
@@ -1231,6 +1238,12 @@ function buildAdvanceTimingJson(doc, advances, durationSec, options) {
1231
1238
  endSec: Math.max(startSec, Math.min(rawEnd, duration))
1232
1239
  });
1233
1240
  }
1241
+ let slideCursor = 0;
1242
+ const slides = (options?.slides ?? []).filter((mark) => mark.charOffset < script.sourceText.length).map((mark, index) => {
1243
+ const time = index === 0 ? 0 : Math.min(duration, Math.max(slideCursor, mark.atMs / 1e3));
1244
+ slideCursor = time;
1245
+ return { charOffset: mark.charOffset, time };
1246
+ });
1234
1247
  return {
1235
1248
  version: 3,
1236
1249
  sourceText: script.sourceText,
@@ -1240,6 +1253,7 @@ function buildAdvanceTimingJson(doc, advances, durationSec, options) {
1240
1253
  // them with block starts would misreport what was measured.
1241
1254
  bookmarks: [],
1242
1255
  blocks,
1256
+ ...slides.length ? { slides } : {},
1243
1257
  // `cameraOffsetSec` is deliberately omitted: a dual take already encodes
1244
1258
  // its skew in the camera clip's `startAt`/`clipStart` attributes, and a
1245
1259
  // second copy here invites a double correction.
@@ -1295,6 +1309,8 @@ export {
1295
1309
  alignTranscript,
1296
1310
  EMPTY_ADVANCE_LOG,
1297
1311
  recordSlideShown,
1312
+ EMPTY_SLIDE_MARK_LOG,
1313
+ recordSlideMark,
1298
1314
  buildAdvanceTimingJson,
1299
1315
  advanceCoverage
1300
1316
  };
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  parseNarrationTimingJson
3
- } from "./chunk-FTN6SGW5.js";
3
+ } from "./chunk-HKHOFTGM.js";
4
4
  import {
5
5
  applySavedPresentation
6
- } from "./chunk-VMKRN7TB.js";
6
+ } from "./chunk-N7I6JP6Q.js";
7
7
  import {
8
8
  SHAPE_NAMES,
9
9
  buildChartData,
@@ -31,7 +31,7 @@ import {
31
31
  templateRegistry,
32
32
  writeCustomTemplatesToFrontmatter,
33
33
  writeCustomThemesToFrontmatter
34
- } from "./chunk-L3VQQ3WT.js";
34
+ } from "./chunk-SKGMNBQX.js";
35
35
  import {
36
36
  ASCII_TREE_VOCAB,
37
37
  ASCII_VOCAB,
@@ -54,7 +54,7 @@ import {
54
54
  toCells,
55
55
  toGrid,
56
56
  traceBoxes
57
- } from "./chunk-R2J7CQJZ.js";
57
+ } from "./chunk-3WUI2N6C.js";
58
58
  import {
59
59
  iconMarker
60
60
  } from "./chunk-7ZAAICW4.js";
@@ -967,13 +967,23 @@ function getTemplateDefaults(templateName, headingText, block) {
967
967
  return {};
968
968
  }
969
969
  }
970
- function blockToSlide(block, index, knownTemplates, documentTitle) {
971
- const headingText = block.sourceHeading ? extractPlainText(block.sourceHeading) : block.title || documentTitle || "";
970
+ function slideTemplate(block, knownTemplates) {
972
971
  const implicitSectionHeader = block.template === "sectionHeader" && block.autoTemplate !== true && !!block.sourceHeading && !block.sourceHeading.templateAnnotation?.template;
973
972
  const requestedTemplate = implicitSectionHeader ? "content" : block.template ?? "content";
974
- const isCustomTemplate = knownTemplates?.has(requestedTemplate) ?? false;
975
- const recognized = hasTemplate(requestedTemplate) || isCustomTemplate;
976
- const template = recognized ? requestedTemplate : "sectionHeader";
973
+ const recognized = hasTemplate(requestedTemplate) || !!knownTemplates?.has(requestedTemplate);
974
+ return recognized ? requestedTemplate : "sectionHeader";
975
+ }
976
+ function previewBlockTemplate(block, doc) {
977
+ const template = slideTemplate(
978
+ block,
979
+ doc?.customTemplates && new Set(doc.customTemplates.map((custom) => custom.name))
980
+ );
981
+ return template === "sectionHeader" && !block.summaryMode && extractBlockImages(block.contents).length > 0 ? "imageWithCaption" : template;
982
+ }
983
+ function blockToSlide(block, index, knownTemplates, documentTitle) {
984
+ const headingText = block.sourceHeading ? extractPlainText(block.sourceHeading) : block.title || documentTitle || "";
985
+ const template = slideTemplate(block, knownTemplates);
986
+ const isCustomTemplate = knownTemplates?.has(template) ?? false;
977
987
  const defaults = getTemplateDefaults(template, headingText, block);
978
988
  const templateOverrides = omitStringBlockMeta(block.templateOverrides);
979
989
  const coercedTemplateOverrides = templateOverrides ? coerceTemplateParams(template, templateOverrides).input : void 0;
@@ -4302,6 +4312,103 @@ function materializeFlashcards(doc, options = {}) {
4302
4312
  };
4303
4313
  }
4304
4314
 
4315
+ // src/narration/reanchor.ts
4316
+ var MIN_SHARED_WORDS = 0.9;
4317
+ var MAX_WORD_EDITS = 500;
4318
+ function words(text) {
4319
+ const found = [];
4320
+ const tokenRe = /\S+/g;
4321
+ let match;
4322
+ while ((match = tokenRe.exec(text)) !== null) {
4323
+ found.push({ text: match[0], start: match.index, end: match.index + match[0].length });
4324
+ }
4325
+ return found;
4326
+ }
4327
+ function sharedWords(a, b, maxEdits) {
4328
+ const n = a.length;
4329
+ const m = b.length;
4330
+ const max = Math.min(n + m, maxEdits);
4331
+ const mid = max + 1;
4332
+ const v = new Int32Array(2 * max + 3);
4333
+ const trace = [];
4334
+ for (let d = 0; d <= max; d++) {
4335
+ trace.push(v.slice(mid - d - 1, mid + d + 2));
4336
+ for (let k = -d; k <= d; k += 2) {
4337
+ let x = k === -d || k !== d && v[mid + k - 1] < v[mid + k + 1] ? v[mid + k + 1] : v[mid + k - 1] + 1;
4338
+ let y = x - k;
4339
+ while (x < n && y < m && a[x] === b[y]) {
4340
+ x++;
4341
+ y++;
4342
+ }
4343
+ v[mid + k] = x;
4344
+ if (x >= n && y >= m) return walkBack(trace, n, m);
4345
+ }
4346
+ }
4347
+ return null;
4348
+ }
4349
+ function walkBack(trace, n, m) {
4350
+ const pairs = [];
4351
+ let x = n;
4352
+ let y = m;
4353
+ for (let d = trace.length - 1; d >= 0; d--) {
4354
+ const row = trace[d];
4355
+ const at = (k2) => row[k2 + d + 1];
4356
+ const k = x - y;
4357
+ const previous = k === -d || k !== d && at(k - 1) < at(k + 1) ? k + 1 : k - 1;
4358
+ const previousX = at(previous);
4359
+ const previousY = previousX - previous;
4360
+ while (x > previousX && y > previousY) {
4361
+ x--;
4362
+ y--;
4363
+ pairs.push([x, y]);
4364
+ }
4365
+ x = previousX;
4366
+ y = previousY;
4367
+ }
4368
+ return pairs.reverse();
4369
+ }
4370
+ function reanchorNarrationText(recorded, current) {
4371
+ if (recorded === current) return (offset) => offset;
4372
+ const from = words(recorded);
4373
+ const to = words(current);
4374
+ if (!from.length || !to.length) return null;
4375
+ const budget = Math.min(
4376
+ MAX_WORD_EDITS,
4377
+ Math.ceil((1 - MIN_SHARED_WORDS) * (from.length + to.length))
4378
+ );
4379
+ const fromText = from.map((word) => word.text);
4380
+ const toText = to.map((word) => word.text);
4381
+ let head = 0;
4382
+ while (head < from.length && head < to.length && fromText[head] === toText[head]) head++;
4383
+ let tail = 0;
4384
+ while (tail < from.length - head && tail < to.length - head && fromText[from.length - 1 - tail] === toText[to.length - 1 - tail])
4385
+ tail++;
4386
+ const middle = sharedWords(
4387
+ fromText.slice(head, from.length - tail),
4388
+ toText.slice(head, to.length - tail),
4389
+ budget
4390
+ );
4391
+ if (!middle) return null;
4392
+ const shared = head + middle.length + tail;
4393
+ if (shared < MIN_SHARED_WORDS * from.length || shared < MIN_SHARED_WORDS * to.length) return null;
4394
+ const target = new Int32Array(from.length).fill(-1);
4395
+ for (let i = 0; i < head; i++) target[i] = i;
4396
+ for (const [i, j] of middle) target[head + i] = head + j;
4397
+ for (let i = 1; i <= tail; i++) target[from.length - i] = to.length - i;
4398
+ return (offset) => {
4399
+ let low = 0;
4400
+ let high = from.length;
4401
+ while (low < high) {
4402
+ const probe = low + high >> 1;
4403
+ if (from[probe].end <= offset) low = probe + 1;
4404
+ else high = probe;
4405
+ }
4406
+ const j = low < from.length ? target[low] : -1;
4407
+ if (j < 0) return void 0;
4408
+ return to[j].start + Math.max(0, offset - from[low].start);
4409
+ };
4410
+ }
4411
+
4305
4412
  // src/doc/applyNarrationTiming.ts
4306
4413
  var MIN_BLOCK_SIMILARITY = 0.5;
4307
4414
  var MIN_V1_SCRIPT_SIMILARITY = 0.8;
@@ -4482,12 +4589,15 @@ async function applyNarrationTiming(doc, container) {
4482
4589
  const blocks = retimeBlocks(doc.blocks, ctx);
4483
4590
  const duration = Math.max(clip.startAt + playedDuration, ctx.cursor);
4484
4591
  const captions = narrationCaptions(doc, clip, timing, timeMap, playedDuration);
4592
+ const currentText = buildNarrationScript(doc).sourceText;
4593
+ const reanchor = reanchorNarrationText(timing.sourceText, currentText);
4594
+ const mapOffset = reanchor ?? ((offset) => offset);
4485
4595
  const retimed = {
4486
4596
  ...doc,
4487
4597
  blocks,
4488
4598
  duration,
4489
4599
  presentationNarration: {
4490
- sourceText: timing.sourceText,
4600
+ sourceText: reanchor ? currentText : timing.sourceText,
4491
4601
  src: clip.src,
4492
4602
  startTime: clip.startAt,
4493
4603
  duration: playedDuration,
@@ -4495,9 +4605,16 @@ async function applyNarrationTiming(doc, container) {
4495
4605
  const time = timeMap ? timeMap.snapSourceToPlayed(event.time) : event.time;
4496
4606
  return time >= 0 && time <= playedDuration ? [{ ...event, time: clip.startAt + time }] : [];
4497
4607
  }),
4608
+ // A slide shown inside a trimmed span appears where playback resumes.
4609
+ slides: timing.slides?.flatMap((mark) => {
4610
+ const time = timeMap ? timeMap.snapSourceToPlayed(mark.time) : mark.time;
4611
+ const charOffset = mapOffset(mark.charOffset);
4612
+ return charOffset !== void 0 && time >= 0 && time <= playedDuration ? [{ charOffset, time: clip.startAt + time }] : [];
4613
+ }),
4498
4614
  bookmarks: timing.bookmarks.flatMap((bookmark) => {
4499
4615
  const time = timeMap ? timeMap.sourceToPlayed(bookmark.time) : bookmark.time;
4500
- return time !== null && time >= 0 && time <= playedDuration ? [{ ...bookmark, time: clip.startAt + time }] : [];
4616
+ const charOffset = mapOffset(bookmark.charOffset);
4617
+ return charOffset !== void 0 && time !== null && time >= 0 && time <= playedDuration ? [{ ...bookmark, charOffset, time: clip.startAt + time }] : [];
4501
4618
  })
4502
4619
  },
4503
4620
  ...captions ? { captions } : {},
@@ -4526,8 +4643,8 @@ function parseTimingJson(data) {
4526
4643
  }
4527
4644
  }
4528
4645
  function normalizeToWords(text) {
4529
- const words = text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 2);
4530
- return new Set(words);
4646
+ const words2 = text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 2);
4647
+ return new Set(words2);
4531
4648
  }
4532
4649
  function scoreTextSimilarity(a, b) {
4533
4650
  const wordsA = normalizeToWords(a);
@@ -6802,6 +6919,7 @@ export {
6802
6919
  MAX_COVER_SLIDE_DURATION_SECONDS,
6803
6920
  resolveCoverSlideSettings,
6804
6921
  docToMarkdown,
6922
+ previewBlockTemplate,
6805
6923
  documentTitleFromFileName,
6806
6924
  buildPreviewDoc,
6807
6925
  resolveThemeForDoc,
@@ -111,8 +111,18 @@ function parseNarrationTimingJson(data) {
111
111
  });
112
112
  }
113
113
  }
114
+ const slides = [];
115
+ if (Array.isArray(raw.slides))
116
+ for (const item of raw.slides) {
117
+ if (!item || typeof item !== "object") continue;
118
+ const mark = item;
119
+ if (Number.isInteger(mark.charOffset) && finiteNonNegative(mark.charOffset) && mark.charOffset < raw.sourceText.length && finiteNonNegative(mark.time) && mark.time <= raw.duration && !slides.some((slide) => slide.charOffset === mark.charOffset))
120
+ slides.push({ charOffset: mark.charOffset, time: mark.time });
121
+ }
122
+ slides.sort((a, b) => a.time - b.time);
114
123
  return {
115
124
  ...builds.length ? { builds } : {},
125
+ ...slides.length ? { slides } : {},
116
126
  version: 3,
117
127
  sourceText: raw.sourceText,
118
128
  duration: raw.duration,