@bendyline/squisq 2.0.1 → 2.2.0

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 (438) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +24 -0
  3. package/dist/{ContentContainer-BXUlIf18.d.ts → ContentContainer-B2w9sUoL.d.ts} +15 -0
  4. package/dist/{Doc-ylqWKDc_.d.ts → Doc-BubIpWsp.d.ts} +160 -3
  5. package/dist/{ImageEditDoc-D828IXJ1.d.ts → ImageEditDoc-CGxk5CHc.d.ts} +1 -1
  6. package/dist/{annotationCoercion-Dr_DY9Hx.d.ts → annotationCoercion-PtRQhk5V.d.ts} +1 -1
  7. package/dist/chunk-2L55443L.js +0 -0
  8. package/dist/chunk-2ZWIXGAC.js +214 -0
  9. package/dist/{chunk-2PWOO4ZE.js → chunk-32R2RZAO.js} +72 -3
  10. package/dist/chunk-3IGPAPQ7.js +645 -0
  11. package/dist/{chunk-QE7TWGVT.js → chunk-4VOD55SX.js} +0 -1
  12. package/dist/{chunk-3E5F2XMR.js → chunk-67L6WRJN.js} +0 -1
  13. package/dist/{chunk-5DKBFXPY.js → chunk-6ECMNUIP.js} +26 -18
  14. package/dist/{chunk-X6DUONGT.js → chunk-7ARJZYQY.js} +280 -128
  15. package/dist/{chunk-DBS6RIFL.js → chunk-7N4G32LG.js} +0 -1
  16. package/dist/{chunk-JOQYPRDZ.js → chunk-7YEZFHLS.js} +10 -8
  17. package/dist/{chunk-2UQOHYE2.js → chunk-7ZAAICW4.js} +0 -1
  18. package/dist/{chunk-66QO7XFB.js → chunk-ACZOVWX3.js} +117 -7
  19. package/dist/{chunk-5J4HKRJF.js → chunk-BAOV476U.js} +0 -1
  20. package/dist/chunk-BCCXTMN5.js +699 -0
  21. package/dist/{chunk-W4O2TX5I.js → chunk-C33GTPUZ.js} +579 -4
  22. package/dist/{chunk-MMPBOUK7.js → chunk-CB45YGAM.js} +7 -2
  23. package/dist/{chunk-CY2R2VPR.js → chunk-DYPMOPIW.js} +18 -2
  24. package/dist/{chunk-VR7UPJ7C.js → chunk-FCG3BIZN.js} +12 -1
  25. package/dist/{chunk-5UYI3RJB.js → chunk-FDYDYL77.js} +54 -40
  26. package/dist/{chunk-TFJVXUHH.js → chunk-I2O6W7DX.js} +1513 -79
  27. package/dist/{chunk-Q7LROV2H.js → chunk-NKNMGIIN.js} +0 -1
  28. package/dist/chunk-OPO5K4DZ.js +241 -0
  29. package/dist/{chunk-TUWMK62B.js → chunk-PUS54YU6.js} +45 -2
  30. package/dist/chunk-QKPXHDLR.js +0 -0
  31. package/dist/{chunk-GZY66SDN.js → chunk-R3KTTOMS.js} +0 -1
  32. package/dist/{chunk-PXLVXTLW.js → chunk-RS5AP3J4.js} +72 -15
  33. package/dist/chunk-WV5ARNDA.js +0 -0
  34. package/dist/{chunk-4X3JQXNM.js → chunk-XOFT65EX.js} +1 -2
  35. package/dist/{chunk-FVTQSNR7.js → chunk-XRW6P7IF.js} +13 -5
  36. package/dist/chunk-XWNNA3KE.js +0 -0
  37. package/dist/chunk-YZNGMV3G.js +0 -0
  38. package/dist/{chunk-R2YZTCLO.js → chunk-ZQKZSJAX.js} +1 -2
  39. package/dist/doc/index.d.ts +166 -12
  40. package/dist/doc/index.js +36 -17
  41. package/dist/generate/index.d.ts +2 -2
  42. package/dist/generate/index.js +2 -3
  43. package/dist/icons/index.js +3 -4
  44. package/dist/icons/inlineIconMarker.js +1 -2
  45. package/dist/imageEdit/index.d.ts +48 -17
  46. package/dist/imageEdit/index.js +3 -4
  47. package/dist/index.d.ts +13 -12
  48. package/dist/index.js +118 -33
  49. package/dist/jsonForm/index.d.ts +10 -3
  50. package/dist/jsonForm/index.js +8 -7
  51. package/dist/markdown/index.d.ts +75 -11
  52. package/dist/markdown/index.js +32 -7
  53. package/dist/materializePageSection-wSLA2A1g.d.ts +223 -0
  54. package/dist/narration/index.d.ts +16 -3
  55. package/dist/narration/index.js +13 -14
  56. package/dist/random/index.d.ts +11 -2
  57. package/dist/random/index.js +2 -3
  58. package/dist/recommend/index.d.ts +1 -1
  59. package/dist/recommend/index.js +3 -4
  60. package/dist/schemas/index.d.ts +31 -6
  61. package/dist/schemas/index.js +43 -6
  62. package/dist/spatial/index.d.ts +2 -1
  63. package/dist/spatial/index.js +1 -2
  64. package/dist/storage/index.d.ts +4 -2
  65. package/dist/storage/index.js +1 -2
  66. package/dist/{themeLibrary-RjVgLpUi.d.ts → themeLibrary-DU9mUmVl.d.ts} +1 -1
  67. package/dist/timing/index.js +3 -4
  68. package/dist/transform/index.d.ts +9 -10
  69. package/dist/transform/index.js +6 -7
  70. package/dist/{types-C4kiRn_k.d.ts → types-8QjefM9J.d.ts} +38 -2
  71. package/dist/{types-BwMPl2CB.d.ts → types-CUNc9biN.d.ts} +24 -1
  72. package/dist/versions/index.d.ts +14 -11
  73. package/dist/versions/index.js +2 -3
  74. package/package.json +4 -2
  75. package/dist/chunk-2PWOO4ZE.js.map +0 -1
  76. package/dist/chunk-2UQOHYE2.js.map +0 -1
  77. package/dist/chunk-3E5F2XMR.js.map +0 -1
  78. package/dist/chunk-4X3JQXNM.js.map +0 -1
  79. package/dist/chunk-5DKBFXPY.js.map +0 -1
  80. package/dist/chunk-5J4HKRJF.js.map +0 -1
  81. package/dist/chunk-5UYI3RJB.js.map +0 -1
  82. package/dist/chunk-66QO7XFB.js.map +0 -1
  83. package/dist/chunk-AMIR72JP.js +0 -380
  84. package/dist/chunk-AMIR72JP.js.map +0 -1
  85. package/dist/chunk-CY2R2VPR.js.map +0 -1
  86. package/dist/chunk-DBS6RIFL.js.map +0 -1
  87. package/dist/chunk-DNJKBAI7.js +0 -1
  88. package/dist/chunk-DNJKBAI7.js.map +0 -1
  89. package/dist/chunk-ET53IIEP.js +0 -1
  90. package/dist/chunk-ET53IIEP.js.map +0 -1
  91. package/dist/chunk-FVJUUTEM.js +0 -74
  92. package/dist/chunk-FVJUUTEM.js.map +0 -1
  93. package/dist/chunk-FVTQSNR7.js.map +0 -1
  94. package/dist/chunk-GZY66SDN.js.map +0 -1
  95. package/dist/chunk-JOQYPRDZ.js.map +0 -1
  96. package/dist/chunk-MMPBOUK7.js.map +0 -1
  97. package/dist/chunk-PGGGKYWG.js +0 -1
  98. package/dist/chunk-PGGGKYWG.js.map +0 -1
  99. package/dist/chunk-PXLVXTLW.js.map +0 -1
  100. package/dist/chunk-Q7LROV2H.js.map +0 -1
  101. package/dist/chunk-QE7TWGVT.js.map +0 -1
  102. package/dist/chunk-R2GC6RLD.js +0 -344
  103. package/dist/chunk-R2GC6RLD.js.map +0 -1
  104. package/dist/chunk-R2YZTCLO.js.map +0 -1
  105. package/dist/chunk-S7A5D7ZJ.js +0 -174
  106. package/dist/chunk-S7A5D7ZJ.js.map +0 -1
  107. package/dist/chunk-TFJVXUHH.js.map +0 -1
  108. package/dist/chunk-TUWMK62B.js.map +0 -1
  109. package/dist/chunk-V543AI2F.js +0 -1
  110. package/dist/chunk-V543AI2F.js.map +0 -1
  111. package/dist/chunk-VR7UPJ7C.js.map +0 -1
  112. package/dist/chunk-W4O2TX5I.js.map +0 -1
  113. package/dist/chunk-X6DUONGT.js.map +0 -1
  114. package/dist/chunk-ZLQKNOZQ.js +0 -1
  115. package/dist/chunk-ZLQKNOZQ.js.map +0 -1
  116. package/dist/doc/index.js.map +0 -1
  117. package/dist/generate/index.js.map +0 -1
  118. package/dist/icons/index.js.map +0 -1
  119. package/dist/icons/inlineIconMarker.js.map +0 -1
  120. package/dist/imageEdit/index.js.map +0 -1
  121. package/dist/index.js.map +0 -1
  122. package/dist/jsonForm/index.js.map +0 -1
  123. package/dist/markdown/index.js.map +0 -1
  124. package/dist/narration/index.js.map +0 -1
  125. package/dist/random/index.js.map +0 -1
  126. package/dist/recommend/index.js.map +0 -1
  127. package/dist/schemas/index.js.map +0 -1
  128. package/dist/spatial/index.js.map +0 -1
  129. package/dist/storage/index.js.map +0 -1
  130. package/dist/timing/index.js.map +0 -1
  131. package/dist/transform/index.js.map +0 -1
  132. package/dist/versions/index.js.map +0 -1
  133. package/src/__tests__/animationUtils.test.ts +0 -117
  134. package/src/__tests__/annotationCoercion.test.ts +0 -243
  135. package/src/__tests__/applyNarrationTiming.test.ts +0 -190
  136. package/src/__tests__/applyRenderStyle.test.ts +0 -146
  137. package/src/__tests__/asciiDiagramBattle.test.ts +0 -246
  138. package/src/__tests__/asciiDiagramDetect.test.ts +0 -162
  139. package/src/__tests__/asciiDiagramMapping.test.ts +0 -38
  140. package/src/__tests__/asciiDiagramParse.test.ts +0 -233
  141. package/src/__tests__/asciiDiagramPipeline.test.ts +0 -273
  142. package/src/__tests__/asciiDiagramRender.test.ts +0 -162
  143. package/src/__tests__/asciiDiagramRepair.test.ts +0 -84
  144. package/src/__tests__/asciiTimelineDetect.test.ts +0 -157
  145. package/src/__tests__/asciiTimelineParse.test.ts +0 -205
  146. package/src/__tests__/asciiTimelinePipeline.test.ts +0 -349
  147. package/src/__tests__/asciiTimelineRender.test.ts +0 -376
  148. package/src/__tests__/atmosphereLayers.test.ts +0 -108
  149. package/src/__tests__/attrTokens.test.ts +0 -167
  150. package/src/__tests__/colorUtils.test.ts +0 -112
  151. package/src/__tests__/contentContainer.test.ts +0 -325
  152. package/src/__tests__/contentExtractor.test.ts +0 -243
  153. package/src/__tests__/coverBlock.test.ts +0 -310
  154. package/src/__tests__/customTemplateSample.test.ts +0 -144
  155. package/src/__tests__/customTemplatesFrontmatter.test.ts +0 -221
  156. package/src/__tests__/customThemesFrontmatter.test.ts +0 -146
  157. package/src/__tests__/dataTable.test.ts +0 -145
  158. package/src/__tests__/diagramBlock.test.ts +0 -122
  159. package/src/__tests__/diagramLayout.test.ts +0 -134
  160. package/src/__tests__/diagramText.test.ts +0 -26
  161. package/src/__tests__/docToMarkdownMedia.test.ts +0 -83
  162. package/src/__tests__/drawing.test.ts +0 -109
  163. package/src/__tests__/drawingBlock.test.ts +0 -124
  164. package/src/__tests__/drawingLayout.test.ts +0 -171
  165. package/src/__tests__/fixtures/asciiDiagramBattle.ts +0 -512
  166. package/src/__tests__/fixtures/asciiDiagrams.ts +0 -287
  167. package/src/__tests__/fixtures/asciiTimelines.ts +0 -35
  168. package/src/__tests__/fixtures/treeviewFixtures.ts +0 -243
  169. package/src/__tests__/geohash.test.ts +0 -110
  170. package/src/__tests__/getLayers.test.ts +0 -243
  171. package/src/__tests__/getLayersFallback.test.ts +0 -103
  172. package/src/__tests__/haversine.test.ts +0 -63
  173. package/src/__tests__/iconResolve.test.ts +0 -122
  174. package/src/__tests__/imageEditExportSvg.test.ts +0 -70
  175. package/src/__tests__/imageEditState.test.ts +0 -74
  176. package/src/__tests__/imageEditVersions.test.ts +0 -243
  177. package/src/__tests__/inferDocumentTitle.test.ts +0 -50
  178. package/src/__tests__/inlineIconMarker.test.ts +0 -36
  179. package/src/__tests__/inputDescriptors.test.ts +0 -162
  180. package/src/__tests__/jsonForm.chooseControl.test.ts +0 -86
  181. package/src/__tests__/jsonForm.evaluateWhen.test.ts +0 -59
  182. package/src/__tests__/jsonForm.inferSchema.test.ts +0 -25
  183. package/src/__tests__/jsonForm.pointer.test.ts +0 -149
  184. package/src/__tests__/jsonForm.tokens.test.ts +0 -84
  185. package/src/__tests__/layoutBlock.test.ts +0 -83
  186. package/src/__tests__/layoutLayout.test.ts +0 -169
  187. package/src/__tests__/localForageAdapter.test.ts +0 -155
  188. package/src/__tests__/majorApiTypes.test.ts +0 -18
  189. package/src/__tests__/markdown.test.ts +0 -1009
  190. package/src/__tests__/markdownIcons.test.ts +0 -104
  191. package/src/__tests__/markdownSanitize.test.ts +0 -81
  192. package/src/__tests__/markdownToDoc.test.ts +0 -957
  193. package/src/__tests__/matchFontFamily.test.ts +0 -114
  194. package/src/__tests__/materializeBlockLayers.test.ts +0 -135
  195. package/src/__tests__/materializeTestUtils.ts +0 -17
  196. package/src/__tests__/mediaAnnotations.test.ts +0 -91
  197. package/src/__tests__/mediaSchedule.test.ts +0 -118
  198. package/src/__tests__/narrationAlign.test.ts +0 -150
  199. package/src/__tests__/narrationFeatures.test.ts +0 -71
  200. package/src/__tests__/narrationNuclei.test.ts +0 -45
  201. package/src/__tests__/narrationPacing.test.ts +0 -189
  202. package/src/__tests__/narrationScript.test.ts +0 -149
  203. package/src/__tests__/narrationSessionRepro.test.ts +0 -62
  204. package/src/__tests__/narrationSidecar.test.ts +0 -88
  205. package/src/__tests__/narrationSyllables.test.ts +0 -65
  206. package/src/__tests__/narrationTestSignals.ts +0 -167
  207. package/src/__tests__/narrationVad.test.ts +0 -66
  208. package/src/__tests__/pandocAttrParse.test.ts +0 -187
  209. package/src/__tests__/recommendTemplates.test.ts +0 -183
  210. package/src/__tests__/resolveDocTheme.test.ts +0 -69
  211. package/src/__tests__/rootExports.test.ts +0 -61
  212. package/src/__tests__/scopedContentContainer.test.ts +0 -109
  213. package/src/__tests__/seededRandom.test.ts +0 -142
  214. package/src/__tests__/shapeGeometry.test.ts +0 -138
  215. package/src/__tests__/shapeVocabulary.test.ts +0 -133
  216. package/src/__tests__/storage.test.ts +0 -60
  217. package/src/__tests__/structuredData.test.ts +0 -249
  218. package/src/__tests__/surface.test.ts +0 -68
  219. package/src/__tests__/templateAnnotationParse.test.ts +0 -160
  220. package/src/__tests__/templateInputs.test.ts +0 -69
  221. package/src/__tests__/templateMetadata.test.ts +0 -32
  222. package/src/__tests__/templates.test.ts +0 -710
  223. package/src/__tests__/themeCompile.test.ts +0 -225
  224. package/src/__tests__/themeValidator.test.ts +0 -131
  225. package/src/__tests__/timing.test.ts +0 -167
  226. package/src/__tests__/transformProvenance.test.ts +0 -160
  227. package/src/__tests__/transformV2.test.ts +0 -163
  228. package/src/__tests__/transitionNormalize.test.ts +0 -61
  229. package/src/__tests__/treeviewBattle.test.ts +0 -76
  230. package/src/__tests__/treeviewDetect.test.ts +0 -168
  231. package/src/__tests__/treeviewParse.test.ts +0 -118
  232. package/src/__tests__/treeviewPipeline.test.ts +0 -183
  233. package/src/__tests__/treeviewRender.test.ts +0 -91
  234. package/src/__tests__/validateDoc.test.ts +0 -260
  235. package/src/__tests__/versions.test.ts +0 -459
  236. package/src/doc/annotationBlocks.ts +0 -117
  237. package/src/doc/applyNarrationTiming.ts +0 -244
  238. package/src/doc/asciiDiagram/chars.ts +0 -210
  239. package/src/doc/asciiDiagram/detect.ts +0 -175
  240. package/src/doc/asciiDiagram/index.ts +0 -38
  241. package/src/doc/asciiDiagram/mapping.ts +0 -225
  242. package/src/doc/asciiDiagram/parse.ts +0 -1095
  243. package/src/doc/asciiDiagram/render.ts +0 -963
  244. package/src/doc/asciiDiagram/repair.ts +0 -400
  245. package/src/doc/asciiDiagram/types.ts +0 -65
  246. package/src/doc/asciiTimeline/detect.ts +0 -138
  247. package/src/doc/asciiTimeline/index.ts +0 -26
  248. package/src/doc/asciiTimeline/mapping.ts +0 -43
  249. package/src/doc/asciiTimeline/parse.ts +0 -870
  250. package/src/doc/asciiTimeline/render.ts +0 -427
  251. package/src/doc/asciiTimeline/types.ts +0 -73
  252. package/src/doc/asciiTimeline/wrappedFlow.ts +0 -427
  253. package/src/doc/audioMapping.ts +0 -442
  254. package/src/doc/customTemplatesFrontmatter.ts +0 -273
  255. package/src/doc/customThemesFrontmatter.ts +0 -95
  256. package/src/doc/docToMarkdown.ts +0 -284
  257. package/src/doc/index.ts +0 -127
  258. package/src/doc/markdownToDoc.ts +0 -1054
  259. package/src/doc/materializeBlockLayers.ts +0 -304
  260. package/src/doc/mediaAnnotations.ts +0 -120
  261. package/src/doc/resolveDocTheme.ts +0 -56
  262. package/src/doc/standaloneAnnotation.ts +0 -58
  263. package/src/doc/structuredData.ts +0 -301
  264. package/src/doc/templateInputs.ts +0 -423
  265. package/src/doc/templates/__tests__/customTemplate.test.ts +0 -170
  266. package/src/doc/templates/__tests__/customTemplateRegistry.test.ts +0 -124
  267. package/src/doc/templates/__tests__/listBlock.test.ts +0 -64
  268. package/src/doc/templates/accentImage.ts +0 -362
  269. package/src/doc/templates/captionUtils.ts +0 -56
  270. package/src/doc/templates/comparisonBar.ts +0 -173
  271. package/src/doc/templates/coverBlock.ts +0 -255
  272. package/src/doc/templates/customTemplate.ts +0 -51
  273. package/src/doc/templates/dataTable.ts +0 -102
  274. package/src/doc/templates/dateEvent.ts +0 -147
  275. package/src/doc/templates/definitionCard.ts +0 -140
  276. package/src/doc/templates/diagramBlock.ts +0 -403
  277. package/src/doc/templates/diagramLayout.ts +0 -159
  278. package/src/doc/templates/drawingBlock.ts +0 -325
  279. package/src/doc/templates/drawingLayout.ts +0 -539
  280. package/src/doc/templates/factCard.ts +0 -146
  281. package/src/doc/templates/fallbackBlock.ts +0 -123
  282. package/src/doc/templates/featureBlock.ts +0 -209
  283. package/src/doc/templates/fullBleedQuote.ts +0 -83
  284. package/src/doc/templates/imageWithCaption.ts +0 -186
  285. package/src/doc/templates/index.ts +0 -642
  286. package/src/doc/templates/inputDescriptors.ts +0 -451
  287. package/src/doc/templates/layoutBlock.ts +0 -43
  288. package/src/doc/templates/layoutLayout.ts +0 -243
  289. package/src/doc/templates/listBlock.ts +0 -207
  290. package/src/doc/templates/mapBlock.ts +0 -138
  291. package/src/doc/templates/metadata.ts +0 -130
  292. package/src/doc/templates/persistentLayers.ts +0 -526
  293. package/src/doc/templates/photoGrid.ts +0 -190
  294. package/src/doc/templates/pullQuote.ts +0 -141
  295. package/src/doc/templates/quoteBlock.ts +0 -141
  296. package/src/doc/templates/registry.ts +0 -88
  297. package/src/doc/templates/sectionHeader.ts +0 -120
  298. package/src/doc/templates/statHighlight.ts +0 -146
  299. package/src/doc/templates/templateNames.ts +0 -22
  300. package/src/doc/templates/timelineBlock.ts +0 -613
  301. package/src/doc/templates/titleBlock.ts +0 -150
  302. package/src/doc/templates/tokens/__tests__/resolveTokens.test.ts +0 -487
  303. package/src/doc/templates/tokens/resolveTokens.ts +0 -453
  304. package/src/doc/templates/treeBlock.ts +0 -131
  305. package/src/doc/templates/twoColumn.ts +0 -263
  306. package/src/doc/templates/videoPullQuote.ts +0 -142
  307. package/src/doc/templates/videoWithCaption.ts +0 -135
  308. package/src/doc/treeview/chars.ts +0 -72
  309. package/src/doc/treeview/detect.ts +0 -145
  310. package/src/doc/treeview/index.ts +0 -30
  311. package/src/doc/treeview/mapping.ts +0 -95
  312. package/src/doc/treeview/parse.ts +0 -201
  313. package/src/doc/treeview/render.ts +0 -41
  314. package/src/doc/treeview/types.ts +0 -43
  315. package/src/doc/utils/animationUtils.ts +0 -399
  316. package/src/doc/utils/applyRenderStyle.ts +0 -106
  317. package/src/doc/utils/diagramText.ts +0 -78
  318. package/src/doc/utils/imageTreatment.ts +0 -70
  319. package/src/doc/utils/nearest.ts +0 -59
  320. package/src/doc/utils/shapeGeometry.ts +0 -614
  321. package/src/doc/utils/themeUtils.ts +0 -243
  322. package/src/doc/validate.ts +0 -575
  323. package/src/generate/contentExtractor.ts +0 -921
  324. package/src/generate/index.ts +0 -18
  325. package/src/generate/templateMapper.ts +0 -177
  326. package/src/icons/iconData.ts +0 -31
  327. package/src/icons/index.ts +0 -26
  328. package/src/icons/inlineIconMarker.ts +0 -73
  329. package/src/icons/resolve.ts +0 -139
  330. package/src/imageEdit/ImageEditVersionManager.ts +0 -73
  331. package/src/imageEdit/export.ts +0 -410
  332. package/src/imageEdit/index.ts +0 -72
  333. package/src/imageEdit/persistence.ts +0 -113
  334. package/src/imageEdit/state.ts +0 -112
  335. package/src/imageEdit/versionPaths.ts +0 -44
  336. package/src/imageEdit/versions.ts +0 -152
  337. package/src/index.ts +0 -15
  338. package/src/internal/immutable.ts +0 -58
  339. package/src/jsonForm/chooseControl.ts +0 -88
  340. package/src/jsonForm/evaluateWhen.ts +0 -59
  341. package/src/jsonForm/index.ts +0 -32
  342. package/src/jsonForm/inferSchema.ts +0 -25
  343. package/src/jsonForm/pointer.ts +0 -154
  344. package/src/jsonForm/tokens.ts +0 -78
  345. package/src/jsonForm/types.ts +0 -167
  346. package/src/markdown/annotationCoercion.ts +0 -295
  347. package/src/markdown/attrTokens.ts +0 -243
  348. package/src/markdown/convert.ts +0 -1353
  349. package/src/markdown/htmlParse.ts +0 -212
  350. package/src/markdown/index.ts +0 -152
  351. package/src/markdown/parse.ts +0 -103
  352. package/src/markdown/sanitize.ts +0 -318
  353. package/src/markdown/stringify.ts +0 -207
  354. package/src/markdown/types.ts +0 -710
  355. package/src/markdown/utils.ts +0 -459
  356. package/src/narration/align.ts +0 -514
  357. package/src/narration/features.ts +0 -231
  358. package/src/narration/index.ts +0 -86
  359. package/src/narration/nuclei.ts +0 -118
  360. package/src/narration/pacing.ts +0 -211
  361. package/src/narration/script.ts +0 -239
  362. package/src/narration/session.ts +0 -100
  363. package/src/narration/sidecar.ts +0 -187
  364. package/src/narration/syllables.ts +0 -85
  365. package/src/narration/trace.ts +0 -50
  366. package/src/narration/types.ts +0 -299
  367. package/src/narration/vad.ts +0 -131
  368. package/src/ngeohash.d.ts +0 -11
  369. package/src/random/SeededRandom.ts +0 -127
  370. package/src/random/index.ts +0 -1
  371. package/src/recommend/index.ts +0 -16
  372. package/src/recommend/numberHighlight.ts +0 -25
  373. package/src/recommend/templates.ts +0 -393
  374. package/src/schemas/BlockTemplates.ts +0 -1046
  375. package/src/schemas/CustomTemplates.ts +0 -126
  376. package/src/schemas/Doc.ts +0 -1052
  377. package/src/schemas/ImageEditDoc.ts +0 -102
  378. package/src/schemas/LayoutStrategy.ts +0 -178
  379. package/src/schemas/Media.ts +0 -179
  380. package/src/schemas/MediaProvider.ts +0 -70
  381. package/src/schemas/Theme.ts +0 -406
  382. package/src/schemas/Transitions.ts +0 -224
  383. package/src/schemas/Types.ts +0 -15
  384. package/src/schemas/Viewport.ts +0 -91
  385. package/src/schemas/colorUtils.ts +0 -219
  386. package/src/schemas/fontStacks.ts +0 -339
  387. package/src/schemas/index.ts +0 -29
  388. package/src/schemas/themeCompile.ts +0 -237
  389. package/src/schemas/themeConstants.ts +0 -2
  390. package/src/schemas/themeLibrary.ts +0 -60
  391. package/src/schemas/themeValidator.ts +0 -426
  392. package/src/schemas/themes/bold.json +0 -48
  393. package/src/schemas/themes/cinematic.json +0 -111
  394. package/src/schemas/themes/documentary.json +0 -96
  395. package/src/schemas/themes/gezellig.json +0 -93
  396. package/src/schemas/themes/index.ts +0 -53
  397. package/src/schemas/themes/magazine.json +0 -89
  398. package/src/schemas/themes/minimalist.json +0 -45
  399. package/src/schemas/themes/morning-light.json +0 -85
  400. package/src/schemas/themes/standard-dark.json +0 -85
  401. package/src/schemas/themes/standard.json +0 -74
  402. package/src/schemas/themes/tech-dark.json +0 -101
  403. package/src/schemas/themes/warm-earth.json +0 -50
  404. package/src/spatial/Geohash.ts +0 -196
  405. package/src/spatial/Haversine.ts +0 -59
  406. package/src/spatial/index.ts +0 -2
  407. package/src/storage/ContentContainer.ts +0 -220
  408. package/src/storage/LocalForageAdapter.ts +0 -103
  409. package/src/storage/LocalStorageAdapter.ts +0 -57
  410. package/src/storage/MediaProviderFromContainer.ts +0 -92
  411. package/src/storage/MemoryStorageAdapter.ts +0 -37
  412. package/src/storage/ScopedContentContainer.ts +0 -143
  413. package/src/storage/Storage.ts +0 -28
  414. package/src/storage/index.ts +0 -9
  415. package/src/timing/index.ts +0 -17
  416. package/src/timing/narrationTiming.ts +0 -220
  417. package/src/timing/readingTime.ts +0 -94
  418. package/src/transform/applyTransform.ts +0 -122
  419. package/src/transform/blockAnalyzer.ts +0 -181
  420. package/src/transform/index.ts +0 -23
  421. package/src/transform/registry.ts +0 -198
  422. package/src/transform/styles/dataDriven.ts +0 -17
  423. package/src/transform/styles/documentary.ts +0 -17
  424. package/src/transform/styles/index.ts +0 -5
  425. package/src/transform/styles/magazine.ts +0 -18
  426. package/src/transform/styles/minimal.ts +0 -17
  427. package/src/transform/styles/narrative.ts +0 -18
  428. package/src/transform/templateSelector.ts +0 -389
  429. package/src/transform/timingAllocator.ts +0 -257
  430. package/src/transform/types.ts +0 -151
  431. package/src/versions/DocumentVersionManager.ts +0 -70
  432. package/src/versions/gitignore.ts +0 -34
  433. package/src/versions/index.ts +0 -56
  434. package/src/versions/operations.ts +0 -144
  435. package/src/versions/paths.ts +0 -51
  436. package/src/versions/snapshotStore.ts +0 -202
  437. package/src/versions/timestamp.ts +0 -48
  438. package/src/versions/types.ts +0 -93
@@ -1,92 +0,0 @@
1
- /**
2
- * MediaProviderFromContainer — bridges ContentContainer to MediaProvider.
3
- *
4
- * Creates a MediaProvider that resolves relative paths by reading binary data
5
- * from a ContentContainer and generating blob URLs. Blob URLs are cached and
6
- * revoked on dispose().
7
- *
8
- * This allows any ContentContainer (memory, slot-backed, zip-loaded) to be
9
- * used with existing rendering components (DocPlayer, ImageLayer, VideoLayer)
10
- * that consume MediaProvider.
11
- */
12
-
13
- import type { MediaProvider, MediaEntry } from '../schemas/MediaProvider.js';
14
- import type { ContentContainer } from './ContentContainer.js';
15
-
16
- /**
17
- * Create a MediaProvider backed by a ContentContainer.
18
- *
19
- * @param container — The ContentContainer to read/write media from
20
- * @returns A MediaProvider that resolves paths to blob URLs
21
- */
22
- export function createMediaProviderFromContainer(container: ContentContainer): MediaProvider {
23
- const blobUrlCache = new Map<string, string>();
24
-
25
- return {
26
- async resolveUrl(relativePath: string): Promise<string> {
27
- const cached = blobUrlCache.get(relativePath);
28
- if (cached) return cached;
29
-
30
- const data = await container.readFile(relativePath);
31
- if (!data) return relativePath;
32
-
33
- const entries = await container.listFiles();
34
- const entry = entries.find((e) => e.path === relativePath);
35
- const mimeType = entry?.mimeType ?? 'application/octet-stream';
36
-
37
- const blob = new Blob([data], { type: mimeType });
38
- const url = URL.createObjectURL(blob);
39
- blobUrlCache.set(relativePath, url);
40
- return url;
41
- },
42
-
43
- async listMedia(): Promise<MediaEntry[]> {
44
- const entries = await container.listFiles();
45
- return entries
46
- .filter((e) => !e.path.toLowerCase().endsWith('.md'))
47
- .map((e) => ({
48
- name: e.path,
49
- mimeType: e.mimeType,
50
- size: e.size,
51
- }));
52
- },
53
-
54
- async addMedia(
55
- name: string,
56
- data: ArrayBuffer | Blob | Uint8Array,
57
- mimeType: string,
58
- ): Promise<string> {
59
- // Invalidate any cached blob URL for this path before overwriting
60
- const cached = blobUrlCache.get(name);
61
- if (cached) {
62
- URL.revokeObjectURL(cached);
63
- blobUrlCache.delete(name);
64
- }
65
-
66
- let buffer: ArrayBuffer | Uint8Array;
67
- if (data instanceof Blob) {
68
- buffer = await data.arrayBuffer();
69
- } else {
70
- buffer = data;
71
- }
72
- await container.writeFile(name, buffer, mimeType);
73
- return name;
74
- },
75
-
76
- async removeMedia(relativePath: string): Promise<void> {
77
- const cached = blobUrlCache.get(relativePath);
78
- if (cached) {
79
- URL.revokeObjectURL(cached);
80
- blobUrlCache.delete(relativePath);
81
- }
82
- await container.removeFile(relativePath);
83
- },
84
-
85
- dispose(): void {
86
- for (const url of blobUrlCache.values()) {
87
- URL.revokeObjectURL(url);
88
- }
89
- blobUrlCache.clear();
90
- },
91
- };
92
- }
@@ -1,37 +0,0 @@
1
- /**
2
- * In-memory storage adapter for testing and SSR environments.
3
- * Data does not persist across page reloads.
4
- */
5
-
6
- import type { StorageAdapter } from './Storage.js';
7
-
8
- export class MemoryStorageAdapter implements StorageAdapter {
9
- readonly supportsEnumeration = true;
10
- private store = new Map<string, string>();
11
-
12
- async get<T>(key: string): Promise<T | null> {
13
- const val = this.store.get(key);
14
- if (val === undefined) return null;
15
- try {
16
- return JSON.parse(val) as T;
17
- } catch {
18
- return null;
19
- }
20
- }
21
-
22
- async set<T>(key: string, value: T): Promise<void> {
23
- this.store.set(key, JSON.stringify(value));
24
- }
25
-
26
- async remove(key: string): Promise<void> {
27
- this.store.delete(key);
28
- }
29
-
30
- async clear(): Promise<void> {
31
- this.store.clear();
32
- }
33
-
34
- async keys(): Promise<string[]> {
35
- return Array.from(this.store.keys());
36
- }
37
- }
@@ -1,143 +0,0 @@
1
- /**
2
- * ScopedContentContainer
3
- *
4
- * Wraps a parent {@link ContentContainer} and prefixes every path with a
5
- * fixed subfolder, presenting that subfolder as the root. Useful for
6
- * sidecar folders (e.g. `<imagebasename>_files/`) where a component
7
- * should be able to read/write/list files relative to its own root
8
- * without knowing where it lives in the parent tree.
9
- *
10
- * Scopes nest: `scopeContainer(scopeContainer(parent, 'a'), 'b')` is
11
- * equivalent to `scopeContainer(parent, 'a/b')`.
12
- *
13
- * `getDocumentPath()` always returns `null` for scoped sidecars — they
14
- * are not document roots.
15
- */
16
-
17
- import type { ContentContainer, ContentEntry } from './ContentContainer.js';
18
-
19
- interface NormalizePathOptions {
20
- allowEmpty?: boolean;
21
- preserveTrailingSlash?: boolean;
22
- }
23
-
24
- /**
25
- * Normalize a container-relative path without ever resolving traversal.
26
- * Backslashes are rejected rather than translated because a filesystem-backed
27
- * parent may interpret them as separators even when an in-memory parent does
28
- * not. Dot segments are similarly rejected instead of collapsed so an invalid
29
- * caller path can never escape after a later platform-specific normalization.
30
- */
31
- function normalizeRelativePath(
32
- path: string,
33
- label: 'prefix' | 'path',
34
- options: NormalizePathOptions = {},
35
- ): string {
36
- const original = path;
37
- let normalized = label === 'prefix' ? path.trim() : path;
38
- if (normalized.includes('\\')) {
39
- throw new Error(`ScopedContentContainer: ${label} must use forward slashes: ${original}`);
40
- }
41
-
42
- const hadTrailingSlash = normalized.endsWith('/');
43
- normalized = normalized.replace(/^\/+|\/+$/g, '');
44
- const segments = normalized === '' ? [] : normalized.split('/').filter(Boolean);
45
- if (segments.some((segment) => segment === '.' || segment === '..')) {
46
- throw new Error(
47
- `ScopedContentContainer: ${label} must not contain '.' or '..' segments: ${original}`,
48
- );
49
- }
50
- if (segments.length === 0 && !options.allowEmpty) {
51
- throw new Error(`ScopedContentContainer: ${label} must not be empty`);
52
- }
53
-
54
- const result = segments.join('/');
55
- return options.preserveTrailingSlash && hadTrailingSlash && result ? `${result}/` : result;
56
- }
57
-
58
- /** Normalize a prefix: strip leading/trailing slashes, ensure no `..` segments. */
59
- function normalizePrefix(prefix: string): string {
60
- return normalizeRelativePath(prefix, 'prefix');
61
- }
62
-
63
- /**
64
- * A ContentContainer view rooted at a subfolder of a parent container.
65
- * All paths passed to / returned from this container are relative to
66
- * the subfolder; the parent never sees an unprefixed path.
67
- */
68
- export class ScopedContentContainer implements ContentContainer {
69
- private readonly parent: ContentContainer;
70
- /** Prefix without trailing slash. */
71
- readonly prefix: string;
72
- /** Prefix with trailing slash. */
73
- private readonly prefixSlash: string;
74
-
75
- constructor(parent: ContentContainer, prefix: string) {
76
- this.parent = parent;
77
- this.prefix = normalizePrefix(prefix);
78
- this.prefixSlash = `${this.prefix}/`;
79
- }
80
-
81
- private toParent(path: string, options: NormalizePathOptions = {}): string {
82
- const normalized = normalizeRelativePath(path, 'path', options);
83
- return this.prefixSlash + normalized;
84
- }
85
-
86
- /** Strip the prefix from a parent-space path. Returns null if the path is outside the scope. */
87
- private fromParent(parentPath: string): string | null {
88
- if (!parentPath.startsWith(this.prefixSlash)) return null;
89
- return parentPath.slice(this.prefixSlash.length);
90
- }
91
-
92
- readFile(path: string): Promise<ArrayBuffer | null> {
93
- return this.parent.readFile(this.toParent(path));
94
- }
95
-
96
- writeFile(path: string, data: ArrayBuffer | Uint8Array, mimeType?: string): Promise<void> {
97
- return this.parent.writeFile(this.toParent(path), data, mimeType);
98
- }
99
-
100
- removeFile(path: string): Promise<void> {
101
- return this.parent.removeFile(this.toParent(path));
102
- }
103
-
104
- async listFiles(prefix?: string): Promise<ContentEntry[]> {
105
- const parentPrefix =
106
- prefix == null
107
- ? this.prefixSlash
108
- : this.toParent(prefix, { allowEmpty: true, preserveTrailingSlash: true });
109
- const entries = await this.parent.listFiles(parentPrefix);
110
- const out: ContentEntry[] = [];
111
- for (const e of entries) {
112
- const local = this.fromParent(e.path);
113
- if (local === null) continue;
114
- out.push({ path: local, mimeType: e.mimeType, size: e.size });
115
- }
116
- return out;
117
- }
118
-
119
- exists(path: string): Promise<boolean> {
120
- return this.parent.exists(this.toParent(path));
121
- }
122
-
123
- /** Sidecars are not document roots. */
124
- async getDocumentPath(): Promise<string | null> {
125
- return null;
126
- }
127
-
128
- async readDocument(): Promise<string | null> {
129
- return null;
130
- }
131
-
132
- async writeDocument(): Promise<void> {
133
- throw new Error(
134
- 'ScopedContentContainer is a sidecar view and does not support writeDocument(). ' +
135
- 'Write to a specific path with writeFile() instead.',
136
- );
137
- }
138
- }
139
-
140
- /** Factory: convenience wrapper for `new ScopedContentContainer(parent, prefix)`. */
141
- export function scopeContainer(parent: ContentContainer, prefix: string): ScopedContentContainer {
142
- return new ScopedContentContainer(parent, prefix);
143
- }
@@ -1,28 +0,0 @@
1
- /**
2
- * Storage - Abstract persistence interface
3
- *
4
- * Defines the contract for persistent storage across different environments.
5
- * All values are JSON-serialized, so any serializable value can be stored.
6
- * Keys can be automatically namespaced with a configurable prefix.
7
- */
8
-
9
- /** Storage adapter interface - implemented by environment-specific adapters */
10
- export interface StorageAdapter {
11
- /** Get a value by key, returns null if not found */
12
- get<T>(key: string): Promise<T | null>;
13
-
14
- /** Set a value for a key */
15
- set<T>(key: string, value: T): Promise<void>;
16
-
17
- /** Remove a value by key */
18
- remove(key: string): Promise<void>;
19
-
20
- /** Clear all stored values (within our namespace) */
21
- clear(): Promise<void>;
22
-
23
- /** Get all keys (within our namespace) */
24
- keys(): Promise<string[]>;
25
-
26
- /** Check if this adapter supports enumeration */
27
- readonly supportsEnumeration: boolean;
28
- }
@@ -1,9 +0,0 @@
1
- export type { StorageAdapter } from './Storage.js';
2
- export { MemoryStorageAdapter } from './MemoryStorageAdapter.js';
3
- export { LocalStorageAdapter } from './LocalStorageAdapter.js';
4
- export { LocalForageAdapter } from './LocalForageAdapter.js';
5
- export type { LocalForageAdapterOptions } from './LocalForageAdapter.js';
6
- export type { ContentContainer, ContentEntry } from './ContentContainer.js';
7
- export { MemoryContentContainer, findDocumentPath } from './ContentContainer.js';
8
- export { ScopedContentContainer, scopeContainer } from './ScopedContentContainer.js';
9
- export { createMediaProviderFromContainer } from './MediaProviderFromContainer.js';
@@ -1,17 +0,0 @@
1
- export {
2
- DEFAULT_WORDS_PER_SECOND,
3
- estimateSpokenWordCount,
4
- countSpokenWords,
5
- estimateTimeFromText,
6
- calculatePrefixDuration,
7
- estimateNarrationDuration,
8
- } from './narrationTiming.js';
9
-
10
- export { estimateReadingTime, estimateNarrationTime } from './readingTime.js';
11
-
12
- export type {
13
- ReadingTimeEstimate,
14
- ReadingTimeOptions,
15
- NarrationTimeEstimate,
16
- NarrationTimeOptions,
17
- } from './readingTime.js';
@@ -1,220 +0,0 @@
1
- /**
2
- * Narration timing estimation.
3
- *
4
- * Estimates how long text takes to speak aloud, accounting for:
5
- * - Numbers spoken as multiple words (e.g., "1910" → "nineteen ten")
6
- * - Pauses at commas
7
- * - Year pronunciation conventions (1000–2099)
8
- *
9
- * Ported from qualla-internal's AudioTiming.ts (pure functions, no Node.js deps).
10
- */
11
-
12
- /** Numbers are spoken more slowly than regular words (1.3× multiplier). */
13
- const NUMBER_SPEAKING_MULTIPLIER = 1.3;
14
-
15
- /** Comma pause in "word equivalents" — speakers pause ~0.3 words at commas. */
16
- const COMMA_PAUSE_PENALTY = 0.3;
17
-
18
- /** Default speaking rate in words per second (~150 WPM). */
19
- export const DEFAULT_WORDS_PER_SECOND = 2.5;
20
-
21
- /**
22
- * Estimate how many "spoken word equivalents" a single token represents.
23
- * Numbers get expanded (e.g., "175,000" → ~5 words × 1.3 multiplier).
24
- */
25
- export function estimateSpokenWordCount(token: string): number {
26
- const cleaned = token.replace(/,/g, '');
27
- const num = parseFloat(cleaned);
28
-
29
- if (isNaN(num) || !isFinite(num)) {
30
- return 1; // Not a number — count as 1 word
31
- }
32
-
33
- return estimateNumberWordCount(cleaned, num) * NUMBER_SPEAKING_MULTIPLIER;
34
- }
35
-
36
- /**
37
- * Raw word count for a number (before the speaking multiplier).
38
- */
39
- function estimateNumberWordCount(cleaned: string, num: number): number {
40
- // Handle decimals: "3.14" → words("3") + "point" + 2 digits
41
- if (cleaned.includes('.')) {
42
- const [whole, decimal] = cleaned.split('.');
43
- const wholeNum = parseFloat(whole) || 0;
44
- return estimateNumberWordCount(whole, wholeNum) + 1 + decimal.length;
45
- }
46
-
47
- const absNum = Math.abs(num);
48
- let words = num < 0 ? 1 : 0; // "negative" / "minus"
49
-
50
- if (absNum === 0) return 1; // "zero"
51
-
52
- // Years (1000–2099) are spoken as two two-digit groups:
53
- // "1910" → "nineteen ten", "2024" → "twenty twenty-four"
54
- if (absNum >= 1000 && absNum <= 2099 && Number.isInteger(absNum)) {
55
- const yearStr = absNum.toString();
56
- if (yearStr.length === 4) {
57
- const firstTwo = parseInt(yearStr.slice(0, 2));
58
- const lastTwo = parseInt(yearStr.slice(2));
59
-
60
- // First part
61
- if (firstTwo >= 10 && firstTwo <= 19) {
62
- words += 1;
63
- } else if (firstTwo >= 20 && firstTwo <= 99) {
64
- words += firstTwo % 10 === 0 ? 1 : 2;
65
- } else {
66
- words += 2; // "two thousand"
67
- }
68
-
69
- // Second part
70
- if (lastTwo === 0) {
71
- if (firstTwo >= 10 && firstTwo <= 99 && firstTwo !== 20) {
72
- words += 1; // "hundred"
73
- }
74
- } else if (lastTwo >= 1 && lastTwo <= 9) {
75
- words += 2; // "oh five"
76
- } else if (lastTwo >= 10 && lastTwo <= 19) {
77
- words += 1;
78
- } else {
79
- words += lastTwo % 10 === 0 ? 1 : 2;
80
- }
81
-
82
- return Math.max(words, 2);
83
- }
84
- }
85
-
86
- // General number handling — each magnitude group adds words
87
- let remaining = absNum;
88
-
89
- if (remaining >= 1_000_000_000) {
90
- const billions = Math.floor(remaining / 1_000_000_000);
91
- words += estimateNumberWordCount(String(billions), billions);
92
- words += 1; // "billion"
93
- remaining %= 1_000_000_000;
94
- }
95
-
96
- if (remaining >= 1_000_000) {
97
- const millions = Math.floor(remaining / 1_000_000);
98
- words += estimateNumberWordCount(String(millions), millions);
99
- words += 1; // "million"
100
- remaining %= 1_000_000;
101
- }
102
-
103
- if (remaining >= 1_000) {
104
- const thousands = Math.floor(remaining / 1_000);
105
- words += estimateNumberWordCount(String(thousands), thousands);
106
- words += 1; // "thousand"
107
- remaining %= 1_000;
108
- }
109
-
110
- if (remaining >= 100) {
111
- words += 2; // digit + "hundred"
112
- remaining %= 100;
113
- }
114
-
115
- if (remaining >= 1) {
116
- if (remaining >= 20) {
117
- words += remaining % 10 === 0 ? 1 : 2;
118
- } else {
119
- words += 1; // 1–19
120
- }
121
- }
122
-
123
- return Math.max(words, 1);
124
- }
125
-
126
- /**
127
- * Count "spoken word equivalents" in a block of text,
128
- * expanding numbers and adding comma pauses.
129
- */
130
- export function countSpokenWords(text: string): number {
131
- const tokens = text.split(/\s+/).filter((w) => w.length > 0);
132
- let count = 0;
133
-
134
- for (const token of tokens) {
135
- // Strip punctuation only at token boundaries so internal punctuation
136
- // (e.g., decimals like "3.14" or digit-grouping commas "1,000") is preserved.
137
- const stripped = token.replace(/^[.,!?;:'"()[\]{}]+|[.,!?;:'"()[\]{}]+$/g, '');
138
- count += estimateSpokenWordCount(stripped);
139
-
140
- // Count only punctuation commas for pauses: exclude digit-grouping commas
141
- // (i.e., commas with digits on both sides, like in "1,234").
142
- let punctuationCommaCount = 0;
143
- for (let i = 0; i < token.length; i++) {
144
- if (token[i] === ',') {
145
- const prev = i > 0 ? token[i - 1] : '';
146
- const next = i < token.length - 1 ? token[i + 1] : '';
147
- const prevIsDigit = prev >= '0' && prev <= '9';
148
- const nextIsDigit = next >= '0' && next <= '9';
149
- if (!(prevIsDigit && nextIsDigit)) {
150
- punctuationCommaCount++;
151
- }
152
- }
153
- }
154
- count += punctuationCommaCount * COMMA_PAUSE_PENALTY;
155
- }
156
-
157
- return count;
158
- }
159
-
160
- /**
161
- * Estimate audio time at a character offset using word-proportion mapping.
162
- *
163
- * Given the full source text and a character position, returns the
164
- * estimated time (in seconds) at which that position would be spoken.
165
- *
166
- * @param text - Full source text
167
- * @param charOffset - Character offset to estimate timing for
168
- * @param totalDuration - Total audio duration in seconds
169
- * @returns Estimated time in seconds
170
- */
171
- export function estimateTimeFromText(
172
- text: string,
173
- charOffset: number,
174
- totalDuration: number,
175
- ): number {
176
- const textBefore = text.slice(0, charOffset);
177
- const spokenWordsBefore = countSpokenWords(textBefore);
178
- const totalSpokenWords = countSpokenWords(text);
179
-
180
- if (totalSpokenWords === 0) return 0;
181
- return (spokenWordsBefore / totalSpokenWords) * totalDuration;
182
- }
183
-
184
- /**
185
- * Estimate how long a spoken prefix adds to audio duration.
186
- *
187
- * When audio includes a spoken title or header before the main content,
188
- * this calculates the extra duration to offset timing calculations.
189
- *
190
- * @param prefix - Prefix text (e.g., an article title spoken before the body)
191
- * @param wordsPerSecond - Speaking rate (default: 2.5)
192
- * @returns Estimated duration in seconds
193
- */
194
- export function calculatePrefixDuration(
195
- prefix: string,
196
- wordsPerSecond: number = DEFAULT_WORDS_PER_SECOND,
197
- ): number {
198
- if (!prefix) return 0;
199
-
200
- const words = prefix.split(/\s+/).filter((w) => w.length > 0);
201
- const newlineCount = (prefix.match(/\n\n/g) || []).length;
202
- const pauseTime = newlineCount * 0.5;
203
-
204
- return words.length / wordsPerSecond + pauseTime;
205
- }
206
-
207
- /**
208
- * Estimate narration duration for a block of text.
209
- *
210
- * @param text - The text to estimate
211
- * @param wordsPerSecond - Speaking rate (default: 2.5, i.e. ~150 WPM)
212
- * @returns Duration in seconds
213
- */
214
- export function estimateNarrationDuration(
215
- text: string,
216
- wordsPerSecond: number = DEFAULT_WORDS_PER_SECOND,
217
- ): number {
218
- const spokenWords = countSpokenWords(text);
219
- return spokenWords / wordsPerSecond;
220
- }
@@ -1,94 +0,0 @@
1
- /**
2
- * Reading time estimation.
3
- *
4
- * Estimates how long it takes to read text silently vs. narrate it aloud.
5
- * Uses configurable words-per-minute rates.
6
- */
7
-
8
- import { countSpokenWords, DEFAULT_WORDS_PER_SECOND } from './narrationTiming.js';
9
-
10
- /** Default silent reading rate (adults average ~200–250 WPM). */
11
- const DEFAULT_READING_WPM = 200;
12
-
13
- /** Result of a reading-time estimate. */
14
- export interface ReadingTimeEstimate {
15
- /** Number of words (plain word count, not spoken equivalents). */
16
- words: number;
17
- /** Estimated minutes (decimal). */
18
- minutes: number;
19
- /** Estimated seconds (rounded). */
20
- seconds: number;
21
- }
22
-
23
- /** Options for reading-time estimation. */
24
- export interface ReadingTimeOptions {
25
- /** Words per minute for silent reading (default: 200). */
26
- wordsPerMinute?: number;
27
- }
28
-
29
- /**
30
- * Estimate silent reading time for a block of text.
31
- *
32
- * @param text - The text to estimate
33
- * @param options - Optional configuration
34
- * @returns Word count + time estimate
35
- */
36
- export function estimateReadingTime(
37
- text: string,
38
- options?: ReadingTimeOptions,
39
- ): ReadingTimeEstimate {
40
- const configuredWpm = options?.wordsPerMinute;
41
- const wpm =
42
- typeof configuredWpm === 'number' && configuredWpm > 0 ? configuredWpm : DEFAULT_READING_WPM;
43
- const words = text.split(/\s+/).filter((w) => w.length > 0).length;
44
- const minutes = words / wpm;
45
-
46
- return {
47
- words,
48
- minutes,
49
- seconds: Math.round(minutes * 60),
50
- };
51
- }
52
-
53
- /** Result of a narration-time estimate. */
54
- export interface NarrationTimeEstimate {
55
- /** Spoken word equivalents (numbers expanded, comma pauses added). */
56
- spokenWords: number;
57
- /** Estimated minutes (decimal). */
58
- minutes: number;
59
- /** Estimated seconds (rounded). */
60
- seconds: number;
61
- }
62
-
63
- /** Options for narration-time estimation. */
64
- export interface NarrationTimeOptions {
65
- /** Words per second for narration (default: 2.5 ≈ 150 WPM). */
66
- wordsPerSecond?: number;
67
- }
68
-
69
- /**
70
- * Estimate narration (spoken) time for a block of text.
71
- *
72
- * Unlike silent reading, this accounts for numbers being spoken as
73
- * multiple words and pauses at commas.
74
- *
75
- * @param text - The text to estimate
76
- * @param options - Optional configuration
77
- * @returns Spoken word equivalents + time estimate
78
- */
79
- export function estimateNarrationTime(
80
- text: string,
81
- options?: NarrationTimeOptions,
82
- ): NarrationTimeEstimate {
83
- const providedWps = options?.wordsPerSecond;
84
- const wps =
85
- typeof providedWps === 'number' && providedWps > 0 ? providedWps : DEFAULT_WORDS_PER_SECOND;
86
- const spokenWords = countSpokenWords(text);
87
- const totalSeconds = spokenWords / wps;
88
-
89
- return {
90
- spokenWords,
91
- minutes: totalSeconds / 60,
92
- seconds: Math.round(totalSeconds),
93
- };
94
- }