@bendyline/squisq 2.11.4 → 2.11.6

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 (34) hide show
  1. package/dist/chunk-44BJ42GT.js +165 -0
  2. package/dist/chunk-764WHWKM.js +332 -0
  3. package/dist/{chunk-XV4SF2N5.js → chunk-BUJ5RV2P.js} +1 -1
  4. package/dist/{chunk-PJRVODWW.js → chunk-C3NAY5YP.js} +7 -2
  5. package/dist/{chunk-67L6WRJN.js → chunk-GHOPHGOK.js} +28 -1
  6. package/dist/{chunk-NV7LNKS2.js → chunk-GRGLZF4A.js} +18 -30
  7. package/dist/{chunk-ZSU5DJLX.js → chunk-J2IPSQKP.js} +104 -4
  8. package/dist/{chunk-NKNMGIIN.js → chunk-SVN7T6BK.js} +0 -3
  9. package/dist/{chunk-4UNTPQ4J.js → chunk-UUI35INI.js} +4 -2
  10. package/dist/{chunk-DQRELU4S.js → chunk-VU4T74LI.js} +1 -1
  11. package/dist/{chunk-LI547QHN.js → chunk-WAGJK36Q.js} +19 -346
  12. package/dist/{chunk-RXYKU6EX.js → chunk-Y4D6TDZT.js} +212 -3
  13. package/dist/chunk-ZP5F7LUH.js +223 -0
  14. package/dist/doc/index.js +9 -11
  15. package/dist/generate/index.d.ts +61 -1
  16. package/dist/generate/index.js +14 -1
  17. package/dist/index.d.ts +5 -4
  18. package/dist/index.js +57 -39
  19. package/dist/jsonForm/index.js +3 -4
  20. package/dist/narration/index.js +6 -7
  21. package/dist/proof/index.d.ts +3 -45
  22. package/dist/recommend/index.d.ts +6 -0
  23. package/dist/recommend/index.js +1 -1
  24. package/dist/review/index.d.ts +141 -0
  25. package/dist/review/index.js +29 -0
  26. package/dist/schemas/index.js +17 -19
  27. package/dist/timing/index.d.ts +29 -1
  28. package/dist/timing/index.js +6 -4
  29. package/dist/transform/index.d.ts +63 -2
  30. package/dist/transform/index.js +17 -6
  31. package/dist/types-BQWu0gzi.d.ts +46 -0
  32. package/package.json +6 -1
  33. package/dist/chunk-BAOV476U.js +0 -214
  34. package/dist/chunk-XOFT65EX.js +0 -34
@@ -1,10 +1,156 @@
1
- import {
2
- cloneAndFreezeData
3
- } from "./chunk-BAOV476U.js";
4
1
  import {
5
2
  isTransitionType
6
3
  } from "./chunk-4VOD55SX.js";
7
4
 
5
+ // src/schemas/Viewport.ts
6
+ var VIEWPORT_PRESETS = {
7
+ /** 16:9 landscape (default, 1080p) */
8
+ landscape: { width: 1920, height: 1080, name: "16:9 Landscape" },
9
+ /** 9:16 portrait (vertical video, stories) */
10
+ portrait: { width: 1080, height: 1920, name: "9:16 Portrait" },
11
+ /** 1:1 square (social media) */
12
+ square: { width: 1080, height: 1080, name: "1:1 Square" },
13
+ /** 4:3 standard */
14
+ standard: { width: 1440, height: 1080, name: "4:3 Standard" }
15
+ };
16
+ function getViewport(viewport) {
17
+ if (typeof viewport === "string") {
18
+ return VIEWPORT_PRESETS[viewport];
19
+ }
20
+ return viewport;
21
+ }
22
+ var REFERENCE_DIAGONAL = Math.sqrt(1920 * 1920 + 1080 * 1080);
23
+ function calculateFontScale(viewport) {
24
+ const currentDiagonal = Math.sqrt(
25
+ viewport.width * viewport.width + viewport.height * viewport.height
26
+ );
27
+ return currentDiagonal / REFERENCE_DIAGONAL;
28
+ }
29
+ function getViewportOrientation(viewport) {
30
+ const ratio = viewport.width / viewport.height;
31
+ if (Math.abs(ratio - 1) < 0.05) return "square";
32
+ return ratio > 1 ? "landscape" : "portrait";
33
+ }
34
+ function getAspectRatioString(viewport) {
35
+ const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
36
+ const divisor = gcd(viewport.width, viewport.height);
37
+ return `${viewport.width / divisor}:${viewport.height / divisor}`;
38
+ }
39
+
40
+ // src/schemas/LayoutStrategy.ts
41
+ var LAYOUT_CONFIGS = {
42
+ landscape: {
43
+ primaryY: "35%",
44
+ secondaryY: "55%",
45
+ tertiaryY: "75%",
46
+ titleScale: 1,
47
+ bodyScale: 1,
48
+ columnLeftX: "25%",
49
+ columnRightX: "75%",
50
+ columnTopY: "35%",
51
+ columnBottomY: "65%",
52
+ stackColumns: false,
53
+ maxTextWidth: "80%",
54
+ horizontalPadding: "10%",
55
+ captionY: "85%",
56
+ captionScale: 1
57
+ },
58
+ portrait: {
59
+ // Content positioned higher for thumb-reach zone on mobile
60
+ primaryY: "25%",
61
+ secondaryY: "42%",
62
+ tertiaryY: "58%",
63
+ // Titles scale down for narrower width; body text scales up to fill vertical space
64
+ titleScale: 0.7,
65
+ bodyScale: 1.5,
66
+ // Stacked columns instead of side-by-side
67
+ columnLeftX: "50%",
68
+ columnRightX: "50%",
69
+ columnTopY: "30%",
70
+ columnBottomY: "55%",
71
+ stackColumns: true,
72
+ // Wider relative to viewport to use available space
73
+ maxTextWidth: "90%",
74
+ horizontalPadding: "5%",
75
+ captionY: "75%",
76
+ captionScale: 0.85
77
+ },
78
+ square: {
79
+ primaryY: "30%",
80
+ secondaryY: "50%",
81
+ tertiaryY: "70%",
82
+ titleScale: 0.85,
83
+ bodyScale: 0.9,
84
+ columnLeftX: "25%",
85
+ columnRightX: "75%",
86
+ columnTopY: "35%",
87
+ columnBottomY: "65%",
88
+ stackColumns: false,
89
+ maxTextWidth: "85%",
90
+ horizontalPadding: "7.5%",
91
+ captionY: "82%",
92
+ captionScale: 0.9
93
+ }
94
+ };
95
+ function getLayoutHints(orientation) {
96
+ return LAYOUT_CONFIGS[orientation];
97
+ }
98
+ function scaledFontSize(basePx, viewport, orientation, isTitle = false) {
99
+ const fontScale = calculateFontScale(viewport);
100
+ const layout = getLayoutHints(orientation);
101
+ const typeScale = isTitle ? layout.titleScale : layout.bodyScale;
102
+ return Math.round(basePx * fontScale * typeScale);
103
+ }
104
+ function getTwoColumnPositions(orientation) {
105
+ const layout = getLayoutHints(orientation);
106
+ if (layout.stackColumns) {
107
+ return {
108
+ left: { x: "50%", y: layout.columnTopY },
109
+ right: { x: "50%", y: layout.columnBottomY }
110
+ };
111
+ }
112
+ return {
113
+ left: { x: layout.columnLeftX, y: "50%" },
114
+ right: { x: layout.columnRightX, y: "50%" }
115
+ };
116
+ }
117
+ function getSafeTextBounds(orientation) {
118
+ const layout = getLayoutHints(orientation);
119
+ return {
120
+ left: layout.horizontalPadding,
121
+ right: layout.horizontalPadding,
122
+ top: "10%",
123
+ bottom: "10%"
124
+ };
125
+ }
126
+
127
+ // src/schemas/BlockTemplates.ts
128
+ var DEFAULT_DOC_FONT = 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
129
+ var DEFAULT_TITLE_FONT = 'Georgia, "Times New Roman", serif';
130
+ function isTemplateBlock(block) {
131
+ return "template" in block && typeof block.template === "string";
132
+ }
133
+ function createTemplateContext(theme, blockIndex, totalBlocks, viewport = VIEWPORT_PRESETS.landscape) {
134
+ const orientation = getViewportOrientation(viewport);
135
+ const overrides = theme.renderStyle.layoutOverrides;
136
+ const baseLayout = getLayoutHints(orientation);
137
+ return {
138
+ theme,
139
+ blockIndex,
140
+ totalBlocks,
141
+ viewport,
142
+ fontScale: calculateFontScale(viewport),
143
+ orientation,
144
+ layout: overrides ? { ...baseLayout, ...overrides } : baseLayout
145
+ };
146
+ }
147
+ function scaledFontSize2(basePx, context, isTitle = false) {
148
+ return scaledFontSize(basePx, context.viewport, context.orientation, isTitle);
149
+ }
150
+ function isPersistentLayerTemplate(layer) {
151
+ return "template" in layer && typeof layer.template === "string";
152
+ }
153
+
8
154
  // src/schemas/CustomTemplates.ts
9
155
  var LAYER_TYPES = /* @__PURE__ */ new Set([
10
156
  "image",
@@ -1177,6 +1323,52 @@ ${summary}${more}`);
1177
1323
  return result.theme;
1178
1324
  }
1179
1325
 
1326
+ // src/internal/immutable.ts
1327
+ function cloneData(value, seen = /* @__PURE__ */ new WeakMap()) {
1328
+ if (value === null || typeof value !== "object") return value;
1329
+ const existing = seen.get(value);
1330
+ if (existing !== void 0) return existing;
1331
+ const tag = Object.prototype.toString.call(value);
1332
+ if (tag === "[object ArrayBuffer]") {
1333
+ const source2 = new Uint8Array(value);
1334
+ const copy2 = new Uint8Array(source2.byteLength);
1335
+ copy2.set(source2);
1336
+ return copy2.buffer;
1337
+ }
1338
+ if (tag === "[object Date]") {
1339
+ return new Date(Date.prototype.getTime.call(value));
1340
+ }
1341
+ if (Array.isArray(value)) {
1342
+ const copy2 = [];
1343
+ seen.set(value, copy2);
1344
+ for (const item of value) copy2.push(cloneData(item, seen));
1345
+ return copy2;
1346
+ }
1347
+ const source = value;
1348
+ const copy = {};
1349
+ seen.set(value, copy);
1350
+ for (const key of Object.keys(source)) {
1351
+ Object.defineProperty(copy, key, {
1352
+ value: cloneData(source[key], seen),
1353
+ enumerable: true,
1354
+ configurable: true,
1355
+ writable: true
1356
+ });
1357
+ }
1358
+ return copy;
1359
+ }
1360
+ function deepFreezeData(value, seen = /* @__PURE__ */ new WeakSet()) {
1361
+ if (value === null || typeof value !== "object" || seen.has(value)) return value;
1362
+ seen.add(value);
1363
+ for (const key of Object.keys(value)) {
1364
+ deepFreezeData(value[key], seen);
1365
+ }
1366
+ return Object.freeze(value);
1367
+ }
1368
+ function cloneAndFreezeData(value) {
1369
+ return deepFreezeData(cloneData(value));
1370
+ }
1371
+
1180
1372
  // src/schemas/Theme.ts
1181
1373
  var FRONTMATTER_CUSTOM_THEMES_KEY = "squisq-custom-themes";
1182
1374
  function deepMerge(target, source) {
@@ -2772,6 +2964,21 @@ function matchFontFamily(name) {
2772
2964
  }
2773
2965
 
2774
2966
  export {
2967
+ VIEWPORT_PRESETS,
2968
+ getViewport,
2969
+ calculateFontScale,
2970
+ getViewportOrientation,
2971
+ getAspectRatioString,
2972
+ getLayoutHints,
2973
+ scaledFontSize,
2974
+ getTwoColumnPositions,
2975
+ getSafeTextBounds,
2976
+ DEFAULT_DOC_FONT,
2977
+ DEFAULT_TITLE_FONT,
2978
+ isTemplateBlock,
2979
+ createTemplateContext,
2980
+ scaledFontSize2,
2981
+ isPersistentLayerTemplate,
2775
2982
  validateCustomTemplateDefinition,
2776
2983
  isCustomTemplateDefinition,
2777
2984
  FRONTMATTER_CUSTOM_TEMPLATES_KEY,
@@ -2806,6 +3013,8 @@ export {
2806
3013
  PAGE_ACCENT_STRATEGIES,
2807
3014
  validateTheme,
2808
3015
  assertTheme,
3016
+ cloneData,
3017
+ cloneAndFreezeData,
2809
3018
  FRONTMATTER_CUSTOM_THEMES_KEY,
2810
3019
  createTheme,
2811
3020
  LIGHT_SURFACE,
@@ -0,0 +1,223 @@
1
+ import {
2
+ SeededRandom
3
+ } from "./chunk-XRW6P7IF.js";
4
+
5
+ // src/generate/mediaMatching.ts
6
+ var DEFAULT_STOPWORDS = /* @__PURE__ */ new Set([
7
+ "a",
8
+ "an",
9
+ "and",
10
+ "are",
11
+ "as",
12
+ "at",
13
+ "be",
14
+ "been",
15
+ "being",
16
+ "but",
17
+ "by",
18
+ "can",
19
+ "could",
20
+ "did",
21
+ "do",
22
+ "does",
23
+ "each",
24
+ "for",
25
+ "from",
26
+ "had",
27
+ "has",
28
+ "have",
29
+ "he",
30
+ "how",
31
+ "if",
32
+ "in",
33
+ "into",
34
+ "is",
35
+ "it",
36
+ "its",
37
+ "more",
38
+ "most",
39
+ "of",
40
+ "on",
41
+ "or",
42
+ "other",
43
+ "our",
44
+ "should",
45
+ "some",
46
+ "such",
47
+ "than",
48
+ "that",
49
+ "the",
50
+ "their",
51
+ "them",
52
+ "then",
53
+ "there",
54
+ "these",
55
+ "they",
56
+ "this",
57
+ "those",
58
+ "through",
59
+ "to",
60
+ "under",
61
+ "until",
62
+ "was",
63
+ "we",
64
+ "were",
65
+ "when",
66
+ "where",
67
+ "which",
68
+ "while",
69
+ "who",
70
+ "why",
71
+ "will",
72
+ "with",
73
+ "would",
74
+ "you",
75
+ "your"
76
+ ]);
77
+ function extractKeywords(text, options = {}) {
78
+ if (!text) return [];
79
+ const stopwords = new Set(DEFAULT_STOPWORDS);
80
+ for (const word of options.stopwords ?? []) stopwords.add(word.toLowerCase());
81
+ const minimum = options.minWordLength ?? 3;
82
+ const words = text.toLowerCase().replace(/[.,;:!?\u2018\u2019'"()[\]{}\u2014\u2013-]/g, " ").replace(/\s+/g, " ").trim().split(" ").filter(Boolean);
83
+ const result = /* @__PURE__ */ new Set();
84
+ const eligible = (word) => word.length >= minimum && !stopwords.has(word);
85
+ for (const word of words) if (eligible(word)) result.add(word);
86
+ if (options.includeBigrams ?? true) {
87
+ for (let index = 0; index < words.length - 1; index += 1) {
88
+ if (eligible(words[index]) && eligible(words[index + 1])) {
89
+ result.add(`${words[index]}_${words[index + 1]}`);
90
+ }
91
+ }
92
+ }
93
+ return [...result];
94
+ }
95
+ function calculateKeywordAffinity(first, second) {
96
+ if (first.length === 0 || second.length === 0) return 0;
97
+ const firstSet = new Set(first);
98
+ const secondSet = new Set(second);
99
+ let overlap = 0;
100
+ for (const keyword of firstSet) {
101
+ if (secondSet.has(keyword)) overlap += keyword.includes("_") ? 2 : 1;
102
+ }
103
+ return Math.min(1, overlap / Math.min(firstSet.size, secondSet.size));
104
+ }
105
+ function matchByKeywordAffinity(mediaKeywords, targets, minimumScore = 0) {
106
+ const candidates = [];
107
+ for (let mediaIndex = 0; mediaIndex < mediaKeywords.length; mediaIndex += 1) {
108
+ for (const target of targets) {
109
+ const score = calculateKeywordAffinity(mediaKeywords[mediaIndex], target.keywords);
110
+ if (score >= minimumScore && score > 0)
111
+ candidates.push({ mediaIndex, targetKey: target.key, score });
112
+ }
113
+ }
114
+ candidates.sort((left, right) => right.score - left.score || left.mediaIndex - right.mediaIndex);
115
+ const assignments = [];
116
+ const assignedMedia = /* @__PURE__ */ new Set();
117
+ const targetCounts = /* @__PURE__ */ new Map();
118
+ for (const candidate of candidates) {
119
+ if (assignedMedia.has(candidate.mediaIndex)) continue;
120
+ const target = targets.find((item) => item.key === candidate.targetKey);
121
+ const capacity = target?.capacity ?? 1;
122
+ if ((targetCounts.get(candidate.targetKey) ?? 0) >= capacity) continue;
123
+ assignments.push(candidate);
124
+ assignedMedia.add(candidate.mediaIndex);
125
+ targetCounts.set(candidate.targetKey, (targetCounts.get(candidate.targetKey) ?? 0) + 1);
126
+ }
127
+ return {
128
+ assignments,
129
+ unmatchedMedia: mediaKeywords.map((_, index) => index).filter((index) => !assignedMedia.has(index))
130
+ };
131
+ }
132
+ var CLIP_DEFAULTS = {
133
+ clipCount: 3,
134
+ minClipDuration: 8,
135
+ maxClipDuration: 20,
136
+ introSkipFraction: 0.1,
137
+ outroSkipFraction: 0.1,
138
+ seed: 42
139
+ };
140
+ function selectSafeZoneClips(source, options = {}) {
141
+ const settings = { ...CLIP_DEFAULTS, ...options };
142
+ if (source.duration <= 0 || settings.clipCount <= 0) return [];
143
+ const safeStart = source.duration * settings.introSkipFraction;
144
+ const safeEnd = source.duration * (1 - settings.outroSkipFraction);
145
+ const safeDuration = safeEnd - safeStart;
146
+ if (safeDuration < settings.minClipDuration) {
147
+ return [toClip(source, 0, Math.min(source.duration, settings.maxClipDuration))];
148
+ }
149
+ const count = Math.min(settings.clipCount, Math.floor(safeDuration / settings.minClipDuration));
150
+ const random = new SeededRandom(settings.seed);
151
+ const interval = safeDuration / count;
152
+ return Array.from({ length: count }, (_, index) => {
153
+ const intervalStart = safeStart + index * interval;
154
+ const intervalEnd = intervalStart + interval;
155
+ const requestedDuration = settings.minClipDuration + random.next() * (settings.maxClipDuration - settings.minClipDuration);
156
+ const clipDuration = Math.min(requestedDuration, interval, safeDuration);
157
+ const jitter = (random.next() - 0.5) * interval * 0.5;
158
+ const center = Math.max(
159
+ intervalStart + clipDuration / 2,
160
+ Math.min(intervalEnd - clipDuration / 2, (intervalStart + intervalEnd) / 2 + jitter)
161
+ );
162
+ const start = Math.max(safeStart, center - clipDuration / 2);
163
+ return toClip(source, start, Math.min(safeEnd, start + clipDuration));
164
+ });
165
+ }
166
+ function selectTranscriptClips(source, transcript, matchText, options = {}) {
167
+ const settings = { ...CLIP_DEFAULTS, ...options };
168
+ const safeStart = source.duration * settings.introSkipFraction;
169
+ const safeEnd = source.duration * (1 - settings.outroSkipFraction);
170
+ const matchKeywords = extractKeywords(matchText);
171
+ const ranked = transcript.filter((segment) => segment.startTime >= safeStart && segment.endTime <= safeEnd).map((segment) => ({
172
+ segment,
173
+ score: calculateKeywordAffinity(
174
+ matchKeywords,
175
+ segment.keywords ?? extractKeywords(segment.text)
176
+ )
177
+ })).filter(({ score }) => score > 0).sort((left, right) => right.score - left.score);
178
+ const selected = [];
179
+ for (const { segment } of ranked) {
180
+ if (selected.length >= settings.clipCount) break;
181
+ const center = (segment.startTime + segment.endTime) / 2;
182
+ if (selected.every(
183
+ (item) => Math.abs((item.startTime + item.endTime) / 2 - center) >= settings.minClipDuration
184
+ )) {
185
+ selected.push(segment);
186
+ }
187
+ }
188
+ const clips = selected.map((segment) => {
189
+ const center = (segment.startTime + segment.endTime) / 2;
190
+ const duration = Math.min(
191
+ settings.maxClipDuration,
192
+ Math.max(settings.minClipDuration, segment.endTime - segment.startTime + 4)
193
+ );
194
+ const start = Math.max(safeStart, center - duration / 2);
195
+ return toClip(source, start, Math.min(safeEnd, start + duration));
196
+ });
197
+ if (clips.length < settings.clipCount) {
198
+ clips.push(
199
+ ...selectSafeZoneClips(source, {
200
+ ...settings,
201
+ clipCount: settings.clipCount - clips.length,
202
+ seed: settings.seed + clips.length
203
+ })
204
+ );
205
+ }
206
+ return clips;
207
+ }
208
+ function toClip(source, start, end) {
209
+ return {
210
+ ...source,
211
+ clipStart: Math.round(start * 100) / 100,
212
+ clipEnd: Math.round(end * 100) / 100,
213
+ sourceDuration: source.duration
214
+ };
215
+ }
216
+
217
+ export {
218
+ extractKeywords,
219
+ calculateKeywordAffinity,
220
+ matchByKeywordAffinity,
221
+ selectSafeZoneClips,
222
+ selectTranscriptClips
223
+ };
package/dist/doc/index.js CHANGED
@@ -70,7 +70,8 @@ import {
70
70
  validateMarkdownDoc,
71
71
  validateMarkdownSource,
72
72
  writeDashboardLayoutsToFrontmatter
73
- } from "../chunk-NV7LNKS2.js";
73
+ } from "../chunk-GRGLZF4A.js";
74
+ import "../chunk-764WHWKM.js";
74
75
  import {
75
76
  ASCII_CHAR_H,
76
77
  ASCII_CHAR_W,
@@ -192,7 +193,7 @@ import {
192
193
  wrapWithPersistentLayers,
193
194
  writeCustomTemplatesToFrontmatter,
194
195
  writeCustomThemesToFrontmatter
195
- } from "../chunk-LI547QHN.js";
196
+ } from "../chunk-WAGJK36Q.js";
196
197
  import {
197
198
  PATH_SHAPE_KINDS,
198
199
  anchorPoint,
@@ -229,26 +230,24 @@ import {
229
230
  parseAsciiTimelineWithStats,
230
231
  parseTree,
231
232
  parseWrappedFlowTimeline
232
- } from "../chunk-PJRVODWW.js";
233
+ } from "../chunk-C3NAY5YP.js";
233
234
  import "../chunk-GAZKTT4R.js";
234
235
  import {
235
236
  DEFAULT_THEME,
236
237
  FRONTMATTER_CUSTOM_TEMPLATES_KEY,
237
238
  FRONTMATTER_CUSTOM_THEMES_KEY,
238
- getAvailableThemes,
239
- getThemeSummaries,
240
- resolveTheme
241
- } from "../chunk-RXYKU6EX.js";
242
- import {
243
239
  VIEWPORT_PRESETS,
244
240
  createTemplateContext,
241
+ getAvailableThemes,
245
242
  getLayoutHints,
243
+ getThemeSummaries,
246
244
  getTwoColumnPositions,
247
245
  getViewport,
248
246
  getViewportOrientation,
249
247
  isTemplateBlock,
248
+ resolveTheme,
250
249
  scaledFontSize2 as scaledFontSize
251
- } from "../chunk-BAOV476U.js";
250
+ } from "../chunk-Y4D6TDZT.js";
252
251
  import "../chunk-CW24CH7I.js";
253
252
  import {
254
253
  CONTAINER_TEMPLATES,
@@ -259,8 +258,7 @@ import {
259
258
  import "../chunk-7N4G32LG.js";
260
259
  import "../chunk-X7BNDUNI.js";
261
260
  import "../chunk-4VOD55SX.js";
262
- import "../chunk-XOFT65EX.js";
263
- import "../chunk-67L6WRJN.js";
261
+ import "../chunk-GHOPHGOK.js";
264
262
  import "../chunk-XRW6P7IF.js";
265
263
  export {
266
264
  ASCII_CHAR_H,
@@ -30,4 +30,64 @@ interface MapOptions {
30
30
  */
31
31
  declare function mapElementToBlock(element: ExtractedElement, options: MapOptions): TemplateBlock;
32
32
 
33
- export { ExtractedElement, type MapOptions, mapElementToBlock };
33
+ /**
34
+ * Generic Media Matching and Clip Selection
35
+ *
36
+ * Provides domain-neutral keyword affinity, greedy section matching, and
37
+ * safe-zone/transcript-aware video clip selection. Host applications supply
38
+ * their own editorial metadata and policy before or after these primitives.
39
+ */
40
+ interface KeywordExtractionOptions {
41
+ stopwords?: Iterable<string>;
42
+ minWordLength?: number;
43
+ includeBigrams?: boolean;
44
+ }
45
+ declare function extractKeywords(text: string, options?: KeywordExtractionOptions): string[];
46
+ declare function calculateKeywordAffinity(first: readonly string[], second: readonly string[]): number;
47
+ interface AffinityTarget<Key extends string = string> {
48
+ key: Key;
49
+ keywords: readonly string[];
50
+ capacity?: number;
51
+ }
52
+ interface AffinityAssignment<Key extends string = string> {
53
+ mediaIndex: number;
54
+ targetKey: Key;
55
+ score: number;
56
+ }
57
+ interface AffinityMatchResult<Key extends string = string> {
58
+ assignments: AffinityAssignment<Key>[];
59
+ unmatchedMedia: number[];
60
+ }
61
+ /** Greedily assign each media item once to the highest-affinity target. */
62
+ declare function matchByKeywordAffinity<Key extends string = string>(mediaKeywords: ReadonlyArray<readonly string[]>, targets: ReadonlyArray<AffinityTarget<Key>>, minimumScore?: number): AffinityMatchResult<Key>;
63
+ interface ClipSource {
64
+ src: string;
65
+ duration: number;
66
+ posterSrc?: string;
67
+ alt?: string;
68
+ credit?: string;
69
+ license?: string;
70
+ }
71
+ interface SelectedClip extends ClipSource {
72
+ clipStart: number;
73
+ clipEnd: number;
74
+ sourceDuration: number;
75
+ }
76
+ interface ClipSelectionOptions {
77
+ clipCount?: number;
78
+ minClipDuration?: number;
79
+ maxClipDuration?: number;
80
+ introSkipFraction?: number;
81
+ outroSkipFraction?: number;
82
+ seed?: number;
83
+ }
84
+ declare function selectSafeZoneClips(source: ClipSource, options?: ClipSelectionOptions): SelectedClip[];
85
+ interface TranscriptSegmentSource {
86
+ startTime: number;
87
+ endTime: number;
88
+ text: string;
89
+ keywords?: readonly string[];
90
+ }
91
+ declare function selectTranscriptClips(source: ClipSource, transcript: ReadonlyArray<TranscriptSegmentSource>, matchText: string, options?: ClipSelectionOptions): SelectedClip[];
92
+
93
+ export { type AffinityAssignment, type AffinityMatchResult, type AffinityTarget, type ClipSelectionOptions, type ClipSource, ExtractedElement, type KeywordExtractionOptions, type MapOptions, type SelectedClip, type TranscriptSegmentSource, calculateKeywordAffinity, extractKeywords, mapElementToBlock, matchByKeywordAffinity, selectSafeZoneClips, selectTranscriptClips };
@@ -1,10 +1,23 @@
1
+ import {
2
+ calculateKeywordAffinity,
3
+ extractKeywords,
4
+ matchByKeywordAffinity,
5
+ selectSafeZoneClips,
6
+ selectTranscriptClips
7
+ } from "../chunk-ZP5F7LUH.js";
1
8
  import {
2
9
  extractContent,
3
10
  mapElementToBlock,
4
11
  stripMarkdown
5
- } from "../chunk-NKNMGIIN.js";
12
+ } from "../chunk-SVN7T6BK.js";
13
+ import "../chunk-XRW6P7IF.js";
6
14
  export {
15
+ calculateKeywordAffinity,
7
16
  extractContent,
17
+ extractKeywords,
8
18
  mapElementToBlock,
19
+ matchByKeywordAffinity,
20
+ selectSafeZoneClips,
21
+ selectTranscriptClips,
9
22
  stripMarkdown
10
23
  };
package/dist/index.d.ts CHANGED
@@ -12,11 +12,11 @@ export { LocalForageAdapter, LocalForageAdapterOptions, LocalStorageAdapter, Mem
12
12
  export { C as ContentContainer, a as ContentEntry, M as MemoryContentContainer, f as findDocumentPath } from './ContentContainer-B2w9sUoL.js';
13
13
  export { DEFAULT_INTERACTIVE_RESOURCE_POLICY, DEFAULT_RESOURCE_MAX_BYTES, DEFAULT_RESOURCE_TIMEOUT_MS, DEFAULT_WRAP_WIDTH, FetchResourceBytesOptions, FetchedResource, HtmlPolicy, LOCAL_ONLY_RESOURCE_POLICY, MARKDOWN_SOURCE_TRANSFORMS, MarkdownSourceEdit, MarkdownSourceTransform, MarkdownSourceTransformId, MarkdownSourceTransformOptions, MarkdownSourceTransformResult, MarkdownWrapState, ResourcePolicy, ResourcePolicyError, SanitizeUrlOptions, TrailingAnnotationMatch, UrlKind, applyMarkdownSourceTransform, cleanupMarkdownSource, countNodes, createDocument, detectMarkdownWrapState, extractPlainText, fetchResourceBytes, findNodesByType, formatBlockScalar, formatFrontmatterValue, formatFrontmatterYaml, fromMdast, getChildren, inferDocumentTitle, isResourceUrlAllowed, matchTrailingPandocAttr, matchTrailingTemplateAnnotation, needsQuoting, parseFrontmatter, parseHtmlToNodes, parseMarkdown, parsePandocAttrTokens, plainTextFromInlineHtml, quoteAttrValue, readFrontmatterThemeId, sanitizeHtmlNodes, sanitizeUrl, serializePandocAttributes, setFrontmatterValues, splitFrontmatterBlock, splitKeyValueToken, stringifyHtmlNodes, stringifyMarkdown, toMdast, tokenizeAttrTokens, unquoteAttrValue, unwrapMarkdownSource, walkMarkdownTree, wrapMarkdownSource } from './markdown/index.js';
14
14
  export { B as BLOCK_META_KEY_DESCRIPTORS, a as BlockMetaKeyDescriptor, K as KNOWN_BLOCK_META_KEYS, b as KnownBlockMetaKey, p as parseTimeSeconds } from './annotationCoercion-Ckqpu33y.js';
15
- export { DEFAULT_WORDS_PER_SECOND, NarrationTimeEstimate, NarrationTimeOptions, ReadingTimeEstimate, ReadingTimeOptions, calculatePrefixDuration, countSpokenWords, estimateNarrationDuration, estimateNarrationTime, estimateReadingTime, estimateSpokenWordCount, estimateTimeFromText } from './timing/index.js';
15
+ export { BuildCaptionTrackOptions, CaptionSegmentSource, DEFAULT_WORDS_PER_SECOND, NarrationTimeEstimate, NarrationTimeOptions, ReadingTimeEstimate, ReadingTimeOptions, buildCaptionTrack, calculatePrefixDuration, countSpokenWords, estimateNarrationDuration, estimateNarrationTime, estimateReadingTime, estimateSpokenWordCount, estimateTimeFromText } from './timing/index.js';
16
16
  export { SeededRandom, hashString } from './random/index.js';
17
17
  export { C as ComparisonData, D as DateData, a as DefinitionData, E as ExtractedElement, b as ExtractionOptions, c as ExtractionResult, d as ExtractionType, F as FactData, I as ImpactLineData, L as ListData, Q as QuoteData, S as StatData, e as extractContent, s as stripMarkdown } from './contentExtractor-BNfVJV2U.js';
18
- export { MapOptions, mapElementToBlock } from './generate/index.js';
19
- export { AnalyzedBlock, BlockImage, DEFAULT_TRANSFORM_STYLE_ID, TransformImage, TransformOptions, TransformResult, TransformStyleConfig, TransformStyleId, TransformStyleInput, TransformStyleRegistry, TransformStyleSummary, analyzeBlocks, applyTransform, createTransformStyleRegistry, extractDocImages, getTransformStyleIds, getTransformStyleSummaries, resolveTransformStyle } from './transform/index.js';
18
+ export { AffinityAssignment, AffinityMatchResult, AffinityTarget, ClipSelectionOptions, ClipSource, KeywordExtractionOptions, MapOptions, SelectedClip, TranscriptSegmentSource, calculateKeywordAffinity, extractKeywords, mapElementToBlock, matchByKeywordAffinity, selectSafeZoneClips, selectTranscriptClips } from './generate/index.js';
19
+ export { AnalyzedBlock, BlockImage, DEFAULT_TRANSFORM_STYLE_ID, NarratedSegmentInput, NarratedSegmentResult, NarratedSegmentTransformOptions, NarratedSegmentVideo, TransformImage, TransformOptions, TransformResult, TransformStyleConfig, TransformStyleId, TransformStyleInput, TransformStyleRegistry, TransformStyleSummary, allocateTiming, analyzeBlocks, applyTransform, createTransformStyleRegistry, extractDocImages, getTransformStyleIds, getTransformStyleSummaries, resolveTransformStyle, transformNarratedSegment } from './transform/index.js';
20
20
  export { C as CoalesceOptions, P as PrunePolicy, R as RevertFailureReason, a as RevertOptions, b as RevertResult, S as SaveVersionOptions, c as SaveVersionResult, V as Version } from './types-8QjefM9J.js';
21
21
  export { DATA_BACKUP_PREFIX, DocumentVersionManager, DocumentVersionManagerOptions, VERSIONS_PREFIX, VERSION_TIMESTAMP_PATTERN, buildDataBackupPath, buildVersionPath, coalesceVersions, formatVersionTimestamp, getDocBasename, listVersions, parseVersionPath, parseVersionTimestamp, pruneVersions, readVersion, revertToVersion, saveVersion } from './versions/index.js';
22
22
  export { BuildJsonFormTokensOptions, ControlKind, InferSchemaOptions, JsonFormValidationError, JsonFormValidator, SquisqAnnotatedSchema, SquisqHints, SquisqWhen, appendPointer, arrayItemKind, buildJsonFormTokens, chooseControl, escapePointerSegment, evaluateWhen, getByPointer, inferSchema, isSafeConditionRegex, pointerSegments, primaryType, resolveFlag, resolveJsonFormTheme, resolveRef, setByPointer, toPointer } from './jsonForm/index.js';
@@ -26,5 +26,6 @@ export { IconSuggestion, canonicalIconToken, iconGlyph, looksLikeIconToken, reso
26
26
  export { BlockContentProfile, RecommendationResult, profileBlockContents, recommendTemplatesForBlock } from './recommend/index.js';
27
27
  export { AdvanceCoverage, AlignConfig, AlignInput, BandpassState, BuildAdvanceTimingOptions, BuildNarrationTimingOptions, BuildScriptOptions, DEFAULT_ALIGN_CONFIG, DEFAULT_FEATURE_CONFIG, DEFAULT_NUCLEI_CONFIG, DEFAULT_PACING_CONFIG, DEFAULT_VAD_CONFIG, EMPTY_ADVANCE_LOG, FeatureConfig, FeatureState, FrameFeatures, NarrationAlignment, NarrationBlockRange, NarrationScript, NarrationSessionConfig, NarrationSessionState, NarrationTimingBlock, NarrationTimingJsonV3, NarrationTimingMethod, NarrationTrace, NucleiConfig, NucleiState, PacingConfig, PacingState, PacingTick, ScriptBlockRange, ScriptToken, SlideAdvance, SlideAdvanceLog, TraceSample, VadConfig, VadState, WordTiming, advanceCoverage, alignNarration, bandpassRun, buildAdvanceTimingJson, buildNarrationScript, buildNarrationTimingJson, createBandpass, createFeatureState, createNarrationSession, createNucleiState, createPacingState, createVadState, detectSyllableOnsets, downsampleTrace, estimateSyllables, expectedSyllablesAt, extractFrameFeatures, featureStep, narrationSessionStep, nucleiStep, pacingStep, parseNarrationTimingJson, reanchorPacing, reanchorSession, recordSlideShown, traceWordPosAt, vadStep, wordIndexAtChar, wordIndexAtTime, wordPosAtExpectedSyllables } from './narration/index.js';
28
28
  export { FenceRenderContext, FenceRenderer, FenceRendererMap, fenceRendererLangs } from './fence/index.js';
29
- export { BlankProtectedSpansOptions, BlankedText, DEFAULT_PROOF_SETTINGS, JoinedSegments, LINT_KIND_CATEGORIES, PROOF_DIALECTS, PROOF_FRONTMATTER_KEYS, PROOF_JOIN_SEPARATOR, ProofCategory, ProofDialect, ProofFinding, ProofRange, ProofSuggestion, ProofSuggestionKind, ProofingSettings, SegmentSpan, blankProtectedSpans, buildJoinedText, categorizeLintKind, dropMaskedFindings, formatProofDictionary, mapJoinedSpanToSegment, parseProofDictionary, readProofingSettings, resolveProofDialect } from './proof/index.js';
29
+ export { P as PROOF_DIALECTS, a as ProofCategory, b as ProofDialect, c as ProofFinding, d as ProofRange, e as ProofSuggestion, f as ProofSuggestionKind } from './types-BQWu0gzi.js';
30
+ export { BlankProtectedSpansOptions, BlankedText, DEFAULT_PROOF_SETTINGS, JoinedSegments, LINT_KIND_CATEGORIES, PROOF_FRONTMATTER_KEYS, PROOF_JOIN_SEPARATOR, ProofingSettings, SegmentSpan, blankProtectedSpans, buildJoinedText, categorizeLintKind, dropMaskedFindings, formatProofDictionary, mapJoinedSpanToSegment, parseProofDictionary, readProofingSettings, resolveProofDialect } from './proof/index.js';
30
31
  import './viewState-lTZS-hP_.js';