@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,17 +1,19 @@
1
1
  import {
2
- estimateNarrationTime,
3
- estimateReadingTime
4
- } from "../chunk-XOFT65EX.js";
2
+ buildCaptionTrack
3
+ } from "../chunk-44BJ42GT.js";
5
4
  import {
6
5
  DEFAULT_WORDS_PER_SECOND,
7
6
  calculatePrefixDuration,
8
7
  countSpokenWords,
9
8
  estimateNarrationDuration,
9
+ estimateNarrationTime,
10
+ estimateReadingTime,
10
11
  estimateSpokenWordCount,
11
12
  estimateTimeFromText
12
- } from "../chunk-67L6WRJN.js";
13
+ } from "../chunk-GHOPHGOK.js";
13
14
  export {
14
15
  DEFAULT_WORDS_PER_SECOND,
16
+ buildCaptionTrack,
15
17
  calculatePrefixDuration,
16
18
  countSpokenWords,
17
19
  estimateNarrationDuration,
@@ -1,4 +1,4 @@
1
- import { r as ColorScheme, O as Doc, k as Block } from '../Doc-BkxT7G80.js';
1
+ import { O as Doc, r as ColorScheme, k as Block, bb as TemplateBlock } from '../Doc-BkxT7G80.js';
2
2
  import { i as PageTransformHints } from '../materializePageSection-Dp2aHFbc.js';
3
3
  import { d as ExtractionType, E as ExtractedElement, b as ExtractionOptions } from '../contentExtractor-BNfVJV2U.js';
4
4
  import '../types-Be6sBUBx.js';
@@ -145,6 +145,67 @@ interface TransformResult {
145
145
  */
146
146
  declare function applyTransform(doc: Doc, style: TransformStyleInput, options?: TransformOptions): TransformResult;
147
147
 
148
+ /**
149
+ * Narrated Segment Transformation
150
+ *
151
+ * Converts a narrated text segment and its media into a timed Doc using the
152
+ * canonical squisq transform pipeline. This is the reusable bridge for hosts
153
+ * that generate one visual sequence per narration segment.
154
+ */
155
+
156
+ interface NarratedSegmentVideo {
157
+ src: string;
158
+ posterSrc?: string;
159
+ alt?: string;
160
+ clipStart: number;
161
+ clipEnd: number;
162
+ sourceDuration?: number;
163
+ credit?: string;
164
+ license?: string;
165
+ }
166
+ interface NarratedSegmentInput {
167
+ articleId: string;
168
+ segmentId: string;
169
+ title: string;
170
+ text: string;
171
+ duration: number;
172
+ audioSrc: string;
173
+ audioName?: string;
174
+ images?: TransformImage[];
175
+ videos?: NarratedSegmentVideo[];
176
+ includeTitleBlock?: boolean;
177
+ }
178
+ interface NarratedSegmentTransformOptions extends Pick<TransformOptions, 'themeId' | 'registry'> {
179
+ style?: TransformStyleInput;
180
+ seed?: number;
181
+ minConfidence?: number;
182
+ slidesPerMinute?: number;
183
+ }
184
+ interface NarratedSegmentResult extends TransformResult {
185
+ seed: number;
186
+ }
187
+ declare function transformNarratedSegment(input: NarratedSegmentInput, options?: NarratedSegmentTransformOptions): NarratedSegmentResult;
188
+
189
+ /**
190
+ * Timing Allocator
191
+ *
192
+ * Distributes timing (startTime, duration) across transformed blocks.
193
+ * When the source Doc has audio, blocks are fitted to the overall duration.
194
+ * When no audio is present, uses reading-time estimation.
195
+ */
196
+
197
+ /**
198
+ * Allocate startTime and duration across a mixed array of blocks and
199
+ * template blocks. Template blocks get timing assigned; existing blocks
200
+ * retain their original timing when possible.
201
+ *
202
+ * @param blocks - The output from templateSelector (mixed Block | TemplateBlock).
203
+ * @param totalDuration - The Doc's total duration (from audio or estimation).
204
+ * @returns A new array of Blocks with consistent timing. Template blocks
205
+ * are returned as Blocks (with startTime/duration set, layers empty).
206
+ */
207
+ declare function allocateTiming(blocks: Array<Block | TemplateBlock>, totalDuration: number): Block[];
208
+
148
209
  /**
149
210
  * Transform Style Registry
150
211
  *
@@ -220,4 +281,4 @@ declare function extractDocImages(blocks: Block[]): TransformImage[];
220
281
  */
221
282
  declare function analyzeBlocks(blocks: Block[], options?: ExtractionOptions): AnalyzedBlock[];
222
283
 
223
- export { type AnalyzedBlock, type BlockImage, DEFAULT_TRANSFORM_STYLE_ID, type TransformImage, type TransformOptions, type TransformResult, type TransformStyleConfig, type TransformStyleId, type TransformStyleInput, type TransformStyleRegistry, type TransformStyleSummary, analyzeBlocks, applyTransform, createTransformStyleRegistry, extractDocImages, getTransformStyleIds, getTransformStyleSummaries, resolveTransformStyle };
284
+ export { type AnalyzedBlock, type BlockImage, DEFAULT_TRANSFORM_STYLE_ID, type NarratedSegmentInput, type NarratedSegmentResult, type NarratedSegmentTransformOptions, type NarratedSegmentVideo, type TransformImage, type TransformOptions, type TransformResult, type TransformStyleConfig, type TransformStyleId, type TransformStyleInput, type TransformStyleRegistry, type TransformStyleSummary, allocateTiming, analyzeBlocks, applyTransform, createTransformStyleRegistry, extractDocImages, getTransformStyleIds, getTransformStyleSummaries, resolveTransformStyle, transformNarratedSegment };
@@ -1,25 +1,36 @@
1
1
  import {
2
2
  DEFAULT_TRANSFORM_STYLE_ID,
3
+ allocateTiming,
3
4
  analyzeBlocks,
4
5
  applyTransform,
5
6
  createTransformStyleRegistry,
6
7
  extractDocImages,
7
8
  getTransformStyleIds,
8
9
  getTransformStyleSummaries,
9
- resolveTransformStyle
10
- } from "../chunk-ZSU5DJLX.js";
11
- import "../chunk-NKNMGIIN.js";
12
- import "../chunk-BAOV476U.js";
10
+ resolveTransformStyle,
11
+ transformNarratedSegment
12
+ } from "../chunk-J2IPSQKP.js";
13
+ import "../chunk-SVN7T6BK.js";
14
+ import "../chunk-WAGJK36Q.js";
15
+ import "../chunk-PUS54YU6.js";
16
+ import "../chunk-C3NAY5YP.js";
17
+ import "../chunk-Y4D6TDZT.js";
18
+ import "../chunk-CW24CH7I.js";
19
+ import "../chunk-TMOHAFYE.js";
20
+ import "../chunk-7N4G32LG.js";
13
21
  import "../chunk-X7BNDUNI.js";
14
- import "../chunk-67L6WRJN.js";
22
+ import "../chunk-4VOD55SX.js";
23
+ import "../chunk-GHOPHGOK.js";
15
24
  import "../chunk-XRW6P7IF.js";
16
25
  export {
17
26
  DEFAULT_TRANSFORM_STYLE_ID,
27
+ allocateTiming,
18
28
  analyzeBlocks,
19
29
  applyTransform,
20
30
  createTransformStyleRegistry,
21
31
  extractDocImages,
22
32
  getTransformStyleIds,
23
33
  getTransformStyleSummaries,
24
- resolveTransformStyle
34
+ resolveTransformStyle,
35
+ transformNarratedSegment
25
36
  };
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Plain-data types for the proofing (grammar + spellcheck) pipeline.
3
+ *
4
+ * These types are engine-agnostic: an editor host adapts a concrete
5
+ * engine (harper.js, a service, a test fake) to produce `ProofFinding`s,
6
+ * while this module stays pure and dependency-free so the mapping and
7
+ * masking helpers can run in Node tests and any consumer bundle.
8
+ */
9
+ /** Severity/color tier of a finding: red, green, or blue squiggle. */
10
+ type ProofCategory = 'spelling' | 'grammar' | 'style';
11
+ /** How a suggestion is applied relative to the finding's span. */
12
+ type ProofSuggestionKind = 'replace' | 'remove' | 'insertAfter';
13
+ /** One candidate fix for a finding. */
14
+ interface ProofSuggestion {
15
+ /** Replacement/insertion text (empty for `remove`). */
16
+ text: string;
17
+ kind: ProofSuggestionKind;
18
+ }
19
+ /** A half-open `[start, end)` range in UTF-16 code units. */
20
+ interface ProofRange {
21
+ start: number;
22
+ end: number;
23
+ }
24
+ /**
25
+ * One issue found in a linted text. Offsets index into the exact string
26
+ * that was linted (UTF-16 code units — the same coordinate space as
27
+ * ProseMirror, Monaco, and DOM Range).
28
+ */
29
+ interface ProofFinding extends ProofRange {
30
+ /** Stable within one lint pass; the provider maps id → engine handle. */
31
+ id: string;
32
+ category: ProofCategory;
33
+ /** Raw engine kind (e.g. `Typo`), for diagnostics and future filtering. */
34
+ kind: string;
35
+ /** Human-readable description of the issue. */
36
+ message: string;
37
+ /** Text at `[start, end)` when linted — staleness check before applying. */
38
+ originalText: string;
39
+ suggestions: ProofSuggestion[];
40
+ }
41
+ /** English dialects supported by the proofing engine. */
42
+ type ProofDialect = 'American' | 'British' | 'Australian' | 'Canadian' | 'Indian';
43
+ /** All supported dialects, in display order. */
44
+ declare const PROOF_DIALECTS: readonly ProofDialect[];
45
+
46
+ export { PROOF_DIALECTS as P, type ProofCategory as a, type ProofDialect as b, type ProofFinding as c, type ProofRange as d, type ProofSuggestion as e, type ProofSuggestionKind as f };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bendyline/squisq",
3
- "version": "2.11.4",
3
+ "version": "2.11.6",
4
4
  "description": "Headless utilities for doc/block rendering, spatial math, Markdown, and storage",
5
5
  "license": "MIT",
6
6
  "author": "Bendyline",
@@ -132,6 +132,11 @@
132
132
  "import": "./dist/proof/index.js",
133
133
  "default": "./dist/proof/index.js"
134
134
  },
135
+ "./review": {
136
+ "types": "./dist/review/index.d.ts",
137
+ "import": "./dist/review/index.js",
138
+ "default": "./dist/review/index.js"
139
+ },
135
140
  "./table": {
136
141
  "types": "./dist/table/index.d.ts",
137
142
  "import": "./dist/table/index.js",
@@ -1,214 +0,0 @@
1
- // src/schemas/Viewport.ts
2
- var VIEWPORT_PRESETS = {
3
- /** 16:9 landscape (default, 1080p) */
4
- landscape: { width: 1920, height: 1080, name: "16:9 Landscape" },
5
- /** 9:16 portrait (vertical video, stories) */
6
- portrait: { width: 1080, height: 1920, name: "9:16 Portrait" },
7
- /** 1:1 square (social media) */
8
- square: { width: 1080, height: 1080, name: "1:1 Square" },
9
- /** 4:3 standard */
10
- standard: { width: 1440, height: 1080, name: "4:3 Standard" }
11
- };
12
- function getViewport(viewport) {
13
- if (typeof viewport === "string") {
14
- return VIEWPORT_PRESETS[viewport];
15
- }
16
- return viewport;
17
- }
18
- var REFERENCE_DIAGONAL = Math.sqrt(1920 * 1920 + 1080 * 1080);
19
- function calculateFontScale(viewport) {
20
- const currentDiagonal = Math.sqrt(
21
- viewport.width * viewport.width + viewport.height * viewport.height
22
- );
23
- return currentDiagonal / REFERENCE_DIAGONAL;
24
- }
25
- function getViewportOrientation(viewport) {
26
- const ratio = viewport.width / viewport.height;
27
- if (Math.abs(ratio - 1) < 0.05) return "square";
28
- return ratio > 1 ? "landscape" : "portrait";
29
- }
30
- function getAspectRatioString(viewport) {
31
- const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
32
- const divisor = gcd(viewport.width, viewport.height);
33
- return `${viewport.width / divisor}:${viewport.height / divisor}`;
34
- }
35
-
36
- // src/schemas/LayoutStrategy.ts
37
- var LAYOUT_CONFIGS = {
38
- landscape: {
39
- primaryY: "35%",
40
- secondaryY: "55%",
41
- tertiaryY: "75%",
42
- titleScale: 1,
43
- bodyScale: 1,
44
- columnLeftX: "25%",
45
- columnRightX: "75%",
46
- columnTopY: "35%",
47
- columnBottomY: "65%",
48
- stackColumns: false,
49
- maxTextWidth: "80%",
50
- horizontalPadding: "10%",
51
- captionY: "85%",
52
- captionScale: 1
53
- },
54
- portrait: {
55
- // Content positioned higher for thumb-reach zone on mobile
56
- primaryY: "25%",
57
- secondaryY: "42%",
58
- tertiaryY: "58%",
59
- // Titles scale down for narrower width; body text scales up to fill vertical space
60
- titleScale: 0.7,
61
- bodyScale: 1.5,
62
- // Stacked columns instead of side-by-side
63
- columnLeftX: "50%",
64
- columnRightX: "50%",
65
- columnTopY: "30%",
66
- columnBottomY: "55%",
67
- stackColumns: true,
68
- // Wider relative to viewport to use available space
69
- maxTextWidth: "90%",
70
- horizontalPadding: "5%",
71
- captionY: "75%",
72
- captionScale: 0.85
73
- },
74
- square: {
75
- primaryY: "30%",
76
- secondaryY: "50%",
77
- tertiaryY: "70%",
78
- titleScale: 0.85,
79
- bodyScale: 0.9,
80
- columnLeftX: "25%",
81
- columnRightX: "75%",
82
- columnTopY: "35%",
83
- columnBottomY: "65%",
84
- stackColumns: false,
85
- maxTextWidth: "85%",
86
- horizontalPadding: "7.5%",
87
- captionY: "82%",
88
- captionScale: 0.9
89
- }
90
- };
91
- function getLayoutHints(orientation) {
92
- return LAYOUT_CONFIGS[orientation];
93
- }
94
- function scaledFontSize(basePx, viewport, orientation, isTitle = false) {
95
- const fontScale = calculateFontScale(viewport);
96
- const layout = getLayoutHints(orientation);
97
- const typeScale = isTitle ? layout.titleScale : layout.bodyScale;
98
- return Math.round(basePx * fontScale * typeScale);
99
- }
100
- function getTwoColumnPositions(orientation) {
101
- const layout = getLayoutHints(orientation);
102
- if (layout.stackColumns) {
103
- return {
104
- left: { x: "50%", y: layout.columnTopY },
105
- right: { x: "50%", y: layout.columnBottomY }
106
- };
107
- }
108
- return {
109
- left: { x: layout.columnLeftX, y: "50%" },
110
- right: { x: layout.columnRightX, y: "50%" }
111
- };
112
- }
113
- function getSafeTextBounds(orientation) {
114
- const layout = getLayoutHints(orientation);
115
- return {
116
- left: layout.horizontalPadding,
117
- right: layout.horizontalPadding,
118
- top: "10%",
119
- bottom: "10%"
120
- };
121
- }
122
-
123
- // src/schemas/BlockTemplates.ts
124
- var DEFAULT_DOC_FONT = 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
125
- var DEFAULT_TITLE_FONT = 'Georgia, "Times New Roman", serif';
126
- function isTemplateBlock(block) {
127
- return "template" in block && typeof block.template === "string";
128
- }
129
- function createTemplateContext(theme, blockIndex, totalBlocks, viewport = VIEWPORT_PRESETS.landscape) {
130
- const orientation = getViewportOrientation(viewport);
131
- const overrides = theme.renderStyle.layoutOverrides;
132
- const baseLayout = getLayoutHints(orientation);
133
- return {
134
- theme,
135
- blockIndex,
136
- totalBlocks,
137
- viewport,
138
- fontScale: calculateFontScale(viewport),
139
- orientation,
140
- layout: overrides ? { ...baseLayout, ...overrides } : baseLayout
141
- };
142
- }
143
- function scaledFontSize2(basePx, context, isTitle = false) {
144
- return scaledFontSize(basePx, context.viewport, context.orientation, isTitle);
145
- }
146
- function isPersistentLayerTemplate(layer) {
147
- return "template" in layer && typeof layer.template === "string";
148
- }
149
-
150
- // src/internal/immutable.ts
151
- function cloneData(value, seen = /* @__PURE__ */ new WeakMap()) {
152
- if (value === null || typeof value !== "object") return value;
153
- const existing = seen.get(value);
154
- if (existing !== void 0) return existing;
155
- const tag = Object.prototype.toString.call(value);
156
- if (tag === "[object ArrayBuffer]") {
157
- const source2 = new Uint8Array(value);
158
- const copy2 = new Uint8Array(source2.byteLength);
159
- copy2.set(source2);
160
- return copy2.buffer;
161
- }
162
- if (tag === "[object Date]") {
163
- return new Date(Date.prototype.getTime.call(value));
164
- }
165
- if (Array.isArray(value)) {
166
- const copy2 = [];
167
- seen.set(value, copy2);
168
- for (const item of value) copy2.push(cloneData(item, seen));
169
- return copy2;
170
- }
171
- const source = value;
172
- const copy = {};
173
- seen.set(value, copy);
174
- for (const key of Object.keys(source)) {
175
- Object.defineProperty(copy, key, {
176
- value: cloneData(source[key], seen),
177
- enumerable: true,
178
- configurable: true,
179
- writable: true
180
- });
181
- }
182
- return copy;
183
- }
184
- function deepFreezeData(value, seen = /* @__PURE__ */ new WeakSet()) {
185
- if (value === null || typeof value !== "object" || seen.has(value)) return value;
186
- seen.add(value);
187
- for (const key of Object.keys(value)) {
188
- deepFreezeData(value[key], seen);
189
- }
190
- return Object.freeze(value);
191
- }
192
- function cloneAndFreezeData(value) {
193
- return deepFreezeData(cloneData(value));
194
- }
195
-
196
- export {
197
- VIEWPORT_PRESETS,
198
- getViewport,
199
- calculateFontScale,
200
- getViewportOrientation,
201
- getAspectRatioString,
202
- getLayoutHints,
203
- scaledFontSize,
204
- getTwoColumnPositions,
205
- getSafeTextBounds,
206
- DEFAULT_DOC_FONT,
207
- DEFAULT_TITLE_FONT,
208
- isTemplateBlock,
209
- createTemplateContext,
210
- scaledFontSize2,
211
- isPersistentLayerTemplate,
212
- cloneData,
213
- cloneAndFreezeData
214
- };
@@ -1,34 +0,0 @@
1
- import {
2
- DEFAULT_WORDS_PER_SECOND,
3
- countSpokenWords
4
- } from "./chunk-67L6WRJN.js";
5
-
6
- // src/timing/readingTime.ts
7
- var DEFAULT_READING_WPM = 200;
8
- function estimateReadingTime(text, options) {
9
- const configuredWpm = options?.wordsPerMinute;
10
- const wpm = typeof configuredWpm === "number" && configuredWpm > 0 ? configuredWpm : DEFAULT_READING_WPM;
11
- const words = text.split(/\s+/).filter((w) => w.length > 0).length;
12
- const minutes = words / wpm;
13
- return {
14
- words,
15
- minutes,
16
- seconds: Math.round(minutes * 60)
17
- };
18
- }
19
- function estimateNarrationTime(text, options) {
20
- const providedWps = options?.wordsPerSecond;
21
- const wps = typeof providedWps === "number" && providedWps > 0 ? providedWps : DEFAULT_WORDS_PER_SECOND;
22
- const spokenWords = countSpokenWords(text);
23
- const totalSeconds = spokenWords / wps;
24
- return {
25
- spokenWords,
26
- minutes: totalSeconds / 60,
27
- seconds: Math.round(totalSeconds)
28
- };
29
- }
30
-
31
- export {
32
- estimateReadingTime,
33
- estimateNarrationTime
34
- };