@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 +0,0 @@
1
- {"version":3,"sources":["../src/schemas/Doc.ts","../src/schemas/themeCompile.ts"],"sourcesContent":["/**\n * Doc Schema\n *\n * Defines the JSON format for AI-scriptable visual docs that accompany\n * audio narration. A Doc describes a sequence of animated blocks\n * with text overlays, images, and transitions synchronized to audio.\n *\n * The format is designed to be:\n * 1. AI-generatable - Claude can create scripts from article content\n * 2. Browser-renderable - SVG + CSS animations (ES2015 compatible)\n * 3. Video-exportable - Frame-by-frame capture via Playwright\n *\n * Timing: Blocks are timed to match narration audio segments. Each article\n * has 3-6 MP3 files (intro + sections), and blocks are grouped by segment.\n */\n\n// ============================================\n// Core Types\n// ============================================\n\n/**\n * Configuration for the Start/resting block shown before playback begins.\n */\nexport interface StartBlockConfig {\n /** Hero image path (relative to article media). When omitted, a theme-driven background is used. */\n heroSrc?: string;\n /** Alt text for the hero image */\n heroAlt?: string;\n /** Title to display over the hero */\n title: string;\n /** Optional subtitle */\n subtitle?: string;\n /** Ambient motion for the hero image */\n ambientMotion?: 'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight';\n /** Photo credit / artist name for the hero image */\n heroCredit?: string;\n /** License identifier for the hero image */\n heroLicense?: string;\n}\n\n/**\n * A complete visual doc for an article.\n */\nexport interface Doc {\n /** Article ID this doc belongs to */\n articleId: string;\n\n /** Total duration in seconds (sum of all audio segments) */\n duration: number;\n\n /** Ordered list of blocks */\n blocks: Block[];\n\n /** Audio track configuration */\n audio: AudioTrack;\n\n /** Caption track for closed captions (generated by postprocess-doc) */\n captions?: CaptionTrack;\n\n /**\n * Start/resting block shown before playback begins.\n * Displays hero image with title - acts as a \"poster\" for the doc.\n * The player shows this until the user starts playback.\n */\n startBlock?: StartBlockConfig;\n\n /**\n * Persistent layers rendered on every block (behind and/or on top of content).\n * Used for consistent branding overlays, background gradients, etc.\n */\n persistentLayers?: import('./BlockTemplates.js').PersistentLayerConfig;\n\n /**\n * Optional theme identifier. Resolved at render time via `resolveTheme()`.\n * When omitted, the renderer uses the default theme ('documentary').\n */\n themeId?: string;\n\n /** Optional metadata */\n meta?: {\n generatedAt?: string;\n generatedBy?: string;\n version?: number;\n };\n\n /**\n * YAML frontmatter from the source markdown.\n * Carries rendering hints like `document-render-as` and custom metadata.\n */\n frontmatter?: Record<string, unknown>;\n}\n\n/**\n * A single block in the doc.\n *\n * Blocks can be flat (audio-synced timeline) or nested (markdown-driven hierarchy).\n * When derived from markdown, a block corresponds to a heading section:\n * - `sourceHeading` references the original MarkdownHeading node\n * - `contents` holds the body markdown between this heading and the next\n * - `children` holds sub-heading blocks (e.g., H2s under an H1)\n */\nexport interface Block {\n /** Unique identifier for this block */\n id: string;\n\n /** When this block appears (seconds from start) */\n startTime: number;\n\n /** How long this block is visible (seconds) */\n duration: number;\n\n /** Which audio segment this block belongs to (0-indexed) */\n audioSegment: number;\n\n /**\n * Pre-computed visual layers, rendered back-to-front.\n *\n * Optional — template-derived blocks typically omit this and compute\n * layers on demand via `getLayers()` from `@bendyline/squisq/doc`.\n * Raw blocks (e.g., hand-crafted by AI) may provide layers directly.\n */\n layers?: Layer[];\n\n /** Entry transition from previous block */\n transition?: Transition;\n\n /** Template name that generated this block (for debugging) */\n template?: string;\n\n /**\n * Display title for template rendering.\n * Extracted from the sourceHeading when the block is created by markdownToDoc().\n * Templates like sectionHeader and titleBlock read this for their title layer.\n */\n title?: string;\n\n // ── Markdown-driven hierarchy (optional) ──\n\n /**\n * Nested sub-blocks (heading hierarchy).\n * When a doc is derived from markdown, sub-headings within this\n * heading's section become child blocks. For example, H2 blocks\n * under an H1 block appear here.\n */\n children?: Block[];\n\n /**\n * Markdown body content for this block's section.\n * Contains the block-level markdown nodes (paragraphs, lists, code,\n * blockquotes, etc.) that appear between this heading and the next\n * heading or sub-heading. Empty for pure structural blocks.\n */\n contents?: import('../markdown/types.js').MarkdownBlockNode[];\n\n /**\n * Reference to the MarkdownHeading node that created this block.\n * Present when the block was derived from markdown via markdownToDoc().\n * Enables round-tripping back to markdown and provides heading depth.\n * Absent for the preamble block (content before the first heading).\n */\n sourceHeading?: import('../markdown/types.js').MarkdownHeading;\n\n /**\n * Template overrides extracted from markdown directives.\n * For example, `### Data Section {template=chart colorScheme=blue}`\n * would produce `{ template: 'chart', colorScheme: 'blue' }`.\n * Allows per-block customization of template selection and parameters.\n */\n templateOverrides?: Record<string, string>;\n}\n\n// ============================================\n// Layer Types\n// ============================================\n\n/**\n * A visual element within a block.\n * Layers are composited back-to-front (first layer is background).\n */\nexport type Layer = ImageLayer | TextLayer | ShapeLayer | MapLayer | VideoLayer | TableLayer;\n\ninterface BaseLayer {\n /** Unique identifier for this layer */\n id: string;\n\n /** Position and size */\n position: Position;\n\n /** Animation to apply */\n animation?: Animation;\n}\n\n/**\n * Image layer - displays an image with optional Ken Burns effect.\n */\nexport interface ImageLayer extends BaseLayer {\n type: 'image';\n content: {\n /** Path to image file (relative to article media dir) */\n src: string;\n /** Alt text for accessibility */\n alt: string;\n /** How to fit image in bounds */\n fit?: 'cover' | 'contain' | 'fill';\n /** Photo credit / artist name */\n credit?: string;\n /** License identifier (e.g., 'CC BY-SA 4.0') */\n license?: string;\n };\n}\n\n/**\n * Text layer - displays text with styling.\n */\nexport interface TextLayer extends BaseLayer {\n type: 'text';\n content: {\n /** Text to display (supports \\n for line breaks) */\n text: string;\n /** Text styling */\n style: TextStyle;\n };\n}\n\n/**\n * Shape layer - simple geometric shapes for visual accents.\n */\nexport interface ShapeLayer extends BaseLayer {\n type: 'shape';\n content: {\n /** Shape type */\n shape: 'rect' | 'circle' | 'line';\n /** Fill color (CSS color or 'none') */\n fill?: string;\n /** Stroke color */\n stroke?: string;\n /** Stroke width in pixels */\n strokeWidth?: number;\n /** Corner radius for rect */\n borderRadius?: number;\n };\n}\n\n/**\n * Map layer - displays a geographic map with optional markers.\n *\n * Maps are rendered as composite tile images from free tile providers.\n * Supported styles use open-source/free tiles requiring attribution.\n */\nexport interface MapLayer extends BaseLayer {\n type: 'map';\n content: {\n /** Center coordinates for the map */\n center: {\n lat: number;\n lng: number;\n };\n /** Zoom level (0-18, typically 8-14 for doc blocks) */\n zoom: number;\n /** Map tile style */\n style: MapTileStyle;\n /** Optional markers to display on the map */\n markers?: MapMarker[];\n /** Pre-rendered static image path (for video export reliability) */\n staticSrc?: string;\n /** Show attribution text (default: true) */\n showAttribution?: boolean;\n };\n}\n\n/**\n * Video layer - displays a short video clip, always muted (narration provides audio).\n *\n * Rendered via an HTML5 <video> element inside <foreignObject>, similar to how\n * ImageLayer uses <img> for Ken Burns effects. clipStart/clipEnd define the window\n * within the source video to play. During Playwright frame capture (seekTo mode),\n * the video is seeked programmatically rather than playing in real time.\n */\nexport interface VideoLayer extends BaseLayer {\n type: 'video';\n content: {\n /** Path to video file (relative to article media dir) */\n src: string;\n /** Path to poster frame (shown before video loads / during seek) */\n posterSrc?: string;\n /** Alt text for accessibility */\n alt: string;\n /** How to fit video in bounds */\n fit?: 'cover' | 'contain' | 'fill';\n /** Start time within the source video (seconds) */\n clipStart: number;\n /** End time within the source video (seconds) */\n clipEnd: number;\n /** Total source video duration (for validation) */\n sourceDuration?: number;\n /** Video credit / artist name */\n credit?: string;\n /** License identifier (e.g., 'CC BY-SA 4.0') */\n license?: string;\n };\n}\n\n/**\n * Table layer - renders a data table with themed styling.\n * Uses foreignObject inside SVG for HTML-based table layout.\n */\nexport interface TableLayer extends BaseLayer {\n type: 'table';\n content: {\n /** Header cell values */\n headers: string[];\n /** Data rows (array of cell value arrays) */\n rows: string[][];\n /** Per-column alignment */\n align?: (('left' | 'right' | 'center') | null)[];\n /** Visual styling */\n style: TableLayerStyle;\n };\n}\n\n/**\n * Styling options for a TableLayer.\n */\nexport interface TableLayerStyle {\n /** Header row background color */\n headerBackground: string;\n /** Header row text color */\n headerColor: string;\n /** Body cell background color */\n cellBackground: string;\n /** Body cell text color */\n cellColor: string;\n /** Border/divider color */\n borderColor: string;\n /** Font size in pixels */\n fontSize: number;\n /** Font family */\n fontFamily?: string;\n /** Header font family (falls back to fontFamily) */\n headerFontFamily?: string;\n /** Corner radius for the table container */\n borderRadius?: number;\n}\n\n/**\n * Available map tile styles from free/open-source providers.\n */\nexport type MapTileStyle =\n | 'terrain' // OpenTopoMap - topographic/terrain (default)\n | 'satellite' // ESRI World Imagery\n | 'road' // OpenStreetMap standard\n | 'toner' // Stadia Toner (high contrast B&W)\n | 'watercolor'; // Stadia Watercolor (artistic)\n\n/**\n * A marker to display on the map.\n */\nexport interface MapMarker {\n /** Marker latitude */\n lat: number;\n /** Marker longitude */\n lng: number;\n /** Optional label text */\n label?: string;\n /** Marker color (CSS color, default: #ef4444) */\n color?: string;\n /** Marker icon type */\n icon?: 'pin' | 'circle' | 'star';\n}\n\n// ============================================\n// Position & Styling\n// ============================================\n\n/**\n * Position and dimensions for a layer.\n * Values can be pixels (number) or percentages (string like \"50%\").\n */\nexport interface Position {\n /** X position (pixels or percentage) */\n x: number | string;\n /** Y position (pixels or percentage) */\n y: number | string;\n /** Width (pixels or percentage) */\n width?: number | string;\n /** Height (pixels or percentage) */\n height?: number | string;\n /** Anchor point for positioning */\n anchor?: 'center' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';\n}\n\n/**\n * Text styling options.\n */\nexport interface TextStyle {\n /** Font size in pixels */\n fontSize: number;\n /** Font family (defaults to system sans-serif) */\n fontFamily?: string;\n /** Font weight */\n fontWeight?: 'normal' | 'bold';\n /** Text color (CSS color) */\n color: string;\n /** Text alignment */\n textAlign?: 'left' | 'center' | 'right';\n /** Line height multiplier */\n lineHeight?: number;\n /** Add drop shadow for readability over images */\n shadow?: boolean;\n /** Background color for text box */\n background?: string;\n /** Padding around text (pixels) */\n padding?: number;\n /** Maximum number of lines before truncation (adds \"...\" to last line) */\n maxLines?: number;\n}\n\n// ============================================\n// Animation & Transitions\n// ============================================\n\n/**\n * Animation to apply to a layer.\n */\nexport interface Animation {\n /** Animation type */\n type: AnimationType;\n /** Duration in seconds (defaults to layer's block duration) */\n duration?: number;\n /** Delay before animation starts (seconds) */\n delay?: number;\n /** CSS easing function */\n easing?: string;\n /** For Ken Burns: zoom direction */\n direction?: 'in' | 'out';\n /** For pan animations: pan direction */\n panDirection?: 'left' | 'right' | 'up' | 'down';\n}\n\n/**\n * Available animation types.\n */\nexport type AnimationType =\n | 'none'\n | 'fadeIn'\n | 'fadeOut'\n | 'slowZoom' // Slow zoom with optional pan\n | 'zoomIn'\n | 'zoomOut'\n | 'panLeft'\n | 'panRight'\n | 'typewriter'; // Text appears letter by letter\n\n/**\n * Transition between blocks.\n */\nexport interface Transition {\n /** Transition type */\n type: TransitionType;\n /** Duration in seconds */\n duration: number;\n}\n\nexport type TransitionType =\n | 'cut' // Instant switch\n | 'fade' // Cross-fade\n | 'dissolve' // Soft dissolve\n | 'slideLeft' // New block enters from right\n | 'slideRight'; // New block enters from left\n\n// ============================================\n// Audio Configuration\n// ============================================\n\n/**\n * Audio track configuration.\n * Articles have multiple MP3 segments (intro + sections).\n */\nexport interface AudioTrack {\n /** Audio segments in playback order */\n segments: AudioSegment[];\n}\n\n// ============================================\n// Captions\n// ============================================\n\n/**\n * A single word with precise timing, used for word-level highlighting\n * in social-style captions. Populated from TTS timing data when available.\n */\nexport interface CaptionWord {\n /** The word text */\n text: string;\n /** Start time in seconds (relative to doc start) */\n startTime: number;\n /** End time in seconds */\n endTime: number;\n}\n\n/**\n * A single caption phrase to display during playback.\n */\nexport interface CaptionPhrase {\n /** The text to display */\n text: string;\n /** Start time in seconds (relative to doc start) */\n startTime: number;\n /** End time in seconds */\n endTime: number;\n /** Which audio segment this caption belongs to (0-indexed) */\n audioSegment: number;\n /**\n * Optional per-word timing from TTS timing data.\n * When present, enables precise word-level highlighting in social\n * caption style. When absent, word timing is interpolated evenly\n * across the phrase duration.\n */\n words?: CaptionWord[];\n}\n\n/**\n * Caption track for a doc.\n */\nexport interface CaptionTrack {\n /** Caption phrases in chronological order */\n phrases: CaptionPhrase[];\n /** When the captions were generated */\n generatedAt: string;\n /** Algorithm version for regeneration detection */\n version: number;\n}\n\n/**\n * A single audio segment (one MP3 file).\n */\nexport interface AudioSegment {\n /** Path to MP3 file (relative to article media dir) */\n src: string;\n /** Segment name (e.g., \"intro\", \"history\") */\n name: string;\n /** Duration in seconds */\n duration: number;\n /** Start time in overall timeline (calculated) */\n startTime: number;\n}\n\n// ============================================\n// Audio Timing Data (from TTS)\n// ============================================\n\n/**\n * A single word-level timing bookmark from TTS synthesis.\n * Used for precise audio-to-content mapping and word-level caption sync.\n */\nexport interface AudioBookmark {\n /** Unique identifier (e.g., \"word-0\", \"word-1\") */\n id: string;\n /** Timestamp in seconds from audio start */\n time: number;\n /** Character offset in the source text */\n charOffset: number;\n /** The word text at this position */\n textFragment?: string;\n}\n\n/**\n * Timing data for an audio segment, typically from a `.timing.json` file\n * generated alongside TTS audio. Contains the source text and per-word\n * timing bookmarks for precise content matching and caption sync.\n */\nexport interface AudioTimingData {\n /** The normalized plain text that was synthesized */\n sourceText: string;\n /** Word-level timing bookmarks */\n bookmarks: AudioBookmark[];\n /** Total audio duration in seconds */\n duration: number;\n}\n\n// ============================================\n// Helper Functions\n// ============================================\n\n/**\n * Calculate total duration from audio segments.\n */\nexport function calculateDuration(audio: AudioTrack): number {\n return audio.segments.reduce((sum, seg) => sum + seg.duration, 0);\n}\n\n/**\n * Find which audio segment is playing at a given time.\n */\nexport function getSegmentAtTime(audio: AudioTrack, time: number): number {\n let elapsed = 0;\n for (let i = 0; i < audio.segments.length; i++) {\n elapsed += audio.segments[i].duration;\n if (time < elapsed) return i;\n }\n return audio.segments.length - 1;\n}\n\n/**\n * Find which block should be visible at a given time.\n */\nexport function getBlockAtTime(blocks: Block[], time: number): Block | null {\n for (let i = blocks.length - 1; i >= 0; i--) {\n const block = blocks[i];\n if (time >= block.startTime && time < block.startTime + block.duration) {\n return block;\n }\n }\n return blocks[0] || null;\n}\n\n/**\n * Find the caption phrase that should be displayed at a given time.\n */\nexport function getCaptionAtTime(\n captions: CaptionTrack | undefined,\n time: number,\n): CaptionPhrase | null {\n if (!captions || !captions.phrases.length) return null;\n\n for (const phrase of captions.phrases) {\n if (time >= phrase.startTime && time < phrase.endTime) {\n return phrase;\n }\n }\n return null;\n}\n\n/**\n * Validate a Doc for completeness.\n */\nexport function validateDoc(script: Doc): string[] {\n const errors: string[] = [];\n\n if (!script.articleId) {\n errors.push('Missing articleId');\n }\n\n if (!script.blocks || script.blocks.length === 0) {\n errors.push('No blocks defined');\n }\n\n if (!script.audio || !script.audio.segments || script.audio.segments.length === 0) {\n errors.push('No audio segments defined');\n }\n\n // Check for gaps in block coverage\n const totalDuration = script.duration;\n let covered = 0;\n for (const block of script.blocks) {\n if (block.startTime > covered + 0.1) {\n errors.push(`Gap in blocks: ${covered}s to ${block.startTime}s`);\n }\n covered = Math.max(covered, block.startTime + block.duration);\n }\n\n if (covered < totalDuration - 0.1) {\n errors.push(`Blocks end at ${covered}s but audio is ${totalDuration}s`);\n }\n\n return errors;\n}\n","/**\n * Theme Compilation\n *\n * Turns a partial Theme (typically authored by the customizer panel from\n * a few seed colors and preset choices) into a complete, validated Theme\n * by:\n *\n * 1. Filling unspecified fields from a hardcoded `STARTER_THEME`.\n * 2. Deriving missing color slots from `seedColors` via OKLCh math.\n * 3. Validating the result.\n *\n * Built-in themes ship as fully-specified Theme JSON and skip this step.\n */\n\nimport type {\n Theme,\n DeepPartial,\n ThemeColorPalette,\n ThemeColorScheme,\n ThemeSeedColors,\n FontFamily,\n} from './Theme.js';\nimport { THEME_SCHEMA_VERSION, createTheme } from './Theme.js';\nimport { assertTheme } from './themeValidator.js';\nimport {\n oklchLighten,\n oklchDarken,\n oklchSetChroma,\n pickContrastingText,\n relativeLuminance,\n} from './colorUtils.js';\n\n/** Internal default theme used to fill in fields the customizer doesn't expose. */\nconst STARTER_BODY_FONT: FontFamily = { stackId: 'system-sans' };\nconst STARTER_TITLE_FONT: FontFamily = { stackId: 'system-serif' };\nconst STARTER_MONO_FONT: FontFamily = { stackId: 'system-mono' };\n\nconst STARTER_COLOR_SCHEMES: Record<string, ThemeColorScheme> = {\n blue: { bg: '#1a365d', text: '#63b3ed', accent: '#90cdf4' },\n green: { bg: '#22543d', text: '#9ae6b4', accent: '#68d391' },\n purple: { bg: '#44337a', text: '#d6bcfa', accent: '#b794f4' },\n red: { bg: '#742a2a', text: '#fc8181', accent: '#feb2b2' },\n orange: { bg: '#744210', text: '#fbd38d', accent: '#f6ad55' },\n teal: { bg: '#234e52', text: '#81e6d9', accent: '#4fd1c5' },\n};\n\nexport const STARTER_THEME: Theme = {\n schemaVersion: THEME_SCHEMA_VERSION,\n id: 'custom',\n name: 'Custom Theme',\n description: 'Customizer starter — gets overridden by user choices.',\n colors: {\n primary: '#3182ce',\n secondary: '#4a5568',\n background: '#1a202c',\n backgroundLight: '#2d3748',\n text: '#f7fafc',\n textMuted: '#a0aec0',\n highlight: '#4299e1',\n warning: '#fc8181',\n },\n typography: {\n bodyFont: STARTER_BODY_FONT,\n titleFont: STARTER_TITLE_FONT,\n monoFont: STARTER_MONO_FONT,\n titleWeight: 'bold',\n },\n style: {\n textShadow: true,\n overlayOpacity: 0.45,\n animationSpeed: 1.0,\n borderRadius: 6,\n },\n renderStyle: {\n name: 'standard',\n defaultTextAnimation: 'fadeIn',\n defaultImageAnimation: 'slowZoom',\n ambientMotion: true,\n defaultTransition: { type: 'fade', duration: 0.7 },\n },\n colorSchemes: STARTER_COLOR_SCHEMES,\n};\n\n/**\n * Derive a full `ThemeColorPalette` from `seedColors`, with any explicit\n * `partialColors` taking precedence over derived values. Background and\n * text are guessed from luminance when the user gave only a primary.\n */\nexport function deriveColorPalette(\n seeds: ThemeSeedColors,\n partialColors: Partial<ThemeColorPalette> = {},\n opts: { contrast?: 'subtle' | 'balanced' | 'high' } = {},\n): ThemeColorPalette {\n const spread = opts.contrast === 'high' ? 0.22 : opts.contrast === 'subtle' ? 0.08 : 0.15;\n\n const primary = seeds.primary;\n const secondary = seeds.secondary ?? oklchSetChroma(oklchLighten(primary, 0.05), 0.5);\n const accent = seeds.accent ?? oklchLighten(primary, spread);\n\n // Decide light vs dark surface from the explicit background, the seed background,\n // or default to dark.\n const bgSeed = partialColors.background ?? seeds.background;\n let background: string;\n if (bgSeed) {\n background = bgSeed;\n } else {\n // Pick a dark or light background that contrasts with primary\n background = relativeLuminance(primary) > 0.5 ? '#0a0a0a' : '#1a202c';\n }\n const isLightSurface = relativeLuminance(background) > 0.5;\n\n const backgroundLight =\n partialColors.backgroundLight ??\n (isLightSurface ? oklchDarken(background, 0.04) : oklchLighten(background, 0.04));\n\n const text =\n partialColors.text ?? seeds.text ?? pickContrastingText(background, '#f7fafc', '#1a202c');\n const textMuted =\n partialColors.textMuted ??\n (isLightSurface ? oklchLighten(text, 0.25) : oklchDarken(text, 0.25));\n\n const highlight = partialColors.highlight ?? accent;\n const warning = partialColors.warning ?? '#fc8181';\n\n return {\n primary: partialColors.primary ?? primary,\n secondary: partialColors.secondary ?? secondary,\n background,\n backgroundLight,\n text,\n textMuted,\n highlight,\n warning,\n };\n}\n\n/** Map a contrast preset to numeric spread used by `deriveColorPalette`. */\nexport type ContrastPreset = 'subtle' | 'balanced' | 'high';\n\nexport interface CompileOptions {\n /** Contrast level for OKLCh derivation (default 'balanced'). */\n contrast?: ContrastPreset;\n}\n\n/**\n * Compile a partial Theme into a complete one. Fills missing fields from\n * `STARTER_THEME`, derives missing color slots from `seedColors` (when\n * present), and validates the result.\n */\nexport function compileTheme(partial: DeepPartial<Theme>, opts: CompileOptions = {}): Theme {\n // Step 1: deep-merge over the starter\n const merged = createTheme(STARTER_THEME, partial);\n merged.schemaVersion = THEME_SCHEMA_VERSION;\n\n // Step 1b: typography fonts are discriminated unions ({stackId} | {custom}),\n // so deep-merge would leave stale keys from the starter when the partial\n // switches form. Replace each font wholesale when explicitly provided.\n const partialTypography = partial.typography;\n if (partialTypography) {\n if (partialTypography.titleFont !== undefined) {\n merged.typography.titleFont = partialTypography.titleFont as FontFamily;\n }\n if (partialTypography.bodyFont !== undefined) {\n merged.typography.bodyFont = partialTypography.bodyFont as FontFamily;\n }\n if (partialTypography.monoFont !== undefined) {\n merged.typography.monoFont = partialTypography.monoFont as FontFamily;\n }\n }\n\n // Step 2: derive missing color slots from seeds, if present\n if (merged.seedColors) {\n const partialColors = (partial.colors ?? {}) as Partial<ThemeColorPalette>;\n merged.colors = deriveColorPalette(merged.seedColors, partialColors, {\n contrast: opts.contrast,\n });\n }\n\n // Step 3: validate\n return assertTheme(merged, `compiled theme \"${merged.id}\"`);\n}\n\n/**\n * Parse a JSON string into a validated Theme. Throws on invalid input.\n */\nexport function parseTheme(json: string): Theme {\n let parsed: unknown;\n try {\n parsed = JSON.parse(json);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n throw new Error(`Invalid theme JSON: ${msg}`);\n }\n return assertTheme(parsed, 'parsed theme');\n}\n\n/**\n * Serialize a Theme to a stable, pretty-printed JSON string. Round-trips\n * cleanly through `parseTheme`.\n */\nexport function serializeTheme(theme: Theme): string {\n return JSON.stringify(theme, null, 2);\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/schemas/Viewport.ts","../src/schemas/LayoutStrategy.ts","../src/schemas/BlockTemplates.ts"],"sourcesContent":["/**\n * Viewport Configuration\n *\n * Defines viewport dimensions for doc rendering across different aspect ratios.\n * Templates use this configuration to adapt their layouts appropriately.\n *\n * Supported aspect ratios:\n * - landscape (16:9) - Default, standard video/presentation format\n * - portrait (9:16) - Vertical video, mobile stories\n * - square (1:1) - Social media posts\n * - standard (4:3) - Legacy presentation format\n */\n\n/**\n * Viewport configuration for doc rendering.\n */\nexport interface ViewportConfig {\n /** Canonical width in virtual pixels */\n width: number;\n /** Canonical height in virtual pixels */\n height: number;\n /** Human-readable name for debugging/display */\n name: string;\n}\n\n/**\n * Standard viewport presets for common aspect ratios.\n */\nexport const VIEWPORT_PRESETS = {\n /** 16:9 landscape (default, 1080p) */\n landscape: { width: 1920, height: 1080, name: '16:9 Landscape' },\n /** 9:16 portrait (vertical video, stories) */\n portrait: { width: 1080, height: 1920, name: '9:16 Portrait' },\n /** 1:1 square (social media) */\n square: { width: 1080, height: 1080, name: '1:1 Square' },\n /** 4:3 standard (legacy) */\n standard: { width: 1440, height: 1080, name: '4:3 Standard' },\n} as const;\n\n/**\n * Viewport preset name.\n */\nexport type ViewportPreset = keyof typeof VIEWPORT_PRESETS;\n\n/**\n * Viewport orientation derived from aspect ratio.\n */\nexport type ViewportOrientation = 'landscape' | 'portrait' | 'square';\n\n/**\n * Get a viewport configuration from a preset name or return the config if already a ViewportConfig.\n */\nexport function getViewport(viewport: ViewportPreset | ViewportConfig): ViewportConfig {\n if (typeof viewport === 'string') {\n return VIEWPORT_PRESETS[viewport];\n }\n return viewport;\n}\n\n/**\n * Calculate font scale factor for a viewport.\n * Based on diagonal pixels relative to 1080p landscape reference.\n * This ensures text remains readable across different viewport sizes.\n */\nconst REFERENCE_DIAGONAL = Math.sqrt(1920 * 1920 + 1080 * 1080); // ~2203\n\nexport function calculateFontScale(viewport: ViewportConfig): number {\n const currentDiagonal = Math.sqrt(\n viewport.width * viewport.width + viewport.height * viewport.height,\n );\n return currentDiagonal / REFERENCE_DIAGONAL;\n}\n\n/**\n * Determine if viewport is landscape, portrait, or square.\n */\nexport function getViewportOrientation(viewport: ViewportConfig): ViewportOrientation {\n const ratio = viewport.width / viewport.height;\n // Allow small tolerance for \"square\" classification\n if (Math.abs(ratio - 1) < 0.05) return 'square';\n return ratio > 1 ? 'landscape' : 'portrait';\n}\n\n/**\n * Get aspect ratio as a string (e.g., \"16:9\", \"9:16\", \"1:1\").\n */\nexport function getAspectRatioString(viewport: ViewportConfig): string {\n const gcd = (a: number, b: number): number => (b === 0 ? a : gcd(b, a % b));\n const divisor = gcd(viewport.width, viewport.height);\n return `${viewport.width / divisor}:${viewport.height / divisor}`;\n}\n","/**\n * Layout Strategy\n *\n * Provides orientation-specific layout hints for slide templates.\n * Templates use these hints to position content appropriately for\n * different aspect ratios (landscape, portrait, square).\n *\n * Key adaptations by orientation:\n * - Portrait: Larger relative text, stacked layouts instead of side-by-side\n * - Square: Balanced layout with moderate adjustments\n * - Landscape: Default/reference layout\n */\n\nimport type { ViewportOrientation, ViewportConfig } from './Viewport.js';\nimport { calculateFontScale } from './Viewport.js';\n\n/**\n * Layout hints for template positioning based on orientation.\n */\nexport interface LayoutHints {\n /** Primary content Y position (percentage string, e.g., \"35%\") */\n primaryY: string;\n /** Secondary content Y position (percentage string) */\n secondaryY: string;\n /** Tertiary/detail Y position (percentage string) */\n tertiaryY: string;\n /** Title font size multiplier (relative to base) */\n titleScale: number;\n /** Body text font size multiplier (relative to base) */\n bodyScale: number;\n /** Two-column: left X position (percentage string) */\n columnLeftX: string;\n /** Two-column: right X position (percentage string) */\n columnRightX: string;\n /** Two-column in portrait: top Y position for stacked layout */\n columnTopY: string;\n /** Two-column in portrait: bottom Y position for stacked layout */\n columnBottomY: string;\n /** Whether two-column should stack vertically */\n stackColumns: boolean;\n /** Max text width (percentage string) for wrapping */\n maxTextWidth: string;\n /** Horizontal padding from edges (percentage string) */\n horizontalPadding: string;\n /** Caption position Y for imageWithCaption (percentage string) */\n captionY: string;\n /** Caption font size multiplier */\n captionScale: number;\n}\n\n/**\n * Layout configurations by orientation.\n */\nconst LAYOUT_CONFIGS: Record<ViewportOrientation, LayoutHints> = {\n landscape: {\n primaryY: '35%',\n secondaryY: '55%',\n tertiaryY: '75%',\n titleScale: 1.0,\n bodyScale: 1.0,\n columnLeftX: '25%',\n columnRightX: '75%',\n columnTopY: '35%',\n columnBottomY: '65%',\n stackColumns: false,\n maxTextWidth: '80%',\n horizontalPadding: '10%',\n captionY: '85%',\n captionScale: 1.0,\n },\n portrait: {\n // Content positioned higher for thumb-reach zone on mobile\n primaryY: '25%',\n secondaryY: '42%',\n tertiaryY: '58%',\n // Titles scale down for narrower width; body text scales up to fill vertical space\n titleScale: 0.7,\n bodyScale: 1.5,\n // Stacked columns instead of side-by-side\n columnLeftX: '50%',\n columnRightX: '50%',\n columnTopY: '30%',\n columnBottomY: '55%',\n stackColumns: true,\n // Wider relative to viewport to use available space\n maxTextWidth: '90%',\n horizontalPadding: '5%',\n captionY: '75%',\n captionScale: 0.85,\n },\n square: {\n primaryY: '30%',\n secondaryY: '50%',\n tertiaryY: '70%',\n titleScale: 0.85,\n bodyScale: 0.9,\n columnLeftX: '25%',\n columnRightX: '75%',\n columnTopY: '35%',\n columnBottomY: '65%',\n stackColumns: false,\n maxTextWidth: '85%',\n horizontalPadding: '7.5%',\n captionY: '82%',\n captionScale: 0.9,\n },\n};\n\n/**\n * Get layout hints for a given orientation.\n */\nexport function getLayoutHints(orientation: ViewportOrientation): LayoutHints {\n return LAYOUT_CONFIGS[orientation];\n}\n\n/**\n * Calculate a scaled font size based on viewport and layout hints.\n *\n * @param basePx - Base font size in pixels (designed for 1920x1080)\n * @param viewport - Target viewport configuration\n * @param orientation - Viewport orientation\n * @param isTitle - Whether this is title text (uses titleScale) or body (uses bodyScale)\n */\nexport function scaledFontSize(\n basePx: number,\n viewport: ViewportConfig,\n orientation: ViewportOrientation,\n isTitle: boolean = false,\n): number {\n const fontScale = calculateFontScale(viewport);\n const layout = getLayoutHints(orientation);\n const typeScale = isTitle ? layout.titleScale : layout.bodyScale;\n return Math.round(basePx * fontScale * typeScale);\n}\n\n/**\n * Get position for two-column layout based on orientation.\n * Returns { left: {x, y}, right: {x, y} } positions.\n */\nexport function getTwoColumnPositions(orientation: ViewportOrientation): {\n left: { x: string; y: string };\n right: { x: string; y: string };\n} {\n const layout = getLayoutHints(orientation);\n\n if (layout.stackColumns) {\n // Portrait: stack vertically\n return {\n left: { x: '50%', y: layout.columnTopY },\n right: { x: '50%', y: layout.columnBottomY },\n };\n }\n\n // Landscape/square: side by side\n return {\n left: { x: layout.columnLeftX, y: '50%' },\n right: { x: layout.columnRightX, y: '50%' },\n };\n}\n\n/**\n * Get safe text bounds for a given orientation.\n * Returns margins to keep text away from edges.\n */\nexport function getSafeTextBounds(orientation: ViewportOrientation): {\n left: string;\n right: string;\n top: string;\n bottom: string;\n} {\n const layout = getLayoutHints(orientation);\n return {\n left: layout.horizontalPadding,\n right: layout.horizontalPadding,\n top: '10%',\n bottom: '10%',\n };\n}\n","/**\n * Block Templates Schema\n *\n * Defines a template system for AI-generated doc blocks. Instead of\n * specifying low-level layers, positions, and animations, AI can use\n * high-level templates like \"title\" or \"statHighlight\" with simple\n * content parameters.\n *\n * Templates are expanded into full Block structures at render time,\n * ensuring consistent styling and reducing AI generation errors.\n *\n * Template Types:\n * - title: Doc intro with title + subtitle\n * - sectionHeader: Colored section divider\n * - statHighlight: Big number/stat with description\n * - quote: Large centered quote\n * - factCard: Key fact with explanation\n * - twoColumn: Side-by-side comparison\n * - dateEvent: Timeline-style date + description\n * - imageWithCaption: Image with text overlay\n */\n\nimport type { Layer, Block, Transition, MapTileStyle, MapMarker } from './Doc.js';\nimport type { ViewportConfig, ViewportOrientation } from './Viewport.js';\nimport type { LayoutHints } from './LayoutStrategy.js';\nimport type { Theme } from './Theme.js';\nimport { VIEWPORT_PRESETS, getViewportOrientation, calculateFontScale } from './Viewport.js';\nimport { getLayoutHints, scaledFontSize as scaleFontSize } from './LayoutStrategy.js';\n\n/**\n * Name of a color scheme defined in the active theme's `colorSchemes` map.\n * Templates reference schemes by name (e.g. 'blue', 'green') and the theme\n * resolves them to actual colors at render time via `resolveColorScheme()`.\n */\nexport type ColorScheme = string;\n\n/**\n * Default font family for doc text.\n * PT Serif provides a classic, readable appearance for documentary-style content.\n * Used as a fallback in TextLayer when no font is specified.\n */\nexport const DEFAULT_DOC_FONT = 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif';\n\n/**\n * Default font family for titles.\n */\nexport const DEFAULT_TITLE_FONT = 'Georgia, \"Times New Roman\", serif';\n\n// ============================================\n// Accent Image System\n// ============================================\n\n/**\n * Position options for accent images on text-based blocks.\n * Accents are tasteful image additions that complement rather than overwhelm text.\n */\nexport type AccentPosition =\n | 'left-strip' // Vertical strip on left (25-30% width), text shifts right\n | 'right-strip' // Vertical strip on right (25-30% width), text shifts left\n | 'bottom-strip' // Horizontal strip at bottom (25-30% height), text shifts up\n | 'corner-inset'; // Small inset image in corner with vignette edge\n\n/**\n * Accent image configuration for text-based blocks.\n * When present, the template adjusts layout to accommodate the image tastefully.\n */\nexport interface AccentImage {\n /** Path to image file (relative to article media dir) */\n src: string;\n /** Alt text for accessibility */\n alt: string;\n /** Where to position the accent image */\n position: AccentPosition;\n /** Ambient motion effect (subtle Ken Burns) */\n ambientMotion?: 'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight';\n /** Photo credit / artist name */\n credit?: string;\n /** License identifier (e.g., 'CC BY-SA 4.0') */\n license?: string;\n}\n\n// ============================================\n// Template Input Types\n// ============================================\n\n/**\n * Base properties shared by all template blocks.\n */\ninterface BaseTemplateBlock {\n /** Unique block ID */\n id: string;\n /** Block duration in seconds */\n duration: number;\n /** Which audio segment this block belongs to */\n audioSegment: number;\n /** Entry transition */\n transition?: Transition;\n /** Show doc's bottom layers (default: true) */\n useBottomLayer?: boolean;\n /** Show doc's top layers (default: true) */\n useTopLayer?: boolean;\n /**\n * Start time within the audio segment when this content is spoken.\n * Used to sync the block appearance with the narration.\n * If not provided, blocks are distributed evenly across the segment.\n */\n sourceStartTime?: number;\n /**\n * Duration of the spoken content this block represents.\n * Used with sourceStartTime to precisely position the block.\n */\n sourceDuration?: number;\n}\n\n/**\n * Title block - doc intro with large title and subtitle.\n */\nexport interface TitleBlockInput extends BaseTemplateBlock {\n template: 'title';\n /** Main title text */\n title: string;\n /** Subtitle or tagline (supports \\n for line breaks) */\n subtitle?: string;\n /** Background color (defaults to theme primary) */\n backgroundColor?: string;\n}\n\n/**\n * Section header - section title card with optional background image.\n * Displays the section title prominently, optionally over an image.\n */\nexport interface SectionHeaderInput extends BaseTemplateBlock {\n template: 'sectionHeader';\n /** Section title */\n title: string;\n /** Color scheme for the section (used for fallback background) */\n colorScheme?: ColorScheme;\n /** Optional background image path */\n imageSrc?: string;\n /** Alt text for background image */\n imageAlt?: string;\n /** Ambient motion for background image */\n ambientMotion?: 'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight';\n}\n\n/**\n * Stat highlight - big number with description and optional detail.\n */\nexport interface StatHighlightInput extends BaseTemplateBlock {\n template: 'statHighlight';\n /** The statistic (e.g., \"89%\", \"2x\", \"7 miles\") */\n stat: string;\n /** Description of what the stat means */\n description: string;\n /** Additional detail or context */\n detail?: string;\n /** Color scheme for the stat */\n colorScheme?: ColorScheme;\n /** Optional accent image to complement the text */\n accentImage?: AccentImage;\n}\n\n/**\n * Quote block - large centered quote text.\n */\nexport interface QuoteBlockInput extends BaseTemplateBlock {\n template: 'quote';\n /** The quote text (supports \\n for line breaks) */\n quote: string;\n /** Attribution (author, source) */\n attribution?: string;\n /** Optional accent image to complement the text */\n accentImage?: AccentImage;\n}\n\n/**\n * Fact card - key fact with explanation.\n */\nexport interface FactCardInput extends BaseTemplateBlock {\n template: 'factCard';\n /** The main fact or statement */\n fact: string;\n /** Explanation or context */\n explanation: string;\n /** Optional source citation */\n source?: string;\n /** Optional accent image to complement the text */\n accentImage?: AccentImage;\n}\n\n/**\n * Two column - side-by-side comparison.\n */\nexport interface TwoColumnInput extends BaseTemplateBlock {\n template: 'twoColumn';\n /** Left column content */\n left: {\n label: string;\n sublabel?: string;\n };\n /** Right column content */\n right: {\n label: string;\n sublabel?: string;\n };\n /** Optional header above columns */\n header?: string;\n /** Color schemes for left and right */\n leftColor?: ColorScheme;\n rightColor?: ColorScheme;\n}\n\n/**\n * Date event - timeline-style date with description.\n */\nexport interface DateEventInput extends BaseTemplateBlock {\n template: 'dateEvent';\n /** The date (e.g., \"July 14, 1974\") */\n date: string;\n /** Description of what happened (supports \\n) */\n description: string;\n /** Optional footer text */\n footer?: string;\n /** Mood: 'neutral', 'somber', 'celebratory' */\n mood?: 'neutral' | 'somber' | 'celebratory';\n /** Optional accent image to complement the text */\n accentImage?: AccentImage;\n}\n\n/**\n * Image with caption - background image with text overlay.\n */\nexport interface ImageWithCaptionInput extends BaseTemplateBlock {\n template: 'imageWithCaption';\n /** Path to image file */\n imageSrc: string;\n /** Alt text for accessibility */\n imageAlt: string;\n /** Caption text */\n caption?: string;\n /** Caption position */\n captionPosition?: 'bottom' | 'top' | 'center';\n /** Ambient motion effect: slow zoom or pan for visual interest */\n ambientMotion?: 'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight';\n /** When true, style caption as a title (larger, centered, prominent) */\n isTitle?: boolean;\n /** Optional subtitle shown below the title (only when isTitle is true) */\n subtitle?: string;\n /** Photo credit / artist name */\n imageCredit?: string;\n /** License identifier (e.g., 'CC BY-SA 4.0') */\n imageLicense?: string;\n}\n\n/**\n * Shared fields for left/right feature blocks. A \"feature\" pairs an\n * image on one side of the block with a title and body paragraph on\n * the other — a common editorial layout for product highlights,\n * profile callouts, or section intros.\n */\ninterface FeatureInputBase extends BaseTemplateBlock {\n /** Path to the feature image. */\n imageSrc: string;\n /** Alt text for accessibility. */\n imageAlt?: string;\n /**\n * Explicit display width of the image, in pixels (typically pulled\n * from a `<img width>` attribute when the WYSIWYG editor resized it).\n * When set, the renderer treats the image as a sized asset and\n * centers it inside its half with padding instead of stretching it\n * to fill the cell.\n */\n imageWidth?: number;\n /** Explicit display height of the image, in pixels. */\n imageHeight?: number;\n /** Heading / title text shown next to the image. */\n title?: string;\n /** Body text shown below the title. */\n body?: string;\n}\n\n/**\n * Left feature — image on the left, title + body stacked on the right.\n */\nexport interface LeftFeatureInput extends FeatureInputBase {\n template: 'leftFeature';\n}\n\n/**\n * Right feature — image on the right, title + body stacked on the left.\n */\nexport interface RightFeatureInput extends FeatureInputBase {\n template: 'rightFeature';\n}\n\n/**\n * Map block - geographic map showing article location.\n *\n * Displays a map centered on given coordinates with optional title,\n * caption, and markers. Great for establishing geographic context.\n * See docs/MAP_TILES.md for available tile styles and attribution.\n */\nexport interface MapBlockInput extends BaseTemplateBlock {\n template: 'map';\n /** Map center coordinates */\n center: {\n lat: number;\n lng: number;\n };\n /** Zoom level (4-16, typically 8-12 for regional context) */\n zoom: number;\n /** Map tile style (default: 'terrain') */\n mapStyle?: MapTileStyle;\n /** Optional title overlay at top */\n title?: string;\n /** Optional caption at bottom */\n caption?: string;\n /** Optional markers to show on map */\n markers?: MapMarker[];\n /** Ambient motion effect: slow zoom or pan for visual interest */\n ambientMotion?: 'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight';\n /** Pre-rendered static image path (set by prerender-maps command) */\n staticSrc?: string;\n}\n\n/**\n * Full-bleed quote - dramatic short text filling the viewport.\n * Like a movie title card. For short, punchy sentences < 60 chars.\n */\nexport interface FullBleedQuoteInput extends BaseTemplateBlock {\n template: 'fullBleedQuote';\n /** Short dramatic text (< 60 chars recommended) */\n text: string;\n /** Color scheme for text tint */\n colorScheme?: ColorScheme;\n}\n\n/**\n * List block - 3-5 items stacked vertically with subtle numbering.\n * Good for enumerations like \"things to see\" or \"key features\".\n */\nexport interface ListBlockInput extends BaseTemplateBlock {\n template: 'list';\n /** List items (3-5 recommended) */\n items: string[];\n /** Optional header above the list */\n title?: string;\n /** Color scheme for numbering accents */\n colorScheme?: ColorScheme;\n /** Optional accent image */\n accentImage?: AccentImage;\n}\n\n/**\n * Photo grid - 2-4 images in a tiled layout.\n * Used when multiple images are available for visual variety.\n */\nexport interface PhotoGridInput extends BaseTemplateBlock {\n template: 'photoGrid';\n /** Images to display (2-4) */\n images: { src: string; alt: string; credit?: string; license?: string }[];\n /** Optional caption below the grid */\n caption?: string;\n /** Ambient motion effect for the largest image */\n ambientMotion?: 'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight';\n}\n\n/**\n * Definition card - dictionary-style term with definition.\n * Large term at top, definition below, optional origin note.\n */\nexport interface DefinitionCardInput extends BaseTemplateBlock {\n template: 'definitionCard';\n /** The term being defined */\n term: string;\n /** The definition text */\n definition: string;\n /** Optional etymology or origin note */\n origin?: string;\n /** Color scheme for term accent */\n colorScheme?: ColorScheme;\n /** Optional accent image */\n accentImage?: AccentImage;\n}\n\n/**\n * Comparison bar - two horizontal bars showing relative numeric values.\n * Good for side-by-side numeric comparisons with visual weight.\n */\nexport interface ComparisonBarInput extends BaseTemplateBlock {\n template: 'comparisonBar';\n /** Left bar label */\n leftLabel: string;\n /** Left bar numeric value */\n leftValue: number;\n /** Right bar label */\n rightLabel: string;\n /** Right bar numeric value */\n rightValue: number;\n /** Unit label (e.g., \"km\", \"people\") */\n unit?: string;\n /** Color scheme */\n colorScheme?: ColorScheme;\n}\n\n/**\n * Pull quote - quote text over a full-bleed background image with dark overlay.\n * Cinematic alternative to quoteBlock when a high-quality image is available.\n */\nexport interface PullQuoteInput extends BaseTemplateBlock {\n template: 'pullQuote';\n /** Quote text */\n text: string;\n /** Optional attribution */\n attribution?: string;\n /** Background image (fills entire viewport) */\n backgroundImage: { src: string; alt: string; credit?: string; license?: string };\n /** Ambient motion for background image */\n ambientMotion?: 'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight';\n}\n\n/**\n * Video with caption - background video clip with text overlay.\n * Plays a short clip from a source video, always muted (narration is the audio track).\n * Mirrors ImageWithCaptionInput but with video-specific fields.\n */\nexport interface VideoWithCaptionInput extends BaseTemplateBlock {\n template: 'videoWithCaption';\n /** Path to video file */\n videoSrc: string;\n /** Path to poster frame (shown before video loads) */\n posterSrc?: string;\n /** Alt text for accessibility */\n videoAlt: string;\n /** Start time within source video (seconds) */\n clipStart: number;\n /** End time within source video (seconds) */\n clipEnd: number;\n /** Source video total duration (for validation) */\n sourceDuration?: number;\n /** Caption text overlay */\n caption?: string;\n /** Caption position */\n captionPosition?: 'bottom' | 'top' | 'center';\n /** Video credit / artist name */\n videoCredit?: string;\n /** License identifier */\n videoLicense?: string;\n}\n\n/**\n * Video pull quote - quote text over a video clip background with dark overlay.\n * Cinematic alternative to pullQuote when a video clip is available.\n */\nexport interface VideoPullQuoteInput extends BaseTemplateBlock {\n template: 'videoPullQuote';\n /** Quote text */\n text: string;\n /** Optional attribution */\n attribution?: string;\n /** Background video clip */\n backgroundVideo: {\n src: string;\n posterSrc?: string;\n alt: string;\n clipStart: number;\n clipEnd: number;\n credit?: string;\n license?: string;\n };\n}\n\n/**\n * Data table - renders a themed table with headers and rows.\n * Ideal for structured data, comparisons, and reference information.\n */\nexport interface DataTableInput extends BaseTemplateBlock {\n template: 'dataTable';\n /** Optional title displayed above the table */\n title?: string;\n /** Header cell values */\n headers: string[];\n /** Data rows (array of cell value arrays) */\n rows: string[][];\n /** Per-column alignment */\n align?: (('left' | 'right' | 'center') | null)[];\n /** Color scheme for the table header */\n colorScheme?: ColorScheme;\n}\n\n/**\n * Union of all template block types.\n */\nexport type TemplateBlock =\n | TitleBlockInput\n | SectionHeaderInput\n | StatHighlightInput\n | QuoteBlockInput\n | FactCardInput\n | TwoColumnInput\n | DateEventInput\n | ImageWithCaptionInput\n | LeftFeatureInput\n | RightFeatureInput\n | MapBlockInput\n | FullBleedQuoteInput\n | ListBlockInput\n | PhotoGridInput\n | DefinitionCardInput\n | ComparisonBarInput\n | PullQuoteInput\n | VideoWithCaptionInput\n | VideoPullQuoteInput\n | DataTableInput;\n\n/**\n * A block can be either a raw Block or a TemplateBlock.\n */\nexport type DocBlock = Block | TemplateBlock;\n\n/**\n * Check if a block is a template block.\n */\nexport function isTemplateBlock(block: DocBlock): block is TemplateBlock {\n return 'template' in block && typeof block.template === 'string';\n}\n\n// ============================================\n// Template Function Type\n// ============================================\n\n/**\n * Template context passed to template functions.\n * Includes viewport information for multi-aspect ratio support.\n */\nexport interface TemplateContext {\n /** Full theme (colors, typography, style, renderStyle, colorSchemes) */\n theme: Theme;\n /** Block index in the doc */\n blockIndex: number;\n /** Total number of blocks */\n totalBlocks: number;\n /** Target viewport configuration */\n viewport: ViewportConfig;\n /** Computed font scale factor for this viewport */\n fontScale: number;\n /** Viewport orientation (landscape, portrait, square) */\n orientation: ViewportOrientation;\n /** Layout hints for this orientation */\n layout: LayoutHints;\n}\n\n/**\n * Create a template context with viewport-derived values.\n */\nexport function createTemplateContext(\n theme: Theme,\n blockIndex: number,\n totalBlocks: number,\n viewport: ViewportConfig = VIEWPORT_PRESETS.landscape,\n): TemplateContext {\n const orientation = getViewportOrientation(viewport);\n return {\n theme,\n blockIndex,\n totalBlocks,\n viewport,\n fontScale: calculateFontScale(viewport),\n orientation,\n layout: getLayoutHints(orientation),\n };\n}\n\n/**\n * Calculate a scaled font size for the given context.\n * Use this in templates to ensure text scales appropriately.\n *\n * @param basePx - Base font size in pixels (designed for 1920x1080)\n * @param context - Template context with viewport info\n * @param isTitle - Whether this is title text (larger scale) or body text\n */\nexport function scaledFontSize(\n basePx: number,\n context: TemplateContext,\n isTitle: boolean = false,\n): number {\n return scaleFontSize(basePx, context.viewport, context.orientation, isTitle);\n}\n\n/**\n * Template function signature.\n * Takes template input and returns layers array.\n */\nexport type TemplateFunction<T extends TemplateBlock> = (\n input: T,\n context: TemplateContext,\n) => Layer[];\n\n/**\n * Registry of all template functions.\n */\nexport type TemplateRegistry = {\n [K in TemplateBlock['template']]: TemplateFunction<Extract<TemplateBlock, { template: K }>>;\n};\n\n// ============================================\n// Persistent Layer System\n// ============================================\n\n/**\n * Configuration for persistent doc-wide layers.\n * Bottom layers render behind all block content, top layers on top.\n */\nexport interface PersistentLayerConfig {\n /** Layers rendered behind all block content */\n bottomLayers?: PersistentLayer[];\n /** Layers rendered on top of all block content */\n topLayers?: PersistentLayer[];\n}\n\n/**\n * A persistent layer - either a template or raw Layer.\n */\nexport type PersistentLayer = PersistentLayerTemplate | Layer;\n\n/**\n * Check if a persistent layer is a template.\n */\nexport function isPersistentLayerTemplate(\n layer: PersistentLayer,\n): layer is PersistentLayerTemplate {\n return 'template' in layer && typeof layer.template === 'string';\n}\n\n/**\n * Template-based persistent layer for easy configuration.\n */\nexport interface PersistentLayerTemplate {\n template: PersistentLayerTemplateType;\n config: PersistentLayerTemplateConfig;\n}\n\n/**\n * Available persistent layer template types.\n */\nexport type PersistentLayerTemplateType =\n | 'solidBackground' // Solid color fill\n | 'gradientBackground' // CSS gradient or preset\n | 'imageBackground' // Blurred/faded hero image\n | 'patternBackground' // Subtle pattern (dots, grid)\n | 'titleCaption' // Article title in corner\n | 'cornerBranding' // Logo or text badge\n | 'progressIndicator'; // Bar/dots showing position\n\n/**\n * Union of all persistent layer template configs.\n */\nexport type PersistentLayerTemplateConfig =\n | SolidBackgroundConfig\n | GradientBackgroundConfig\n | ImageBackgroundConfig\n | PatternBackgroundConfig\n | TitleCaptionConfig\n | CornerBrandingConfig\n | ProgressIndicatorConfig;\n\n// ============================================\n// Background Layer Configs\n// ============================================\n\n/**\n * Solid color background.\n */\nexport interface SolidBackgroundConfig {\n type: 'solidBackground';\n /** CSS color value */\n color: string;\n}\n\n/**\n * Gradient background (CSS gradient or preset).\n */\nexport interface GradientBackgroundConfig {\n type: 'gradientBackground';\n /** Custom CSS gradient string */\n gradient?: string;\n /** Preset gradient name */\n preset?: 'dark-vignette' | 'radial-dark' | 'warm-sunset' | 'cool-blue' | 'earth-tones';\n}\n\n/**\n * Image background (blurred/faded hero image).\n */\nexport interface ImageBackgroundConfig {\n type: 'imageBackground';\n /** Path to image file */\n src: string;\n /** Blur radius in pixels (0-20) */\n blur?: number;\n /** Opacity (0-1) */\n opacity?: number;\n /** Ambient motion effect */\n ambientMotion?: 'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight';\n}\n\n/**\n * Pattern background (subtle repeating pattern).\n */\nexport interface PatternBackgroundConfig {\n type: 'patternBackground';\n /** Pattern type */\n pattern: 'dots' | 'grid' | 'diagonal' | 'noise';\n /** Pattern color */\n color?: string;\n /** Pattern opacity (0-1) */\n opacity?: number;\n /** Pattern scale multiplier */\n scale?: number;\n}\n\n// ============================================\n// Overlay Layer Configs\n// ============================================\n\n/**\n * Title caption overlay (article title in corner).\n */\nexport interface TitleCaptionConfig {\n type: 'titleCaption';\n /** Title text */\n title: string;\n /** Subtitle text (e.g., short URL like \"qual..la/slug\") */\n subtitle?: string;\n /** Position on screen */\n position: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';\n /** Font size in pixels (default: 18) */\n fontSize?: number;\n /** Show thumbnail alongside title */\n showThumbnail?: boolean;\n /** Thumbnail image path */\n thumbnailSrc?: string;\n}\n\n/**\n * Corner branding overlay (logo or text badge).\n */\nexport interface CornerBrandingConfig {\n type: 'cornerBranding';\n /** Text content or image path */\n content: string;\n /** Position on screen */\n position: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';\n /** Whether content is an image path (vs text) */\n isImage?: boolean;\n}\n\n/**\n * Progress indicator overlay (bar or dots showing position).\n */\nexport interface ProgressIndicatorConfig {\n type: 'progressIndicator';\n /** Indicator style */\n style: 'bar' | 'dots' | 'fraction';\n /** Position on screen */\n position: 'bottom' | 'top';\n /** Indicator color */\n color?: string;\n}\n"],"mappings":"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","names":["scaledFontSize"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/spatial/Haversine.ts","../src/spatial/Geohash.ts"],"sourcesContent":["/**\n * Haversine Distance Calculation\n *\n * Provides accurate distance calculation between two geographic coordinates\n * using the Haversine formula, which accounts for Earth's curvature.\n */\n\nimport type { Coordinates } from '../schemas/Types.js';\n\n/**\n * Calculate distance between two coordinates using Haversine formula.\n *\n * @param from Start coordinates\n * @param to End coordinates\n * @returns Distance in kilometers\n */\nexport function haversineDistance(from: Coordinates, to: Coordinates): number {\n const R = 6371; // Earth's radius in kilometers\n\n const dLat = toRadians(to.lat - from.lat);\n const dLng = toRadians(to.lng - from.lng);\n\n const a =\n Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n Math.cos(toRadians(from.lat)) *\n Math.cos(toRadians(to.lat)) *\n Math.sin(dLng / 2) *\n Math.sin(dLng / 2);\n\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));\n\n return R * c;\n}\n\n/**\n * Calculate bearing from one coordinate to another.\n *\n * @param from Start coordinates\n * @param to End coordinates\n * @returns Bearing in degrees (0-360, where 0 = north, 90 = east)\n */\nexport function calculateBearing(from: Coordinates, to: Coordinates): number {\n const dLng = toRadians(to.lng - from.lng);\n const lat1 = toRadians(from.lat);\n const lat2 = toRadians(to.lat);\n\n const x = Math.sin(dLng) * Math.cos(lat2);\n const y = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLng);\n\n const bearing = Math.atan2(x, y);\n return ((bearing * 180) / Math.PI + 360) % 360;\n}\n\n/**\n * Convert degrees to radians.\n */\nfunction toRadians(degrees: number): number {\n return (degrees * Math.PI) / 180;\n}\n","/**\n * Geohash Utilities\n *\n * Provides geohash encoding/decoding and spatial utilities using the standard\n * ngeohash library for core operations, plus custom utilities for overlap checking\n * and distance calculation.\n *\n * Geohashes are a hierarchical spatial indexing system that divides the world\n * into a grid of cells. Each additional character narrows the area by ~1/32.\n *\n * Precision guide:\n * - 4 chars: ~39km x 19km (used for tile indexing)\n * - 5 chars: ~5km x 5km\n * - 6 chars: ~1.2km x 0.6km\n */\n\nimport ngeohash from 'ngeohash';\n\n/**\n * Encode latitude/longitude to a geohash string.\n * Uses the standard ngeohash library.\n */\nexport function encodeGeohash(lat: number, lng: number, precision = 9): string {\n return ngeohash.encode(lat, lng, precision);\n}\n\n/**\n * Decode a geohash to latitude/longitude center with error bounds.\n * Uses the standard ngeohash library.\n */\nexport function decodeGeohash(hash: string): {\n lat: number;\n lng: number;\n latErr: number;\n lngErr: number;\n} {\n const result = ngeohash.decode(hash);\n return {\n lat: result.latitude,\n lng: result.longitude,\n latErr: result.error.latitude,\n lngErr: result.error.longitude,\n };\n}\n\n/**\n * Get the 8 neighboring geohash cells.\n * Returns up to 8 neighbors (fewer at poles or antimeridian).\n * Uses the standard ngeohash library.\n */\nexport function getNeighbors(hash: string): string[] {\n return ngeohash.neighbors(hash);\n}\n\n/**\n * Get a 3x3 grid of geohash4 cells (center + 8 neighbors).\n * Used for landing bonus expansions in Fly mode.\n *\n * @param geohash4 - Center geohash4 cell\n * @returns Array of 9 geohash4 cells (center first, then neighbors)\n *\n * @example\n * getGeohash4Neighbors('c23n')\n * // => ['c23n', 'c23p', 'c23q', 'c23j', 'c23m', 'c23k', 'c23h', 'c23e', 'c23s']\n */\nexport function getGeohash4Neighbors(geohash4: string): string[] {\n if (geohash4.length !== 4) {\n throw new Error(`getGeohash4Neighbors requires 4-char geohash, got: ${geohash4}`);\n }\n const neighbors = getNeighbors(geohash4);\n return [geohash4, ...neighbors];\n}\n\n/**\n * Get the prefix of a geohash at a given precision.\n * Simple helper for extracting geohash prefixes for directory organization.\n */\nexport function getGeohashPrefix(geohash: string, precision: number): string {\n return geohash.slice(0, precision);\n}\n\n/**\n * Convert a geohash prefix to a hierarchical path.\n *\n * Examples:\n * \"9mud\" -> \"9/m/u/d\"\n * \"9q8y\" -> \"9/q/8/y\"\n * \"c24k\" -> \"c/2/4/k\"\n *\n * This is used for organizing files in hierarchical directories to avoid\n * thousands of folders in a single directory, which causes filesystem\n * performance issues.\n */\nexport function geohashToHierarchicalPath(geohash4: string): string {\n if (geohash4.length !== 4) {\n throw new Error(`geohashToHierarchicalPath requires 4-char geohash, got: ${geohash4}`);\n }\n const [c1, c2, c3, c4] = geohash4.split('');\n return `${c1}/${c2}/${c3}/${c4}`;\n}\n\n/**\n * Compute all geohash cells along the path between two geohash cells.\n * Interpolates lat/lng points between the centers of `from` and `to`,\n * encoding each to a geohash at the given precision, and returns the\n * deduplicated list of intermediate cells (excluding `from` and `to`).\n */\nexport function getGeohashPath(from: string, to: string, precision = 4): string[] {\n if (from === to) return [];\n\n const fromCenter = decodeGeohash(from);\n const toCenter = decodeGeohash(to);\n\n // Compute approximate distance to determine step count\n const dLat = Math.abs(toCenter.lat - fromCenter.lat);\n const dLng = Math.abs(toCenter.lng - fromCenter.lng);\n // Rough km: 1 degree lat ≈ 111km, 1 degree lng ≈ 111km * cos(midLat)\n const midLatRad = ((fromCenter.lat + toCenter.lat) / 2) * (Math.PI / 180);\n const approxKm = Math.sqrt((dLat * 111) ** 2 + (dLng * 111 * Math.cos(midLatRad)) ** 2);\n\n // Step every ~15km to avoid skipping any geohash4 cell (~39x19km)\n const steps = Math.max(2, Math.ceil(approxKm / 15));\n\n const seen = new Set<string>();\n seen.add(from);\n seen.add(to);\n\n const path: string[] = [];\n for (let i = 1; i < steps; i++) {\n const t = i / steps;\n const lat = fromCenter.lat + t * (toCenter.lat - fromCenter.lat);\n const lng = fromCenter.lng + t * (toCenter.lng - fromCenter.lng);\n const hash = encodeGeohash(lat, lng, precision);\n if (!seen.has(hash)) {\n seen.add(hash);\n path.push(hash);\n }\n }\n\n return path;\n}\n\n/**\n * Check if a geohash cell overlaps with a bounding box.\n * Custom implementation (not available in ngeohash).\n */\nexport function geohashOverlapsBounds(\n hash: string,\n bounds: { north: number; south: number; east: number; west: number },\n): boolean {\n const { lat, lng, latErr, lngErr } = decodeGeohash(hash);\n\n const hashNorth = lat + latErr;\n const hashSouth = lat - latErr;\n const hashEast = lng + lngErr;\n const hashWest = lng - lngErr;\n\n return !(\n hashNorth < bounds.south ||\n hashSouth > bounds.north ||\n hashEast < bounds.west ||\n hashWest > bounds.east\n );\n}\n\n// haversineDistance is now in shared/spatial/Haversine.ts (canonical location).\n// Re-export for backwards compatibility with existing imports.\nexport { haversineDistance } from './Haversine.js';\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/schemas/Theme.ts","../src/schemas/colorUtils.ts","../src/schemas/themeValidator.ts","../src/schemas/themes/standard.json","../src/schemas/themes/standard-dark.json","../src/schemas/themes/documentary.json","../src/schemas/themes/minimalist.json","../src/schemas/themes/bold.json","../src/schemas/themes/morning-light.json","../src/schemas/themes/tech-dark.json","../src/schemas/themes/magazine.json","../src/schemas/themes/cinematic.json","../src/schemas/themes/warm-earth.json","../src/schemas/themes/gezellig.json","../src/schemas/themes/index.ts","../src/schemas/themeLibrary.ts","../src/schemas/fontStacks.ts"],"sourcesContent":["/**\n * Theme System\n *\n * A Theme bundles color palette, typography, visual style, render-style\n * algorithm, and per-block color schemes into one JSON-serializable object.\n *\n * Built-in themes and customizer-authored themes share this exact schema.\n * Customizer-authored themes additionally specify `seedColors` so the few\n * fields the user picked can be re-edited later; built-ins typically omit\n * `seedColors` and ship with explicit `colors` already filled in.\n *\n * Design principles:\n * - Fully JSON-serializable. No functions; no raw CSS font strings.\n * - Font families are structured `FontFamily` references resolved by\n * `resolveFontFamily()` at render time.\n * - Doc carries an optional `themeId`; resolution happens at render time\n * via `resolveTheme(id)`.\n * - `createTheme` deep-merges a base theme with partial overrides;\n * `compileTheme` fills in defaults and derives missing color slots from\n * `seedColors`; both produce a complete `Theme`.\n */\n\nimport type { LayoutHints } from './LayoutStrategy.js';\nimport type { AnimationType, TransitionType } from './Doc.js';\nimport type { PersistentLayerConfig } from './BlockTemplates.js';\n\n// ============================================\n// Schema version\n// ============================================\n\n/** Current Theme schema version. Bump on breaking changes; loader migrates. */\nexport const THEME_SCHEMA_VERSION = '1' as const;\nexport type ThemeSchemaVersion = typeof THEME_SCHEMA_VERSION;\n\n// ============================================\n// Color Palette\n// ============================================\n\n/**\n * Core color palette for a theme. Every color is a `#rrggbb` hex string.\n */\nexport interface ThemeColorPalette {\n /** Primary accent color */\n primary: string;\n /** Secondary accent color */\n secondary: string;\n /** Background color (typically dark) */\n background: string;\n /** Lighter background for contrast panels */\n backgroundLight: string;\n /** Main text color */\n text: string;\n /** Muted/secondary text color */\n textMuted: string;\n /** Highlight/emphasis color */\n highlight: string;\n /** Warning/alert color */\n warning: string;\n}\n\n/**\n * A named color scheme used by templates for per-block color variation\n * (e.g., statHighlight or sectionHeader).\n */\nexport interface ThemeColorScheme {\n /** Background fill */\n bg: string;\n /** Primary text tint */\n text: string;\n /** Accent / secondary tint */\n accent: string;\n}\n\n/**\n * Optional authoring metadata. When present and `colors` is partial,\n * `compileTheme` derives missing color slots from these seeds via OKLCh\n * lightening / darkening. Round-trips a customizer-authored theme back\n * into editable form.\n */\nexport interface ThemeSeedColors {\n primary: string;\n secondary?: string;\n accent?: string;\n background?: string;\n text?: string;\n}\n\n// ============================================\n// Typography\n// ============================================\n\n/** Categorical bucket for a font family — drives default fallback. */\nexport type FontFamilyKind = 'sans' | 'serif' | 'mono' | 'display';\n\n/**\n * Structured reference to a font family. Either a curated stack id (looked\n * up in `AVAILABLE_FONT_STACKS`) or a custom user-supplied name with a\n * structured fallback bucket. Themes never carry raw CSS family strings.\n */\nexport type FontFamily =\n | { stackId: string }\n | {\n custom: {\n name: string;\n fallback: 'serif' | 'sans-serif' | 'monospace' | 'system-ui';\n };\n };\n\n/**\n * Typography settings for a theme.\n */\nexport interface ThemeTypography {\n /** Font family for body / description text */\n bodyFont: FontFamily;\n /** Font family for titles and headings */\n titleFont: FontFamily;\n /** Font family for code / monospaced text (optional) */\n monoFont?: FontFamily;\n /** Multiplier applied to LayoutHints.titleScale (default 1.0) */\n titleScale?: number;\n /** Multiplier applied to LayoutHints.bodyScale (default 1.0) */\n bodyScale?: number;\n /** Default body line height (default 1.4) */\n lineHeight?: number;\n /** Default title line height */\n titleLineHeight?: number;\n /** Default title font weight */\n titleWeight?: 'normal' | 'bold';\n}\n\n// ============================================\n// Visual Style\n// ============================================\n\n/**\n * Global visual-style knobs that templates consult.\n */\nexport interface ThemeStyle {\n /** Default border radius for cards / shapes (px) */\n borderRadius?: number;\n /** Whether templates should default to text shadows */\n textShadow?: boolean;\n /** Darkness of overlay on image-backed blocks (0–1) */\n overlayOpacity?: number;\n /** Multiplier on all animation durations (1.0 = normal, <1 faster, >1 slower) */\n animationSpeed?: number;\n /** Default horizontal padding for text (percentage string, e.g. \"5%\") */\n blockPadding?: string;\n}\n\n// ============================================\n// Render Style\n// ============================================\n\n/**\n * Render-style algorithm preset. Controls layout tweaks, default animations,\n * transitions, and per-template behavioral hints.\n */\nexport interface RenderStyle {\n /** Identifier for this algorithmic approach (e.g. \"documentary\", \"magazine\") */\n name: string;\n /** Partial overrides merged onto the orientation-based LayoutHints */\n layoutOverrides?: Partial<LayoutHints>;\n /** Default entrance animation for text layers */\n defaultTextAnimation?: AnimationType;\n /** Default animation for background / image layers */\n defaultImageAnimation?: AnimationType;\n /** Whether to apply Ken Burns ambient motion to images by default */\n ambientMotion?: boolean;\n /** Default block-to-block transition */\n defaultTransition?: { type: TransitionType; duration?: number };\n /**\n * Per-template behavioral hints. Keys are template names, values are\n * string/number/boolean maps that templates can read to vary their output.\n * Templates that consume hints publish a `hintSchema` export documenting\n * the keys they recognise.\n */\n templateHints?: Record<string, Record<string, string | number | boolean>>;\n}\n\n// ============================================\n// Theme\n// ============================================\n\n/**\n * A complete, JSON-serializable theme definition. Built-in and customizer-\n * authored themes share this exact shape.\n */\nexport interface Theme {\n /** Schema version. Always '1' for now. */\n schemaVersion: ThemeSchemaVersion;\n /** Unique identifier (e.g. \"documentary\") */\n id: string;\n /** Human-readable display name */\n name: string;\n /** Short description for theme pickers */\n description?: string;\n /** Optional authoring seeds (customizer fills these; built-ins typically omit) */\n seedColors?: ThemeSeedColors;\n /** Color palette */\n colors: ThemeColorPalette;\n /** Typography settings */\n typography: ThemeTypography;\n /** Global visual-style knobs */\n style: ThemeStyle;\n /** Algorithmic render-style preset */\n renderStyle: RenderStyle;\n /**\n * Named color schemes for per-block color variation.\n * Templates reference these by name (e.g. \"blue\", \"warm\").\n */\n colorSchemes: Record<string, ThemeColorScheme>;\n /** Optional persistent layers baked into the theme */\n persistentLayers?: PersistentLayerConfig;\n}\n\n// ============================================\n// Deep-Partial helper type\n// ============================================\n\n/**\n * Recursively makes every property optional.\n */\nexport type DeepPartial<T> = {\n [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];\n};\n\n// ============================================\n// Helpers\n// ============================================\n\n/**\n * Deep-merge `source` into `target`, returning a new object.\n * Arrays are replaced wholesale (not concatenated).\n */\nfunction deepMerge<T extends Record<string, unknown>>(target: T, source: DeepPartial<T>): T {\n const result = { ...target } as Record<string, unknown>;\n for (const key of Object.keys(source)) {\n const srcVal = (source as Record<string, unknown>)[key];\n const tgtVal = (target as Record<string, unknown>)[key];\n if (\n srcVal !== null &&\n srcVal !== undefined &&\n typeof srcVal === 'object' &&\n !Array.isArray(srcVal) &&\n tgtVal !== null &&\n tgtVal !== undefined &&\n typeof tgtVal === 'object' &&\n !Array.isArray(tgtVal)\n ) {\n result[key] = deepMerge(\n tgtVal as Record<string, unknown>,\n srcVal as DeepPartial<Record<string, unknown>>,\n );\n } else if (srcVal !== undefined) {\n result[key] = srcVal;\n }\n }\n return result as T;\n}\n\n/**\n * Create a new theme by deep-merging overrides onto a base theme.\n * The returned theme gets its own `id` if one is provided in overrides,\n * otherwise keeps the base theme's `id` suffixed with \"-custom\".\n */\nexport function createTheme(base: Theme, overrides: DeepPartial<Theme>): Theme {\n const merged = deepMerge(\n base as unknown as Record<string, unknown>,\n overrides as DeepPartial<Record<string, unknown>>,\n ) as unknown as Theme;\n if (!overrides.id && merged.id === base.id) {\n merged.id = `${base.id}-custom`;\n }\n if (!merged.schemaVersion) merged.schemaVersion = THEME_SCHEMA_VERSION;\n return merged;\n}\n\n// ============================================\n// Surface Schemes — orthogonal to Theme\n// ============================================\n\n/**\n * A Surface Scheme is the light/dark axis, orthogonal to the editorial\n * identity of a Theme. A Theme chooses voice (serif vs sans, muted vs\n * bold, documentary vs magazine); a SurfaceScheme chooses what the paper\n * looks like. Any theme can render on either surface.\n */\nexport interface SurfaceScheme {\n /** Identifier — 'light', 'dark', or a custom id. */\n id: string;\n background: string;\n backgroundLight: string;\n text: string;\n textMuted: string;\n}\n\n/** Near-white paper with dark text — standard light mode. */\nexport const LIGHT_SURFACE: SurfaceScheme = {\n id: 'light',\n background: '#ffffff',\n backgroundLight: '#f5f5f5',\n text: '#1a1a1a',\n textMuted: '#666666',\n};\n\n/** Dark charcoal paper with light text — standard dark mode. */\nexport const DARK_SURFACE: SurfaceScheme = {\n id: 'dark',\n background: '#1a202c',\n backgroundLight: '#2d3748',\n text: '#f0f0f0',\n textMuted: '#a0aec0',\n};\n\n/**\n * Overlay a SurfaceScheme's surface colors onto a Theme's palette,\n * leaving everything else (primary, highlight, warning, typography,\n * style, renderStyle, colorSchemes) untouched.\n */\nexport function applySurface(theme: Theme, surface: SurfaceScheme): Theme {\n return {\n ...theme,\n colors: {\n ...theme.colors,\n background: surface.background,\n backgroundLight: surface.backgroundLight,\n text: surface.text,\n textMuted: surface.textMuted,\n },\n };\n}\n\n// ============================================\n// Runtime registry — for custom themes\n// ============================================\n\nconst CUSTOM_THEME_REGISTRY = new Map<string, Theme>();\n\n/**\n * Register a Theme so it can be looked up by id via `resolveTheme(id)`.\n * Lets `Doc.themeId` round-trip through Doc serialization for custom themes.\n *\n * Registered themes take precedence over built-ins with the same id.\n */\nexport function registerTheme(theme: Theme): void {\n CUSTOM_THEME_REGISTRY.set(theme.id, theme);\n}\n\n/** Remove a previously registered theme. */\nexport function unregisterTheme(id: string): void {\n CUSTOM_THEME_REGISTRY.delete(id);\n}\n\n/** Snapshot of all currently registered (non-built-in) themes. */\nexport function getRegisteredThemes(): Theme[] {\n return Array.from(CUSTOM_THEME_REGISTRY.values());\n}\n\n/** @internal — used by themeLibrary's `resolveTheme` to check the registry first. */\nexport function lookupRegisteredTheme(id: string | undefined): Theme | undefined {\n if (!id) return undefined;\n return CUSTOM_THEME_REGISTRY.get(id);\n}\n","/**\n * Color Utilities\n *\n * Pure-JS color math used by theme compilation and contrast checks.\n * No dependencies. Operates on `#rrggbb` hex strings.\n *\n * Internally uses OKLCh — perceptually uniform, so lightening by 0.1\n * looks like the same change at any starting point. Out-of-gamut\n * results are clamped to sRGB.\n */\n\nconst HEX_RE = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;\n\n/** Test whether a string is a valid `#rgb` or `#rrggbb` hex color. */\nexport function isHex(value: string): boolean {\n return HEX_RE.test(value);\n}\n\n/** Parse `#rgb` or `#rrggbb` into 0..1 sRGB triplet. Returns null on failure. */\nfunction parseHex(hex: string): [number, number, number] | null {\n if (!HEX_RE.test(hex)) return null;\n let body = hex.slice(1);\n if (body.length === 3)\n body = body\n .split('')\n .map((c) => c + c)\n .join('');\n return [\n parseInt(body.slice(0, 2), 16) / 255,\n parseInt(body.slice(2, 4), 16) / 255,\n parseInt(body.slice(4, 6), 16) / 255,\n ];\n}\n\nfunction toHex(rgb: [number, number, number]): string {\n const ch = (v: number) => {\n const c = Math.max(0, Math.min(255, Math.round(v * 255)));\n return c.toString(16).padStart(2, '0');\n };\n return '#' + ch(rgb[0]) + ch(rgb[1]) + ch(rgb[2]);\n}\n\nfunction srgbToLinear(c: number): number {\n return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n}\n\nfunction linearToSrgb(c: number): number {\n return c <= 0.0031308 ? c * 12.92 : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;\n}\n\ninterface OKLCh {\n L: number;\n C: number;\n h: number;\n}\n\nfunction rgbToOklch(rgb: [number, number, number]): OKLCh {\n const [sr, sg, sb] = rgb;\n const r = srgbToLinear(sr);\n const g = srgbToLinear(sg);\n const b = srgbToLinear(sb);\n\n const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;\n const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;\n const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;\n\n const l_ = Math.cbrt(l);\n const m_ = Math.cbrt(m);\n const s_ = Math.cbrt(s);\n\n const L = 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_;\n const a = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_;\n const bb = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_;\n\n const C = Math.sqrt(a * a + bb * bb);\n let h = (Math.atan2(bb, a) * 180) / Math.PI;\n if (h < 0) h += 360;\n return { L, C, h };\n}\n\nfunction oklchToRgb({ L, C, h }: OKLCh): [number, number, number] {\n const hr = (h * Math.PI) / 180;\n const a = C * Math.cos(hr);\n const bb = C * Math.sin(hr);\n\n const l_ = L + 0.3963377774 * a + 0.2158037573 * bb;\n const m_ = L - 0.1055613458 * a - 0.0638541728 * bb;\n const s_ = L - 0.0894841775 * a - 1.291485548 * bb;\n\n const l = l_ * l_ * l_;\n const m = m_ * m_ * m_;\n const s = s_ * s_ * s_;\n\n const r = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;\n const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;\n const b = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;\n\n return [\n Math.max(0, Math.min(1, linearToSrgb(r))),\n Math.max(0, Math.min(1, linearToSrgb(g))),\n Math.max(0, Math.min(1, linearToSrgb(b))),\n ];\n}\n\n/**\n * Lighten a color by `amount` (0..1) in OKLCh L space.\n * Falls back to the input on parse failure.\n */\nexport function oklchLighten(hex: string, amount: number): string {\n const rgb = parseHex(hex);\n if (!rgb) return hex;\n const lch = rgbToOklch(rgb);\n lch.L = Math.max(0, Math.min(1, lch.L + amount));\n return toHex(oklchToRgb(lch));\n}\n\n/**\n * Darken a color by `amount` (0..1) in OKLCh L space.\n * Falls back to the input on parse failure.\n */\nexport function oklchDarken(hex: string, amount: number): string {\n return oklchLighten(hex, -amount);\n}\n\n/**\n * Adjust the OKLCh chroma of a color by a multiplier (e.g. 0.7 to mute).\n */\nexport function oklchSetChroma(hex: string, multiplier: number): string {\n const rgb = parseHex(hex);\n if (!rgb) return hex;\n const lch = rgbToOklch(rgb);\n lch.C = Math.max(0, lch.C * multiplier);\n return toHex(oklchToRgb(lch));\n}\n\n/**\n * WCAG relative luminance of a hex color, returned as 0..1.\n */\nexport function relativeLuminance(hex: string): number {\n const rgb = parseHex(hex);\n if (!rgb) return 0;\n const [r, g, b] = rgb.map(srgbToLinear) as [number, number, number];\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n\n/**\n * WCAG contrast ratio between two hex colors. Returns 1..21.\n */\nexport function contrastRatio(a: string, b: string): number {\n const la = relativeLuminance(a);\n const lb = relativeLuminance(b);\n const lighter = Math.max(la, lb);\n const darker = Math.min(la, lb);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\n/**\n * Pick a near-white or near-black text color that contrasts well against `bg`.\n */\nexport function pickContrastingText(bg: string, light = '#f7fafc', dark = '#1a202c'): string {\n return contrastRatio(bg, dark) >= contrastRatio(bg, light) ? dark : light;\n}\n\n/**\n * Derive a 5-step lighter→darker scale from a seed color.\n * Stops are evenly spaced in OKLCh L space around the seed.\n * `spread` controls amplitude (0.05 = subtle, 0.15 = balanced, 0.22 = high).\n */\nexport function deriveScale(\n seedHex: string,\n spread = 0.15,\n): {\n lighter2: string;\n lighter1: string;\n base: string;\n darker1: string;\n darker2: string;\n} {\n return {\n lighter2: oklchLighten(seedHex, spread),\n lighter1: oklchLighten(seedHex, spread / 2),\n base: seedHex,\n darker1: oklchDarken(seedHex, spread / 2),\n darker2: oklchDarken(seedHex, spread),\n };\n}\n","/**\n * Theme Validator\n *\n * Hand-rolled validator for `Theme` JSON. No dependencies. Produces a\n * flat list of typed errors with JSON paths, suitable for surfacing in\n * the customizer UI or throwing at module init for built-in themes.\n *\n * Design: walk the candidate object, push errors for each violation.\n * Coverage is exhaustive for required fields and shapes; permissive on\n * forward-compatible fields (unknown keys are ignored, not rejected).\n */\n\nimport type { Theme, ThemeColorPalette } from './Theme.js';\nimport { THEME_SCHEMA_VERSION } from './Theme.js';\nimport { isHex } from './colorUtils.js';\n\nexport interface ValidationError {\n path: string;\n message: string;\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationError[];\n /** Present only when `valid === true`. The same input typed as `Theme`. */\n theme?: Theme;\n}\n\nconst VALID_FALLBACK = new Set(['serif', 'sans-serif', 'monospace', 'system-ui']);\nconst VALID_TITLE_WEIGHT = new Set(['normal', 'bold']);\nconst VALID_TRANSITION_TYPES = new Set([\n 'cut',\n 'fade',\n 'dissolve',\n 'slideLeft',\n 'slideRight',\n 'slideUp',\n 'slideDown',\n 'zoom',\n]);\nconst VALID_GRADIENT_PRESETS = new Set([\n 'dark-vignette',\n 'radial-dark',\n 'warm-sunset',\n 'cool-blue',\n 'earth-tones',\n]);\n\nclass V {\n errors: ValidationError[] = [];\n err(path: string, message: string): void {\n this.errors.push({ path, message });\n }\n isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n }\n isString(v: unknown): v is string {\n return typeof v === 'string';\n }\n isNumber(v: unknown): v is number {\n return typeof v === 'number' && Number.isFinite(v);\n }\n isBoolean(v: unknown): v is boolean {\n return typeof v === 'boolean';\n }\n hex(path: string, v: unknown): void {\n if (!this.isString(v)) {\n this.err(path, `expected hex color string, got ${typeof v}`);\n } else if (!isHex(v)) {\n this.err(path, `expected #rgb or #rrggbb hex color, got \"${v}\"`);\n }\n }\n\n palette(path: string, v: unknown): void {\n if (!this.isObject(v)) {\n this.err(path, 'expected object');\n return;\n }\n const required: (keyof ThemeColorPalette)[] = [\n 'primary',\n 'secondary',\n 'background',\n 'backgroundLight',\n 'text',\n 'textMuted',\n 'highlight',\n 'warning',\n ];\n for (const k of required) this.hex(`${path}.${k}`, v[k]);\n }\n\n colorScheme(path: string, v: unknown): void {\n if (!this.isObject(v)) {\n this.err(path, 'expected object');\n return;\n }\n this.hex(`${path}.bg`, v.bg);\n this.hex(`${path}.text`, v.text);\n this.hex(`${path}.accent`, v.accent);\n }\n\n colorSchemes(path: string, v: unknown): void {\n if (!this.isObject(v)) {\n this.err(path, 'expected object map');\n return;\n }\n for (const key of Object.keys(v)) {\n this.colorScheme(`${path}.${key}`, v[key]);\n }\n }\n\n fontFamily(path: string, v: unknown): void {\n if (!this.isObject(v)) {\n this.err(path, 'expected FontFamily object ({ stackId } or { custom })');\n return;\n }\n if ('stackId' in v) {\n if (!this.isString(v.stackId) || v.stackId.length === 0) {\n this.err(`${path}.stackId`, 'expected non-empty string');\n }\n return;\n }\n if ('custom' in v) {\n const c = v.custom;\n if (!this.isObject(c)) {\n this.err(`${path}.custom`, 'expected { name, fallback } object');\n return;\n }\n if (!this.isString(c.name) || c.name.length === 0) {\n this.err(`${path}.custom.name`, 'expected non-empty string');\n }\n if (!this.isString(c.fallback) || !VALID_FALLBACK.has(c.fallback)) {\n this.err(\n `${path}.custom.fallback`,\n `expected one of: serif, sans-serif, monospace, system-ui`,\n );\n }\n return;\n }\n this.err(path, 'expected { stackId } or { custom: { name, fallback } }');\n }\n\n typography(path: string, v: unknown): void {\n if (!this.isObject(v)) {\n this.err(path, 'expected object');\n return;\n }\n this.fontFamily(`${path}.bodyFont`, v.bodyFont);\n this.fontFamily(`${path}.titleFont`, v.titleFont);\n if (v.monoFont !== undefined) this.fontFamily(`${path}.monoFont`, v.monoFont);\n for (const k of ['titleScale', 'bodyScale', 'lineHeight', 'titleLineHeight']) {\n if (v[k] !== undefined && !this.isNumber(v[k])) {\n this.err(`${path}.${k}`, `expected number, got ${typeof v[k]}`);\n }\n }\n if (v.titleWeight !== undefined) {\n if (!this.isString(v.titleWeight) || !VALID_TITLE_WEIGHT.has(v.titleWeight)) {\n this.err(`${path}.titleWeight`, 'expected \"normal\" or \"bold\"');\n }\n }\n }\n\n style(path: string, v: unknown): void {\n if (!this.isObject(v)) {\n this.err(path, 'expected object');\n return;\n }\n if (v.borderRadius !== undefined && !this.isNumber(v.borderRadius)) {\n this.err(`${path}.borderRadius`, 'expected number');\n }\n if (v.textShadow !== undefined && !this.isBoolean(v.textShadow)) {\n this.err(`${path}.textShadow`, 'expected boolean');\n }\n for (const k of ['overlayOpacity', 'animationSpeed']) {\n if (v[k] !== undefined && !this.isNumber(v[k])) {\n this.err(`${path}.${k}`, 'expected number');\n }\n }\n if (v.blockPadding !== undefined && !this.isString(v.blockPadding)) {\n this.err(`${path}.blockPadding`, 'expected string (percentage e.g. \"5%\")');\n }\n }\n\n renderStyle(path: string, v: unknown): void {\n if (!this.isObject(v)) {\n this.err(path, 'expected object');\n return;\n }\n if (!this.isString(v.name) || v.name.length === 0) {\n this.err(`${path}.name`, 'expected non-empty string');\n }\n if (v.ambientMotion !== undefined && !this.isBoolean(v.ambientMotion)) {\n this.err(`${path}.ambientMotion`, 'expected boolean');\n }\n for (const k of ['defaultTextAnimation', 'defaultImageAnimation']) {\n if (v[k] !== undefined && !this.isString(v[k])) {\n this.err(`${path}.${k}`, 'expected animation type string');\n }\n }\n if (v.defaultTransition !== undefined) {\n const t = v.defaultTransition;\n if (!this.isObject(t)) {\n this.err(`${path}.defaultTransition`, 'expected object');\n } else {\n if (!this.isString(t.type) || !VALID_TRANSITION_TYPES.has(t.type)) {\n this.err(`${path}.defaultTransition.type`, 'expected valid transition type');\n }\n if (t.duration !== undefined && !this.isNumber(t.duration)) {\n this.err(`${path}.defaultTransition.duration`, 'expected number');\n }\n }\n }\n if (v.layoutOverrides !== undefined && !this.isObject(v.layoutOverrides)) {\n this.err(`${path}.layoutOverrides`, 'expected object');\n }\n if (v.templateHints !== undefined) {\n if (!this.isObject(v.templateHints)) {\n this.err(`${path}.templateHints`, 'expected object map');\n } else {\n for (const tplName of Object.keys(v.templateHints)) {\n const hints = v.templateHints[tplName];\n if (!this.isObject(hints)) {\n this.err(`${path}.templateHints.${tplName}`, 'expected object');\n continue;\n }\n for (const key of Object.keys(hints)) {\n const val = hints[key];\n const t = typeof val;\n if (t !== 'string' && t !== 'number' && t !== 'boolean') {\n this.err(\n `${path}.templateHints.${tplName}.${key}`,\n `expected string|number|boolean, got ${t}`,\n );\n }\n }\n }\n }\n }\n }\n\n seedColors(path: string, v: unknown): void {\n if (!this.isObject(v)) {\n this.err(path, 'expected object');\n return;\n }\n if (v.primary === undefined) {\n this.err(`${path}.primary`, 'required when seedColors is present');\n } else {\n this.hex(`${path}.primary`, v.primary);\n }\n for (const k of ['secondary', 'accent', 'background', 'text']) {\n if (v[k] !== undefined) this.hex(`${path}.${k}`, v[k]);\n }\n }\n\n persistentLayer(path: string, v: unknown): void {\n if (!this.isObject(v)) {\n this.err(path, 'expected object');\n return;\n }\n // Either { template, config } or a raw Layer — only validate the template form here\n if ('template' in v) {\n if (!this.isString(v.template)) {\n this.err(`${path}.template`, 'expected string');\n return;\n }\n const cfg = v.config;\n if (!this.isObject(cfg)) {\n this.err(`${path}.config`, 'expected object');\n return;\n }\n if (cfg.type !== v.template) {\n this.err(`${path}.config.type`, `expected \"${v.template}\", got \"${String(cfg.type)}\"`);\n }\n if (v.template === 'gradientBackground' && cfg.preset !== undefined) {\n if (!this.isString(cfg.preset) || !VALID_GRADIENT_PRESETS.has(cfg.preset)) {\n this.err(\n `${path}.config.preset`,\n `expected one of: ${Array.from(VALID_GRADIENT_PRESETS).join(', ')}`,\n );\n }\n }\n if (v.template === 'gradientBackground' && 'gradient' in cfg) {\n this.err(\n `${path}.config.gradient`,\n 'raw CSS gradient strings are not allowed in Theme JSON; use a `preset`',\n );\n }\n }\n // Raw Layer form is permissive — no schema check here\n }\n\n persistentLayers(path: string, v: unknown): void {\n if (!this.isObject(v)) {\n this.err(path, 'expected object');\n return;\n }\n for (const side of ['bottomLayers', 'topLayers']) {\n const arr = v[side];\n if (arr === undefined) continue;\n if (!Array.isArray(arr)) {\n this.err(`${path}.${side}`, 'expected array');\n continue;\n }\n arr.forEach((entry, i) => this.persistentLayer(`${path}.${side}[${i}]`, entry));\n }\n }\n}\n\nexport function validateTheme(input: unknown): ValidationResult {\n const v = new V();\n if (!v.isObject(input)) {\n return { valid: false, errors: [{ path: '', message: 'expected object' }] };\n }\n\n if (input.schemaVersion !== THEME_SCHEMA_VERSION) {\n v.err(\n 'schemaVersion',\n `expected \"${THEME_SCHEMA_VERSION}\", got \"${String(input.schemaVersion)}\"`,\n );\n }\n if (!v.isString(input.id) || input.id.length === 0) {\n v.err('id', 'expected non-empty string');\n }\n if (!v.isString(input.name) || input.name.length === 0) {\n v.err('name', 'expected non-empty string');\n }\n if (input.description !== undefined && !v.isString(input.description)) {\n v.err('description', 'expected string');\n }\n\n if (input.seedColors !== undefined) v.seedColors('seedColors', input.seedColors);\n\n if (input.colors === undefined) {\n v.err('colors', 'required');\n } else {\n v.palette('colors', input.colors);\n }\n\n if (input.typography === undefined) {\n v.err('typography', 'required');\n } else {\n v.typography('typography', input.typography);\n }\n\n if (input.style === undefined) {\n v.err('style', 'required');\n } else {\n v.style('style', input.style);\n }\n\n if (input.renderStyle === undefined) {\n v.err('renderStyle', 'required');\n } else {\n v.renderStyle('renderStyle', input.renderStyle);\n }\n\n if (input.colorSchemes === undefined) {\n v.err('colorSchemes', 'required');\n } else {\n v.colorSchemes('colorSchemes', input.colorSchemes);\n }\n\n if (input.persistentLayers !== undefined) {\n v.persistentLayers('persistentLayers', input.persistentLayers);\n }\n\n if (v.errors.length === 0) {\n return { valid: true, errors: [], theme: input as unknown as Theme };\n }\n return { valid: false, errors: v.errors };\n}\n\n/** Throws on invalid input. Useful at module init for built-in themes. */\nexport function assertTheme(input: unknown, source = 'theme'): Theme {\n const result = validateTheme(input);\n if (!result.valid || !result.theme) {\n const summary = result.errors\n .slice(0, 5)\n .map((e) => ` ${e.path || '<root>'}: ${e.message}`)\n .join('\\n');\n const more = result.errors.length > 5 ? `\\n ... and ${result.errors.length - 5} more` : '';\n throw new Error(`Invalid ${source}:\\n${summary}${more}`);\n }\n return result.theme;\n}\n\n// (Theme types are re-exported from `./Theme.js` via the schemas barrel.)\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"standard\",\n \"name\": \"Standard Light\",\n \"description\": \"Clean and safe — black-on-white, system fonts only, no external font dependencies. Default theme.\",\n \"colors\": {\n \"primary\": \"#2563eb\",\n \"secondary\": \"#475569\",\n \"background\": \"#ffffff\",\n \"backgroundLight\": \"#f1f5f9\",\n \"text\": \"#0f172a\",\n \"textMuted\": \"#475569\",\n \"highlight\": \"#1d4ed8\",\n \"warning\": \"#dc2626\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"system-sans\" },\n \"titleFont\": { \"stackId\": \"system-serif\" },\n \"monoFont\": { \"stackId\": \"system-mono\" },\n \"titleWeight\": \"bold\"\n },\n \"style\": {\n \"textShadow\": false,\n \"overlayOpacity\": 0.35,\n \"animationSpeed\": 1.0\n },\n \"renderStyle\": {\n \"name\": \"standard\",\n \"defaultTextAnimation\": \"fadeIn\",\n \"defaultImageAnimation\": \"slowZoom\",\n \"ambientMotion\": true,\n \"defaultTransition\": { \"type\": \"fade\", \"duration\": 0.7 }\n },\n \"colorSchemes\": {\n \"blue\": { \"bg\": \"#dbeafe\", \"text\": \"#1d4ed8\", \"accent\": \"#2563eb\" },\n \"green\": { \"bg\": \"#dcfce7\", \"text\": \"#166534\", \"accent\": \"#16a34a\" },\n \"purple\": { \"bg\": \"#ede9fe\", \"text\": \"#5b21b6\", \"accent\": \"#7c3aed\" },\n \"red\": { \"bg\": \"#fee2e2\", \"text\": \"#991b1b\", \"accent\": \"#dc2626\" },\n \"orange\": { \"bg\": \"#ffedd5\", \"text\": \"#9a3412\", \"accent\": \"#ea580c\" },\n \"teal\": { \"bg\": \"#ccfbf1\", \"text\": \"#115e59\", \"accent\": \"#0d9488\" }\n }\n}\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"standard-dark\",\n \"name\": \"Standard Dark\",\n \"description\": \"Standard, dark variant. System fonts, dark navy background, light text.\",\n \"colors\": {\n \"primary\": \"#3182ce\",\n \"secondary\": \"#4a5568\",\n \"background\": \"#1a202c\",\n \"backgroundLight\": \"#2d3748\",\n \"text\": \"#f7fafc\",\n \"textMuted\": \"#a0aec0\",\n \"highlight\": \"#4299e1\",\n \"warning\": \"#fc8181\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"system-sans\" },\n \"titleFont\": { \"stackId\": \"system-serif\" },\n \"monoFont\": { \"stackId\": \"system-mono\" },\n \"titleWeight\": \"bold\"\n },\n \"style\": {\n \"textShadow\": true,\n \"overlayOpacity\": 0.45,\n \"animationSpeed\": 1.0\n },\n \"renderStyle\": {\n \"name\": \"standard\",\n \"defaultTextAnimation\": \"fadeIn\",\n \"defaultImageAnimation\": \"slowZoom\",\n \"ambientMotion\": true,\n \"defaultTransition\": { \"type\": \"fade\", \"duration\": 0.7 }\n },\n \"colorSchemes\": {\n \"blue\": { \"bg\": \"#1a365d\", \"text\": \"#63b3ed\", \"accent\": \"#90cdf4\" },\n \"green\": { \"bg\": \"#22543d\", \"text\": \"#9ae6b4\", \"accent\": \"#68d391\" },\n \"purple\": { \"bg\": \"#44337a\", \"text\": \"#d6bcfa\", \"accent\": \"#b794f4\" },\n \"red\": { \"bg\": \"#742a2a\", \"text\": \"#fc8181\", \"accent\": \"#feb2b2\" },\n \"orange\": { \"bg\": \"#744210\", \"text\": \"#fbd38d\", \"accent\": \"#f6ad55\" },\n \"teal\": { \"bg\": \"#234e52\", \"text\": \"#81e6d9\", \"accent\": \"#4fd1c5\" }\n },\n \"persistentLayers\": {\n \"bottomLayers\": [\n {\n \"template\": \"gradientBackground\",\n \"config\": { \"type\": \"gradientBackground\", \"preset\": \"dark-vignette\" }\n }\n ]\n }\n}\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"documentary\",\n \"name\": \"Documentary\",\n \"description\": \"Classic dark cinematic look with elegant serif typography.\",\n \"colors\": {\n \"primary\": \"#3d5a80\",\n \"secondary\": \"#63b3ed\",\n \"background\": \"#1a202c\",\n \"backgroundLight\": \"#2d3748\",\n \"text\": \"#ffffff\",\n \"textMuted\": \"#a0aec0\",\n \"highlight\": \"#63b3ed\",\n \"warning\": \"#fc8181\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"source-serif\" },\n \"titleFont\": { \"stackId\": \"playfair\" },\n \"titleWeight\": \"bold\"\n },\n \"style\": {\n \"textShadow\": true,\n \"overlayOpacity\": 0.5,\n \"animationSpeed\": 1.0\n },\n \"renderStyle\": {\n \"name\": \"documentary\",\n \"defaultTextAnimation\": \"fadeIn\",\n \"defaultImageAnimation\": \"slowZoom\",\n \"ambientMotion\": true,\n \"defaultTransition\": { \"type\": \"fade\", \"duration\": 0.8 }\n },\n \"colorSchemes\": {\n \"blue\": { \"bg\": \"#1a365d\", \"text\": \"#63b3ed\", \"accent\": \"#90cdf4\" },\n \"green\": { \"bg\": \"#22543d\", \"text\": \"#9ae6b4\", \"accent\": \"#68d391\" },\n \"purple\": { \"bg\": \"#44337a\", \"text\": \"#d6bcfa\", \"accent\": \"#b794f4\" },\n \"red\": { \"bg\": \"#742a2a\", \"text\": \"#fc8181\", \"accent\": \"#feb2b2\" },\n \"orange\": { \"bg\": \"#744210\", \"text\": \"#fbd38d\", \"accent\": \"#f6ad55\" },\n \"teal\": { \"bg\": \"#234e52\", \"text\": \"#81e6d9\", \"accent\": \"#4fd1c5\" }\n },\n \"persistentLayers\": {\n \"bottomLayers\": [\n {\n \"template\": \"gradientBackground\",\n \"config\": { \"type\": \"gradientBackground\", \"preset\": \"dark-vignette\" }\n }\n ]\n }\n}\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"minimalist\",\n \"name\": \"Minimalist\",\n \"description\": \"Clean near-white background with sans-serif type and minimal animation.\",\n \"colors\": {\n \"primary\": \"#2d3748\",\n \"secondary\": \"#4a5568\",\n \"background\": \"#f7fafc\",\n \"backgroundLight\": \"#edf2f7\",\n \"text\": \"#1a202c\",\n \"textMuted\": \"#718096\",\n \"highlight\": \"#3182ce\",\n \"warning\": \"#e53e3e\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"inter\" },\n \"titleFont\": { \"stackId\": \"inter\" },\n \"titleWeight\": \"bold\",\n \"lineHeight\": 1.6\n },\n \"style\": {\n \"textShadow\": false,\n \"overlayOpacity\": 0.3,\n \"animationSpeed\": 1.2,\n \"borderRadius\": 8\n },\n \"renderStyle\": {\n \"name\": \"minimalist\",\n \"defaultTextAnimation\": \"fadeIn\",\n \"ambientMotion\": false,\n \"defaultTransition\": { \"type\": \"fade\", \"duration\": 0.6 },\n \"templateHints\": {\n \"title\": { \"showAccentLine\": false }\n }\n },\n \"colorSchemes\": {\n \"blue\": { \"bg\": \"#ebf8ff\", \"text\": \"#2b6cb0\", \"accent\": \"#3182ce\" },\n \"green\": { \"bg\": \"#f0fff4\", \"text\": \"#276749\", \"accent\": \"#38a169\" },\n \"purple\": { \"bg\": \"#faf5ff\", \"text\": \"#553c9a\", \"accent\": \"#805ad5\" },\n \"red\": { \"bg\": \"#fff5f5\", \"text\": \"#c53030\", \"accent\": \"#e53e3e\" },\n \"orange\": { \"bg\": \"#fffaf0\", \"text\": \"#c05621\", \"accent\": \"#dd6b20\" },\n \"teal\": { \"bg\": \"#e6fffa\", \"text\": \"#285e61\", \"accent\": \"#319795\" }\n }\n}\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"bold\",\n \"name\": \"Bold\",\n \"description\": \"High-contrast black with vivid accents and dramatic animations.\",\n \"colors\": {\n \"primary\": \"#e53e3e\",\n \"secondary\": \"#ed8936\",\n \"background\": \"#000000\",\n \"backgroundLight\": \"#1a1a1a\",\n \"text\": \"#ffffff\",\n \"textMuted\": \"#cbd5e0\",\n \"highlight\": \"#f6e05e\",\n \"warning\": \"#fc8181\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"roboto\" },\n \"titleFont\": { \"stackId\": \"oswald\" },\n \"titleWeight\": \"bold\",\n \"titleScale\": 1.15,\n \"bodyScale\": 1.0,\n \"titleLineHeight\": 1.1\n },\n \"style\": {\n \"textShadow\": true,\n \"overlayOpacity\": 0.6,\n \"animationSpeed\": 0.8\n },\n \"renderStyle\": {\n \"name\": \"bold\",\n \"defaultTextAnimation\": \"zoomIn\",\n \"defaultImageAnimation\": \"slowZoom\",\n \"ambientMotion\": true,\n \"defaultTransition\": { \"type\": \"dissolve\", \"duration\": 0.5 },\n \"templateHints\": {\n \"statHighlight\": { \"entrance\": \"dramatic\" },\n \"fullBleedQuote\": { \"entrance\": \"dramatic\" }\n }\n },\n \"colorSchemes\": {\n \"blue\": { \"bg\": \"#1a202c\", \"text\": \"#63b3ed\", \"accent\": \"#90cdf4\" },\n \"green\": { \"bg\": \"#1a202c\", \"text\": \"#48bb78\", \"accent\": \"#68d391\" },\n \"purple\": { \"bg\": \"#1a202c\", \"text\": \"#b794f4\", \"accent\": \"#d6bcfa\" },\n \"red\": { \"bg\": \"#1a202c\", \"text\": \"#fc8181\", \"accent\": \"#feb2b2\" },\n \"orange\": { \"bg\": \"#1a202c\", \"text\": \"#f6ad55\", \"accent\": \"#fbd38d\" },\n \"teal\": { \"bg\": \"#1a202c\", \"text\": \"#4fd1c5\", \"accent\": \"#81e6d9\" }\n }\n}\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"morning-light\",\n \"name\": \"Morning Light\",\n \"description\": \"Warm light background with dark text and gentle serif typography.\",\n \"colors\": {\n \"primary\": \"#744210\",\n \"secondary\": \"#975a16\",\n \"background\": \"#faf8f5\",\n \"backgroundLight\": \"#f5f0eb\",\n \"text\": \"#2d3748\",\n \"textMuted\": \"#718096\",\n \"highlight\": \"#dd6b20\",\n \"warning\": \"#c53030\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"lora\" },\n \"titleFont\": { \"stackId\": \"merriweather\" },\n \"titleWeight\": \"bold\",\n \"lineHeight\": 1.7\n },\n \"style\": {\n \"textShadow\": false,\n \"overlayOpacity\": 0.35,\n \"animationSpeed\": 1.1,\n \"borderRadius\": 4\n },\n \"renderStyle\": {\n \"name\": \"morning-light\",\n \"defaultTextAnimation\": \"fadeIn\",\n \"ambientMotion\": false,\n \"defaultTransition\": { \"type\": \"fade\", \"duration\": 1.0 }\n },\n \"colorSchemes\": {\n \"blue\": { \"bg\": \"#ebf8ff\", \"text\": \"#2c5282\", \"accent\": \"#4299e1\" },\n \"green\": { \"bg\": \"#f0fff4\", \"text\": \"#22543d\", \"accent\": \"#48bb78\" },\n \"purple\": { \"bg\": \"#faf5ff\", \"text\": \"#44337a\", \"accent\": \"#9f7aea\" },\n \"red\": { \"bg\": \"#fff5f5\", \"text\": \"#9b2c2c\", \"accent\": \"#fc8181\" },\n \"orange\": { \"bg\": \"#fffaf0\", \"text\": \"#744210\", \"accent\": \"#ed8936\" },\n \"teal\": { \"bg\": \"#e6fffa\", \"text\": \"#234e52\", \"accent\": \"#38b2ac\" }\n }\n}\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"tech-dark\",\n \"name\": \"Tech Dark\",\n \"description\": \"True black with neon cyan/green accents and monospace titles.\",\n \"colors\": {\n \"primary\": \"#00e5ff\",\n \"secondary\": \"#00e676\",\n \"background\": \"#0a0a0a\",\n \"backgroundLight\": \"#1a1a2e\",\n \"text\": \"#e0e0e0\",\n \"textMuted\": \"#9e9e9e\",\n \"highlight\": \"#00e5ff\",\n \"warning\": \"#ff5252\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"ibm-plex-sans\" },\n \"titleFont\": { \"stackId\": \"jetbrains-mono\" },\n \"monoFont\": { \"stackId\": \"jetbrains-mono\" },\n \"titleWeight\": \"bold\",\n \"titleScale\": 0.9,\n \"lineHeight\": 1.5\n },\n \"style\": {\n \"textShadow\": true,\n \"overlayOpacity\": 0.55,\n \"animationSpeed\": 0.9,\n \"borderRadius\": 2\n },\n \"renderStyle\": {\n \"name\": \"tech-dark\",\n \"defaultTextAnimation\": \"typewriter\",\n \"defaultImageAnimation\": \"slowZoom\",\n \"ambientMotion\": true,\n \"defaultTransition\": { \"type\": \"dissolve\", \"duration\": 0.4 },\n \"templateHints\": {\n \"statHighlight\": { \"entrance\": \"dramatic\" }\n }\n },\n \"colorSchemes\": {\n \"blue\": { \"bg\": \"#0d1b2a\", \"text\": \"#00b0ff\", \"accent\": \"#40c4ff\" },\n \"green\": { \"bg\": \"#0d1b0d\", \"text\": \"#00e676\", \"accent\": \"#69f0ae\" },\n \"purple\": { \"bg\": \"#1a0d2e\", \"text\": \"#d500f9\", \"accent\": \"#ea80fc\" },\n \"red\": { \"bg\": \"#2e0d0d\", \"text\": \"#ff5252\", \"accent\": \"#ff8a80\" },\n \"orange\": { \"bg\": \"#2e1a0d\", \"text\": \"#ff9100\", \"accent\": \"#ffab40\" },\n \"teal\": { \"bg\": \"#0d2e2e\", \"text\": \"#1de9b6\", \"accent\": \"#64ffda\" }\n }\n}\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"magazine\",\n \"name\": \"Magazine\",\n \"description\": \"Rich editorial palette with mixed serif/sans typography and slide transitions.\",\n \"colors\": {\n \"primary\": \"#c53030\",\n \"secondary\": \"#2b6cb0\",\n \"background\": \"#1a202c\",\n \"backgroundLight\": \"#2d3748\",\n \"text\": \"#f7fafc\",\n \"textMuted\": \"#cbd5e0\",\n \"highlight\": \"#ed8936\",\n \"warning\": \"#fc8181\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"dm-sans\" },\n \"titleFont\": { \"stackId\": \"dm-serif\" },\n \"titleWeight\": \"bold\",\n \"titleScale\": 1.05,\n \"lineHeight\": 1.5\n },\n \"style\": {\n \"textShadow\": true,\n \"overlayOpacity\": 0.45,\n \"animationSpeed\": 1.0,\n \"borderRadius\": 6\n },\n \"renderStyle\": {\n \"name\": \"magazine\",\n \"defaultTextAnimation\": \"fadeIn\",\n \"defaultImageAnimation\": \"slowZoom\",\n \"ambientMotion\": true,\n \"defaultTransition\": { \"type\": \"slideLeft\", \"duration\": 0.7 }\n },\n \"colorSchemes\": {\n \"blue\": { \"bg\": \"#1a365d\", \"text\": \"#90cdf4\", \"accent\": \"#63b3ed\" },\n \"green\": { \"bg\": \"#1c4532\", \"text\": \"#9ae6b4\", \"accent\": \"#68d391\" },\n \"purple\": { \"bg\": \"#322659\", \"text\": \"#d6bcfa\", \"accent\": \"#b794f4\" },\n \"red\": { \"bg\": \"#63171b\", \"text\": \"#feb2b2\", \"accent\": \"#fc8181\" },\n \"orange\": { \"bg\": \"#652b19\", \"text\": \"#fbd38d\", \"accent\": \"#f6ad55\" },\n \"teal\": { \"bg\": \"#1d4044\", \"text\": \"#81e6d9\", \"accent\": \"#4fd1c5\" }\n }\n}\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"cinematic\",\n \"name\": \"Cinematic\",\n \"description\": \"Ultra-dark with moody gradients, gold accents, and slow dissolve transitions.\",\n \"colors\": {\n \"primary\": \"#d69e2e\",\n \"secondary\": \"#b7791f\",\n \"background\": \"#0a0f1a\",\n \"backgroundLight\": \"#1a202c\",\n \"text\": \"#f7fafc\",\n \"textMuted\": \"#a0aec0\",\n \"highlight\": \"#ecc94b\",\n \"warning\": \"#fc8181\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"crimson\" },\n \"titleFont\": { \"stackId\": \"cormorant\" },\n \"titleWeight\": \"bold\",\n \"lineHeight\": 1.5,\n \"titleLineHeight\": 1.2\n },\n \"style\": {\n \"textShadow\": true,\n \"overlayOpacity\": 0.55,\n \"animationSpeed\": 1.2\n },\n \"renderStyle\": {\n \"name\": \"cinematic\",\n \"defaultTextAnimation\": \"fadeIn\",\n \"defaultImageAnimation\": \"slowZoom\",\n \"ambientMotion\": true,\n \"defaultTransition\": { \"type\": \"dissolve\", \"duration\": 1.2 },\n \"templateHints\": {\n \"title\": { \"showAccentLine\": true }\n }\n },\n \"colorSchemes\": {\n \"blue\": { \"bg\": \"#0d1b2a\", \"text\": \"#90cdf4\", \"accent\": \"#63b3ed\" },\n \"green\": { \"bg\": \"#0d1b14\", \"text\": \"#9ae6b4\", \"accent\": \"#68d391\" },\n \"purple\": { \"bg\": \"#1a0d2e\", \"text\": \"#d6bcfa\", \"accent\": \"#b794f4\" },\n \"red\": { \"bg\": \"#2a0d0d\", \"text\": \"#fc8181\", \"accent\": \"#feb2b2\" },\n \"orange\": { \"bg\": \"#2a1a0d\", \"text\": \"#fbd38d\", \"accent\": \"#f6ad55\" },\n \"teal\": { \"bg\": \"#0d2a2a\", \"text\": \"#81e6d9\", \"accent\": \"#4fd1c5\" }\n },\n \"persistentLayers\": {\n \"bottomLayers\": [\n {\n \"template\": \"gradientBackground\",\n \"config\": { \"type\": \"gradientBackground\", \"preset\": \"radial-dark\" }\n }\n ]\n }\n}\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"warm-earth\",\n \"name\": \"Warm Earth\",\n \"description\": \"Natural warm tones with earthy browns and terracotta accents.\",\n \"colors\": {\n \"primary\": \"#9c4221\",\n \"secondary\": \"#c05621\",\n \"background\": \"#1c1410\",\n \"backgroundLight\": \"#2d241e\",\n \"text\": \"#faf5f0\",\n \"textMuted\": \"#c4a882\",\n \"highlight\": \"#dd6b20\",\n \"warning\": \"#e53e3e\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"pt-serif\" },\n \"titleFont\": { \"stackId\": \"pt-serif\" },\n \"titleWeight\": \"bold\",\n \"lineHeight\": 1.6\n },\n \"style\": {\n \"textShadow\": true,\n \"overlayOpacity\": 0.5,\n \"animationSpeed\": 1.1\n },\n \"renderStyle\": {\n \"name\": \"warm-earth\",\n \"defaultTextAnimation\": \"fadeIn\",\n \"defaultImageAnimation\": \"panLeft\",\n \"ambientMotion\": true,\n \"defaultTransition\": { \"type\": \"fade\", \"duration\": 0.9 }\n },\n \"colorSchemes\": {\n \"blue\": { \"bg\": \"#2a1f14\", \"text\": \"#90cdf4\", \"accent\": \"#63b3ed\" },\n \"green\": { \"bg\": \"#1e2a14\", \"text\": \"#9ae6b4\", \"accent\": \"#68d391\" },\n \"purple\": { \"bg\": \"#2a142a\", \"text\": \"#d6bcfa\", \"accent\": \"#b794f4\" },\n \"red\": { \"bg\": \"#2a1414\", \"text\": \"#fc8181\", \"accent\": \"#feb2b2\" },\n \"orange\": { \"bg\": \"#2a1e0a\", \"text\": \"#fbd38d\", \"accent\": \"#f6ad55\" },\n \"teal\": { \"bg\": \"#142a28\", \"text\": \"#81e6d9\", \"accent\": \"#4fd1c5\" }\n },\n \"persistentLayers\": {\n \"bottomLayers\": [\n {\n \"template\": \"gradientBackground\",\n \"config\": { \"type\": \"gradientBackground\", \"preset\": \"earth-tones\" }\n }\n ]\n }\n}\n","{\n \"schemaVersion\": \"1\",\n \"id\": \"gezellig\",\n \"name\": \"Gezellig\",\n \"description\": \"Warm sage + terracotta palette inspired by the Gezel desktop app. Subtle orange-tinted dark background, cream text, sage and terracotta accents.\",\n \"colors\": {\n \"primary\": \"#b0724c\",\n \"secondary\": \"#667f62\",\n \"background\": \"#1f1a17\",\n \"backgroundLight\": \"#2b2420\",\n \"text\": \"#f3ede0\",\n \"textMuted\": \"#a89b85\",\n \"highlight\": \"#c0875d\",\n \"warning\": \"#e07a6b\"\n },\n \"typography\": {\n \"bodyFont\": { \"stackId\": \"system-sans-emoji\" },\n \"titleFont\": { \"stackId\": \"system-serif-emoji\" },\n \"monoFont\": { \"stackId\": \"system-mono\" },\n \"titleWeight\": \"bold\",\n \"lineHeight\": 1.55\n },\n \"style\": {\n \"textShadow\": false,\n \"overlayOpacity\": 0.4,\n \"animationSpeed\": 1.0,\n \"borderRadius\": 6\n },\n \"renderStyle\": {\n \"name\": \"gezellig\",\n \"defaultTextAnimation\": \"fadeIn\",\n \"defaultImageAnimation\": \"slowZoom\",\n \"ambientMotion\": false,\n \"defaultTransition\": { \"type\": \"fade\", \"duration\": 0.6 }\n },\n \"colorSchemes\": {\n \"terracotta\": { \"bg\": \"#3d2620\", \"text\": \"#f3ede0\", \"accent\": \"#c0875d\" },\n \"sage\": { \"bg\": \"#28332a\", \"text\": \"#e3ead9\", \"accent\": \"#8aa589\" },\n \"amber\": { \"bg\": \"#3d2e17\", \"text\": \"#fbe3a8\", \"accent\": \"#d4a149\" },\n \"plum\": { \"bg\": \"#2e1f2a\", \"text\": \"#e8d4e0\", \"accent\": \"#b088a5\" },\n \"ink\": { \"bg\": \"#1a1f26\", \"text\": \"#d5dde8\", \"accent\": \"#7b8fa8\" },\n \"cream\": { \"bg\": \"#f3ede0\", \"text\": \"#2b2420\", \"accent\": \"#b0724c\" }\n }\n}\n","/**\n * Built-in Theme Library\n *\n * Loads each built-in theme from its JSON sidecar, validates it, and\n * exports the typed `Theme` constants. The JSON files in this directory\n * are syntactically identical to customizer-authored themes — they just\n * use more of the schema.\n *\n * Validation runs at module init: if a built-in JSON drifts from the\n * schema, the import fails loudly during build / startup.\n */\n\nimport type { Theme } from '../Theme.js';\nimport { assertTheme } from '../themeValidator.js';\n\nimport standardJson from './standard.json' with { type: 'json' };\nimport standardDarkJson from './standard-dark.json' with { type: 'json' };\nimport documentaryJson from './documentary.json' with { type: 'json' };\nimport minimalistJson from './minimalist.json' with { type: 'json' };\nimport boldJson from './bold.json' with { type: 'json' };\nimport morningLightJson from './morning-light.json' with { type: 'json' };\nimport techDarkJson from './tech-dark.json' with { type: 'json' };\nimport magazineJson from './magazine.json' with { type: 'json' };\nimport cinematicJson from './cinematic.json' with { type: 'json' };\nimport warmEarthJson from './warm-earth.json' with { type: 'json' };\nimport gezelligJson from './gezellig.json' with { type: 'json' };\n\nexport const standard: Theme = assertTheme(standardJson, 'standard.json');\nexport const standardDark: Theme = assertTheme(standardDarkJson, 'standard-dark.json');\nexport const documentary: Theme = assertTheme(documentaryJson, 'documentary.json');\nexport const minimalist: Theme = assertTheme(minimalistJson, 'minimalist.json');\nexport const bold: Theme = assertTheme(boldJson, 'bold.json');\nexport const morningLight: Theme = assertTheme(morningLightJson, 'morning-light.json');\nexport const techDark: Theme = assertTheme(techDarkJson, 'tech-dark.json');\nexport const magazine: Theme = assertTheme(magazineJson, 'magazine.json');\nexport const cinematic: Theme = assertTheme(cinematicJson, 'cinematic.json');\nexport const warmEarth: Theme = assertTheme(warmEarthJson, 'warm-earth.json');\nexport const gezellig: Theme = assertTheme(gezelligJson, 'gezellig.json');\n\n/** All built-in themes, keyed by id. */\nexport const BUILTIN_THEMES: Record<string, Theme> = {\n standard,\n 'standard-dark': standardDark,\n documentary,\n minimalist,\n bold,\n 'morning-light': morningLight,\n 'tech-dark': techDark,\n magazine,\n cinematic,\n 'warm-earth': warmEarth,\n gezellig,\n};\n","/**\n * Built-in Theme Library\n *\n * Public entry point for theme lookup. Built-in themes live as JSON\n * sidecars in [./themes/](./themes/) — they share the exact same shape\n * as customizer-authored themes (no two-tier distinction).\n *\n * Usage:\n * ```ts\n * import { THEMES, resolveTheme } from '@bendyline/squisq/schemas';\n *\n * const theme = resolveTheme('minimalist'); // by id, with registry override\n * const theme = THEMES.documentary; // direct access to a built-in\n * ```\n */\n\nimport type { Theme } from './Theme.js';\nimport { lookupRegisteredTheme } from './Theme.js';\nimport { BUILTIN_THEMES } from './themes/index.js';\n\n/** All built-in themes, keyed by id. */\nexport const THEMES: Record<string, Theme> = BUILTIN_THEMES;\n\n/** The default theme id. */\nexport const DEFAULT_THEME_ID = 'standard';\n\n/** The default theme (standard — safe system fonts, no external dependencies). */\nexport const DEFAULT_THEME: Theme = THEMES[DEFAULT_THEME_ID];\n\n/**\n * Resolve a theme by id. Custom themes registered via `registerTheme()`\n * take precedence over built-ins; otherwise built-ins are searched and\n * the default theme is returned for unknown ids.\n */\nexport function resolveTheme(id: string | undefined): Theme {\n const registered = lookupRegisteredTheme(id);\n if (registered) return registered;\n if (id && id in THEMES) return THEMES[id];\n return DEFAULT_THEME;\n}\n\n/** Get all built-in theme ids. */\nexport function getAvailableThemes(): string[] {\n return Object.keys(THEMES);\n}\n\n/** Get a summary of all built-in themes (id + name + description) for theme pickers. */\nexport function getThemeSummaries(): Array<{ id: string; name: string; description?: string }> {\n return Object.values(THEMES).map((t) => ({\n id: t.id,\n name: t.name,\n description: t.description,\n }));\n}\n","/**\n * Font Stacks\n *\n * Curated registry of font families used by built-in themes and offered in\n * the theme customizer. Each stack has a stable `id` (referenced by JSON\n * theme files via `{ stackId }`) and a CSS `family` string that resolves\n * to the actual font when rendered.\n *\n * Themes never carry raw CSS font strings — they reference a `stackId` or\n * specify a `{ custom: { name, fallback } }` form, both of which resolve\n * here at render time.\n */\n\nimport type { FontFamily, FontFamilyKind } from './Theme.js';\n\nexport interface FontStack {\n /** Stable identifier referenced by Theme JSON. */\n id: string;\n /** Display label for pickers. */\n label: string;\n /** Full CSS font-family string with safe fallbacks. */\n family: string;\n /** Categorical bucket for the picker UI. */\n kind: FontFamilyKind;\n /**\n * Google Fonts family name, when this stack is served by Google Fonts.\n * Used by exports that bundle a `<link>` to fonts.googleapis.com so the\n * face renders correctly even when the host page doesn't preload it.\n * Omit (or set to undefined) for purely system stacks.\n */\n googleFontFamily?: string;\n}\n\n/** All curated stacks, in the order they should appear in pickers. */\nexport const AVAILABLE_FONT_STACKS: FontStack[] = [\n // System defaults\n {\n id: 'system-sans',\n label: 'System Sans',\n family: 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif',\n kind: 'sans',\n },\n {\n id: 'system-serif',\n label: 'System Serif',\n family: 'Georgia, \"Times New Roman\", serif',\n kind: 'serif',\n },\n {\n id: 'system-mono',\n label: 'System Mono',\n family: 'Consolas, \"Courier New\", monospace',\n kind: 'mono',\n },\n // Curated Google Fonts. `googleFontFamily` is the canonical family\n // name Google serves the face under (used by exports that emit a\n // `<link rel=\"stylesheet\" href=\"https://fonts.googleapis.com/...\">`\n // so the face renders even when the host doesn't preload it).\n {\n id: 'inter',\n label: 'Inter',\n family: '\"Inter\", \"Segoe UI\", Roboto, sans-serif',\n kind: 'sans',\n googleFontFamily: 'Inter',\n },\n {\n id: 'ibm-plex-sans',\n label: 'IBM Plex Sans',\n family: '\"IBM Plex Sans\", \"Segoe UI\", Roboto, sans-serif',\n kind: 'sans',\n googleFontFamily: 'IBM Plex Sans',\n },\n {\n id: 'roboto',\n label: 'Roboto',\n family: '\"Roboto\", \"Segoe UI\", Arial, sans-serif',\n kind: 'sans',\n googleFontFamily: 'Roboto',\n },\n {\n id: 'dm-sans',\n label: 'DM Sans',\n family: '\"DM Sans\", \"Segoe UI\", Roboto, sans-serif',\n kind: 'sans',\n googleFontFamily: 'DM Sans',\n },\n {\n id: 'oswald',\n label: 'Oswald',\n family: '\"Oswald\", Impact, \"Arial Black\", sans-serif',\n kind: 'display',\n googleFontFamily: 'Oswald',\n },\n {\n id: 'playfair',\n label: 'Playfair Display',\n family: '\"Playfair Display\", Georgia, serif',\n kind: 'serif',\n googleFontFamily: 'Playfair Display',\n },\n {\n id: 'source-serif',\n label: 'Source Serif',\n family: '\"Source Serif 4\", \"PT Serif\", Georgia, serif',\n kind: 'serif',\n googleFontFamily: 'Source Serif 4',\n },\n {\n id: 'merriweather',\n label: 'Merriweather',\n family: '\"Merriweather\", Georgia, serif',\n kind: 'serif',\n googleFontFamily: 'Merriweather',\n },\n {\n id: 'lora',\n label: 'Lora',\n family: '\"Lora\", \"Merriweather\", Georgia, serif',\n kind: 'serif',\n googleFontFamily: 'Lora',\n },\n {\n id: 'pt-serif',\n label: 'PT Serif',\n family: '\"PT Serif\", Georgia, serif',\n kind: 'serif',\n googleFontFamily: 'PT Serif',\n },\n {\n id: 'crimson',\n label: 'Crimson Text',\n family: '\"Crimson Text\", Georgia, serif',\n kind: 'serif',\n googleFontFamily: 'Crimson Text',\n },\n {\n id: 'cormorant',\n label: 'Cormorant Garamond',\n family: '\"Cormorant Garamond\", Garamond, Georgia, serif',\n kind: 'serif',\n googleFontFamily: 'Cormorant Garamond',\n },\n {\n id: 'dm-serif',\n label: 'DM Serif Display',\n family: '\"DM Serif Display\", Georgia, serif',\n kind: 'display',\n googleFontFamily: 'DM Serif Display',\n },\n {\n id: 'jetbrains-mono',\n label: 'JetBrains Mono',\n family: '\"JetBrains Mono\", \"Fira Code\", Consolas, monospace',\n kind: 'mono',\n googleFontFamily: 'JetBrains Mono',\n },\n // Themed system stacks with emoji fallbacks (used by gezellig)\n {\n id: 'system-sans-emoji',\n label: 'System Sans + Emoji',\n family:\n 'system-ui, -apple-system, \"Segoe UI\", Roboto, \"OpenMoji Color\", \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Noto Color Emoji\", sans-serif',\n kind: 'sans',\n },\n {\n id: 'system-serif-emoji',\n label: 'System Serif + Emoji',\n family:\n 'Georgia, \"Times New Roman\", \"OpenMoji Color\", \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Noto Color Emoji\", serif',\n kind: 'serif',\n },\n];\n\nconst STACKS_BY_ID: Record<string, FontStack> = Object.fromEntries(\n AVAILABLE_FONT_STACKS.map((s) => [s.id, s]),\n);\n\n/** Look up a stack by id. Returns undefined if not registered. */\nexport function getFontStack(id: string): FontStack | undefined {\n return STACKS_BY_ID[id];\n}\n\n/** Default fallback CSS family per kind, used when a custom font has no fallback specified. */\nconst FALLBACK_BY_KIND: Record<FontFamilyKind, string> = {\n sans: 'system-ui, sans-serif',\n serif: 'Georgia, serif',\n mono: 'Consolas, monospace',\n display: 'Impact, Arial, sans-serif',\n};\n\n/**\n * Resolve a `FontFamily` reference (or legacy raw string) to a CSS family string.\n * Used by `getThemeFont` at render time. Never returns an empty string —\n * unrecognized stackIds fall back to the requested role's default.\n */\nexport function resolveFontFamily(\n family: FontFamily | string | undefined,\n roleFallback: string,\n): string {\n if (!family) return roleFallback;\n if (typeof family === 'string') return family;\n if ('stackId' in family) {\n const stack = STACKS_BY_ID[family.stackId];\n return stack ? stack.family : roleFallback;\n }\n if ('custom' in family) {\n const { name, fallback } = family.custom;\n const fb =\n fallback === 'system-ui'\n ? 'system-ui, sans-serif'\n : fallback === 'serif'\n ? 'Georgia, serif'\n : fallback === 'monospace'\n ? 'Consolas, monospace'\n : 'system-ui, sans-serif';\n const safeName = name.includes(' ') || name.includes(',') ? `\"${name}\"` : name;\n return `${safeName}, ${fb}`;\n }\n return roleFallback;\n}\n\n/** Convenience: quick `{ stackId }` factory for code that constructs themes. */\nexport function fontStack(id: string): FontFamily {\n return { stackId: id };\n}\n\n/**\n * Build a `https://fonts.googleapis.com/css2?...` URL that loads the\n * subset of supplied `FontFamily` references that are served by Google\n * Fonts. Returns `null` when nothing in the list needs Google hosting\n * (system stacks, custom fonts, or unknown stack ids) — callers can use\n * that to skip emitting a `<link>` entirely.\n *\n * The URL requests regular + bold (400/700) for each family, which is\n * what the templates use. `display=swap` keeps the fallback visible\n * while the web font streams in.\n */\nexport function buildGoogleFontsUrl(families: Array<FontFamily | undefined>): string | null {\n const names = new Set<string>();\n for (const f of families) {\n if (!f || typeof f === 'string') continue;\n if ('stackId' in f) {\n const stack = STACKS_BY_ID[f.stackId];\n if (stack?.googleFontFamily) names.add(stack.googleFontFamily);\n }\n }\n if (names.size === 0) return null;\n // css2 syntax: ?family=Name+With+Spaces:wght@400;700&family=Other:wght@400;700&display=swap\n const params = Array.from(names)\n .sort()\n .map((name) => `family=${encodeURIComponent(name).replace(/%20/g, '+')}:wght@400;700`)\n .join('&');\n return `https://fonts.googleapis.com/css2?${params}&display=swap`;\n}\n\n/** Default fallback families exposed for tools that need them. */\nexport const FONT_FALLBACKS = FALLBACK_BY_KIND;\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/markdown/utils.ts"],"sourcesContent":["/**\n * Markdown Tree Utilities\n *\n * Helper functions for traversing and querying the MarkdownDocument tree.\n * All functions are pure and operate on the JSON node interfaces.\n */\n\nimport type { MarkdownNode, MarkdownDocument } from './types.js';\n\n/**\n * Get the children of any markdown node, if it has children.\n * Returns an empty array for leaf nodes (text, code, break, etc.).\n *\n * This is useful for generic tree walking where you don't want to\n * check the specific node type.\n */\nexport function getChildren(node: MarkdownNode): MarkdownNode[] {\n if ('children' in node && Array.isArray(node.children)) {\n return node.children as MarkdownNode[];\n }\n return [];\n}\n\n/**\n * Walk the markdown tree depth-first, calling the visitor for each node.\n *\n * The visitor receives the current node and its parent. Return `true`\n * from the visitor to skip the node's children (prune).\n *\n * @param node - The root node to start walking from\n * @param visitor - Called for each node; return true to skip children\n * @param parent - (internal) Parent node\n */\nexport function walkMarkdownTree(\n node: MarkdownNode,\n visitor: (node: MarkdownNode, parent?: MarkdownNode) => void | boolean,\n parent?: MarkdownNode,\n): void {\n const skip = visitor(node, parent);\n if (skip === true) return;\n\n const children = getChildren(node);\n for (const child of children) {\n walkMarkdownTree(child, visitor, node);\n }\n}\n\n/**\n * Find all nodes of a specific type in the tree.\n *\n * @param root - The document or node to search within\n * @param type - The node type to find (e.g., 'heading', 'link', 'text')\n * @returns Array of matching nodes\n *\n * @example\n * ```ts\n * const headings = findNodesByType(doc, 'heading');\n * const links = findNodesByType(doc, 'link');\n * ```\n */\nexport function findNodesByType<T extends MarkdownNode>(root: MarkdownNode, type: T['type']): T[] {\n const results: T[] = [];\n walkMarkdownTree(root, (node) => {\n if (node.type === type) {\n results.push(node as T);\n }\n });\n return results;\n}\n\n/**\n * Extract all plain text content from a node and its descendants.\n * Concatenates text values, ignoring formatting, links, etc.\n *\n * @param node - The node to extract text from\n * @returns Plain text content\n *\n * @example\n * ```ts\n * const heading = doc.children[0]; // { type: 'heading', children: [{ type: 'text', value: 'Hello' }] }\n * extractPlainText(heading); // 'Hello'\n * ```\n */\nexport function extractPlainText(node: MarkdownNode): string {\n if ('value' in node && typeof node.value === 'string') {\n return node.value;\n }\n\n const children = getChildren(node);\n // Preserve boundaries between block-level elements (list items, paragraphs\n // inside list items, blockquotes) so downstream consumers like caption\n // splitting can treat each item as a separate phrase.\n const separator = node.type === 'list' || node.type === 'listItem' ? '\\n' : '';\n return children.map(extractPlainText).join(separator);\n}\n\n/**\n * Count the total number of nodes in the tree.\n *\n * @param node - The root node\n * @returns Total node count (including the root)\n */\nexport function countNodes(node: MarkdownNode): number {\n let count = 1;\n const children = getChildren(node);\n for (const child of children) {\n count += countNodes(child);\n }\n return count;\n}\n\n/**\n * Parse a YAML frontmatter string into a key-value record.\n *\n * Handles simple `key: value` pairs common in markdown frontmatter.\n * Values are trimmed; quoted strings have their quotes removed.\n * Returns `null` if parsing fails or the input is empty.\n *\n * @param yaml - The raw YAML string (without the `---` delimiters)\n * @returns A record of string keys to parsed values, or null\n */\nexport function parseFrontmatter(yaml: string): Record<string, unknown> | null {\n if (!yaml || !yaml.trim()) return null;\n\n const result: Record<string, unknown> = {};\n\n for (const line of yaml.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx < 1) continue;\n\n const key = trimmed.slice(0, colonIdx).trim();\n let value: string | boolean | number = trimmed.slice(colonIdx + 1).trim();\n\n // Remove surrounding quotes\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.slice(1, -1);\n }\n\n // Parse booleans and numbers\n if (value === 'true') {\n result[key] = true;\n } else if (value === 'false') {\n result[key] = false;\n } else if (value !== '' && !isNaN(Number(value))) {\n result[key] = Number(value);\n } else {\n result[key] = value;\n }\n }\n\n return Object.keys(result).length > 0 ? result : null;\n}\n\nconst FRONTMATTER_BLOCK_RE = /^---\\r?\\n([\\s\\S]*?)\\r?\\n---(\\r?\\n)?/;\n\n/** Quote a frontmatter scalar so it round-trips cleanly through `parseFrontmatter`. */\nfunction formatFrontmatterValue(value: string | number | boolean): string {\n if (typeof value === 'boolean' || typeof value === 'number') return String(value);\n // Quote when needed: leading/trailing whitespace, leading punctuation that\n // could trigger YAML modes, or values that look like reserved literals.\n const needsQuote =\n /^\\s|\\s$/.test(value) ||\n /^[!&*?|>%@`]/.test(value) ||\n /[:#]/.test(value) ||\n value === '' ||\n value === 'true' ||\n value === 'false' ||\n /^-?\\d+(\\.\\d+)?$/.test(value);\n if (!needsQuote) return value;\n // Prefer double quotes; escape any embedded double-quote / backslash.\n const escaped = value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n return `\"${escaped}\"`;\n}\n\n/**\n * Update a markdown source string's YAML frontmatter block, applying the\n * given key/value updates. A `null` or `undefined` value removes the key.\n * If no frontmatter block exists and any non-null update is supplied, a\n * new block is prepended; if every update is a removal and no block\n * exists, the source is returned unchanged.\n *\n * Existing key order is preserved; new keys are appended in the order\n * they appear in `updates`. The simple parser used here handles plain\n * `key: value` pairs only — comments, multi-line scalars, and nested\n * structures are left untouched (we only rewrite lines whose key matches\n * one in `updates`).\n *\n * @param source - The markdown source string.\n * @param updates - Map of key → new value (or null/undefined to remove).\n * @returns The updated markdown source string.\n */\nexport function setFrontmatterValues(\n source: string,\n updates: Record<string, string | number | boolean | null | undefined>,\n): string {\n const updateKeys = Object.keys(updates);\n if (updateKeys.length === 0) return source;\n\n const match = source.match(FRONTMATTER_BLOCK_RE);\n const handled = new Set<string>();\n\n // Existing frontmatter block — rewrite line-by-line, preserving order.\n if (match) {\n const inner = match[1];\n const lines = inner.split(/\\r?\\n/);\n const newLines: string[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) {\n newLines.push(line);\n continue;\n }\n const colonIdx = trimmed.indexOf(':');\n if (colonIdx < 1) {\n newLines.push(line);\n continue;\n }\n const key = trimmed.slice(0, colonIdx).trim();\n if (!Object.prototype.hasOwnProperty.call(updates, key)) {\n newLines.push(line);\n continue;\n }\n handled.add(key);\n const next = updates[key];\n if (next === null || next === undefined) continue; // remove\n newLines.push(`${key}: ${formatFrontmatterValue(next)}`);\n }\n\n // Append any keys that weren't already present.\n for (const key of updateKeys) {\n if (handled.has(key)) continue;\n const next = updates[key];\n if (next === null || next === undefined) continue;\n newLines.push(`${key}: ${formatFrontmatterValue(next)}`);\n }\n\n // If every line got removed, drop the block entirely.\n const nonEmpty = newLines.filter((l) => l.trim().length > 0);\n const rest = source.slice(match[0].length);\n if (nonEmpty.length === 0) return rest;\n return `---\\n${newLines.join('\\n')}\\n---\\n${rest}`;\n }\n\n // No existing block — only create one if there's at least one non-null\n // value to write.\n const fresh: string[] = [];\n for (const key of updateKeys) {\n const next = updates[key];\n if (next === null || next === undefined) continue;\n fresh.push(`${key}: ${formatFrontmatterValue(next)}`);\n }\n if (fresh.length === 0) return source;\n return `---\\n${fresh.join('\\n')}\\n---\\n${source}`;\n}\n\n/**\n * Create a minimal MarkdownDocument from a list of block nodes.\n * Convenience function for programmatic document construction.\n */\nexport function createDocument(...children: MarkdownDocument['children']): MarkdownDocument {\n return {\n type: 'document',\n children,\n };\n}\n\n/**\n * Infer a human-readable title for a markdown document.\n *\n * Resolution order:\n * 1. `title:` value in YAML frontmatter (when present and non-empty)\n * 2. Text of the first heading found, walking top-level depth (H1, then\n * H2, etc.) — the shallowest heading wins regardless of source order\n *\n * Returns `undefined` when no usable title is found.\n */\nexport function inferDocumentTitle(doc: MarkdownDocument): string | undefined {\n const fmTitle = doc.frontmatter?.title;\n if (typeof fmTitle === 'string') {\n const trimmed = fmTitle.trim();\n if (trimmed) return trimmed;\n }\n\n let best: { depth: number; text: string } | null = null;\n for (const node of doc.children) {\n if (node.type !== 'heading') continue;\n const text = extractPlainText(node).trim();\n if (!text) continue;\n if (best === null || node.depth < best.depth) {\n best = { depth: node.depth, text };\n if (best.depth === 1) break;\n }\n }\n\n return best?.text;\n}\n\n/**\n * Read a theme id from a markdown document's frontmatter.\n *\n * Checks the editor's canonical `squisq-theme` key first, then the\n * shorter legacy aliases (`themeId`, `theme`). Returns `undefined`\n * when none of them carry a non-empty string. Centralizing the lookup\n * keeps the export pipelines (DOCX, PPTX, HTML, plain-HTML bundle) in\n * sync with whatever the editor writes — adding a new frontmatter\n * spelling later is a one-file change.\n */\nexport function readFrontmatterThemeId(\n frontmatter: Record<string, unknown> | undefined,\n): string | undefined {\n if (!frontmatter) return undefined;\n const keys = ['squisq-theme', 'themeId', 'theme'] as const;\n for (const key of keys) {\n const raw = frontmatter[key];\n if (typeof raw === 'string') {\n const trimmed = raw.trim();\n if (trimmed) return trimmed;\n }\n }\n return undefined;\n}\n"],"mappings":"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","names":[]}