@bendyline/squisq 1.4.0 → 1.5.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 (782) hide show
  1. package/dist/{Doc-BeSeH2iX.d.ts → Doc-BsMkmzH8.d.ts} +838 -268
  2. package/dist/{ImageEditDoc-BTIvw0oq.d.ts → ImageEditDoc-DvoeHMP9.d.ts} +11 -4
  3. package/dist/{chunk-ZTX4PFFT.js → chunk-2OIBZYKP.js} +75 -2
  4. package/dist/chunk-2OIBZYKP.js.map +1 -0
  5. package/dist/chunk-2UQOHYE2.js +45 -0
  6. package/dist/chunk-2UQOHYE2.js.map +1 -0
  7. package/dist/{chunk-B4EEON3N.js → chunk-4AKUQPEE.js} +536 -103
  8. package/dist/chunk-4AKUQPEE.js.map +1 -0
  9. package/dist/chunk-4ZFRZBU2.js +6582 -0
  10. package/dist/chunk-4ZFRZBU2.js.map +1 -0
  11. package/dist/{chunk-57CVQCFX.js → chunk-7MQGNR76.js} +79 -3
  12. package/dist/chunk-7MQGNR76.js.map +1 -0
  13. package/dist/{chunk-5WFRKURX.js → chunk-DLXZMS5K.js} +4 -2
  14. package/dist/chunk-DLXZMS5K.js.map +1 -0
  15. package/dist/{chunk-MYIH7FWD.js → chunk-FBKP5CAO.js} +1 -1
  16. package/dist/chunk-FBKP5CAO.js.map +1 -0
  17. package/dist/chunk-KZNXZ5SM.js +333 -0
  18. package/dist/chunk-KZNXZ5SM.js.map +1 -0
  19. package/dist/{chunk-WMOI7FN3.js → chunk-LRCV7N7F.js} +12 -2
  20. package/dist/{chunk-WMOI7FN3.js.map → chunk-LRCV7N7F.js.map} +1 -1
  21. package/dist/{chunk-3K5OG6KI.js → chunk-OH43RPTP.js} +403 -187
  22. package/dist/chunk-OH43RPTP.js.map +1 -0
  23. package/dist/{chunk-H3AXU4MJ.js → chunk-OKJOQXK4.js} +149 -2
  24. package/dist/chunk-OKJOQXK4.js.map +1 -0
  25. package/dist/chunk-PGGGKYWG.js +1 -0
  26. package/dist/chunk-PGGGKYWG.js.map +1 -0
  27. package/dist/{chunk-7UDSRZKG.js → chunk-Q3ROPT5H.js} +35 -14
  28. package/dist/chunk-Q3ROPT5H.js.map +1 -0
  29. package/dist/chunk-QE7TWGVT.js +178 -0
  30. package/dist/chunk-QE7TWGVT.js.map +1 -0
  31. package/dist/chunk-RUDYOTA6.js +345 -0
  32. package/dist/chunk-RUDYOTA6.js.map +1 -0
  33. package/dist/chunk-TVSGLUID.js +596 -0
  34. package/dist/chunk-TVSGLUID.js.map +1 -0
  35. package/dist/chunk-ZLQKNOZQ.js +1 -0
  36. package/dist/chunk-ZLQKNOZQ.js.map +1 -0
  37. package/dist/doc/index.d.ts +5 -10
  38. package/dist/doc/index.js +263 -7
  39. package/dist/doc/index.js.map +1 -1
  40. package/dist/generate/index.d.ts +106 -7
  41. package/dist/generate/index.js +16 -3
  42. package/dist/generate/index.js.map +1 -1
  43. package/dist/icons/index.d.ts +62 -10
  44. package/dist/icons/index.js +29 -9
  45. package/dist/icons/index.js.map +1 -1
  46. package/dist/icons/inlineIconMarker.d.ts +1 -0
  47. package/dist/icons/inlineIconMarker.js +15 -0
  48. package/dist/icons/inlineIconMarker.js.map +1 -0
  49. package/dist/imageEdit/index.d.ts +219 -11
  50. package/dist/imageEdit/index.js +56 -21
  51. package/dist/imageEdit/index.js.map +1 -1
  52. package/dist/index.d.ts +24 -13
  53. package/dist/index.js +680 -12
  54. package/dist/index.js.map +1 -1
  55. package/dist/inlineIconMarker-CiE8Hlvz.d.ts +59 -0
  56. package/dist/jsonForm/index.d.ts +189 -12
  57. package/dist/jsonForm/index.js +26 -11
  58. package/dist/jsonForm/index.js.map +1 -1
  59. package/dist/markdown/index.d.ts +474 -19
  60. package/dist/markdown/index.js +72 -33
  61. package/dist/markdown/index.js.map +1 -1
  62. package/dist/random/index.d.ts +51 -2
  63. package/dist/random/index.js +9 -1
  64. package/dist/random/index.js.map +1 -1
  65. package/dist/recommend/index.d.ts +39 -13
  66. package/dist/recommend/index.js +10 -14
  67. package/dist/recommend/index.js.map +1 -1
  68. package/dist/schemas/index.d.ts +208 -15
  69. package/dist/schemas/index.js +150 -11
  70. package/dist/schemas/index.js.map +1 -1
  71. package/dist/spatial/index.d.ts +116 -3
  72. package/dist/spatial/index.js +24 -2
  73. package/dist/spatial/index.js.map +1 -1
  74. package/dist/storage/index.d.ts +159 -10
  75. package/dist/storage/index.js +20 -6
  76. package/dist/storage/index.js.map +1 -1
  77. package/dist/story/index.d.ts +906 -40
  78. package/dist/story/index.js +124 -6
  79. package/dist/{themeLibrary-BHjJ0Qx6.d.ts → themeLibrary-DQQKuRMx.d.ts} +1 -1
  80. package/dist/timing/index.d.ts +109 -4
  81. package/dist/timing/index.js +23 -2
  82. package/dist/timing/index.js.map +1 -1
  83. package/dist/transform/index.d.ts +213 -6
  84. package/dist/transform/index.js +26 -3
  85. package/dist/transform/index.js.map +1 -1
  86. package/dist/{types-BdZkdJ3z.d.ts → types-DlAZ7MW4.d.ts} +115 -1
  87. package/dist/versions/index.d.ts +123 -24
  88. package/dist/versions/index.js +34 -27
  89. package/dist/versions/index.js.map +1 -1
  90. package/package.json +6 -1
  91. package/src/__tests__/animationUtils.test.ts +40 -0
  92. package/src/__tests__/annotationCoercion.test.ts +243 -0
  93. package/src/__tests__/applyRenderStyle.test.ts +146 -0
  94. package/src/__tests__/atmosphereLayers.test.ts +108 -0
  95. package/src/__tests__/attrTokens.test.ts +162 -0
  96. package/src/__tests__/customTemplateSample.test.ts +83 -0
  97. package/src/__tests__/customTemplatesFrontmatter.test.ts +205 -0
  98. package/src/__tests__/customThemesFrontmatter.test.ts +118 -0
  99. package/src/__tests__/diagramBlock.test.ts +122 -0
  100. package/src/__tests__/diagramLayout.test.ts +134 -0
  101. package/src/__tests__/drawing.test.ts +109 -0
  102. package/src/__tests__/drawingBlock.test.ts +124 -0
  103. package/src/__tests__/drawingLayout.test.ts +171 -0
  104. package/src/__tests__/geohash.test.ts +6 -5
  105. package/src/__tests__/getLayers.test.ts +6 -2
  106. package/src/__tests__/getLayersFallback.test.ts +103 -0
  107. package/src/__tests__/imageEditExportSvg.test.ts +70 -0
  108. package/src/__tests__/imageEditVersions.test.ts +72 -0
  109. package/src/__tests__/inlineIconMarker.test.ts +36 -0
  110. package/src/__tests__/layoutBlock.test.ts +83 -0
  111. package/src/__tests__/layoutLayout.test.ts +169 -0
  112. package/src/__tests__/markdown.test.ts +23 -0
  113. package/src/__tests__/markdownSanitize.test.ts +64 -0
  114. package/src/__tests__/markdownToDoc.test.ts +223 -2
  115. package/src/__tests__/mediaAnnotations.test.ts +64 -0
  116. package/src/__tests__/mediaSchedule.test.ts +118 -0
  117. package/src/__tests__/pandocAttrParse.test.ts +187 -0
  118. package/src/__tests__/resolveDocTheme.test.ts +55 -0
  119. package/src/__tests__/rootExports.test.ts +43 -0
  120. package/src/__tests__/shapeGeometry.test.ts +89 -0
  121. package/src/__tests__/shapeVocabulary.test.ts +133 -0
  122. package/src/__tests__/structuredData.test.ts +179 -0
  123. package/src/__tests__/templateAnnotationParse.test.ts +108 -0
  124. package/src/__tests__/templateMetadata.test.ts +21 -0
  125. package/src/__tests__/templates.test.ts +145 -4
  126. package/src/__tests__/themeCompile.test.ts +42 -0
  127. package/src/__tests__/themeValidator.test.ts +6 -0
  128. package/src/__tests__/transformV2.test.ts +137 -0
  129. package/src/__tests__/transitionNormalize.test.ts +61 -0
  130. package/src/__tests__/validateDoc.test.ts +100 -0
  131. package/src/doc/customTemplatesFrontmatter.ts +308 -0
  132. package/src/doc/customThemesFrontmatter.ts +90 -0
  133. package/src/doc/docToMarkdown.ts +73 -4
  134. package/src/doc/getLayers.ts +40 -17
  135. package/src/doc/index.ts +35 -1
  136. package/src/doc/markdownToDoc.ts +333 -12
  137. package/src/doc/mediaAnnotations.ts +118 -0
  138. package/src/doc/resolveDocTheme.ts +55 -0
  139. package/src/doc/structuredData.ts +230 -0
  140. package/src/doc/templateInputs.ts +240 -0
  141. package/src/doc/templates/__tests__/customTemplate.test.ts +151 -0
  142. package/src/doc/templates/__tests__/customTemplateRegistry.test.ts +110 -0
  143. package/src/doc/templates/accentImage.ts +30 -6
  144. package/src/doc/templates/captionUtils.ts +23 -0
  145. package/src/doc/templates/comparisonBar.ts +26 -18
  146. package/src/doc/templates/coverBlock.ts +7 -4
  147. package/src/doc/templates/customTemplate.ts +45 -0
  148. package/src/doc/templates/dataTable.ts +37 -19
  149. package/src/doc/templates/dateEvent.ts +41 -20
  150. package/src/doc/templates/definitionCard.ts +26 -18
  151. package/src/doc/templates/diagramBlock.ts +204 -0
  152. package/src/doc/templates/diagramLayout.ts +159 -0
  153. package/src/doc/templates/drawingBlock.ts +325 -0
  154. package/src/doc/templates/drawingLayout.ts +539 -0
  155. package/src/doc/templates/factCard.ts +51 -25
  156. package/src/doc/templates/fallbackBlock.ts +123 -0
  157. package/src/doc/templates/featureBlock.ts +20 -13
  158. package/src/doc/templates/fullBleedQuote.ts +18 -8
  159. package/src/doc/templates/imageWithCaption.ts +22 -9
  160. package/src/doc/templates/index.ts +215 -46
  161. package/src/doc/templates/layoutBlock.ts +43 -0
  162. package/src/doc/templates/layoutLayout.ts +243 -0
  163. package/src/doc/templates/listBlock.ts +56 -30
  164. package/src/doc/templates/mapBlock.ts +15 -12
  165. package/src/doc/templates/metadata.ts +120 -0
  166. package/src/doc/templates/persistentLayers.ts +129 -11
  167. package/src/doc/templates/photoGrid.ts +23 -12
  168. package/src/doc/templates/pullQuote.ts +30 -12
  169. package/src/doc/templates/quoteBlock.ts +54 -29
  170. package/src/doc/templates/sectionHeader.ts +25 -11
  171. package/src/doc/templates/statHighlight.ts +39 -22
  172. package/src/doc/templates/titleBlock.ts +59 -21
  173. package/src/doc/templates/tokens/__tests__/resolveTokens.test.ts +221 -0
  174. package/src/doc/templates/tokens/resolveTokens.ts +0 -0
  175. package/src/doc/templates/twoColumn.ts +48 -30
  176. package/src/doc/templates/videoPullQuote.ts +22 -12
  177. package/src/doc/templates/videoWithCaption.ts +13 -8
  178. package/src/doc/utils/animationUtils.ts +267 -3
  179. package/src/doc/utils/applyRenderStyle.ts +113 -0
  180. package/src/doc/utils/imageTreatment.ts +70 -0
  181. package/src/doc/utils/shapeGeometry.ts +464 -0
  182. package/src/doc/utils/themeUtils.ts +75 -1
  183. package/src/doc/validate.ts +476 -0
  184. package/src/generate/slideshowGenerator.ts +7 -0
  185. package/src/icons/index.ts +8 -0
  186. package/src/icons/inlineIconMarker.ts +73 -0
  187. package/src/imageEdit/export.ts +85 -2
  188. package/src/imageEdit/index.ts +1 -0
  189. package/src/imageEdit/persistence.ts +51 -0
  190. package/src/index.ts +2 -0
  191. package/src/markdown/annotationCoercion.ts +295 -0
  192. package/src/markdown/attrTokens.ts +222 -0
  193. package/src/markdown/convert.ts +229 -26
  194. package/src/markdown/index.ts +36 -0
  195. package/src/markdown/sanitize.ts +298 -0
  196. package/src/markdown/stringify.ts +84 -3
  197. package/src/markdown/types.ts +66 -0
  198. package/src/markdown/utils.ts +49 -1
  199. package/src/recommend/templates.ts +24 -0
  200. package/src/schemas/BlockTemplates.ts +133 -4
  201. package/src/schemas/CustomTemplates.ts +74 -0
  202. package/src/schemas/Doc.ts +353 -29
  203. package/src/schemas/ImageEditDoc.ts +11 -4
  204. package/src/schemas/Media.ts +169 -0
  205. package/src/schemas/Theme.ts +23 -1
  206. package/src/schemas/Transitions.ts +224 -0
  207. package/src/schemas/colorUtils.ts +33 -0
  208. package/src/schemas/fontStacks.ts +5 -2
  209. package/src/schemas/index.ts +3 -0
  210. package/src/schemas/themeCompile.ts +23 -4
  211. package/src/schemas/themeValidator.ts +49 -11
  212. package/src/schemas/themes/cinematic.json +69 -12
  213. package/src/schemas/themes/documentary.json +58 -11
  214. package/src/schemas/themes/gezellig.json +60 -11
  215. package/src/schemas/themes/magazine.json +54 -9
  216. package/src/schemas/themes/morning-light.json +52 -9
  217. package/src/schemas/themes/standard-dark.json +48 -13
  218. package/src/schemas/themes/standard.json +44 -12
  219. package/src/schemas/themes/tech-dark.json +65 -12
  220. package/src/spatial/Geohash.ts +52 -21
  221. package/src/transform/applyTransform.ts +43 -4
  222. package/src/transform/index.ts +1 -0
  223. package/src/transform/registry.ts +44 -13
  224. package/src/transform/styles/dataDriven.ts +2 -1
  225. package/src/transform/styles/documentary.ts +2 -1
  226. package/src/transform/styles/magazine.ts +3 -1
  227. package/src/transform/styles/minimal.ts +2 -1
  228. package/src/transform/styles/narrative.ts +3 -1
  229. package/src/transform/templateSelector.ts +87 -11
  230. package/src/transform/types.ts +35 -2
  231. package/dist/__tests__/animationUtils.test.d.ts +0 -2
  232. package/dist/__tests__/animationUtils.test.d.ts.map +0 -1
  233. package/dist/__tests__/animationUtils.test.js +0 -60
  234. package/dist/__tests__/animationUtils.test.js.map +0 -1
  235. package/dist/__tests__/colorUtils.test.d.ts +0 -2
  236. package/dist/__tests__/colorUtils.test.d.ts.map +0 -1
  237. package/dist/__tests__/colorUtils.test.js +0 -94
  238. package/dist/__tests__/colorUtils.test.js.map +0 -1
  239. package/dist/__tests__/contentContainer.test.d.ts +0 -2
  240. package/dist/__tests__/contentContainer.test.d.ts.map +0 -1
  241. package/dist/__tests__/contentContainer.test.js +0 -234
  242. package/dist/__tests__/contentContainer.test.js.map +0 -1
  243. package/dist/__tests__/contentExtractor.test.d.ts +0 -2
  244. package/dist/__tests__/contentExtractor.test.d.ts.map +0 -1
  245. package/dist/__tests__/contentExtractor.test.js +0 -151
  246. package/dist/__tests__/contentExtractor.test.js.map +0 -1
  247. package/dist/__tests__/coverBlock.test.d.ts +0 -2
  248. package/dist/__tests__/coverBlock.test.d.ts.map +0 -1
  249. package/dist/__tests__/coverBlock.test.js +0 -197
  250. package/dist/__tests__/coverBlock.test.js.map +0 -1
  251. package/dist/__tests__/dataTable.test.d.ts +0 -2
  252. package/dist/__tests__/dataTable.test.d.ts.map +0 -1
  253. package/dist/__tests__/dataTable.test.js +0 -110
  254. package/dist/__tests__/dataTable.test.js.map +0 -1
  255. package/dist/__tests__/geohash.test.d.ts +0 -2
  256. package/dist/__tests__/geohash.test.d.ts.map +0 -1
  257. package/dist/__tests__/geohash.test.js +0 -87
  258. package/dist/__tests__/geohash.test.js.map +0 -1
  259. package/dist/__tests__/getLayers.test.d.ts +0 -2
  260. package/dist/__tests__/getLayers.test.d.ts.map +0 -1
  261. package/dist/__tests__/getLayers.test.js +0 -191
  262. package/dist/__tests__/getLayers.test.js.map +0 -1
  263. package/dist/__tests__/haversine.test.d.ts +0 -2
  264. package/dist/__tests__/haversine.test.d.ts.map +0 -1
  265. package/dist/__tests__/haversine.test.js +0 -56
  266. package/dist/__tests__/haversine.test.js.map +0 -1
  267. package/dist/__tests__/iconResolve.test.d.ts +0 -2
  268. package/dist/__tests__/iconResolve.test.d.ts.map +0 -1
  269. package/dist/__tests__/iconResolve.test.js +0 -99
  270. package/dist/__tests__/iconResolve.test.js.map +0 -1
  271. package/dist/__tests__/imageEditState.test.d.ts +0 -2
  272. package/dist/__tests__/imageEditState.test.d.ts.map +0 -1
  273. package/dist/__tests__/imageEditState.test.js +0 -61
  274. package/dist/__tests__/imageEditState.test.js.map +0 -1
  275. package/dist/__tests__/imageEditVersions.test.d.ts +0 -2
  276. package/dist/__tests__/imageEditVersions.test.d.ts.map +0 -1
  277. package/dist/__tests__/imageEditVersions.test.js +0 -141
  278. package/dist/__tests__/imageEditVersions.test.js.map +0 -1
  279. package/dist/__tests__/inferDocumentTitle.test.d.ts +0 -2
  280. package/dist/__tests__/inferDocumentTitle.test.d.ts.map +0 -1
  281. package/dist/__tests__/inferDocumentTitle.test.js +0 -42
  282. package/dist/__tests__/inferDocumentTitle.test.js.map +0 -1
  283. package/dist/__tests__/jsonForm.chooseControl.test.d.ts +0 -2
  284. package/dist/__tests__/jsonForm.chooseControl.test.d.ts.map +0 -1
  285. package/dist/__tests__/jsonForm.chooseControl.test.js +0 -74
  286. package/dist/__tests__/jsonForm.chooseControl.test.js.map +0 -1
  287. package/dist/__tests__/jsonForm.evaluateWhen.test.d.ts +0 -2
  288. package/dist/__tests__/jsonForm.evaluateWhen.test.d.ts.map +0 -1
  289. package/dist/__tests__/jsonForm.evaluateWhen.test.js +0 -51
  290. package/dist/__tests__/jsonForm.evaluateWhen.test.js.map +0 -1
  291. package/dist/__tests__/jsonForm.inferSchema.test.d.ts +0 -2
  292. package/dist/__tests__/jsonForm.inferSchema.test.d.ts.map +0 -1
  293. package/dist/__tests__/jsonForm.inferSchema.test.js +0 -23
  294. package/dist/__tests__/jsonForm.inferSchema.test.js.map +0 -1
  295. package/dist/__tests__/jsonForm.pointer.test.d.ts +0 -2
  296. package/dist/__tests__/jsonForm.pointer.test.d.ts.map +0 -1
  297. package/dist/__tests__/jsonForm.pointer.test.js +0 -94
  298. package/dist/__tests__/jsonForm.pointer.test.js.map +0 -1
  299. package/dist/__tests__/localForageAdapter.test.d.ts +0 -8
  300. package/dist/__tests__/localForageAdapter.test.d.ts.map +0 -1
  301. package/dist/__tests__/localForageAdapter.test.js +0 -130
  302. package/dist/__tests__/localForageAdapter.test.js.map +0 -1
  303. package/dist/__tests__/markdown.test.d.ts +0 -2
  304. package/dist/__tests__/markdown.test.d.ts.map +0 -1
  305. package/dist/__tests__/markdown.test.js +0 -715
  306. package/dist/__tests__/markdown.test.js.map +0 -1
  307. package/dist/__tests__/markdownIcons.test.d.ts +0 -2
  308. package/dist/__tests__/markdownIcons.test.d.ts.map +0 -1
  309. package/dist/__tests__/markdownIcons.test.js +0 -93
  310. package/dist/__tests__/markdownIcons.test.js.map +0 -1
  311. package/dist/__tests__/markdownToDoc.test.d.ts +0 -2
  312. package/dist/__tests__/markdownToDoc.test.d.ts.map +0 -1
  313. package/dist/__tests__/markdownToDoc.test.js +0 -458
  314. package/dist/__tests__/markdownToDoc.test.js.map +0 -1
  315. package/dist/__tests__/recommendTemplates.test.d.ts +0 -2
  316. package/dist/__tests__/recommendTemplates.test.d.ts.map +0 -1
  317. package/dist/__tests__/recommendTemplates.test.js +0 -158
  318. package/dist/__tests__/recommendTemplates.test.js.map +0 -1
  319. package/dist/__tests__/scopedContentContainer.test.d.ts +0 -2
  320. package/dist/__tests__/scopedContentContainer.test.d.ts.map +0 -1
  321. package/dist/__tests__/scopedContentContainer.test.js +0 -74
  322. package/dist/__tests__/scopedContentContainer.test.js.map +0 -1
  323. package/dist/__tests__/seededRandom.test.d.ts +0 -2
  324. package/dist/__tests__/seededRandom.test.d.ts.map +0 -1
  325. package/dist/__tests__/seededRandom.test.js +0 -125
  326. package/dist/__tests__/seededRandom.test.js.map +0 -1
  327. package/dist/__tests__/slideshowGenerator.test.d.ts +0 -2
  328. package/dist/__tests__/slideshowGenerator.test.d.ts.map +0 -1
  329. package/dist/__tests__/slideshowGenerator.test.js +0 -114
  330. package/dist/__tests__/slideshowGenerator.test.js.map +0 -1
  331. package/dist/__tests__/storage.test.d.ts +0 -2
  332. package/dist/__tests__/storage.test.d.ts.map +0 -1
  333. package/dist/__tests__/storage.test.js +0 -51
  334. package/dist/__tests__/storage.test.js.map +0 -1
  335. package/dist/__tests__/surface.test.d.ts +0 -2
  336. package/dist/__tests__/surface.test.d.ts.map +0 -1
  337. package/dist/__tests__/surface.test.js +0 -57
  338. package/dist/__tests__/surface.test.js.map +0 -1
  339. package/dist/__tests__/templateAnnotationParse.test.d.ts +0 -2
  340. package/dist/__tests__/templateAnnotationParse.test.d.ts.map +0 -1
  341. package/dist/__tests__/templateAnnotationParse.test.js +0 -42
  342. package/dist/__tests__/templateAnnotationParse.test.js.map +0 -1
  343. package/dist/__tests__/templates.test.d.ts +0 -2
  344. package/dist/__tests__/templates.test.d.ts.map +0 -1
  345. package/dist/__tests__/templates.test.js +0 -298
  346. package/dist/__tests__/templates.test.js.map +0 -1
  347. package/dist/__tests__/themeCompile.test.d.ts +0 -2
  348. package/dist/__tests__/themeCompile.test.d.ts.map +0 -1
  349. package/dist/__tests__/themeCompile.test.js +0 -134
  350. package/dist/__tests__/themeCompile.test.js.map +0 -1
  351. package/dist/__tests__/themeValidator.test.d.ts +0 -2
  352. package/dist/__tests__/themeValidator.test.d.ts.map +0 -1
  353. package/dist/__tests__/themeValidator.test.js +0 -107
  354. package/dist/__tests__/themeValidator.test.js.map +0 -1
  355. package/dist/__tests__/timing.test.d.ts +0 -2
  356. package/dist/__tests__/timing.test.d.ts.map +0 -1
  357. package/dist/__tests__/timing.test.js +0 -131
  358. package/dist/__tests__/timing.test.js.map +0 -1
  359. package/dist/__tests__/versions.test.d.ts +0 -2
  360. package/dist/__tests__/versions.test.d.ts.map +0 -1
  361. package/dist/__tests__/versions.test.js +0 -339
  362. package/dist/__tests__/versions.test.js.map +0 -1
  363. package/dist/chunk-3K5OG6KI.js.map +0 -1
  364. package/dist/chunk-57CVQCFX.js.map +0 -1
  365. package/dist/chunk-5WFRKURX.js.map +0 -1
  366. package/dist/chunk-7UDSRZKG.js.map +0 -1
  367. package/dist/chunk-B4EEON3N.js.map +0 -1
  368. package/dist/chunk-H3AXU4MJ.js.map +0 -1
  369. package/dist/chunk-KSWJR66U.js +0 -3706
  370. package/dist/chunk-KSWJR66U.js.map +0 -1
  371. package/dist/chunk-MYIH7FWD.js.map +0 -1
  372. package/dist/chunk-ZTX4PFFT.js.map +0 -1
  373. package/dist/doc/audioMapping.d.ts +0 -36
  374. package/dist/doc/audioMapping.d.ts.map +0 -1
  375. package/dist/doc/audioMapping.js +0 -350
  376. package/dist/doc/audioMapping.js.map +0 -1
  377. package/dist/doc/docToMarkdown.d.ts +0 -41
  378. package/dist/doc/docToMarkdown.d.ts.map +0 -1
  379. package/dist/doc/docToMarkdown.js +0 -88
  380. package/dist/doc/docToMarkdown.js.map +0 -1
  381. package/dist/doc/getLayers.d.ts +0 -65
  382. package/dist/doc/getLayers.d.ts.map +0 -1
  383. package/dist/doc/getLayers.js +0 -114
  384. package/dist/doc/getLayers.js.map +0 -1
  385. package/dist/doc/index.d.ts.map +0 -1
  386. package/dist/doc/markdownToDoc.d.ts +0 -75
  387. package/dist/doc/markdownToDoc.d.ts.map +0 -1
  388. package/dist/doc/markdownToDoc.js +0 -432
  389. package/dist/doc/markdownToDoc.js.map +0 -1
  390. package/dist/doc/templates/accentImage.d.ts +0 -59
  391. package/dist/doc/templates/accentImage.d.ts.map +0 -1
  392. package/dist/doc/templates/accentImage.js +0 -275
  393. package/dist/doc/templates/accentImage.js.map +0 -1
  394. package/dist/doc/templates/captionUtils.d.ts +0 -20
  395. package/dist/doc/templates/captionUtils.d.ts.map +0 -1
  396. package/dist/doc/templates/captionUtils.js +0 -29
  397. package/dist/doc/templates/captionUtils.js.map +0 -1
  398. package/dist/doc/templates/comparisonBar.d.ts +0 -13
  399. package/dist/doc/templates/comparisonBar.d.ts.map +0 -1
  400. package/dist/doc/templates/comparisonBar.js +0 -145
  401. package/dist/doc/templates/comparisonBar.js.map +0 -1
  402. package/dist/doc/templates/coverBlock.d.ts +0 -51
  403. package/dist/doc/templates/coverBlock.d.ts.map +0 -1
  404. package/dist/doc/templates/coverBlock.js +0 -153
  405. package/dist/doc/templates/coverBlock.js.map +0 -1
  406. package/dist/doc/templates/dataTable.d.ts +0 -14
  407. package/dist/doc/templates/dataTable.d.ts.map +0 -1
  408. package/dist/doc/templates/dataTable.js +0 -73
  409. package/dist/doc/templates/dataTable.js.map +0 -1
  410. package/dist/doc/templates/dateEvent.d.ts +0 -15
  411. package/dist/doc/templates/dateEvent.d.ts.map +0 -1
  412. package/dist/doc/templates/dateEvent.js +0 -114
  413. package/dist/doc/templates/dateEvent.js.map +0 -1
  414. package/dist/doc/templates/definitionCard.d.ts +0 -13
  415. package/dist/doc/templates/definitionCard.d.ts.map +0 -1
  416. package/dist/doc/templates/definitionCard.js +0 -117
  417. package/dist/doc/templates/definitionCard.js.map +0 -1
  418. package/dist/doc/templates/factCard.d.ts +0 -15
  419. package/dist/doc/templates/factCard.d.ts.map +0 -1
  420. package/dist/doc/templates/factCard.js +0 -104
  421. package/dist/doc/templates/factCard.js.map +0 -1
  422. package/dist/doc/templates/featureBlock.d.ts +0 -18
  423. package/dist/doc/templates/featureBlock.d.ts.map +0 -1
  424. package/dist/doc/templates/featureBlock.js +0 -180
  425. package/dist/doc/templates/featureBlock.js.map +0 -1
  426. package/dist/doc/templates/fullBleedQuote.d.ts +0 -25
  427. package/dist/doc/templates/fullBleedQuote.d.ts.map +0 -1
  428. package/dist/doc/templates/fullBleedQuote.js +0 -67
  429. package/dist/doc/templates/fullBleedQuote.js.map +0 -1
  430. package/dist/doc/templates/imageWithCaption.d.ts +0 -13
  431. package/dist/doc/templates/imageWithCaption.d.ts.map +0 -1
  432. package/dist/doc/templates/imageWithCaption.js +0 -146
  433. package/dist/doc/templates/imageWithCaption.js.map +0 -1
  434. package/dist/doc/templates/index.d.ts +0 -129
  435. package/dist/doc/templates/index.d.ts.map +0 -1
  436. package/dist/doc/templates/index.js +0 -478
  437. package/dist/doc/templates/index.js.map +0 -1
  438. package/dist/doc/templates/listBlock.d.ts +0 -13
  439. package/dist/doc/templates/listBlock.d.ts.map +0 -1
  440. package/dist/doc/templates/listBlock.js +0 -109
  441. package/dist/doc/templates/listBlock.js.map +0 -1
  442. package/dist/doc/templates/mapBlock.d.ts +0 -17
  443. package/dist/doc/templates/mapBlock.d.ts.map +0 -1
  444. package/dist/doc/templates/mapBlock.js +0 -115
  445. package/dist/doc/templates/mapBlock.js.map +0 -1
  446. package/dist/doc/templates/persistentLayers.d.ts +0 -39
  447. package/dist/doc/templates/persistentLayers.d.ts.map +0 -1
  448. package/dist/doc/templates/persistentLayers.js +0 -447
  449. package/dist/doc/templates/persistentLayers.js.map +0 -1
  450. package/dist/doc/templates/photoGrid.d.ts +0 -20
  451. package/dist/doc/templates/photoGrid.d.ts.map +0 -1
  452. package/dist/doc/templates/photoGrid.js +0 -175
  453. package/dist/doc/templates/photoGrid.js.map +0 -1
  454. package/dist/doc/templates/pullQuote.d.ts +0 -13
  455. package/dist/doc/templates/pullQuote.d.ts.map +0 -1
  456. package/dist/doc/templates/pullQuote.js +0 -113
  457. package/dist/doc/templates/pullQuote.js.map +0 -1
  458. package/dist/doc/templates/quoteBlock.d.ts +0 -15
  459. package/dist/doc/templates/quoteBlock.d.ts.map +0 -1
  460. package/dist/doc/templates/quoteBlock.js +0 -101
  461. package/dist/doc/templates/quoteBlock.js.map +0 -1
  462. package/dist/doc/templates/sectionHeader.d.ts +0 -14
  463. package/dist/doc/templates/sectionHeader.d.ts.map +0 -1
  464. package/dist/doc/templates/sectionHeader.js +0 -97
  465. package/dist/doc/templates/sectionHeader.js.map +0 -1
  466. package/dist/doc/templates/statHighlight.d.ts +0 -27
  467. package/dist/doc/templates/statHighlight.d.ts.map +0 -1
  468. package/dist/doc/templates/statHighlight.js +0 -114
  469. package/dist/doc/templates/statHighlight.js.map +0 -1
  470. package/dist/doc/templates/titleBlock.d.ts +0 -24
  471. package/dist/doc/templates/titleBlock.d.ts.map +0 -1
  472. package/dist/doc/templates/titleBlock.js +0 -103
  473. package/dist/doc/templates/titleBlock.js.map +0 -1
  474. package/dist/doc/templates/twoColumn.d.ts +0 -15
  475. package/dist/doc/templates/twoColumn.d.ts.map +0 -1
  476. package/dist/doc/templates/twoColumn.js +0 -225
  477. package/dist/doc/templates/twoColumn.js.map +0 -1
  478. package/dist/doc/templates/videoPullQuote.d.ts +0 -20
  479. package/dist/doc/templates/videoPullQuote.d.ts.map +0 -1
  480. package/dist/doc/templates/videoPullQuote.js +0 -122
  481. package/dist/doc/templates/videoPullQuote.js.map +0 -1
  482. package/dist/doc/templates/videoWithCaption.d.ts +0 -20
  483. package/dist/doc/templates/videoWithCaption.d.ts.map +0 -1
  484. package/dist/doc/templates/videoWithCaption.js +0 -107
  485. package/dist/doc/templates/videoWithCaption.js.map +0 -1
  486. package/dist/doc/utils/animationUtils.d.ts +0 -34
  487. package/dist/doc/utils/animationUtils.d.ts.map +0 -1
  488. package/dist/doc/utils/animationUtils.js +0 -110
  489. package/dist/doc/utils/animationUtils.js.map +0 -1
  490. package/dist/doc/utils/themeUtils.d.ts +0 -64
  491. package/dist/doc/utils/themeUtils.d.ts.map +0 -1
  492. package/dist/doc/utils/themeUtils.js +0 -136
  493. package/dist/doc/utils/themeUtils.js.map +0 -1
  494. package/dist/generate/contentExtractor.d.ts +0 -112
  495. package/dist/generate/contentExtractor.d.ts.map +0 -1
  496. package/dist/generate/contentExtractor.js +0 -638
  497. package/dist/generate/contentExtractor.js.map +0 -1
  498. package/dist/generate/index.d.ts.map +0 -1
  499. package/dist/generate/slideshowGenerator.d.ts +0 -72
  500. package/dist/generate/slideshowGenerator.d.ts.map +0 -1
  501. package/dist/generate/slideshowGenerator.js +0 -159
  502. package/dist/generate/slideshowGenerator.js.map +0 -1
  503. package/dist/generate/templateMapper.d.ts +0 -23
  504. package/dist/generate/templateMapper.d.ts.map +0 -1
  505. package/dist/generate/templateMapper.js +0 -114
  506. package/dist/generate/templateMapper.js.map +0 -1
  507. package/dist/icons/iconData.d.ts +0 -26
  508. package/dist/icons/iconData.d.ts.map +0 -1
  509. package/dist/icons/iconData.js +0 -12
  510. package/dist/icons/iconData.js.map +0 -1
  511. package/dist/icons/index.d.ts.map +0 -1
  512. package/dist/icons/resolve.d.ts +0 -61
  513. package/dist/icons/resolve.d.ts.map +0 -1
  514. package/dist/icons/resolve.js +0 -130
  515. package/dist/icons/resolve.js.map +0 -1
  516. package/dist/imageEdit/ImageEditVersionManager.d.ts +0 -31
  517. package/dist/imageEdit/ImageEditVersionManager.d.ts.map +0 -1
  518. package/dist/imageEdit/ImageEditVersionManager.js +0 -39
  519. package/dist/imageEdit/ImageEditVersionManager.js.map +0 -1
  520. package/dist/imageEdit/export.d.ts +0 -33
  521. package/dist/imageEdit/export.d.ts.map +0 -1
  522. package/dist/imageEdit/export.js +0 -253
  523. package/dist/imageEdit/export.js.map +0 -1
  524. package/dist/imageEdit/index.d.ts.map +0 -1
  525. package/dist/imageEdit/persistence.d.ts +0 -15
  526. package/dist/imageEdit/persistence.d.ts.map +0 -1
  527. package/dist/imageEdit/persistence.js +0 -49
  528. package/dist/imageEdit/persistence.js.map +0 -1
  529. package/dist/imageEdit/state.d.ts +0 -42
  530. package/dist/imageEdit/state.d.ts.map +0 -1
  531. package/dist/imageEdit/state.js +0 -98
  532. package/dist/imageEdit/state.js.map +0 -1
  533. package/dist/imageEdit/versionPaths.d.ts +0 -27
  534. package/dist/imageEdit/versionPaths.d.ts.map +0 -1
  535. package/dist/imageEdit/versionPaths.js +0 -57
  536. package/dist/imageEdit/versionPaths.js.map +0 -1
  537. package/dist/imageEdit/versions.d.ts +0 -67
  538. package/dist/imageEdit/versions.d.ts.map +0 -1
  539. package/dist/imageEdit/versions.js +0 -161
  540. package/dist/imageEdit/versions.js.map +0 -1
  541. package/dist/index.d.ts.map +0 -1
  542. package/dist/jsonForm/chooseControl.d.ts +0 -20
  543. package/dist/jsonForm/chooseControl.d.ts.map +0 -1
  544. package/dist/jsonForm/chooseControl.js +0 -82
  545. package/dist/jsonForm/chooseControl.js.map +0 -1
  546. package/dist/jsonForm/evaluateWhen.d.ts +0 -12
  547. package/dist/jsonForm/evaluateWhen.d.ts.map +0 -1
  548. package/dist/jsonForm/evaluateWhen.js +0 -65
  549. package/dist/jsonForm/evaluateWhen.js.map +0 -1
  550. package/dist/jsonForm/index.d.ts.map +0 -1
  551. package/dist/jsonForm/inferSchema.d.ts +0 -12
  552. package/dist/jsonForm/inferSchema.d.ts.map +0 -1
  553. package/dist/jsonForm/inferSchema.js +0 -15
  554. package/dist/jsonForm/inferSchema.js.map +0 -1
  555. package/dist/jsonForm/pointer.d.ts +0 -26
  556. package/dist/jsonForm/pointer.d.ts.map +0 -1
  557. package/dist/jsonForm/pointer.js +0 -102
  558. package/dist/jsonForm/pointer.js.map +0 -1
  559. package/dist/jsonForm/types.d.ts +0 -120
  560. package/dist/jsonForm/types.d.ts.map +0 -1
  561. package/dist/jsonForm/types.js +0 -10
  562. package/dist/jsonForm/types.js.map +0 -1
  563. package/dist/markdown/convert.d.ts +0 -81
  564. package/dist/markdown/convert.d.ts.map +0 -1
  565. package/dist/markdown/convert.js +0 -975
  566. package/dist/markdown/convert.js.map +0 -1
  567. package/dist/markdown/htmlParse.d.ts +0 -26
  568. package/dist/markdown/htmlParse.d.ts.map +0 -1
  569. package/dist/markdown/htmlParse.js +0 -195
  570. package/dist/markdown/htmlParse.js.map +0 -1
  571. package/dist/markdown/index.d.ts.map +0 -1
  572. package/dist/markdown/parse.d.ts +0 -27
  573. package/dist/markdown/parse.d.ts.map +0 -1
  574. package/dist/markdown/parse.js +0 -90
  575. package/dist/markdown/parse.js.map +0 -1
  576. package/dist/markdown/stringify.d.ts +0 -32
  577. package/dist/markdown/stringify.d.ts.map +0 -1
  578. package/dist/markdown/stringify.js +0 -108
  579. package/dist/markdown/stringify.js.map +0 -1
  580. package/dist/markdown/types.d.ts +0 -531
  581. package/dist/markdown/types.d.ts.map +0 -1
  582. package/dist/markdown/types.js +0 -17
  583. package/dist/markdown/types.js.map +0 -1
  584. package/dist/markdown/utils.d.ts +0 -118
  585. package/dist/markdown/utils.d.ts.map +0 -1
  586. package/dist/markdown/utils.js +0 -308
  587. package/dist/markdown/utils.js.map +0 -1
  588. package/dist/random/SeededRandom.d.ts +0 -50
  589. package/dist/random/SeededRandom.d.ts.map +0 -1
  590. package/dist/random/SeededRandom.js +0 -115
  591. package/dist/random/SeededRandom.js.map +0 -1
  592. package/dist/random/index.d.ts.map +0 -1
  593. package/dist/recommend/index.d.ts.map +0 -1
  594. package/dist/recommend/templates.d.ts +0 -39
  595. package/dist/recommend/templates.d.ts.map +0 -1
  596. package/dist/recommend/templates.js +0 -235
  597. package/dist/recommend/templates.js.map +0 -1
  598. package/dist/schemas/BlockTemplates.d.ts +0 -638
  599. package/dist/schemas/BlockTemplates.d.ts.map +0 -1
  600. package/dist/schemas/BlockTemplates.js +0 -72
  601. package/dist/schemas/BlockTemplates.js.map +0 -1
  602. package/dist/schemas/Doc.d.ts +0 -503
  603. package/dist/schemas/Doc.d.ts.map +0 -1
  604. package/dist/schemas/Doc.js +0 -90
  605. package/dist/schemas/Doc.js.map +0 -1
  606. package/dist/schemas/ImageEditDoc.d.ts +0 -81
  607. package/dist/schemas/ImageEditDoc.d.ts.map +0 -1
  608. package/dist/schemas/ImageEditDoc.js +0 -20
  609. package/dist/schemas/ImageEditDoc.js.map +0 -1
  610. package/dist/schemas/LayoutStrategy.d.ts +0 -84
  611. package/dist/schemas/LayoutStrategy.d.ts.map +0 -1
  612. package/dist/schemas/LayoutStrategy.js +0 -123
  613. package/dist/schemas/LayoutStrategy.js.map +0 -1
  614. package/dist/schemas/MediaProvider.d.ts +0 -65
  615. package/dist/schemas/MediaProvider.d.ts.map +0 -1
  616. package/dist/schemas/MediaProvider.js +0 -13
  617. package/dist/schemas/MediaProvider.js.map +0 -1
  618. package/dist/schemas/Theme.d.ts +0 -233
  619. package/dist/schemas/Theme.d.ts.map +0 -1
  620. package/dist/schemas/Theme.js +0 -129
  621. package/dist/schemas/Theme.js.map +0 -1
  622. package/dist/schemas/Types.d.ts +0 -14
  623. package/dist/schemas/Types.d.ts.map +0 -1
  624. package/dist/schemas/Types.js +0 -5
  625. package/dist/schemas/Types.js.map +0 -1
  626. package/dist/schemas/Viewport.d.ts +0 -74
  627. package/dist/schemas/Viewport.d.ts.map +0 -1
  628. package/dist/schemas/Viewport.js +0 -63
  629. package/dist/schemas/Viewport.js.map +0 -1
  630. package/dist/schemas/colorUtils.d.ts +0 -51
  631. package/dist/schemas/colorUtils.d.ts.map +0 -1
  632. package/dist/schemas/colorUtils.js +0 -154
  633. package/dist/schemas/colorUtils.js.map +0 -1
  634. package/dist/schemas/fontStacks.d.ts +0 -57
  635. package/dist/schemas/fontStacks.d.ts.map +0 -1
  636. package/dist/schemas/fontStacks.js +0 -227
  637. package/dist/schemas/fontStacks.js.map +0 -1
  638. package/dist/schemas/index.d.ts.map +0 -1
  639. package/dist/schemas/themeCompile.d.ts +0 -45
  640. package/dist/schemas/themeCompile.d.ts.map +0 -1
  641. package/dist/schemas/themeCompile.js +0 -160
  642. package/dist/schemas/themeCompile.js.map +0 -1
  643. package/dist/schemas/themeLibrary.d.ts +0 -37
  644. package/dist/schemas/themeLibrary.d.ts.map +0 -1
  645. package/dist/schemas/themeLibrary.js +0 -49
  646. package/dist/schemas/themeLibrary.js.map +0 -1
  647. package/dist/schemas/themeValidator.d.ts +0 -26
  648. package/dist/schemas/themeValidator.d.ts.map +0 -1
  649. package/dist/schemas/themeValidator.js +0 -352
  650. package/dist/schemas/themeValidator.js.map +0 -1
  651. package/dist/schemas/themes/bold.json +0 -48
  652. package/dist/schemas/themes/cinematic.json +0 -54
  653. package/dist/schemas/themes/documentary.json +0 -49
  654. package/dist/schemas/themes/gezellig.json +0 -44
  655. package/dist/schemas/themes/index.d.ts +0 -26
  656. package/dist/schemas/themes/index.d.ts.map +0 -1
  657. package/dist/schemas/themes/index.js +0 -49
  658. package/dist/schemas/themes/index.js.map +0 -1
  659. package/dist/schemas/themes/magazine.json +0 -44
  660. package/dist/schemas/themes/minimalist.json +0 -45
  661. package/dist/schemas/themes/morning-light.json +0 -42
  662. package/dist/schemas/themes/standard-dark.json +0 -50
  663. package/dist/schemas/themes/standard.json +0 -42
  664. package/dist/schemas/themes/tech-dark.json +0 -48
  665. package/dist/schemas/themes/warm-earth.json +0 -50
  666. package/dist/spatial/Geohash.d.ts +0 -85
  667. package/dist/spatial/Geohash.d.ts.map +0 -1
  668. package/dist/spatial/Geohash.js +0 -142
  669. package/dist/spatial/Geohash.js.map +0 -1
  670. package/dist/spatial/Haversine.d.ts +0 -24
  671. package/dist/spatial/Haversine.d.ts.map +0 -1
  672. package/dist/spatial/Haversine.js +0 -48
  673. package/dist/spatial/Haversine.js.map +0 -1
  674. package/dist/spatial/index.d.ts.map +0 -1
  675. package/dist/storage/ContentContainer.d.ts +0 -87
  676. package/dist/storage/ContentContainer.d.ts.map +0 -1
  677. package/dist/storage/ContentContainer.js +0 -131
  678. package/dist/storage/ContentContainer.js.map +0 -1
  679. package/dist/storage/LocalForageAdapter.d.ts +0 -36
  680. package/dist/storage/LocalForageAdapter.d.ts.map +0 -1
  681. package/dist/storage/LocalForageAdapter.js +0 -82
  682. package/dist/storage/LocalForageAdapter.js.map +0 -1
  683. package/dist/storage/LocalStorageAdapter.d.ts +0 -16
  684. package/dist/storage/LocalStorageAdapter.d.ts.map +0 -1
  685. package/dist/storage/LocalStorageAdapter.js +0 -50
  686. package/dist/storage/LocalStorageAdapter.js.map +0 -1
  687. package/dist/storage/MediaProviderFromContainer.d.ts +0 -21
  688. package/dist/storage/MediaProviderFromContainer.d.ts.map +0 -1
  689. package/dist/storage/MediaProviderFromContainer.js +0 -79
  690. package/dist/storage/MediaProviderFromContainer.js.map +0 -1
  691. package/dist/storage/MemoryStorageAdapter.d.ts +0 -15
  692. package/dist/storage/MemoryStorageAdapter.d.ts.map +0 -1
  693. package/dist/storage/MemoryStorageAdapter.js +0 -34
  694. package/dist/storage/MemoryStorageAdapter.js.map +0 -1
  695. package/dist/storage/ScopedContentContainer.d.ts +0 -44
  696. package/dist/storage/ScopedContentContainer.d.ts.map +0 -1
  697. package/dist/storage/ScopedContentContainer.js +0 -94
  698. package/dist/storage/ScopedContentContainer.js.map +0 -1
  699. package/dist/storage/Storage.d.ts +0 -23
  700. package/dist/storage/Storage.d.ts.map +0 -1
  701. package/dist/storage/Storage.js +0 -9
  702. package/dist/storage/Storage.js.map +0 -1
  703. package/dist/storage/index.d.ts.map +0 -1
  704. package/dist/timing/index.d.ts.map +0 -1
  705. package/dist/timing/narrationTiming.d.ts +0 -54
  706. package/dist/timing/narrationTiming.d.ts.map +0 -1
  707. package/dist/timing/narrationTiming.js +0 -190
  708. package/dist/timing/narrationTiming.js.map +0 -1
  709. package/dist/timing/readingTime.d.ts +0 -54
  710. package/dist/timing/readingTime.d.ts.map +0 -1
  711. package/dist/timing/readingTime.js +0 -49
  712. package/dist/timing/readingTime.js.map +0 -1
  713. package/dist/transform/applyTransform.d.ts +0 -22
  714. package/dist/transform/applyTransform.d.ts.map +0 -1
  715. package/dist/transform/applyTransform.js +0 -68
  716. package/dist/transform/applyTransform.js.map +0 -1
  717. package/dist/transform/blockAnalyzer.d.ts +0 -48
  718. package/dist/transform/blockAnalyzer.d.ts.map +0 -1
  719. package/dist/transform/blockAnalyzer.js +0 -135
  720. package/dist/transform/blockAnalyzer.js.map +0 -1
  721. package/dist/transform/index.d.ts.map +0 -1
  722. package/dist/transform/registry.d.ts +0 -19
  723. package/dist/transform/registry.d.ts.map +0 -1
  724. package/dist/transform/registry.js +0 -41
  725. package/dist/transform/registry.js.map +0 -1
  726. package/dist/transform/styles/dataDriven.d.ts +0 -4
  727. package/dist/transform/styles/dataDriven.d.ts.map +0 -1
  728. package/dist/transform/styles/dataDriven.js +0 -15
  729. package/dist/transform/styles/dataDriven.js.map +0 -1
  730. package/dist/transform/styles/documentary.d.ts +0 -4
  731. package/dist/transform/styles/documentary.d.ts.map +0 -1
  732. package/dist/transform/styles/documentary.js +0 -15
  733. package/dist/transform/styles/documentary.js.map +0 -1
  734. package/dist/transform/styles/index.d.ts +0 -6
  735. package/dist/transform/styles/index.d.ts.map +0 -1
  736. package/dist/transform/styles/index.js +0 -6
  737. package/dist/transform/styles/index.js.map +0 -1
  738. package/dist/transform/styles/magazine.d.ts +0 -4
  739. package/dist/transform/styles/magazine.d.ts.map +0 -1
  740. package/dist/transform/styles/magazine.js +0 -15
  741. package/dist/transform/styles/magazine.js.map +0 -1
  742. package/dist/transform/styles/minimal.d.ts +0 -4
  743. package/dist/transform/styles/minimal.d.ts.map +0 -1
  744. package/dist/transform/styles/minimal.js +0 -15
  745. package/dist/transform/styles/minimal.js.map +0 -1
  746. package/dist/transform/styles/narrative.d.ts +0 -4
  747. package/dist/transform/styles/narrative.d.ts.map +0 -1
  748. package/dist/transform/styles/narrative.js +0 -15
  749. package/dist/transform/styles/narrative.js.map +0 -1
  750. package/dist/transform/templateSelector.d.ts +0 -30
  751. package/dist/transform/templateSelector.d.ts.map +0 -1
  752. package/dist/transform/templateSelector.js +0 -218
  753. package/dist/transform/templateSelector.js.map +0 -1
  754. package/dist/transform/timingAllocator.d.ts +0 -21
  755. package/dist/transform/timingAllocator.d.ts.map +0 -1
  756. package/dist/transform/timingAllocator.js +0 -111
  757. package/dist/transform/timingAllocator.js.map +0 -1
  758. package/dist/transform/types.d.ts +0 -86
  759. package/dist/transform/types.d.ts.map +0 -1
  760. package/dist/transform/types.js +0 -9
  761. package/dist/transform/types.js.map +0 -1
  762. package/dist/versions/DocumentVersionManager.d.ts +0 -31
  763. package/dist/versions/DocumentVersionManager.d.ts.map +0 -1
  764. package/dist/versions/DocumentVersionManager.js +0 -33
  765. package/dist/versions/DocumentVersionManager.js.map +0 -1
  766. package/dist/versions/index.d.ts.map +0 -1
  767. package/dist/versions/operations.d.ts +0 -44
  768. package/dist/versions/operations.d.ts.map +0 -1
  769. package/dist/versions/operations.js +0 -190
  770. package/dist/versions/operations.js.map +0 -1
  771. package/dist/versions/paths.d.ts +0 -29
  772. package/dist/versions/paths.d.ts.map +0 -1
  773. package/dist/versions/paths.js +0 -66
  774. package/dist/versions/paths.js.map +0 -1
  775. package/dist/versions/timestamp.d.ts +0 -22
  776. package/dist/versions/timestamp.d.ts.map +0 -1
  777. package/dist/versions/timestamp.js +0 -44
  778. package/dist/versions/timestamp.js.map +0 -1
  779. package/dist/versions/types.d.ts +0 -92
  780. package/dist/versions/types.d.ts.map +0 -1
  781. package/dist/versions/types.js +0 -11
  782. package/dist/versions/types.js.map +0 -1
@@ -1,3706 +0,0 @@
1
- import {
2
- DEFAULT_THEME,
3
- resolveFontFamily
4
- } from "./chunk-B4EEON3N.js";
5
- import {
6
- VIEWPORT_PRESETS,
7
- createTemplateContext,
8
- getTwoColumnPositions,
9
- isPersistentLayerTemplate,
10
- isTemplateBlock,
11
- scaledFontSize2 as scaledFontSize
12
- } from "./chunk-5WFRKURX.js";
13
- import {
14
- extractPlainText
15
- } from "./chunk-H3AXU4MJ.js";
16
- import {
17
- estimateReadingTime
18
- } from "./chunk-4X3JQXNM.js";
19
-
20
- // src/doc/templates/persistentLayers.ts
21
- var GRADIENT_PRESETS = {
22
- "dark-vignette": "radial-gradient(ellipse at center, rgba(26,32,44,0.8) 0%, rgba(0,0,0,0.95) 100%)",
23
- "radial-dark": "radial-gradient(ellipse at center, #1a202c 0%, #000000 100%)",
24
- "warm-sunset": "linear-gradient(135deg, rgba(124,58,48,0.9) 0%, rgba(26,32,44,0.95) 100%)",
25
- "cool-blue": "linear-gradient(135deg, rgba(26,54,93,0.9) 0%, rgba(26,32,44,0.95) 100%)",
26
- "earth-tones": "linear-gradient(135deg, rgba(68,51,34,0.9) 0%, rgba(26,32,44,0.95) 100%)"
27
- };
28
- function expandSolidBackground(config) {
29
- return {
30
- type: "shape",
31
- id: "persistent-bg-solid",
32
- content: {
33
- shape: "rect",
34
- fill: config.color
35
- },
36
- position: { x: 0, y: 0, width: "100%", height: "100%" }
37
- };
38
- }
39
- function expandGradientBackground(config) {
40
- const gradient = config.gradient ?? GRADIENT_PRESETS[config.preset ?? "dark-vignette"];
41
- return {
42
- type: "shape",
43
- id: "persistent-bg-gradient",
44
- content: {
45
- shape: "rect",
46
- fill: gradient
47
- },
48
- position: { x: 0, y: 0, width: "100%", height: "100%" }
49
- };
50
- }
51
- function expandImageBackground(config) {
52
- const layers = [];
53
- const opacity = config.opacity ?? 0.4;
54
- const imageLayer = {
55
- type: "image",
56
- id: "persistent-bg-image",
57
- content: {
58
- src: config.src,
59
- alt: "Background",
60
- fit: "cover"
61
- },
62
- position: { x: 0, y: 0, width: "100%", height: "100%" },
63
- animation: config.ambientMotion ? {
64
- type: config.ambientMotion,
65
- duration: 30
66
- // Long ambient motion
67
- } : void 0
68
- };
69
- layers.push(imageLayer);
70
- layers.push({
71
- type: "shape",
72
- id: "persistent-bg-overlay",
73
- content: {
74
- shape: "rect",
75
- fill: `rgba(0,0,0,${0.5 + (1 - opacity) * 0.3})`
76
- },
77
- position: { x: 0, y: 0, width: "100%", height: "100%" }
78
- });
79
- return layers;
80
- }
81
- function expandPatternBackground(config) {
82
- const opacity = config.opacity ?? 0.1;
83
- const color = config.color ?? `rgba(255,255,255,${opacity})`;
84
- return {
85
- type: "shape",
86
- id: "persistent-bg-pattern",
87
- content: {
88
- shape: "rect",
89
- fill: color
90
- },
91
- position: { x: 0, y: 0, width: "100%", height: "100%" }
92
- };
93
- }
94
- function expandTitleCaption(config) {
95
- const layers = [];
96
- const fontSize = config.fontSize ?? 18;
97
- const hasSubtitle = !!config.subtitle;
98
- const isBottom = config.position.includes("bottom");
99
- const isLeft = config.position.includes("left");
100
- const pad = 3;
101
- const pillHeight = hasSubtitle ? "15%" : "7%";
102
- const bgYPos = isBottom ? hasSubtitle ? "78%" : "84%" : "2%";
103
- const bgXPos = isLeft ? `${pad}%` : "68%";
104
- const thumbW = hasSubtitle ? "6%" : "5%";
105
- const thumbH = hasSubtitle ? "10%" : "5%";
106
- const thumbPad = 1.5;
107
- const textX = config.showThumbnail && isLeft ? `${pad + thumbPad + 6 + thumbPad}%` : `${pad + thumbPad}%`;
108
- const textWidth = config.showThumbnail ? "19%" : "24%";
109
- const titleYPos = isBottom ? hasSubtitle ? "80%" : "86%" : "4%";
110
- layers.push({
111
- type: "shape",
112
- id: "persistent-caption-bg",
113
- content: {
114
- shape: "rect",
115
- fill: "rgba(0,0,0,0.6)",
116
- borderRadius: 8
117
- },
118
- position: {
119
- x: bgXPos,
120
- y: bgYPos,
121
- width: config.showThumbnail ? "30%" : "28%",
122
- height: pillHeight
123
- }
124
- });
125
- if (config.showThumbnail && config.thumbnailSrc) {
126
- const thumbX = isLeft ? `${pad + thumbPad}%` : "93%";
127
- const thumbY = isBottom ? hasSubtitle ? `${78 + thumbPad}%` : "85%" : "3%";
128
- layers.push({
129
- type: "image",
130
- id: "persistent-caption-thumb",
131
- content: {
132
- src: config.thumbnailSrc,
133
- alt: "Article thumbnail",
134
- fit: "cover"
135
- },
136
- position: {
137
- x: thumbX,
138
- y: thumbY,
139
- width: thumbW,
140
- height: thumbH
141
- }
142
- });
143
- }
144
- layers.push({
145
- type: "text",
146
- id: "persistent-caption-title",
147
- content: {
148
- text: config.title,
149
- style: {
150
- fontSize,
151
- fontWeight: "bold",
152
- color: "rgba(255,255,255,0.9)",
153
- textAlign: isLeft ? "left" : "right",
154
- maxLines: 1
155
- }
156
- },
157
- position: {
158
- x: textX,
159
- y: titleYPos,
160
- width: textWidth
161
- }
162
- });
163
- if (hasSubtitle) {
164
- const subtitleYPos = isBottom ? "85.5%" : "8%";
165
- layers.push({
166
- type: "text",
167
- id: "persistent-caption-subtitle",
168
- content: {
169
- text: config.subtitle,
170
- style: {
171
- fontSize: 18,
172
- fontWeight: "normal",
173
- color: "rgba(255,255,255,0.55)",
174
- textAlign: isLeft ? "left" : "right"
175
- }
176
- },
177
- position: {
178
- x: textX,
179
- y: subtitleYPos,
180
- width: textWidth
181
- }
182
- });
183
- }
184
- return layers;
185
- }
186
- function expandCornerBranding(config) {
187
- const isBottom = config.position.includes("bottom");
188
- const isLeft = config.position.includes("left");
189
- const xPos = isLeft ? "3%" : "90%";
190
- const yPos = isBottom ? "94%" : "3%";
191
- if (config.isImage) {
192
- return {
193
- type: "image",
194
- id: "persistent-branding",
195
- content: {
196
- src: config.content,
197
- alt: "Branding",
198
- fit: "contain"
199
- },
200
- position: {
201
- x: xPos,
202
- y: yPos,
203
- width: "8%",
204
- height: "4%"
205
- }
206
- };
207
- }
208
- return {
209
- type: "text",
210
- id: "persistent-branding",
211
- content: {
212
- text: config.content,
213
- style: {
214
- fontSize: 14,
215
- fontWeight: "normal",
216
- color: "rgba(255,255,255,0.6)"
217
- }
218
- },
219
- position: {
220
- x: xPos,
221
- y: yPos
222
- }
223
- };
224
- }
225
- function expandProgressIndicator(config) {
226
- const color = config.color ?? "rgba(255,255,255,0.3)";
227
- const y = config.position === "top" ? "1%" : "98%";
228
- return {
229
- type: "shape",
230
- id: "persistent-progress",
231
- content: {
232
- shape: "rect",
233
- fill: color,
234
- borderRadius: 2
235
- },
236
- position: {
237
- x: "5%",
238
- y,
239
- width: "90%",
240
- height: "0.5%"
241
- }
242
- };
243
- }
244
- function expandPersistentLayer(layer) {
245
- if (!isPersistentLayerTemplate(layer)) {
246
- return [layer];
247
- }
248
- const template = layer;
249
- const config = template.config;
250
- switch (config.type) {
251
- case "solidBackground":
252
- return [expandSolidBackground(config)];
253
- case "gradientBackground":
254
- return [expandGradientBackground(config)];
255
- case "imageBackground":
256
- return expandImageBackground(config);
257
- case "patternBackground":
258
- return [expandPatternBackground(config)];
259
- case "titleCaption":
260
- return expandTitleCaption(config);
261
- case "cornerBranding":
262
- return [expandCornerBranding(config)];
263
- case "progressIndicator":
264
- return [expandProgressIndicator(config)];
265
- default:
266
- console.warn("Unknown persistent layer template:", config.type);
267
- return [];
268
- }
269
- }
270
- function expandPersistentLayers(layers) {
271
- if (!layers || layers.length === 0) {
272
- return [];
273
- }
274
- return layers.reduce((acc, layer) => acc.concat(expandPersistentLayer(layer)), []);
275
- }
276
- function getDocStyleConfig(preset, articleTitle, heroSrc, subtitle) {
277
- switch (preset) {
278
- case "minimal":
279
- return {};
280
- case "documentary":
281
- return {
282
- bottomLayers: [
283
- {
284
- template: "gradientBackground",
285
- config: { type: "gradientBackground", preset: "dark-vignette" }
286
- }
287
- ],
288
- topLayers: [
289
- {
290
- template: "titleCaption",
291
- config: {
292
- type: "titleCaption",
293
- title: articleTitle,
294
- subtitle,
295
- position: "bottom-left",
296
- fontSize: 24,
297
- showThumbnail: !!heroSrc,
298
- thumbnailSrc: heroSrc
299
- }
300
- }
301
- ]
302
- };
303
- case "branded":
304
- return {
305
- bottomLayers: [
306
- {
307
- template: "gradientBackground",
308
- config: { type: "gradientBackground", preset: "cool-blue" }
309
- }
310
- ],
311
- topLayers: [
312
- {
313
- template: "titleCaption",
314
- config: {
315
- type: "titleCaption",
316
- title: articleTitle,
317
- subtitle,
318
- position: "bottom-left",
319
- fontSize: 26,
320
- showThumbnail: !!heroSrc,
321
- thumbnailSrc: heroSrc
322
- }
323
- }
324
- ]
325
- };
326
- case "cinematic":
327
- return {
328
- bottomLayers: heroSrc ? [
329
- {
330
- template: "imageBackground",
331
- config: {
332
- type: "imageBackground",
333
- src: heroSrc,
334
- blur: 12,
335
- opacity: 0.3,
336
- ambientMotion: "zoomIn"
337
- }
338
- }
339
- ] : [
340
- {
341
- template: "gradientBackground",
342
- config: { type: "gradientBackground", preset: "radial-dark" }
343
- }
344
- ],
345
- topLayers: [
346
- {
347
- template: "titleCaption",
348
- config: {
349
- type: "titleCaption",
350
- title: articleTitle,
351
- subtitle,
352
- position: "bottom-right",
353
- fontSize: 22
354
- }
355
- }
356
- ]
357
- };
358
- case "clean":
359
- return {
360
- bottomLayers: [
361
- {
362
- template: "solidBackground",
363
- config: { type: "solidBackground", color: "#1a202c" }
364
- }
365
- ]
366
- };
367
- default:
368
- return {};
369
- }
370
- }
371
-
372
- // src/doc/utils/themeUtils.ts
373
- var FALLBACK_COLOR_SCHEME = {
374
- bg: "#1a365d",
375
- text: "#63b3ed",
376
- accent: "#90cdf4"
377
- };
378
- function resolveColorScheme(context, name) {
379
- const schemes = context.theme.colorSchemes;
380
- if (name && name in schemes) return schemes[name];
381
- const keys = Object.keys(schemes);
382
- if (keys.length > 0) return schemes[keys[0]];
383
- return FALLBACK_COLOR_SCHEME;
384
- }
385
- var FALLBACK_BODY = 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif';
386
- var FALLBACK_TITLE = 'Georgia, "Times New Roman", serif';
387
- var FALLBACK_MONO = 'Consolas, "Courier New", monospace';
388
- function getThemeFont(context, role) {
389
- const { typography } = context.theme;
390
- switch (role) {
391
- case "title":
392
- return resolveFontFamily(typography.titleFont, FALLBACK_TITLE);
393
- case "body":
394
- return resolveFontFamily(typography.bodyFont, FALLBACK_BODY);
395
- case "mono":
396
- return resolveFontFamily(typography.monoFont, FALLBACK_MONO);
397
- }
398
- }
399
- function themedFontSize(basePx, context, isTitle = false) {
400
- const { fontScale, layout, theme } = context;
401
- const layoutScale = isTitle ? layout.titleScale : layout.bodyScale;
402
- const themeScale = isTitle ? theme.typography.titleScale ?? 1 : theme.typography.bodyScale ?? 1;
403
- return Math.round(basePx * fontScale * layoutScale * themeScale);
404
- }
405
- function scaleAnimationDuration(baseDuration, context) {
406
- const speed = context.theme.style.animationSpeed ?? 1;
407
- return baseDuration * speed;
408
- }
409
- function getDefaultAnimation(context, layerType) {
410
- const rs = context.theme.renderStyle;
411
- return layerType === "text" ? rs.defaultTextAnimation : rs.defaultImageAnimation;
412
- }
413
- function shouldUseShadow(context) {
414
- return context.theme.style.textShadow ?? true;
415
- }
416
- function getOverlayOpacity(context) {
417
- return context.theme.style.overlayOpacity ?? 0.5;
418
- }
419
- function getTemplateHint(context, templateName, key, fallback) {
420
- const hints = context.theme.renderStyle.templateHints;
421
- if (!hints) return fallback;
422
- const tplHints = hints[templateName];
423
- if (!tplHints || !(key in tplHints)) return fallback;
424
- return tplHints[key];
425
- }
426
-
427
- // src/doc/templates/titleBlock.ts
428
- function titleBlock(input, context) {
429
- const { title, subtitle, backgroundColor } = input;
430
- const { theme, layout } = context;
431
- const titleFontSize = scaledFontSize(96, context, true);
432
- const subtitleFontSize = scaledFontSize(36, context, false);
433
- const baseBg = backgroundColor || theme.colors.primary;
434
- const layers = [
435
- // Background — radial gradient for depth instead of flat color
436
- {
437
- type: "shape",
438
- id: "bg",
439
- content: {
440
- shape: "rect",
441
- fill: `radial-gradient(ellipse at 50% 40%, ${baseBg} 0%, ${theme.colors.background} 100%)`
442
- },
443
- position: { x: 0, y: 0, width: "100%", height: "100%" }
444
- },
445
- // Subtle decorative line above title
446
- {
447
- type: "shape",
448
- id: "accent-line",
449
- content: {
450
- shape: "rect",
451
- fill: "rgba(255, 255, 255, 0.2)"
452
- },
453
- position: {
454
- x: "40%",
455
- y: subtitle ? "28%" : "38%",
456
- width: "20%",
457
- height: "2px"
458
- }
459
- },
460
- // Title
461
- {
462
- type: "text",
463
- id: "title",
464
- content: {
465
- text: title,
466
- style: {
467
- fontSize: titleFontSize,
468
- fontFamily: getThemeFont(context, "title"),
469
- fontWeight: "bold",
470
- color: theme.colors.text,
471
- textAlign: "center",
472
- shadow: true
473
- }
474
- },
475
- position: {
476
- x: "50%",
477
- y: subtitle ? layout.primaryY : "50%",
478
- anchor: "center",
479
- width: layout.maxTextWidth
480
- },
481
- animation: { type: "fadeIn", duration: 2 }
482
- }
483
- ];
484
- if (subtitle) {
485
- layers.push({
486
- type: "text",
487
- id: "subtitle",
488
- content: {
489
- text: subtitle,
490
- style: {
491
- fontSize: subtitleFontSize,
492
- fontFamily: getThemeFont(context, "body"),
493
- color: theme.colors.textMuted,
494
- textAlign: "center",
495
- lineHeight: 1.5
496
- }
497
- },
498
- position: {
499
- x: "50%",
500
- y: layout.secondaryY,
501
- anchor: "center",
502
- width: layout.maxTextWidth
503
- },
504
- animation: { type: "fadeIn", duration: 1.5, delay: 1 }
505
- });
506
- }
507
- return layers;
508
- }
509
-
510
- // src/doc/templates/sectionHeader.ts
511
- function sectionHeader(input, context) {
512
- const { title = "", colorScheme = "blue", imageSrc, imageAlt, ambientMotion } = input;
513
- const { layout } = context;
514
- const colors = resolveColorScheme(context, colorScheme);
515
- const titleFontSize = scaledFontSize(72, context, true);
516
- const layers = [];
517
- if (imageSrc) {
518
- layers.push({
519
- type: "image",
520
- id: "bg-image",
521
- content: {
522
- src: imageSrc,
523
- alt: imageAlt || title,
524
- fit: "cover"
525
- },
526
- position: { x: 0, y: 0, width: "100%", height: "100%" },
527
- animation: ambientMotion ? { type: ambientMotion, duration: 8 } : { type: "slowZoom", duration: 8, direction: "in" }
528
- });
529
- layers.push({
530
- type: "shape",
531
- id: "overlay",
532
- content: {
533
- shape: "rect",
534
- fill: "rgba(0, 0, 0, 0.5)"
535
- },
536
- position: { x: 0, y: 0, width: "100%", height: "100%" }
537
- });
538
- } else {
539
- layers.push({
540
- type: "shape",
541
- id: "bg",
542
- content: {
543
- shape: "rect",
544
- fill: colors.bg
545
- },
546
- position: { x: 0, y: 0, width: "100%", height: "100%" }
547
- });
548
- layers.push({
549
- type: "shape",
550
- id: "line-top",
551
- content: { shape: "rect", fill: `${colors.text}33` },
552
- position: { x: "50%", y: "40%", width: "20%", height: "2px", anchor: "center" }
553
- });
554
- layers.push({
555
- type: "shape",
556
- id: "line-bottom",
557
- content: { shape: "rect", fill: `${colors.text}33` },
558
- position: { x: "50%", y: "60%", width: "20%", height: "2px", anchor: "center" }
559
- });
560
- }
561
- layers.push({
562
- type: "text",
563
- id: "title",
564
- content: {
565
- text: title,
566
- style: {
567
- fontSize: titleFontSize,
568
- fontFamily: getThemeFont(context, "title"),
569
- fontWeight: "bold",
570
- color: imageSrc ? "#ffffff" : colors.text,
571
- textAlign: "center",
572
- shadow: true
573
- }
574
- },
575
- position: {
576
- x: "50%",
577
- y: "50%",
578
- anchor: "center",
579
- width: layout.maxTextWidth
580
- },
581
- animation: { type: "fadeIn", duration: 1.5 }
582
- });
583
- return layers;
584
- }
585
-
586
- // src/doc/templates/accentImage.ts
587
- var PERCENTAGE_RE = /^(\d+(?:\.\d+)?)\s*%?$/;
588
- var DEFAULT_LAYOUT = {
589
- textCenterX: "50%",
590
- textWidth: "85%",
591
- textYAdjust: 0,
592
- adjustY: false
593
- };
594
- function mapAmbientMotion(motion, duration) {
595
- if (!motion) return void 0;
596
- const base = duration !== void 0 ? { duration } : {};
597
- switch (motion) {
598
- case "zoomIn":
599
- case "in":
600
- return { type: "slowZoom", direction: "in", ...base };
601
- case "zoomOut":
602
- case "out":
603
- return { type: "slowZoom", direction: "out", ...base };
604
- case "panLeft":
605
- case "left":
606
- return { type: "slowZoom", panDirection: "left", ...base };
607
- case "panRight":
608
- case "right":
609
- return { type: "slowZoom", panDirection: "right", ...base };
610
- default:
611
- return void 0;
612
- }
613
- }
614
- var STRIP_SIZE = 35;
615
- var STRIP_SIZE_PCT = `${STRIP_SIZE}%`;
616
- function getAccentLayout(position) {
617
- switch (position) {
618
- case "left-strip":
619
- return {
620
- textCenterX: `${50 + STRIP_SIZE / 2}%`,
621
- // Shift center right
622
- textWidth: `${100 - STRIP_SIZE - 8}%`,
623
- // Leave margin
624
- textYAdjust: 0,
625
- adjustY: false
626
- };
627
- case "right-strip":
628
- return {
629
- textCenterX: `${50 - STRIP_SIZE / 2}%`,
630
- // Shift center left
631
- textWidth: `${100 - STRIP_SIZE - 8}%`,
632
- textYAdjust: 0,
633
- adjustY: false
634
- };
635
- case "bottom-strip":
636
- return {
637
- textCenterX: "50%",
638
- textWidth: "85%",
639
- textYAdjust: -10,
640
- // Shift content up by 10%
641
- adjustY: true
642
- };
643
- case "corner-inset":
644
- return {
645
- textCenterX: "45%",
646
- // Slight shift to avoid corner
647
- textWidth: "70%",
648
- textYAdjust: 0,
649
- adjustY: false
650
- };
651
- default:
652
- return DEFAULT_LAYOUT;
653
- }
654
- }
655
- function createAccentLayers(accent, slideId) {
656
- const layers = [];
657
- const { src, alt, position, ambientMotion, credit, license } = accent;
658
- switch (position) {
659
- case "left-strip":
660
- layers.push(createStripImage(src, alt, "left", slideId, ambientMotion, credit, license));
661
- layers.push(createStripGradient("left", slideId));
662
- break;
663
- case "right-strip":
664
- layers.push(createStripImage(src, alt, "right", slideId, ambientMotion, credit, license));
665
- layers.push(createStripGradient("right", slideId));
666
- break;
667
- case "bottom-strip":
668
- layers.push(createBottomStripImage(src, alt, slideId, ambientMotion, credit, license));
669
- layers.push(createBottomStripGradient(slideId));
670
- break;
671
- case "corner-inset":
672
- layers.push(createCornerInsetImage(src, alt, slideId, ambientMotion, credit, license));
673
- layers.push(createCornerVignette(slideId));
674
- break;
675
- }
676
- return layers;
677
- }
678
- function createStripImage(src, alt, side, slideId, ambientMotion, credit, license) {
679
- return {
680
- type: "image",
681
- id: `${slideId}-accent-img`,
682
- content: {
683
- src,
684
- alt,
685
- fit: "cover",
686
- credit,
687
- license
688
- },
689
- position: {
690
- x: side === "left" ? 0 : `${100 - STRIP_SIZE}%`,
691
- y: 0,
692
- width: STRIP_SIZE_PCT,
693
- height: "100%"
694
- },
695
- animation: mapAmbientMotion(ambientMotion, 15)
696
- };
697
- }
698
- function createStripGradient(side, slideId) {
699
- const gradientId = side === "left" ? "accent-gradient-left" : "accent-gradient-right";
700
- return {
701
- type: "shape",
702
- id: `${slideId}-accent-fade`,
703
- content: {
704
- shape: "rect",
705
- // SVG gradient will be handled by the renderer
706
- // Using a semi-transparent overlay as fallback
707
- fill: `url(#${gradientId})`
708
- },
709
- position: {
710
- x: side === "left" ? `${STRIP_SIZE - 8}%` : `${100 - STRIP_SIZE}%`,
711
- y: 0,
712
- width: "10%",
713
- height: "100%"
714
- }
715
- };
716
- }
717
- function createBottomStripImage(src, alt, slideId, ambientMotion, credit, license) {
718
- return {
719
- type: "image",
720
- id: `${slideId}-accent-img`,
721
- content: {
722
- src,
723
- alt,
724
- fit: "cover",
725
- credit,
726
- license
727
- },
728
- position: {
729
- x: 0,
730
- y: `${100 - STRIP_SIZE}%`,
731
- width: "100%",
732
- height: STRIP_SIZE_PCT
733
- },
734
- animation: mapAmbientMotion(ambientMotion, 15)
735
- };
736
- }
737
- function createBottomStripGradient(slideId) {
738
- return {
739
- type: "shape",
740
- id: `${slideId}-accent-fade`,
741
- content: {
742
- shape: "rect",
743
- fill: "url(#accent-gradient-bottom)"
744
- },
745
- position: {
746
- x: 0,
747
- y: `${100 - STRIP_SIZE - 8}%`,
748
- width: "100%",
749
- height: "12%"
750
- }
751
- };
752
- }
753
- function createCornerInsetImage(src, alt, slideId, ambientMotion, credit, license) {
754
- return {
755
- type: "image",
756
- id: `${slideId}-accent-img`,
757
- content: {
758
- src,
759
- alt,
760
- fit: "cover",
761
- credit,
762
- license
763
- },
764
- position: {
765
- x: "70%",
766
- y: "60%",
767
- width: "28%",
768
- height: "38%",
769
- anchor: "top-left"
770
- },
771
- animation: mapAmbientMotion(ambientMotion, 15) ?? { type: "fadeIn", duration: 2, delay: 0.5 }
772
- };
773
- }
774
- function createCornerVignette(slideId) {
775
- return {
776
- type: "shape",
777
- id: `${slideId}-accent-vignette`,
778
- content: {
779
- shape: "rect",
780
- fill: "url(#accent-vignette-corner)",
781
- borderRadius: 8
782
- },
783
- position: {
784
- x: "69%",
785
- y: "59%",
786
- width: "30%",
787
- height: "40%"
788
- }
789
- };
790
- }
791
- function adjustY(originalY, layout) {
792
- if (!layout.adjustY || layout.textYAdjust === 0) {
793
- return typeof originalY === "number" ? `${originalY}%` : originalY;
794
- }
795
- const yStr = typeof originalY === "number" ? `${originalY}` : originalY;
796
- const match = yStr.match(PERCENTAGE_RE);
797
- if (match) {
798
- const yValue = parseFloat(match[1]);
799
- const adjusted = Math.max(5, yValue + layout.textYAdjust);
800
- return `${adjusted}%`;
801
- }
802
- return yStr;
803
- }
804
-
805
- // src/doc/templates/captionUtils.ts
806
- var TRAILING_PUNCT_RE = /[.;:!?]+$/;
807
- function cleanCaption(text) {
808
- return text.replace(TRAILING_PUNCT_RE, "").trim();
809
- }
810
- function createBackgroundLayer(id, fill) {
811
- return {
812
- type: "shape",
813
- id,
814
- content: { shape: "rect", fill },
815
- position: { x: 0, y: 0, width: "100%", height: "100%" }
816
- };
817
- }
818
-
819
- // src/doc/templates/statHighlight.ts
820
- function statHighlight(input, context) {
821
- const { stat, description, detail, colorScheme = "blue", accentImage } = input;
822
- const { theme } = context;
823
- const colors = resolveColorScheme(context, colorScheme);
824
- const accentLayout = accentImage ? getAccentLayout(accentImage.position) : DEFAULT_LAYOUT;
825
- const statFontSize = scaledFontSize(148, context, true);
826
- const descFontSize = scaledFontSize(32, context, false);
827
- const detailFontSize = scaledFontSize(26, context, false);
828
- const layers = [
829
- createBackgroundLayer(
830
- "bg",
831
- `linear-gradient(180deg, ${theme.colors.background} 0%, #0f1520 100%)`
832
- )
833
- ];
834
- if (accentImage) {
835
- layers.push(...createAccentLayers(accentImage, input.id));
836
- }
837
- layers.push({
838
- type: "text",
839
- id: "stat",
840
- content: {
841
- text: stat,
842
- style: {
843
- fontSize: statFontSize,
844
- fontFamily: getThemeFont(context, "title"),
845
- fontWeight: "bold",
846
- color: colors.text,
847
- shadow: !!accentImage
848
- }
849
- },
850
- position: {
851
- x: accentLayout.textCenterX,
852
- y: adjustY("32%", accentLayout),
853
- anchor: "center"
854
- },
855
- animation: { type: "zoomIn", duration: 0.6 }
856
- });
857
- layers.push({
858
- type: "text",
859
- id: "description",
860
- content: {
861
- text: description,
862
- style: {
863
- fontSize: descFontSize,
864
- fontFamily: getThemeFont(context, "body"),
865
- color: theme.colors.textMuted,
866
- textAlign: "center",
867
- lineHeight: 1.6,
868
- shadow: !!accentImage
869
- }
870
- },
871
- position: {
872
- x: accentLayout.textCenterX,
873
- y: adjustY("58%", accentLayout),
874
- width: accentLayout.textWidth,
875
- anchor: "center"
876
- },
877
- animation: { type: "fadeIn", duration: 1, delay: 0.3 }
878
- });
879
- if (detail) {
880
- layers.push({
881
- type: "text",
882
- id: "detail",
883
- content: {
884
- text: detail,
885
- style: {
886
- fontSize: detailFontSize,
887
- fontFamily: getThemeFont(context, "body"),
888
- color: colors.accent,
889
- textAlign: "center",
890
- shadow: !!accentImage
891
- }
892
- },
893
- position: {
894
- x: accentLayout.textCenterX,
895
- y: adjustY("75%", accentLayout),
896
- anchor: "center"
897
- },
898
- animation: { type: "fadeIn", duration: 1, delay: 1 }
899
- });
900
- }
901
- return layers;
902
- }
903
-
904
- // src/doc/templates/quoteBlock.ts
905
- function quoteBlock(input, context) {
906
- const { quote, attribution, accentImage } = input;
907
- const { theme, layout } = context;
908
- const accentLayout = accentImage ? getAccentLayout(accentImage.position) : DEFAULT_LAYOUT;
909
- const quoteFontSize = scaledFontSize(48, context, true);
910
- const attrFontSize = scaledFontSize(24, context, false);
911
- const decorativeQuoteFontSize = scaledFontSize(280, context, true);
912
- const layers = [
913
- createBackgroundLayer(
914
- "bg",
915
- `linear-gradient(160deg, ${theme.colors.backgroundLight} 0%, #1e2636 100%)`
916
- )
917
- ];
918
- if (accentImage) {
919
- layers.push(...createAccentLayers(accentImage, input.id));
920
- }
921
- layers.push({
922
- type: "text",
923
- id: "deco-quote",
924
- content: {
925
- text: "\u201C",
926
- style: {
927
- fontSize: decorativeQuoteFontSize,
928
- fontFamily: getThemeFont(context, "title"),
929
- color: "rgba(255, 255, 255, 0.06)",
930
- textAlign: "center"
931
- }
932
- },
933
- position: {
934
- x: accentLayout.textCenterX,
935
- y: adjustY("18%", accentLayout),
936
- anchor: "center"
937
- }
938
- });
939
- const quoteY = attribution ? layout.primaryY : "50%";
940
- layers.push({
941
- type: "text",
942
- id: "quote",
943
- content: {
944
- text: quote,
945
- style: {
946
- fontSize: quoteFontSize,
947
- fontFamily: getThemeFont(context, "title"),
948
- color: theme.colors.text,
949
- textAlign: "center",
950
- lineHeight: 1.6,
951
- shadow: true
952
- }
953
- },
954
- position: {
955
- x: accentLayout.textCenterX,
956
- y: adjustY(quoteY, accentLayout),
957
- anchor: "center",
958
- width: accentLayout.textWidth
959
- },
960
- animation: { type: "fadeIn", duration: 2 }
961
- });
962
- if (attribution) {
963
- layers.push({
964
- type: "text",
965
- id: "attribution",
966
- content: {
967
- text: `\u2014 ${attribution}`,
968
- style: {
969
- fontSize: attrFontSize,
970
- fontFamily: getThemeFont(context, "body"),
971
- color: theme.colors.textMuted,
972
- textAlign: "center",
973
- shadow: !!accentImage
974
- }
975
- },
976
- position: {
977
- x: accentLayout.textCenterX,
978
- y: adjustY(layout.captionY, accentLayout),
979
- anchor: "center"
980
- },
981
- animation: { type: "fadeIn", duration: 1, delay: 1.5 }
982
- });
983
- }
984
- return layers;
985
- }
986
-
987
- // src/doc/templates/factCard.ts
988
- function factCard(input, context) {
989
- const { fact, explanation, source, accentImage } = input;
990
- const { theme } = context;
991
- const accentLayout = accentImage ? getAccentLayout(accentImage.position) : DEFAULT_LAYOUT;
992
- const factFontSize = scaledFontSize(56, context, true);
993
- const explainFontSize = scaledFontSize(32, context, false);
994
- const sourceFontSize = scaledFontSize(20, context, false);
995
- const layers = [
996
- createBackgroundLayer(
997
- "bg",
998
- `linear-gradient(170deg, #1e2030 0%, ${theme.colors.background} 100%)`
999
- )
1000
- ];
1001
- if (accentImage) {
1002
- layers.push(...createAccentLayers(accentImage, input.id));
1003
- }
1004
- layers.push({
1005
- type: "text",
1006
- id: "fact",
1007
- content: {
1008
- text: fact,
1009
- style: {
1010
- fontSize: factFontSize,
1011
- fontFamily: getThemeFont(context, "title"),
1012
- fontWeight: "bold",
1013
- color: theme.colors.text,
1014
- textAlign: "center",
1015
- lineHeight: 1.4,
1016
- shadow: true
1017
- }
1018
- },
1019
- position: {
1020
- x: accentLayout.textCenterX,
1021
- y: adjustY("35%", accentLayout),
1022
- width: accentLayout.textWidth,
1023
- anchor: "center"
1024
- },
1025
- animation: { type: "fadeIn", duration: 1.5 }
1026
- });
1027
- layers.push({
1028
- type: "text",
1029
- id: "explanation",
1030
- content: {
1031
- text: explanation,
1032
- style: {
1033
- fontSize: explainFontSize,
1034
- fontFamily: getThemeFont(context, "body"),
1035
- color: theme.colors.textMuted,
1036
- textAlign: "center",
1037
- lineHeight: 1.5,
1038
- shadow: !!accentImage
1039
- }
1040
- },
1041
- position: {
1042
- x: accentLayout.textCenterX,
1043
- y: adjustY("60%", accentLayout),
1044
- width: accentLayout.textWidth,
1045
- anchor: "center"
1046
- },
1047
- animation: { type: "fadeIn", duration: 1, delay: 0.8 }
1048
- });
1049
- if (source) {
1050
- layers.push({
1051
- type: "text",
1052
- id: "source",
1053
- content: {
1054
- text: source,
1055
- style: {
1056
- fontSize: sourceFontSize,
1057
- fontFamily: getThemeFont(context, "body"),
1058
- color: theme.colors.textMuted,
1059
- textAlign: "center",
1060
- shadow: !!accentImage
1061
- }
1062
- },
1063
- position: {
1064
- x: accentLayout.textCenterX,
1065
- y: adjustY("85%", accentLayout),
1066
- anchor: "center"
1067
- },
1068
- animation: { type: "fadeIn", duration: 0.8, delay: 1.5 }
1069
- });
1070
- }
1071
- return layers;
1072
- }
1073
-
1074
- // src/doc/templates/twoColumn.ts
1075
- function twoColumn(input, context) {
1076
- const { left, right, header, leftColor = "green", rightColor = "blue" } = input;
1077
- if (!left?.label || !right?.label) return [];
1078
- const { theme, layout, orientation } = context;
1079
- const leftColors = resolveColorScheme(context, leftColor);
1080
- const rightColors = resolveColorScheme(context, rightColor);
1081
- const positions = getTwoColumnPositions(orientation);
1082
- const isStacked = layout.stackColumns;
1083
- const columnWidth = isStacked ? "85%" : "42%";
1084
- const headerFontSize = scaledFontSize(32, context, false);
1085
- const labelFontSize = scaledFontSize(44, context, true);
1086
- const sublabelFontSize = scaledFontSize(22, context, false);
1087
- const layers = [
1088
- // Background — subtle gradient to add depth
1089
- {
1090
- type: "shape",
1091
- id: "bg",
1092
- content: {
1093
- shape: "rect",
1094
- fill: `linear-gradient(135deg, ${theme.colors.background} 0%, #16202e 100%)`
1095
- },
1096
- position: { x: 0, y: 0, width: "100%", height: "100%" }
1097
- }
1098
- ];
1099
- if (!isStacked) {
1100
- layers.push({
1101
- type: "shape",
1102
- id: "left-panel",
1103
- content: {
1104
- shape: "rect",
1105
- fill: "rgba(255, 255, 255, 0.04)"
1106
- },
1107
- position: { x: "3%", y: "15%", width: "44%", height: "70%" }
1108
- });
1109
- layers.push({
1110
- type: "shape",
1111
- id: "right-panel",
1112
- content: {
1113
- shape: "rect",
1114
- fill: "rgba(255, 255, 255, 0.04)"
1115
- },
1116
- position: { x: "53%", y: "15%", width: "44%", height: "70%" }
1117
- });
1118
- }
1119
- const headerY = isStacked ? "12%" : "22%";
1120
- if (header) {
1121
- layers.push({
1122
- type: "text",
1123
- id: "header",
1124
- content: {
1125
- text: header,
1126
- style: {
1127
- fontSize: headerFontSize,
1128
- fontFamily: getThemeFont(context, "title"),
1129
- color: theme.colors.textMuted,
1130
- textAlign: "center"
1131
- }
1132
- },
1133
- position: { x: "50%", y: headerY, anchor: "center" },
1134
- animation: { type: "fadeIn", duration: 0.8 }
1135
- });
1136
- }
1137
- let leftY;
1138
- let leftSublabelY;
1139
- let rightY;
1140
- let rightSublabelY;
1141
- if (isStacked) {
1142
- leftY = header ? "30%" : "25%";
1143
- leftSublabelY = header ? "40%" : "35%";
1144
- rightY = header ? "60%" : "55%";
1145
- rightSublabelY = header ? "70%" : "65%";
1146
- } else {
1147
- const baseY = header ? "47%" : "45%";
1148
- const sublabelOffset = header ? "58%" : "56%";
1149
- leftY = baseY;
1150
- leftSublabelY = sublabelOffset;
1151
- rightY = baseY;
1152
- rightSublabelY = sublabelOffset;
1153
- }
1154
- layers.push({
1155
- type: "text",
1156
- id: "left-label",
1157
- content: {
1158
- text: left.label,
1159
- style: {
1160
- fontSize: labelFontSize,
1161
- fontFamily: getThemeFont(context, "body"),
1162
- fontWeight: "bold",
1163
- color: leftColors.text,
1164
- textAlign: "center",
1165
- lineHeight: 1.3
1166
- }
1167
- },
1168
- position: {
1169
- x: positions.left.x,
1170
- y: leftY,
1171
- anchor: "center",
1172
- width: columnWidth
1173
- },
1174
- animation: { type: "fadeIn", duration: 1 }
1175
- });
1176
- if (left.sublabel) {
1177
- layers.push({
1178
- type: "text",
1179
- id: "left-sublabel",
1180
- content: {
1181
- text: left.sublabel,
1182
- style: {
1183
- fontSize: sublabelFontSize,
1184
- fontFamily: getThemeFont(context, "body"),
1185
- color: theme.colors.textMuted,
1186
- textAlign: "center",
1187
- lineHeight: 1.4
1188
- }
1189
- },
1190
- position: {
1191
- x: positions.left.x,
1192
- y: leftSublabelY,
1193
- anchor: "center",
1194
- width: columnWidth
1195
- },
1196
- animation: { type: "fadeIn", duration: 0.8, delay: 0.3 }
1197
- });
1198
- }
1199
- const connectorFontSize = scaledFontSize(120, context, true);
1200
- const connectorY = isStacked ? "48%" : "50%";
1201
- const connectorSymbol = isStacked ? "\u2193" : "\u2192";
1202
- layers.push({
1203
- type: "text",
1204
- id: "connector",
1205
- content: {
1206
- text: connectorSymbol,
1207
- style: {
1208
- fontSize: connectorFontSize,
1209
- fontFamily: getThemeFont(context, "title"),
1210
- fontWeight: "bold",
1211
- color: "rgba(255, 255, 255, 0.6)",
1212
- textAlign: "center"
1213
- }
1214
- },
1215
- position: {
1216
- x: "50%",
1217
- y: connectorY,
1218
- anchor: "center"
1219
- },
1220
- animation: { type: "fadeIn", duration: 0.6, delay: 0.4 }
1221
- });
1222
- layers.push({
1223
- type: "text",
1224
- id: "right-label",
1225
- content: {
1226
- text: right.label,
1227
- style: {
1228
- fontSize: labelFontSize,
1229
- fontFamily: getThemeFont(context, "body"),
1230
- fontWeight: "bold",
1231
- color: rightColors.text,
1232
- textAlign: "center",
1233
- lineHeight: 1.3
1234
- }
1235
- },
1236
- position: {
1237
- x: positions.right.x,
1238
- y: rightY,
1239
- anchor: "center",
1240
- width: columnWidth
1241
- },
1242
- animation: { type: "fadeIn", duration: 1, delay: 0.5 }
1243
- });
1244
- if (right.sublabel) {
1245
- layers.push({
1246
- type: "text",
1247
- id: "right-sublabel",
1248
- content: {
1249
- text: right.sublabel,
1250
- style: {
1251
- fontSize: sublabelFontSize,
1252
- fontFamily: getThemeFont(context, "body"),
1253
- color: theme.colors.textMuted,
1254
- textAlign: "center",
1255
- lineHeight: 1.4
1256
- }
1257
- },
1258
- position: {
1259
- x: positions.right.x,
1260
- y: rightSublabelY,
1261
- anchor: "center",
1262
- width: columnWidth
1263
- },
1264
- animation: { type: "fadeIn", duration: 0.8, delay: 0.8 }
1265
- });
1266
- }
1267
- return layers;
1268
- }
1269
-
1270
- // src/doc/templates/dateEvent.ts
1271
- var MOOD_COLORS = {
1272
- neutral: { bg: "#1a202c", date: "#63b3ed", text: "#ffffff" },
1273
- somber: { bg: "#1a1a2e", date: "#e53e3e", text: "#a0aec0" },
1274
- celebratory: { bg: "#1a365d", date: "#68d391", text: "#ffffff" }
1275
- };
1276
- function dateEvent(input, context) {
1277
- const { date, description, footer, mood = "neutral", accentImage } = input;
1278
- const { theme } = context;
1279
- const colors = MOOD_COLORS[mood];
1280
- const accentLayout = accentImage ? getAccentLayout(accentImage.position) : DEFAULT_LAYOUT;
1281
- const dateFontSize = scaledFontSize(96, context, true);
1282
- const descFontSize = scaledFontSize(30, context, false);
1283
- const footerFontSize = scaledFontSize(26, context, false);
1284
- const layers = [
1285
- // Background — unique diagonal gradient to differentiate from other dark templates
1286
- {
1287
- type: "shape",
1288
- id: "bg",
1289
- content: {
1290
- shape: "rect",
1291
- fill: `linear-gradient(135deg, ${colors.bg} 0%, #0d1117 100%)`
1292
- },
1293
- position: { x: 0, y: 0, width: "100%", height: "100%" }
1294
- }
1295
- ];
1296
- if (accentImage) {
1297
- layers.push(...createAccentLayers(accentImage, input.id));
1298
- }
1299
- layers.push({
1300
- type: "text",
1301
- id: "date",
1302
- content: {
1303
- text: date,
1304
- style: {
1305
- fontSize: dateFontSize,
1306
- fontFamily: getThemeFont(context, "title"),
1307
- fontWeight: "bold",
1308
- color: colors.date,
1309
- shadow: !!accentImage
1310
- }
1311
- },
1312
- position: {
1313
- x: accentLayout.textCenterX,
1314
- y: adjustY("35%", accentLayout),
1315
- anchor: "center"
1316
- },
1317
- animation: { type: "fadeIn", duration: 1.5 }
1318
- });
1319
- layers.push({
1320
- type: "text",
1321
- id: "description",
1322
- content: {
1323
- text: description,
1324
- style: {
1325
- fontSize: descFontSize,
1326
- fontFamily: getThemeFont(context, "body"),
1327
- color: colors.text,
1328
- textAlign: "center",
1329
- lineHeight: 1.8,
1330
- shadow: !!accentImage
1331
- }
1332
- },
1333
- position: {
1334
- x: accentLayout.textCenterX,
1335
- y: adjustY("58%", accentLayout),
1336
- width: accentLayout.textWidth,
1337
- anchor: "center"
1338
- },
1339
- animation: { type: "fadeIn", duration: 2, delay: 1 }
1340
- });
1341
- if (footer) {
1342
- layers.push({
1343
- type: "text",
1344
- id: "footer",
1345
- content: {
1346
- text: footer,
1347
- style: {
1348
- fontSize: footerFontSize,
1349
- fontFamily: getThemeFont(context, "body"),
1350
- color: theme.colors.textMuted,
1351
- shadow: !!accentImage
1352
- }
1353
- },
1354
- position: {
1355
- x: accentLayout.textCenterX,
1356
- y: adjustY("82%", accentLayout),
1357
- anchor: "center"
1358
- },
1359
- animation: { type: "fadeIn", duration: 1, delay: 3 }
1360
- });
1361
- }
1362
- return layers;
1363
- }
1364
-
1365
- // src/doc/templates/imageWithCaption.ts
1366
- function imageWithCaption(input, context) {
1367
- const {
1368
- imageSrc,
1369
- imageAlt,
1370
- caption: rawCaption,
1371
- captionPosition: _captionPosition = "bottom",
1372
- ambientMotion,
1373
- isTitle,
1374
- subtitle,
1375
- imageCredit,
1376
- imageLicense
1377
- } = input;
1378
- const caption = rawCaption ? cleanCaption(rawCaption) : rawCaption;
1379
- const { theme, layout } = context;
1380
- const captionFontSize = scaledFontSize(36, context, false);
1381
- const titleFontSize = scaledFontSize(96, context, true);
1382
- const subtitleFontSize = scaledFontSize(36, context, false);
1383
- const legacyKenBurns = input.kenBurns;
1384
- const motion = ambientMotion || legacyKenBurns;
1385
- const imageAnimation = mapAmbientMotion(motion);
1386
- const layers = [
1387
- // Background image
1388
- {
1389
- type: "image",
1390
- id: "bg-image",
1391
- content: {
1392
- src: imageSrc,
1393
- alt: imageAlt,
1394
- fit: "cover",
1395
- credit: imageCredit,
1396
- license: imageLicense
1397
- },
1398
- position: { x: 0, y: 0, width: "100%", height: "100%" },
1399
- animation: imageAnimation
1400
- }
1401
- ];
1402
- if (isTitle && caption) {
1403
- layers.push({
1404
- type: "shape",
1405
- id: "title-gradient",
1406
- content: {
1407
- shape: "rect",
1408
- fill: "linear-gradient(0deg, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.4) 40%, rgba(0,0,0,0.1) 70%, transparent 100%)"
1409
- },
1410
- position: { x: 0, y: 0, width: "100%", height: "100%" }
1411
- });
1412
- layers.push({
1413
- type: "text",
1414
- id: "title",
1415
- content: {
1416
- text: caption,
1417
- style: {
1418
- fontSize: titleFontSize,
1419
- fontFamily: getThemeFont(context, "title"),
1420
- fontWeight: "bold",
1421
- color: theme.colors.text,
1422
- textAlign: "center",
1423
- shadow: true
1424
- }
1425
- },
1426
- position: {
1427
- x: "50%",
1428
- y: subtitle ? "70%" : "75%",
1429
- anchor: "center",
1430
- width: layout.maxTextWidth
1431
- },
1432
- animation: { type: "fadeIn", duration: 0.8 }
1433
- });
1434
- if (subtitle) {
1435
- layers.push({
1436
- type: "text",
1437
- id: "subtitle",
1438
- content: {
1439
- text: subtitle,
1440
- style: {
1441
- fontSize: subtitleFontSize,
1442
- fontFamily: getThemeFont(context, "body"),
1443
- color: theme.colors.textMuted,
1444
- textAlign: "center",
1445
- lineHeight: 1.5
1446
- }
1447
- },
1448
- position: {
1449
- x: "50%",
1450
- y: "82%",
1451
- anchor: "center",
1452
- width: layout.maxTextWidth
1453
- },
1454
- animation: { type: "fadeIn", duration: 0.8, delay: 0.2 }
1455
- });
1456
- }
1457
- return layers;
1458
- }
1459
- if (caption) {
1460
- layers.push({
1461
- type: "shape",
1462
- id: "caption-gradient",
1463
- content: {
1464
- shape: "rect",
1465
- fill: "linear-gradient(0deg, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.3) 60%, transparent 100%)"
1466
- },
1467
- position: {
1468
- x: 0,
1469
- y: "65%",
1470
- width: "100%",
1471
- height: "35%"
1472
- }
1473
- });
1474
- layers.push({
1475
- type: "text",
1476
- id: "caption",
1477
- content: {
1478
- text: caption,
1479
- style: {
1480
- fontSize: captionFontSize,
1481
- fontFamily: getThemeFont(context, "body"),
1482
- color: theme.colors.text,
1483
- textAlign: "center",
1484
- shadow: true
1485
- }
1486
- },
1487
- position: {
1488
- x: "50%",
1489
- y: "82%",
1490
- anchor: "center",
1491
- width: layout.maxTextWidth
1492
- },
1493
- animation: { type: "fadeIn", duration: 1.5, delay: 0.5 }
1494
- });
1495
- }
1496
- return layers;
1497
- }
1498
-
1499
- // src/doc/templates/featureBlock.ts
1500
- function buildFeatureLayers(input, context, side) {
1501
- const { imageSrc, imageAlt, imageWidth, imageHeight, title, body } = input;
1502
- const { theme, layout } = context;
1503
- const sized = (imageWidth ?? 0) > 0 || (imageHeight ?? 0) > 0;
1504
- const stack = layout.stackColumns;
1505
- const titleFontSize = scaledFontSize(48, context, true);
1506
- const bodyFontSize = scaledFontSize(24, context, false);
1507
- let imgX;
1508
- let imgY;
1509
- let imgW;
1510
- let imgH;
1511
- let imageFit;
1512
- if (stack) {
1513
- imgX = "0";
1514
- imgY = "0";
1515
- imgW = "100%";
1516
- imgH = "50%";
1517
- imageFit = sized ? "contain" : "cover";
1518
- } else if (sized) {
1519
- const halfStart = side === "left" ? 5 : 55;
1520
- imgX = `${halfStart}%`;
1521
- imgY = "5%";
1522
- imgW = "40%";
1523
- imgH = "90%";
1524
- imageFit = "contain";
1525
- } else {
1526
- imgX = side === "left" ? "0" : "50%";
1527
- imgY = "0";
1528
- imgW = "50%";
1529
- imgH = "100%";
1530
- imageFit = "cover";
1531
- }
1532
- const COLUMN_INSET = 4;
1533
- const textColumnWidth = stack ? 90 : 42;
1534
- const textX = stack ? `${(100 - textColumnWidth) / 2}%` : side === "left" ? `${50 + COLUMN_INSET}%` : `${50 - COLUMN_INSET}%`;
1535
- const titleY = stack ? "60%" : body ? "42%" : "50%";
1536
- const bodyY = stack ? "78%" : title ? "55%" : "50%";
1537
- const textAnchor = side === "right" && !stack ? "top-right" : "top-left";
1538
- const textAlign = side === "right" && !stack ? "right" : "left";
1539
- const layers = [
1540
- {
1541
- type: "shape",
1542
- id: "feature-bg",
1543
- content: { shape: "rect", fill: theme.colors.background },
1544
- position: { x: 0, y: 0, width: "100%", height: "100%" }
1545
- }
1546
- ];
1547
- if (imageSrc) {
1548
- layers.push({
1549
- type: "image",
1550
- id: "feature-image",
1551
- content: {
1552
- src: imageSrc,
1553
- alt: imageAlt ?? title ?? "",
1554
- fit: imageFit
1555
- },
1556
- position: { x: imgX, y: imgY, width: imgW, height: imgH }
1557
- });
1558
- }
1559
- if (title) {
1560
- layers.push({
1561
- type: "text",
1562
- id: "feature-title",
1563
- content: {
1564
- text: title,
1565
- style: {
1566
- fontSize: titleFontSize,
1567
- fontFamily: getThemeFont(context, "title"),
1568
- fontWeight: "bold",
1569
- color: theme.colors.text,
1570
- textAlign,
1571
- lineHeight: 1.2
1572
- }
1573
- },
1574
- position: {
1575
- x: textX,
1576
- y: titleY,
1577
- anchor: textAnchor,
1578
- width: `${textColumnWidth}%`
1579
- },
1580
- animation: { type: "fadeIn", duration: 0.8 }
1581
- });
1582
- }
1583
- if (body) {
1584
- layers.push({
1585
- type: "text",
1586
- id: "feature-body",
1587
- content: {
1588
- text: body,
1589
- style: {
1590
- fontSize: bodyFontSize,
1591
- fontFamily: getThemeFont(context, "body"),
1592
- color: theme.colors.textMuted,
1593
- textAlign,
1594
- lineHeight: 1.5
1595
- }
1596
- },
1597
- position: {
1598
- x: textX,
1599
- y: bodyY,
1600
- anchor: textAnchor,
1601
- width: `${textColumnWidth}%`
1602
- },
1603
- animation: { type: "fadeIn", duration: 0.8, delay: 0.2 }
1604
- });
1605
- }
1606
- return layers;
1607
- }
1608
- function leftFeature(input, context) {
1609
- return buildFeatureLayers(input, context, "left");
1610
- }
1611
- function rightFeature(input, context) {
1612
- return buildFeatureLayers(input, context, "right");
1613
- }
1614
-
1615
- // src/doc/templates/mapBlock.ts
1616
- function mapBlock(input, context) {
1617
- const {
1618
- center,
1619
- zoom,
1620
- mapStyle = "terrain",
1621
- title,
1622
- caption,
1623
- markers,
1624
- ambientMotion,
1625
- staticSrc
1626
- } = input;
1627
- const { theme, layout } = context;
1628
- const titleFontSize = scaledFontSize(64, context, true);
1629
- const captionFontSize = scaledFontSize(32, context, false);
1630
- const mapAnimation = mapAmbientMotion(ambientMotion);
1631
- const layers = [
1632
- // Map background
1633
- {
1634
- type: "map",
1635
- id: "map-bg",
1636
- content: {
1637
- center,
1638
- zoom,
1639
- style: mapStyle,
1640
- markers,
1641
- showAttribution: true,
1642
- staticSrc
1643
- // Use pre-rendered image if available
1644
- },
1645
- position: { x: 0, y: 0, width: "100%", height: "100%" },
1646
- animation: mapAnimation
1647
- }
1648
- ];
1649
- if (title) {
1650
- layers.push({
1651
- type: "shape",
1652
- id: "title-overlay",
1653
- content: {
1654
- shape: "rect",
1655
- fill: "rgba(0,0,0,0.6)"
1656
- },
1657
- position: { x: 0, y: 0, width: "100%", height: "18%" }
1658
- });
1659
- layers.push({
1660
- type: "text",
1661
- id: "title",
1662
- content: {
1663
- text: title,
1664
- style: {
1665
- fontSize: titleFontSize,
1666
- fontFamily: getThemeFont(context, "title"),
1667
- fontWeight: "bold",
1668
- color: theme.colors.text,
1669
- textAlign: "center",
1670
- shadow: true
1671
- }
1672
- },
1673
- position: {
1674
- x: "50%",
1675
- y: "9%",
1676
- anchor: "center",
1677
- width: layout.maxTextWidth
1678
- },
1679
- animation: { type: "fadeIn", duration: 1, delay: 0.3 }
1680
- });
1681
- }
1682
- if (caption) {
1683
- layers.push({
1684
- type: "shape",
1685
- id: "caption-overlay",
1686
- content: {
1687
- shape: "rect",
1688
- fill: "rgba(0,0,0,0.6)"
1689
- },
1690
- position: { x: 0, y: "82%", width: "100%", height: "18%" }
1691
- });
1692
- layers.push({
1693
- type: "text",
1694
- id: "caption",
1695
- content: {
1696
- text: caption,
1697
- style: {
1698
- fontSize: captionFontSize,
1699
- fontFamily: getThemeFont(context, "body"),
1700
- color: theme.colors.text,
1701
- textAlign: "center",
1702
- shadow: true
1703
- }
1704
- },
1705
- position: {
1706
- x: "50%",
1707
- y: layout.captionY,
1708
- anchor: "center",
1709
- width: layout.maxTextWidth
1710
- },
1711
- animation: { type: "fadeIn", duration: 1, delay: 0.5 }
1712
- });
1713
- }
1714
- return layers;
1715
- }
1716
-
1717
- // src/doc/templates/fullBleedQuote.ts
1718
- function fullBleedQuote(input, context) {
1719
- const { text, colorScheme = "blue" } = input;
1720
- const { theme } = context;
1721
- const colors = resolveColorScheme(context, colorScheme);
1722
- const textFontSize = scaledFontSize(120, context, true);
1723
- return [
1724
- // Background — dark radial vignette for cinematic feel
1725
- {
1726
- type: "shape",
1727
- id: "bg",
1728
- content: {
1729
- shape: "rect",
1730
- fill: `radial-gradient(ellipse at 50% 50%, ${theme.colors.backgroundLight} 0%, #000000 100%)`
1731
- },
1732
- position: { x: 0, y: 0, width: "100%", height: "100%" }
1733
- },
1734
- // The text — massive, centered
1735
- {
1736
- type: "text",
1737
- id: "impact-text",
1738
- content: {
1739
- text,
1740
- style: {
1741
- fontSize: textFontSize,
1742
- fontFamily: getThemeFont(context, "title"),
1743
- fontWeight: "bold",
1744
- color: colors.text,
1745
- textAlign: "center",
1746
- lineHeight: 1.2,
1747
- shadow: true
1748
- }
1749
- },
1750
- position: {
1751
- x: "50%",
1752
- y: "50%",
1753
- anchor: "center",
1754
- width: "85%"
1755
- },
1756
- animation: { type: "fadeIn", duration: 1.5 }
1757
- }
1758
- ];
1759
- }
1760
-
1761
- // src/doc/templates/listBlock.ts
1762
- function listBlock(input, context) {
1763
- const { title, accentImage } = input;
1764
- const items = Array.isArray(input.items) ? input.items : [];
1765
- const { theme } = context;
1766
- const accentLayout = accentImage ? getAccentLayout(accentImage.position) : DEFAULT_LAYOUT;
1767
- const titleFontSize = scaledFontSize(44, context, true);
1768
- const itemFontSize = scaledFontSize(34, context, false);
1769
- const layers = [
1770
- // Background — gradient
1771
- {
1772
- type: "shape",
1773
- id: "bg",
1774
- content: {
1775
- shape: "rect",
1776
- fill: `linear-gradient(155deg, ${theme.colors.backgroundLight} 0%, ${theme.colors.background} 100%)`
1777
- },
1778
- position: { x: 0, y: 0, width: "100%", height: "100%" }
1779
- }
1780
- ];
1781
- if (accentImage) {
1782
- layers.push(...createAccentLayers(accentImage, input.id));
1783
- }
1784
- const startY = title ? 30 : 22;
1785
- if (title) {
1786
- layers.push({
1787
- type: "text",
1788
- id: "list-title",
1789
- content: {
1790
- text: title,
1791
- style: {
1792
- fontSize: titleFontSize,
1793
- fontFamily: getThemeFont(context, "title"),
1794
- fontWeight: "bold",
1795
- color: theme.colors.text,
1796
- textAlign: "center",
1797
- shadow: !!accentImage
1798
- }
1799
- },
1800
- position: {
1801
- x: accentLayout.textCenterX,
1802
- y: adjustY("16%", accentLayout),
1803
- anchor: "center"
1804
- },
1805
- animation: { type: "fadeIn", duration: 1 }
1806
- });
1807
- }
1808
- const centerX = parseFloat(accentLayout.textCenterX);
1809
- const widthPct = parseFloat(accentLayout.textWidth);
1810
- const leftX = Number.isFinite(centerX) && Number.isFinite(widthPct) ? `${centerX - widthPct / 2}%` : "8%";
1811
- const endY = 80;
1812
- const spacing = items.length > 1 ? (endY - startY) / (items.length - 1) : 0;
1813
- for (let i = 0; i < items.length; i++) {
1814
- const y = startY + spacing * i;
1815
- const itemText = `${i + 1}. ${items[i]}`;
1816
- layers.push({
1817
- type: "text",
1818
- id: `item-${i}`,
1819
- content: {
1820
- text: itemText,
1821
- style: {
1822
- fontSize: itemFontSize,
1823
- fontFamily: getThemeFont(context, "body"),
1824
- color: theme.colors.text,
1825
- textAlign: "left",
1826
- lineHeight: 1.2,
1827
- shadow: !!accentImage
1828
- }
1829
- },
1830
- position: {
1831
- x: leftX,
1832
- y: adjustY(`${y}%`, accentLayout),
1833
- width: accentLayout.textWidth
1834
- },
1835
- animation: { type: "fadeIn", duration: 0.8, delay: 0.3 + 0.3 * i }
1836
- });
1837
- }
1838
- return layers;
1839
- }
1840
-
1841
- // src/doc/templates/photoGrid.ts
1842
- var GAP = 0.5;
1843
- function photoGrid(input, context) {
1844
- const { images, caption: rawCaption, ambientMotion } = input;
1845
- if (!images || images.length === 0) return [];
1846
- const caption = rawCaption ? cleanCaption(rawCaption) : rawCaption;
1847
- const { theme, layout } = context;
1848
- const layers = [
1849
- // Black background (visible in gaps between images)
1850
- {
1851
- type: "shape",
1852
- id: "bg",
1853
- content: { shape: "rect", fill: "#000000" },
1854
- position: { x: 0, y: 0, width: "100%", height: "100%" }
1855
- }
1856
- ];
1857
- const captionHeight = caption ? layout.stackColumns ? 18 : 22 : 0;
1858
- const gridHeight = 100 - captionHeight;
1859
- const positions = getGridPositions(images.length, gridHeight, layout.stackColumns);
1860
- const altFontSize = scaledFontSize(24, context, false);
1861
- for (let i = 0; i < Math.min(images.length, 4); i++) {
1862
- const img = images[i];
1863
- const pos = positions[i];
1864
- layers.push({
1865
- type: "shape",
1866
- id: `grid-placeholder-${i}`,
1867
- content: { shape: "rect", fill: theme.colors.background },
1868
- position: { x: `${pos.x}%`, y: `${pos.y}%`, width: `${pos.w}%`, height: `${pos.h}%` }
1869
- });
1870
- if (img.alt) {
1871
- layers.push({
1872
- type: "text",
1873
- id: `grid-alt-${i}`,
1874
- content: {
1875
- text: img.alt,
1876
- style: {
1877
- fontSize: altFontSize,
1878
- fontFamily: getThemeFont(context, "body"),
1879
- color: theme.colors.textMuted,
1880
- textAlign: "center"
1881
- }
1882
- },
1883
- position: { x: `${pos.x + pos.w / 2}%`, y: `${pos.y + pos.h / 2}%`, anchor: "center" }
1884
- });
1885
- }
1886
- layers.push({
1887
- type: "image",
1888
- id: `grid-img-${i}`,
1889
- content: {
1890
- src: img.src,
1891
- alt: img.alt,
1892
- fit: "cover",
1893
- credit: img.credit,
1894
- license: img.license
1895
- },
1896
- position: {
1897
- x: `${pos.x}%`,
1898
- y: `${pos.y}%`,
1899
- width: `${pos.w}%`,
1900
- height: `${pos.h}%`
1901
- },
1902
- // Apply ambient motion to the first (largest) image only
1903
- animation: i === 0 && ambientMotion ? { type: ambientMotion, duration: 15 } : { type: "fadeIn", duration: 1, delay: 0.2 * i }
1904
- });
1905
- }
1906
- if (caption) {
1907
- const captionFontSize = scaledFontSize(layout.stackColumns ? 28 : 40, context, false);
1908
- layers.push({
1909
- type: "shape",
1910
- id: "caption-bg",
1911
- content: {
1912
- shape: "rect",
1913
- fill: "linear-gradient(transparent, rgba(0,0,0,0.8))"
1914
- },
1915
- position: { x: 0, y: `${gridHeight - 4}%`, width: "100%", height: `${captionHeight + 4}%` }
1916
- });
1917
- layers.push({
1918
- type: "text",
1919
- id: "caption",
1920
- content: {
1921
- text: caption,
1922
- style: {
1923
- fontSize: captionFontSize,
1924
- fontFamily: getThemeFont(context, "body"),
1925
- color: theme.colors.text,
1926
- textAlign: "center",
1927
- shadow: true
1928
- }
1929
- },
1930
- position: {
1931
- x: "50%",
1932
- y: `${gridHeight + (layout.stackColumns ? captionHeight / 2 : captionHeight * 0.3)}%`,
1933
- anchor: "center",
1934
- width: "90%"
1935
- },
1936
- animation: { type: "fadeIn", duration: 1, delay: 0.5 }
1937
- });
1938
- }
1939
- return layers;
1940
- }
1941
- function getGridPositions(count, gridHeight, stacked) {
1942
- const halfW = 50 - GAP / 2;
1943
- const halfH = gridHeight / 2 - GAP / 2;
1944
- switch (count) {
1945
- case 2:
1946
- if (stacked) {
1947
- return [
1948
- { x: 0, y: 0, w: 100, h: halfH },
1949
- { x: 0, y: gridHeight / 2 + GAP / 2, w: 100, h: halfH }
1950
- ];
1951
- }
1952
- return [
1953
- { x: 0, y: 0, w: halfW, h: gridHeight },
1954
- { x: 50 + GAP / 2, y: 0, w: halfW, h: gridHeight }
1955
- ];
1956
- case 3: {
1957
- if (stacked) {
1958
- const thirdH = gridHeight / 3 - GAP * 2 / 3;
1959
- return [
1960
- { x: 0, y: 0, w: 100, h: thirdH },
1961
- { x: 0, y: gridHeight / 3 + GAP / 3, w: 100, h: thirdH },
1962
- { x: 0, y: gridHeight * 2 / 3 + GAP * 2 / 3, w: 100, h: thirdH }
1963
- ];
1964
- }
1965
- const leftW = 60 - GAP / 2;
1966
- const rightW = 40 - GAP / 2;
1967
- return [
1968
- { x: 0, y: 0, w: leftW, h: gridHeight },
1969
- { x: 60 + GAP / 2, y: 0, w: rightW, h: halfH },
1970
- { x: 60 + GAP / 2, y: gridHeight / 2 + GAP / 2, w: rightW, h: halfH }
1971
- ];
1972
- }
1973
- case 4:
1974
- default:
1975
- return [
1976
- { x: 0, y: 0, w: halfW, h: halfH },
1977
- { x: 50 + GAP / 2, y: 0, w: halfW, h: halfH },
1978
- { x: 0, y: gridHeight / 2 + GAP / 2, w: halfW, h: halfH },
1979
- { x: 50 + GAP / 2, y: gridHeight / 2 + GAP / 2, w: halfW, h: halfH }
1980
- ];
1981
- }
1982
- }
1983
-
1984
- // src/doc/templates/definitionCard.ts
1985
- function definitionCard(input, context) {
1986
- const { term, definition, origin, colorScheme = "blue", accentImage } = input;
1987
- const { theme } = context;
1988
- const colors = resolveColorScheme(context, colorScheme);
1989
- const accentLayout = accentImage ? getAccentLayout(accentImage.position) : DEFAULT_LAYOUT;
1990
- const termFontSize = scaledFontSize(72, context, true);
1991
- const defFontSize = scaledFontSize(32, context, false);
1992
- const originFontSize = scaledFontSize(22, context, false);
1993
- const layers = [
1994
- createBackgroundLayer(
1995
- "bg",
1996
- `linear-gradient(145deg, #1e2030 0%, ${theme.colors.background} 100%)`
1997
- )
1998
- ];
1999
- if (accentImage) {
2000
- layers.push(...createAccentLayers(accentImage, input.id));
2001
- }
2002
- layers.push({
2003
- type: "text",
2004
- id: "term",
2005
- content: {
2006
- text: term,
2007
- style: {
2008
- fontSize: termFontSize,
2009
- fontFamily: getThemeFont(context, "title"),
2010
- fontWeight: "bold",
2011
- color: colors.text,
2012
- textAlign: "center",
2013
- shadow: !!accentImage
2014
- }
2015
- },
2016
- position: {
2017
- x: accentLayout.textCenterX,
2018
- y: adjustY("30%", accentLayout),
2019
- anchor: "center"
2020
- },
2021
- animation: { type: "fadeIn", duration: 1.5 }
2022
- });
2023
- layers.push({
2024
- type: "shape",
2025
- id: "separator",
2026
- content: {
2027
- shape: "rect",
2028
- fill: `${colors.text}33`
2029
- // accent color at 20% opacity
2030
- },
2031
- position: {
2032
- x: accentLayout.textCenterX,
2033
- y: adjustY("42%", accentLayout),
2034
- width: "30%",
2035
- height: "2px",
2036
- anchor: "center"
2037
- }
2038
- });
2039
- layers.push({
2040
- type: "text",
2041
- id: "definition",
2042
- content: {
2043
- text: definition,
2044
- style: {
2045
- fontSize: defFontSize,
2046
- fontFamily: getThemeFont(context, "body"),
2047
- color: theme.colors.text,
2048
- textAlign: "center",
2049
- lineHeight: 1.6,
2050
- maxLines: 4,
2051
- shadow: !!accentImage
2052
- }
2053
- },
2054
- position: {
2055
- x: accentLayout.textCenterX,
2056
- y: adjustY("55%", accentLayout),
2057
- width: accentLayout.textWidth,
2058
- anchor: "center"
2059
- },
2060
- animation: { type: "fadeIn", duration: 1, delay: 0.8 }
2061
- });
2062
- if (origin) {
2063
- layers.push({
2064
- type: "text",
2065
- id: "origin",
2066
- content: {
2067
- text: origin,
2068
- style: {
2069
- fontSize: originFontSize,
2070
- fontFamily: getThemeFont(context, "body"),
2071
- color: theme.colors.textMuted,
2072
- textAlign: "center",
2073
- shadow: !!accentImage
2074
- }
2075
- },
2076
- position: {
2077
- x: accentLayout.textCenterX,
2078
- y: adjustY("78%", accentLayout),
2079
- anchor: "center"
2080
- },
2081
- animation: { type: "fadeIn", duration: 0.8, delay: 1.5 }
2082
- });
2083
- }
2084
- return layers;
2085
- }
2086
-
2087
- // src/doc/templates/comparisonBar.ts
2088
- function comparisonBar(input, context) {
2089
- const { leftLabel, leftValue, rightLabel, rightValue, unit, colorScheme = "blue" } = input;
2090
- const { theme } = context;
2091
- const colors = resolveColorScheme(context, colorScheme);
2092
- const labelFontSize = scaledFontSize(28, context, false);
2093
- const valueFontSize = scaledFontSize(48, context, true);
2094
- const maxValue = Math.max(leftValue, rightValue, 1);
2095
- const maxBarWidth = 65;
2096
- const leftBarWidth = leftValue / maxValue * maxBarWidth;
2097
- const rightBarWidth = rightValue / maxValue * maxBarWidth;
2098
- const barStartX = 15;
2099
- const barHeight = 6;
2100
- const topBarY = 36;
2101
- const bottomBarY = 58;
2102
- const formatValue = (v) => {
2103
- if (v >= 1e6) return `${(v / 1e6).toFixed(1)}M`;
2104
- if (v >= 1e3) return `${(v / 1e3).toFixed(v >= 1e4 ? 0 : 1)}K`;
2105
- return v.toLocaleString();
2106
- };
2107
- const leftDisplay = unit ? `${formatValue(leftValue)} ${unit}` : formatValue(leftValue);
2108
- const rightDisplay = unit ? `${formatValue(rightValue)} ${unit}` : formatValue(rightValue);
2109
- return [
2110
- // Background
2111
- {
2112
- type: "shape",
2113
- id: "bg",
2114
- content: {
2115
- shape: "rect",
2116
- fill: `linear-gradient(180deg, ${theme.colors.background} 0%, #0f1520 100%)`
2117
- },
2118
- position: { x: 0, y: 0, width: "100%", height: "100%" }
2119
- },
2120
- // Top bar label
2121
- {
2122
- type: "text",
2123
- id: "left-label",
2124
- content: {
2125
- text: leftLabel,
2126
- style: {
2127
- fontSize: labelFontSize,
2128
- fontFamily: getThemeFont(context, "body"),
2129
- color: theme.colors.textMuted
2130
- }
2131
- },
2132
- position: { x: `${barStartX}%`, y: `${topBarY - 8}%` }
2133
- },
2134
- // Top bar value
2135
- {
2136
- type: "text",
2137
- id: "left-value",
2138
- content: {
2139
- text: leftDisplay,
2140
- style: {
2141
- fontSize: valueFontSize,
2142
- fontFamily: getThemeFont(context, "body"),
2143
- fontWeight: "bold",
2144
- color: colors.text
2145
- }
2146
- },
2147
- position: { x: `${barStartX + leftBarWidth + 2}%`, y: `${topBarY - 1}%` },
2148
- animation: { type: "fadeIn", duration: 0.8, delay: 0.3 }
2149
- },
2150
- // Top bar
2151
- {
2152
- type: "shape",
2153
- id: "left-bar",
2154
- content: {
2155
- shape: "rect",
2156
- fill: colors.text,
2157
- borderRadius: 4
2158
- },
2159
- position: {
2160
- x: `${barStartX}%`,
2161
- y: `${topBarY}%`,
2162
- width: `${leftBarWidth}%`,
2163
- height: `${barHeight}%`
2164
- },
2165
- animation: { type: "fadeIn", duration: 1 }
2166
- },
2167
- // Bottom bar label
2168
- {
2169
- type: "text",
2170
- id: "right-label",
2171
- content: {
2172
- text: rightLabel,
2173
- style: {
2174
- fontSize: labelFontSize,
2175
- fontFamily: getThemeFont(context, "body"),
2176
- color: theme.colors.textMuted
2177
- }
2178
- },
2179
- position: { x: `${barStartX}%`, y: `${bottomBarY - 8}%` }
2180
- },
2181
- // Bottom bar value
2182
- {
2183
- type: "text",
2184
- id: "right-value",
2185
- content: {
2186
- text: rightDisplay,
2187
- style: {
2188
- fontSize: valueFontSize,
2189
- fontFamily: getThemeFont(context, "body"),
2190
- fontWeight: "bold",
2191
- color: colors.accent
2192
- }
2193
- },
2194
- position: { x: `${barStartX + rightBarWidth + 2}%`, y: `${bottomBarY - 1}%` },
2195
- animation: { type: "fadeIn", duration: 0.8, delay: 0.6 }
2196
- },
2197
- // Bottom bar
2198
- {
2199
- type: "shape",
2200
- id: "right-bar",
2201
- content: {
2202
- shape: "rect",
2203
- fill: colors.accent,
2204
- borderRadius: 4
2205
- },
2206
- position: {
2207
- x: `${barStartX}%`,
2208
- y: `${bottomBarY}%`,
2209
- width: `${rightBarWidth}%`,
2210
- height: `${barHeight}%`
2211
- },
2212
- animation: { type: "fadeIn", duration: 1, delay: 0.3 }
2213
- }
2214
- ];
2215
- }
2216
-
2217
- // src/doc/templates/pullQuote.ts
2218
- function pullQuote(input, context) {
2219
- const { text, attribution, backgroundImage, ambientMotion } = input;
2220
- if (!backgroundImage?.src) return [];
2221
- const quoteFontSize = scaledFontSize(52, context, true);
2222
- const attrFontSize = scaledFontSize(24, context, false);
2223
- const decoFontSize = scaledFontSize(200, context, true);
2224
- const layers = [
2225
- // Full-bleed background image
2226
- {
2227
- type: "image",
2228
- id: "bg-image",
2229
- content: {
2230
- src: backgroundImage.src,
2231
- alt: backgroundImage.alt,
2232
- fit: "cover",
2233
- credit: backgroundImage.credit,
2234
- license: backgroundImage.license
2235
- },
2236
- position: { x: 0, y: 0, width: "100%", height: "100%" },
2237
- animation: ambientMotion ? { type: ambientMotion, duration: 15 } : void 0
2238
- },
2239
- // Dark overlay for text readability
2240
- {
2241
- type: "shape",
2242
- id: "overlay",
2243
- content: {
2244
- shape: "rect",
2245
- fill: "rgba(0, 0, 0, 0.55)"
2246
- },
2247
- position: { x: 0, y: 0, width: "100%", height: "100%" }
2248
- },
2249
- // Decorative quotation mark
2250
- {
2251
- type: "text",
2252
- id: "deco-quote",
2253
- content: {
2254
- text: "\u201C",
2255
- style: {
2256
- fontSize: decoFontSize,
2257
- fontFamily: getThemeFont(context, "title"),
2258
- color: "rgba(255, 255, 255, 0.08)",
2259
- textAlign: "center"
2260
- }
2261
- },
2262
- position: {
2263
- x: "50%",
2264
- y: "20%",
2265
- anchor: "center"
2266
- }
2267
- },
2268
- // Quote text
2269
- {
2270
- type: "text",
2271
- id: "quote-text",
2272
- content: {
2273
- text,
2274
- style: {
2275
- fontSize: quoteFontSize,
2276
- fontFamily: getThemeFont(context, "title"),
2277
- color: "#ffffff",
2278
- textAlign: "center",
2279
- lineHeight: 1.5,
2280
- shadow: true
2281
- }
2282
- },
2283
- position: {
2284
- x: "50%",
2285
- y: attribution ? "45%" : "50%",
2286
- anchor: "center",
2287
- width: "80%"
2288
- },
2289
- animation: { type: "fadeIn", duration: 2 }
2290
- }
2291
- ];
2292
- if (attribution) {
2293
- layers.push({
2294
- type: "text",
2295
- id: "attribution",
2296
- content: {
2297
- text: `\u2014 ${attribution}`,
2298
- style: {
2299
- fontSize: attrFontSize,
2300
- fontFamily: getThemeFont(context, "body"),
2301
- color: "rgba(255, 255, 255, 0.7)",
2302
- textAlign: "center",
2303
- shadow: true
2304
- }
2305
- },
2306
- position: {
2307
- x: "50%",
2308
- y: "72%",
2309
- anchor: "center"
2310
- },
2311
- animation: { type: "fadeIn", duration: 1, delay: 1.5 }
2312
- });
2313
- }
2314
- return layers;
2315
- }
2316
-
2317
- // src/doc/templates/videoWithCaption.ts
2318
- function videoWithCaption(input, context) {
2319
- const {
2320
- videoSrc,
2321
- posterSrc,
2322
- videoAlt,
2323
- clipStart,
2324
- clipEnd,
2325
- sourceDuration,
2326
- caption: rawCaption,
2327
- captionPosition = "bottom",
2328
- videoCredit,
2329
- videoLicense
2330
- } = input;
2331
- const caption = rawCaption ? cleanCaption(rawCaption) : rawCaption;
2332
- const { theme, layout } = context;
2333
- const captionFontSize = scaledFontSize(36, context, false);
2334
- const creditFontSize = scaledFontSize(16, context, false);
2335
- const layers = [
2336
- // Background video clip
2337
- {
2338
- type: "video",
2339
- id: "bg-video",
2340
- content: {
2341
- src: videoSrc,
2342
- posterSrc,
2343
- alt: videoAlt,
2344
- fit: "cover",
2345
- clipStart,
2346
- clipEnd,
2347
- sourceDuration,
2348
- credit: videoCredit,
2349
- license: videoLicense
2350
- },
2351
- position: { x: 0, y: 0, width: "100%", height: "100%" }
2352
- }
2353
- ];
2354
- if (caption) {
2355
- layers.push({
2356
- type: "shape",
2357
- id: "caption-gradient",
2358
- content: {
2359
- shape: "rect",
2360
- fill: "linear-gradient(0deg, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.3) 60%, transparent 100%)"
2361
- },
2362
- position: {
2363
- x: 0,
2364
- y: captionPosition === "top" ? 0 : "65%",
2365
- width: "100%",
2366
- height: "35%"
2367
- }
2368
- });
2369
- const captionY = captionPosition === "top" ? "15%" : captionPosition === "center" ? "50%" : "82%";
2370
- layers.push({
2371
- type: "text",
2372
- id: "caption",
2373
- content: {
2374
- text: caption,
2375
- style: {
2376
- fontSize: captionFontSize,
2377
- fontFamily: getThemeFont(context, "body"),
2378
- color: theme.colors.text,
2379
- textAlign: "center",
2380
- shadow: true
2381
- }
2382
- },
2383
- position: {
2384
- x: "50%",
2385
- y: captionY,
2386
- anchor: "center",
2387
- width: layout.maxTextWidth
2388
- },
2389
- animation: { type: "fadeIn", duration: 1.5, delay: 0.5 }
2390
- });
2391
- }
2392
- if (videoCredit) {
2393
- layers.push({
2394
- type: "text",
2395
- id: "credit",
2396
- content: {
2397
- text: videoCredit,
2398
- style: {
2399
- fontSize: creditFontSize,
2400
- fontFamily: getThemeFont(context, "body"),
2401
- color: "rgba(255, 255, 255, 0.5)",
2402
- textAlign: "right"
2403
- }
2404
- },
2405
- position: {
2406
- x: "96%",
2407
- y: "96%",
2408
- anchor: "bottom-right"
2409
- }
2410
- });
2411
- }
2412
- return layers;
2413
- }
2414
-
2415
- // src/doc/templates/videoPullQuote.ts
2416
- function videoPullQuote(input, context) {
2417
- const { text, attribution, backgroundVideo } = input;
2418
- if (!backgroundVideo?.src) return [];
2419
- const quoteFontSize = scaledFontSize(52, context, true);
2420
- const attrFontSize = scaledFontSize(24, context, false);
2421
- const decoFontSize = scaledFontSize(200, context, true);
2422
- const layers = [
2423
- // Full-bleed background video clip
2424
- {
2425
- type: "video",
2426
- id: "bg-video",
2427
- content: {
2428
- src: backgroundVideo.src,
2429
- posterSrc: backgroundVideo.posterSrc,
2430
- alt: backgroundVideo.alt,
2431
- fit: "cover",
2432
- clipStart: backgroundVideo.clipStart,
2433
- clipEnd: backgroundVideo.clipEnd,
2434
- credit: backgroundVideo.credit,
2435
- license: backgroundVideo.license
2436
- },
2437
- position: { x: 0, y: 0, width: "100%", height: "100%" }
2438
- },
2439
- // Dark overlay for text readability
2440
- {
2441
- type: "shape",
2442
- id: "overlay",
2443
- content: {
2444
- shape: "rect",
2445
- fill: "rgba(0, 0, 0, 0.55)"
2446
- },
2447
- position: { x: 0, y: 0, width: "100%", height: "100%" }
2448
- },
2449
- // Decorative quotation mark
2450
- {
2451
- type: "text",
2452
- id: "deco-quote",
2453
- content: {
2454
- text: "\u201C",
2455
- style: {
2456
- fontSize: decoFontSize,
2457
- fontFamily: getThemeFont(context, "title"),
2458
- color: "rgba(255, 255, 255, 0.08)",
2459
- textAlign: "center"
2460
- }
2461
- },
2462
- position: {
2463
- x: "50%",
2464
- y: "20%",
2465
- anchor: "center"
2466
- }
2467
- },
2468
- // Quote text
2469
- {
2470
- type: "text",
2471
- id: "quote-text",
2472
- content: {
2473
- text,
2474
- style: {
2475
- fontSize: quoteFontSize,
2476
- fontFamily: getThemeFont(context, "title"),
2477
- color: "#ffffff",
2478
- textAlign: "center",
2479
- lineHeight: 1.5,
2480
- shadow: true
2481
- }
2482
- },
2483
- position: {
2484
- x: "50%",
2485
- y: attribution ? "45%" : "50%",
2486
- anchor: "center",
2487
- width: "80%"
2488
- },
2489
- animation: { type: "fadeIn", duration: 2 }
2490
- }
2491
- ];
2492
- if (attribution) {
2493
- layers.push({
2494
- type: "text",
2495
- id: "attribution",
2496
- content: {
2497
- text: `\u2014 ${attribution}`,
2498
- style: {
2499
- fontSize: attrFontSize,
2500
- fontFamily: getThemeFont(context, "body"),
2501
- color: "rgba(255, 255, 255, 0.7)",
2502
- textAlign: "center",
2503
- shadow: true
2504
- }
2505
- },
2506
- position: {
2507
- x: "50%",
2508
- y: "72%",
2509
- anchor: "center"
2510
- },
2511
- animation: { type: "fadeIn", duration: 1, delay: 1.5 }
2512
- });
2513
- }
2514
- return layers;
2515
- }
2516
-
2517
- // src/doc/templates/dataTable.ts
2518
- function dataTable(input, context) {
2519
- const { title, headers, rows, align, colorScheme } = input;
2520
- const { theme } = context;
2521
- const colors = resolveColorScheme(context, colorScheme);
2522
- const titleFontSize = scaledFontSize(48, context, true);
2523
- const tableFontSize = scaledFontSize(28, context, false);
2524
- const layers = [
2525
- createBackgroundLayer(
2526
- "bg",
2527
- `linear-gradient(170deg, ${theme.colors.background} 0%, #0f1520 100%)`
2528
- )
2529
- ];
2530
- if (title) {
2531
- layers.push({
2532
- type: "text",
2533
- id: "title",
2534
- content: {
2535
- text: title,
2536
- style: {
2537
- fontSize: titleFontSize,
2538
- fontFamily: getThemeFont(context, "title"),
2539
- fontWeight: "bold",
2540
- color: theme.colors.text,
2541
- textAlign: "center",
2542
- shadow: true
2543
- }
2544
- },
2545
- position: { x: "50%", y: "10%", width: "80%", anchor: "center" },
2546
- animation: { type: "fadeIn", duration: 0.8 }
2547
- });
2548
- }
2549
- layers.push({
2550
- type: "table",
2551
- id: "table",
2552
- content: {
2553
- headers,
2554
- rows,
2555
- align,
2556
- style: {
2557
- headerBackground: colors.accent,
2558
- headerColor: colors.text,
2559
- cellBackground: "rgba(255,255,255,0.05)",
2560
- cellColor: theme.colors.text,
2561
- borderColor: "rgba(255,255,255,0.12)",
2562
- fontSize: tableFontSize,
2563
- fontFamily: getThemeFont(context, "body"),
2564
- headerFontFamily: getThemeFont(context, "title"),
2565
- borderRadius: 8
2566
- }
2567
- },
2568
- position: {
2569
- x: "10%",
2570
- y: title ? "18%" : "8%",
2571
- width: "80%",
2572
- height: title ? "74%" : "84%"
2573
- },
2574
- animation: { type: "fadeIn", duration: 1, delay: title ? 0.4 : 0 }
2575
- });
2576
- return layers;
2577
- }
2578
-
2579
- // src/doc/templates/coverBlock.ts
2580
- function coverBlock(input, context) {
2581
- const { heroSrc, heroAlt, title, subtitle, ambientMotion, heroCredit, heroLicense } = input;
2582
- const { theme, layout } = context;
2583
- const titleFontSize = scaledFontSize(120, context, true);
2584
- const subtitleFontSize = scaledFontSize(40, context, false);
2585
- const layers = [];
2586
- if (heroSrc) {
2587
- const imageAnimation = mapAmbientMotion(ambientMotion);
2588
- layers.push(
2589
- {
2590
- type: "image",
2591
- id: "cover-hero",
2592
- content: {
2593
- src: heroSrc,
2594
- alt: heroAlt || title,
2595
- fit: "cover",
2596
- credit: heroCredit,
2597
- license: heroLicense
2598
- },
2599
- position: { x: 0, y: 0, width: "100%", height: "100%" },
2600
- animation: imageAnimation
2601
- },
2602
- {
2603
- type: "shape",
2604
- id: "cover-gradient",
2605
- content: {
2606
- shape: "rect",
2607
- fill: "linear-gradient(0deg, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.4) 40%, rgba(0,0,0,0.1) 70%, transparent 100%)"
2608
- },
2609
- position: { x: 0, y: 0, width: "100%", height: "100%" }
2610
- }
2611
- );
2612
- } else {
2613
- layers.push({
2614
- type: "shape",
2615
- id: "cover-bg",
2616
- content: {
2617
- shape: "rect",
2618
- fill: `radial-gradient(ellipse at 50% 40%, ${theme.colors.primary} 0%, ${theme.colors.background} 100%)`
2619
- },
2620
- position: { x: 0, y: 0, width: "100%", height: "100%" }
2621
- });
2622
- layers.push({
2623
- type: "shape",
2624
- id: "cover-accent",
2625
- content: {
2626
- shape: "rect",
2627
- fill: "rgba(255, 255, 255, 0.2)"
2628
- },
2629
- position: {
2630
- x: "35%",
2631
- y: subtitle ? "42%" : "58%",
2632
- width: "30%",
2633
- height: "2px"
2634
- }
2635
- });
2636
- }
2637
- layers.push({
2638
- type: "text",
2639
- id: "cover-title",
2640
- content: {
2641
- text: title,
2642
- style: {
2643
- fontSize: titleFontSize,
2644
- fontFamily: getThemeFont(context, "title"),
2645
- fontWeight: "bold",
2646
- color: theme.colors.text,
2647
- textAlign: "center",
2648
- shadow: true
2649
- }
2650
- },
2651
- position: {
2652
- x: "50%",
2653
- y: heroSrc ? subtitle ? "70%" : "75%" : subtitle ? layout.primaryY : "50%",
2654
- anchor: "center",
2655
- width: layout.maxTextWidth
2656
- },
2657
- // No animation delay - shown immediately at rest
2658
- animation: { type: "fadeIn", duration: 0.8 }
2659
- });
2660
- if (subtitle) {
2661
- layers.push({
2662
- type: "text",
2663
- id: "cover-subtitle",
2664
- content: {
2665
- text: subtitle,
2666
- style: {
2667
- fontSize: subtitleFontSize,
2668
- fontFamily: getThemeFont(context, "body"),
2669
- color: theme.colors.textMuted,
2670
- textAlign: "center",
2671
- lineHeight: 1.5
2672
- }
2673
- },
2674
- position: {
2675
- x: "50%",
2676
- y: heroSrc ? "82%" : layout.secondaryY,
2677
- anchor: "center",
2678
- width: layout.maxTextWidth
2679
- },
2680
- animation: { type: "fadeIn", duration: 0.8, delay: 0.2 }
2681
- });
2682
- }
2683
- return layers;
2684
- }
2685
- function startBlockToCoverInput(config) {
2686
- return {
2687
- heroSrc: config.heroSrc,
2688
- heroAlt: config.heroAlt,
2689
- title: config.title,
2690
- subtitle: config.subtitle,
2691
- ambientMotion: config.ambientMotion,
2692
- heroCredit: config.heroCredit,
2693
- heroLicense: config.heroLicense
2694
- };
2695
- }
2696
- function expandCoverBlock(config, context) {
2697
- const input = startBlockToCoverInput(config);
2698
- return coverBlock(input, context);
2699
- }
2700
-
2701
- // src/doc/templates/index.ts
2702
- var templateRegistry = {
2703
- title: titleBlock,
2704
- sectionHeader,
2705
- statHighlight,
2706
- quote: quoteBlock,
2707
- factCard,
2708
- twoColumn,
2709
- dateEvent,
2710
- imageWithCaption,
2711
- leftFeature,
2712
- rightFeature,
2713
- map: mapBlock,
2714
- fullBleedQuote,
2715
- list: listBlock,
2716
- photoGrid,
2717
- definitionCard,
2718
- comparisonBar,
2719
- pullQuote,
2720
- videoWithCaption,
2721
- videoPullQuote,
2722
- dataTable
2723
- };
2724
- var TEMPLATE_ALIASES = {
2725
- titleBlock: "title",
2726
- quoteBlock: "quote",
2727
- mapBlock: "map",
2728
- listBlock: "list"
2729
- };
2730
- function resolveTemplateName(name) {
2731
- return TEMPLATE_ALIASES[name] ?? name;
2732
- }
2733
- function expandTemplateBlock(templateBlock, context) {
2734
- const resolved = resolveTemplateName(templateBlock.template);
2735
- const templateFn = templateRegistry[resolved];
2736
- if (!templateFn) {
2737
- console.warn(`Unknown template: ${templateBlock.template}`);
2738
- return {
2739
- id: templateBlock.id,
2740
- startTime: 0,
2741
- duration: templateBlock.duration,
2742
- audioSegment: templateBlock.audioSegment,
2743
- transition: templateBlock.transition,
2744
- template: templateBlock.template
2745
- // Preserve for debugging
2746
- };
2747
- }
2748
- let layers;
2749
- try {
2750
- layers = templateFn(templateBlock, context);
2751
- if (!Array.isArray(layers)) {
2752
- console.error(
2753
- `Template ${templateBlock.template} did not return an array, got:`,
2754
- typeof layers
2755
- );
2756
- layers = [];
2757
- }
2758
- } catch (err) {
2759
- console.error(`Error expanding template ${templateBlock.template}:`, err);
2760
- layers = [];
2761
- }
2762
- return {
2763
- id: templateBlock.id,
2764
- startTime: 0,
2765
- // Will be calculated later
2766
- duration: templateBlock.duration,
2767
- audioSegment: templateBlock.audioSegment,
2768
- ...layers.length > 0 ? { layers } : {},
2769
- transition: templateBlock.transition,
2770
- template: templateBlock.template
2771
- // Preserve for debugging
2772
- };
2773
- }
2774
- function expandDocBlocks(blocks, options = {}) {
2775
- const opts = options;
2776
- const theme = opts.theme ?? DEFAULT_THEME;
2777
- const viewport = opts.viewport ?? VIEWPORT_PRESETS.landscape;
2778
- const { persistentLayers, audioSegments } = opts;
2779
- const totalBlocks = blocks.length;
2780
- const bottomLayers = expandPersistentLayers(persistentLayers?.bottomLayers);
2781
- const topLayers = expandPersistentLayers(persistentLayers?.topLayers);
2782
- if (!audioSegments || audioSegments.length === 0) {
2783
- let currentTime = 0;
2784
- return blocks.map((block, index) => {
2785
- const context = createTemplateContext(theme, index, totalBlocks, viewport);
2786
- const expandedBlock = isTemplateBlock(block) ? expandTemplateBlock(block, context) : block;
2787
- const templateBlock = block;
2788
- const useBottom = templateBlock.useBottomLayer !== false;
2789
- const useTop = templateBlock.useTopLayer !== false;
2790
- if (bottomLayers.length > 0 || topLayers.length > 0) {
2791
- expandedBlock.layers = [
2792
- ...useBottom ? bottomLayers : [],
2793
- ...expandedBlock.layers ?? [],
2794
- ...useTop ? topLayers : []
2795
- ];
2796
- }
2797
- expandedBlock.startTime = currentTime;
2798
- currentTime += expandedBlock.duration;
2799
- return expandedBlock;
2800
- });
2801
- }
2802
- const blocksBySegment = /* @__PURE__ */ new Map();
2803
- blocks.forEach((block, index) => {
2804
- const segmentIndex = block.audioSegment ?? 0;
2805
- if (!blocksBySegment.has(segmentIndex)) {
2806
- blocksBySegment.set(segmentIndex, []);
2807
- }
2808
- blocksBySegment.get(segmentIndex).push({ block, originalIndex: index });
2809
- });
2810
- const expandedBlocks = new Array(blocks.length);
2811
- for (const [segmentIndex, segmentBlocks] of blocksBySegment) {
2812
- const audioSegment = audioSegments[segmentIndex];
2813
- if (!audioSegment) {
2814
- let offsetTime = 0;
2815
- for (const { block, originalIndex } of segmentBlocks) {
2816
- const context = createTemplateContext(theme, originalIndex, totalBlocks, viewport);
2817
- const expandedBlock = isTemplateBlock(block) ? expandTemplateBlock(block, context) : block;
2818
- const templateBlock = block;
2819
- const useBottom = templateBlock.useBottomLayer !== false;
2820
- const useTop = templateBlock.useTopLayer !== false;
2821
- if (bottomLayers.length > 0 || topLayers.length > 0) {
2822
- expandedBlock.layers = [
2823
- ...useBottom ? bottomLayers : [],
2824
- ...expandedBlock.layers ?? [],
2825
- ...useTop ? topLayers : []
2826
- ];
2827
- }
2828
- expandedBlock.startTime = offsetTime;
2829
- offsetTime += expandedBlock.duration;
2830
- expandedBlocks[originalIndex] = expandedBlock;
2831
- }
2832
- continue;
2833
- }
2834
- const sectionHeaderBlocks = [];
2835
- const contentBlocks = [];
2836
- for (const item of segmentBlocks) {
2837
- const templateBlock = item.block;
2838
- if (templateBlock.template === "sectionHeader") {
2839
- sectionHeaderBlocks.push(item);
2840
- } else {
2841
- contentBlocks.push(item);
2842
- }
2843
- }
2844
- const fixedDuration = sectionHeaderBlocks.reduce((sum, { block }) => {
2845
- return sum + (block.duration ?? 0);
2846
- }, 0);
2847
- const contentBlockDuration = contentBlocks.reduce((sum, { block }) => {
2848
- return sum + (block.duration ?? 0);
2849
- }, 0);
2850
- const remainingDuration = audioSegment.duration - fixedDuration;
2851
- const scaleFactor = contentBlockDuration > 0 && remainingDuration > 0 ? remainingDuration / contentBlockDuration : 1;
2852
- const expandedInfos = [];
2853
- for (const { block, originalIndex } of segmentBlocks) {
2854
- const context = createTemplateContext(theme, originalIndex, totalBlocks, viewport);
2855
- const expandedBlock = isTemplateBlock(block) ? expandTemplateBlock(block, context) : block;
2856
- const templateBlock = block;
2857
- const useBottom = templateBlock.useBottomLayer !== false;
2858
- const useTop = templateBlock.useTopLayer !== false;
2859
- if (bottomLayers.length > 0 || topLayers.length > 0) {
2860
- expandedBlock.layers = [
2861
- ...useBottom ? bottomLayers : [],
2862
- ...expandedBlock.layers ?? [],
2863
- ...useTop ? topLayers : []
2864
- ];
2865
- }
2866
- expandedInfos.push({
2867
- block: expandedBlock,
2868
- originalIndex,
2869
- templateBlock,
2870
- hasSourceTiming: typeof templateBlock.sourceStartTime === "number"
2871
- });
2872
- }
2873
- const hasAnySourceTiming = expandedInfos.some((info) => info.hasSourceTiming);
2874
- expandedInfos.sort((a, b) => {
2875
- if (hasAnySourceTiming) {
2876
- const aIsHeader = a.templateBlock.template === "sectionHeader";
2877
- const bIsHeader = b.templateBlock.template === "sectionHeader";
2878
- if (aIsHeader && !bIsHeader) return -1;
2879
- if (!aIsHeader && bIsHeader) return 1;
2880
- if (a.hasSourceTiming && b.hasSourceTiming) {
2881
- return a.templateBlock.sourceStartTime - b.templateBlock.sourceStartTime;
2882
- }
2883
- if (a.hasSourceTiming && !b.hasSourceTiming) return -1;
2884
- if (!a.hasSourceTiming && b.hasSourceTiming) return 1;
2885
- }
2886
- return a.originalIndex - b.originalIndex;
2887
- });
2888
- let offsetWithinSegment = 0;
2889
- for (let i = 0; i < expandedInfos.length; i++) {
2890
- const info = expandedInfos[i];
2891
- const { block: expandedBlock, templateBlock } = info;
2892
- if (info.hasSourceTiming) {
2893
- const sourceStart = templateBlock.sourceStartTime;
2894
- expandedBlock.startTime = audioSegment.startTime + sourceStart;
2895
- if (typeof templateBlock.sourceDuration === "number") {
2896
- expandedBlock.duration = Math.max(5, templateBlock.sourceDuration);
2897
- }
2898
- offsetWithinSegment = sourceStart + expandedBlock.duration;
2899
- } else if (templateBlock.template === "sectionHeader") {
2900
- expandedBlock.startTime = audioSegment.startTime + offsetWithinSegment;
2901
- offsetWithinSegment += expandedBlock.duration;
2902
- } else {
2903
- expandedBlock.startTime = audioSegment.startTime + offsetWithinSegment;
2904
- const scaledDuration = expandedBlock.duration * scaleFactor;
2905
- expandedBlock.duration = scaledDuration;
2906
- offsetWithinSegment += scaledDuration;
2907
- }
2908
- expandedBlocks[info.originalIndex] = expandedBlock;
2909
- }
2910
- const segmentExpandedBlocks = expandedInfos.map((info) => expandedBlocks[info.originalIndex]).sort((a, b) => a.startTime - b.startTime);
2911
- for (let i = 0; i < segmentExpandedBlocks.length - 1; i++) {
2912
- const current = segmentExpandedBlocks[i];
2913
- const next = segmentExpandedBlocks[i + 1];
2914
- const currentEnd = current.startTime + current.duration;
2915
- if (currentEnd > next.startTime) {
2916
- current.duration = next.startTime - current.startTime;
2917
- } else if (currentEnd < next.startTime - 0.5) {
2918
- current.duration = Math.max(0.1, next.startTime - current.startTime);
2919
- }
2920
- }
2921
- const MIN_TRANSITION_GAP = 5;
2922
- const segmentEnd = audioSegment.startTime + audioSegment.duration;
2923
- while (segmentExpandedBlocks.length > 1) {
2924
- const lastBlock = segmentExpandedBlocks[segmentExpandedBlocks.length - 1];
2925
- const timeFromLastToEnd = segmentEnd - lastBlock.startTime;
2926
- if (timeFromLastToEnd < MIN_TRANSITION_GAP && lastBlock.template !== "sectionHeader") {
2927
- const prevBlock = segmentExpandedBlocks[segmentExpandedBlocks.length - 2];
2928
- prevBlock.duration = segmentEnd - prevBlock.startTime;
2929
- lastBlock.duration = 0;
2930
- lastBlock.startTime = segmentEnd;
2931
- segmentExpandedBlocks.pop();
2932
- } else {
2933
- if (lastBlock.startTime + lastBlock.duration < segmentEnd) {
2934
- lastBlock.duration = segmentEnd - lastBlock.startTime;
2935
- }
2936
- break;
2937
- }
2938
- }
2939
- if (segmentExpandedBlocks.length === 1) {
2940
- const onlyBlock = segmentExpandedBlocks[0];
2941
- if (onlyBlock.startTime + onlyBlock.duration < segmentEnd) {
2942
- onlyBlock.duration = segmentEnd - onlyBlock.startTime;
2943
- }
2944
- }
2945
- let changed = true;
2946
- while (changed) {
2947
- changed = false;
2948
- for (let i = segmentExpandedBlocks.length - 1; i >= 1; i--) {
2949
- const block = segmentExpandedBlocks[i];
2950
- if (block.duration > 0 && block.duration < MIN_TRANSITION_GAP) {
2951
- const prev = segmentExpandedBlocks[i - 1];
2952
- const blockEnd = block.startTime + block.duration;
2953
- prev.duration = blockEnd - prev.startTime;
2954
- block.duration = 0;
2955
- block.startTime = segmentEnd;
2956
- segmentExpandedBlocks.splice(i, 1);
2957
- changed = true;
2958
- break;
2959
- }
2960
- }
2961
- }
2962
- const MAX_BLOCK_DURATION = 20;
2963
- for (let i = 0; i < segmentExpandedBlocks.length; i++) {
2964
- const block = segmentExpandedBlocks[i];
2965
- if (block.duration > MAX_BLOCK_DURATION) {
2966
- const numParts = Math.ceil(block.duration / MAX_BLOCK_DURATION);
2967
- const partDuration = block.duration / numParts;
2968
- if (partDuration >= MIN_TRANSITION_GAP) {
2969
- block.duration = partDuration;
2970
- for (let p = 1; p < numParts; p++) {
2971
- const splitBlock = {
2972
- id: `${block.id}-split-${p}`,
2973
- startTime: block.startTime + p * partDuration,
2974
- duration: partDuration,
2975
- audioSegment: block.audioSegment,
2976
- layers: (block.layers ?? []).map((layer) => ({
2977
- ...layer,
2978
- id: `${layer.id}-split-${p}`
2979
- })),
2980
- transition: { type: "dissolve", duration: 1 },
2981
- template: block.template
2982
- };
2983
- expandedBlocks.push(splitBlock);
2984
- }
2985
- }
2986
- }
2987
- }
2988
- }
2989
- return expandedBlocks.filter((block) => block && block.duration > 0);
2990
- }
2991
- function getAvailableTemplates() {
2992
- return Object.keys(templateRegistry);
2993
- }
2994
- function hasTemplate(name) {
2995
- return resolveTemplateName(name) in templateRegistry;
2996
- }
2997
-
2998
- // src/doc/utils/animationUtils.ts
2999
- function getAnimationStyle(animation, _currentTime = 0) {
3000
- if (!animation || animation.type === "none") {
3001
- return { className: "", style: {} };
3002
- }
3003
- const className = getAnimationClassName(animation);
3004
- const style = getAnimationCSSVars(animation);
3005
- return { className, style };
3006
- }
3007
- function getAnimationClassName(animation) {
3008
- const { type, direction, panDirection } = animation;
3009
- switch (type) {
3010
- case "fadeIn":
3011
- return "anim-fadeIn";
3012
- case "fadeOut":
3013
- return "anim-fadeOut";
3014
- case "slowZoom":
3015
- if (panDirection === "left") return "anim-slowZoom-panLeft";
3016
- if (panDirection === "right") return "anim-slowZoom-panRight";
3017
- if (direction === "out") return "anim-slowZoom-out";
3018
- return "anim-slowZoom-in";
3019
- case "zoomIn":
3020
- return "anim-zoomIn";
3021
- case "zoomOut":
3022
- return "anim-zoomOut";
3023
- case "panLeft":
3024
- return "anim-panLeft";
3025
- case "panRight":
3026
- return "anim-panRight";
3027
- case "typewriter":
3028
- return "anim-typewriter";
3029
- default:
3030
- return "";
3031
- }
3032
- }
3033
- function getAnimationCSSVars(animation) {
3034
- const vars = {};
3035
- if (animation.duration !== void 0) {
3036
- vars["--anim-duration"] = `${animation.duration}s`;
3037
- }
3038
- if (animation.delay !== void 0) {
3039
- vars["--anim-delay"] = `${animation.delay}s`;
3040
- }
3041
- if (animation.easing) {
3042
- vars["--anim-easing"] = animation.easing;
3043
- }
3044
- return vars;
3045
- }
3046
- function getDefaultAnimationDuration(type) {
3047
- switch (type) {
3048
- case "slowZoom":
3049
- case "panLeft":
3050
- case "panRight":
3051
- return 8;
3052
- // Long, slow animations
3053
- case "typewriter":
3054
- return 3;
3055
- case "fadeIn":
3056
- case "fadeOut":
3057
- return 1;
3058
- case "zoomIn":
3059
- case "zoomOut":
3060
- return 0.5;
3061
- default:
3062
- return 1;
3063
- }
3064
- }
3065
- function getTransitionClass(type, entering) {
3066
- const mode = entering ? "enter" : "exit";
3067
- return `transition-${type}-${mode}`;
3068
- }
3069
- function getAnimationProgress(animation, currentTime, slideDuration) {
3070
- const delay = animation.delay || 0;
3071
- const duration = animation.duration || slideDuration;
3072
- if (currentTime < delay) return 0;
3073
- if (currentTime >= delay + duration) return 1;
3074
- return (currentTime - delay) / duration;
3075
- }
3076
-
3077
- // src/doc/markdownToDoc.ts
3078
- var SLUG_NON_WORD_RE = /[^\w\s-]/g;
3079
- var SLUG_SPACES_RE = /[\s_]+/g;
3080
- var SLUG_MULTI_HYPHEN_RE = /-+/g;
3081
- var SLUG_TRIM_HYPHEN_RE = /^-|-$/g;
3082
- function slugify(text) {
3083
- return text.toLowerCase().replace(SLUG_NON_WORD_RE, "").replace(SLUG_SPACES_RE, "-").replace(SLUG_MULTI_HYPHEN_RE, "-").replace(SLUG_TRIM_HYPHEN_RE, "") || // Trim leading/trailing hyphens
3084
- "block";
3085
- }
3086
- function createIdGenerator() {
3087
- const used = /* @__PURE__ */ new Map();
3088
- return (heading, _index) => {
3089
- const text = extractPlainText(heading);
3090
- const base = slugify(text);
3091
- const count = used.get(base) ?? 0;
3092
- used.set(base, count + 1);
3093
- if (count === 0) return base;
3094
- return `${base}-${count + 1}`;
3095
- };
3096
- }
3097
- function markdownToDoc(markdownDoc, options) {
3098
- const articleId = options?.articleId ?? "markdown-doc";
3099
- const defaultTemplate = options?.defaultTemplate ?? "sectionHeader";
3100
- const defaultDuration = options?.defaultDuration ?? 5;
3101
- const generateId = options?.generateId ?? createIdGenerator();
3102
- const rootBlocks = [];
3103
- let headingIndex = 0;
3104
- const stack = [];
3105
- let pendingContents = [];
3106
- let currentBlock = null;
3107
- function flushContents() {
3108
- if (currentBlock && pendingContents.length > 0) {
3109
- currentBlock.contents = (currentBlock.contents ?? []).concat(pendingContents);
3110
- pendingContents = [];
3111
- }
3112
- }
3113
- function makeBlock(heading) {
3114
- const id = heading ? generateId(heading, headingIndex++) : "preamble";
3115
- const annotation = heading?.templateAnnotation;
3116
- const rawTemplate = annotation?.template ?? (heading ? defaultTemplate : void 0);
3117
- const template = rawTemplate != null ? resolveTemplateName(rawTemplate) : void 0;
3118
- const title = heading ? extractPlainText(heading) : void 0;
3119
- const block = {
3120
- id,
3121
- startTime: 0,
3122
- duration: defaultDuration,
3123
- audioSegment: 0,
3124
- template,
3125
- ...heading ? { sourceHeading: heading } : {},
3126
- ...title ? { title } : {}
3127
- };
3128
- if (annotation?.params) {
3129
- block.templateOverrides = annotation.params;
3130
- }
3131
- return block;
3132
- }
3133
- for (const node of markdownDoc.children) {
3134
- if (node.type === "heading") {
3135
- const heading = node;
3136
- const depth = heading.depth;
3137
- flushContents();
3138
- const newBlock = makeBlock(heading);
3139
- if (stack.length === 0) {
3140
- if (currentBlock && !currentBlock.sourceHeading) {
3141
- rootBlocks.push(currentBlock);
3142
- }
3143
- rootBlocks.push(newBlock);
3144
- stack.push({ block: newBlock, depth });
3145
- } else {
3146
- while (stack.length > 0 && stack[stack.length - 1].depth >= depth) {
3147
- stack.pop();
3148
- }
3149
- if (stack.length === 0) {
3150
- rootBlocks.push(newBlock);
3151
- stack.push({ block: newBlock, depth });
3152
- } else {
3153
- const parent = stack[stack.length - 1].block;
3154
- if (!parent.children) parent.children = [];
3155
- parent.children.push(newBlock);
3156
- stack.push({ block: newBlock, depth });
3157
- }
3158
- }
3159
- currentBlock = newBlock;
3160
- } else {
3161
- if (!currentBlock) {
3162
- currentBlock = makeBlock(null);
3163
- }
3164
- pendingContents.push(node);
3165
- }
3166
- }
3167
- flushContents();
3168
- if (currentBlock && !currentBlock.sourceHeading && !rootBlocks.includes(currentBlock)) {
3169
- rootBlocks.push(currentBlock);
3170
- }
3171
- const allBlocks = flattenBlocks(rootBlocks);
3172
- const minDuration = 3;
3173
- const phrases = [];
3174
- for (const block of allBlocks) {
3175
- const bodyText = getBlockBodyText(block);
3176
- if (bodyText.length > 0) {
3177
- const estimate = estimateReadingTime(bodyText);
3178
- block.duration = Math.max(minDuration, estimate.seconds);
3179
- } else {
3180
- block.duration = defaultDuration;
3181
- }
3182
- }
3183
- let currentTime = 0;
3184
- for (const block of allBlocks) {
3185
- block.startTime = currentTime;
3186
- const bodyText = getBlockBodyText(block);
3187
- if (bodyText.length > 0) {
3188
- const sentences = splitIntoSentences(bodyText);
3189
- if (sentences.length > 0) {
3190
- const timePerSentence = block.duration / sentences.length;
3191
- for (let i = 0; i < sentences.length; i++) {
3192
- phrases.push({
3193
- text: sentences[i],
3194
- startTime: currentTime + i * timePerSentence,
3195
- endTime: currentTime + (i + 1) * timePerSentence,
3196
- audioSegment: 0
3197
- });
3198
- }
3199
- }
3200
- }
3201
- currentTime += block.duration;
3202
- }
3203
- const captions = phrases.length > 0 ? { phrases, generatedAt: (/* @__PURE__ */ new Date()).toISOString(), version: 1 } : void 0;
3204
- const doc = {
3205
- articleId,
3206
- duration: currentTime,
3207
- blocks: rootBlocks,
3208
- audio: {
3209
- segments: []
3210
- },
3211
- ...captions ? { captions } : {},
3212
- ...markdownDoc.frontmatter ? { frontmatter: markdownDoc.frontmatter } : {}
3213
- };
3214
- if (options?.generateCoverBlock ?? true) {
3215
- const coverConfig = buildStartBlock(markdownDoc, rootBlocks);
3216
- if (coverConfig) {
3217
- doc.startBlock = coverConfig;
3218
- }
3219
- }
3220
- return doc;
3221
- }
3222
- function flattenBlocks(blocks) {
3223
- const result = [];
3224
- for (const block of blocks) {
3225
- result.push(block);
3226
- if (block.children) {
3227
- result.push(...flattenBlocks(block.children));
3228
- }
3229
- }
3230
- return result;
3231
- }
3232
- function countBlocks(blocks) {
3233
- let count = 0;
3234
- for (const block of blocks) {
3235
- count += 1;
3236
- if (block.children) {
3237
- count += countBlocks(block.children);
3238
- }
3239
- }
3240
- return count;
3241
- }
3242
- function getBlockDepth(block) {
3243
- return block.sourceHeading?.depth ?? 0;
3244
- }
3245
- function getBlockBodyText(block) {
3246
- if (!block.contents || block.contents.length === 0) return "";
3247
- return block.contents.map((node) => extractPlainText(node)).join("\n").trim();
3248
- }
3249
- var MAX_PHRASE_WORDS = 12;
3250
- function splitIntoSentences(text) {
3251
- const lines = text.split(/\n+/).map((s) => s.trim()).filter((s) => s.length > 0);
3252
- const sentenceRe = /(?<=[.!?])\s+/;
3253
- const fragments = [];
3254
- for (const line of lines) {
3255
- const sentences = line.split(sentenceRe).map((s) => s.trim()).filter((s) => s.length > 0);
3256
- fragments.push(...sentences);
3257
- }
3258
- if (fragments.length === 0) return [];
3259
- const split = [];
3260
- for (const frag of fragments) {
3261
- const words = frag.split(/\s+/);
3262
- if (words.length > MAX_PHRASE_WORDS) {
3263
- const mid = Math.floor(frag.length / 2);
3264
- const clauseRe = /[,;]\s+|\s+—\s+|\s+-\s+/g;
3265
- let bestSplit = -1;
3266
- let bestDist = Infinity;
3267
- let match;
3268
- while ((match = clauseRe.exec(frag)) !== null) {
3269
- const dist = Math.abs(match.index - mid);
3270
- if (dist < bestDist) {
3271
- bestDist = dist;
3272
- bestSplit = match.index + match[0].length;
3273
- }
3274
- }
3275
- if (bestSplit > 0 && bestSplit < frag.length - 5) {
3276
- split.push(frag.slice(0, bestSplit).trim());
3277
- split.push(frag.slice(bestSplit).trim());
3278
- } else {
3279
- split.push(frag);
3280
- }
3281
- } else {
3282
- split.push(frag);
3283
- }
3284
- }
3285
- const merged = [split[0]];
3286
- for (let i = 1; i < split.length; i++) {
3287
- if (split[i].length < 15 && merged.length > 0) {
3288
- merged[merged.length - 1] += " " + split[i];
3289
- } else {
3290
- merged.push(split[i]);
3291
- }
3292
- }
3293
- return merged;
3294
- }
3295
- function findFirstHtmlImage(nodes) {
3296
- for (const node of nodes) {
3297
- if (node.type !== "htmlElement") continue;
3298
- if (node.tagName === "img" && node.attributes.src) {
3299
- return { url: node.attributes.src, alt: node.attributes.alt };
3300
- }
3301
- const nested = findFirstHtmlImage(node.children);
3302
- if (nested) return nested;
3303
- }
3304
- return void 0;
3305
- }
3306
- function findFirstImage(node) {
3307
- if (node.type === "image") {
3308
- const img = node;
3309
- return { url: img.url, alt: img.alt };
3310
- }
3311
- if (node.type === "htmlBlock" || node.type === "htmlInline") {
3312
- const html = node;
3313
- if (html.htmlChildren) {
3314
- const found = findFirstHtmlImage(html.htmlChildren);
3315
- if (found) return found;
3316
- }
3317
- }
3318
- if ("children" in node && Array.isArray(node.children)) {
3319
- for (const child of node.children) {
3320
- const found = findFirstImage(child);
3321
- if (found) return found;
3322
- }
3323
- }
3324
- return void 0;
3325
- }
3326
- function buildStartBlock(markdownDoc, rootBlocks) {
3327
- const firstH1 = rootBlocks.find((b) => b.sourceHeading?.depth === 1);
3328
- if (!firstH1) return void 0;
3329
- const title = firstH1.title ?? extractPlainText(firstH1.sourceHeading);
3330
- if (!title) return void 0;
3331
- const subtitle = firstH1.contents?.[0]?.type === "paragraph" ? extractPlainText(firstH1.contents[0]) : void 0;
3332
- const firstImage = findFirstImage(markdownDoc);
3333
- const config = {
3334
- title,
3335
- ...subtitle ? { subtitle } : {},
3336
- ...firstImage ? { heroSrc: firstImage.url, heroAlt: firstImage.alt ?? title } : {},
3337
- ambientMotion: "zoomIn"
3338
- };
3339
- return config;
3340
- }
3341
-
3342
- // src/doc/docToMarkdown.ts
3343
- function docToMarkdown(doc) {
3344
- const children = [];
3345
- function emitBlock(block) {
3346
- if (block.sourceHeading) {
3347
- const heading = ensureAnnotation(block, block.sourceHeading);
3348
- children.push(heading);
3349
- }
3350
- if (block.contents) {
3351
- children.push(...block.contents);
3352
- }
3353
- if (block.children) {
3354
- for (const child of block.children) {
3355
- emitBlock(child);
3356
- }
3357
- }
3358
- }
3359
- for (const block of doc.blocks) {
3360
- emitBlock(block);
3361
- }
3362
- return {
3363
- type: "document",
3364
- children
3365
- };
3366
- }
3367
- function ensureAnnotation(block, heading) {
3368
- if (heading.templateAnnotation) return heading;
3369
- const hasExplicitTemplate = block.template && block.template !== "sectionHeader";
3370
- const hasOverrides = block.templateOverrides && Object.keys(block.templateOverrides).length > 0;
3371
- if (!hasExplicitTemplate && !hasOverrides) return heading;
3372
- return {
3373
- ...heading,
3374
- children: [...heading.children],
3375
- templateAnnotation: {
3376
- template: block.template ?? "sectionHeader",
3377
- ...hasOverrides ? { params: block.templateOverrides } : {}
3378
- }
3379
- };
3380
- }
3381
-
3382
- // src/doc/getLayers.ts
3383
- function getLayers(block, context = {}) {
3384
- const theme = context.theme ?? DEFAULT_THEME;
3385
- const viewport = context.viewport ?? VIEWPORT_PRESETS.landscape;
3386
- const blockIndex = context.blockIndex ?? 0;
3387
- const totalBlocks = context.totalBlocks ?? 1;
3388
- const existingLayers = block.layers;
3389
- if (existingLayers && existingLayers.length > 0 && !isTemplateBlock(block)) {
3390
- return injectPersistentLayers(existingLayers, block, context);
3391
- }
3392
- if (isTemplateBlock(block)) {
3393
- const resolved = resolveTemplateName(block.template);
3394
- if (resolved in templateRegistry) {
3395
- const templateName = resolved;
3396
- const templateCtx = createTemplateContext(theme, blockIndex, totalBlocks, viewport);
3397
- let layers;
3398
- try {
3399
- const templateFn = templateRegistry[templateName];
3400
- layers = templateFn(block, templateCtx);
3401
- if (!Array.isArray(layers)) {
3402
- console.error(`Template ${templateName} did not return an array, got:`, typeof layers);
3403
- layers = [];
3404
- }
3405
- } catch (err) {
3406
- console.error(`Error expanding template ${templateName}:`, err);
3407
- layers = [];
3408
- }
3409
- return injectPersistentLayers(layers, block, context);
3410
- }
3411
- }
3412
- return injectPersistentLayers([], block, context);
3413
- }
3414
- function injectPersistentLayers(layers, block, context) {
3415
- const { persistentLayers } = context;
3416
- if (!persistentLayers) return layers;
3417
- const bottomLayers = expandPersistentLayers(persistentLayers.bottomLayers);
3418
- const topLayers = expandPersistentLayers(persistentLayers.topLayers);
3419
- if (bottomLayers.length === 0 && topLayers.length === 0) return layers;
3420
- const templateBlock = block;
3421
- const useBottom = templateBlock.useBottomLayer !== false;
3422
- const useTop = templateBlock.useTopLayer !== false;
3423
- return [...useBottom ? bottomLayers : [], ...layers, ...useTop ? topLayers : []];
3424
- }
3425
-
3426
- // src/doc/audioMapping.ts
3427
- function parseTimingJson(data) {
3428
- try {
3429
- const text = new TextDecoder().decode(data);
3430
- const parsed = JSON.parse(text);
3431
- if (parsed && typeof parsed.sourceText === "string" && typeof parsed.duration === "number") {
3432
- return {
3433
- sourceText: parsed.sourceText,
3434
- bookmarks: Array.isArray(parsed.bookmarks) ? parsed.bookmarks : [],
3435
- duration: parsed.duration
3436
- };
3437
- }
3438
- return null;
3439
- } catch {
3440
- return null;
3441
- }
3442
- }
3443
- function normalizeToWords(text) {
3444
- const words = text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 2);
3445
- return new Set(words);
3446
- }
3447
- function scoreTextSimilarity(a, b) {
3448
- const wordsA = normalizeToWords(a);
3449
- const wordsB = normalizeToWords(b);
3450
- if (wordsA.size === 0 || wordsB.size === 0) return 0;
3451
- let intersection = 0;
3452
- for (const w of wordsA) {
3453
- if (wordsB.has(w)) intersection++;
3454
- }
3455
- const union = (/* @__PURE__ */ new Set([...wordsA, ...wordsB])).size;
3456
- return union > 0 ? intersection / union : 0;
3457
- }
3458
- function slugify2(text) {
3459
- return text.toLowerCase().replace(/[^\w\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
3460
- }
3461
- function blockToPlainText(block) {
3462
- const parts = [];
3463
- if (block.title) parts.push(block.title);
3464
- if (block.contents) {
3465
- for (const node of block.contents) {
3466
- parts.push(extractPlainText(node));
3467
- }
3468
- }
3469
- return parts.join("\n");
3470
- }
3471
- function flattenForAudio(blocks) {
3472
- const result = [];
3473
- for (const block of blocks) {
3474
- if (block.children && block.children.length > 0) {
3475
- result.push(...flattenForAudio(block.children));
3476
- } else {
3477
- result.push(block);
3478
- }
3479
- }
3480
- return result;
3481
- }
3482
- var AUDIO_ONLY_EXTENSIONS = [".mp3", ".wav", ".ogg", ".m4a"];
3483
- var AMBIGUOUS_EXTENSIONS = [".webm", ".mp4"];
3484
- function isNarrationAudioPath(path) {
3485
- const lower = path.toLowerCase();
3486
- if (AUDIO_ONLY_EXTENSIONS.some((ext) => lower.endsWith(ext))) return true;
3487
- if (AMBIGUOUS_EXTENSIONS.some((ext) => lower.endsWith(ext))) {
3488
- return lower.startsWith("audio/");
3489
- }
3490
- return false;
3491
- }
3492
- function stripAudioExtension(filename) {
3493
- const lower = filename.toLowerCase();
3494
- for (const ext of [...AUDIO_ONLY_EXTENSIONS, ...AMBIGUOUS_EXTENSIONS]) {
3495
- if (lower.endsWith(ext)) return filename.slice(0, -ext.length);
3496
- }
3497
- return filename;
3498
- }
3499
- function parseConsolidatedTiming(data) {
3500
- try {
3501
- const text = new TextDecoder().decode(data);
3502
- const parsed = JSON.parse(text);
3503
- if (parsed && parsed.version === 2 && parsed.sections) {
3504
- return parsed.sections;
3505
- }
3506
- return null;
3507
- } catch {
3508
- return null;
3509
- }
3510
- }
3511
- async function discoverMp3s(container) {
3512
- const files = await container.listFiles();
3513
- const audioFiles = files.filter((f) => isNarrationAudioPath(f.path));
3514
- const results = [];
3515
- let consolidatedSections = null;
3516
- const consolidatedData = await container.readFile("timing.json");
3517
- if (consolidatedData) {
3518
- consolidatedSections = parseConsolidatedTiming(consolidatedData);
3519
- }
3520
- for (const file of audioFiles) {
3521
- const filename = file.path.split("/").pop() ?? file.path;
3522
- let timing = null;
3523
- if (consolidatedSections) {
3524
- const audioBase = stripAudioExtension(filename);
3525
- for (const [sectionName, sectionTiming] of Object.entries(consolidatedSections)) {
3526
- if (audioBase.endsWith(`-${sectionName}`)) {
3527
- timing = sectionTiming;
3528
- break;
3529
- }
3530
- }
3531
- }
3532
- if (!timing) {
3533
- const timingPath = `${file.path}.timing.json`;
3534
- const timingData = await container.readFile(timingPath);
3535
- if (timingData) {
3536
- timing = parseTimingJson(timingData);
3537
- }
3538
- }
3539
- results.push({ path: file.path, filename, timing });
3540
- }
3541
- return results;
3542
- }
3543
- function resolveFromAnnotations(blocks, mp3s) {
3544
- const matches = [];
3545
- const flat = flattenForAudio(blocks);
3546
- for (const block of flat) {
3547
- const audioRef = block.templateOverrides?.audio;
3548
- if (!audioRef) continue;
3549
- const mp3 = mp3s.find(
3550
- (m) => m.filename === audioRef || m.path === audioRef || m.path.endsWith(`/${audioRef}`)
3551
- );
3552
- if (mp3) {
3553
- matches.push({ block, mp3 });
3554
- }
3555
- }
3556
- return matches;
3557
- }
3558
- var MIN_CONTENT_SIMILARITY = 0.35;
3559
- var MIN_FILENAME_SIMILARITY = 0.5;
3560
- function autoMatchBlocks(blocks, mp3s) {
3561
- const flat = flattenForAudio(blocks);
3562
- if (flat.length === 0 || mp3s.length === 0) return [];
3563
- const scoredPairs = [];
3564
- for (let mi = 0; mi < mp3s.length; mi++) {
3565
- const mp3 = mp3s[mi];
3566
- for (let bi = 0; bi < flat.length; bi++) {
3567
- const block = flat[bi];
3568
- const blockText = blockToPlainText(block);
3569
- if (!blockText.trim()) continue;
3570
- let score = 0;
3571
- if (mp3.timing?.sourceText) {
3572
- score = scoreTextSimilarity(mp3.timing.sourceText, blockText);
3573
- }
3574
- if (score < MIN_CONTENT_SIMILARITY && block.title) {
3575
- const titleSlug = slugify2(block.title);
3576
- const fileSlug = slugify2(stripAudioExtension(mp3.filename));
3577
- if (fileSlug.includes(titleSlug) && titleSlug.length >= 3) {
3578
- score = Math.max(score, MIN_FILENAME_SIMILARITY + 0.1);
3579
- }
3580
- }
3581
- if (score >= MIN_CONTENT_SIMILARITY) {
3582
- scoredPairs.push({ block, blockIndex: bi, mp3, mp3Index: mi, score });
3583
- }
3584
- }
3585
- }
3586
- scoredPairs.sort((a, b) => b.score - a.score);
3587
- const usedBlocks = /* @__PURE__ */ new Set();
3588
- const usedMp3s = /* @__PURE__ */ new Set();
3589
- const matches = [];
3590
- for (const pair of scoredPairs) {
3591
- if (usedBlocks.has(pair.blockIndex) || usedMp3s.has(pair.mp3Index)) continue;
3592
- usedBlocks.add(pair.blockIndex);
3593
- usedMp3s.add(pair.mp3Index);
3594
- matches.push({ block: pair.block, mp3: pair.mp3, score: pair.score });
3595
- }
3596
- return matches;
3597
- }
3598
- async function resolveAudioMapping(doc, container) {
3599
- const mp3s = await discoverMp3s(container);
3600
- if (mp3s.length === 0) return doc;
3601
- let matches = resolveFromAnnotations(doc.blocks, mp3s);
3602
- if (matches.length === 0) {
3603
- matches = autoMatchBlocks(doc.blocks, mp3s).map((m) => ({
3604
- block: m.block,
3605
- mp3: m.mp3
3606
- }));
3607
- }
3608
- if (matches.length === 0) return doc;
3609
- const flat = flattenForAudio(doc.blocks);
3610
- const blockOrder = new Map(flat.map((b, i) => [b.id, i]));
3611
- matches.sort((a, b) => (blockOrder.get(a.block.id) ?? 0) - (blockOrder.get(b.block.id) ?? 0));
3612
- const segments = [];
3613
- const blockToSegment = /* @__PURE__ */ new Map();
3614
- let startTime = 0;
3615
- for (let i = 0; i < matches.length; i++) {
3616
- const { block, mp3 } = matches[i];
3617
- const duration = mp3.timing?.duration ?? 30;
3618
- segments.push({
3619
- src: mp3.path,
3620
- name: block.title ?? block.id,
3621
- duration,
3622
- startTime
3623
- });
3624
- blockToSegment.set(block.id, i);
3625
- startTime += duration;
3626
- }
3627
- const newBlocks = assignSegmentIndices(doc.blocks, blockToSegment);
3628
- return {
3629
- ...doc,
3630
- blocks: newBlocks,
3631
- duration: startTime,
3632
- audio: { segments }
3633
- };
3634
- }
3635
- function assignSegmentIndices(blocks, blockToSegment, inheritedSegment) {
3636
- return blocks.map((block) => {
3637
- const segment = blockToSegment.get(block.id) ?? inheritedSegment ?? block.audioSegment;
3638
- const newBlock = {
3639
- ...block,
3640
- audioSegment: segment
3641
- };
3642
- if (block.children) {
3643
- newBlock.children = assignSegmentIndices(block.children, blockToSegment, segment);
3644
- }
3645
- return newBlock;
3646
- });
3647
- }
3648
-
3649
- export {
3650
- expandPersistentLayers,
3651
- getDocStyleConfig,
3652
- resolveColorScheme,
3653
- getThemeFont,
3654
- themedFontSize,
3655
- scaleAnimationDuration,
3656
- getDefaultAnimation,
3657
- shouldUseShadow,
3658
- getOverlayOpacity,
3659
- getTemplateHint,
3660
- titleBlock,
3661
- sectionHeader,
3662
- DEFAULT_LAYOUT,
3663
- getAccentLayout,
3664
- createAccentLayers,
3665
- adjustY,
3666
- statHighlight,
3667
- quoteBlock,
3668
- factCard,
3669
- twoColumn,
3670
- dateEvent,
3671
- imageWithCaption,
3672
- leftFeature,
3673
- rightFeature,
3674
- mapBlock,
3675
- fullBleedQuote,
3676
- listBlock,
3677
- photoGrid,
3678
- definitionCard,
3679
- comparisonBar,
3680
- pullQuote,
3681
- videoWithCaption,
3682
- videoPullQuote,
3683
- dataTable,
3684
- coverBlock,
3685
- expandCoverBlock,
3686
- templateRegistry,
3687
- TEMPLATE_ALIASES,
3688
- resolveTemplateName,
3689
- expandTemplateBlock,
3690
- expandDocBlocks,
3691
- getAvailableTemplates,
3692
- hasTemplate,
3693
- getAnimationStyle,
3694
- getDefaultAnimationDuration,
3695
- getTransitionClass,
3696
- getAnimationProgress,
3697
- markdownToDoc,
3698
- flattenBlocks,
3699
- countBlocks,
3700
- getBlockDepth,
3701
- docToMarkdown,
3702
- getLayers,
3703
- scoreTextSimilarity,
3704
- resolveAudioMapping
3705
- };
3706
- //# sourceMappingURL=chunk-KSWJR66U.js.map