@openpresentation/opf 0.13.0 → 0.15.1

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 (611) hide show
  1. package/README.md +40 -49
  2. package/dist/catalog-refs-BSfGELpt.d.ts +128 -0
  3. package/dist/catalog-schemas-CinPh5WA.d.ts +12 -0
  4. package/dist/catalog.d.ts +91 -0
  5. package/dist/{chunk-E34DJ5LL.js → catalog.js} +16949 -17628
  6. package/dist/{chart-data-Cdr6rRVV.d.ts → chart-data-BnNqgnC-.d.ts} +17 -6
  7. package/dist/{chunk-7QBCWNWL.js → chunk-2CJPC4HI.js} +1807 -1904
  8. package/dist/{chunk-II5EYKZU.js → chunk-374R35TJ.js} +2 -92
  9. package/dist/chunk-3JG4YXWF.js +1842 -0
  10. package/dist/chunk-3RKB4RDJ.js +192 -0
  11. package/dist/{chunk-IS2CPNVJ.js → chunk-5FTUIDUH.js} +26 -26
  12. package/dist/{chunk-GJKJL4YY.js → chunk-HXHOZ7AH.js} +1379 -504
  13. package/dist/{chunk-MPM7NRG7.js → chunk-O744SXXA.js} +2014 -885
  14. package/dist/chunk-QDI75P2M.js +3515 -0
  15. package/dist/chunk-SPFV27O5.js +210 -0
  16. package/dist/chunk-TRDXRRQK.js +17 -0
  17. package/dist/chunk-TWQJLI6E.js +601 -0
  18. package/dist/{chunk-ATGDDJPX.js → chunk-U4J75TRG.js} +3 -3
  19. package/dist/{chunk-RAYB46AB.js → chunk-UBFJ2QHH.js} +34 -30
  20. package/dist/chunk-VGAOJEY7.js +94 -0
  21. package/dist/chunk-ZPU46TFA.js +83 -0
  22. package/dist/{composition-D7we69Tr.d.ts → composition-D2tghM82.d.ts} +947 -111
  23. package/dist/composition.d.ts +3 -2
  24. package/dist/composition.js +2 -2
  25. package/dist/convert.d.ts +18 -19
  26. package/dist/convert.js +61 -50
  27. package/dist/data.d.ts +4 -4
  28. package/dist/data.js +3 -3
  29. package/dist/diff.d.ts +4 -4
  30. package/dist/diff.js +7 -605
  31. package/dist/docs.js +56 -44
  32. package/dist/examples.d.ts +1 -1
  33. package/dist/examples.js +49451 -6259
  34. package/dist/finding-CT_f_vbD.d.ts +212 -0
  35. package/dist/format.d.ts +4 -4
  36. package/dist/format.js +2 -83
  37. package/dist/index.d.ts +492 -309
  38. package/dist/index.js +767 -1097
  39. package/dist/json-BFSdESOE.d.ts +19 -0
  40. package/dist/markdown.d.ts +40 -27
  41. package/dist/markdown.js +9 -1941
  42. package/dist/pagination-wedbe7eq.d.ts +119 -0
  43. package/dist/pagination.d.ts +4 -61
  44. package/dist/pagination.js +6 -6
  45. package/dist/patch.d.ts +12 -23
  46. package/dist/patch.js +6 -6
  47. package/dist/{presentation-mG-IYErQ.d.ts → presentation-CDKQVkyI.d.ts} +702 -1026
  48. package/dist/repo-readme.js +1 -1
  49. package/dist/schemas.d.ts +284 -1
  50. package/dist/schemas.js +1 -1
  51. package/dist/spec/README.md +11 -6
  52. package/dist/spec/catalogs/audiences/index.json +2 -50
  53. package/dist/spec/catalogs/chart-types/100pct-stacked-area.json +21 -0
  54. package/dist/spec/catalogs/chart-types/100pct-stacked-bar.json +22 -0
  55. package/dist/spec/catalogs/chart-types/100pct-stacked-column.json +22 -0
  56. package/dist/spec/catalogs/chart-types/area.json +2 -60
  57. package/dist/spec/catalogs/chart-types/bar.json +2 -48
  58. package/dist/spec/catalogs/chart-types/box-and-whisker.json +2 -132
  59. package/dist/spec/catalogs/chart-types/column.json +2 -52
  60. package/dist/spec/catalogs/chart-types/combo.json +37 -0
  61. package/dist/spec/catalogs/chart-types/doughnut.json +2 -40
  62. package/dist/spec/catalogs/chart-types/filled-radar.json +2 -52
  63. package/dist/spec/catalogs/chart-types/funnel.json +2 -46
  64. package/dist/spec/catalogs/chart-types/histogram.json +2 -149
  65. package/dist/spec/catalogs/chart-types/index.json +50 -520
  66. package/dist/spec/catalogs/chart-types/line-with-markers.json +2 -60
  67. package/dist/spec/catalogs/chart-types/line.json +2 -60
  68. package/dist/spec/catalogs/chart-types/pareto.json +2 -50
  69. package/dist/spec/catalogs/chart-types/pie.json +2 -40
  70. package/dist/spec/catalogs/chart-types/radar-with-markers.json +2 -52
  71. package/dist/spec/catalogs/chart-types/radar.json +2 -52
  72. package/dist/spec/catalogs/chart-types/scatter.json +2 -73
  73. package/dist/spec/catalogs/chart-types/stacked-area.json +21 -0
  74. package/dist/spec/catalogs/chart-types/stacked-bar.json +22 -0
  75. package/dist/spec/catalogs/chart-types/stacked-column.json +22 -0
  76. package/dist/spec/catalogs/chart-types/stacked-line-with-markers.json +22 -0
  77. package/dist/spec/catalogs/chart-types/stacked-line.json +21 -0
  78. package/dist/spec/catalogs/chart-types/treemap.json +2 -48
  79. package/dist/spec/catalogs/chart-types/waterfall.json +2 -52
  80. package/dist/spec/catalogs/chart-types/world.json +2 -64
  81. package/dist/spec/catalogs/font-schemes/angsana-new.json +2 -2
  82. package/dist/spec/catalogs/font-schemes/aparajita.json +3 -3
  83. package/dist/spec/catalogs/font-schemes/aptos.json +1 -1
  84. package/dist/spec/catalogs/font-schemes/arabic-typesetting.json +2 -2
  85. package/dist/spec/catalogs/font-schemes/arial.json +1 -1
  86. package/dist/spec/catalogs/font-schemes/batang.json +2 -2
  87. package/dist/spec/catalogs/font-schemes/bookman.json +1 -1
  88. package/dist/spec/catalogs/font-schemes/calibri.json +1 -1
  89. package/dist/spec/catalogs/font-schemes/century-schoolbook.json +1 -1
  90. package/dist/spec/catalogs/font-schemes/consolas.json +2 -4
  91. package/dist/spec/catalogs/font-schemes/constantia.json +1 -1
  92. package/dist/spec/catalogs/font-schemes/courier-new.json +2 -4
  93. package/dist/spec/catalogs/font-schemes/daunpenh.json +2 -2
  94. package/dist/spec/catalogs/font-schemes/david.json +2 -2
  95. package/dist/spec/catalogs/font-schemes/dilleniaupc.json +2 -2
  96. package/dist/spec/catalogs/font-schemes/fangsong.json +2 -2
  97. package/dist/spec/catalogs/font-schemes/garamond.json +1 -1
  98. package/dist/spec/catalogs/font-schemes/gautami.json +2 -2
  99. package/dist/spec/catalogs/font-schemes/georgia.json +1 -1
  100. package/dist/spec/catalogs/font-schemes/gisha.json +3 -3
  101. package/dist/spec/catalogs/font-schemes/grandview.json +1 -1
  102. package/dist/spec/catalogs/font-schemes/gungsuh.json +2 -2
  103. package/dist/spec/catalogs/font-schemes/impact.json +1 -1
  104. package/dist/spec/catalogs/font-schemes/index.json +1 -1
  105. package/dist/spec/catalogs/font-schemes/kalinga.json +2 -2
  106. package/dist/spec/catalogs/font-schemes/kartika.json +2 -2
  107. package/dist/spec/catalogs/font-schemes/khmer-ui.json +2 -2
  108. package/dist/spec/catalogs/font-schemes/latha.json +2 -2
  109. package/dist/spec/catalogs/font-schemes/lucida-sans.json +1 -1
  110. package/dist/spec/catalogs/font-schemes/malgun-gothic.json +2 -2
  111. package/dist/spec/catalogs/font-schemes/mangal.json +4 -5
  112. package/dist/spec/catalogs/font-schemes/meiryo.json +2 -2
  113. package/dist/spec/catalogs/font-schemes/microsoft-jhenghei.json +2 -2
  114. package/dist/spec/catalogs/font-schemes/microsoft-yahei.json +5 -5
  115. package/dist/spec/catalogs/font-schemes/mingliu.json +2 -2
  116. package/dist/spec/catalogs/font-schemes/miriam.json +2 -2
  117. package/dist/spec/catalogs/font-schemes/montserrat.json +1 -1
  118. package/dist/spec/catalogs/font-schemes/ms-mincho.json +2 -2
  119. package/dist/spec/catalogs/font-schemes/nirmala-ui.json +2 -2
  120. package/dist/spec/catalogs/font-schemes/noto-naksh-arabic.json +2 -2
  121. package/dist/spec/catalogs/font-schemes/noto-nastaliq-urdu.json +3 -3
  122. package/dist/spec/catalogs/font-schemes/noto-sans-arabic.json +4 -4
  123. package/dist/spec/catalogs/font-schemes/noto-sans-armenian.json +2 -2
  124. package/dist/spec/catalogs/font-schemes/noto-sans-bengali.json +3 -3
  125. package/dist/spec/catalogs/font-schemes/noto-sans-devangari.json +3 -3
  126. package/dist/spec/catalogs/font-schemes/noto-sans-ethiopic.json +2 -2
  127. package/dist/spec/catalogs/font-schemes/noto-sans-georgian.json +2 -2
  128. package/dist/spec/catalogs/font-schemes/noto-sans-gujarati.json +2 -2
  129. package/dist/spec/catalogs/font-schemes/noto-sans-gurmukhi.json +2 -2
  130. package/dist/spec/catalogs/font-schemes/noto-sans-hebrew.json +2 -2
  131. package/dist/spec/catalogs/font-schemes/noto-sans-jp.json +2 -2
  132. package/dist/spec/catalogs/font-schemes/noto-sans-kannada.json +2 -2
  133. package/dist/spec/catalogs/font-schemes/noto-sans-khmer.json +2 -2
  134. package/dist/spec/catalogs/font-schemes/noto-sans-kr.json +2 -2
  135. package/dist/spec/catalogs/font-schemes/noto-sans-malayalam.json +2 -2
  136. package/dist/spec/catalogs/font-schemes/noto-sans-mongolian.json +2 -2
  137. package/dist/spec/catalogs/font-schemes/noto-sans-oriya.json +2 -2
  138. package/dist/spec/catalogs/font-schemes/noto-sans-sc.json +5 -5
  139. package/dist/spec/catalogs/font-schemes/noto-sans-tamil.json +2 -2
  140. package/dist/spec/catalogs/font-schemes/noto-sans-tc.json +2 -2
  141. package/dist/spec/catalogs/font-schemes/noto-sans-telugu.json +2 -2
  142. package/dist/spec/catalogs/font-schemes/noto-sans-thai.json +2 -2
  143. package/dist/spec/catalogs/font-schemes/noto-sans.json +5 -5
  144. package/dist/spec/catalogs/font-schemes/nyala.json +2 -2
  145. package/dist/spec/catalogs/font-schemes/open-sans.json +1 -1
  146. package/dist/spec/catalogs/font-schemes/pmingliu.json +2 -2
  147. package/dist/spec/catalogs/font-schemes/poppins.json +1 -1
  148. package/dist/spec/catalogs/font-schemes/pt-serif.json +1 -1
  149. package/dist/spec/catalogs/font-schemes/raavi.json +2 -2
  150. package/dist/spec/catalogs/font-schemes/raleway.json +1 -1
  151. package/dist/spec/catalogs/font-schemes/roboto.json +1 -1
  152. package/dist/spec/catalogs/font-schemes/rockwell.json +1 -1
  153. package/dist/spec/catalogs/font-schemes/sakkal-majalla.json +4 -4
  154. package/dist/spec/catalogs/font-schemes/seaford.json +1 -1
  155. package/dist/spec/catalogs/font-schemes/segoe-ui-light.json +1 -1
  156. package/dist/spec/catalogs/font-schemes/segoe-ui.json +1 -1
  157. package/dist/spec/catalogs/font-schemes/shonar-bangla.json +3 -3
  158. package/dist/spec/catalogs/font-schemes/shruti.json +2 -2
  159. package/dist/spec/catalogs/font-schemes/simsun.json +2 -2
  160. package/dist/spec/catalogs/font-schemes/skeena.json +1 -1
  161. package/dist/spec/catalogs/font-schemes/sylfaen.json +3 -3
  162. package/dist/spec/catalogs/font-schemes/tahoma.json +1 -1
  163. package/dist/spec/catalogs/font-schemes/tenorite.json +1 -1
  164. package/dist/spec/catalogs/font-schemes/times-new-roman.json +1 -1
  165. package/dist/spec/catalogs/font-schemes/traditional-arabic.json +4 -4
  166. package/dist/spec/catalogs/font-schemes/trebuchet-ms.json +1 -1
  167. package/dist/spec/catalogs/font-schemes/tunga.json +2 -2
  168. package/dist/spec/catalogs/font-schemes/verdana.json +1 -1
  169. package/dist/spec/catalogs/font-schemes/vrinda.json +2 -2
  170. package/dist/spec/catalogs/font-schemes/yu-gothic.json +2 -2
  171. package/dist/spec/catalogs/layouts/action-plan.json +9 -15
  172. package/dist/spec/catalogs/layouts/agenda.json +8 -15
  173. package/dist/spec/catalogs/layouts/appendix-index.json +7 -15
  174. package/dist/spec/catalogs/layouts/architecture-stack.json +9 -15
  175. package/dist/spec/catalogs/layouts/assumptions-dependencies.json +9 -15
  176. package/dist/spec/catalogs/layouts/before-after.json +9 -15
  177. package/dist/spec/catalogs/layouts/benchmark-target-table.json +9 -15
  178. package/dist/spec/catalogs/layouts/blank.json +11 -1
  179. package/dist/spec/catalogs/layouts/bullet-list.json +9 -15
  180. package/dist/spec/catalogs/layouts/business-model-canvas.json +9 -15
  181. package/dist/spec/catalogs/layouts/capability-map.json +11 -16
  182. package/dist/spec/catalogs/layouts/case-study.json +9 -15
  183. package/dist/spec/catalogs/layouts/chapter-recap.json +8 -15
  184. package/dist/spec/catalogs/layouts/chart-1x-title-center.json +30 -0
  185. package/dist/spec/catalogs/layouts/chart-1x.json +15 -0
  186. package/dist/spec/catalogs/layouts/chart-2x-title-center.json +36 -0
  187. package/dist/spec/catalogs/layouts/chart-2x-vertical-title-left.json +37 -0
  188. package/dist/spec/catalogs/layouts/chart-2x.json +15 -0
  189. package/dist/spec/catalogs/layouts/chart-3x-bottom-vertical-title-left.json +46 -0
  190. package/dist/spec/catalogs/layouts/chart-3x-left-title-center.json +45 -0
  191. package/dist/spec/catalogs/layouts/chart-3x-left.json +40 -0
  192. package/dist/spec/catalogs/layouts/chart-3x-right-title-center.json +45 -0
  193. package/dist/spec/catalogs/layouts/chart-3x-right.json +40 -0
  194. package/dist/spec/catalogs/layouts/chart-3x-title-center.json +39 -0
  195. package/dist/spec/catalogs/layouts/chart-3x-top-vertical-title-left.json +46 -0
  196. package/dist/spec/catalogs/layouts/chart-3x.json +15 -0
  197. package/dist/spec/catalogs/layouts/circular-lifecycle.json +9 -15
  198. package/dist/spec/catalogs/layouts/code-1x.json +10 -0
  199. package/dist/spec/catalogs/layouts/comparison.json +9 -15
  200. package/dist/spec/catalogs/layouts/competitive-landscape.json +11 -16
  201. package/dist/spec/catalogs/layouts/customer-journey.json +11 -16
  202. package/dist/spec/catalogs/layouts/customer-logos.json +9 -15
  203. package/dist/spec/catalogs/layouts/dashboard.json +9 -15
  204. package/dist/spec/catalogs/layouts/data-visualization.json +9 -15
  205. package/dist/spec/catalogs/layouts/decision-tree.json +11 -16
  206. package/dist/spec/catalogs/layouts/detailed-data-table.json +9 -15
  207. package/dist/spec/catalogs/layouts/ecosystem-map.json +11 -16
  208. package/dist/spec/catalogs/layouts/executive-decision.json +9 -15
  209. package/dist/spec/catalogs/layouts/executive-summary.json +9 -15
  210. package/dist/spec/catalogs/layouts/extract/canonical.json +7 -16
  211. package/dist/spec/catalogs/layouts/faq.json +9 -15
  212. package/dist/spec/catalogs/layouts/feature-comparison-matrix.json +9 -15
  213. package/dist/spec/catalogs/layouts/forecast-scenario.json +9 -15
  214. package/dist/spec/catalogs/layouts/funnel-pyramid.json +9 -15
  215. package/dist/spec/catalogs/layouts/gantt-project-plan.json +9 -15
  216. package/dist/spec/catalogs/layouts/geographic-map.json +10 -15
  217. package/dist/spec/catalogs/layouts/heatmap-cohort.json +9 -15
  218. package/dist/spec/catalogs/layouts/hub-and-spoke.json +9 -15
  219. package/dist/spec/catalogs/layouts/icon-grid.json +11 -16
  220. package/dist/spec/catalogs/layouts/image-1x-crop-title-center.json +32 -0
  221. package/dist/spec/catalogs/layouts/image-1x-crop-title-left.json +32 -0
  222. package/dist/spec/catalogs/layouts/image-1x-crop.json +27 -0
  223. package/dist/spec/catalogs/layouts/image-1x-fit-title-center.json +32 -0
  224. package/dist/spec/catalogs/layouts/image-1x.json +14 -1
  225. package/dist/spec/catalogs/layouts/image-2x-crop-title-center.json +38 -0
  226. package/dist/spec/catalogs/layouts/image-2x-crop-vertical-title-left.json +39 -0
  227. package/dist/spec/catalogs/layouts/image-2x-crop-vertical.json +34 -0
  228. package/dist/spec/catalogs/layouts/image-2x-crop.json +33 -0
  229. package/dist/spec/catalogs/layouts/image-2x-fit-title-center.json +38 -0
  230. package/dist/spec/catalogs/layouts/image-2x-fit-vertical-title-left.json +39 -0
  231. package/dist/spec/catalogs/layouts/image-2x-fit-vertical.json +34 -0
  232. package/dist/spec/catalogs/layouts/image-2x.json +15 -2
  233. package/dist/spec/catalogs/layouts/image-3x-crop-title-center.json +41 -0
  234. package/dist/spec/catalogs/layouts/image-3x-crop-vertical-title-left.json +42 -0
  235. package/dist/spec/catalogs/layouts/image-3x-crop-vertical.json +37 -0
  236. package/dist/spec/catalogs/layouts/image-3x-crop.json +36 -0
  237. package/dist/spec/catalogs/layouts/image-3x-fit-title-center.json +41 -0
  238. package/dist/spec/catalogs/layouts/image-3x-fit-vertical-title-left.json +42 -0
  239. package/dist/spec/catalogs/layouts/image-3x-fit-vertical.json +37 -0
  240. package/dist/spec/catalogs/layouts/image-3x-fit.json +36 -0
  241. package/dist/spec/catalogs/layouts/image-3x.json +16 -3
  242. package/dist/spec/catalogs/layouts/image-focus.json +13 -18
  243. package/dist/spec/catalogs/layouts/image-only-1x-crop-title-center.json +31 -0
  244. package/dist/spec/catalogs/layouts/image-only-1x-fit-title-center.json +31 -0
  245. package/dist/spec/catalogs/layouts/image-only-2x-crop-title-center.json +37 -0
  246. package/dist/spec/catalogs/layouts/image-only-2x-crop-vertical-title-left.json +38 -0
  247. package/dist/spec/catalogs/layouts/image-only-2x-crop-vertical.json +33 -0
  248. package/dist/spec/catalogs/layouts/image-only-2x-fit-title-center.json +37 -0
  249. package/dist/spec/catalogs/layouts/image-only-2x-fit-vertical-title-left.json +38 -0
  250. package/dist/spec/catalogs/layouts/image-only-2x-fit-vertical.json +33 -0
  251. package/dist/spec/catalogs/layouts/image-only-3x-crop-title-center.json +40 -0
  252. package/dist/spec/catalogs/layouts/image-only-3x-crop-vertical-title-left.json +41 -0
  253. package/dist/spec/catalogs/layouts/image-only-3x-crop-vertical.json +36 -0
  254. package/dist/spec/catalogs/layouts/image-only-3x-crop.json +35 -0
  255. package/dist/spec/catalogs/layouts/image-only-3x-fit-title-center.json +40 -0
  256. package/dist/spec/catalogs/layouts/image-only-3x-fit-vertical-title-left.json +41 -0
  257. package/dist/spec/catalogs/layouts/image-only-3x-fit-vertical.json +36 -0
  258. package/dist/spec/catalogs/layouts/image-only-3x-fit.json +35 -0
  259. package/dist/spec/catalogs/layouts/index.json +1041 -151
  260. package/dist/spec/catalogs/layouts/key-takeaway.json +8 -15
  261. package/dist/spec/catalogs/layouts/kpi-scorecard.json +9 -15
  262. package/dist/spec/catalogs/layouts/list-1x-box-title-center.json +32 -0
  263. package/dist/spec/catalogs/layouts/list-1x-box-vertical-title-center.json +33 -0
  264. package/dist/spec/catalogs/layouts/list-1x-box-vertical-title-left.json +33 -0
  265. package/dist/spec/catalogs/layouts/list-1x-box-vertical.json +28 -0
  266. package/dist/spec/catalogs/layouts/list-1x-box.json +27 -0
  267. package/dist/spec/catalogs/layouts/list-1x-itemimage-title-center.json +32 -0
  268. package/dist/spec/catalogs/layouts/list-1x-itemimage-vertical-title-center.json +33 -0
  269. package/dist/spec/catalogs/layouts/list-1x-title-center.json +31 -0
  270. package/dist/spec/catalogs/layouts/list-1x-vertical-title-center.json +32 -0
  271. package/dist/spec/catalogs/layouts/list-1x.json +17 -1
  272. package/dist/spec/catalogs/layouts/list-2x-box-title-center.json +38 -0
  273. package/dist/spec/catalogs/layouts/list-2x-box-vertical-title-center.json +39 -0
  274. package/dist/spec/catalogs/layouts/list-2x-box-vertical-title-left.json +39 -0
  275. package/dist/spec/catalogs/layouts/list-2x-box-vertical.json +34 -0
  276. package/dist/spec/catalogs/layouts/list-2x-box.json +33 -0
  277. package/dist/spec/catalogs/layouts/list-2x-itemimage-title-center.json +38 -0
  278. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical-title-center.json +39 -0
  279. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical-title-left.json +39 -0
  280. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical.json +34 -0
  281. package/dist/spec/catalogs/layouts/list-2x-title-center.json +37 -0
  282. package/dist/spec/catalogs/layouts/list-2x-vertical-title-center.json +38 -0
  283. package/dist/spec/catalogs/layouts/list-2x-vertical-title-left.json +38 -0
  284. package/dist/spec/catalogs/layouts/list-2x-vertical.json +33 -0
  285. package/dist/spec/catalogs/layouts/list-2x.json +16 -0
  286. package/dist/spec/catalogs/layouts/list-3x-box-title-center.json +41 -0
  287. package/dist/spec/catalogs/layouts/list-3x-box-vertical-title-center.json +42 -0
  288. package/dist/spec/catalogs/layouts/list-3x-box-vertical-title-left.json +42 -0
  289. package/dist/spec/catalogs/layouts/list-3x-box-vertical.json +37 -0
  290. package/dist/spec/catalogs/layouts/list-3x-box.json +36 -0
  291. package/dist/spec/catalogs/layouts/list-3x-itemimage-title-center.json +41 -0
  292. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical-title-center.json +42 -0
  293. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical-title-left.json +42 -0
  294. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical.json +37 -0
  295. package/dist/spec/catalogs/layouts/list-3x-itemimage.json +36 -0
  296. package/dist/spec/catalogs/layouts/list-3x-title-center.json +40 -0
  297. package/dist/spec/catalogs/layouts/list-3x-vertical-title-center.json +41 -0
  298. package/dist/spec/catalogs/layouts/list-3x-vertical-title-left.json +41 -0
  299. package/dist/spec/catalogs/layouts/list-3x-vertical.json +36 -0
  300. package/dist/spec/catalogs/layouts/list-3x.json +16 -0
  301. package/dist/spec/catalogs/layouts/list-4x-box-title-center.json +45 -0
  302. package/dist/spec/catalogs/layouts/list-4x-box-vertical-title-center.json +45 -0
  303. package/dist/spec/catalogs/layouts/list-4x-box-vertical-title-left.json +45 -0
  304. package/dist/spec/catalogs/layouts/list-4x-box-vertical.json +40 -0
  305. package/dist/spec/catalogs/layouts/list-4x-box.json +40 -0
  306. package/dist/spec/catalogs/layouts/list-4x-itemimage-title-center.json +45 -0
  307. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical-title-center.json +45 -0
  308. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical-title-left.json +45 -0
  309. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical.json +40 -0
  310. package/dist/spec/catalogs/layouts/list-4x-title-center.json +44 -0
  311. package/dist/spec/catalogs/layouts/list-4x-vertical-title-center.json +44 -0
  312. package/dist/spec/catalogs/layouts/list-4x-vertical-title-left.json +44 -0
  313. package/dist/spec/catalogs/layouts/list-4x-vertical.json +39 -0
  314. package/dist/spec/catalogs/layouts/list-4x.json +16 -0
  315. package/dist/spec/catalogs/layouts/list-5x-box-title-center.json +48 -0
  316. package/dist/spec/catalogs/layouts/list-5x-box-vertical-title-center.json +50 -0
  317. package/dist/spec/catalogs/layouts/list-5x-box-vertical-title-left.json +50 -0
  318. package/dist/spec/catalogs/layouts/list-5x-box-vertical.json +45 -0
  319. package/dist/spec/catalogs/layouts/list-5x-box.json +43 -0
  320. package/dist/spec/catalogs/layouts/list-5x-itemimage-title-center.json +48 -0
  321. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical-title-center.json +48 -0
  322. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical-title-left.json +48 -0
  323. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical.json +43 -0
  324. package/dist/spec/catalogs/layouts/list-5x-title-center.json +47 -0
  325. package/dist/spec/catalogs/layouts/list-5x-vertical-title-center.json +47 -0
  326. package/dist/spec/catalogs/layouts/list-5x-vertical-title-left.json +47 -0
  327. package/dist/spec/catalogs/layouts/list-5x-vertical.json +42 -0
  328. package/dist/spec/catalogs/layouts/list-5x.json +16 -0
  329. package/dist/spec/catalogs/layouts/list-6x-box-title-center.json +51 -0
  330. package/dist/spec/catalogs/layouts/list-6x-box-vertical-title-center.json +53 -0
  331. package/dist/spec/catalogs/layouts/list-6x-box-vertical-title-left.json +53 -0
  332. package/dist/spec/catalogs/layouts/list-6x-box-vertical.json +48 -0
  333. package/dist/spec/catalogs/layouts/list-6x-box.json +46 -0
  334. package/dist/spec/catalogs/layouts/list-6x-itemimage-title-center.json +51 -0
  335. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical-title-center.json +51 -0
  336. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical-title-left.json +51 -0
  337. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical.json +46 -0
  338. package/dist/spec/catalogs/layouts/list-6x-title-center.json +50 -0
  339. package/dist/spec/catalogs/layouts/list-6x-vertical-title-center.json +50 -0
  340. package/dist/spec/catalogs/layouts/list-6x-vertical-title-left.json +50 -0
  341. package/dist/spec/catalogs/layouts/list-6x-vertical.json +45 -0
  342. package/dist/spec/catalogs/layouts/list-6x.json +16 -0
  343. package/dist/spec/catalogs/layouts/logic-tree.json +9 -15
  344. package/dist/spec/catalogs/layouts/market-size.json +9 -15
  345. package/dist/spec/catalogs/layouts/matrix-quadrant.json +9 -15
  346. package/dist/spec/catalogs/layouts/media-1x.json +11 -1
  347. package/dist/spec/catalogs/layouts/network-dependency-map.json +10 -15
  348. package/dist/spec/catalogs/layouts/number-1x-box-title-center.json +30 -0
  349. package/dist/spec/catalogs/layouts/number-1x-box.json +25 -0
  350. package/dist/spec/catalogs/layouts/number-1x-title-center.json +29 -0
  351. package/dist/spec/catalogs/layouts/number-1x.json +16 -1
  352. package/dist/spec/catalogs/layouts/number-2x-box-title-center.json +36 -0
  353. package/dist/spec/catalogs/layouts/number-2x-box.json +31 -0
  354. package/dist/spec/catalogs/layouts/number-2x-title-center.json +35 -0
  355. package/dist/spec/catalogs/layouts/number-2x.json +15 -0
  356. package/dist/spec/catalogs/layouts/number-3x-box-title-center.json +39 -0
  357. package/dist/spec/catalogs/layouts/number-3x-box.json +34 -0
  358. package/dist/spec/catalogs/layouts/number-3x-title-center.json +38 -0
  359. package/dist/spec/catalogs/layouts/number-3x.json +15 -0
  360. package/dist/spec/catalogs/layouts/number-4x-box-title-center.json +43 -0
  361. package/dist/spec/catalogs/layouts/number-4x-box.json +38 -0
  362. package/dist/spec/catalogs/layouts/number-4x-title-center.json +42 -0
  363. package/dist/spec/catalogs/layouts/number-4x.json +15 -0
  364. package/dist/spec/catalogs/layouts/number-5x-box-title-center.json +46 -0
  365. package/dist/spec/catalogs/layouts/number-5x-box.json +41 -0
  366. package/dist/spec/catalogs/layouts/number-5x-title-center.json +45 -0
  367. package/dist/spec/catalogs/layouts/number-5x.json +15 -0
  368. package/dist/spec/catalogs/layouts/number-6x-box-title-center.json +49 -0
  369. package/dist/spec/catalogs/layouts/number-6x-box.json +44 -0
  370. package/dist/spec/catalogs/layouts/number-6x-title-center.json +48 -0
  371. package/dist/spec/catalogs/layouts/number-6x.json +15 -0
  372. package/dist/spec/catalogs/layouts/one-column-explainer.json +9 -15
  373. package/dist/spec/catalogs/layouts/org-chart.json +9 -15
  374. package/dist/spec/catalogs/layouts/persona-grid.json +11 -16
  375. package/dist/spec/catalogs/layouts/photo-grid.json +14 -19
  376. package/dist/spec/catalogs/layouts/pricing-table.json +9 -15
  377. package/dist/spec/catalogs/layouts/process-flow.json +9 -15
  378. package/dist/spec/catalogs/layouts/product-feature.json +11 -16
  379. package/dist/spec/catalogs/layouts/pros-cons.json +9 -15
  380. package/dist/spec/catalogs/layouts/qa-discussion.json +7 -15
  381. package/dist/spec/catalogs/layouts/quote-1x.json +11 -1
  382. package/dist/spec/catalogs/layouts/quote-highlight.json +9 -15
  383. package/dist/spec/catalogs/layouts/raci-matrix.json +9 -15
  384. package/dist/spec/catalogs/layouts/risk-heatmap.json +9 -15
  385. package/dist/spec/catalogs/layouts/roadmap.json +9 -15
  386. package/dist/spec/catalogs/layouts/screenshot-walkthrough.json +11 -16
  387. package/dist/spec/catalogs/layouts/section-divider.json +8 -15
  388. package/dist/spec/catalogs/layouts/single-message-statement.json +8 -15
  389. package/dist/spec/catalogs/layouts/stats-metrics.json +9 -15
  390. package/dist/spec/catalogs/layouts/status-rag.json +9 -15
  391. package/dist/spec/catalogs/layouts/swimlane-process.json +11 -16
  392. package/dist/spec/catalogs/layouts/swot-analysis.json +9 -15
  393. package/dist/spec/catalogs/layouts/table-1x.json +10 -0
  394. package/dist/spec/catalogs/layouts/team-bio.json +11 -16
  395. package/dist/spec/catalogs/layouts/testimonial-grid.json +9 -15
  396. package/dist/spec/catalogs/layouts/text-1x-box-title-center.json +31 -0
  397. package/dist/spec/catalogs/layouts/text-1x-box-title-left.json +31 -0
  398. package/dist/spec/catalogs/layouts/text-1x-center-box-title-center.json +31 -0
  399. package/dist/spec/catalogs/layouts/text-1x-center-box-title-left.json +31 -0
  400. package/dist/spec/catalogs/layouts/text-1x-center-box.json +26 -0
  401. package/dist/spec/catalogs/layouts/text-1x-center-title-center.json +30 -0
  402. package/dist/spec/catalogs/layouts/text-1x-center-title-left.json +30 -0
  403. package/dist/spec/catalogs/layouts/text-1x-center.json +25 -0
  404. package/dist/spec/catalogs/layouts/text-1x-left-box.json +26 -0
  405. package/dist/spec/catalogs/layouts/text-1x-title-center.json +30 -0
  406. package/dist/spec/catalogs/layouts/text-1x.json +11 -1
  407. package/dist/spec/catalogs/layouts/text-2x-box-title-center.json +37 -0
  408. package/dist/spec/catalogs/layouts/text-2x-box-vertical-title-left.json +37 -0
  409. package/dist/spec/catalogs/layouts/text-2x-center-box-title-center.json +37 -0
  410. package/dist/spec/catalogs/layouts/text-2x-center-box-vertical-title-left.json +37 -0
  411. package/dist/spec/catalogs/layouts/text-2x-center-box.json +32 -0
  412. package/dist/spec/catalogs/layouts/text-2x-center-title-center.json +36 -0
  413. package/dist/spec/catalogs/layouts/text-2x-center-vertical-title-left.json +36 -0
  414. package/dist/spec/catalogs/layouts/text-2x-center.json +31 -0
  415. package/dist/spec/catalogs/layouts/text-2x-left-box.json +32 -0
  416. package/dist/spec/catalogs/layouts/text-2x-title-center.json +36 -0
  417. package/dist/spec/catalogs/layouts/text-2x-vertical-title-left.json +36 -0
  418. package/dist/spec/catalogs/layouts/text-2x.json +10 -0
  419. package/dist/spec/catalogs/layouts/text-3x-box-title-center.json +40 -0
  420. package/dist/spec/catalogs/layouts/text-3x-box-vertical-title-left.json +41 -0
  421. package/dist/spec/catalogs/layouts/text-3x-center-box-title-center.json +40 -0
  422. package/dist/spec/catalogs/layouts/text-3x-center-box-vertical-title-left.json +41 -0
  423. package/dist/spec/catalogs/layouts/text-3x-center-box.json +35 -0
  424. package/dist/spec/catalogs/layouts/text-3x-center-title-center.json +39 -0
  425. package/dist/spec/catalogs/layouts/text-3x-center-vertical-title-left.json +40 -0
  426. package/dist/spec/catalogs/layouts/text-3x-center.json +34 -0
  427. package/dist/spec/catalogs/layouts/text-3x-left-box.json +35 -0
  428. package/dist/spec/catalogs/layouts/text-3x-left.json +34 -0
  429. package/dist/spec/catalogs/layouts/text-3x-title-center.json +39 -0
  430. package/dist/spec/catalogs/layouts/text-3x-vertical-title-left.json +40 -0
  431. package/dist/spec/catalogs/layouts/text-3x.json +10 -0
  432. package/dist/spec/catalogs/layouts/thank-you-cta.json +8 -15
  433. package/dist/spec/catalogs/layouts/three-column.json +9 -15
  434. package/dist/spec/catalogs/layouts/timeline-1x.json +11 -1
  435. package/dist/spec/catalogs/layouts/timeline.json +9 -15
  436. package/dist/spec/catalogs/layouts/title-center-box.json +27 -0
  437. package/dist/spec/catalogs/layouts/title-center-image-bottom.json +34 -0
  438. package/dist/spec/catalogs/layouts/title-center-image-top.json +34 -0
  439. package/dist/spec/catalogs/layouts/title-center.json +26 -0
  440. package/dist/spec/catalogs/layouts/title-left-image-bottom.json +34 -0
  441. package/dist/spec/catalogs/layouts/title-left-image-left.json +34 -0
  442. package/dist/spec/catalogs/layouts/title-left-image-right.json +34 -0
  443. package/dist/spec/catalogs/layouts/title-left-image-top.json +34 -0
  444. package/dist/spec/catalogs/layouts/title-slide.json +8 -15
  445. package/dist/spec/catalogs/layouts/title-subtitle.json +11 -1
  446. package/dist/spec/catalogs/layouts/title.json +11 -1
  447. package/dist/spec/catalogs/layouts/two-column.json +9 -15
  448. package/dist/spec/catalogs/layouts/venn-overlap.json +9 -15
  449. package/dist/spec/catalogs/layouts/waterfall-bridge.json +9 -15
  450. package/dist/spec/catalogs/layouts/wheel-radial.json +9 -15
  451. package/dist/spec/catalogs/manifest.json +22 -22
  452. package/dist/spec/catalogs/narratives/board-meeting.json +45 -45
  453. package/dist/spec/catalogs/narratives/business-narrative.json +19 -19
  454. package/dist/spec/catalogs/narratives/business-review.json +27 -27
  455. package/dist/spec/catalogs/narratives/capacity-planning.json +19 -19
  456. package/dist/spec/catalogs/narratives/challenge-resolution.json +17 -17
  457. package/dist/spec/catalogs/narratives/change-story.json +13 -13
  458. package/dist/spec/catalogs/narratives/classic-story.json +17 -17
  459. package/dist/spec/catalogs/narratives/company-intro.json +21 -21
  460. package/dist/spec/catalogs/narratives/conference-talk.json +4 -4
  461. package/dist/spec/catalogs/narratives/data-story.json +13 -14
  462. package/dist/spec/catalogs/narratives/early-startup-pitch.json +27 -27
  463. package/dist/spec/catalogs/narratives/educate.json +21 -21
  464. package/dist/spec/catalogs/narratives/employee-review.json +19 -19
  465. package/dist/spec/catalogs/narratives/failure-analysis.json +23 -23
  466. package/dist/spec/catalogs/narratives/focus.json +27 -27
  467. package/dist/spec/catalogs/narratives/golden-circle.json +4 -4
  468. package/dist/spec/catalogs/narratives/heros-journey.json +13 -13
  469. package/dist/spec/catalogs/narratives/index.json +145 -145
  470. package/dist/spec/catalogs/narratives/innovation.json +21 -21
  471. package/dist/spec/catalogs/narratives/justice.json +25 -25
  472. package/dist/spec/catalogs/narratives/marketing-strategy.json +25 -25
  473. package/dist/spec/catalogs/narratives/performance-improvement-plan.json +19 -19
  474. package/dist/spec/catalogs/narratives/performance-review.json +25 -25
  475. package/dist/spec/catalogs/narratives/persuade.json +17 -17
  476. package/dist/spec/catalogs/narratives/persuasive-sales.json +19 -19
  477. package/dist/spec/catalogs/narratives/pitch-deck.json +6 -6
  478. package/dist/spec/catalogs/narratives/problem-solution.json +5 -5
  479. package/dist/spec/catalogs/narratives/product-launch.json +23 -23
  480. package/dist/spec/catalogs/narratives/project-proposal.json +23 -23
  481. package/dist/spec/catalogs/narratives/pyramid-principle.json +9 -9
  482. package/dist/spec/catalogs/narratives/qbr.json +8 -8
  483. package/dist/spec/catalogs/narratives/rags-to-riches.json +17 -17
  484. package/dist/spec/catalogs/narratives/reveal.json +19 -19
  485. package/dist/spec/catalogs/narratives/scqa.json +4 -4
  486. package/dist/spec/catalogs/narratives/situation-complication-resolution.json +11 -11
  487. package/dist/spec/catalogs/narratives/sparkline.json +11 -11
  488. package/dist/spec/catalogs/narratives/star-method.json +11 -11
  489. package/dist/spec/catalogs/narratives/status-update.json +15 -15
  490. package/dist/spec/catalogs/narratives/strategic-advisory.json +17 -17
  491. package/dist/spec/catalogs/narratives/strategic-narrative.json +4 -4
  492. package/dist/spec/catalogs/narratives/survey-analysis.json +23 -23
  493. package/dist/spec/catalogs/narratives/survival-story.json +23 -23
  494. package/dist/spec/catalogs/narratives/transformation-arc.json +4 -4
  495. package/dist/spec/catalogs/narratives/trend-analysis.json +17 -17
  496. package/dist/spec/catalogs/narratives/underdog-victory.json +19 -19
  497. package/dist/spec/catalogs/narratives/venture-pitch.json +27 -27
  498. package/dist/spec/catalogs/narratives/vision-roadmap.json +13 -13
  499. package/dist/spec/catalogs/narratives/weekly-progress.json +23 -23
  500. package/dist/spec/catalogs/narratives/what-so-what-now-what.json +9 -9
  501. package/dist/spec/openapi.yaml +4 -7
  502. package/dist/spec/reference/engine-defaults.json +22 -30
  503. package/dist/spec/reference/engine-vocabularies.json +1577 -0
  504. package/dist/spec/schemas/audience.schema.json +6 -27
  505. package/dist/spec/schemas/catalog-index.schema.json +2 -2
  506. package/dist/spec/schemas/catalog-manifest.schema.json +3 -3
  507. package/dist/spec/schemas/chart-type.schema.json +17 -321
  508. package/dist/spec/schemas/color-scheme.schema.json +23 -36
  509. package/dist/spec/schemas/finding.schema.json +191 -0
  510. package/dist/spec/schemas/font-scheme.schema.json +17 -75
  511. package/dist/spec/schemas/language.schema.json +7 -28
  512. package/dist/spec/schemas/layout.schema.json +130 -184
  513. package/dist/spec/schemas/narrative.schema.json +20 -48
  514. package/dist/spec/schemas/opf.schema.json +678 -701
  515. package/dist/spec/schemas/purpose.schema.json +5 -26
  516. package/dist/spec/schemas/social-platform.schema.json +2 -48
  517. package/dist/spec/schemas/theme.schema.json +13 -38
  518. package/dist/spec/schemas/tone.schema.json +4 -25
  519. package/dist/spec-files.d.ts +1 -1
  520. package/dist/spec-files.js +1 -1
  521. package/dist/symbol-font-encodings.js +18448 -1
  522. package/dist/types.d.ts +1125 -4
  523. package/dist/validation-types-BOcY9GTs.d.ts +276 -0
  524. package/dist/validator.d.ts +63 -4
  525. package/dist/validator.js +5 -5
  526. package/dist/yaml.d.ts +102 -0
  527. package/dist/yaml.js +322 -0
  528. package/package.json +9 -17
  529. package/dist/audit.d.ts +0 -35
  530. package/dist/audit.js +0 -7
  531. package/dist/catalogs-ywCamd8C.d.ts +0 -1465
  532. package/dist/catalogs.d.ts +0 -2
  533. package/dist/catalogs.js +0 -2
  534. package/dist/chunk-7N4VMAT4.js +0 -1694
  535. package/dist/chunk-FYLJVF7X.js +0 -18448
  536. package/dist/chunk-INU7ZNSB.js +0 -670
  537. package/dist/chunk-IYCJUKWD.js +0 -951
  538. package/dist/chunk-PIQXLBBJ.js +0 -445
  539. package/dist/chunk-S5W34SIJ.js +0 -1
  540. package/dist/lint-B7azdiuE.d.ts +0 -197
  541. package/dist/lint.d.ts +0 -7
  542. package/dist/lint.js +0 -6
  543. package/dist/previews.d.ts +0 -40
  544. package/dist/previews.js +0 -1
  545. package/dist/schemas-BbPonsTz.d.ts +0 -270
  546. package/dist/spec/catalogs/audiences/customers.json +0 -27
  547. package/dist/spec/catalogs/audiences/executives.json +0 -27
  548. package/dist/spec/catalogs/audiences/investors.json +0 -27
  549. package/dist/spec/catalogs/audiences/marketing-team.json +0 -27
  550. package/dist/spec/catalogs/audiences/regulators.json +0 -27
  551. package/dist/spec/catalogs/audiences/sales-team.json +0 -27
  552. package/dist/spec/catalogs/chart-types/100pct-bullet-bar-2x.json +0 -91
  553. package/dist/spec/catalogs/chart-types/100pct-bullet-bar-3x.json +0 -103
  554. package/dist/spec/catalogs/chart-types/100pct-bullet-bar.json +0 -79
  555. package/dist/spec/catalogs/chart-types/100pct-bullet-column-2x.json +0 -91
  556. package/dist/spec/catalogs/chart-types/100pct-bullet-column-3x.json +0 -103
  557. package/dist/spec/catalogs/chart-types/100pct-bullet-column.json +0 -79
  558. package/dist/spec/catalogs/chart-types/100pct-progress-bar.json +0 -105
  559. package/dist/spec/catalogs/chart-types/100pct-stacked-area-2x.json +0 -106
  560. package/dist/spec/catalogs/chart-types/100pct-stacked-area-3x.json +0 -123
  561. package/dist/spec/catalogs/chart-types/100pct-stacked-bar-2x.json +0 -89
  562. package/dist/spec/catalogs/chart-types/100pct-stacked-bar-3x.json +0 -100
  563. package/dist/spec/catalogs/chart-types/100pct-stacked-column-2x.json +0 -95
  564. package/dist/spec/catalogs/chart-types/100pct-stacked-column-3x.json +0 -108
  565. package/dist/spec/catalogs/chart-types/australia.json +0 -76
  566. package/dist/spec/catalogs/chart-types/box-and-whisker-2x.json +0 -136
  567. package/dist/spec/catalogs/chart-types/box-and-whisker-3x.json +0 -168
  568. package/dist/spec/catalogs/chart-types/bullet-bar-2x.json +0 -89
  569. package/dist/spec/catalogs/chart-types/bullet-bar-3x.json +0 -101
  570. package/dist/spec/catalogs/chart-types/bullet-bar.json +0 -77
  571. package/dist/spec/catalogs/chart-types/bullet-column-2x.json +0 -89
  572. package/dist/spec/catalogs/chart-types/bullet-column-3x.json +0 -101
  573. package/dist/spec/catalogs/chart-types/bullet-column.json +0 -77
  574. package/dist/spec/catalogs/chart-types/canada.json +0 -86
  575. package/dist/spec/catalogs/chart-types/clustered-bar-2x.json +0 -89
  576. package/dist/spec/catalogs/chart-types/clustered-column.json +0 -95
  577. package/dist/spec/catalogs/chart-types/dot-plot-2x.json +0 -99
  578. package/dist/spec/catalogs/chart-types/dot-plot-3x.json +0 -124
  579. package/dist/spec/catalogs/chart-types/dot-plot-4x.json +0 -149
  580. package/dist/spec/catalogs/chart-types/dot-plot-5x.json +0 -174
  581. package/dist/spec/catalogs/chart-types/dot-plot-6x.json +0 -199
  582. package/dist/spec/catalogs/chart-types/dot-plot.json +0 -74
  583. package/dist/spec/catalogs/chart-types/dumbbell.json +0 -120
  584. package/dist/spec/catalogs/chart-types/line-2x.json +0 -105
  585. package/dist/spec/catalogs/chart-types/line-3x.json +0 -127
  586. package/dist/spec/catalogs/chart-types/line-with-high-low-and-markers.json +0 -144
  587. package/dist/spec/catalogs/chart-types/line-with-high-low.json +0 -144
  588. package/dist/spec/catalogs/chart-types/line-with-markers-2x.json +0 -106
  589. package/dist/spec/catalogs/chart-types/line-with-markers-3x.json +0 -128
  590. package/dist/spec/catalogs/chart-types/sparkline-2x.json +0 -138
  591. package/dist/spec/catalogs/chart-types/sparkline-3x.json +0 -174
  592. package/dist/spec/catalogs/chart-types/sparkline-4x.json +0 -210
  593. package/dist/spec/catalogs/chart-types/sparkline-5x.json +0 -246
  594. package/dist/spec/catalogs/chart-types/sparkline-6x.json +0 -282
  595. package/dist/spec/catalogs/chart-types/sparkline.json +0 -102
  596. package/dist/spec/catalogs/chart-types/stacked-area-2x.json +0 -106
  597. package/dist/spec/catalogs/chart-types/stacked-area-3x.json +0 -123
  598. package/dist/spec/catalogs/chart-types/stacked-bar-2x.json +0 -89
  599. package/dist/spec/catalogs/chart-types/stacked-bar-3x.json +0 -100
  600. package/dist/spec/catalogs/chart-types/stacked-column-2x.json +0 -95
  601. package/dist/spec/catalogs/chart-types/stacked-column-3x.json +0 -108
  602. package/dist/spec/catalogs/chart-types/stacked-line-2x.json +0 -106
  603. package/dist/spec/catalogs/chart-types/stacked-line-3x.json +0 -123
  604. package/dist/spec/catalogs/chart-types/stacked-line-with-markers-2x.json +0 -107
  605. package/dist/spec/catalogs/chart-types/stacked-line-with-markers-3x.json +0 -124
  606. package/dist/spec/catalogs/chart-types/treemap-2x.json +0 -101
  607. package/dist/spec/catalogs/chart-types/treemap-3x.json +0 -122
  608. package/dist/spec/catalogs/chart-types/united-kingdom.json +0 -68
  609. package/dist/spec/catalogs/chart-types/united-states.json +0 -82
  610. package/dist/spec/catalogs/layouts/image-bleed.json +0 -10
  611. package/dist/validator-CIylxoIm.d.ts +0 -172
@@ -1,4 +1,4 @@
1
- import { catalogs } from './chunk-E34DJ5LL.js';
1
+ import { checkCatalogsOption, resolveReference, unresolvedReference, provenanceOf } from './chunk-SPFV27O5.js';
2
2
 
3
3
  // src/table.ts
4
4
  var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
@@ -7,7 +7,7 @@ function tableGrid(value, path = "table") {
7
7
  const values = [...hasHeaders ? [table.columns] : [], ...Array.isArray(table.rows) ? table.rows : []];
8
8
  const columnCount = values.reduce((count, row) => Math.max(count, Array.isArray(row) ? row.length : 0), 1), rowCount = values.length;
9
9
  const owners = Array.from({ length: rowCount }, () => Array(columnCount));
10
- const rows2 = Array.from({ length: rowCount }, () => []), issues = [];
10
+ const rows3 = Array.from({ length: rowCount }, () => []), issues = [];
11
11
  const location = (r, c) => `${path}.${hasHeaders && r === 0 ? "columns" : `rows.${r - Number(hasHeaders)}`}.${c}`;
12
12
  for (let r = 0; r < rowCount; r++) for (let c = 0; c < columnCount; c++) {
13
13
  const input = values[r]?.[c], cellPath = location(r, c), existing = owners[r][c];
@@ -15,21 +15,21 @@ function tableGrid(value, path = "table") {
15
15
  if (input !== null) issues.push({ path: cellPath, message: "A position covered by a spanning cell must explicitly contain null; content cannot be hidden." });
16
16
  continue;
17
17
  }
18
- const object = record(input), styled = Object.hasOwn(object, "value");
19
- const column = !styled && hasHeaders && r === 0 && typeof object.name === "string";
20
- const rowSpan = styled ? object.rowSpan ?? 1 : 1, colSpan = styled ? object.colSpan ?? 1 : 1;
18
+ const object2 = record(input), styled = Object.hasOwn(object2, "value");
19
+ const column = !styled && hasHeaders && r === 0 && typeof object2.name === "string";
20
+ const rowSpan = styled ? object2.rowSpan ?? 1 : 1, colSpan = styled ? object2.colSpan ?? 1 : 1;
21
21
  if (!Number.isSafeInteger(rowSpan) || !Number.isSafeInteger(colSpan) || rowSpan < 1 || colSpan < 1 || r + rowSpan > rowCount || c + colSpan > columnCount || hasHeaders && r === 0 && rowSpan > 1) {
22
22
  issues.push({ path: cellPath, message: "Cell spans must be positive integers within the table grid and cannot cross from headers into body rows." });
23
23
  continue;
24
24
  }
25
- const cell = { input, value: styled ? object.value : column ? object.name : input, style: styled ? record(object.style) : {}, row: r, column: c, rowSpan, colSpan, header: hasHeaders && r === 0, path: cellPath, valuePath: styled ? cellPath + ".value" : column ? cellPath + ".name" : cellPath };
26
- rows2[r].push(cell);
25
+ const cell = { input, value: styled ? object2.value : column ? object2.name : input, style: styled ? record(object2.style) : {}, row: r, column: c, rowSpan, colSpan, header: hasHeaders && r === 0, path: cellPath, valuePath: styled ? cellPath + ".value" : column ? cellPath + ".name" : cellPath };
26
+ rows3[r].push(cell);
27
27
  for (let y = r; y < r + rowSpan; y++) for (let x = c; x < c + colSpan; x++) {
28
28
  if (owners[y][x]) issues.push({ path: cellPath, message: "Cell spans cannot overlap another spanning cell." });
29
29
  else owners[y][x] = cell;
30
30
  }
31
31
  }
32
- return { rows: rows2, columnCount, rowCount, hasHeaders, owners, issues };
32
+ return { rows: rows3, columnCount, rowCount, hasHeaders, owners, issues };
33
33
  }
34
34
  function tableRowBoundaries(value) {
35
35
  const grid = tableGrid(value), offset = Number(grid.hasHeaders), count = grid.rowCount - offset;
@@ -38,562 +38,6 @@ function tableRowBoundaries(value) {
38
38
  return [...allowed];
39
39
  }
40
40
 
41
- // src/generated/catalog-ids.ts
42
- var catalogIds = {
43
- audiences: [
44
- "executives",
45
- "board",
46
- "engineering-team",
47
- "investors",
48
- "customers",
49
- "sales-team",
50
- "marketing-team",
51
- "all-hands",
52
- "candidates",
53
- "regulators",
54
- "executive",
55
- "investor",
56
- "technical",
57
- "sales",
58
- "marketing",
59
- "academic",
60
- "internal-team",
61
- "customer",
62
- "general-public",
63
- "media",
64
- "partner",
65
- "regulatory"
66
- ],
67
- purposes: [
68
- "inform",
69
- "decide",
70
- "align",
71
- "persuade",
72
- "educate",
73
- "report",
74
- "pitch",
75
- "sell",
76
- "plan"
77
- ],
78
- tones: [
79
- "formal",
80
- "casual",
81
- "inspirational",
82
- "technical",
83
- "persuasive",
84
- "authoritative",
85
- "conversational"
86
- ],
87
- themes: [
88
- "minimal",
89
- "classic",
90
- "dark",
91
- "bold"
92
- ],
93
- layouts: [
94
- "blank",
95
- "chart-1x",
96
- "chart-2x",
97
- "chart-3x",
98
- "code-1x",
99
- "image-1x",
100
- "image-2x",
101
- "image-3x",
102
- "image-bleed",
103
- "list-1x",
104
- "list-2x",
105
- "list-3x",
106
- "list-4x",
107
- "list-5x",
108
- "list-6x",
109
- "media-1x",
110
- "number-1x",
111
- "number-2x",
112
- "number-3x",
113
- "number-4x",
114
- "number-5x",
115
- "number-6x",
116
- "quote-1x",
117
- "table-1x",
118
- "text-1x",
119
- "text-2x",
120
- "text-3x",
121
- "timeline-1x",
122
- "title",
123
- "title-subtitle",
124
- "title-slide",
125
- "two-column",
126
- "image-focus",
127
- "data-visualization",
128
- "quote-highlight",
129
- "section-divider",
130
- "agenda",
131
- "thank-you-cta",
132
- "bullet-list",
133
- "three-column",
134
- "icon-grid",
135
- "faq",
136
- "stats-metrics",
137
- "comparison",
138
- "swot-analysis",
139
- "matrix-quadrant",
140
- "funnel-pyramid",
141
- "timeline",
142
- "process-flow",
143
- "photo-grid",
144
- "before-after",
145
- "testimonial-grid",
146
- "team-bio",
147
- "pricing-table",
148
- "roadmap",
149
- "product-feature",
150
- "executive-summary",
151
- "key-takeaway",
152
- "chapter-recap",
153
- "qa-discussion",
154
- "single-message-statement",
155
- "one-column-explainer",
156
- "case-study",
157
- "pros-cons",
158
- "feature-comparison-matrix",
159
- "venn-overlap",
160
- "decision-tree",
161
- "kpi-scorecard",
162
- "dashboard",
163
- "waterfall-bridge",
164
- "benchmark-target-table",
165
- "heatmap-cohort",
166
- "risk-heatmap",
167
- "forecast-scenario",
168
- "swimlane-process",
169
- "gantt-project-plan",
170
- "circular-lifecycle",
171
- "customer-journey",
172
- "org-chart",
173
- "capability-map",
174
- "logic-tree",
175
- "hub-and-spoke",
176
- "architecture-stack",
177
- "ecosystem-map",
178
- "network-dependency-map",
179
- "wheel-radial",
180
- "geographic-map",
181
- "screenshot-walkthrough",
182
- "market-size",
183
- "persona-grid",
184
- "competitive-landscape",
185
- "business-model-canvas",
186
- "customer-logos",
187
- "executive-decision",
188
- "status-rag",
189
- "raci-matrix",
190
- "action-plan",
191
- "assumptions-dependencies",
192
- "appendix-index",
193
- "detailed-data-table"
194
- ],
195
- chartTypes: [
196
- "100pct-stacked-area-3x",
197
- "100pct-stacked-bar-3x",
198
- "100pct-stacked-column-3x",
199
- "area",
200
- "bar",
201
- "box-and-whisker",
202
- "column",
203
- "doughnut",
204
- "filled-radar",
205
- "funnel",
206
- "histogram",
207
- "line",
208
- "line-with-markers",
209
- "pareto",
210
- "pie",
211
- "radar",
212
- "radar-with-markers",
213
- "scatter",
214
- "stacked-area-3x",
215
- "stacked-bar-3x",
216
- "stacked-column-3x",
217
- "stacked-line-3x",
218
- "stacked-line-with-markers-3x",
219
- "treemap",
220
- "waterfall",
221
- "world",
222
- "100pct-bullet-bar",
223
- "100pct-bullet-bar-2x",
224
- "100pct-bullet-bar-3x",
225
- "100pct-bullet-column",
226
- "100pct-bullet-column-2x",
227
- "100pct-bullet-column-3x",
228
- "100pct-progress-bar",
229
- "100pct-stacked-area-2x",
230
- "100pct-stacked-bar-2x",
231
- "100pct-stacked-column-2x",
232
- "australia",
233
- "box-and-whisker-2x",
234
- "box-and-whisker-3x",
235
- "bullet-bar",
236
- "bullet-bar-2x",
237
- "bullet-bar-3x",
238
- "bullet-column",
239
- "bullet-column-2x",
240
- "bullet-column-3x",
241
- "canada",
242
- "clustered-bar-2x",
243
- "clustered-column",
244
- "dot-plot",
245
- "dot-plot-2x",
246
- "dot-plot-3x",
247
- "dot-plot-4x",
248
- "dot-plot-5x",
249
- "dot-plot-6x",
250
- "dumbbell",
251
- "line-2x",
252
- "line-3x",
253
- "line-with-high-low",
254
- "line-with-high-low-and-markers",
255
- "line-with-markers-2x",
256
- "line-with-markers-3x",
257
- "sparkline",
258
- "sparkline-2x",
259
- "sparkline-3x",
260
- "sparkline-4x",
261
- "sparkline-5x",
262
- "sparkline-6x",
263
- "stacked-area-2x",
264
- "stacked-bar-2x",
265
- "stacked-column-2x",
266
- "stacked-line-2x",
267
- "stacked-line-with-markers-2x",
268
- "treemap-2x",
269
- "treemap-3x",
270
- "united-kingdom",
271
- "united-states"
272
- ],
273
- narratives: [
274
- "problem-solution",
275
- "scqa",
276
- "pyramid-principle",
277
- "situation-complication-resolution",
278
- "what-so-what-now-what",
279
- "strategic-narrative",
280
- "golden-circle",
281
- "conference-talk",
282
- "transformation-arc",
283
- "pitch-deck",
284
- "early-startup-pitch",
285
- "venture-pitch",
286
- "persuasive-sales",
287
- "sparkline",
288
- "company-intro",
289
- "marketing-strategy",
290
- "product-launch",
291
- "strategic-advisory",
292
- "challenge-resolution",
293
- "project-proposal",
294
- "vision-roadmap",
295
- "failure-analysis",
296
- "star-method",
297
- "classic-story",
298
- "heros-journey",
299
- "business-narrative",
300
- "change-story",
301
- "rags-to-riches",
302
- "underdog-victory",
303
- "survival-story",
304
- "educate",
305
- "persuade",
306
- "reveal",
307
- "justice",
308
- "innovation",
309
- "focus",
310
- "qbr",
311
- "business-review",
312
- "board-meeting",
313
- "weekly-progress",
314
- "status-update",
315
- "performance-review",
316
- "survey-analysis",
317
- "trend-analysis",
318
- "data-story",
319
- "employee-review",
320
- "performance-improvement-plan",
321
- "capacity-planning"
322
- ],
323
- socialPlatforms: [
324
- "linkedin",
325
- "x",
326
- "github",
327
- "youtube",
328
- "instagram",
329
- "facebook",
330
- "tiktok",
331
- "threads",
332
- "mastodon",
333
- "bluesky"
334
- ],
335
- languages: [
336
- "afrikaans",
337
- "albanian",
338
- "amharic",
339
- "arabic",
340
- "armenian",
341
- "aymara",
342
- "azerbaijani",
343
- "bengali",
344
- "berber-latin",
345
- "bosnian-latin",
346
- "bulgarian",
347
- "catalan",
348
- "cebuano",
349
- "chinese-simplified",
350
- "chinese-traditional",
351
- "chittagonian",
352
- "croatian",
353
- "czech",
354
- "danish",
355
- "dutch",
356
- "english",
357
- "english-au",
358
- "english-ca",
359
- "english-gb",
360
- "english-in",
361
- "english-us",
362
- "estonian",
363
- "filipino",
364
- "finnish",
365
- "french",
366
- "fulfulde",
367
- "galician",
368
- "georgian",
369
- "german",
370
- "greek",
371
- "gujarati",
372
- "hausa",
373
- "hebrew",
374
- "hindi",
375
- "hungarian",
376
- "igbo",
377
- "indonesian",
378
- "italian",
379
- "japanese",
380
- "kannada",
381
- "kazakh",
382
- "khmer",
383
- "kinyarwanda",
384
- "korean",
385
- "kurmanji",
386
- "latvian",
387
- "lithuanian",
388
- "macedonian",
389
- "malagasy",
390
- "malay",
391
- "malayalam",
392
- "maori",
393
- "marathi",
394
- "mongolian",
395
- "nepali",
396
- "norwegian",
397
- "odia",
398
- "oromo",
399
- "pashto",
400
- "persian",
401
- "polish",
402
- "portuguese",
403
- "punjabi-gurmukhi",
404
- "punjabi-shahmukhi",
405
- "romanian",
406
- "russian",
407
- "serbian-cyrillic",
408
- "serbian-latin",
409
- "shona",
410
- "slovak",
411
- "slovenian",
412
- "somali",
413
- "spanish",
414
- "swahili",
415
- "swedish",
416
- "tagalog",
417
- "tajik",
418
- "tamil",
419
- "telugu",
420
- "thai",
421
- "turkish",
422
- "ukrainian",
423
- "urdu",
424
- "uzbek-latin",
425
- "vietnamese-quoc-ngu",
426
- "xhosa",
427
- "yoruba",
428
- "zulu"
429
- ],
430
- colorSchemes: [
431
- "black-and-white",
432
- "bold-red",
433
- "boost",
434
- "burnt-orange",
435
- "cool-horizon",
436
- "corporate-blue",
437
- "deep-purple",
438
- "forest-green",
439
- "golden-yellow",
440
- "luxury",
441
- "pastel-red",
442
- "slate-gray",
443
- "steel-blue",
444
- "vibes"
445
- ],
446
- fontSchemes: [
447
- "consolas",
448
- "courier-new",
449
- "arial",
450
- "calibri",
451
- "impact",
452
- "lucida-sans",
453
- "segoe-ui",
454
- "segoe-ui-light",
455
- "tahoma",
456
- "trebuchet-ms",
457
- "verdana",
458
- "bookman",
459
- "century-schoolbook",
460
- "constantia",
461
- "garamond",
462
- "rockwell",
463
- "times-new-roman",
464
- "aptos",
465
- "grandview",
466
- "seaford",
467
- "skeena",
468
- "tenorite",
469
- "georgia",
470
- "microsoft-yahei",
471
- "simsun",
472
- "fangsong",
473
- "yu-gothic",
474
- "pmingliu",
475
- "mingliu",
476
- "ms-mincho",
477
- "malgun-gothic",
478
- "batang",
479
- "gungsuh",
480
- "mangal",
481
- "nirmala-ui",
482
- "latha",
483
- "david",
484
- "miriam",
485
- "gisha",
486
- "vrinda",
487
- "shruti",
488
- "tunga",
489
- "kartika",
490
- "kalinga",
491
- "raavi",
492
- "gautami",
493
- "arabic-typesetting",
494
- "microsoft-jhenghei",
495
- "meiryo",
496
- "angsana-new",
497
- "aparajita",
498
- "dilleniaupc",
499
- "sakkal-majalla",
500
- "shonar-bangla",
501
- "sylfaen",
502
- "traditional-arabic",
503
- "montserrat",
504
- "open-sans",
505
- "poppins",
506
- "pt-serif",
507
- "raleway",
508
- "roboto",
509
- "noto-sans-arabic",
510
- "noto-sans-armenian",
511
- "noto-sans-bengali",
512
- "noto-sans-devangari",
513
- "noto-sans-georgian",
514
- "noto-sans-gujarati",
515
- "noto-sans-gurmukhi",
516
- "noto-sans-hebrew",
517
- "noto-sans-jp",
518
- "noto-sans-kannada",
519
- "noto-sans-kr",
520
- "noto-sans-malayalam",
521
- "noto-sans-mongolian",
522
- "noto-sans-oriya",
523
- "noto-sans-sc",
524
- "noto-sans-tamil",
525
- "noto-sans-tc",
526
- "noto-sans-telugu",
527
- "noto-sans",
528
- "noto-sans-thai",
529
- "noto-nastaliq-urdu",
530
- "noto-naksh-arabic",
531
- "noto-sans-ethiopic",
532
- "noto-sans-khmer",
533
- "nyala",
534
- "daunpenh",
535
- "khmer-ui"
536
- ]
537
- };
538
- var deprecatedCatalogIds = {
539
- "audiences/executives": "executive",
540
- "audiences/investors": "investor",
541
- "audiences/customers": "customer",
542
- "audiences/sales-team": "sales",
543
- "audiences/marketing-team": "marketing",
544
- "audiences/regulators": "regulatory",
545
- "chartTypes/100pct-bullet-bar": "100pct-stacked-bar-3x",
546
- "chartTypes/100pct-bullet-bar-2x": "100pct-stacked-bar-3x",
547
- "chartTypes/100pct-bullet-bar-3x": "100pct-stacked-bar-3x",
548
- "chartTypes/100pct-bullet-column": "100pct-stacked-column-3x",
549
- "chartTypes/100pct-bullet-column-2x": "100pct-stacked-column-3x",
550
- "chartTypes/100pct-bullet-column-3x": "100pct-stacked-column-3x",
551
- "chartTypes/100pct-progress-bar": "100pct-stacked-bar-3x",
552
- "chartTypes/100pct-stacked-area-2x": "100pct-stacked-area-3x",
553
- "chartTypes/100pct-stacked-bar-2x": "100pct-stacked-bar-3x",
554
- "chartTypes/100pct-stacked-column-2x": "100pct-stacked-column-3x",
555
- "chartTypes/australia": "world",
556
- "chartTypes/box-and-whisker-2x": "box-and-whisker",
557
- "chartTypes/box-and-whisker-3x": "box-and-whisker",
558
- "chartTypes/bullet-bar": "bar",
559
- "chartTypes/bullet-bar-2x": "bar",
560
- "chartTypes/bullet-bar-3x": "bar",
561
- "chartTypes/bullet-column": "column",
562
- "chartTypes/bullet-column-2x": "column",
563
- "chartTypes/bullet-column-3x": "column",
564
- "chartTypes/canada": "world",
565
- "chartTypes/clustered-bar-2x": "bar",
566
- "chartTypes/clustered-column": "column",
567
- "chartTypes/dot-plot": "scatter",
568
- "chartTypes/dot-plot-2x": "scatter",
569
- "chartTypes/dot-plot-3x": "scatter",
570
- "chartTypes/dot-plot-4x": "scatter",
571
- "chartTypes/dot-plot-5x": "scatter",
572
- "chartTypes/dot-plot-6x": "scatter",
573
- "chartTypes/dumbbell": "scatter",
574
- "chartTypes/line-2x": "line",
575
- "chartTypes/line-3x": "line",
576
- "chartTypes/line-with-high-low": "line",
577
- "chartTypes/line-with-high-low-and-markers": "line-with-markers",
578
- "chartTypes/line-with-markers-2x": "line-with-markers",
579
- "chartTypes/line-with-markers-3x": "line-with-markers",
580
- "chartTypes/sparkline": "line",
581
- "chartTypes/sparkline-2x": "line",
582
- "chartTypes/sparkline-3x": "line",
583
- "chartTypes/sparkline-4x": "line",
584
- "chartTypes/sparkline-5x": "line",
585
- "chartTypes/sparkline-6x": "line",
586
- "chartTypes/stacked-area-2x": "stacked-area-3x",
587
- "chartTypes/stacked-bar-2x": "stacked-bar-3x",
588
- "chartTypes/stacked-column-2x": "stacked-column-3x",
589
- "chartTypes/stacked-line-2x": "stacked-line-3x",
590
- "chartTypes/stacked-line-with-markers-2x": "stacked-line-with-markers-3x",
591
- "chartTypes/treemap-2x": "treemap",
592
- "chartTypes/treemap-3x": "treemap",
593
- "chartTypes/united-kingdom": "world",
594
- "chartTypes/united-states": "world"
595
- };
596
-
597
41
  // src/chart-options.ts
598
42
  var END_POSITIONS = ["center", "inside-end", "inside-base", "outside-end"];
599
43
  var STACKED_POSITIONS = ["center", "inside-end", "inside-base"];
@@ -602,9 +46,12 @@ var PIE_POSITIONS = ["center", "inside-end", "outside-end"];
602
46
  var NONE = [];
603
47
  var VALUE_CATEGORY = ["category", "value"];
604
48
  var ALL_CONTENT = ["category", "value", "percent"];
605
- var categoryKinds = /* @__PURE__ */ new Set(["bar", "line", "area", "scatter", "histogram", "pareto", "box", "waterfall", "funnel"]);
606
- var valueKinds = /* @__PURE__ */ new Set(["bar", "line", "area", "scatter", "histogram", "pareto", "box", "waterfall"]);
607
- var legendKinds = /* @__PURE__ */ new Set(["bar", "line", "area", "pie", "doughnut", "scatter", "radar", "box"]);
49
+ var COMBO_POSITIONS = ["center", "inside-end", "inside-base", "outside-end", "above", "below", "left", "right"];
50
+ var categoryKinds = /* @__PURE__ */ new Set(["bar", "line", "area", "scatter", "histogram", "pareto", "box", "waterfall", "funnel", "combo"]);
51
+ var valueKinds = /* @__PURE__ */ new Set(["bar", "line", "area", "scatter", "histogram", "pareto", "box", "waterfall", "combo"]);
52
+ var legendKinds = /* @__PURE__ */ new Set(["bar", "line", "area", "pie", "doughnut", "scatter", "radar", "box", "combo"]);
53
+ var highlightSeriesKinds = /* @__PURE__ */ new Set(["bar", "line", "area", "scatter", "radar"]);
54
+ var highlightCategoryKinds = /* @__PURE__ */ new Set(["bar", "line", "pie", "doughnut"]);
608
55
  function labelSupport(target) {
609
56
  const none = { supported: true, content: VALUE_CATEGORY, positions: NONE, defaultPosition: null, defaultOn: false };
610
57
  switch (target.kind) {
@@ -613,6 +60,9 @@ function labelSupport(target) {
613
60
  case "line":
614
61
  case "scatter":
615
62
  return { ...none, positions: POINT_POSITIONS, defaultPosition: "above" };
63
+ // Columns take the clustered positions and lines the point positions ('center' fits both); each part falls back to its own default.
64
+ case "combo":
65
+ return { ...none, positions: COMBO_POSITIONS, defaultPosition: "outside-end" };
616
66
  case "pie":
617
67
  return { ...none, content: ALL_CONTENT, positions: PIE_POSITIONS, defaultPosition: "outside-end" };
618
68
  case "doughnut":
@@ -634,25 +84,26 @@ function labelSupport(target) {
634
84
  }
635
85
  function chartOptionSupport(target) {
636
86
  return {
637
- axisTitles: { category: categoryKinds.has(target.kind), value: valueKinds.has(target.kind) },
87
+ axisTitles: { category: categoryKinds.has(target.kind), value: valueKinds.has(target.kind), secondary: target.kind === "combo" },
638
88
  legend: legendKinds.has(target.kind),
89
+ highlight: { series: highlightSeriesKinds.has(target.kind), categories: highlightCategoryKinds.has(target.kind) },
639
90
  dataLabels: labelSupport(target)
640
91
  };
641
92
  }
642
93
  var KEPT = {
643
94
  column: { kind: "bar" },
644
- "stacked-column-3x": { kind: "bar", stacked: true },
645
- "100pct-stacked-column-3x": { kind: "bar", stacked: true },
95
+ "stacked-column": { kind: "bar", stacked: true },
96
+ "100pct-stacked-column": { kind: "bar", stacked: true },
646
97
  bar: { kind: "bar" },
647
- "stacked-bar-3x": { kind: "bar", stacked: true },
648
- "100pct-stacked-bar-3x": { kind: "bar", stacked: true },
98
+ "stacked-bar": { kind: "bar", stacked: true },
99
+ "100pct-stacked-bar": { kind: "bar", stacked: true },
649
100
  line: { kind: "line" },
650
101
  "line-with-markers": { kind: "line" },
651
- "stacked-line-3x": { kind: "line", stacked: true },
652
- "stacked-line-with-markers-3x": { kind: "line", stacked: true },
102
+ "stacked-line": { kind: "line", stacked: true },
103
+ "stacked-line-with-markers": { kind: "line", stacked: true },
653
104
  area: { kind: "area" },
654
- "stacked-area-3x": { kind: "area", stacked: true },
655
- "100pct-stacked-area-3x": { kind: "area", stacked: true },
105
+ "stacked-area": { kind: "area", stacked: true },
106
+ "100pct-stacked-area": { kind: "area", stacked: true },
656
107
  pie: { kind: "pie" },
657
108
  doughnut: { kind: "doughnut" },
658
109
  scatter: { kind: "scatter" },
@@ -665,14 +116,14 @@ var KEPT = {
665
116
  "box-and-whisker": { kind: "box" },
666
117
  waterfall: { kind: "waterfall" },
667
118
  funnel: { kind: "funnel" },
668
- world: { kind: "map" }
119
+ world: { kind: "map" },
120
+ combo: { kind: "combo" }
669
121
  };
670
122
  function chartOptionTarget(typeId) {
671
123
  if (typeof typeId !== "string") return void 0;
672
124
  const raw = typeId.trim().toLowerCase();
673
125
  const id = raw === "donut" ? "doughnut" : raw;
674
- const kept = deprecatedCatalogIds[`chartTypes/${id}`] ?? id;
675
- const target = Object.hasOwn(KEPT, kept) ? KEPT[kept] : void 0;
126
+ const target = Object.hasOwn(KEPT, id) ? KEPT[id] : void 0;
676
127
  return target ? { ...target } : void 0;
677
128
  }
678
129
  var record2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -686,11 +137,25 @@ function resolveChartOptions(chart, target) {
686
137
  const support = target ? chartOptionSupport(target) : void 0;
687
138
  const adapt = (option, reason, message) => result.diagnostics.push({ code: "chart-option-adapted", option, reason, message });
688
139
  const kind2 = target?.kind ?? "unknown";
140
+ const combo = target?.kind === "combo";
141
+ if (!combo) {
142
+ for (const option of ["line", "secondaryAxis"]) {
143
+ if (chart[option] !== void 0) adapt(option, "unsupported-type", `Only a 'combo' chart draws line series${option === "secondaryAxis" ? " on a secondary axis" : ""}; ${option} is ignored on a '${kind2}' chart.`);
144
+ }
145
+ }
689
146
  if (record2(chart.axisTitles)) {
690
- for (const axis of ["category", "value"]) {
147
+ for (const axis of ["category", "value", "secondary"]) {
691
148
  const raw = chart.axisTitles[axis];
692
149
  if (typeof raw !== "string" || !raw.trim()) continue;
693
- if (support && !support.axisTitles[axis]) {
150
+ if (axis === "secondary" && support && !support.axisTitles.secondary) {
151
+ adapt("axisTitles.secondary", "unsupported-type", `Only a 'combo' chart has a secondary value axis; the secondary axis title is not drawn or exported on a '${kind2}' chart.`);
152
+ continue;
153
+ }
154
+ if (axis === "secondary" && combo && !(Array.isArray(chart.secondaryAxis) && chart.secondaryAxis.some((name) => typeof name === "string"))) {
155
+ adapt("axisTitles.secondary", "unsupported-type", "This combo chart plots no series on a secondary axis (secondaryAxis is absent); the secondary axis title is not drawn or exported.");
156
+ continue;
157
+ }
158
+ if (axis !== "secondary" && support && !support.axisTitles[axis]) {
694
159
  adapt(`axisTitles.${axis}`, "unsupported-type", `A '${kind2}' chart has no ${axis} axis to title; the ${axis} axis title is not drawn or exported.`);
695
160
  continue;
696
161
  }
@@ -717,8 +182,18 @@ function resolveChartOptions(chart, target) {
717
182
  if (!content.length) content.push("value");
718
183
  const positions = support?.dataLabels.positions ?? NONE;
719
184
  let position = support?.dataLabels.defaultPosition ?? null;
720
- if (typeof options.position === "string" && POSITIONS.has(options.position) && options.position !== "auto") {
721
- if (!support || positions.includes(options.position)) position = options.position;
185
+ let linePosition;
186
+ const requestedPosition = typeof options.position === "string" && POSITIONS.has(options.position) && options.position !== "auto" ? options.position : void 0;
187
+ if (combo) {
188
+ linePosition = "above";
189
+ if (requestedPosition) {
190
+ if (END_POSITIONS.includes(requestedPosition)) position = requestedPosition;
191
+ else adapt("dataLabels.position", "unsupported-position", `The column series of a combo chart cannot place data labels '${requestedPosition}'; they use outside-end.`);
192
+ if (POINT_POSITIONS.includes(requestedPosition)) linePosition = requestedPosition;
193
+ else adapt("dataLabels.position", "unsupported-position", `The line series of a combo chart cannot place data labels '${requestedPosition}'; they use above.`);
194
+ }
195
+ } else if (requestedPosition) {
196
+ if (!support || positions.includes(requestedPosition)) position = requestedPosition;
722
197
  else adapt("dataLabels.position", "unsupported-position", `A '${kind2}'${target?.stacked ? " stacked" : ""} chart cannot place data labels '${options.position}'; the type's default position is used.`);
723
198
  }
724
199
  let separator = typeof options.separator === "string" ? options.separator : DEFAULT_CHART_LABEL_SEPARATOR;
@@ -726,10 +201,23 @@ function resolveChartOptions(chart, target) {
726
201
  separator = separator.replace(/[\r\n]+/g, " ");
727
202
  adapt("dataLabels.separator", "unsupported-content", "A data label is one line; the line break in the separator is replaced with a space.");
728
203
  }
729
- result.dataLabels = { content, position, separator };
204
+ result.dataLabels = { content, position, separator, ...linePosition ? { linePosition } : {} };
730
205
  }
731
206
  }
732
- result.active = result.legend !== void 0 || result.dataLabels !== void 0 || result.dataLabelsOff === true || result.axisTitles.category !== void 0 || result.axisTitles.value !== void 0;
207
+ if (record2(chart.highlight)) {
208
+ const names = (value) => Array.isArray(value) ? [...new Set(value.filter((entry) => typeof entry === "string"))] : [];
209
+ const kept = { series: [], categories: [] };
210
+ for (const part of ["series", "categories"]) {
211
+ const requested = names(chart.highlight[part]);
212
+ if (!requested.length) continue;
213
+ if (support && !support.highlight[part]) {
214
+ const alternative = part === "series" ? support.highlight.categories ? " (name categories instead)" : "" : support.highlight.series ? " (name series instead)" : "";
215
+ adapt(`highlight.${part}`, "unsupported-type", `A '${kind2}' chart cannot highlight ${part}${alternative}; the highlighted ${part} are ignored.`);
216
+ } else kept[part] = requested;
217
+ }
218
+ if (kept.series.length || kept.categories.length) result.highlight = kept;
219
+ }
220
+ result.active = result.legend !== void 0 || result.dataLabels !== void 0 || result.dataLabelsOff === true || result.axisTitles.category !== void 0 || result.axisTitles.value !== void 0 || result.axisTitles.secondary !== void 0;
733
221
  return result;
734
222
  }
735
223
  function formatChartLabelNumber(value) {
@@ -741,6 +229,14 @@ function formatChartLabelPercent(share) {
741
229
  function chartLabelText(parts, content, separator = DEFAULT_CHART_LABEL_SEPARATOR) {
742
230
  return CONTENT_ORDER.filter((part) => content.includes(part) && parts[part] !== void 0).map((part) => parts[part]).join(separator);
743
231
  }
232
+ function chartHighlightMarks(highlight, data) {
233
+ if (!highlight) return void 0;
234
+ const first = data.columns.length > 1 ? data.hasX ? 2 : 1 : 0;
235
+ const series = data.columns.slice(first).map((name) => highlight.series.includes(name));
236
+ const label = (cell) => cell === null || cell === void 0 ? "" : String(cell);
237
+ const categories = data.columns.length > 1 ? data.rows.map((row) => highlight.categories.includes(label(row[0]))) : data.rows.map(() => false);
238
+ return series.some(Boolean) || categories.some(Boolean) ? { series, categories } : void 0;
239
+ }
744
240
 
745
241
  // src/content-walk.ts
746
242
  function isRecord(value) {
@@ -749,7 +245,6 @@ function isRecord(value) {
749
245
  function pathFor(parentPath, key) {
750
246
  return parentPath === "/" ? `/${key}` : `${parentPath}/${key.replaceAll("~", "~0").replaceAll("/", "~1")}`;
751
247
  }
752
- var bareIdPattern = /^[a-z0-9][a-z0-9-]*$/;
753
248
  var promotedRegionKeys = [
754
249
  "left",
755
250
  "center",
@@ -928,6 +423,24 @@ function formatSlideNumber(format, current, total) {
928
423
  return { text: text2, fields: fields2 };
929
424
  }
930
425
 
426
+ // src/deck-metadata.ts
427
+ function recordsOf(value) {
428
+ return (Array.isArray(value) ? value : value === void 0 || value === null ? [] : [value]).filter(isRecord);
429
+ }
430
+ function speakersOf(presentation) {
431
+ return isRecord(presentation) ? recordsOf(presentation.speaker) : [];
432
+ }
433
+ function organizationsOf(presentation) {
434
+ return isRecord(presentation) ? recordsOf(presentation.organization) : [];
435
+ }
436
+ function primarySpeaker(presentation) {
437
+ return speakersOf(presentation)[0];
438
+ }
439
+ function primaryOrganization(presentation) {
440
+ const organizations = organizationsOf(presentation);
441
+ return organizations.find((item) => item.role === "primary") ?? organizations[0];
442
+ }
443
+
931
444
  // src/variables.ts
932
445
  var VARIABLE_KINDS = ["color", "text", "number", "date", "image", "url", "list"];
933
446
  var DEFAULT_VARIABLE_DATE_FORMAT = "MMMM d, yyyy";
@@ -941,12 +454,15 @@ var OPFVariableError = class extends Error {
941
454
  }
942
455
  };
943
456
  var idPattern = /^[a-z][a-z0-9-]*$/;
944
- var referencePattern = /^var:([a-z][a-z0-9-]*)$/;
457
+ var nameSource = String.raw`[a-z][a-z0-9-]*|(?:deck|speaker|organization)(?:\.[A-Za-z0-9_-]+){1,2}`;
458
+ var referencePattern = new RegExp(String.raw`^var:(${nameSource})$`);
459
+ var builtinNamePattern = /^(?:speakers|(?:deck|speaker|organization)(?:\.[A-Za-z0-9_-]+){1,2})$/;
460
+ var builtinUsePattern = /\{\{\s*(?:speakers\b|(?:deck|speaker|organization)\.)|^var:(?:speakers$|(?:deck|speaker|organization)\.)/;
945
461
  var hexPattern = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/;
946
462
  var urlPattern = /^(?:https?:\/\/|mailto:|tel:)\S+$/;
947
463
  var datePrefixPattern = /^(\d{4}-\d{2}-\d{2})(?:[T ].*)?$/;
948
464
  var decimalPattern = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
949
- var tokenPattern = /\\\{\{|\{\{\s*([a-z][a-z0-9-]*)\s*(?:\|([^{}]*))?\}\}/g;
465
+ var tokenPattern = new RegExp(String.raw`\\\{\{|\{\{\s*(${nameSource})\s*(?:\|([^{}]*))?\}\}`, "g");
950
466
  var SAMPLES = {
951
467
  color: "#000000",
952
468
  text: "Sample text",
@@ -1039,8 +555,18 @@ function variableDeclarations(presentation) {
1039
555
  }
1040
556
  return out;
1041
557
  }
558
+ function usesBuiltins(value, root = true) {
559
+ if (typeof value === "string") return value.length >= 6 && builtinUsePattern.test(value);
560
+ if (Array.isArray(value)) return value.some((entry) => usesBuiltins(entry, false));
561
+ if (!isRecord(value)) return false;
562
+ for (const [key, entry] of Object.entries(value)) {
563
+ if (skippedKeys.has(key) || root && skippedRootKeys.has(key)) continue;
564
+ if (usesBuiltins(entry, false)) return true;
565
+ }
566
+ return false;
567
+ }
1042
568
  function hasContentVariables(presentation) {
1043
- return isTemplate(presentation) || variableDeclarations(presentation).some((declaration) => declaration.kind !== "color");
569
+ return isTemplate(presentation) || variableDeclarations(presentation).some((declaration) => declaration.kind !== "color") || usesBuiltins(presentation);
1044
570
  }
1045
571
  var POSITIVE_ZERO = "0";
1046
572
  function formatVariableNumber(value, pattern) {
@@ -1127,6 +653,93 @@ function inlineText(effective, format, path, context) {
1127
653
  return value.join(format ?? ", ");
1128
654
  }
1129
655
  }
656
+ var DECK_FIELDS = { name: "text", description: "text", author: "text" };
657
+ var SPEAKER_FIELDS = { name: "text", title: "text", email: "text", phone: "text", bio: "text", photo: "image" };
658
+ var ORGANIZATION_FIELDS = { name: "text", legalName: "text", tagline: "text", domain: "text", email: "text", phone: "text", logo: "image" };
659
+ function isBuiltinName(name) {
660
+ return builtinNamePattern.test(name);
661
+ }
662
+ function builtinFields(root) {
663
+ return root === "deck" ? DECK_FIELDS : root === "speaker" ? SPEAKER_FIELDS : ORGANIZATION_FIELDS;
664
+ }
665
+ function present(value) {
666
+ if (typeof value === "string") return value.trim() === "" ? void 0 : value;
667
+ if (isRecord(value)) return typeof value.src === "string" && value.src.trim() ? value : void 0;
668
+ return void 0;
669
+ }
670
+ function builtinSource(name, doc) {
671
+ if (name === "speakers") {
672
+ const names = speakersOf(doc).map((speaker) => present(speaker.name)).filter((entry) => typeof entry === "string");
673
+ return { ok: true, kind: "list", raw: names.length ? names : void 0 };
674
+ }
675
+ const parts = name.split(".");
676
+ const root = parts[0];
677
+ const fields2 = builtinFields(root);
678
+ const list = (names) => names.map((entry) => `'${entry}'`).join(", ");
679
+ if (root === "deck") {
680
+ const field2 = parts[1];
681
+ if (parts.length !== 2 || !Object.hasOwn(fields2, field2)) return { ok: false, message: `'${name}' is not a built-in variable; the deck built-ins are ${list(Object.keys(fields2).map((key) => `deck.${key}`))}.` };
682
+ const value = doc[field2];
683
+ return { ok: true, kind: "text", raw: field2 === "author" && Array.isArray(value) ? present(value.filter((entry) => typeof entry === "string").join(", ")) : present(value) };
684
+ }
685
+ const field = parts[parts.length - 1];
686
+ if (!Object.hasOwn(fields2, field)) {
687
+ return { ok: false, message: `'${name}' is not a built-in variable: '${field}' is not a ${root} field; the fields are ${list(Object.keys(fields2))}.` };
688
+ }
689
+ let entity;
690
+ if (parts.length === 2) entity = root === "speaker" ? primarySpeaker(doc) : primaryOrganization(doc);
691
+ else {
692
+ const id = parts[1];
693
+ const entries = root === "speaker" ? speakersOf(doc) : organizationsOf(doc);
694
+ entity = entries.find((entry) => entry.id === id);
695
+ if (!entity) return { ok: false, message: `'${name}' names no ${root} with id '${id}'.` };
696
+ }
697
+ return { ok: true, kind: fields2[field], raw: present(entity?.[field]) };
698
+ }
699
+ function builtinEffective(name, path, context) {
700
+ if (context.resolvingBuiltins.has(name)) return void 0;
701
+ const cached = context.builtins.get(name);
702
+ if (cached !== void 0) {
703
+ if (cached === null) diag(context, unknownBuiltin(name, path, context), `ubi:${name}:${path}`);
704
+ else if (cached.status === "unfilled") diag(context, missingBuiltin(name, path), `bim:${name}:${path}`);
705
+ return cached ?? void 0;
706
+ }
707
+ const source = builtinSource(name, context.doc);
708
+ if (!source.ok) {
709
+ context.builtins.set(name, null);
710
+ diag(context, unknownBuiltin(name, path, context), `ubi:${name}:${path}`);
711
+ return void 0;
712
+ }
713
+ const declaration = { id: name, kind: source.kind, path: "", required: context.keepMissingBuiltins };
714
+ let effective;
715
+ const coerced = source.raw === void 0 ? void 0 : coerceVariableValue(source.kind, source.raw);
716
+ if (coerced?.ok) {
717
+ let value = coerced.value;
718
+ if (typeof value === "string" && value.includes("{{")) {
719
+ context.resolvingBuiltins.add(name);
720
+ value = interpolate(value, path, context).value;
721
+ context.resolvingBuiltins.delete(name);
722
+ }
723
+ effective = { declaration: { ...declaration, value }, status: "filled", value, provided: false };
724
+ } else {
725
+ effective = { declaration, status: "unfilled", provided: false };
726
+ diag(context, missingBuiltin(name, path), `bim:${name}:${path}`);
727
+ }
728
+ context.builtins.set(name, effective);
729
+ return effective;
730
+ }
731
+ function unknownBuiltin(name, path, context) {
732
+ const source = builtinSource(name, context.doc);
733
+ return { code: "variable-unknown-builtin", severity: "error", path, id: name, message: source.ok ? `'${name}' is not a built-in variable.` : source.message };
734
+ }
735
+ function missingBuiltin(name, path) {
736
+ return { code: "variable-builtin-missing", severity: "warning", path, id: name, message: `Built-in '${name}' has no value in this document, so it resolves to nothing; add the field it reads (see docs/templates-and-variables.md).` };
737
+ }
738
+ function lookupVariable(id, path, context) {
739
+ const declared = context.effective.get(id);
740
+ if (declared || !isBuiltinName(id)) return declared;
741
+ return builtinEffective(id, path, context);
742
+ }
1130
743
  function interpolate(text2, path, context) {
1131
744
  let changed = false;
1132
745
  const value = text2.replace(tokenPattern, (match, id, format) => {
@@ -1138,9 +751,9 @@ function interpolate(text2, path, context) {
1138
751
  return match;
1139
752
  }
1140
753
  context.uses.push({ id, path, form: "token" });
1141
- const effective = context.effective.get(id);
754
+ const effective = lookupVariable(id, path, context);
1142
755
  if (!effective) {
1143
- diag(context, { code: "variable-unknown", severity: "warning", path, id, message: `'{{${id}}}' names no declared variable; declare '${id}' in the top-level variables map, or write '\\{{' for literal braces.` }, `unk:${id}:${path}`);
756
+ if (!isBuiltinName(id)) diag(context, { code: "variable-unknown", severity: "warning", path, id, message: `'{{${id}}}' names no declared variable; declare '${id}' in the top-level variables map, or write '\\{{' for literal braces.` }, `unk:${id}:${path}`);
1144
757
  return match;
1145
758
  }
1146
759
  if (effective.status === "unfilled" && !context.shape) {
@@ -1168,7 +781,7 @@ function reduceString(text2, path, parentIsArray, context) {
1168
781
  const reference = referencePattern.exec(text2);
1169
782
  if (reference) {
1170
783
  const id = reference[1];
1171
- const effective = context.effective.get(id);
784
+ const effective = lookupVariable(id, path, context);
1172
785
  if (effective && effective.declaration.kind !== "color") {
1173
786
  context.uses.push({ id, path, form: "reference" });
1174
787
  if (effective.status === "unfilled" && !context.shape) {
@@ -1250,7 +863,11 @@ function plan(presentation, values, options) {
1250
863
  unescape: false,
1251
864
  shape: options.shape === true,
1252
865
  content: hasContentVariables(presentation) || template,
1253
- seen: /* @__PURE__ */ new Set()
866
+ seen: /* @__PURE__ */ new Set(),
867
+ doc: presentation,
868
+ keepMissingBuiltins: options.examples === true,
869
+ builtins: /* @__PURE__ */ new Map(),
870
+ resolvingBuiltins: /* @__PURE__ */ new Set()
1254
871
  };
1255
872
  const unfilled = [];
1256
873
  const examplesUsed = [];
@@ -1374,6 +991,32 @@ function listVariables(presentation, values = {}) {
1374
991
  };
1375
992
  });
1376
993
  }
994
+ var FIELD_LABELS = { name: "name", legalName: "legal name", tagline: "tagline", domain: "domain", email: "email", phone: "phone", logo: "logo", title: "title", bio: "bio", photo: "photo", description: "description", author: "author" };
995
+ function listBuiltinVariables(presentation) {
996
+ if (!isRecord(presentation)) return [];
997
+ const names = [];
998
+ for (const field of Object.keys(DECK_FIELDS)) names.push({ name: `deck.${field}`, label: `Deck ${FIELD_LABELS[field]}` });
999
+ for (const field of Object.keys(SPEAKER_FIELDS)) names.push({ name: `speaker.${field}`, label: `Speaker ${FIELD_LABELS[field]}` });
1000
+ names.push({ name: "speakers", label: "All speaker names" });
1001
+ for (const field of Object.keys(ORGANIZATION_FIELDS)) names.push({ name: `organization.${field}`, label: `Organization ${FIELD_LABELS[field]}` });
1002
+ for (const [root, entries] of [["speaker", speakersOf(presentation)], ["organization", organizationsOf(presentation)]]) {
1003
+ for (const entry of entries) {
1004
+ if (typeof entry.id !== "string" || entry.id === "") continue;
1005
+ for (const field of Object.keys(builtinFields(root))) names.push({ name: `${root}.${entry.id}.${field}`, label: `${root === "speaker" ? "Speaker" : "Organization"} ${entry.id} ${FIELD_LABELS[field]}` });
1006
+ }
1007
+ }
1008
+ const built = plan(presentation, {}, { examples: false, partial: true, shape: true });
1009
+ built.context.content = true;
1010
+ walk(presentation, "", false, built.context);
1011
+ const out = [];
1012
+ for (const { name, label } of names) {
1013
+ const source = builtinSource(name, presentation);
1014
+ if (!source.ok) continue;
1015
+ const coerced = source.raw === void 0 ? void 0 : coerceVariableValue(source.kind, source.raw);
1016
+ out.push({ name, kind: source.kind, label, ...coerced?.ok ? { value: coerced.value } : {}, available: coerced?.ok === true, uses: built.context.uses.filter((use) => use.id === name) });
1017
+ }
1018
+ return out;
1019
+ }
1377
1020
 
1378
1021
  // src/chart-data.ts
1379
1022
  var record3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
@@ -1451,7 +1094,7 @@ function excelInteger(integer) {
1451
1094
  const placeholders = "#".repeat(width - zeros) + "0".repeat(zeros);
1452
1095
  return placeholders.replace(/\B(?=(.{3})+$)/g, ",");
1453
1096
  }
1454
- function excelNumberFormat(format) {
1097
+ function toExcelNumberFormat(format) {
1455
1098
  if (format === void 0 || format === "") return "General";
1456
1099
  const parts = formatParts(format);
1457
1100
  if (!parts) return "General";
@@ -1489,7 +1132,7 @@ function excelTokens(code) {
1489
1132
  }
1490
1133
  return tokens;
1491
1134
  }
1492
- function numberFormatFromExcel(code) {
1135
+ function fromExcelNumberFormat(code) {
1493
1136
  if (typeof code !== "string") return void 0;
1494
1137
  const trimmed = code.trim();
1495
1138
  if (trimmed === "" || /^general$/i.test(trimmed)) return void 0;
@@ -1580,8 +1223,8 @@ function inlinedData(ref, datasets) {
1580
1223
  const diagnostics = [];
1581
1224
  const selection = selectFields(dataset.columns, ref.fields, "", "", diagnostics);
1582
1225
  if (diagnostics.some((entry) => entry.code === "dataset-field-unknown")) return void 0;
1583
- const rows2 = dataset.rows.map((row) => selection.indices.map((index) => Array.isArray(row) && index < row.length ? structuredClone(row[index]) : null));
1584
- return { columns: selection.columns.map(inlineColumn), rows: rows2, ...record3(dataset.source) ? { source: structuredClone(dataset.source) } : {} };
1226
+ const rows3 = dataset.rows.map((row) => selection.indices.map((index) => Array.isArray(row) && index < row.length ? structuredClone(row[index]) : null));
1227
+ return { columns: selection.columns.map(inlineColumn), rows: rows3, ...record3(dataset.source) ? { source: structuredClone(dataset.source) } : {} };
1585
1228
  }
1586
1229
  function inlineDatasets(document) {
1587
1230
  if (!record3(document)) return document;
@@ -1655,7 +1298,7 @@ function resolveChartData(chart, document, options = {}) {
1655
1298
  const data = record3(chart) ? chart.data : void 0;
1656
1299
  if (!record3(data)) return fail("no-columns", "The chart has no data.");
1657
1300
  let columns2;
1658
- let rows2;
1301
+ let rows3;
1659
1302
  let columnsPath;
1660
1303
  let rowsPath;
1661
1304
  let source;
@@ -1675,15 +1318,12 @@ function resolveChartData(chart, document, options = {}) {
1675
1318
  const selection = selectFields(dataset.columns, data.fields, at(base, "data", "fields"), columnsPath, diagnostics);
1676
1319
  columns2 = selection.columns;
1677
1320
  selected = selection.indices;
1678
- rows2 = dataset.rows;
1321
+ rows3 = dataset.rows;
1679
1322
  if (record3(dataset.source)) source = dataset.source;
1680
- } else if (typeof data.src === "string") {
1681
- diagnostics.push({ code: "chart-data-source-unresolved", severity: "warning", path: at(base, "data", "src"), message: `chart data source '${data.src}' is not loaded by any engine; the preview and export draw a placeholder. Import the data inline (columns and rows, with a 'source' for provenance) or reference a dataset` });
1682
- return fail("data-not-inline", "The chart reads an external data source, which no engine resolves.");
1683
1323
  } else {
1684
1324
  if (!Array.isArray(data.columns)) return fail("no-columns", "The chart data has no columns.");
1685
1325
  columns2 = data.columns;
1686
- rows2 = Array.isArray(data.rows) ? data.rows : [];
1326
+ rows3 = Array.isArray(data.rows) ? data.rows : [];
1687
1327
  columnsPath = at(base, "data", "columns");
1688
1328
  rowsPath = at(base, "data", "rows");
1689
1329
  formatDiagnostics(columns2, columnsPath, diagnostics);
@@ -1741,10 +1381,46 @@ function resolveChartData(chart, document, options = {}) {
1741
1381
  series = [x];
1742
1382
  x = void 0;
1743
1383
  }
1384
+ let combo;
1385
+ if (record3(chart) && chartOptionTarget(chart.type)?.kind === "combo") {
1386
+ const listed = (option, problem) => {
1387
+ const found = /* @__PURE__ */ new Set();
1388
+ const value = chart[option];
1389
+ if (!Array.isArray(value)) return found;
1390
+ value.forEach((name, index) => {
1391
+ const path = at(base, option, index);
1392
+ const column = known(name, path);
1393
+ if (column === void 0) return;
1394
+ const reason = problem(column);
1395
+ if (reason) diagnostics.push({ code: "chart-mapping-adapted", severity: "warning", path, message: `${JSON.stringify(name)} ${reason}` });
1396
+ else found.add(column);
1397
+ });
1398
+ return found;
1399
+ };
1400
+ const notPlotted = "is not a plotted series of the chart";
1401
+ const lines = listed("line", (column) => series.includes(column) ? void 0 : `${notPlotted}; it is not drawn as a line`);
1402
+ if (chart.line === void 0 && series.length >= 2) lines.add(series[series.length - 1]);
1403
+ if (series.length && series.every((column) => lines.has(column))) {
1404
+ lines.delete(series[0]);
1405
+ diagnostics.push({ code: "chart-mapping-adapted", severity: "warning", path: at(base, chart.line === void 0 ? "type" : "line"), message: series.length === 1 ? `a combo chart needs at least two series, one drawn as columns and one as a line; its one series ${JSON.stringify(names[series[0]])} is drawn as columns` : `a combo chart keeps at least one column series; ${JSON.stringify(names[series[0]])} is drawn as columns, not as a line` });
1406
+ } else if (series.length === 1) {
1407
+ diagnostics.push({ code: "chart-mapping-adapted", severity: "warning", path: at(base, "type"), message: `a combo chart needs at least two series, one drawn as columns and one as a line; its one series ${JSON.stringify(names[series[0]])} is drawn as columns` });
1408
+ }
1409
+ const secondary = listed("secondaryAxis", (column) => !series.includes(column) ? `${notPlotted}; it has no axis to move to` : !lines.has(column) ? "is drawn as columns; only a line series can use the secondary axis, so it stays on the primary axis" : void 0);
1410
+ const bars = series.filter((column) => !lines.has(column));
1411
+ const primaryLines = series.filter((column) => lines.has(column) && !secondary.has(column));
1412
+ const secondaryLines = series.filter((column) => lines.has(column) && secondary.has(column));
1413
+ series = [...bars, ...primaryLines, ...secondaryLines];
1414
+ combo = [
1415
+ ...bars.map(() => ({ role: "bar", axis: "primary" })),
1416
+ ...primaryLines.map(() => ({ role: "line", axis: "primary" })),
1417
+ ...secondaryLines.map(() => ({ role: "line", axis: "secondary" }))
1418
+ ];
1419
+ }
1744
1420
  const order = [category, ...x === void 0 ? [] : [x], ...series];
1745
- if (!rows2.length) return fail("no-rows", "The chart data has no rows.");
1421
+ if (!rows3.length) return fail("no-rows", "The chart data has no rows.");
1746
1422
  const lone = names.length === 1 && !diagnostics.some((entry) => entry.code === "dataset-field-unknown");
1747
- const out = rows2.map((row, rowIndex) => order.map((column, position) => {
1423
+ const out = rows3.map((row, rowIndex) => order.map((column, position) => {
1748
1424
  const sourceIndex = selected ? selected[column] : column;
1749
1425
  const cell = Array.isArray(row) && sourceIndex < row.length ? row[sourceIndex] : null;
1750
1426
  if (position === 0 && !lone) return cell === void 0 ? null : cell;
@@ -1754,6 +1430,26 @@ function resolveChartData(chart, document, options = {}) {
1754
1430
  }
1755
1431
  return number;
1756
1432
  }));
1433
+ const highlight = record3(chart) && record3(chart.highlight) ? chart.highlight : void 0;
1434
+ if (highlight) {
1435
+ const plotted = order.slice(order.length - series.length).map((index) => names[index]);
1436
+ const labels = lone ? void 0 : new Set(out.map((row) => row[0] === null || row[0] === void 0 ? "" : String(row[0])));
1437
+ const listed = (value) => Array.isArray(value) ? value : [];
1438
+ const highlightPath = at(base, "highlight");
1439
+ listed(highlight.series).forEach((name, index) => {
1440
+ const path = at(highlightPath, "series", index);
1441
+ if (typeof name !== "string" || !names.includes(name)) {
1442
+ diagnostics.push({ code: "chart-highlight-unknown-name", severity: "error", path, message: `highlight names series ${JSON.stringify(name)}, which the chart data does not have as a column; use one of ${names.map((entry) => JSON.stringify(entry)).join(", ")}` });
1443
+ } else if (!plotted.includes(name)) {
1444
+ diagnostics.push({ code: "chart-highlight-adapted", severity: "warning", path, message: `highlight names column ${JSON.stringify(name)}, which is not plotted as a series (it is the category or X column, or the mapping leaves it out); it highlights nothing` });
1445
+ }
1446
+ });
1447
+ listed(highlight.categories).forEach((name, index) => {
1448
+ if (typeof name === "string" && labels?.has(name)) return;
1449
+ const shown = labels ? [...labels].slice(0, 12).map((entry) => JSON.stringify(entry)).join(", ") : "";
1450
+ diagnostics.push({ code: "chart-highlight-unknown-name", severity: "error", path: at(highlightPath, "categories", index), message: `highlight names category ${JSON.stringify(name)}, which no row of the chart data has as its label${shown ? `; the labels are ${shown}${labels.size > 12 ? ", ..." : ""}` : ""}` });
1451
+ });
1452
+ }
1757
1453
  return {
1758
1454
  ok: true,
1759
1455
  columns: order.map((index) => names[index]),
@@ -1762,6 +1458,7 @@ function resolveChartData(chart, document, options = {}) {
1762
1458
  rows: out,
1763
1459
  ...source ? { source } : {},
1764
1460
  ...datasetId !== void 0 ? { dataset: datasetId } : {},
1461
+ ...combo ? { combo } : {},
1765
1462
  diagnostics
1766
1463
  };
1767
1464
  }
@@ -1778,18 +1475,18 @@ function chartNumberFixes(chart, document, options) {
1778
1475
  if (!candidates.size) return fixes;
1779
1476
  const data = chart.data;
1780
1477
  let columns2;
1781
- let rows2;
1478
+ let rows3;
1782
1479
  let columnsPath;
1783
1480
  let rowsPath;
1784
1481
  if (isDatasetRef(data)) {
1785
1482
  const dataset = datasetsOf(document)[data.dataset];
1786
1483
  columns2 = dataset.columns;
1787
- rows2 = dataset.rows;
1484
+ rows3 = dataset.rows;
1788
1485
  columnsPath = at("/datasets", data.dataset, "columns");
1789
1486
  rowsPath = at("/datasets", data.dataset, "rows");
1790
1487
  } else {
1791
1488
  columns2 = data.columns;
1792
- rows2 = data.rows;
1489
+ rows3 = data.rows;
1793
1490
  columnsPath = at(options.path ?? "", "data", "columns");
1794
1491
  rowsPath = at(options.path ?? "", "data", "rows");
1795
1492
  }
@@ -1797,7 +1494,7 @@ function chartNumberFixes(chart, document, options) {
1797
1494
  const header = columns2[column];
1798
1495
  const name = columnName(header);
1799
1496
  if (name === void 0 || columnFormat(header) !== void 0) continue;
1800
- const fix = columnFix(rows2, column, rowsPath);
1497
+ const fix = columnFix(rows3, column, rowsPath);
1801
1498
  if (!fix) continue;
1802
1499
  fixes.set(column, {
1803
1500
  patches: [...fix.patches, { op: "replace", path: at(columnsPath, column), value: record3(header) ? { ...header, format: fix.format } : { name, format: fix.format } }],
@@ -1808,14 +1505,14 @@ function chartNumberFixes(chart, document, options) {
1808
1505
  }
1809
1506
  return fixes;
1810
1507
  }
1811
- function columnFix(rows2, column, rowsPath) {
1508
+ function columnFix(rows3, column, rowsPath) {
1812
1509
  const cells = [];
1813
1510
  let prefix;
1814
1511
  let suffix;
1815
1512
  let grouping = false;
1816
1513
  let wide = false;
1817
1514
  const decimals = [];
1818
- for (const [index, row] of rows2.entries()) {
1515
+ for (const [index, row] of rows3.entries()) {
1819
1516
  const cell = Array.isArray(row) && column < row.length ? row[column] : null;
1820
1517
  if (cell === null || cell === void 0 || cell === "") continue;
1821
1518
  const patch = chartNumber(cell) === null;
@@ -1870,12 +1567,12 @@ function resolveTableData(table, document, options = {}) {
1870
1567
  const columnsPath = at("/datasets", id, "columns");
1871
1568
  formatDiagnostics(dataset.columns, columnsPath, diagnostics);
1872
1569
  const selection = selectFields(dataset.columns, table.fields, at(base, "fields"), columnsPath, diagnostics);
1873
- const rows3 = dataset.rows.map((row) => selection.indices.map((index) => Array.isArray(row) && index < row.length ? row[index] : null));
1874
- return { columns: selection.columns, rows: rows3, formats: selection.formats, dataset: id, diagnostics };
1570
+ const rows4 = dataset.rows.map((row) => selection.indices.map((index) => Array.isArray(row) && index < row.length ? row[index] : null));
1571
+ return { columns: selection.columns, rows: rows4, formats: selection.formats, dataset: id, diagnostics };
1875
1572
  }
1876
1573
  const columns2 = Array.isArray(table.columns) ? table.columns : void 0;
1877
- const rows2 = Array.isArray(table.rows) ? table.rows.filter(Array.isArray) : [];
1878
- const width = Math.max(columns2?.length ?? 0, ...rows2.map((row) => row.length), 0);
1574
+ const rows3 = Array.isArray(table.rows) ? table.rows.filter(Array.isArray) : [];
1575
+ const width = Math.max(columns2?.length ?? 0, ...rows3.map((row) => row.length), 0);
1879
1576
  const formats = Array.from({ length: width }, (_, index) => {
1880
1577
  const header = columns2?.[index];
1881
1578
  return columnFormat(header) ?? cellFormat(header);
@@ -1893,7 +1590,7 @@ function resolveTableData(table, document, options = {}) {
1893
1590
  check(cell, at(base, "rows", rowIndex, index));
1894
1591
  });
1895
1592
  });
1896
- return { ...columns2 ? { columns: columns2 } : {}, rows: rows2, formats, diagnostics };
1593
+ return { ...columns2 ? { columns: columns2 } : {}, rows: rows3, formats, diagnostics };
1897
1594
  }
1898
1595
  function tableCellDisplayValue(cell, columnFormat2) {
1899
1596
  if (record3(cell) && own(cell, "value")) {
@@ -2019,6 +1716,38 @@ function intrinsicImageAspect(value, assets) {
2019
1716
  return size ? size.width / size.height : void 0;
2020
1717
  }
2021
1718
 
1719
+ // src/design-hints.ts
1720
+ var DESIGN_HINT_KEYS = ["titleAlignment", "contentAlignment", "contentBox", "contentDirection", "chartPrimary", "imageFit", "listBullet"];
1721
+ var ALIGNMENTS = ["left", "center", "right"];
1722
+ var VALUES = {
1723
+ titleAlignment: ALIGNMENTS,
1724
+ contentAlignment: ALIGNMENTS,
1725
+ contentBox: "boolean",
1726
+ contentDirection: ["horizontal", "vertical"],
1727
+ chartPrimary: ["none", "top", "bottom", "left", "right"],
1728
+ imageFit: ["cover", "contain", "stretch"],
1729
+ listBullet: ["character", "image"]
1730
+ };
1731
+ var accepts = (key, value) => VALUES[key] === "boolean" ? typeof value === "boolean" : VALUES[key].includes(value);
1732
+ var object = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
1733
+ function resolveDesignHints(options = {}) {
1734
+ const slide = object(object(options.slide).design), host = object(options.deck), deck = object(object(options.presentation).design), layout = object(object(options.layout).design);
1735
+ const index = options.slideIndex ?? 0;
1736
+ const result = { sources: {}, paths: {} };
1737
+ const set2 = (key, value, source, path) => {
1738
+ result[key] = value;
1739
+ result.sources[key] = source;
1740
+ result.paths[key] = path;
1741
+ };
1742
+ for (const key of DESIGN_HINT_KEYS) {
1743
+ if (accepts(key, slide[key])) set2(key, slide[key], "slide", `slides.${index}.design.${key}`);
1744
+ else if (accepts(key, host[key])) set2(key, host[key], "deck", `design.${key}`);
1745
+ else if (accepts(key, deck[key])) set2(key, deck[key], "deck", `design.${key}`);
1746
+ else if (accepts(key, layout[key])) set2(key, layout[key], "layout", `slides.${index}.layout`);
1747
+ }
1748
+ return result;
1749
+ }
1750
+
2022
1751
  // src/reading-order.ts
2023
1752
  function visualReadingOrder(items, direction = "ltr") {
2024
1753
  const index = new Map(items.map((item, i) => [item, i]));
@@ -2028,18 +1757,18 @@ function visualReadingOrder(items, direction = "ltr") {
2028
1757
  function readingRows(items) {
2029
1758
  const index = new Map(items.map((item, i) => [item, i]));
2030
1759
  const sorted = [...items].sort((a, b) => a.box.y - b.box.y || a.box.x - b.box.x || index.get(a) - index.get(b));
2031
- const rows2 = [];
1760
+ const rows3 = [];
2032
1761
  for (const item of sorted) {
2033
1762
  const centre = item.box.y + item.box.height / 2;
2034
- const row = rows2.find((candidate) => centre >= candidate.top && centre <= candidate.bottom);
1763
+ const row = rows3.find((candidate) => centre >= candidate.top && centre <= candidate.bottom);
2035
1764
  if (row) {
2036
1765
  row.items.push(item);
2037
1766
  row.top = Math.min(row.top, item.box.y);
2038
1767
  row.bottom = Math.max(row.bottom, item.box.y + item.box.height);
2039
- } else rows2.push({ top: item.box.y, bottom: item.box.y + item.box.height, items: [item] });
1768
+ } else rows3.push({ top: item.box.y, bottom: item.box.y + item.box.height, items: [item] });
2040
1769
  }
2041
- rows2.sort((a, b) => a.top - b.top);
2042
- return rows2.map((row) => row.items.sort((a, b) => index.get(a) - index.get(b)));
1770
+ rows3.sort((a, b) => a.top - b.top);
1771
+ return rows3.map((row) => row.items.sort((a, b) => index.get(a) - index.get(b)));
2043
1772
  }
2044
1773
 
2045
1774
  // src/direction.ts
@@ -2082,7 +1811,106 @@ function paragraphDirectionAt(text2, deckDirection) {
2082
1811
  };
2083
1812
  }
2084
1813
 
1814
+ // src/generated/engine-data.ts
1815
+ var engineDefaultsSource = {
1816
+ "theme": {
1817
+ "background": {
1818
+ "type": "theme",
1819
+ "slot": "dark2"
1820
+ },
1821
+ "dimensions": "widescreen"
1822
+ },
1823
+ "colorScheme": {
1824
+ "accent1": "#2874A6",
1825
+ "accent2": "#1B4F72",
1826
+ "accent3": "#5499C7",
1827
+ "accent4": "#7BDBB2",
1828
+ "accent5": "#3AC67A",
1829
+ "accent6": "#24A89E",
1830
+ "dark1": "#000000",
1831
+ "dark2": "#011842",
1832
+ "light1": "#FFFFFF",
1833
+ "light2": "#F0F0F0",
1834
+ "hyperlink": "#0000EE",
1835
+ "followedHyperlink": "#551A8B"
1836
+ },
1837
+ "fontScheme": {
1838
+ "major": "Aptos Display",
1839
+ "minor": "Aptos",
1840
+ "languageFamily": "latin"
1841
+ },
1842
+ "chartTypes": [
1843
+ "stacked-column",
1844
+ "stacked-area",
1845
+ "line-with-markers"
1846
+ ]
1847
+ };
1848
+ var engineVocabulariesSource = { "chartTypes": ["100pct-stacked-area", "100pct-stacked-bar", "100pct-stacked-column", "area", "bar", "box-and-whisker", "column", "combo", "doughnut", "filled-radar", "funnel", "histogram", "line", "line-with-markers", "pareto", "pie", "radar", "radar-with-markers", "scatter", "stacked-area", "stacked-bar", "stacked-column", "stacked-line", "stacked-line-with-markers", "treemap", "waterfall", "world"], "socialPlatforms": { "linkedin": { "baseUrl": "https://linkedin.com", "profileUrlPattern": "https://linkedin.com/in/{handle}", "companyUrlPattern": "https://linkedin.com/company/{handle}", "handlePrefix": "" }, "x": { "baseUrl": "https://x.com", "profileUrlPattern": "https://x.com/{handle}", "handlePrefix": "@" }, "github": { "baseUrl": "https://github.com", "profileUrlPattern": "https://github.com/{handle}", "companyUrlPattern": "https://github.com/{handle}", "handlePrefix": "" }, "youtube": { "baseUrl": "https://youtube.com", "profileUrlPattern": "https://youtube.com/@{handle}", "handlePrefix": "@" }, "instagram": { "baseUrl": "https://instagram.com", "profileUrlPattern": "https://instagram.com/{handle}", "handlePrefix": "@" }, "facebook": { "baseUrl": "https://facebook.com", "profileUrlPattern": "https://facebook.com/{handle}", "companyUrlPattern": "https://facebook.com/{handle}", "handlePrefix": "" }, "tiktok": { "baseUrl": "https://tiktok.com", "profileUrlPattern": "https://tiktok.com/@{handle}", "handlePrefix": "@" }, "threads": { "baseUrl": "https://threads.net", "profileUrlPattern": "https://threads.net/@{handle}", "handlePrefix": "@" }, "mastodon": { "baseUrl": "https://mastodon.social", "profileUrlPattern": "https://mastodon.social/@{handle}", "handlePrefix": "@" }, "bluesky": { "baseUrl": "https://bsky.app", "profileUrlPattern": "https://bsky.app/profile/{handle}", "handlePrefix": "" } }, "languages": [{ "tag": "af", "script": "Latn", "direction": "ltr", "ooxmlLang": "af-ZA", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "sq", "script": "Latn", "direction": "ltr", "ooxmlLang": "sq-AL", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "am", "script": "Ethi", "direction": "ltr", "ooxmlLang": "am-ET", "fonts": { "powerpoint": { "major": "Nyala", "minor": "Nyala" }, "google": { "major": "Noto Sans Ethiopic", "minor": "Noto Sans Ethiopic" } } }, { "tag": "ar", "script": "Arab", "direction": "rtl", "ooxmlLang": "ar-SA", "fonts": { "powerpoint": { "major": "Arabic Typesetting", "minor": "Arabic Typesetting" }, "google": { "major": "Noto Naskh Arabic", "minor": "Noto Naskh Arabic" } } }, { "tag": "hy", "script": "Armn", "direction": "ltr", "ooxmlLang": "hy-AM", "fonts": { "powerpoint": { "major": "Sylfaen", "minor": "Sylfaen" }, "google": { "major": "Noto Sans Armenian", "minor": "Noto Sans Armenian" } } }, { "tag": "ay", "script": "Latn", "direction": "ltr", "ooxmlLang": "ay-BO", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "az", "script": "Latn", "direction": "ltr", "ooxmlLang": "az-Latn-AZ", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "bn", "script": "Beng", "direction": "ltr", "ooxmlLang": "bn-BD", "fonts": { "powerpoint": { "major": "Shonar Bangla", "minor": "Shonar Bangla" }, "google": { "major": "Noto Sans Bengali", "minor": "Noto Sans Bengali" } } }, { "tag": "ber-Latn", "script": "Latn", "direction": "ltr", "ooxmlLang": "tzm-Latn-DZ", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "bs-Latn", "script": "Latn", "direction": "ltr", "ooxmlLang": "bs-Latn-BA", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "bg", "script": "Cyrl", "direction": "ltr", "ooxmlLang": "bg-BG", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Noto Sans", "minor": "Noto Sans" } } }, { "tag": "ca", "script": "Latn", "direction": "ltr", "ooxmlLang": "ca-ES", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "ceb", "script": "Latn", "direction": "ltr", "ooxmlLang": "ceb-PH", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "zh-Hans", "script": "Hans", "direction": "ltr", "ooxmlLang": "zh-CN", "fonts": { "powerpoint": { "major": "Microsoft YaHei", "minor": "Microsoft YaHei" }, "google": { "major": "Noto Sans SC", "minor": "Noto Sans SC" } } }, { "tag": "zh-Hant", "script": "Hant", "direction": "ltr", "ooxmlLang": "zh-TW", "fonts": { "powerpoint": { "major": "Microsoft JhengHei", "minor": "Microsoft JhengHei" }, "google": { "major": "Noto Sans TC", "minor": "Noto Sans TC" } } }, { "tag": "ctg", "script": "Beng", "direction": "ltr", "ooxmlLang": "bn-BD", "fonts": { "powerpoint": { "major": "Vrinda", "minor": "Vrinda" }, "google": { "major": "Noto Sans Bengali", "minor": "Noto Sans Bengali" } } }, { "tag": "hr", "script": "Latn", "direction": "ltr", "ooxmlLang": "hr-HR", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "cs", "script": "Latn", "direction": "ltr", "ooxmlLang": "cs-CZ", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "da", "script": "Latn", "direction": "ltr", "ooxmlLang": "da-DK", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "nl", "script": "Latn", "direction": "ltr", "ooxmlLang": "nl-NL", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "en", "script": "Latn", "direction": "ltr", "ooxmlLang": "en-US", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "en-AU", "script": "Latn", "direction": "ltr", "ooxmlLang": "en-AU", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "en-CA", "script": "Latn", "direction": "ltr", "ooxmlLang": "en-CA", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "en-GB", "script": "Latn", "direction": "ltr", "ooxmlLang": "en-GB", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "en-IN", "script": "Latn", "direction": "ltr", "ooxmlLang": "en-IN", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "en-US", "script": "Latn", "direction": "ltr", "ooxmlLang": "en-US", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "et", "script": "Latn", "direction": "ltr", "ooxmlLang": "et-EE", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "fil", "script": "Latn", "direction": "ltr", "ooxmlLang": "fil-PH", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "fi", "script": "Latn", "direction": "ltr", "ooxmlLang": "fi-FI", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "fr", "script": "Latn", "direction": "ltr", "ooxmlLang": "fr-FR", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "ff", "script": "Latn", "direction": "ltr", "ooxmlLang": "ff-Latn-SN", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "gl", "script": "Latn", "direction": "ltr", "ooxmlLang": "gl-ES", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "ka", "script": "Geor", "direction": "ltr", "ooxmlLang": "ka-GE", "fonts": { "powerpoint": { "major": "Sylfaen", "minor": "Sylfaen" }, "google": { "major": "Noto Sans Georgian", "minor": "Noto Sans Georgian" } } }, { "tag": "de", "script": "Latn", "direction": "ltr", "ooxmlLang": "de-DE", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "el", "script": "Grek", "direction": "ltr", "ooxmlLang": "el-GR", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Noto Sans", "minor": "Noto Sans" } } }, { "tag": "gu", "script": "Gujr", "direction": "ltr", "ooxmlLang": "gu-IN", "fonts": { "powerpoint": { "major": "Shruti", "minor": "Shruti" }, "google": { "major": "Noto Sans Gujarati", "minor": "Noto Sans Gujarati" } } }, { "tag": "ha", "script": "Latn", "direction": "ltr", "ooxmlLang": "ha-Latn-NG", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "he", "script": "Hebr", "direction": "rtl", "ooxmlLang": "he-IL", "fonts": { "powerpoint": { "major": "David", "minor": "David" }, "google": { "major": "Noto Sans Hebrew", "minor": "Noto Sans Hebrew" } } }, { "tag": "hi", "script": "Deva", "direction": "ltr", "ooxmlLang": "hi-IN", "fonts": { "powerpoint": { "major": "Mangal", "minor": "Mangal" }, "google": { "major": "Noto Sans Devanagari", "minor": "Noto Sans Devanagari" } } }, { "tag": "hu", "script": "Latn", "direction": "ltr", "ooxmlLang": "hu-HU", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "ig", "script": "Latn", "direction": "ltr", "ooxmlLang": "ig-NG", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "id", "script": "Latn", "direction": "ltr", "ooxmlLang": "id-ID", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "it", "script": "Latn", "direction": "ltr", "ooxmlLang": "it-IT", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "ja", "script": "Jpan", "direction": "ltr", "ooxmlLang": "ja-JP", "fonts": { "powerpoint": { "major": "Meiryo", "minor": "Meiryo" }, "google": { "major": "Noto Sans JP", "minor": "Noto Sans JP" } } }, { "tag": "kn", "script": "Knda", "direction": "ltr", "ooxmlLang": "kn-IN", "fonts": { "powerpoint": { "major": "Tunga", "minor": "Tunga" }, "google": { "major": "Noto Sans Kannada", "minor": "Noto Sans Kannada" } } }, { "tag": "kk", "script": "Cyrl", "direction": "ltr", "ooxmlLang": "kk-KZ", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Noto Sans", "minor": "Noto Sans" } } }, { "tag": "km", "script": "Khmr", "direction": "ltr", "ooxmlLang": "km-KH", "fonts": { "powerpoint": { "major": "DaunPenh", "minor": "DaunPenh" }, "google": { "major": "Noto Sans Khmer", "minor": "Noto Sans Khmer" } } }, { "tag": "rw", "script": "Latn", "direction": "ltr", "ooxmlLang": "rw-RW", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "ko", "script": "Kore", "direction": "ltr", "ooxmlLang": "ko-KR", "fonts": { "powerpoint": { "major": "Malgun Gothic", "minor": "Malgun Gothic" }, "google": { "major": "Noto Sans KR", "minor": "Noto Sans KR" } } }, { "tag": "kmr", "script": "Latn", "direction": "ltr", "ooxmlLang": "kmr-TR", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "lv", "script": "Latn", "direction": "ltr", "ooxmlLang": "lv-LV", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "lt", "script": "Latn", "direction": "ltr", "ooxmlLang": "lt-LT", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "mk", "script": "Cyrl", "direction": "ltr", "ooxmlLang": "mk-MK", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Noto Sans", "minor": "Noto Sans" } } }, { "tag": "mg", "script": "Latn", "direction": "ltr", "ooxmlLang": "mg-MG", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "zsm", "script": "Latn", "direction": "ltr", "ooxmlLang": "ms-MY", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "ml", "script": "Mlym", "direction": "ltr", "ooxmlLang": "ml-IN", "fonts": { "powerpoint": { "major": "Kartika", "minor": "Kartika" }, "google": { "major": "Noto Sans Malayalam", "minor": "Noto Sans Malayalam" } } }, { "tag": "mi", "script": "Latn", "direction": "ltr", "ooxmlLang": "mi-NZ", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "mr", "script": "Deva", "direction": "ltr", "ooxmlLang": "mr-IN", "fonts": { "powerpoint": { "major": "Mangal", "minor": "Mangal" }, "google": { "major": "Noto Sans Devanagari", "minor": "Noto Sans Devanagari" } } }, { "tag": "mn", "script": "Cyrl", "direction": "ltr", "ooxmlLang": "mn-MN", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Noto Sans Mongolian", "minor": "Noto Sans Mongolian" } } }, { "tag": "ne", "script": "Deva", "direction": "ltr", "ooxmlLang": "ne-NP", "fonts": { "powerpoint": { "major": "Mangal", "minor": "Mangal" }, "google": { "major": "Noto Sans Devanagari", "minor": "Noto Sans Devanagari" } } }, { "tag": "no", "script": "Latn", "direction": "ltr", "ooxmlLang": "nb-NO", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "or", "script": "Orya", "direction": "ltr", "ooxmlLang": "or-IN", "fonts": { "powerpoint": { "major": "Kalinga", "minor": "Kalinga" }, "google": { "major": "Noto Sans Oriya", "minor": "Noto Sans Oriya" } } }, { "tag": "om", "script": "Latn", "direction": "ltr", "ooxmlLang": "om-ET", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "ps", "script": "Arab", "direction": "rtl", "ooxmlLang": "ps-AF", "fonts": { "powerpoint": { "major": "Arial Black", "minor": "Arial" }, "google": { "major": "Noto Naskh Arabic", "minor": "Noto Naskh Arabic" } } }, { "tag": "fa", "script": "Arab", "direction": "rtl", "ooxmlLang": "fa-IR", "fonts": { "powerpoint": { "major": "Arabic Typesetting", "minor": "Arabic Typesetting" }, "google": { "major": "Noto Naskh Arabic", "minor": "Noto Naskh Arabic" } } }, { "tag": "pl", "script": "Latn", "direction": "ltr", "ooxmlLang": "pl-PL", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "pt", "script": "Latn", "direction": "ltr", "ooxmlLang": "pt-BR", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "pa-Guru", "script": "Guru", "direction": "ltr", "ooxmlLang": "pa-IN", "fonts": { "powerpoint": { "major": "Raavi", "minor": "Raavi" }, "google": { "major": "Noto Sans Gurmukhi", "minor": "Noto Sans Gurmukhi" } } }, { "tag": "pa-Arab", "script": "Arab", "direction": "rtl", "ooxmlLang": "pa-Arab-PK", "fonts": { "powerpoint": { "major": "Arial Black", "minor": "Arial" }, "google": { "major": "Noto Nastaliq Urdu", "minor": "Noto Nastaliq Urdu" } } }, { "tag": "ro", "script": "Latn", "direction": "ltr", "ooxmlLang": "ro-RO", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "ru", "script": "Cyrl", "direction": "ltr", "ooxmlLang": "ru-RU", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Noto Sans", "minor": "Noto Sans" } } }, { "tag": "sr-Cyrl", "script": "Cyrl", "direction": "ltr", "ooxmlLang": "sr-Cyrl-RS", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Noto Sans", "minor": "Noto Sans" } } }, { "tag": "sr-Latn", "script": "Latn", "direction": "ltr", "ooxmlLang": "sr-Latn-RS", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "sn", "script": "Latn", "direction": "ltr", "ooxmlLang": "sn-Latn-ZW", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "sk", "script": "Latn", "direction": "ltr", "ooxmlLang": "sk-SK", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "sl", "script": "Latn", "direction": "ltr", "ooxmlLang": "sl-SI", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "so", "script": "Latn", "direction": "ltr", "ooxmlLang": "so-SO", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "es", "script": "Latn", "direction": "ltr", "ooxmlLang": "es-ES", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "sw", "script": "Latn", "direction": "ltr", "ooxmlLang": "sw-KE", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "sv", "script": "Latn", "direction": "ltr", "ooxmlLang": "sv-SE", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "tl", "script": "Latn", "direction": "ltr", "ooxmlLang": "fil-PH", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "tg", "script": "Cyrl", "direction": "ltr", "ooxmlLang": "tg-Cyrl-TJ", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Noto Sans", "minor": "Noto Sans" } } }, { "tag": "ta", "script": "Taml", "direction": "ltr", "ooxmlLang": "ta-IN", "fonts": { "powerpoint": { "major": "Latha", "minor": "Latha" }, "google": { "major": "Noto Sans Tamil", "minor": "Noto Sans Tamil" } } }, { "tag": "te", "script": "Telu", "direction": "ltr", "ooxmlLang": "te-IN", "fonts": { "powerpoint": { "major": "Gautami", "minor": "Gautami" }, "google": { "major": "Noto Sans Telugu", "minor": "Noto Sans Telugu" } } }, { "tag": "th", "script": "Thai", "direction": "ltr", "ooxmlLang": "th-TH", "fonts": { "powerpoint": { "major": "Angsana New", "minor": "Angsana New" }, "google": { "major": "Noto Sans Thai", "minor": "Noto Sans Thai" } } }, { "tag": "tr", "script": "Latn", "direction": "ltr", "ooxmlLang": "tr-TR", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "uk", "script": "Cyrl", "direction": "ltr", "ooxmlLang": "uk-UA", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Noto Sans", "minor": "Noto Sans" } } }, { "tag": "ur", "script": "Arab", "direction": "rtl", "ooxmlLang": "ur-PK", "fonts": { "powerpoint": { "major": "Arabic Typesetting", "minor": "Arabic Typesetting" }, "google": { "major": "Noto Nastaliq Urdu", "minor": "Noto Nastaliq Urdu" } } }, { "tag": "uz-Latn", "script": "Latn", "direction": "ltr", "ooxmlLang": "uz-Latn-UZ", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "vi-Latn", "script": "Latn", "direction": "ltr", "ooxmlLang": "vi-VN", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "xh", "script": "Latn", "direction": "ltr", "ooxmlLang": "xh-ZA", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "yo", "script": "Latn", "direction": "ltr", "ooxmlLang": "yo-NG", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }, { "tag": "zu", "script": "Latn", "direction": "ltr", "ooxmlLang": "zu-ZA", "fonts": { "powerpoint": { "major": "Aptos Display", "minor": "Aptos" }, "google": { "major": "Roboto", "minor": "Roboto" } } }] };
1849
+
1850
+ // src/engine-vocabularies.ts
1851
+ var ENGINE_DEFAULT_THEME = engineDefaultsSource.theme;
1852
+ var ENGINE_DEFAULT_COLOR_SCHEME = engineDefaultsSource.colorScheme;
1853
+ var ENGINE_DEFAULT_FONT_SCHEME = engineDefaultsSource.fontScheme;
1854
+ var ENGINE_DEFAULT_CHART_TYPES = engineDefaultsSource.chartTypes;
1855
+ var CHART_TYPES = engineVocabulariesSource.chartTypes;
1856
+ var SOCIAL_PLATFORMS = engineVocabulariesSource.socialPlatforms;
1857
+ var LANGUAGES = engineVocabulariesSource.languages;
1858
+
1859
+ // src/design-records.ts
1860
+ var isRec = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
1861
+ var rec = (value) => isRec(value) ? value : {};
1862
+ function resolveRecordReference(document, kind2, reference, path, fallback, options, diagnostics) {
1863
+ const object2 = isRec(reference) ? reference : void 0;
1864
+ const id = typeof reference === "string" ? reference : typeof object2?.id === "string" ? object2.id : void 0;
1865
+ if (id === void 0) return { record: { ...fallback, ...object2 } };
1866
+ const found = resolveReference(document, kind2, id, options);
1867
+ if (!found) diagnostics.push(unresolvedReference(document, kind2, id, object2 ? `${path}.id` : path, options));
1868
+ return { record: { ...found ? found.record : fallback, ...object2 }, ...found ? { provenance: provenanceOf(found) } : {} };
1869
+ }
1870
+ function resolveDesignRecords(document, slideIndex, options = {}) {
1871
+ checkCatalogsOption(options.catalogs, "resolveDesignRecords");
1872
+ const deck = rec(document);
1873
+ const slides = Array.isArray(deck.slides) ? deck.slides : [];
1874
+ const own2 = slideIndex === void 0 ? {} : rec(rec(slides[slideIndex]).design);
1875
+ const shared = rec(deck.design);
1876
+ const design = { ...shared, ...own2 };
1877
+ const slidePath = `slides.${slideIndex}.design`;
1878
+ const diagnostics = [];
1879
+ const themePath = own2.theme !== void 0 ? `${slidePath}.theme` : "design.theme";
1880
+ const themeFound = typeof design.theme === "string" ? resolveReference(document, "themes", design.theme, options) : void 0;
1881
+ if (typeof design.theme === "string" && !themeFound) diagnostics.push(unresolvedReference(document, "themes", design.theme, themePath, options));
1882
+ const theme = themeFound ? { ...themeFound.record } : { ...ENGINE_DEFAULT_THEME };
1883
+ const inTheme = { ...options, ...themeFound ? { group: themeFound.group } : {} };
1884
+ const inThemePath = (key) => themeFound?.origin === "document" ? `catalogs.${themeFound.group}.themes.${themeFound.id}.${key}` : themePath;
1885
+ const colorFromDesign = design.colorScheme !== void 0;
1886
+ const colorSchemePath = own2.colorScheme !== void 0 ? `${slidePath}.colorScheme` : shared.colorScheme !== void 0 ? "design.colorScheme" : inThemePath("colorScheme");
1887
+ const color = resolveRecordReference(document, "colorSchemes", colorFromDesign ? design.colorScheme : theme.colorScheme, colorFromDesign ? colorSchemePath : inThemePath("colorScheme"), ENGINE_DEFAULT_COLOR_SCHEME, colorFromDesign ? options : inTheme, diagnostics);
1888
+ const fontFromDesign = design.fontScheme !== void 0;
1889
+ const fontSchemePath = own2.fontScheme !== void 0 ? `${slidePath}.fontScheme` : shared.fontScheme !== void 0 ? "design.fontScheme" : inThemePath("fontScheme");
1890
+ const font = resolveRecordReference(document, "fontSchemes", fontFromDesign ? design.fontScheme : theme.fontScheme, fontSchemePath, ENGINE_DEFAULT_FONT_SCHEME, fontFromDesign ? options : inTheme, diagnostics);
1891
+ const fontReference = fontFromDesign ? design.fontScheme : theme.fontScheme;
1892
+ const fontSchemeReference = typeof fontReference === "string" ? fontReference : isRec(fontReference) && typeof fontReference.id === "string" ? fontReference.id : void 0;
1893
+ const provenance = {
1894
+ ...themeFound ? { theme: provenanceOf(themeFound) } : {},
1895
+ ...color.provenance ? { colorScheme: color.provenance } : {},
1896
+ ...font.provenance ? { fontScheme: font.provenance } : {}
1897
+ };
1898
+ return { theme, colorScheme: color.record, fontScheme: font.record, themePath, colorSchemePath, fontSchemePath, ...fontSchemeReference !== void 0 ? { fontSchemeReference } : {}, provenance, diagnostics };
1899
+ }
1900
+ function resolveFontScheme(document, reference, path, options = {}) {
1901
+ checkCatalogsOption(options.catalogs, "resolveFontScheme");
1902
+ const diagnostics = [];
1903
+ const { record: scheme } = resolveRecordReference(document, "fontSchemes", reference, path, ENGINE_DEFAULT_FONT_SCHEME, options, diagnostics);
1904
+ return { scheme, diagnostics };
1905
+ }
1906
+
2085
1907
  // src/script-fonts.ts
1908
+ function normalizeLanguageFamily(value) {
1909
+ if (value === "latin") return "latin";
1910
+ if (value === "ea" || value === "eastAsian") return "ea";
1911
+ if (value === "cs" || value === "complexScript") return "cs";
1912
+ return void 0;
1913
+ }
2086
1914
  var eastAsianScripts = /* @__PURE__ */ new Set(["Hani", "Hans", "Hant", "Hanb", "Jpan", "Kore", "Hang", "Jamo", "Hira", "Kana", "Hrkt", "Bopo", "Yiii"]);
2087
1915
  var complexScripts = /* @__PURE__ */ new Set([
2088
1916
  "Arab",
@@ -2132,7 +1960,6 @@ var likelyScripts = {
2132
1960
  mn: { script: "Cyrl", regions: { CN: "Mong" } },
2133
1961
  ms: { script: "Latn" }
2134
1962
  };
2135
- var bareLanguageId = /^[a-z][a-z0-9-]*$/;
2136
1963
  function scriptFontRole(script) {
2137
1964
  const code = normalizeScript(script);
2138
1965
  if (code && eastAsianScripts.has(code)) return "eastAsian";
@@ -2191,56 +2018,36 @@ function inferScript(tag) {
2191
2018
  return void 0;
2192
2019
  }
2193
2020
  }
2194
- function inlineRecords(document, kind2) {
2195
- const kinds = isRecord(document.catalogs) ? document.catalogs : {};
2196
- const entry = kinds[kind2];
2197
- return isRecord(entry) && Array.isArray(entry.records) ? entry.records.filter(isRecord) : [];
2198
- }
2199
- function allRecords(document, kind2) {
2200
- return [...inlineRecords(document, kind2), ...catalogs[kind2]];
2201
- }
2202
- function resolveReference(lookup, kind2, reference) {
2203
- if (typeof reference === "string") return lookup(kind2, reference);
2204
- if (!isRecord(reference)) return void 0;
2205
- const base = typeof reference.id === "string" ? lookup(kind2, reference.id) : void 0;
2206
- return { ...base, ...reference };
2207
- }
2208
- function matchLanguageTag(document, tag) {
2021
+ function matchLanguageTag(tag) {
2209
2022
  const wanted = splitTag(tag);
2210
2023
  if (!wanted) return void 0;
2211
- const records = allRecords(document, "languages").filter((record6) => typeof record6.bcp47 === "string");
2212
2024
  const key = canonicalTag(tag).toLowerCase();
2213
- const exact = records.find((record6) => canonicalTag(record6.bcp47).toLowerCase() === key);
2025
+ const exact = LANGUAGES.find((entry) => canonicalTag(entry.tag).toLowerCase() === key);
2214
2026
  if (exact) return exact;
2215
2027
  const language = matchingLanguages[wanted.language] ?? wanted.language;
2216
2028
  const script = wanted.script ?? vendoredScript(language, wanted.region);
2217
- const candidates = records.flatMap((record6) => {
2218
- const parts = splitTag(record6.bcp47);
2029
+ const candidates = LANGUAGES.flatMap((entry) => {
2030
+ const parts = splitTag(entry.tag);
2219
2031
  if (!parts || (matchingLanguages[parts.language] ?? parts.language) !== language) return [];
2220
- const recordScript = normalizeScript(record6.script) ?? parts.script ?? vendoredScript(language, parts.region);
2221
- if (script && recordScript && script !== recordScript) return [];
2222
- return [{ record: record6, region: parts.region }];
2032
+ const entryScript = normalizeScript(entry.script) ?? parts.script ?? vendoredScript(language, parts.region);
2033
+ if (script && entryScript && script !== entryScript) return [];
2034
+ return [{ entry, region: parts.region }];
2223
2035
  });
2224
- return candidates.find((candidate) => wanted.region && candidate.region === wanted.region)?.record ?? candidates.find((candidate) => !candidate.region)?.record ?? candidates[0]?.record;
2036
+ return candidates.find((candidate) => wanted.region && candidate.region === wanted.region)?.entry ?? candidates.find((candidate) => !candidate.region)?.entry ?? candidates[0]?.entry;
2225
2037
  }
2226
- function resolveLanguage(document, lookup, reference) {
2038
+ function resolveLanguage(reference) {
2227
2039
  if (typeof reference === "string") {
2228
2040
  const value = reference.trim();
2229
- const byId = bareLanguageId.test(value) ? lookup("languages", value) : void 0;
2230
- if (byId) return { record: byId, languageId: value };
2231
- if (/^[a-z][a-z0-9+.-]*:/i.test(value) || !splitTag(value)) return void 0;
2232
- const matched = matchLanguageTag(document, value);
2233
- if (matched) return { record: matched, authoredTag: value, languageId: text(matched.id) };
2234
- return inferScript(value) ? { record: {}, authoredTag: value } : void 0;
2041
+ if (!splitTag(value)) return void 0;
2042
+ const known2 = matchLanguageTag(value);
2043
+ if (!known2 && !inferScript(value)) return void 0;
2044
+ return { tag: value, ...known2 ? { known: known2 } : {}, overrides: {} };
2235
2045
  }
2236
2046
  if (!isRecord(reference)) return void 0;
2237
- const authoredTag = text(reference.bcp47);
2238
- if (authoredTag !== void 0 && !splitTag(authoredTag)) return void 0;
2239
- const base = typeof reference.id === "string" ? lookup("languages", reference.id) : authoredTag ? matchLanguageTag(document, authoredTag) : void 0;
2240
- const record6 = { ...base, ...reference };
2241
- const tag = text(record6.bcp47);
2047
+ const tag = text(reference.bcp47);
2242
2048
  if (!tag || !splitTag(tag)) return void 0;
2243
- return { record: record6, authoredTag, authoredOoxmlLang: text(reference.ooxmlLang), languageId: text(base?.id) };
2049
+ const known = matchLanguageTag(tag);
2050
+ return { tag, ...known ? { known } : {}, overrides: reference };
2244
2051
  }
2245
2052
  function pairFamilies(value) {
2246
2053
  if (!isRecord(value)) return void 0;
@@ -2250,57 +2057,55 @@ function pairFamilies(value) {
2250
2057
  const body = minor ?? major;
2251
2058
  return heading && body ? { heading, body } : void 0;
2252
2059
  }
2253
- function schemeServesLanguage(scheme, language) {
2060
+ function schemeServesLanguage(scheme, tag, script) {
2254
2061
  const entries = Array.isArray(scheme.languages) ? scheme.languages.filter((entry) => typeof entry === "string") : [];
2255
2062
  if (entries.length === 0) return true;
2256
- const name = text(language.name)?.toLowerCase();
2257
- if (!name) return false;
2258
- const base = name.replace(/\s*\([^)]*\)\s*$/, "");
2063
+ const wanted = splitTag(tag);
2064
+ if (!wanted) return false;
2065
+ const language = matchingLanguages[wanted.language] ?? wanted.language;
2259
2066
  return entries.some((entry) => {
2260
- const value = entry.trim().toLowerCase();
2261
- return value === name || value === base;
2067
+ const parts = splitTag(entry);
2068
+ if (!parts || (matchingLanguages[parts.language] ?? parts.language) !== language) return false;
2069
+ const entryScript = parts.script ?? vendoredScript(language, parts.region);
2070
+ return !entryScript || entryScript === script;
2262
2071
  });
2263
2072
  }
2264
2073
  function resolveScriptFonts(input, options = {}) {
2265
2074
  const document = isRecord(input) ? input : {};
2266
- const lookup = (kind2, id) => inlineRecords(document, kind2).find((record7) => record7.id === id) ?? catalogs[kind2].find((record7) => record7.id === id);
2267
- let design = isRecord(document.design) ? document.design : {};
2268
2075
  if (options.slideIndex !== void 0) {
2269
2076
  const slides = Array.isArray(document.slides) ? document.slides : [];
2270
2077
  if (!Number.isInteger(options.slideIndex) || options.slideIndex < 0 || options.slideIndex >= slides.length) {
2271
2078
  throw new RangeError(`slideIndex must be an integer between 0 and ${slides.length - 1}.`);
2272
2079
  }
2273
- const slide = slides[options.slideIndex];
2274
- if (isRecord(slide) && isRecord(slide.design)) design = { ...design, ...slide.design };
2275
2080
  }
2276
- const theme = resolveReference(lookup, "themes", design.theme ?? "minimal") ?? {};
2277
- const scheme = resolveFontSchemeReference(design.fontScheme ?? theme.fontScheme ?? DEFAULT_FONT_SCHEME, (id) => lookup("fontSchemes", id)).scheme;
2081
+ const catalogs = { catalogs: checkCatalogsOption(options.catalogs, "resolveScriptFonts") };
2082
+ const scheme = resolveDesignRecords(document, options.slideIndex, catalogs).fontScheme;
2278
2083
  const latin = resolveFontFamilies(scheme);
2279
- const fromOption = options.language !== void 0 ? resolveLanguage(document, lookup, options.language) : void 0;
2280
- const fromDocument = fromOption ? void 0 : resolveLanguage(document, lookup, document.language);
2084
+ const fromOption = options.language !== void 0 ? resolveLanguage(options.language) : void 0;
2085
+ const fromDocument = fromOption ? void 0 : resolveLanguage(document.language);
2281
2086
  const requestedDefault = text(options.defaultLanguage);
2282
2087
  const fallbackTag = requestedDefault && splitTag(requestedDefault) ? requestedDefault : "en-US";
2283
- const language = fromOption ?? fromDocument ?? resolveLanguage(document, lookup, fallbackTag) ?? { record: {}, authoredTag: fallbackTag };
2088
+ const language = fromOption ?? fromDocument ?? resolveLanguage(fallbackTag) ?? { tag: fallbackTag, overrides: {} };
2284
2089
  const languageSource = fromOption ? "option" : fromDocument ? "document" : "default";
2285
- const record6 = language.record;
2286
- const bcp47 = canonicalTag(language.authoredTag ?? text(record6.bcp47) ?? fallbackTag);
2287
- const curated = text(record6.ooxmlLang);
2288
- const lang = language.authoredOoxmlLang ? canonicalTag(language.authoredOoxmlLang) : language.authoredTag && splitTag(language.authoredTag)?.region ? canonicalTag(language.authoredTag) : curated ? canonicalTag(curated) : bcp47;
2090
+ const overrides = language.overrides;
2091
+ const known = language.known;
2092
+ const bcp47 = canonicalTag(language.tag);
2093
+ const authoredOoxml = text(overrides.ooxmlLang);
2094
+ const lang = authoredOoxml ? canonicalTag(authoredOoxml) : splitTag(language.tag)?.region ? bcp47 : known ? canonicalTag(known.ooxmlLang) : bcp47;
2289
2095
  const parts = splitTag(bcp47);
2290
- const script = normalizeScript(record6.script) ?? (language.languageId ? parts?.script ?? (parts ? vendoredScript(matchingLanguages[parts.language] ?? parts.language, parts.region) : void 0) ?? normalizeScript(matchLanguageTag({}, bcp47)?.script) : inferScript(bcp47)) ?? "Zzzz";
2096
+ const script = normalizeScript(overrides.script) ?? (known ? normalizeScript(known.script) ?? parts?.script ?? (parts ? vendoredScript(matchingLanguages[parts.language] ?? parts.language, parts.region) : void 0) : inferScript(bcp47)) ?? "Zzzz";
2291
2097
  const scriptRole = scriptFontRole(script);
2292
- const declaredDirection = record6.direction;
2098
+ const declaredDirection = overrides.direction ?? known?.direction;
2293
2099
  const direction = declaredDirection === "rtl" || declaredDirection === "ltr" ? declaredDirection : rtlScripts.has(script) ? "rtl" : "ltr";
2294
- const app = options.app ?? "PowerPoint";
2295
- const preferred = app === "Google Slides" ? record6.googleFontScheme : record6.fontScheme;
2296
- const alternate = app === "Google Slides" ? record6.fontScheme : record6.googleFontScheme;
2297
- const languageScheme = resolveReference(lookup, "fontSchemes", preferred) ?? resolveReference(lookup, "fontSchemes", alternate);
2100
+ const app = options.app ?? "powerpoint";
2101
+ const named = (key) => typeof overrides[key] === "string" ? resolveReference(document, "fontSchemes", overrides[key], catalogs)?.record : void 0;
2102
+ const languageScheme = app === "google-slides" ? named("googleFontScheme") ?? known?.fonts.google ?? named("fontScheme") : named("fontScheme") ?? known?.fonts.powerpoint ?? named("googleFontScheme");
2298
2103
  const languageFamilies = pairFamilies(languageScheme);
2299
- const schemeAdmitsLanguage = schemeServesLanguage(scheme, record6);
2104
+ const schemeAdmitsLanguage = schemeServesLanguage(scheme, bcp47, script);
2300
2105
  const slot = (role, family) => {
2301
2106
  const explicit = pairFamilies(scheme[role]);
2302
2107
  if (explicit) return { ...explicit, source: "fontScheme" };
2303
- if (scheme.languageFamily === family && schemeAdmitsLanguage) return { ...latin, source: "schemeFamily" };
2108
+ if (normalizeLanguageFamily(scheme.languageFamily) === family && schemeAdmitsLanguage) return { ...latin, source: "schemeFamily" };
2304
2109
  if (scriptRole === role && languageFamilies) return { ...languageFamilies, source: "language" };
2305
2110
  return { heading: latin.heading, body: latin.body, source: "latin" };
2306
2111
  };
@@ -2318,7 +2123,6 @@ function resolveScriptFonts(input, options = {}) {
2318
2123
  ...body,
2319
2124
  lang,
2320
2125
  bcp47,
2321
- ...language.languageId ? { languageId: language.languageId } : {},
2322
2126
  languageSource,
2323
2127
  script,
2324
2128
  scriptRole,
@@ -2403,10 +2207,10 @@ function listNumbers(items, numbering) {
2403
2207
  const levels = resolveNumbering(numbering);
2404
2208
  const counters = [];
2405
2209
  return items.map((item, index) => {
2406
- const object = isObject(item) ? item : void 0;
2407
- const level = object?.level === void 0 ? 0 : object.level;
2210
+ const object2 = isObject(item) ? item : void 0;
2211
+ const level = object2?.level === void 0 ? 0 : object2.level;
2408
2212
  if (typeof level !== "number" || !Number.isInteger(level) || level < 0) throw new RangeError("List levels must be nonnegative integers.");
2409
- const own2 = object?.start;
2213
+ const own2 = object2?.start;
2410
2214
  if (own2 !== void 0 && (typeof own2 !== "number" || !Number.isInteger(own2) || own2 < 1 || own2 > MAX_NUMBERING_VALUE)) throw new RangeError(`A list item start must be an integer from 1 to ${MAX_NUMBERING_VALUE}.`);
2411
2215
  const { style: authored, start, suffix } = numberingAtLevel(levels, level);
2412
2216
  const previous = counters[level];
@@ -2425,8 +2229,8 @@ function sliceNumberedItems(items, numbering, from, to = items.length) {
2425
2229
  const wanted = whole[from + index].value;
2426
2230
  if (listNumbers(result.slice(0, index + 1), numbering)[index].value === wanted) continue;
2427
2231
  const item = result[index];
2428
- const object = isObject(item) ? item : { text: item };
2429
- result[index] = { ...object, start: wanted };
2232
+ const object2 = isObject(item) ? item : { text: item };
2233
+ result[index] = { ...object2, start: wanted };
2430
2234
  }
2431
2235
  return result;
2432
2236
  }
@@ -2479,6 +2283,7 @@ var schemeColorRoles = /* @__PURE__ */ new Set([
2479
2283
  "accent",
2480
2284
  "background",
2481
2285
  "surface",
2286
+ "surfaceAlt",
2482
2287
  "text",
2483
2288
  "textSecondary"
2484
2289
  ]);
@@ -2522,6 +2327,11 @@ function resolveColorRef(reference, options) {
2522
2327
  const roleKey = reference;
2523
2328
  const fromRoles = roles?.[roleKey];
2524
2329
  if (fromRoles) return normalizeHexColor(fromRoles) ?? fallback;
2330
+ if (reference === "surfaceAlt") {
2331
+ const surface = resolveColorRef("surface", { colorScheme, roles, variables, fallback: "#FFFFFF" });
2332
+ const text2 = resolveColorRef("text", { colorScheme, roles, variables, fallback: textColorForFill(surface, "#000000") });
2333
+ return surfaceAltColor(surface, text2);
2334
+ }
2525
2335
  const fromScheme = normalizeHexColor(colorScheme[reference]);
2526
2336
  if (fromScheme) return fromScheme;
2527
2337
  const slot = defaultRoleSlots[reference];
@@ -2530,6 +2340,52 @@ function resolveColorRef(reference, options) {
2530
2340
  if (schemeColorSlots.has(reference)) return schemeSlot(colorScheme, reference, fallback);
2531
2341
  return fallback;
2532
2342
  }
2343
+ var DARK_BACKGROUND_LUMINANCE = 0.179;
2344
+ function isDarkColor(color) {
2345
+ const hex = normalizeHexColor(color);
2346
+ const value = hex ? luminance(hex) : void 0;
2347
+ return value !== void 0 && value < DARK_BACKGROUND_LUMINANCE;
2348
+ }
2349
+ function defaultSlideBackground(colorScheme) {
2350
+ return keepAlpha(colorScheme.background) ?? slotKeepingAlpha(colorScheme, "light1", "#FFFFFF");
2351
+ }
2352
+ function keepAlpha(value) {
2353
+ if (typeof value !== "string") return void 0;
2354
+ const hex = value.trim();
2355
+ if (/^#[0-9a-f]{8}$/i.test(hex)) return hex.toUpperCase();
2356
+ return normalizeHexColor(hex);
2357
+ }
2358
+ function slotKeepingAlpha(colorScheme, slot, fallback) {
2359
+ return keepAlpha(colorScheme[slot]) ?? fallback;
2360
+ }
2361
+ var DEFAULT_HYPERLINK = "#0563C1";
2362
+ var DEFAULT_FOLLOWED_HYPERLINK = "#954F72";
2363
+ var MIN_LINK_CONTRAST = 4.5;
2364
+ function readableLink(link, background, text2) {
2365
+ const linkHex = normalizeHexColor(link), backgroundHex = normalizeHexColor(background);
2366
+ const contrast2 = linkHex && backgroundHex ? colorContrast(linkHex, backgroundHex) : void 0;
2367
+ return contrast2 !== void 0 && contrast2 < MIN_LINK_CONTRAST ? text2 : link;
2368
+ }
2369
+ function resolveColorRoles(colorScheme, options = {}) {
2370
+ const slot = (name, fallback) => slotKeepingAlpha(colorScheme, name, fallback);
2371
+ const background = keepAlpha(options.background) ?? defaultSlideBackground(colorScheme);
2372
+ const dark = isDarkColor(background);
2373
+ const text2 = dark ? slot("light1", "#FFFFFF") : keepAlpha(colorScheme.text) ?? slot("dark1", "#111827");
2374
+ const surface = keepAlpha(colorScheme.surface) ?? (dark ? slot("dark2", "#1E293B") : slot("light2", "#F8FAFC"));
2375
+ return {
2376
+ primary: keepAlpha(colorScheme.primary) ?? slot("accent1", "#2563EB"),
2377
+ secondary: keepAlpha(colorScheme.secondary) ?? slot("accent2", "#0F766E"),
2378
+ accent: keepAlpha(colorScheme.accent) ?? slot("accent3", "#F59E0B"),
2379
+ background,
2380
+ surface,
2381
+ surfaceAlt: surfaceAltColor(surface, text2),
2382
+ text: text2,
2383
+ textSecondary: keepAlpha(colorScheme.textSecondary) ?? (dark ? slot("light2", "#E2E8F0") : slot("dark2", "#334155")),
2384
+ hyperlink: readableLink(slot("hyperlink", DEFAULT_HYPERLINK), background, text2),
2385
+ followedHyperlink: slot("followedHyperlink", DEFAULT_FOLLOWED_HYPERLINK),
2386
+ dark
2387
+ };
2388
+ }
2533
2389
  function luminance(value) {
2534
2390
  if (typeof value !== "string") return void 0;
2535
2391
  let hex = value.trim();
@@ -2547,19 +2403,19 @@ function colorContrast(foreground, background) {
2547
2403
  return a === void 0 || b === void 0 ? void 0 : (Math.max(a, b) + 0.05) / (Math.min(a, b) + 0.05);
2548
2404
  }
2549
2405
  function textColorForFill(fill, preferred) {
2550
- const background = luminance(fill), contrast = colorContrast(preferred, fill);
2551
- if (background === void 0 || contrast === void 0 || contrast >= 4.5) return preferred;
2406
+ const background = luminance(fill), contrast2 = colorContrast(preferred, fill);
2407
+ if (background === void 0 || contrast2 === void 0 || contrast2 >= 4.5) return preferred;
2552
2408
  return (background + 0.05) / 0.05 >= 1.05 / (background + 0.05) ? "#000000" : "#FFFFFF";
2553
2409
  }
2554
2410
  function chartColorForFill(fill, preferred) {
2555
- const contrast = colorContrast(preferred, fill);
2556
- if (contrast === void 0 || contrast >= 3) return preferred;
2411
+ const contrast2 = colorContrast(preferred, fill);
2412
+ if (contrast2 === void 0 || contrast2 >= 3) return preferred;
2557
2413
  let hex = preferred.trim();
2558
2414
  if (hex.length === 4) hex = `#${[...hex.slice(1)].map((c) => c + c).join("")}`;
2559
- const channels = [1, 3, 5].map((offset) => Number.parseInt(hex.slice(offset, offset + 2), 16));
2415
+ const channels2 = [1, 3, 5].map((offset) => Number.parseInt(hex.slice(offset, offset + 2), 16));
2560
2416
  for (let step = 1; step <= 255; step++) {
2561
2417
  const candidates = [0, 255].map((target) => {
2562
- const color = `#${channels.map((channel) => Math.round(channel + (target - channel) * step / 255).toString(16).padStart(2, "0")).join("")}`.toUpperCase();
2418
+ const color = `#${channels2.map((channel) => Math.round(channel + (target - channel) * step / 255).toString(16).padStart(2, "0")).join("")}`.toUpperCase();
2563
2419
  return { color, contrast: colorContrast(color, fill) ?? 0 };
2564
2420
  }).sort((a, b) => b.contrast - a.contrast);
2565
2421
  const best = candidates[0];
@@ -2581,8 +2437,8 @@ var toLinear = (channel) => {
2581
2437
  return n <= 0.04045 ? n / 12.92 : ((n + 0.055) / 1.055) ** 2.4;
2582
2438
  };
2583
2439
  var fromLinear = (value) => 255 * (value <= 31308e-7 ? value * 12.92 : 1.055 * value ** (1 / 2.4) - 0.055);
2584
- function labOf(channels) {
2585
- const [r, g, b] = channels.map(toLinear);
2440
+ function labOf(channels2) {
2441
+ const [r, g, b] = channels2.map(toLinear);
2586
2442
  const f = (t) => t > 216 / 24389 ? Math.cbrt(t) : (24389 / 27 * t + 16) / 116;
2587
2443
  const fx = f((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / D65[0]), fy = f(0.2126729 * r + 0.7151522 * g + 0.072175 * b), fz = f((0.0193339 * r + 0.119192 * g + 0.9503041 * b) / D65[2]);
2588
2444
  return [116 * fy - 16, 500 * (fx - fy), 200 * (fy - fz)];
@@ -2598,21 +2454,21 @@ function labToLinear([l, a, b]) {
2598
2454
  ];
2599
2455
  return rgb.every((channel) => channel >= -5e-4 && channel <= 1.0005) ? rgb : void 0;
2600
2456
  }
2601
- var hexOfChannels = (channels) => `#${channels.map((channel) => Math.max(0, Math.min(255, Math.round(channel))).toString(16).padStart(2, "0")).join("").toUpperCase()}`;
2457
+ var hexOfChannels = (channels2) => `#${channels2.map((channel) => Math.max(0, Math.min(255, Math.round(channel))).toString(16).padStart(2, "0")).join("").toUpperCase()}`;
2602
2458
  function labWithLightness(l, a, b) {
2603
2459
  const chroma = Math.hypot(a, b), hue = Math.atan2(b, a);
2604
2460
  const at3 = (scale) => labToLinear([l, Math.cos(hue) * chroma * scale, Math.sin(hue) * chroma * scale]);
2605
- let linear = at3(1);
2606
- if (!linear) {
2461
+ let linear2 = at3(1);
2462
+ if (!linear2) {
2607
2463
  let low = 0, high = 1;
2608
2464
  for (let step = 0; step < 24; step++) {
2609
2465
  const mid = (low + high) / 2;
2610
2466
  if (at3(mid)) low = mid;
2611
2467
  else high = mid;
2612
2468
  }
2613
- linear = at3(low) ?? [0, 0, 0];
2469
+ linear2 = at3(low) ?? [0, 0, 0];
2614
2470
  }
2615
- return hexOfChannels(linear.map((channel) => fromLinear(Math.max(0, Math.min(1, channel)))));
2471
+ return hexOfChannels(linear2.map((channel) => fromLinear(Math.max(0, Math.min(1, channel)))));
2616
2472
  }
2617
2473
  function labDifference(a, b) {
2618
2474
  return Math.hypot(a[0] - b[0], a[1] - b[1], a[2] - b[2]);
@@ -2621,15 +2477,15 @@ var CHART_SERIES_SHORTFALL_WEIGHT = 8;
2621
2477
  function chartPaletteForFill(fill, palette) {
2622
2478
  const opaqueFill = colorContrast(fill, fill) !== void 0;
2623
2479
  const preferredLab = palette.map((color) => {
2624
- const channels = opaqueChannels(color);
2625
- return channels ? labOf(channels) : void 0;
2480
+ const channels2 = opaqueChannels(color);
2481
+ return channels2 ? labOf(channels2) : void 0;
2626
2482
  });
2627
2483
  const adjusted = palette.map((color) => chartColorForFill(fill, color));
2628
2484
  const kept = palette.map((color, index) => opaqueFill && preferredLab[index] !== void 0 && adjusted[index] === color);
2629
2485
  const placed = palette.map((_, index) => kept[index] || !opaqueFill || !preferredLab[index] ? adjusted[index] : void 0);
2630
2486
  const placedLab = placed.map((color) => {
2631
- const channels = color === void 0 ? void 0 : opaqueChannels(color);
2632
- return channels ? labOf(channels) : void 0;
2487
+ const channels2 = color === void 0 ? void 0 : opaqueChannels(color);
2488
+ return channels2 ? labOf(channels2) : void 0;
2633
2489
  });
2634
2490
  palette.forEach((_, index) => {
2635
2491
  const wanted = preferredLab[index], base = adjusted[index];
@@ -2653,8 +2509,8 @@ function chartPaletteForFill(fill, palette) {
2653
2509
  }
2654
2510
  let best = { color: base, lab: baseLab, cost: cost({ moved: 0, ...start }), moved: 0 };
2655
2511
  for (let step = 0; step <= 400; step++) {
2656
- const color = labWithLightness(step / 4, wanted[1], wanted[2]), contrast = colorContrast(color, fill);
2657
- if (contrast === void 0 || contrast < 3) continue;
2512
+ const color = labWithLightness(step / 4, wanted[1], wanted[2]), contrast2 = colorContrast(color, fill);
2513
+ if (contrast2 === void 0 || contrast2 < 3) continue;
2658
2514
  const lab = labOf(opaqueChannels(color)), moved = Math.abs(lab[0] - baseLab[0]), total = cost({ moved, ...shortfall(lab) });
2659
2515
  if (total < best.cost - 1e-9 || Math.abs(total - best.cost) <= 1e-9 && moved < best.moved) best = { color, lab, cost: total, moved };
2660
2516
  }
@@ -2663,6 +2519,1113 @@ function chartPaletteForFill(fill, palette) {
2663
2519
  });
2664
2520
  return placed;
2665
2521
  }
2522
+ var CHART_HIGHLIGHT_MUTED_MIX = 0.3;
2523
+ var CHART_HIGHLIGHT_MUTED_MIN_CONTRAST = 1.6;
2524
+ var mixChannels = (from, to, amount) => hexOfChannels(from.map((channel, index) => channel + (to[index] - channel) * amount));
2525
+ function chartHighlightColors(surface, primary, text2) {
2526
+ const fill = normalizeHexColor(surface) ?? "#FFFFFF";
2527
+ const accent = chartColorForFill(fill, normalizeHexColor(primary) ?? "#000000");
2528
+ const ink = normalizeHexColor(text2) ?? textColorForFill(fill, "#000000");
2529
+ const from = opaqueChannels(fill), to = opaqueChannels(ink);
2530
+ let muted = mixChannels(from, to, CHART_HIGHLIGHT_MUTED_MIX);
2531
+ for (let amount = CHART_HIGHLIGHT_MUTED_MIX; (colorContrast(muted, fill) ?? Infinity) < CHART_HIGHLIGHT_MUTED_MIN_CONTRAST && amount < 1; ) {
2532
+ amount = Math.min(1, amount + 0.02);
2533
+ muted = mixChannels(from, to, amount);
2534
+ }
2535
+ return { accent, muted };
2536
+ }
2537
+ var SURFACE_ALT_MIX = 0.1;
2538
+ var SURFACE_ALT_MIN_CONTRAST = 1.1;
2539
+ function surfaceAltColor(surface, text2) {
2540
+ const fill = normalizeHexColor(surface) ?? "#FFFFFF";
2541
+ const ink = normalizeHexColor(text2) ?? textColorForFill(fill, "#000000");
2542
+ const from = opaqueChannels(fill), toText = opaqueChannels(ink);
2543
+ const step = (color) => (colorContrast(color, fill) ?? 1) >= SURFACE_ALT_MIN_CONTRAST;
2544
+ const readable = (color) => (colorContrast(ink, color) ?? 0) >= 4.5 || (colorContrast(ink, color) ?? 0) >= (colorContrast(ink, fill) ?? 0);
2545
+ for (let amount = SURFACE_ALT_MIX; amount <= 0.5 + 1e-9; amount += 0.02) {
2546
+ const band = mixChannels(from, toText, amount);
2547
+ if (!readable(band)) break;
2548
+ if (step(band)) return band;
2549
+ }
2550
+ const away = (luminance(ink) ?? 0) > (luminance(fill) ?? 0) ? [0, 0, 0] : [255, 255, 255];
2551
+ for (let amount = SURFACE_ALT_MIX; amount <= 1 + 1e-9; amount += 0.02) {
2552
+ const band = mixChannels(from, away, Math.min(1, amount));
2553
+ if (step(band)) return band;
2554
+ }
2555
+ return mixChannels(from, toText, SURFACE_ALT_MIX);
2556
+ }
2557
+
2558
+ // src/legible-color.ts
2559
+ var channels = (hex) => [1, 3, 5].map((offset) => Number.parseInt(hex.slice(offset, offset + 2), 16));
2560
+ var toHex = (values) => `#${values.map((value) => Math.max(0, Math.min(255, Math.round(value))).toString(16).padStart(2, "0")).join("").toUpperCase()}`;
2561
+ var linear = (value) => {
2562
+ const n = value / 255;
2563
+ return n <= 0.04045 ? n / 12.92 : ((n + 0.055) / 1.055) ** 2.4;
2564
+ };
2565
+ var luminance2 = (hex) => {
2566
+ const [r, g, b] = channels(hex);
2567
+ return 0.2126 * linear(r) + 0.7152 * linear(g) + 0.0722 * linear(b);
2568
+ };
2569
+ var contrast = (a, b) => {
2570
+ const x = luminance2(a), y = luminance2(b);
2571
+ return (Math.max(x, y) + 0.05) / (Math.min(x, y) + 0.05);
2572
+ };
2573
+ var normalize = (value) => {
2574
+ if (typeof value !== "string") return void 0;
2575
+ const text2 = value.trim();
2576
+ if (/^#[0-9a-f]{3}$/i.test(text2)) return `#${[...text2.slice(1)].map((c) => c + c).join("")}`.toUpperCase();
2577
+ return /^#[0-9a-f]{6}([0-9a-f]{2})?$/i.test(text2) ? text2.slice(0, 7).toUpperCase() : void 0;
2578
+ };
2579
+ function toHsl(hex) {
2580
+ const [r, g, b] = channels(hex).map((value) => value / 255);
2581
+ const max = Math.max(r, g, b), min = Math.min(r, g, b), l = (max + min) / 2, d = max - min;
2582
+ if (d === 0) return [0, 0, l];
2583
+ const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
2584
+ const h = max === r ? (g - b) / d + (g < b ? 6 : 0) : max === g ? (b - r) / d + 2 : (r - g) / d + 4;
2585
+ return [h * 60, s, l];
2586
+ }
2587
+ function fromHsl(h, s, l) {
2588
+ const hue = (h % 360 + 360) % 360, c = (1 - Math.abs(2 * l - 1)) * s, x = c * (1 - Math.abs(hue / 60 % 2 - 1)), m = l - c / 2;
2589
+ const [r, g, b] = hue < 60 ? [c, x, 0] : hue < 120 ? [x, c, 0] : hue < 180 ? [0, c, x] : hue < 240 ? [0, x, c] : hue < 300 ? [x, 0, c] : [c, 0, x];
2590
+ return toHex([(r + m) * 255, (g + m) * 255, (b + m) * 255]);
2591
+ }
2592
+ function legible(foreground, background, minimum) {
2593
+ if (contrast(foreground, background) >= minimum) return foreground;
2594
+ const [h, s, l] = toHsl(foreground), preferred = luminance2(background) < 0.5 ? 1 : -1;
2595
+ for (const direction of [preferred, -preferred]) {
2596
+ for (let step = 1; step <= 100; step++) {
2597
+ const lightness = l + direction * step / 100;
2598
+ if (lightness < 0 || lightness > 1) break;
2599
+ const candidate = fromHsl(h, s, lightness);
2600
+ if (contrast(candidate, background) >= minimum) return candidate;
2601
+ }
2602
+ }
2603
+ return contrast("#FFFFFF", background) >= contrast("#000000", background) ? "#FFFFFF" : "#000000";
2604
+ }
2605
+
2606
+ // src/code-syntax.ts
2607
+ var CODE_HIGHLIGHT_MAX_LENGTH = 2e5;
2608
+ var CODE_SYNTAX_MIN_CONTRAST = 4.5;
2609
+ var CODE_PANEL_BACKGROUND = "#111827";
2610
+ var CODE_PANEL_FOREGROUND = "#E5E7EB";
2611
+ var set = (words) => new Set((words ?? "").split(/\s+/).filter(Boolean));
2612
+ var JS_KEYWORDS = "break case catch class const continue debugger default delete do else enum export extends finally for from function if import in instanceof let new of return static super switch this throw try typeof var void while with yield async await as get set declare namespace module abstract implements interface private protected public readonly override keyof satisfies type is infer";
2613
+ var JS = { line: ["//"], block: [["/*", "*/"]], strings: "'\"`", keywords: JS_KEYWORDS, literals: "true false null undefined NaN Infinity", types: "string number boolean object symbol bigint never unknown any void", defs: { function: "function", class: "type", interface: "type", enum: "type", type: "type" }, capsTypes: true, calls: true, decorators: true };
2614
+ var C_LIKE_KEYWORDS = "auto break case catch char class const constexpr continue default delete do double else enum explicit extern false final float for friend goto if inline int long mutable namespace new noexcept nullptr operator override private protected public register return short signed sizeof static struct switch template this throw true try typedef typename union unsigned using virtual void volatile while";
2615
+ var LANGUAGES2 = {
2616
+ javascript: JS,
2617
+ typescript: JS,
2618
+ python: { line: ["#"], strings: `'"`, triple: ['"""', "'''"], keywords: "and as assert async await break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield match case self cls", literals: "True False None", types: "int float str bool bytes list dict set tuple object type", defs: { def: "function", class: "type" }, capsTypes: true, calls: true, decorators: true },
2619
+ rust: { line: ["//"], block: [["/*", "*/"]], strings: '"', rawStrings: "r", keywords: "as async await break const continue crate dyn else enum extern fn for if impl in let loop match mod move mut pub ref return self Self static struct super trait type unsafe use where while", literals: "true false", types: "i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 bool char str String Vec Option Result Box", defs: { fn: "function", struct: "type", enum: "type", trait: "type", type: "type", mod: "type" }, capsTypes: true, calls: true, macros: true },
2620
+ go: { line: ["//"], block: [["/*", "*/"]], strings: "\"'`", noEscapes: "`", keywords: "break case chan const continue default defer else fallthrough for func go goto if import interface map package range return select struct switch type var", literals: "true false nil iota", types: "int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr float32 float64 complex64 complex128 string bool byte rune error any", defs: { func: "function", type: "type" }, capsTypes: true, calls: true },
2621
+ bash: { line: ["#"], strings: `'"`, noEscapes: "'", keywords: "if then else elif fi for while until do done case esac in function select time return exit break continue export local readonly declare unset set shift source alias trap eval exec", literals: "true false", variables: true, calls: false },
2622
+ json: { line: ["//"], block: [["/*", "*/"]], strings: '"', literals: "true false null", quotedKeys: true },
2623
+ yaml: { kind: "yaml" },
2624
+ toml: { kind: "ini", line: ["#"] },
2625
+ ini: { kind: "ini", line: ["#", ";"] },
2626
+ markup: { kind: "markup" },
2627
+ css: { kind: "css" },
2628
+ sql: { line: ["--"], block: [["/*", "*/"]], strings: `'"`, ci: true, keywords: "add all alter and any as asc between by case check column commit constraint create cross database default delete desc distinct drop else end exists foreign from full group having if in index inner insert into is join key left like limit not null offset on or order outer primary references replace right rollback select set table then top union unique update values view when where with", literals: "true false", types: "int integer bigint smallint decimal numeric float real double varchar char text date time timestamp boolean serial uuid json" },
2629
+ java: { line: ["//"], block: [["/*", "*/"]], strings: `"'`, keywords: "abstract assert break case catch class const continue default do else enum extends final finally for goto if implements import instanceof interface native new package private protected public return static strictfp super switch synchronized this throw throws transient try var volatile while record sealed permits", literals: "true false null", types: "boolean byte char double float int long short void String Object", defs: { class: "type", interface: "type", enum: "type", record: "type" }, capsTypes: true, calls: true, decorators: true },
2630
+ csharp: { line: ["//"], block: [["/*", "*/"]], strings: `"'`, keywords: "abstract as async await base break case catch checked class const continue default delegate do else enum event explicit extern finally fixed for foreach goto if implicit in interface internal is lock namespace new operator out override params private protected public readonly ref return sealed sizeof stackalloc static struct switch this throw try typeof unchecked unsafe using var virtual volatile while record init required", literals: "true false null", types: "bool byte char decimal double float int long object sbyte short string uint ulong ushort void dynamic", defs: { class: "type", interface: "type", struct: "type", enum: "type", record: "type" }, capsTypes: true, calls: true, decorators: false },
2631
+ kotlin: { line: ["//"], block: [["/*", "*/"]], strings: `"'`, triple: ['"""'], keywords: "abstract actual annotation as break by catch class companion const constructor continue crossinline data do else enum expect external final finally for fun get if import in infix init inline inner interface internal is it lateinit lazy noinline object open operator out override package private protected public reified return sealed set super suspend tailrec this throw try typealias val var vararg when where while", literals: "true false null", types: "Int Long Short Byte Float Double Boolean Char String Unit Any Nothing", defs: { fun: "function", class: "type", interface: "type", object: "type" }, capsTypes: true, calls: true, decorators: true },
2632
+ swift: { line: ["//"], block: [["/*", "*/"]], strings: '"', triple: ['"""'], keywords: "actor as associatedtype async await break case catch class continue default defer deinit do else enum extension fallthrough fileprivate for func guard if import in init inout internal is let nonisolated open operator private protocol public repeat rethrows return self Self static struct subscript super switch throw throws try typealias var where while", literals: "true false nil", types: "Int Double Float Bool String Character Array Dictionary Set Optional Any", defs: { func: "function", class: "type", struct: "type", enum: "type", protocol: "type", extension: "type" }, capsTypes: true, calls: true, decorators: true },
2633
+ ruby: { line: ["#"], strings: `'"`, keywords: "alias and begin break case class def defined do else elsif end ensure for if in module next not or redo rescue retry return self super then undef unless until when while yield require require_relative include extend attr_accessor attr_reader attr_writer private protected public", literals: "true false nil", defs: { def: "function", class: "type", module: "type" }, capsTypes: true, calls: true },
2634
+ php: { line: ["//", "#"], block: [["/*", "*/"]], strings: `'"`, keywords: "abstract and array as break callable case catch class clone const continue declare default do echo else elseif empty enddeclare endfor endforeach endif endswitch endwhile extends final finally fn for foreach function global goto if implements include include_once instanceof insteadof interface isset list match namespace new or print private protected public readonly require require_once return static switch throw trait try unset use var while xor yield", literals: "true false null TRUE FALSE NULL", defs: { function: "function", class: "type", interface: "type", trait: "type" }, capsTypes: true, calls: true, variables: true },
2635
+ c: { line: ["//"], block: [["/*", "*/"]], strings: `"'`, keywords: C_LIKE_KEYWORDS, literals: "true false NULL nullptr", types: "size_t ssize_t int8_t int16_t int32_t int64_t uint8_t uint16_t uint32_t uint64_t bool FILE", calls: true, capsTypes: false, directives: true, defs: { struct: "type", enum: "type", union: "type", class: "type" } },
2636
+ hcl: { line: ["#", "//"], block: [["/*", "*/"]], strings: '"', keywords: "resource data variable output locals module provider terraform for in if else dynamic content backend required_providers lifecycle", literals: "true false null", types: "string number bool list map set object tuple any", calls: true },
2637
+ dockerfile: { line: ["#"], strings: `'"`, keywords: "FROM RUN CMD LABEL MAINTAINER EXPOSE ENV ADD COPY ENTRYPOINT VOLUME USER WORKDIR ARG ONBUILD STOPSIGNAL HEALTHCHECK SHELL AS", variables: true }
2638
+ };
2639
+ var ALIASES = {
2640
+ js: "javascript",
2641
+ javascript: "javascript",
2642
+ mjs: "javascript",
2643
+ cjs: "javascript",
2644
+ jsx: "javascript",
2645
+ node: "javascript",
2646
+ nodejs: "javascript",
2647
+ ts: "typescript",
2648
+ typescript: "typescript",
2649
+ tsx: "typescript",
2650
+ mts: "typescript",
2651
+ cts: "typescript",
2652
+ python: "python",
2653
+ py: "python",
2654
+ python3: "python",
2655
+ py3: "python",
2656
+ rust: "rust",
2657
+ rs: "rust",
2658
+ go: "go",
2659
+ golang: "go",
2660
+ bash: "bash",
2661
+ sh: "bash",
2662
+ shell: "bash",
2663
+ zsh: "bash",
2664
+ console: "bash",
2665
+ shellscript: "bash",
2666
+ fish: "bash",
2667
+ json: "json",
2668
+ jsonc: "json",
2669
+ json5: "json",
2670
+ yaml: "yaml",
2671
+ yml: "yaml",
2672
+ toml: "toml",
2673
+ ini: "ini",
2674
+ conf: "ini",
2675
+ cfg: "ini",
2676
+ properties: "ini",
2677
+ env: "ini",
2678
+ markup: "markup",
2679
+ html: "markup",
2680
+ xml: "markup",
2681
+ svg: "markup",
2682
+ xhtml: "markup",
2683
+ vue: "markup",
2684
+ plist: "markup",
2685
+ css: "css",
2686
+ scss: "css",
2687
+ less: "css",
2688
+ sass: "css",
2689
+ sql: "sql",
2690
+ postgres: "sql",
2691
+ postgresql: "sql",
2692
+ mysql: "sql",
2693
+ sqlite: "sql",
2694
+ pgsql: "sql",
2695
+ java: "java",
2696
+ csharp: "csharp",
2697
+ cs: "csharp",
2698
+ "c#": "csharp",
2699
+ kotlin: "kotlin",
2700
+ kt: "kotlin",
2701
+ swift: "swift",
2702
+ ruby: "ruby",
2703
+ rb: "ruby",
2704
+ php: "php",
2705
+ c: "c",
2706
+ h: "c",
2707
+ cpp: "c",
2708
+ "c++": "c",
2709
+ cc: "c",
2710
+ cxx: "c",
2711
+ hpp: "c",
2712
+ hh: "c",
2713
+ objc: "c",
2714
+ hcl: "hcl",
2715
+ terraform: "hcl",
2716
+ tf: "hcl",
2717
+ tfvars: "hcl",
2718
+ dockerfile: "dockerfile",
2719
+ docker: "dockerfile"
2720
+ };
2721
+ var CODE_HIGHLIGHT_LANGUAGES = Object.freeze(Object.keys(LANGUAGES2));
2722
+ function resolveCodeLanguage(language) {
2723
+ if (typeof language !== "string") return void 0;
2724
+ const key = language.trim().toLowerCase().replace(/^(?:language|lang)[-:]/, "").replace(/^\./, "");
2725
+ return Object.hasOwn(ALIASES, key) ? ALIASES[key] : void 0;
2726
+ }
2727
+ var IDENT = /[\p{L}_$][\p{L}\p{N}_$]*/uy;
2728
+ var NUMBER = /(?:0[xX][\da-fA-F_]+|0[bB][01_]+|0[oO][0-7_]+|\d[\d_]*(?:\.\d[\d_]*)?(?:[eE][+-]?\d[\d_]*)?)[a-zA-Z]{0,4}/y;
2729
+ var isIdentChar = (character) => character !== void 0 && /[\p{L}\p{N}_$]/u.test(character);
2730
+ function endOfLine(source, from) {
2731
+ const index = source.slice(from).search(/\r\n|\r|\n/);
2732
+ return index < 0 ? source.length : from + index;
2733
+ }
2734
+ function pushToken(tokens, start, end, kind2) {
2735
+ if (end <= start) return;
2736
+ const last = tokens[tokens.length - 1];
2737
+ if (last && last.kind === kind2 && last.end === start && kind2 !== "function" && kind2 !== "property") last.end = end;
2738
+ else tokens.push({ start, end, kind: kind2 });
2739
+ }
2740
+ function scanQuoted(source, from, quote, escapes, multiline) {
2741
+ let index = from + 1;
2742
+ while (index < source.length) {
2743
+ const character = source[index];
2744
+ if (escapes && character === "\\") {
2745
+ index += 2;
2746
+ continue;
2747
+ }
2748
+ if (character === quote) return index + 1;
2749
+ if (!multiline && (character === "\n" || character === "\r")) return index;
2750
+ index++;
2751
+ }
2752
+ return source.length;
2753
+ }
2754
+ function scanGeneric(source, def) {
2755
+ const tokens = [];
2756
+ const keywords = set(def.keywords), literals = set(def.literals), types = set(def.types);
2757
+ const fold = (word) => def.ci ? word.toLowerCase() : word;
2758
+ if (def.ci) for (const list of [keywords, literals, types]) for (const word of [...list]) {
2759
+ list.delete(word);
2760
+ list.add(word.toLowerCase());
2761
+ }
2762
+ const strings = def.strings ?? "", lineComments = def.line ?? [], blocks = def.block ?? [], triples = def.triple ?? [];
2763
+ let index = 0, pendingDef;
2764
+ const atLineStart = (position) => {
2765
+ let at3 = position - 1;
2766
+ while (at3 >= 0 && (source[at3] === " " || source[at3] === " ")) at3--;
2767
+ return at3 < 0 || source[at3] === "\n" || source[at3] === "\r";
2768
+ };
2769
+ while (index < source.length) {
2770
+ const character = source[index];
2771
+ if (/\s/.test(character)) {
2772
+ index++;
2773
+ continue;
2774
+ }
2775
+ const lineComment = lineComments.find((opener) => source.startsWith(opener, index));
2776
+ if (lineComment && !(lineComment === "#" && def.directives) && !(lineComment === "#" && def.variables && source[index - 1] === "$") && !(def.variables && lineComment === "#" && index > 0 && !/[\s;&|(]/.test(source[index - 1]))) {
2777
+ const end = endOfLine(source, index);
2778
+ pushToken(tokens, index, end, "comment");
2779
+ index = end;
2780
+ continue;
2781
+ }
2782
+ const block = blocks.find(([opener]) => source.startsWith(opener, index));
2783
+ if (block) {
2784
+ const close = source.indexOf(block[1], index + block[0].length);
2785
+ const end = close < 0 ? source.length : close + block[1].length;
2786
+ pushToken(tokens, index, end, "comment");
2787
+ index = end;
2788
+ continue;
2789
+ }
2790
+ if (def.directives && character === "#" && atLineStart(index)) {
2791
+ const match = /#[ \t]*\w+/y;
2792
+ match.lastIndex = index;
2793
+ const found = match.exec(source);
2794
+ if (found) {
2795
+ pushToken(tokens, index, index + found[0].length, "keyword");
2796
+ index += found[0].length;
2797
+ if (/include/.test(found[0])) {
2798
+ const header = /[ \t]*(<[^>\n]*>)/y;
2799
+ header.lastIndex = index;
2800
+ const matched = header.exec(source);
2801
+ if (matched) {
2802
+ const start = index + matched[0].length - matched[1].length;
2803
+ pushToken(tokens, start, start + matched[1].length, "string");
2804
+ index += matched[0].length;
2805
+ }
2806
+ }
2807
+ continue;
2808
+ }
2809
+ }
2810
+ const triple = triples.find((opener) => source.startsWith(opener, index));
2811
+ if (triple) {
2812
+ const close = source.indexOf(triple, index + 3);
2813
+ const end = close < 0 ? source.length : close + 3;
2814
+ pushToken(tokens, index, end, "string");
2815
+ index = end;
2816
+ pendingDef = void 0;
2817
+ continue;
2818
+ }
2819
+ if (def.rawStrings && character === def.rawStrings && /^r#*"/.test(source.slice(index, index + 8)) && !isIdentChar(source[index - 1])) {
2820
+ const hashes = /^r(#*)"/.exec(source.slice(index, index + 8))[1];
2821
+ const close = source.indexOf(`"${hashes}`, index + 2 + hashes.length);
2822
+ const end = close < 0 ? source.length : close + 1 + hashes.length;
2823
+ pushToken(tokens, index, end, "string");
2824
+ index = end;
2825
+ continue;
2826
+ }
2827
+ if (strings.includes(character)) {
2828
+ if (def === LANGUAGES2.rust && character === "'" && !/^'(?:\\.[^']*|[^\\'])'/.test(source.slice(index, index + 12))) {
2829
+ const match = /'[\p{L}_][\p{L}\p{N}_]*/uy;
2830
+ match.lastIndex = index;
2831
+ const found = match.exec(source);
2832
+ const end2 = index + (found ? found[0].length : 1);
2833
+ if (found) pushToken(tokens, index, end2, "type");
2834
+ index = end2;
2835
+ continue;
2836
+ }
2837
+ const escapes = !(def.noEscapes ?? "").includes(character);
2838
+ const multiline = character === "`";
2839
+ const end = scanQuoted(source, index, character, escapes, multiline);
2840
+ let kind2 = "string";
2841
+ if (def.quotedKeys) {
2842
+ const after = /^[ \t]*:/.exec(source.slice(end, end + 40));
2843
+ if (after) kind2 = "property";
2844
+ }
2845
+ pushToken(tokens, index, end, kind2);
2846
+ index = end;
2847
+ pendingDef = void 0;
2848
+ continue;
2849
+ }
2850
+ if (def.variables && character === "$") {
2851
+ const match = /\$(?:\{[^}\n]*\}|[A-Za-z_]\w*|[0-9@#?!$*-])/y;
2852
+ match.lastIndex = index;
2853
+ const found = match.exec(source);
2854
+ if (found) {
2855
+ pushToken(tokens, index, index + found[0].length, "property");
2856
+ index += found[0].length;
2857
+ continue;
2858
+ }
2859
+ }
2860
+ if (def.decorators && character === "@" && /[\p{L}_]/u.test(source[index + 1] ?? "")) {
2861
+ const match = /@[\p{L}_][\p{L}\p{N}_$.]*/uy;
2862
+ match.lastIndex = index;
2863
+ const found = match.exec(source);
2864
+ pushToken(tokens, index, index + found[0].length, "function");
2865
+ index += found[0].length;
2866
+ continue;
2867
+ }
2868
+ if (/\d/.test(character) && !isIdentChar(source[index - 1])) {
2869
+ NUMBER.lastIndex = index;
2870
+ const found = NUMBER.exec(source);
2871
+ if (found) {
2872
+ pushToken(tokens, index, index + found[0].length, "number");
2873
+ index += found[0].length;
2874
+ pendingDef = void 0;
2875
+ continue;
2876
+ }
2877
+ }
2878
+ if (def === LANGUAGES2.python && /[rRbBfFuU]/.test(character) && /^[rRbBfFuU]{1,2}['"]/.test(source.slice(index, index + 3)) && !isIdentChar(source[index - 1])) {
2879
+ const prefix = /^[rRbBfFuU]{1,2}/.exec(source.slice(index, index + 3))[0].length;
2880
+ const quote = source[index + prefix];
2881
+ const triple2 = source.startsWith(quote.repeat(3), index + prefix);
2882
+ let end;
2883
+ if (triple2) {
2884
+ const close = source.indexOf(quote.repeat(3), index + prefix + 3);
2885
+ end = close < 0 ? source.length : close + 3;
2886
+ } else end = scanQuoted(source, index + prefix, quote, !/[rR]/.test(source.slice(index, index + prefix)), false);
2887
+ pushToken(tokens, index, end, "string");
2888
+ index = end;
2889
+ pendingDef = void 0;
2890
+ continue;
2891
+ }
2892
+ IDENT.lastIndex = index;
2893
+ const identifier = IDENT.exec(source);
2894
+ if (identifier) {
2895
+ const word = identifier[0], end = index + word.length, folded = fold(word);
2896
+ let kind2;
2897
+ if (pendingDef && !keywords.has(folded)) kind2 = pendingDef;
2898
+ else if (keywords.has(folded)) {
2899
+ kind2 = "keyword";
2900
+ pendingDef = def.defs && Object.hasOwn(def.defs, folded) ? def.defs[folded] : void 0;
2901
+ pushToken(tokens, index, end, kind2);
2902
+ index = end;
2903
+ continue;
2904
+ } else if (literals.has(word) || literals.has(folded)) kind2 = "number";
2905
+ else if (types.has(folded)) kind2 = "type";
2906
+ else if (def.calls && source[end] === "(") kind2 = "function";
2907
+ else if (def.macros && source[end] === "!" && /[([{]/.test(source[end + 1] ?? "")) kind2 = "function";
2908
+ else if (def.capsTypes && /^[A-Z]/.test(word) && /[a-z]/.test(word)) kind2 = "type";
2909
+ pendingDef = void 0;
2910
+ if (kind2) pushToken(tokens, index, end, kind2);
2911
+ index = end;
2912
+ continue;
2913
+ }
2914
+ pendingDef = void 0;
2915
+ index++;
2916
+ }
2917
+ return tokens;
2918
+ }
2919
+ var YAML_LITERALS = /* @__PURE__ */ new Set(["true", "false", "null", "yes", "no", "on", "off", "~", "True", "False", "Null", "TRUE", "FALSE", "NULL"]);
2920
+ function scanYamlValue(source, start, end, tokens, comments) {
2921
+ let index = start;
2922
+ while (index < end) {
2923
+ const character = source[index];
2924
+ if (character === "#" && (index === start || /\s/.test(source[index - 1])) && comments.includes("#")) {
2925
+ pushToken(tokens, index, end, "comment");
2926
+ return;
2927
+ }
2928
+ if (character === ";" && comments.includes(";") && (index === start || /\s/.test(source[index - 1]))) {
2929
+ pushToken(tokens, index, end, "comment");
2930
+ return;
2931
+ }
2932
+ if (character === '"' || character === "'") {
2933
+ const close = scanQuoted(source, index, character, character === '"', false);
2934
+ pushToken(tokens, index, Math.min(close, end), "string");
2935
+ index = Math.min(close, end);
2936
+ continue;
2937
+ }
2938
+ if ((character === "&" || character === "*") && /[\w-]/.test(source[index + 1] ?? "")) {
2939
+ const match = /[&*][\w-]+/y;
2940
+ match.lastIndex = index;
2941
+ const found2 = match.exec(source);
2942
+ pushToken(tokens, index, index + found2[0].length, "type");
2943
+ index += found2[0].length;
2944
+ continue;
2945
+ }
2946
+ if (!isIdentChar(source[index - 1]) && /[\d-]/.test(character)) {
2947
+ const match = /-?\d[\d_]*(?:\.\d+)?(?:[eE][+-]?\d+)?(?=[\s,\]}]|$)/y;
2948
+ match.lastIndex = index;
2949
+ const found2 = match.exec(source);
2950
+ if (found2 && index + found2[0].length <= end) {
2951
+ pushToken(tokens, index, index + found2[0].length, "number");
2952
+ index += found2[0].length;
2953
+ continue;
2954
+ }
2955
+ }
2956
+ const word = /[\w.~-]+/y;
2957
+ word.lastIndex = index;
2958
+ const found = word.exec(source);
2959
+ if (found) {
2960
+ if (YAML_LITERALS.has(found[0]) && !/[\w.-]/.test(source[index + found[0].length] ?? "")) pushToken(tokens, index, index + found[0].length, "number");
2961
+ index += found[0].length;
2962
+ continue;
2963
+ }
2964
+ index++;
2965
+ }
2966
+ }
2967
+ function lineRanges(source) {
2968
+ const ranges = [];
2969
+ let cursor = 0;
2970
+ const pattern = /\r\n|\r|\n/g;
2971
+ for (let match = pattern.exec(source); match; match = pattern.exec(source)) {
2972
+ ranges.push({ start: cursor, end: match.index });
2973
+ cursor = match.index + match[0].length;
2974
+ }
2975
+ ranges.push({ start: cursor, end: source.length });
2976
+ return ranges;
2977
+ }
2978
+ function yamlKey(source, from, to) {
2979
+ const first = source[from];
2980
+ if (first === void 0 || from >= to) return void 0;
2981
+ let index = from;
2982
+ if (first === '"' || first === "'") {
2983
+ index = Math.min(scanQuoted(source, from, first, first === '"', false), to);
2984
+ let at3 = index;
2985
+ while (at3 < to && (source[at3] === " " || source[at3] === " ")) at3++;
2986
+ return source[index - 1] === first && source[at3] === ":" && (at3 + 1 >= to || /\s/.test(source[at3 + 1])) ? { nameEnd: index, colon: at3 } : void 0;
2987
+ }
2988
+ if (/[\s#:{}[\],&*!|>%@`]/.test(first) || first === "-" && /[\s#:]/.test(source[from + 1] ?? " ")) return void 0;
2989
+ for (; index < to; index++) {
2990
+ const character = source[index];
2991
+ if (character === "#" && /\s/.test(source[index - 1])) return void 0;
2992
+ if (character === ":" && (index + 1 >= to || /\s/.test(source[index + 1]))) {
2993
+ let nameEnd = index;
2994
+ while (nameEnd > from && /\s/.test(source[nameEnd - 1])) nameEnd--;
2995
+ return nameEnd > from ? { nameEnd, colon: index } : void 0;
2996
+ }
2997
+ }
2998
+ return void 0;
2999
+ }
3000
+ function scanYaml(source) {
3001
+ const tokens = [];
3002
+ let blockIndent = -1;
3003
+ for (const { start, end } of lineRanges(source)) {
3004
+ const text2 = source.slice(start, end), indent = /^ */.exec(text2)[0].length;
3005
+ if (blockIndent >= 0) {
3006
+ if (text2.trim() === "" || indent > blockIndent) {
3007
+ if (text2.trim() !== "") pushToken(tokens, start + indent, end, "string");
3008
+ continue;
3009
+ }
3010
+ blockIndent = -1;
3011
+ }
3012
+ if (/^\s*#/.test(text2)) {
3013
+ pushToken(tokens, start + indent, end, "comment");
3014
+ continue;
3015
+ }
3016
+ if (/^(?:---|\.\.\.)(?:\s|$)/.test(text2)) {
3017
+ pushToken(tokens, start, start + 3, "keyword");
3018
+ scanYamlValue(source, start + 3, end, tokens, "#");
3019
+ continue;
3020
+ }
3021
+ let cursor = start + indent;
3022
+ const dash = /^(?:-\s+)+/.exec(text2.slice(indent));
3023
+ if (dash) cursor += dash[0].length;
3024
+ let valueStart = cursor;
3025
+ const key = yamlKey(source, cursor, end);
3026
+ if (key) {
3027
+ pushToken(tokens, cursor, key.nameEnd, "property");
3028
+ valueStart = key.colon + 1;
3029
+ }
3030
+ scanYamlValue(source, valueStart, end, tokens, "#");
3031
+ if (/(?:^|\s)[|>][+-]?\d?\s*(?:#.*)?$/.test(text2.slice(valueStart - start))) blockIndent = indent;
3032
+ }
3033
+ return tokens;
3034
+ }
3035
+ function scanIni(source, def) {
3036
+ const tokens = [], comments = (def.line ?? []).join("");
3037
+ for (const { start, end } of lineRanges(source)) {
3038
+ const text2 = source.slice(start, end), indent = /^\s*/.exec(text2)[0].length, first = text2[indent];
3039
+ if (first === void 0) continue;
3040
+ if (comments.includes(first)) {
3041
+ pushToken(tokens, start + indent, end, "comment");
3042
+ continue;
3043
+ }
3044
+ if (first === "[") {
3045
+ const close = text2.indexOf("]", indent);
3046
+ const stop = close < 0 ? end : start + close + 1;
3047
+ pushToken(tokens, start + indent, stop, "type");
3048
+ scanYamlValue(source, stop, end, tokens, comments);
3049
+ continue;
3050
+ }
3051
+ const key = /^("[^"\n]*"|'[^'\n]*'|[^\s=:#;"']+(?:\s+[^\s=:#;"']+)*)\s*[=:]/.exec(text2.slice(indent));
3052
+ let valueStart = start + indent;
3053
+ if (key) {
3054
+ pushToken(tokens, start + indent, start + indent + key[1].length, "property");
3055
+ valueStart = start + indent + key[0].length;
3056
+ }
3057
+ scanYamlValue(source, valueStart, end, tokens, comments);
3058
+ }
3059
+ return tokens;
3060
+ }
3061
+ function scanMarkup(source) {
3062
+ const tokens = [];
3063
+ let index = 0;
3064
+ while (index < source.length) {
3065
+ const open = source.indexOf("<", index);
3066
+ if (open < 0) break;
3067
+ if (source.startsWith("<!--", open)) {
3068
+ const close = source.indexOf("-->", open + 4);
3069
+ const end = close < 0 ? source.length : close + 3;
3070
+ pushToken(tokens, open, end, "comment");
3071
+ index = end;
3072
+ continue;
3073
+ }
3074
+ if (source.startsWith("<![CDATA[", open)) {
3075
+ const close = source.indexOf("]]>", open);
3076
+ const end = close < 0 ? source.length : close + 3;
3077
+ pushToken(tokens, open, end, "string");
3078
+ index = end;
3079
+ continue;
3080
+ }
3081
+ const name = /<([/?!]?)([A-Za-z][\w:.-]*|DOCTYPE)?/y;
3082
+ name.lastIndex = open;
3083
+ const found = name.exec(source);
3084
+ if (!found || !found[2]) {
3085
+ index = open + 1;
3086
+ continue;
3087
+ }
3088
+ pushToken(tokens, open + 1, open + found[0].length, "keyword");
3089
+ index = open + found[0].length;
3090
+ while (index < source.length && source[index] !== ">") {
3091
+ const character = source[index];
3092
+ if (character === '"' || character === "'") {
3093
+ const close = source.indexOf(character, index + 1);
3094
+ const end = close < 0 ? source.length : close + 1;
3095
+ pushToken(tokens, index, end, "string");
3096
+ index = end;
3097
+ continue;
3098
+ }
3099
+ const attribute = /[A-Za-z_:@#][\w:.@#-]*/y;
3100
+ attribute.lastIndex = index;
3101
+ const matched = attribute.exec(source);
3102
+ if (matched) {
3103
+ pushToken(tokens, index, index + matched[0].length, "property");
3104
+ index += matched[0].length;
3105
+ continue;
3106
+ }
3107
+ index++;
3108
+ }
3109
+ if (source[index] === ">") index++;
3110
+ }
3111
+ return tokens;
3112
+ }
3113
+ function scanCss(source) {
3114
+ const tokens = [];
3115
+ let index = 0, depth = 0;
3116
+ while (index < source.length) {
3117
+ const character = source[index];
3118
+ if (/\s/.test(character)) {
3119
+ index++;
3120
+ continue;
3121
+ }
3122
+ if (source.startsWith("/*", index)) {
3123
+ const close = source.indexOf("*/", index + 2);
3124
+ const end = close < 0 ? source.length : close + 2;
3125
+ pushToken(tokens, index, end, "comment");
3126
+ index = end;
3127
+ continue;
3128
+ }
3129
+ if (character === '"' || character === "'") {
3130
+ const end = scanQuoted(source, index, character, true, false);
3131
+ pushToken(tokens, index, end, "string");
3132
+ index = end;
3133
+ continue;
3134
+ }
3135
+ if (character === "{") {
3136
+ depth++;
3137
+ index++;
3138
+ continue;
3139
+ }
3140
+ if (character === "}") {
3141
+ depth = Math.max(0, depth - 1);
3142
+ index++;
3143
+ continue;
3144
+ }
3145
+ if (character === "@") {
3146
+ const match = /@[\w-]+/y;
3147
+ match.lastIndex = index;
3148
+ const found2 = match.exec(source);
3149
+ if (found2) {
3150
+ pushToken(tokens, index, index + found2[0].length, "keyword");
3151
+ index += found2[0].length;
3152
+ continue;
3153
+ }
3154
+ }
3155
+ if (character === "!") {
3156
+ const match = /!\s*important/y;
3157
+ match.lastIndex = index;
3158
+ const found2 = match.exec(source);
3159
+ if (found2) {
3160
+ pushToken(tokens, index, index + found2[0].length, "keyword");
3161
+ index += found2[0].length;
3162
+ continue;
3163
+ }
3164
+ }
3165
+ if (character === "#" && depth > 0) {
3166
+ const match = /#[\da-fA-F]{3,8}\b/y;
3167
+ match.lastIndex = index;
3168
+ const found2 = match.exec(source);
3169
+ if (found2) {
3170
+ pushToken(tokens, index, index + found2[0].length, "number");
3171
+ index += found2[0].length;
3172
+ continue;
3173
+ }
3174
+ }
3175
+ if (depth > 0 && (/\d/.test(character) || (character === "-" || character === "." || character === "+") && /\d/.test(source[index + 1] ?? ""))) {
3176
+ const match = /[-+]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?(?:%|[a-zA-Z]+)?/y;
3177
+ match.lastIndex = index;
3178
+ const found2 = match.exec(source);
3179
+ if (found2 && !isIdentChar(source[index - 1])) {
3180
+ pushToken(tokens, index, index + found2[0].length, "number");
3181
+ index += found2[0].length;
3182
+ continue;
3183
+ }
3184
+ }
3185
+ const word = /-?[\p{L}_][\p{L}\p{N}_-]*/uy;
3186
+ word.lastIndex = index;
3187
+ const found = word.exec(source);
3188
+ if (found) {
3189
+ const end = index + found[0].length;
3190
+ let back = index - 1;
3191
+ while (back >= 0 && /\s/.test(source[back])) back--;
3192
+ const before = back >= 0 ? source[back] : "";
3193
+ if (depth > 0 && /^\s*:(?!:)/.test(source.slice(end, end + 8)) && (before === "{" || before === ";" || before === "")) pushToken(tokens, index, end, "property");
3194
+ else if (source[end] === "(") pushToken(tokens, index, end, "function");
3195
+ index = end;
3196
+ continue;
3197
+ }
3198
+ if (depth === 0 && (character === "." || character === "#")) {
3199
+ const match = /[.#][\p{L}_-][\p{L}\p{N}_-]*/uy;
3200
+ match.lastIndex = index;
3201
+ const matched = match.exec(source);
3202
+ if (matched) {
3203
+ pushToken(tokens, index, index + matched[0].length, "type");
3204
+ index += matched[0].length;
3205
+ continue;
3206
+ }
3207
+ }
3208
+ index++;
3209
+ }
3210
+ return tokens;
3211
+ }
3212
+ function tokenizeCode(source, language) {
3213
+ const id = resolveCodeLanguage(language);
3214
+ if (id === void 0 || typeof source !== "string" || source.length === 0 || source.length > CODE_HIGHLIGHT_MAX_LENGTH) return [];
3215
+ const def = LANGUAGES2[id];
3216
+ let tokens;
3217
+ switch (def.kind) {
3218
+ case "yaml":
3219
+ tokens = scanYaml(source);
3220
+ break;
3221
+ case "ini":
3222
+ tokens = scanIni(source, def);
3223
+ break;
3224
+ case "markup":
3225
+ tokens = scanMarkup(source);
3226
+ break;
3227
+ case "css":
3228
+ tokens = scanCss(source);
3229
+ break;
3230
+ default:
3231
+ tokens = scanGeneric(source, def);
3232
+ }
3233
+ return tokens.filter((token) => token.end > token.start).sort((a, b) => a.start - b.start);
3234
+ }
3235
+ function codeLineRuns(tokens, start, end, source) {
3236
+ const runs = [];
3237
+ const push = (from, to, kind2) => {
3238
+ if (kind2 === void 0 || source === void 0 || !source.slice(from, to).includes(" ")) {
3239
+ runs.push(kind2 === void 0 ? { start: from, end: to } : { start: from, end: to, kind: kind2 });
3240
+ return;
3241
+ }
3242
+ let at3 = from;
3243
+ for (let index = from; index < to; index++) {
3244
+ if (source[index] !== " ") continue;
3245
+ if (index > at3) runs.push({ start: at3, end: index, kind: kind2 });
3246
+ runs.push({ start: index, end: index + 1 });
3247
+ at3 = index + 1;
3248
+ }
3249
+ if (at3 < to) runs.push({ start: at3, end: to, kind: kind2 });
3250
+ };
3251
+ let cursor = start;
3252
+ for (const token of tokens) {
3253
+ if (token.end <= start) continue;
3254
+ if (token.start >= end) break;
3255
+ const from = Math.max(token.start, start), to = Math.min(token.end, end);
3256
+ if (from > cursor) push(cursor, from);
3257
+ push(from, to, token.kind);
3258
+ cursor = to;
3259
+ }
3260
+ if (cursor < end) push(cursor, end);
3261
+ return runs;
3262
+ }
3263
+ var distance = (a, b) => Math.hypot(...channels(a).map((value, index) => value - channels(b)[index]));
3264
+ var FALLBACK = { keyword: "#C4B5FD", string: "#86EFAC", number: "#FCD34D", function: "#93C5FD", type: "#67E8F9", property: "#F9A8D4", comment: "#94A3B8" };
3265
+ function codeSyntaxPalette(theme = {}, options = {}) {
3266
+ const background = normalize(options.background) ?? CODE_PANEL_BACKGROUND, plain = normalize(options.foreground) ?? CODE_PANEL_FOREGROUND;
3267
+ const minimum = options.minimumContrast ?? CODE_SYNTAX_MIN_CONTRAST;
3268
+ const palette = { plain: legible(plain, background, minimum) };
3269
+ const taken = [palette.plain];
3270
+ const slots = [["keyword", theme.primary], ["string", theme.accent], ["number", theme.secondary], ["comment", theme.mutedText], ["function", void 0], ["type", void 0], ["property", void 0]];
3271
+ for (const [kind2, themed] of slots) {
3272
+ const candidates = [normalize(themed), FALLBACK[kind2]].filter((value) => value !== void 0).map((value) => legible(value, background, minimum));
3273
+ let [h, s, l] = toHsl(FALLBACK[kind2]);
3274
+ let pick = candidates.find((candidate) => taken.every((other) => distance(candidate, other) >= 48));
3275
+ for (let turn = 0; pick === void 0 && turn < 9; turn++) {
3276
+ h += 40;
3277
+ const candidate = legible(fromHsl(h, s, l), background, minimum);
3278
+ if (taken.every((other) => distance(candidate, other) >= 48)) pick = candidate;
3279
+ }
3280
+ palette[kind2] = pick ?? candidates[candidates.length - 1];
3281
+ taken.push(palette[kind2]);
3282
+ }
3283
+ return palette;
3284
+ }
3285
+ function codeSyntaxPaletteForScheme(scheme, options = {}) {
3286
+ const record6 = scheme && typeof scheme === "object" ? scheme : {};
3287
+ const pick = (role, slot, fallback) => normalize(record6[role]) ?? normalize(record6[slot]) ?? fallback;
3288
+ return codeSyntaxPalette({ primary: pick("primary", "accent1", "#2563EB"), secondary: pick("secondary", "accent2", "#0F766E"), accent: pick("accent", "accent3", "#F59E0B") }, options);
3289
+ }
3290
+
3291
+ // src/metric-trend.ts
3292
+ var METRIC_DEFAULT_SENTIMENT = Object.freeze({ up: "positive", down: "negative", flat: "neutral" });
3293
+ function metricEffectiveSentiment(trend, sentiment) {
3294
+ return sentiment ?? METRIC_DEFAULT_SENTIMENT[trend];
3295
+ }
3296
+ var METRIC_TREND_SHAPES = Object.freeze({ up: "upArrow", down: "downArrow", flat: "rightArrow" });
3297
+ var METRIC_TREND_MIN_CONTRAST = 4.5;
3298
+ var SEMANTIC = {
3299
+ positive: { light: "#15803D", dark: "#4ADE80" },
3300
+ negative: { light: "#B91C1C", dark: "#F87171" }
3301
+ };
3302
+ function metricTrendColor(trend, options) {
3303
+ const background = normalize(options.background) ?? "#FFFFFF";
3304
+ const sentiment = metricEffectiveSentiment(trend, options.sentiment);
3305
+ if (sentiment === "neutral") return legible(normalize(options.neutral) ?? (luminance2(background) < 0.5 ? "#CBD5E1" : "#475569"), background, METRIC_TREND_MIN_CONTRAST);
3306
+ const pair = SEMANTIC[sentiment];
3307
+ return legible(luminance2(background) < 0.5 ? pair.dark : pair.light, background, METRIC_TREND_MIN_CONTRAST);
3308
+ }
3309
+ function metricTrendPoints(shape, box) {
3310
+ const { x: l, y: t, width: w, height: h } = box, r = l + w, b = t + h, hc = l + w / 2, vc = t + h / 2, ss = Math.min(w, h);
3311
+ if (shape === "rightArrow") {
3312
+ const x12 = r - ss * 0.5, y1 = vc - h * 0.25, y22 = vc + h * 0.25;
3313
+ return [[l, y1], [x12, y1], [x12, t], [r, vc], [x12, b], [x12, y22], [l, y22]];
3314
+ }
3315
+ const dy = ss * 0.5, x1 = hc - w * 0.25, x2 = hc + w * 0.25;
3316
+ if (shape === "upArrow") {
3317
+ const y22 = t + dy;
3318
+ return [[l, y22], [hc, t], [r, y22], [x2, y22], [x2, b], [x1, b], [x1, y22]];
3319
+ }
3320
+ const y2 = b - dy;
3321
+ return [[l, y2], [x1, y2], [x1, t], [x2, t], [x2, y2], [r, y2], [hc, b]];
3322
+ }
3323
+ function metricTrendMark(layout, options) {
3324
+ const part = layout.parts.find((candidate) => candidate.role === "trend");
3325
+ if (!part || !part.visible || !part.fit || part.fit.sourceLines.length === 0) return void 0;
3326
+ const trend = part.text.trim();
3327
+ if (!Object.hasOwn(METRIC_TREND_SHAPES, trend)) return void 0;
3328
+ const line = part.fit.sourceLines[0], origin = part.linePositions[0];
3329
+ if (!origin || line.width <= 0) return void 0;
3330
+ const size = part.fit.fontSize * 0.72, gap = part.fit.fontSize * 0.3, left = part.box.x, right = part.box.x + part.box.width;
3331
+ const after = origin.x + line.width + gap, before = origin.x - gap - size;
3332
+ const fitsAfter = after + size <= right + 0.01, fitsBefore = before >= left - 0.01;
3333
+ const x = layout.alignment === "left" ? fitsAfter ? after : fitsBefore ? before : void 0 : fitsBefore ? before : fitsAfter ? after : void 0;
3334
+ if (x === void 0) return void 0;
3335
+ const shape = METRIC_TREND_SHAPES[trend], box = { x, y: origin.baseline - size, width: size, height: size };
3336
+ const sentiment = metricEffectiveSentiment(trend, options.sentiment ?? layout.sentiment);
3337
+ return { trend, sentiment, shape, box, points: metricTrendPoints(shape, box), color: metricTrendColor(trend, { ...options, sentiment }), ariaLabel: `Trend: ${trend}`, path: part.path };
3338
+ }
3339
+
3340
+ // src/timeline-status.ts
3341
+ var TIMELINE_STATUSES = Object.freeze(["done", "current", "planned"]);
3342
+ var TIMELINE_TEXT_MIN_CONTRAST = 4.5;
3343
+ var TIMELINE_OUTLINE_MIN_CONTRAST = 3;
3344
+ function timelineMarkerShapes(marker, colors) {
3345
+ const background = normalize(colors.background) ?? "#FFFFFF";
3346
+ const primary = normalize(colors.primary), outline = primary ? legible(primary, background, TIMELINE_OUTLINE_MIN_CONTRAST) : colors.primary;
3347
+ const shapes = [];
3348
+ const width = marker.strokeWidth ?? 0;
3349
+ if (marker.status === "current" && marker.ring) {
3350
+ shapes.push({ role: "ring", shape: "ellipse", cx: marker.x, cy: marker.y, radius: marker.ring.radius, fill: colors.background, stroke: { color: outline, width } });
3351
+ }
3352
+ if (marker.status === "planned") {
3353
+ shapes.push({ role: "marker", shape: "ellipse", cx: marker.x, cy: marker.y, radius: marker.radius, fill: colors.background, stroke: { color: outline, width } });
3354
+ } else {
3355
+ shapes.push({ role: "marker", shape: "ellipse", cx: marker.x, cy: marker.y, radius: marker.radius, fill: colors.primary });
3356
+ }
3357
+ return shapes;
3358
+ }
3359
+ function timelineTextColor(part, colors) {
3360
+ if (part.status !== "planned") return colors.text;
3361
+ const background = normalize(colors.background) ?? "#FFFFFF", muted = normalize(colors.mutedText);
3362
+ return muted ? legible(muted, background, TIMELINE_TEXT_MIN_CONTRAST) : colors.mutedText;
3363
+ }
3364
+
3365
+ // src/code-highlight.ts
3366
+ function codeLineCount(source) {
3367
+ let count = 1;
3368
+ for (let index = 0; index < source.length; index++) {
3369
+ const char = source[index];
3370
+ if (char === "\r" && source[index + 1] === "\n") index++;
3371
+ if (char === "\r" || char === "\n") count++;
3372
+ }
3373
+ return count > 1 && /(?:\r\n|\r|\n)$/.test(source) ? count - 1 : count;
3374
+ }
3375
+ var isLine = (value) => typeof value === "number" && Number.isInteger(value) && value >= 1;
3376
+ function codeHighlightLines(highlight, source) {
3377
+ const lineCount = codeLineCount(source), marked = /* @__PURE__ */ new Set(), issues = [];
3378
+ if (!Array.isArray(highlight)) return { lineCount, lines: [], issues };
3379
+ highlight.forEach((entry, index) => {
3380
+ const range = Array.isArray(entry) ? entry : [entry, entry];
3381
+ if (range.length !== 2 || !isLine(range[0]) || !isLine(range[1])) {
3382
+ issues.push({ code: "code-highlight-invalid", index, message: "A code highlight entry is a line number or a [start, end] pair of line numbers from 1." });
3383
+ return;
3384
+ }
3385
+ const [start, end] = range;
3386
+ if (start > end) {
3387
+ issues.push({ code: "code-highlight-range-reversed", index, message: `The highlight range [${start}, ${end}] ends before it starts, so it marks no line; write [${end}, ${start}].` });
3388
+ return;
3389
+ }
3390
+ if (end > lineCount) issues.push({ code: "code-highlight-out-of-range", index, message: `The highlight ${start === end ? `line ${start}` : `range [${start}, ${end}]`} is past the last line (the code has ${lineCount} ${lineCount === 1 ? "line" : "lines"}); lines beyond it are ignored.` });
3391
+ for (let line = start; line <= Math.min(end, lineCount); line++) marked.add(line);
3392
+ });
3393
+ return { lineCount, lines: [...marked].sort((a, b) => a - b), issues };
3394
+ }
3395
+ function codeHighlightList(lines) {
3396
+ const sorted = [...new Set(lines)].sort((a, b) => a - b), out = [];
3397
+ for (let index = 0; index < sorted.length; ) {
3398
+ let end = index;
3399
+ while (sorted[end + 1] === sorted[end] + 1) end++;
3400
+ out.push(end === index ? sorted[index] : [sorted[index], sorted[end]]);
3401
+ index = end + 1;
3402
+ }
3403
+ return out;
3404
+ }
3405
+ function codeLineNumbers(sourceLines) {
3406
+ let line = 1;
3407
+ return sourceLines.map((entry) => {
3408
+ const number = line;
3409
+ if (entry.boundary === "hard") line++;
3410
+ return number;
3411
+ });
3412
+ }
3413
+ function codeHighlightBands(sourceLines, lines) {
3414
+ if (!lines.length) return [];
3415
+ const marked = new Set(lines), numbers = codeLineNumbers(sourceLines), bands = [];
3416
+ numbers.forEach((number, index) => {
3417
+ if (!marked.has(number)) return;
3418
+ const last = bands.at(-1);
3419
+ if (last && last.last === index - 1) last.last = index;
3420
+ else bands.push({ first: index, last: index });
3421
+ });
3422
+ return bands;
3423
+ }
3424
+ function codeHighlightSlice(highlight, source, start, end) {
3425
+ const { lines } = codeHighlightLines(highlight, source);
3426
+ if (!lines.length) return void 0;
3427
+ const breaks = (text2) => (text2.match(/\r\n|\r|\n/g) ?? []).length;
3428
+ const before = breaks(source.slice(0, start)), count = codeLineCount(source.slice(start, end));
3429
+ const kept = lines.filter((line) => line > before && line <= before + count).map((line) => line - before);
3430
+ return kept.length ? codeHighlightList(kept) : void 0;
3431
+ }
3432
+ var CODE_HIGHLIGHT_DIM = 0.35;
3433
+ var CODE_HIGHLIGHT_BAND_TINT = 0.3;
3434
+ var blend = (from, to, amount) => {
3435
+ const a = channels(from), b = channels(to);
3436
+ return toHex(a.map((value, index) => value + (b[index] - value) * amount));
3437
+ };
3438
+ function codeHighlightColors(scheme, palette = codeSyntaxPaletteForScheme(scheme)) {
3439
+ const record6 = scheme && typeof scheme === "object" ? scheme : {};
3440
+ const primary = normalize(record6.primary) ?? normalize(record6.accent1) ?? "#2563EB";
3441
+ const [hue, saturation] = toHsl(primary);
3442
+ const tint = fromHsl(hue, Math.min(saturation, 0.7), 0.45);
3443
+ const band = blend(CODE_PANEL_BACKGROUND, tint, CODE_HIGHLIGHT_BAND_TINT);
3444
+ const lit = {}, dim = {};
3445
+ for (const key of Object.keys(palette)) {
3446
+ lit[key] = legible(palette[key], band, CODE_SYNTAX_MIN_CONTRAST);
3447
+ dim[key] = legible(blend(palette[key], CODE_PANEL_BACKGROUND, CODE_HIGHLIGHT_DIM), CODE_PANEL_BACKGROUND, CODE_SYNTAX_MIN_CONTRAST);
3448
+ }
3449
+ return { band, lit, dim };
3450
+ }
3451
+
3452
+ // src/watermark.ts
3453
+ var WATERMARK_TEXT_ROTATION = -30;
3454
+ var WATERMARK_TEXT_MAX_WIDTH = 0.7;
3455
+ var WATERMARK_TEXT_MAX_HEIGHT = 0.3;
3456
+ function layoutWatermark(text2, size, options = {}) {
3457
+ const value = typeof text2 === "string" ? text2.replace(/\s*[\r\n]+\s*/g, " ").trim() : "";
3458
+ if (!value) return void 0;
3459
+ const { width, height } = size;
3460
+ if (![width, height].every((n) => Number.isFinite(n) && n > 0)) throw new RangeError("Watermark slide size must be finite and positive.");
3461
+ const fontFamily = options.fontFamily ?? "sans-serif", fontWeight = options.fontWeight ?? 700;
3462
+ const style = resolveTextStyle({ fontFamily, fontWeight, italic: false, path: "design.watermark" }, options.textMeasurement);
3463
+ const measure = textWidthMeasurer(style, options.textMeasurement);
3464
+ const reference = 100, unit = measure(value, reference);
3465
+ const wanted = unit > 0 ? WATERMARK_TEXT_MAX_WIDTH * width * reference / unit : WATERMARK_TEXT_MAX_HEIGHT * Math.min(width, height);
3466
+ const fontSize = Math.max(1, Math.min(wanted, WATERMARK_TEXT_MAX_HEIGHT * Math.min(width, height)));
3467
+ const textWidth = measure(value, fontSize);
3468
+ const boxWidth = textWidth + fontSize * 0.5, boxHeight = fontSize * 1.4;
3469
+ return {
3470
+ text: value,
3471
+ fontFamily: style.fontFamily,
3472
+ fontWeight,
3473
+ style,
3474
+ fontSize,
3475
+ textWidth,
3476
+ box: { x: (width - boxWidth) / 2, y: (height - boxHeight) / 2, width: boxWidth, height: boxHeight },
3477
+ rotation: WATERMARK_TEXT_ROTATION
3478
+ };
3479
+ }
3480
+
3481
+ // src/pattern-fills.ts
3482
+ var PATTERN_PRESETS = Object.freeze([
3483
+ "pct5",
3484
+ "pct10",
3485
+ "pct20",
3486
+ "pct25",
3487
+ "pct30",
3488
+ "pct40",
3489
+ "pct50",
3490
+ "pct60",
3491
+ "pct70",
3492
+ "pct75",
3493
+ "pct80",
3494
+ "pct90",
3495
+ "horz",
3496
+ "vert",
3497
+ "ltHorz",
3498
+ "ltVert",
3499
+ "dkHorz",
3500
+ "dkVert",
3501
+ "narHorz",
3502
+ "narVert",
3503
+ "dashHorz",
3504
+ "dashVert",
3505
+ "cross",
3506
+ "dnDiag",
3507
+ "upDiag",
3508
+ "ltDnDiag",
3509
+ "ltUpDiag",
3510
+ "dkDnDiag",
3511
+ "dkUpDiag",
3512
+ "wdDnDiag",
3513
+ "wdUpDiag",
3514
+ "dashDnDiag",
3515
+ "dashUpDiag",
3516
+ "diagCross",
3517
+ "smCheck",
3518
+ "lgCheck",
3519
+ "smGrid",
3520
+ "lgGrid",
3521
+ "dotGrid",
3522
+ "smConfetti",
3523
+ "lgConfetti",
3524
+ "horzBrick",
3525
+ "diagBrick",
3526
+ "solidDmnd",
3527
+ "openDmnd",
3528
+ "dotDmnd",
3529
+ "plaid",
3530
+ "sphere",
3531
+ "weave",
3532
+ "divot",
3533
+ "shingle",
3534
+ "wave",
3535
+ "trellis",
3536
+ "zigZag"
3537
+ ]);
3538
+ var PATTERN_PRESET_ALIASES = Object.freeze({ diagStripe: "wdUpDiag" });
3539
+ var PATTERN_TILE_SIZE = 8;
3540
+ var MEASURED = {
3541
+ pct5: "#......./......../......../......../....#.../......../......../........",
3542
+ pct10: "#......./......../....#.../......../#......./......../....#.../........",
3543
+ pct20: "#...#.../......../..#...#./......../#...#.../......../..#...#./........",
3544
+ pct25: "#...#.../..#...#./#...#.../..#...#./#...#.../..#...#./#...#.../..#...#.",
3545
+ pct30: "#.#.#.#./.#...#../#.#.#.#./...#...#/#.#.#.#./.#...#../#.#.#.#./...#...#",
3546
+ pct40: "#.#.#.#./.#.#.#.#/#.#.#.#./.#.#...#/#.#.#.#./.#.#.#.#/#.#.#.#./...#.#.#",
3547
+ pct50: "#.#.#.#./.#.#.#.#/#.#.#.#./.#.#.#.#/#.#.#.#./.#.#.#.#/#.#.#.#./.#.#.#.#",
3548
+ pct60: "###.###./.#.#.#.#/#.###.##/.#.#.#.#/###.###./.#.#.#.#/#.###.##/.#.#.#.#",
3549
+ pct70: ".###.###/##.###.#/.###.###/##.###.#/.###.###/##.###.#/.###.###/##.###.#",
3550
+ pct75: ".###.###/########/##.###.#/########/.###.###/########/##.###.#/########",
3551
+ pct80: "###.####/########/#######./########/###.####/########/#######./########",
3552
+ pct90: "########/########/########/####.###/########/########/########/.#######",
3553
+ horz: "########/......../......../......../......../......../......../........",
3554
+ vert: "#......./#......./#......./#......./#......./#......./#......./#.......",
3555
+ ltHorz: "########/......../......../......../########/......../......../........",
3556
+ ltVert: "#...#.../#...#.../#...#.../#...#.../#...#.../#...#.../#...#.../#...#...",
3557
+ dkHorz: "########/########/......../......../########/########/......../........",
3558
+ dkVert: "##..##../##..##../##..##../##..##../##..##../##..##../##..##../##..##..",
3559
+ narHorz: "########/......../########/......../########/......../########/........",
3560
+ narVert: ".#.#.#.#/.#.#.#.#/.#.#.#.#/.#.#.#.#/.#.#.#.#/.#.#.#.#/.#.#.#.#/.#.#.#.#",
3561
+ dashHorz: "####..../......../......../......../....####/......../......../........",
3562
+ dashVert: "#......./#......./#......./#......./....#.../....#.../....#.../....#...",
3563
+ cross: "########/#......./#......./#......./#......./#......./#......./#.......",
3564
+ dnDiag: "#......./.#....../..#...../...#..../....#.../.....#../......#./.......#",
3565
+ upDiag: ".......#/......#./.....#../....#.../...#..../..#...../.#....../#.......",
3566
+ ltDnDiag: "#...#.../.#...#../..#...#./...#...#/#...#.../.#...#../..#...#./...#...#",
3567
+ ltUpDiag: "...#...#/..#...#./.#...#../#...#.../...#...#/..#...#./.#...#../#...#...",
3568
+ dkDnDiag: "##..##../.##..##./..##..##/#..##..#/##..##../.##..##./..##..##/#..##..#",
3569
+ dkUpDiag: "..##..##/.##..##./##..##../#..##..#/..##..##/.##..##./##..##../#..##..#",
3570
+ wdDnDiag: "##.....#/###...../.###..../..###.../...###../....###./.....###/#.....##",
3571
+ wdUpDiag: "#.....##/.....###/....###./...###../..###.../.###..../###...../##.....#",
3572
+ dashDnDiag: "......../......../#...#.../.#...#../..#...#./...#...#/......../........",
3573
+ dashUpDiag: "......../......../...#...#/..#...#./.#...#../#...#.../......../........",
3574
+ diagCross: "#......#/.#....#./..#..#../...##.../...##.../..#..#../.#....#./#......#",
3575
+ smCheck: "#..##..#/.##..##./.##..##./#..##..#/#..##..#/.##..##./.##..##./#..##..#",
3576
+ lgCheck: "####..../####..../####..../####..../....####/....####/....####/....####",
3577
+ smGrid: "########/#...#.../#...#.../#...#.../########/#...#.../#...#.../#...#...",
3578
+ lgGrid: "########/#......./#......./#......./#......./#......./#......./#.......",
3579
+ dotGrid: "#.#.#.#./......../#......./......../#......./......../#......./........",
3580
+ smConfetti: "#......./....#.../.#....../......#./...#..../.......#/..#...../.....#..",
3581
+ lgConfetti: "#.##...#/..##..../......##/...##.##/##.##.../##....../....##../#...##.#",
3582
+ horzBrick: "########/#......./#......./#......./########/....#.../....#.../....#...",
3583
+ diagBrick: ".......#/......#./.....#../....#.../...##.../..#..#../.#....#./#......#",
3584
+ solidDmnd: "...#..../..###.../.#####../#######./.#####../..###.../...#..../........",
3585
+ openDmnd: "#.....#./.#...#../..#.#.../...#..../..#.#.../.#...#../#.....#./.......#",
3586
+ dotDmnd: "#......./......../..#...#./......../....#.../......../..#...#./........",
3587
+ plaid: "#.#.#.#./.#.#.#.#/#.#.#.#./.#.#.#.#/####..../####..../####..../####....",
3588
+ sphere: ".###.###/#...#..#/#...####/#...####/.###.###/#..##.../#####.../#####...",
3589
+ weave: "#...#.../.#.#.#../..#...#./.#...#.#/#...#.../...#.#../..#...#./.#.#...#",
3590
+ divot: "......../...#..../....#.../...#..../......../#......./.......#/#.......",
3591
+ shingle: "......##/#....#../.#..#.../..##..../....##../......#./.......#/.......#",
3592
+ wave: "......../...##.../..#..#.#/##....../......../...##.../..#..#.#/##......",
3593
+ trellis: "########/.##..##./########/#..##..#/########/.##..##./########/#..##..#",
3594
+ zigZag: "#......#/.#....#./..#..#../...##.../#......#/.#....#./..#..#../...##..."
3595
+ };
3596
+ function rows(preset) {
3597
+ const art = MEASURED[preset];
3598
+ if (!art) return void 0;
3599
+ return art.split("/").map((row) => [...row].reduce((bits, cell, index) => cell === "#" ? bits | 128 >> index : bits, 0));
3600
+ }
3601
+ var BITMAPS = /* @__PURE__ */ new Map();
3602
+ for (const preset of PATTERN_PRESETS) {
3603
+ const bitmap = rows(preset);
3604
+ if (bitmap) BITMAPS.set(preset, Object.freeze(bitmap));
3605
+ }
3606
+ function resolvePatternPreset(preset) {
3607
+ if (typeof preset !== "string") return void 0;
3608
+ if (BITMAPS.has(preset)) return preset;
3609
+ return Object.hasOwn(PATTERN_PRESET_ALIASES, preset) ? PATTERN_PRESET_ALIASES[preset] : void 0;
3610
+ }
3611
+ function patternBitmap(preset) {
3612
+ const resolved = resolvePatternPreset(preset);
3613
+ return resolved === void 0 ? void 0 : BITMAPS.get(resolved);
3614
+ }
3615
+ function patternRuns(preset) {
3616
+ const bitmap = patternBitmap(preset);
3617
+ if (!bitmap) return void 0;
3618
+ const runs = [];
3619
+ bitmap.forEach((row, y) => {
3620
+ for (let x = 0; x < 8; x++) {
3621
+ if (!(row & 128 >> x)) continue;
3622
+ const start = x;
3623
+ while (x + 1 < 8 && row & 128 >> x + 1) x++;
3624
+ runs.push({ x: start, y, width: x - start + 1 });
3625
+ }
3626
+ });
3627
+ return runs;
3628
+ }
2666
3629
 
2667
3630
  // src/annotations.ts
2668
3631
  var CITATION_MARKER_SCALE = 2 / 3;
@@ -2676,6 +3639,7 @@ var isRecord3 = (value) => !!value && typeof value === "object" && !Array.isArra
2676
3639
  var round = (value) => Math.round(value * 1e6) / 1e6 || value;
2677
3640
  var regionKey = /^(top|middle|bottom|left|center|right)([+:]|$)/;
2678
3641
  var TEXT_FIELDS = ["text", "items", "bullets"];
3642
+ var HEADING_FIELDS = ["tag", "title", "subtitle"];
2679
3643
  function annotationText(value) {
2680
3644
  if (typeof value === "string") return value;
2681
3645
  if (Array.isArray(value)) return value.map((run) => typeof run === "string" ? run : record4(run).text ?? "").join("");
@@ -2723,8 +3687,10 @@ function walkCitationRuns(slide, basePath, visit) {
2723
3687
  if (field === "text") runs(payload.text, `${path}.text`);
2724
3688
  else list(payload[field], `${path}.${field}`);
2725
3689
  }
3690
+ if (isRecord3(payload.quote)) runs(payload.quote.text, `${path}.quote.text`);
2726
3691
  };
2727
3692
  const value = record4(slide);
3693
+ for (const field of HEADING_FIELDS) runs(value[field], `${basePath}.${field}`);
2728
3694
  const regions = Object.keys(value).filter((key) => regionKey.test(key)).sort();
2729
3695
  if (regions.length) {
2730
3696
  for (const key of regions) host(value[key], `${basePath}.${key}`, 0);
@@ -2846,23 +3812,36 @@ function referencesSlide(presentation, options = {}) {
2846
3812
  return { title, items };
2847
3813
  }
2848
3814
 
3815
+ // src/layout-content.ts
3816
+ var LAYOUT_BODY_KINDS = ["text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
3817
+ var bodyKinds = new Set(LAYOUT_BODY_KINDS);
3818
+ function layoutContent(record6) {
3819
+ const heading = { title: false, subtitle: false, tag: false };
3820
+ const counts = /* @__PURE__ */ new Map();
3821
+ let count = 0;
3822
+ for (const placeholder of Array.isArray(record6?.placeholders) ? record6.placeholders : []) {
3823
+ const type = placeholder?.type;
3824
+ if (type === "title" || type === "subtitle" || type === "tag") heading[type] = true;
3825
+ else if (typeof type === "string" && bodyKinds.has(type)) {
3826
+ counts.set(type, (counts.get(type) ?? 0) + 1);
3827
+ count += 1;
3828
+ }
3829
+ }
3830
+ let kind2 = "title", best = 0;
3831
+ for (const [candidate, total] of counts) if (total > best) {
3832
+ kind2 = candidate;
3833
+ best = total;
3834
+ }
3835
+ return { kind: kind2, count, heading };
3836
+ }
3837
+
2849
3838
  // src/composition.ts
2850
3839
  var MAX_COMPOSITION_DEPTH = 32;
2851
3840
  var FALLBACK_CODE_FAMILY = "Roboto Mono";
2852
- var DEFAULT_FONT_SCHEME = "aptos";
2853
- var DEFAULT_FONT_FAMILIES = { heading: "Aptos Display", body: "Aptos" };
2854
- function resolveFontSchemeReference(reference, lookup, path = "design.fontScheme") {
2855
- const overrides = typeof reference === "object" && reference !== null && !Array.isArray(reference) ? reference : void 0;
2856
- const id = typeof reference === "string" ? reference : typeof overrides?.id === "string" ? overrides.id : void 0;
2857
- const found = id === void 0 ? void 0 : lookup(id);
2858
- const base = record5(found ?? lookup(DEFAULT_FONT_SCHEME));
2859
- const scheme = overrides ? { ...base, ...overrides } : { ...base };
2860
- if (id === void 0 || found !== void 0) return { scheme };
2861
- return { scheme, diagnostic: { code: "unresolved-font-scheme", path, id, fallback: DEFAULT_FONT_SCHEME, message: `Font scheme '${id}' is not in the inline or bundled catalogs; using the default font scheme '${DEFAULT_FONT_SCHEME}'.` } };
2862
- }
3841
+ var DEFAULT_FONT_FAMILIES = { heading: String(ENGINE_DEFAULT_FONT_SCHEME.major), body: String(ENGINE_DEFAULT_FONT_SCHEME.minor) };
2863
3842
  function resolveFontFamilies(input) {
2864
3843
  const scheme = record5(input);
2865
- const family = (value) => typeof value === "string" ? value : record5(value).family;
3844
+ const family = (value) => typeof value === "string" && value ? value : void 0;
2866
3845
  const accent = family(scheme.accent);
2867
3846
  return {
2868
3847
  heading: family(scheme.heading) ?? scheme.major ?? scheme.minor ?? DEFAULT_FONT_FAMILIES.heading,
@@ -2945,19 +3924,32 @@ var OPFCompositionError = class extends Error {
2945
3924
  };
2946
3925
  var fields = ["text", "items", "bullets", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
2947
3926
  var headings = /* @__PURE__ */ new Set(["title", "subtitle", "tag"]);
2948
- var COVER_LAYOUT_IDS = /* @__PURE__ */ new Set(["title", "title-subtitle"]);
2949
- var rows = ["top", "middle", "bottom"];
3927
+ var rows2 = ["top", "middle", "bottom"];
2950
3928
  var columns = ["left", "center", "right"];
2951
3929
  var record5 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
2952
3930
  var kind = (field) => field === "items" ? "list" : field === "bullets" ? "text" : field;
2953
3931
  var round2 = (value) => Math.round(value * 1e6) / 1e6 || value;
2954
- var SLIDE_IMAGE_POSITIONS = ["background", "top", "bottom", "left", "right"];
2955
- var SLIDE_IMAGE_BAND = 0.5;
3932
+ var PLACEMENT_BAND = 0.5;
3933
+ var IMAGE_EDGES = ["left", "right", "top", "bottom"];
3934
+ var IMAGE_FITS = ["cover", "contain", "stretch"];
3935
+ var BACKGROUND_FITS = ["cover", "contain", "stretch", "tile"];
3936
+ var IMAGE_SOURCE = /^(asset:|https:\/\/|data:|\.\/|\.\.\/)/;
3937
+ var IMAGE_OPTION_KEYS = ["fit", "focus", "aspectRatio", "shape", "cornerRadius", "border", "opacity", "recolor", "overlay", "placement"];
3938
+ var imagePayload = (host) => {
3939
+ const payload = { type: host.type ?? "image", image: host.image };
3940
+ for (const key of IMAGE_OPTION_KEYS) if (host[key] !== void 0) payload[key] = host[key];
3941
+ return payload;
3942
+ };
2956
3943
  var assetSource = (value) => typeof value === "string" ? value : record5(value).src;
2957
3944
  var finite = (value, min, max) => typeof value === "number" && Number.isFinite(value) && value >= min && value <= max ? value : void 0;
2958
3945
  var pathNumber = (value) => String(round2(value));
2959
- var SLIDE_IMAGE_SHAPES = { rectangle: "rect", rounded: "roundRect", circle: "ellipse", hexagon: "hexagon" };
2960
- function slideImageShape(kind2, box, cornerRadius = 1 / 6) {
3946
+ var IMAGE_SHAPES = { rectangle: "rect", rounded: "roundRect", circle: "ellipse", hexagon: "hexagon" };
3947
+ var roundBox = (box) => ({ x: round2(box.x), y: round2(box.y), width: round2(box.width), height: round2(box.height) });
3948
+ var imageFocus = (value) => {
3949
+ const focus = record5(value), x = finite(focus.x, 0, 1), y = finite(focus.y, 0, 1);
3950
+ return x !== void 0 && y !== void 0 ? { x, y } : { x: 0.5, y: 0.5 };
3951
+ };
3952
+ function imageShape(kind2, box, cornerRadius = 1 / 6) {
2961
3953
  const { x, y, width: w, height: h } = box, r = x + w, b = y + h, ss = Math.min(w, h), n = pathNumber;
2962
3954
  const rect = `M${n(x)} ${n(y)}H${n(r)}V${n(b)}H${n(x)}Z`;
2963
3955
  if (kind2 === "rounded") {
@@ -2976,66 +3968,96 @@ function slideImageShape(kind2, box, cornerRadius = 1 / 6) {
2976
3968
  }
2977
3969
  return { kind: "rectangle", preset: "rect", adjust: {}, path: rect };
2978
3970
  }
2979
- function resolveSlideImage(slide, layout, presentation, width, height, path, padding, scale, diagnostics, rtl = false) {
2980
- const own2 = record5(slide.design), deck = record5(record5(presentation).design);
2981
- const local = own2.slideImage !== void 0;
2982
- const configured = local ? own2.slideImage : deck.slideImage;
2983
- if (!configured || typeof configured !== "object" && typeof configured !== "string") return void 0;
2984
- const treatment = typeof configured === "object" && !Array.isArray(configured) && "position" in configured ? record5(configured) : void 0;
2985
- const alignment = typeof layout.slideImageAlignment === "string" ? layout.slideImageAlignment.toLowerCase() : void 0;
2986
- const authoredPosition = treatment ? treatment.position : SLIDE_IMAGE_POSITIONS.find((value2) => value2 === alignment) ?? "background";
2987
- if (!SLIDE_IMAGE_POSITIONS.includes(authoredPosition)) return void 0;
2988
- const mirrorSide = (side) => !rtl ? side : side === "left" ? "right" : side === "right" ? "left" : side;
2989
- const position = mirrorSide(authoredPosition);
2990
- const designSource = treatment ? treatment.src : configured;
2991
- const root = slide.image, sameSource = root !== void 0 && designSource !== void 0 && assetSource(root) === assetSource(designSource);
2992
- if (!local && layout.slideImage !== true && !sameSource) return void 0;
2993
- const replacesContent = root !== void 0 && (designSource === void 0 || sameSource);
2994
- const value = replacesContent ? root : designSource;
2995
- const source = assetSource(value);
2996
- if (typeof source !== "string" || !source) return void 0;
2997
- const t = treatment ?? {};
2998
- const fill = t.fill === "crop" || t.fill === "fit" ? t.fill : (own2.imageFill ?? deck.imageFill) === "fit" ? "fit" : "crop";
2999
- const share = finite(t.size, 0.1, 0.9) ?? SLIDE_IMAGE_BAND;
3000
- const band = { width: round2(width * share), height: round2(height * share) };
3001
- const region = position === "left" ? { x: 0, y: 0, width: band.width, height } : position === "right" ? { x: round2(width - band.width), y: 0, width: band.width, height } : position === "top" ? { x: 0, y: 0, width, height: band.height } : position === "bottom" ? { x: 0, y: round2(height - band.height), width, height: band.height } : { x: 0, y: 0, width, height };
3002
- const designPath = local ? `${path}.design.slideImage` : "design.slideImage";
3003
- const kind2 = Object.hasOwn(SLIDE_IMAGE_SHAPES, t.shape) ? t.shape : "rectangle";
3004
- let box = t.inset === true ? { x: region.x + padding, y: region.y + padding, width: Math.max(scale, region.width - 2 * padding), height: Math.max(scale, region.height - 2 * padding) } : { ...region };
3005
- const aspect = kind2 === "circle" ? 1 : finite(t.aspectRatio, Number.MIN_VALUE, 10);
3971
+ function fitImage(frame, fit, aspect, focus = { x: 0.5, y: 0.5 }) {
3972
+ if (![frame.x, frame.y, frame.width, frame.height].every(Number.isFinite) || frame.width <= 0 || frame.height <= 0) throw new RangeError("An image frame needs finite coordinates and a positive size.");
3973
+ if (fit === "stretch" || !Number.isFinite(aspect) || aspect <= 0) return { image: roundBox(frame), crop: { left: 0, top: 0, right: 0, bottom: 0 } };
3974
+ const wide = aspect > frame.width / frame.height, cover = fit === "cover";
3975
+ const width = wide === cover ? frame.height * aspect : frame.width, height = wide === cover ? frame.height : frame.width / aspect;
3976
+ const point = imageFocus(focus);
3977
+ const place = (start, span, size, at3) => cover ? Math.min(start, Math.max(start + span - size, start + span / 2 - at3 * size)) : start + (span - size) / 2;
3978
+ const image = { x: place(frame.x, frame.width, width, point.x), y: place(frame.y, frame.height, height, point.y), width, height };
3979
+ const crop = {
3980
+ left: round2((frame.x - image.x) / width),
3981
+ top: round2((frame.y - image.y) / height),
3982
+ right: round2((image.x + width - frame.x - frame.width) / width),
3983
+ bottom: round2((image.y + height - frame.y - frame.height) / height)
3984
+ };
3985
+ for (const key of ["left", "top", "right", "bottom"]) if (Object.is(crop[key], -0)) crop[key] = 0;
3986
+ return { image: roundBox(image), crop };
3987
+ }
3988
+ function imageBackground(value) {
3989
+ if (typeof value === "string") return IMAGE_SOURCE.test(value) ? { src: value, fit: "cover", focus: { x: 0.5, y: 0.5 } } : void 0;
3990
+ const background = record5(value);
3991
+ if (background.type !== "image" || typeof background.src !== "string" || !background.src) return void 0;
3992
+ const opacity = finite(background.opacity, 0, 1);
3993
+ return {
3994
+ src: background.src,
3995
+ ...typeof background.alt === "string" ? { alt: background.alt } : {},
3996
+ fit: BACKGROUND_FITS.includes(background.fit) ? background.fit : "cover",
3997
+ focus: imageFocus(background.focus),
3998
+ ...opacity !== void 0 ? { opacity } : {},
3999
+ ...background.recolor !== void 0 ? { recolor: background.recolor } : {},
4000
+ ...background.overlay !== void 0 ? { overlay: background.overlay } : {}
4001
+ };
4002
+ }
4003
+ function composeRecolor(value) {
4004
+ if (value === "grayscale") return { type: "grayscale" };
4005
+ const duotone = record5(value);
4006
+ return duotone.dark !== void 0 && duotone.light !== void 0 ? { type: "duotone", dark: duotone.dark, light: duotone.light } : void 0;
4007
+ }
4008
+ function composeOverlay(value, frame, shape, path, mirrorSide, diagnostics) {
4009
+ const overlay = record5(value), opacity = finite(overlay.opacity, 0, 1);
4010
+ if (overlay.color === void 0 || opacity === void 0) return void 0;
4011
+ const edge = IMAGE_EDGES.includes(overlay.edge) ? mirrorSide(overlay.edge) : void 0;
4012
+ if (edge && shape.kind !== "rectangle") {
4013
+ diagnostics.push({ code: "unsupported-image-treatment", path: `${path}.edge`, message: "An edge overlay needs a rectangle frame; a band cannot follow a rounded, circular or hexagonal mask as one native shape. Remove edge or use shape rectangle." });
4014
+ return void 0;
4015
+ }
4016
+ const part = finite(overlay.size, 0.05, 1) ?? 0.3;
4017
+ const box = !edge ? frame : edge === "top" ? { ...frame, height: round2(frame.height * part) } : edge === "bottom" ? { ...frame, y: round2(frame.y + frame.height * (1 - part)), height: round2(frame.height * part) } : edge === "left" ? { ...frame, width: round2(frame.width * part) } : { ...frame, x: round2(frame.x + frame.width * (1 - part)), width: round2(frame.width * part) };
4018
+ return { path, color: overlay.color, opacity, ...edge ? { edge } : {}, box, shape: edge ? imageShape("rectangle", box) : shape };
4019
+ }
4020
+ function composeImage(host, hostPath, region, frameArea, context) {
4021
+ const kindName = Object.hasOwn(IMAGE_SHAPES, host.shape) ? host.shape : "rectangle";
4022
+ const { scale } = context;
4023
+ let box = { ...frameArea };
4024
+ const aspect = kindName === "circle" ? 1 : finite(host.aspectRatio, Number.MIN_VALUE, 10);
3006
4025
  if (aspect) {
3007
4026
  const frameWidth = Math.min(box.width, box.height * aspect), frameHeight = frameWidth / aspect;
3008
4027
  box = { x: box.x + (box.width - frameWidth) / 2, y: box.y + (box.height - frameHeight) / 2, width: frameWidth, height: frameHeight };
3009
4028
  }
3010
- box = { x: round2(box.x), y: round2(box.y), width: round2(box.width), height: round2(box.height) };
3011
- const result = {
3012
- path: designPath,
3013
- sourcePath: replacesContent ? `${path}.image` : designPath,
3014
- value,
3015
- position,
3016
- fill,
3017
- region,
3018
- box,
3019
- replacesContent,
3020
- shape: slideImageShape(kind2, box, finite(t.cornerRadius, 0, 0.5))
3021
- };
3022
- if (typeof t.alt === "string") result.alt = t.alt;
3023
- const border = record5(t.border), borderWidth = finite(border.width, 0, 64);
4029
+ box = roundBox(box);
4030
+ const fit = IMAGE_FITS.includes(host.fit) ? host.fit : context.fit ?? "cover";
4031
+ const focus = imageFocus(host.focus);
4032
+ const shape = imageShape(kindName, box, finite(host.cornerRadius, 0, 0.5));
4033
+ const result = { region: roundBox(region), box, fit, focus, shape };
4034
+ const border = record5(host.border), borderWidth = finite(border.width, 0, 64);
3024
4035
  if (border.color !== void 0 && borderWidth) result.border = { color: border.color, width: round2(borderWidth * scale) };
3025
- const opacity = finite(t.opacity, 0, 1);
4036
+ const opacity = finite(host.opacity, 0, 1);
3026
4037
  if (opacity !== void 0 && opacity < 1) result.opacity = opacity;
3027
- if (t.recolor === "grayscale") result.recolor = { type: "grayscale" };
3028
- else if (record5(t.recolor).dark !== void 0 && record5(t.recolor).light !== void 0) result.recolor = { type: "duotone", dark: t.recolor.dark, light: t.recolor.light };
3029
- const overlay = record5(t.overlay), overlayOpacity = finite(overlay.opacity, 0, 1);
3030
- if (overlay.color !== void 0 && overlayOpacity !== void 0) {
3031
- const edge = ["top", "bottom", "left", "right"].includes(overlay.edge) ? mirrorSide(overlay.edge) : void 0;
3032
- if (edge && kind2 !== "rectangle") diagnostics.push({ code: "unsupported-image-treatment", path: `${designPath}.overlay.edge`, message: "An edge overlay needs a rectangle frame; a band cannot follow a rounded, circular or hexagonal mask as one native shape. Remove edge or use shape rectangle." });
3033
- else {
3034
- const part = finite(overlay.size, 0.05, 1) ?? 0.3;
3035
- const bandBox = !edge ? box : edge === "top" ? { ...box, height: round2(box.height * part) } : edge === "bottom" ? { ...box, y: round2(box.y + box.height * (1 - part)), height: round2(box.height * part) } : edge === "left" ? { ...box, width: round2(box.width * part) } : { ...box, x: round2(box.x + box.width * (1 - part)), width: round2(box.width * part) };
3036
- result.overlay = { color: overlay.color, opacity: overlayOpacity, box: bandBox, shape: edge ? slideImageShape("rectangle", bandBox) : result.shape };
3037
- }
3038
- }
4038
+ const recolor = composeRecolor(host.recolor);
4039
+ if (recolor) result.recolor = recolor;
4040
+ const overlay = composeOverlay(host.overlay, box, shape, `${hostPath}.overlay`, context.mirrorSide, context.diagnostics);
4041
+ if (overlay) result.overlay = overlay;
4042
+ if (context.placement) result.placement = context.placement;
4043
+ const pictureAspect = intrinsicImageAspect(host.image, context.assets);
4044
+ if (pictureAspect) result.picture = fitImage(box, fit, pictureAspect, focus);
4045
+ return result;
4046
+ }
4047
+ function resolveBackgroundImage(slide, presentation, themeBackground, width, height, path, mirrorSide, diagnostics) {
4048
+ const own2 = record5(slide.design), deck = record5(record5(presentation).design);
4049
+ const [value, at3] = own2.background !== void 0 ? [own2.background, `${path}.design.background`] : deck.background !== void 0 ? [deck.background, "design.background"] : [themeBackground, "theme"];
4050
+ const background = imageBackground(value);
4051
+ if (!background) return void 0;
4052
+ const box = { x: 0, y: 0, width, height };
4053
+ const result = { path: at3, src: background.src, ...background.alt !== void 0 ? { alt: background.alt } : {}, fit: background.fit, focus: background.focus, box };
4054
+ if (background.opacity !== void 0 && background.opacity < 1) result.opacity = background.opacity;
4055
+ const recolor = composeRecolor(background.recolor);
4056
+ if (recolor) result.recolor = recolor;
4057
+ const overlay = composeOverlay(background.overlay, box, imageShape("rectangle", box), `${at3}.overlay`, mirrorSide, diagnostics);
4058
+ if (overlay) result.overlay = overlay;
4059
+ const aspect = background.fit === "tile" ? void 0 : intrinsicImageAspect(background.src, record5(presentation).assets);
4060
+ if (aspect) result.picture = fitImage(box, background.fit, aspect, background.focus);
3039
4061
  return result;
3040
4062
  }
3041
4063
  var LOGO_LOCKUP_CHAINS = {
@@ -3058,10 +4080,10 @@ function resolveLogo(presentation, slide, options = {}) {
3058
4080
  if (typeof value === "string" || typeof value === "object" && !Array.isArray(value) && "src" in record5(value)) {
3059
4081
  return usable(value) ? { source: value, path, variant: "default", slot } : null;
3060
4082
  }
3061
- const set = record5(value);
3062
- if (!Object.keys(set).some((key) => LOGO_SET_KEYS.has(key))) return null;
4083
+ const set2 = record5(value);
4084
+ if (!Object.keys(set2).some((key) => LOGO_SET_KEYS.has(key))) return null;
3063
4085
  for (const key of chain) {
3064
- const variant = set[key];
4086
+ const variant = set2[key];
3065
4087
  if (variant !== void 0 && usable(variant)) return { source: variant, path: `${path}.${key}`, variant: key, slot };
3066
4088
  }
3067
4089
  return null;
@@ -3078,11 +4100,11 @@ function resolveLogo(presentation, slide, options = {}) {
3078
4100
  return pick(record5(organizations[index]).logo, Array.isArray(deck.organization) ? `organization.${index}.logo` : "organization.logo");
3079
4101
  }
3080
4102
  var webUrl = /^https?:\/\/\S+$/i;
3081
- function resolveSocialProfile(platform, value, records = [], owner = "organization") {
4103
+ function resolveSocialProfile(platform, value, owner = "organization") {
3082
4104
  const raw = String(value).trim().replace(/\s+/gu, " ");
3083
4105
  const display = (url2) => url2.replace(/^https:\/\//i, "");
3084
4106
  if (webUrl.test(raw)) return { text: display(raw), href: raw, resolved: false };
3085
- const platformRecord = records.find((item) => item?.id === platform);
4107
+ const platformRecord = Object.hasOwn(SOCIAL_PLATFORMS, platform) ? SOCIAL_PLATFORMS[platform] : void 0;
3086
4108
  const base = typeof platformRecord?.baseUrl === "string" && webUrl.test(platformRecord.baseUrl) ? `${platformRecord.baseUrl.replace(/\/+$/u, "")}/{handle}` : void 0;
3087
4109
  const pattern = (owner === "organization" ? platformRecord?.companyUrlPattern : void 0) ?? platformRecord?.profileUrlPattern ?? base;
3088
4110
  const prefix = platformRecord?.handlePrefix ?? "";
@@ -3108,8 +4130,8 @@ function layoutFurniture(input, options = {}) {
3108
4130
  const sourceRoot = `slides.${options.slideIndex ?? 0}`, organizations = Array.isArray(options.presentation?.organization) ? options.presentation.organization : [options.presentation?.organization];
3109
4131
  const primaryIndex = organizations.findIndex((item) => record5(item).role === "primary"), organizationIndex = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
3110
4132
  const organization = record5(organizations[organizationIndex]), organizationRoot = Array.isArray(options.presentation?.organization) ? `organization.${organizationIndex}` : "organization", organizationPath = `${organizationRoot}.name`;
3111
- const inlinePlatforms = record5(record5(options.presentation?.catalogs).socialPlatforms).records, platformRecords = [...Array.isArray(inlinePlatforms) ? inlinePlatforms : [], ...options.socialPlatforms ?? []];
3112
- const fontFamily = options.fonts?.body ?? "sans-serif";
4133
+ const speakers = Array.isArray(options.presentation?.speaker) ? options.presentation.speaker : [options.presentation?.speaker], speaker = record5(speakers[0]), speakerRoot = Array.isArray(options.presentation?.speaker) ? "speaker.0" : "speaker";
4134
+ const fontFamily = options.fontFamilies?.body ?? "sans-serif";
3113
4135
  let headerBottom = 0, footerTop = height, configured = false;
3114
4136
  const error = (path, message, code = "text-overflow") => diagnostics.push({ code, path, message });
3115
4137
  for (const kind2 of ["header", "footer"]) {
@@ -3179,8 +4201,12 @@ function layoutFurniture(input, options = {}) {
3179
4201
  if (typeof organization.name === "string") add("organization", organization.name, true, organizationPath);
3180
4202
  else error(`${path}.organization`, "Generated organization name needs a named organization in the presentation.", "unresolved-content");
3181
4203
  }
4204
+ if (content.speaker === true) {
4205
+ if (typeof speaker.name === "string" && speaker.name.trim()) add("speaker", typeof speaker.title === "string" && speaker.title.trim() ? `${speaker.name}, ${speaker.title}` : speaker.name, true, `${speakerRoot}.name`);
4206
+ else error(`${path}.speaker`, "Generated speaker needs a named speaker in the presentation.", "unresolved-content");
4207
+ }
3182
4208
  if (content.socials === true) {
3183
- const links = Object.entries(record5(organization.socials)).filter(([, value2]) => typeof value2 === "string" && value2.trim()).map(([platform, value2]) => ({ platform, sourcePath: `${organizationRoot}.socials.${platform}`, ...resolveSocialProfile(platform, value2, platformRecords, "organization") }));
4209
+ const links = Object.entries(record5(organization.socials)).filter(([, value2]) => typeof value2 === "string" && value2.trim()).map(([platform, value2]) => ({ platform, sourcePath: `${organizationRoot}.socials.${platform}`, ...resolveSocialProfile(platform, value2, "organization") }));
3184
4210
  if (links.length) add("socials", links.map((link) => link.text).join("\n"), true, `${organizationRoot}.socials`, { links });
3185
4211
  else error(`${path}.socials`, "Generated social profiles need a primary organization with socials.", "unresolved-content");
3186
4212
  }
@@ -3272,12 +4298,25 @@ function fitAtSizes(layout, requested, minimum, step = 1, snap = true) {
3272
4298
  }
3273
4299
  throw new Error("Text fitting did not evaluate its bounded floor trial.");
3274
4300
  }
4301
+ var PHOTO_RATIO = 3;
4302
+ var PHOTO_GAP = 0.75;
4303
+ function quoteBodyRuns(runs) {
4304
+ if (!runs.length) return ['""'];
4305
+ const last = runs.length - 1;
4306
+ return runs.map((run, index) => {
4307
+ const before = index === 0 ? '"' : "", after = index === last ? '"' : "";
4308
+ return typeof run === "string" ? before + run + after : { ...run, text: before + run.text + after };
4309
+ });
4310
+ }
3275
4311
  function layoutQuote(value, box, options = {}) {
3276
4312
  const shorthand = typeof value === "string";
3277
4313
  const quote = shorthand ? { text: value } : value;
3278
- if (!quote || Array.isArray(quote) || typeof quote.text !== "string" || [quote.attribution, quote.source].some((field) => field !== void 0 && typeof field !== "string")) {
3279
- throw new TypeError("Quote content must be a string or a text object with optional string attribution/source.");
4314
+ const photoValue = quote?.photo;
4315
+ if (!quote || Array.isArray(quote) || typeof quote.text !== "string" && !Array.isArray(quote.text) || [quote.attribution, quote.role, quote.source].some((field) => field !== void 0 && typeof field !== "string") || photoValue !== void 0 && typeof photoValue !== "string" && !(typeof photoValue === "object" && photoValue !== null && typeof photoValue.src === "string")) {
4316
+ throw new TypeError("Quote content must be a string or a text object (text a string or TextRun[]) with optional string attribution/role/source and an asset photo.");
3280
4317
  }
4318
+ const richBody = Array.isArray(quote.text) ? quote.text : void 0;
4319
+ const quoteText = richBody ? annotationText(richBody) : quote.text;
3281
4320
  const scale = options.scale ?? 1, minimum = snapFontSizeUp((options.minFontSize ?? 16) * scale);
3282
4321
  if (![box.x, box.y, box.width, box.height, scale, minimum].every(Number.isFinite) || box.width <= 0 || box.height <= 0 || scale <= 0 || minimum <= 0) {
3283
4322
  throw new RangeError("Quote dimensions, scale and minimum font size must be finite and positive.");
@@ -3287,78 +4326,96 @@ function layoutQuote(value, box, options = {}) {
3287
4326
  const diagnostics = [], parts = [];
3288
4327
  const report = (reason, diagnosticPath, roles, message) => diagnostics.push({ code: "text-overflow", reason, path: diagnosticPath, parts: roles, message });
3289
4328
  const source = (sourcePath, text2, outputStart) => ({ path: sourcePath, start: 0, end: text2.length, outputStart, outputEnd: outputStart + text2.length });
3290
- const add = (role, text2, sources, area, fontSize, fontFamily, fontWeight, partPath) => {
4329
+ const add = (role, text2, sources, area, fontSize, fontFamily, fontWeight, partPath, runs) => {
3291
4330
  const requestedStyle = { fontFamily, fontWeight, italic: false, path: partPath };
3292
4331
  const style = resolveTextStyle({ ...requestedStyle }, options.textMeasurement);
3293
4332
  const requestedFontSize = gridFontSize(fontSize * scale, minimum);
3294
- const part = { role, path: partPath, text: text2, sources, box: area, requestedFontSize, minFontSize: minimum, requestedStyle, style };
4333
+ const part = { role, path: partPath, text: text2, sources, box: area, requestedFontSize, minFontSize: minimum, requestedStyle, style, ...runs ? { runs } : {} };
3295
4334
  parts.push(part);
3296
4335
  return part;
3297
4336
  };
3298
4337
  let footer = "";
3299
4338
  const footerSources = [];
3300
- for (const field of ["attribution", "source"]) {
4339
+ for (const field of ["attribution", "role", "source"]) {
3301
4340
  const text2 = quote[field];
3302
4341
  if (!text2) continue;
3303
- if (footer) footer += " - ";
4342
+ if (footer) footer += field === "role" ? "\n" : " - ";
3304
4343
  footerSources.push(source(`${path}.${field}`, text2, footer.length));
3305
4344
  footer += text2;
3306
4345
  }
4346
+ const hasPhoto = photoValue !== void 0, hasFooter = footer !== "", hasBlock = hasPhoto || hasFooter;
4347
+ const photoPath = `${path}.photo`, rtl = options.direction === "rtl";
3307
4348
  const bodyPath = shorthand ? path : `${path}.text`;
3308
4349
  const body = add(
3309
4350
  "body",
3310
- `"${quote.text}"`,
3311
- [source(bodyPath, quote.text, 1)],
3312
- { x: box.x + 18, y: box.y + 18, width: box.width - 36, height: box.height - (footer ? 94 : 36) },
4351
+ `"${quoteText}"`,
4352
+ [source(bodyPath, quoteText, 1)],
4353
+ { x: box.x + 18, y: box.y + 18, width: box.width - 36, height: box.height - (hasBlock ? 94 : 36) },
3313
4354
  28,
3314
- options.fonts?.accent ?? options.fonts?.heading ?? "sans-serif",
4355
+ options.fontFamilies?.accent ?? options.fontFamilies?.heading ?? "sans-serif",
3315
4356
  600,
3316
- bodyPath
4357
+ bodyPath,
4358
+ richBody ? quoteBodyRuns(richBody) : void 0
3317
4359
  );
3318
- const attribution = footer ? add(
4360
+ const attribution = hasFooter ? add(
3319
4361
  "footer",
3320
4362
  footer,
3321
4363
  footerSources,
3322
4364
  { x: box.x + 18, y: box.y + box.height - 58, width: box.width - 36, height: 40 },
3323
4365
  17,
3324
- options.fonts?.body ?? "sans-serif",
4366
+ options.fontFamilies?.body ?? "sans-serif",
3325
4367
  500,
3326
4368
  path
3327
4369
  ) : void 0;
4370
+ const footerRequested = attribution?.requestedFontSize ?? gridFontSize(17 * scale, minimum);
3328
4371
  const usable = (area) => [area.x, area.y, area.width, area.height].every(Number.isFinite) && area.width > 0 && area.height > 0;
3329
- const fit = (part, area, size = part.requestedFontSize, floor = minimum) => usable(area) ? fitText(part.text, area, size, floor, textWidthMeasurer(part.style, options.textMeasurement), options.direction) : void 0;
4372
+ const fit = (part, area, size = part.requestedFontSize, floor = minimum) => !usable(area) ? void 0 : part.runs ? fitRichText(part.runs, area, size, floor, { style: part.style, textMeasurement: options.textMeasurement, ...options.citationMarker ? { citationMarker: options.citationMarker } : {}, ...options.direction ? { direction: options.direction } : {} }) : fitText(part.text, area, size, floor, textWidthMeasurer(part.style, options.textMeasurement), options.direction);
4373
+ const heightOf = (fit2) => "richLines" in fit2 ? fit2.height : fit2.lines.length * fit2.lineHeight;
3330
4374
  const inner = { x: box.x + 18, y: box.y + 18, width: box.width - 36, height: box.height - 36 };
3331
- if (!attribution) body.fit = fit(body, body.box);
4375
+ let photo, photoFits = true;
4376
+ if (!hasBlock) body.fit = fit(body, body.box);
3332
4377
  else if (usable(inner) && inner.height > 18) {
3333
4378
  const available = inner.height - 18;
3334
4379
  const preferredBody = fit(body, inner, body.requestedFontSize, body.requestedFontSize);
3335
4380
  const minimumBody = body.requestedFontSize === minimum ? preferredBody : fit(body, inner, minimum, minimum);
3336
- const preferredBodyHeight = preferredBody.lines.length * preferredBody.lineHeight;
3337
- const minimumBodyHeight = minimumBody.lines.length * minimumBody.lineHeight;
4381
+ const preferredBodyHeight = heightOf(preferredBody);
4382
+ const minimumBodyHeight = heightOf(minimumBody);
3338
4383
  let selected;
3339
- for (const size of /* @__PURE__ */ new Set([attribution.requestedFontSize, minimum])) {
3340
- const natural = fit(attribution, inner, size, size);
3341
- const naturalHeight = natural.lines.length * natural.lineHeight;
3342
- const preferredHeight = Math.max(40, naturalHeight);
3343
- const bodyReservation = Math.min(minimumBodyHeight, Math.max(minimumBody.lineHeight, available - natural.lineHeight));
3344
- const footerHeight = preferredBodyHeight + preferredHeight <= available + 0.01 ? preferredHeight : Math.min(naturalHeight, Math.max(0, available - bodyReservation));
4384
+ for (const size of /* @__PURE__ */ new Set([footerRequested, minimum])) {
4385
+ const diameter = hasPhoto ? PHOTO_RATIO * size : 0, gap = hasPhoto ? PHOTO_GAP * size : 0;
4386
+ const textArea = { ...inner, width: inner.width - diameter - gap, x: rtl ? inner.x : inner.x + diameter + gap };
4387
+ const natural = attribution ? fit(attribution, textArea, size, size) : void 0;
4388
+ const naturalHeight = natural ? natural.lines.length * natural.lineHeight : 0;
4389
+ const blockHeight = Math.max(naturalHeight, diameter);
4390
+ const lineHeight = natural?.lineHeight ?? size * 1.22;
4391
+ const preferredHeight = Math.max(40, blockHeight);
4392
+ const bodyReservation = Math.min(minimumBodyHeight, Math.max(minimumBody.lineHeight, available - lineHeight));
4393
+ const footerHeight = preferredBodyHeight + preferredHeight <= available + 0.01 ? preferredHeight : Math.min(blockHeight, Math.max(0, available - bodyReservation));
3345
4394
  const bodyBox = { ...inner, height: available - footerHeight };
3346
4395
  const footerBox = { ...inner, y: inner.y + inner.height - footerHeight, height: footerHeight };
3347
4396
  const bodyFit = fit(body, bodyBox);
3348
- const footerFit = usable(footerBox) ? { ...natural, overflow: natural.overflow || naturalHeight > footerHeight + 0.01 } : void 0;
3349
- const overflow = !bodyFit || !footerFit || bodyFit.overflow || footerFit.overflow;
3350
- const score = (body.requestedFontSize - (bodyFit?.fontSize ?? minimum) + attribution.requestedFontSize - size) / scale;
4397
+ const photoBox = hasPhoto ? { x: rtl ? inner.x + inner.width - diameter : inner.x, y: footerBox.y + (footerHeight - diameter) / 2, width: diameter, height: diameter } : void 0;
4398
+ const textBox = attribution ? hasPhoto ? { ...textArea, y: footerBox.y + Math.max(0, footerHeight - naturalHeight) / 2, height: Math.min(naturalHeight, footerHeight) } : footerBox : void 0;
4399
+ const footerFit = attribution && natural && usable(footerBox) ? { ...natural, overflow: natural.overflow || naturalHeight > footerHeight + 0.01 } : void 0;
4400
+ const fitsPhoto = !hasPhoto || diameter <= footerHeight + 0.01 && (!attribution || usable(textArea));
4401
+ const overflow = !bodyFit || bodyFit.overflow || (attribution ? !footerFit || footerFit.overflow : false) || !fitsPhoto;
4402
+ const score = (body.requestedFontSize - (bodyFit?.fontSize ?? minimum) + footerRequested - size) / scale;
3351
4403
  if (!selected || !overflow && (selected.overflow || score < selected.score) || overflow && selected.overflow) {
3352
- selected = { bodyBox, footerBox, bodyFit, footerFit, score, overflow };
4404
+ selected = { bodyBox, footerBox, textBox, photoBox, bodyFit, footerFit, score, overflow, photoFits: fitsPhoto };
3353
4405
  }
3354
4406
  }
3355
4407
  if (selected) {
3356
4408
  body.box = selected.bodyBox;
3357
4409
  body.fit = selected.bodyFit;
3358
- attribution.box = selected.footerBox;
3359
- attribution.fit = selected.footerFit;
4410
+ if (attribution) {
4411
+ attribution.box = selected.textBox ?? selected.footerBox;
4412
+ attribution.fit = selected.footerFit;
4413
+ }
4414
+ if (selected.photoBox) photo = { path: photoPath, value: photoValue, box: selected.photoBox, shape: imageShape("circle", selected.photoBox) };
4415
+ photoFits = selected.photoFits;
3360
4416
  }
3361
4417
  }
4418
+ if (hasPhoto && !photo) photoFits = false;
3362
4419
  for (const part of parts) {
3363
4420
  const area = part.box;
3364
4421
  if (!part.fit) {
@@ -3370,17 +4427,20 @@ function layoutQuote(value, box, options = {}) {
3370
4427
  report("part-outside-cell", part.path, [part.role], `Quote ${part.role} extends outside its cell; increase the cell size or change the arrangement.`);
3371
4428
  }
3372
4429
  }
3373
- if (body?.fit && attribution?.fit && body.box.y + body.fit.lines.length * body.fit.lineHeight > attribution.box.y + 0.01 && attribution.box.y + attribution.fit.lines.length * attribution.fit.lineHeight > body.box.y + 0.01) {
4430
+ if (hasPhoto && !photoFits) report("photo-fit", photoPath, ["footer"], "Quote photo does not fit beside the attribution at the readability floor; increase the cell size, shorten the text or remove the photo.");
4431
+ if (body?.fit && attribution?.fit && body.box.y + heightOf(body.fit) > attribution.box.y + 0.01 && attribution.box.y + attribution.fit.lines.length * attribution.fit.lineHeight > body.box.y + 0.01) {
3374
4432
  report("part-overlap", path, ["body", "footer"], "Quote body and footer line boxes overlap; do not accept this layout without more space.");
4433
+ } else if (body?.fit && photo && body.box.y + heightOf(body.fit) > photo.box.y + 0.01) {
4434
+ report("part-overlap", path, ["body", "footer"], "Quote body and photo overlap; do not accept this layout without more space.");
3375
4435
  }
3376
4436
  if (diagnostics.length && options.overflow === "error") throw new OPFCompositionError(diagnostics);
3377
- return { algorithm: "quote-flow-v1", textMeasurement: options.textMeasurement ? "provided" : "estimated", parts, diagnostics, overflow: diagnostics.length > 0 };
4437
+ return { algorithm: "quote-flow-v1", textMeasurement: options.textMeasurement ? "provided" : "estimated", parts, ...photo ? { photo } : {}, diagnostics, overflow: diagnostics.length > 0 };
3378
4438
  }
3379
4439
  function layoutMetric(value, box, options = {}) {
3380
4440
  const scalar = typeof value === "string" || typeof value === "number";
3381
4441
  const metric = scalar ? { value } : value;
3382
4442
  const isValue = (input) => typeof input === "string" || typeof input === "number" && Number.isFinite(input);
3383
- if (!metric || Array.isArray(metric) || !isValue(metric.value) || [metric.label, metric.description, metric.unit].some((field) => field !== void 0 && typeof field !== "string") || metric.delta !== void 0 && !isValue(metric.delta) || metric.trend !== void 0 && !["up", "down", "flat"].includes(metric.trend)) {
4443
+ if (!metric || Array.isArray(metric) || !isValue(metric.value) || [metric.label, metric.description, metric.unit].some((field) => field !== void 0 && typeof field !== "string") || metric.delta !== void 0 && !isValue(metric.delta) || metric.trend !== void 0 && !["up", "down", "flat"].includes(metric.trend) || metric.sentiment !== void 0 && !["positive", "negative", "neutral"].includes(metric.sentiment)) {
3384
4444
  throw new TypeError("Metric content requires a finite numeric or string value and schema-valid display metadata.");
3385
4445
  }
3386
4446
  const scale = options.scale ?? 1, minimum = snapFontSizeUp((options.minFontSize ?? 16) * scale);
@@ -3398,7 +4458,7 @@ function layoutMetric(value, box, options = {}) {
3398
4458
  if (sourceValue === void 0) continue;
3399
4459
  const text2 = String(sourceValue), path = scalar ? sourcePath : `${sourcePath}.${role}`;
3400
4460
  const nominal = role === "value" ? Math.min(76 * scale, box.height * 0.28) : (role === "description" ? 20 : role === "trend" ? 18 : 23) * scale;
3401
- const requestedStyle = { fontFamily: (role === "value" ? options.fonts?.heading : options.fonts?.body) ?? "sans-serif", fontWeight: role === "value" ? 800 : role === "description" ? 400 : 500, italic: false, path };
4461
+ const requestedStyle = { fontFamily: (role === "value" ? options.fontFamilies?.heading : options.fontFamilies?.body) ?? "sans-serif", fontWeight: role === "value" ? 800 : role === "description" ? 400 : 500, italic: false, path };
3402
4462
  const part = {
3403
4463
  role,
3404
4464
  path,
@@ -3544,24 +4604,28 @@ function layoutMetric(value, box, options = {}) {
3544
4604
  }
3545
4605
  }
3546
4606
  if (diagnostics.length && options.overflow === "error") throw new OPFCompositionError(diagnostics);
3547
- return { algorithm: "metric-flow-v1", alignment, textMeasurement: options.textMeasurement ? "provided" : "estimated", arrangement: selected.arrangement, attempts, parts, diagnostics, overflow: diagnostics.length > 0 };
4607
+ return { algorithm: "metric-flow-v1", alignment, textMeasurement: options.textMeasurement ? "provided" : "estimated", arrangement: selected.arrangement, ...metric.sentiment === void 0 ? {} : { sentiment: metric.sentiment }, attempts, parts, diagnostics, overflow: diagnostics.length > 0 };
3548
4608
  }
4609
+ var TIMELINE_STATUS_VALUES = ["done", "current", "planned"];
4610
+ var TIMELINE_RING_RATIO = 1.6;
3549
4611
  function layoutTimeline(value, box, options = {}) {
3550
4612
  const shorthand = Array.isArray(value), timeline = shorthand ? { events: value } : value;
3551
4613
  if (!timeline || !Array.isArray(timeline.events) || !timeline.events.length || [timeline.name, timeline.description].some((field) => field !== void 0 && typeof field !== "string") || timeline.events.some((event) => !event || typeof event.what !== "string" || [event.when, event.description].some((field) => field !== void 0 && typeof field !== "string"))) {
3552
4614
  throw new TypeError("Timeline content requires ordered events with string labels and optional string metadata.");
3553
4615
  }
4616
+ if (timeline.events.some((event) => event.status !== void 0 && !TIMELINE_STATUS_VALUES.includes(event.status))) throw new TypeError("Timeline event status must be 'done', 'current' or 'planned'.");
3554
4617
  const scale = options.scale ?? 1, minimum = snapFontSizeUp((options.minFontSize ?? 16) * scale), padding = (options.textRasterPadding ?? 1) * scale;
3555
4618
  if (![box.x, box.y, box.width, box.height, scale, minimum, padding].every(Number.isFinite) || box.width <= 0 || box.height <= 0 || scale <= 0 || minimum <= 0 || padding < 0) throw new RangeError("Timeline dimensions, scale and minimum must be positive, with finite nonnegative raster padding.");
3556
4619
  if (options.overflow !== void 0 && !["warn", "error"].includes(options.overflow)) throw new RangeError("Invalid timeline overflow policy.");
3557
4620
  const outlines = options.textMeasurement?.outlineBounds !== void 0, rtl = options.direction === "rtl";
3558
4621
  if (outlines && typeof options.textMeasurement?.outlineBounds !== "function") throw new TypeError("Text outline provider must be a function.");
3559
4622
  const path = options.path ?? "timeline", eventPath = (index) => shorthand ? `${path}.${index}` : `${path}.events.${index}`;
3560
- const fonts = resolveFontFamilies(options.fonts), source = [];
4623
+ const fonts = resolveFontFamilies(options.fontFamilies), source = [];
3561
4624
  const add = (role, text2, partPath, size, weight, eventIndex) => {
3562
4625
  if (text2 === void 0) return;
3563
- const requestedStyle = { fontFamily: fonts.body, fontWeight: weight, italic: false, path: partPath };
3564
- source.push({ role, eventIndex, path: partPath, text: text2, sources: [{ path: partPath, start: 0, end: text2.length }], box: { ...box }, alignment: "center", requestedFontSize: gridFontSize(size * scale, minimum), minFontSize: minimum, requestedStyle, style: resolveTextStyle({ ...requestedStyle }, options.textMeasurement) });
4626
+ const status = eventIndex === void 0 ? void 0 : timeline.events[eventIndex].status;
4627
+ const requestedStyle = { fontFamily: fonts.body, fontWeight: status === "current" && role === "what" ? 700 : weight, italic: false, path: partPath };
4628
+ source.push({ role, eventIndex, ...status ? { status } : {}, path: partPath, text: text2, sources: [{ path: partPath, start: 0, end: text2.length }], box: { ...box }, alignment: "center", requestedFontSize: gridFontSize(size * scale, minimum), minFontSize: minimum, requestedStyle, style: resolveTextStyle({ ...requestedStyle }, options.textMeasurement) });
3565
4629
  };
3566
4630
  add("name", timeline.name, `${path}.name`, 24, 700);
3567
4631
  add("description", timeline.description, `${path}.description`, 18, 400);
@@ -3631,12 +4695,18 @@ function layoutTimeline(value, box, options = {}) {
3631
4695
  y += placed.box.height + 8 * scale;
3632
4696
  }
3633
4697
  const available = box.y + box.height - y, count = events.length, radius = Math.min(9 * scale, box.width / Math.max(2, count) / 5, Math.max(scale, available) * 0.04);
4698
+ const statusOf = (index) => timeline.events[index].status, ringRadius = radius * TIMELINE_RING_RATIO, strokeWidth = Math.min(2 * scale, radius / 2);
4699
+ const hasRing = timeline.events.some((event) => event.status === "current");
4700
+ const marker = (index, x, y2) => {
4701
+ const status = statusOf(index);
4702
+ return { path: eventPath(index), eventIndex: index, x, y: y2, radius, ...status ? { status } : {}, ...status === "current" ? { ring: { radius: ringRadius } } : {}, ...status === "current" || status === "planned" ? { strokeWidth } : {} };
4703
+ };
3634
4704
  if (arrangement === "alternating") {
3635
4705
  const width = box.width / Math.max(2, count), step = (box.width - width) / Math.max(1, count - 1), start = count === 1 ? box.x + box.width / 2 : box.x + width / 2;
3636
4706
  const lineY = y + Math.max(scale, available) * 0.46;
3637
4707
  events.forEach((fields2, index) => {
3638
4708
  const x = start + (rtl ? count - 1 - index : index) * step, top = index % 2 === 0 ? y : lineY + 24 * scale, bottom = index % 2 === 0 ? lineY - 24 * scale : box.y + box.height;
3639
- markers.push({ path: eventPath(index), eventIndex: index, x, y: lineY, radius });
4709
+ markers.push(marker(index, x, lineY));
3640
4710
  let cursor = top;
3641
4711
  for (const part of fields2) {
3642
4712
  const placed = place(part, x - width / 2, cursor, width, "center");
@@ -3645,7 +4715,8 @@ function layoutTimeline(value, box, options = {}) {
3645
4715
  }
3646
4716
  });
3647
4717
  } else {
3648
- const x = rtl ? box.x + box.width - radius : box.x + radius, textX = rtl ? box.x : box.x + 24 * scale, width = box.width - 24 * scale;
4718
+ const lead = hasRing ? ringRadius + strokeWidth / 2 : radius, gap = 24 * scale + (lead - radius);
4719
+ const x = rtl ? box.x + box.width - lead : box.x + lead, textX = rtl ? box.x : box.x + gap, width = box.width - gap;
3649
4720
  events.forEach((fields2, index) => {
3650
4721
  const top = y;
3651
4722
  let first2;
@@ -3654,13 +4725,16 @@ function layoutTimeline(value, box, options = {}) {
3654
4725
  first2 ??= placed;
3655
4726
  y += placed.box.height;
3656
4727
  }
3657
- markers.push({ path: eventPath(index), eventIndex: index, x, y: top + Math.min(first2?.box.height ?? 2 * radius, 2 * radius) / 2, radius });
4728
+ markers.push(marker(index, x, top + Math.min(first2?.box.height ?? 2 * radius, 2 * radius) / 2));
3658
4729
  y += 16 * scale;
3659
4730
  });
3660
4731
  }
3661
- for (const marker of markers) if (marker.x - marker.radius < box.x - 0.01 || marker.y - marker.radius < box.y - 0.01 || marker.x + marker.radius > box.x + box.width + 0.01 || marker.y + marker.radius > box.y + box.height + 0.01) {
3662
- diagnostics.push({ code: "text-overflow", reason: "event-space", path: marker.path, message: "Timeline marker has no usable space; increase the cell or paginate events." });
3663
- score2 += 1;
4732
+ for (const marker2 of markers) {
4733
+ const extent = (marker2.ring?.radius ?? marker2.radius) + (marker2.strokeWidth ?? 0) / 2;
4734
+ if (marker2.x - extent < box.x - 0.01 || marker2.y - extent < box.y - 0.01 || marker2.x + extent > box.x + box.width + 0.01 || marker2.y + extent > box.y + box.height + 0.01) {
4735
+ diagnostics.push({ code: "text-overflow", reason: "event-space", path: marker2.path, message: "Timeline marker has no usable space; increase the cell or paginate events." });
4736
+ score2 += 1;
4737
+ }
3664
4738
  }
3665
4739
  const first = markers[0], last = markers.at(-1), connector = rtl ? { x1: Math.min(first.x, last.x), y1: first.y, x2: Math.max(first.x, last.x), y2: last.y } : { x1: first.x, y1: first.y, x2: last.x, y2: last.y };
3666
4740
  const candidate = { arrangement, parts, markers, connector, diagnostics, score: score2 };
@@ -3771,7 +4845,7 @@ function layoutCode(value, box, options = {}) {
3771
4845
  const path = options.path ?? "code", inner = { x: box.x + 18, y: box.y + 18, width: box.width - 36, height: box.height - 36 };
3772
4846
  const parts = [], diagnostics = [];
3773
4847
  const add = (role, text2, partPath, generated = false) => {
3774
- const requestedStyle = { fontFamily: options.fonts?.code ?? "monospace", fontWeight: role === "body" ? 400 : 700, italic: false, path: partPath };
4848
+ const requestedStyle = { fontFamily: options.fontFamilies?.code ?? "monospace", fontWeight: role === "body" ? 400 : 700, italic: false, path: partPath };
3775
4849
  const part = {
3776
4850
  role,
3777
4851
  path: partPath,
@@ -3857,7 +4931,8 @@ function richTextLayouter(input, box, requestedSize, options, minimum = 0) {
3857
4931
  if (typeof run?.text !== "string" || run.fontSize !== void 0 && (!Number.isFinite(run.fontSize) || run.fontSize <= 0)) throw new RangeError("Rich text runs need text and a positive finite font size.");
3858
4932
  const start = offset;
3859
4933
  offset += run.text.length;
3860
- const style = resolveTextStyle({ ...options.style, fontFamily: run.fontFamily ?? options.style.fontFamily, fontWeight: run.bold === void 0 ? options.style.fontWeight : run.bold ? 700 : 400, italic: run.italic ?? options.style.italic, path: options.style.path ? `${options.style.path}.${runIndex}` : void 0 }, options.textMeasurement);
4934
+ const resolvedStyle = resolveTextStyle({ ...options.style, fontFamily: run.fontFamily ?? (run.code === true ? options.codeFontFamily ?? "monospace" : options.style.fontFamily), fontWeight: run.bold === void 0 ? options.style.fontWeight : run.bold ? 700 : 400, italic: run.italic ?? options.style.italic, path: options.style.path ? `${options.style.path}.${runIndex}` : void 0 }, options.textMeasurement);
4935
+ const style = typeof run.lang === "string" && run.lang ? { ...resolvedStyle, lang: run.lang } : resolvedStyle;
3861
4936
  const marker = options.citationMarker && options.style.path && run.text ? options.citationMarker(`${options.style.path}.${runIndex}`) : void 0;
3862
4937
  return { run, runIndex, start, end: offset, style, ...marker ? { marker } : {} };
3863
4938
  });
@@ -3974,15 +5049,15 @@ var PICTURE_BULLET_SCALE = 0.65;
3974
5049
  function fitList(input, box, requestedSize = 25, minFontSize = 16, options = { style: { fontFamily: "sans-serif", fontWeight: 400 } }) {
3975
5050
  if (!Array.isArray(input) || ![box.width, box.height, requestedSize, minFontSize].every((value) => Number.isFinite(value) && value > 0)) throw new RangeError("List content, dimensions and font sizes must be valid.");
3976
5051
  const source = input.map((value, index) => {
3977
- const object = typeof value === "object" && !Array.isArray(value) ? value : void 0;
3978
- const text2 = object ? object.text : value, description = object?.description, level = object?.level ?? 0;
5052
+ const object2 = typeof value === "object" && !Array.isArray(value) ? value : void 0;
5053
+ const text2 = object2 ? object2.text : value, description = object2?.description, level = object2?.level ?? 0;
3979
5054
  if (!Number.isInteger(level) || level < 0) throw new RangeError("List levels must be nonnegative integers.");
3980
5055
  const runs = (value2) => typeof value2 === "string" ? [value2] : value2;
3981
5056
  if (!Array.isArray(runs(text2)) || description !== void 0 && !Array.isArray(runs(description))) throw new TypeError("List text and descriptions must be strings or text runs.");
3982
5057
  const base = options.style.path ? `${options.style.path}.${index}` : void 0;
3983
5058
  const plain = (value2) => typeof value2 === "string" ? value2 : value2.map((run) => typeof run === "string" ? run : run.text).join("");
3984
5059
  const direction = options.direction === "rtl" ? paragraphDirection(plain(text2), "rtl") : void 0;
3985
- return { index, level, direction, value: text2, descriptionValue: description, textPath: base ? base + (object ? ".text" : "") : void 0, descriptionPath: base ? base + ".description" : void 0, runs: runs(text2), descriptionRuns: description === void 0 ? void 0 : runs(description) };
5060
+ return { index, level, direction, value: text2, descriptionValue: description, textPath: base ? base + (object2 ? ".text" : "") : void 0, descriptionPath: base ? base + ".description" : void 0, runs: runs(text2), descriptionRuns: description === void 0 ? void 0 : runs(description) };
3986
5061
  });
3987
5062
  const numbers = options.numbering === void 0 ? void 0 : listNumbers(input, options.numbering);
3988
5063
  const markerStyleFor = (item) => {
@@ -4079,13 +5154,13 @@ function layoutTable(value, box, options = {}) {
4079
5154
  const cellMinimum = (cell) => Array.isArray(cell.value) ? richMinimum(cell.value, requested, minimum) : minimum;
4080
5155
  const fitCell = (cell, height, min) => {
4081
5156
  const textBox = { width: Math.max(scale, cell.width), height: Math.max(scale, height) };
4082
- return Array.isArray(cell.value) ? fitRichText(cell.value, textBox, requested, min, { style: cell.textStyle, textMeasurement: options.textMeasurement, uniformLineHeight: true, direction: options.direction }) : fitText(flatten(cell.value), textBox, requested, min, textWidthMeasurer(resolveTextStyle(cell.textStyle, options.textMeasurement), options.textMeasurement), options.direction);
5157
+ return Array.isArray(cell.value) ? fitRichText(cell.value, textBox, requested, min, { style: cell.textStyle, ...options.codeFontFamily ? { codeFontFamily: options.codeFontFamily } : {}, textMeasurement: options.textMeasurement, uniformLineHeight: true, direction: options.direction }) : fitText(flatten(cell.value), textBox, requested, min, textWidthMeasurer(resolveTextStyle(cell.textStyle, options.textMeasurement), options.textMeasurement), options.direction);
4083
5158
  };
4084
5159
  const textHeight = (fit) => "height" in fit ? fit.height : fit.lines.length * fit.lineHeight;
4085
5160
  const required = (cell, natural2) => {
4086
5161
  const floor = cellMinimum(cell), size = gridFontSize(natural2 ? Math.max(requested, floor) : floor, floor);
4087
5162
  const textBox = { width: Math.max(scale, cell.width), height: scale };
4088
- const fit = Array.isArray(cell.value) ? richTextLayouter(cell.value, textBox, requested, { style: cell.textStyle, textMeasurement: options.textMeasurement, uniformLineHeight: true }, minimum)(size) : fitText(flatten(cell.value), textBox, size, size, textWidthMeasurer(resolveTextStyle(cell.textStyle, options.textMeasurement), options.textMeasurement));
5163
+ const fit = Array.isArray(cell.value) ? richTextLayouter(cell.value, textBox, requested, { style: cell.textStyle, ...options.codeFontFamily ? { codeFontFamily: options.codeFontFamily } : {}, textMeasurement: options.textMeasurement, uniformLineHeight: true }, minimum)(size) : fitText(flatten(cell.value), textBox, size, size, textWidthMeasurer(resolveTextStyle(cell.textStyle, options.textMeasurement), options.textMeasurement));
4089
5164
  return textHeight(fit) + (cell.padding.top + cell.padding.bottom) * scale;
4090
5165
  };
4091
5166
  const natural = Array(grid.rowCount).fill(0), needed = Array(grid.rowCount).fill(0);
@@ -4106,7 +5181,7 @@ function layoutTable(value, box, options = {}) {
4106
5181
  const ys = [box.y];
4107
5182
  for (const height of heights) ys.push(ys.at(-1) + height);
4108
5183
  let overflow = false;
4109
- const rows2 = heights.map((height, r) => ({ box: { x: box.x, y: ys[r], width: box.width, height }, cells: [] }));
5184
+ const rows3 = heights.map((height, r) => ({ box: { x: box.x, y: ys[r], width: box.width, height }, cells: [] }));
4110
5185
  for (const cell of cells) {
4111
5186
  const cellBox = { x: box.x + (options.direction === "rtl" ? columnCount - cell.column - cell.colSpan : cell.column) * cellWidth, y: ys[cell.row], width: cell.colSpan * cellWidth, height: ys[cell.row + cell.rowSpan] - ys[cell.row] };
4112
5187
  const available = cellBox.height - (cell.padding.top + cell.padding.bottom) * scale;
@@ -4114,12 +5189,12 @@ function layoutTable(value, box, options = {}) {
4114
5189
  const offset = cell.style.verticalAlign === "bottom" ? Math.max(0, available - height) : cell.style.verticalAlign === "middle" ? Math.max(0, (available - height) / 2) : 0;
4115
5190
  const textBox = { x: cellBox.x + cell.padding.left * scale, y: cellBox.y + cell.padding.top * scale + offset, width: Math.max(scale, cell.width), height: Math.max(scale, available - offset) };
4116
5191
  overflow ||= cell.width <= 0 || available <= 0 || fit.overflow;
4117
- rows2[cell.row].cells.push({ value: cell.value, input: cell.input, path: cell.valuePath, sourcePath: cell.path, style: cell.style, row: cell.row, column: cell.column, rowSpan: cell.rowSpan, colSpan: cell.colSpan, header: cell.header, rich: Array.isArray(cell.value), box: cellBox, textBox, textStyle: resolveTextStyle(cell.textStyle, options.textMeasurement), fit, ...fit.directions ? { direction: fit.directions[0] } : {} });
5192
+ rows3[cell.row].cells.push({ value: cell.value, input: cell.input, path: cell.valuePath, sourcePath: cell.path, style: cell.style, row: cell.row, column: cell.column, rowSpan: cell.rowSpan, colSpan: cell.colSpan, header: cell.header, rich: Array.isArray(cell.value), box: cellBox, textBox, textStyle: resolveTextStyle(cell.textStyle, options.textMeasurement), fit, ...fit.directions ? { direction: fit.directions[0] } : {} });
4118
5193
  }
4119
- return { rows: rows2, columnCount, height: sum(heights), overflow };
5194
+ return { rows: rows3, columnCount, height: sum(heights), overflow };
4120
5195
  }
4121
5196
  function tableOverflows(value, box, scale, settings, options, path) {
4122
- return box.width <= 0 || box.height <= 0 || layoutTable(value, box, { scale, minFontSize: settings.minFontSize, fontFamily: options.fonts?.body, textMeasurement: options.textMeasurement, path, presentation: options.presentation }).overflow;
5197
+ return box.width <= 0 || box.height <= 0 || layoutTable(value, box, { scale, minFontSize: settings.minFontSize, fontFamily: options.fontFamilies?.body, ...options.fontFamilies?.code ? { codeFontFamily: options.fontFamilies.code } : {}, textMeasurement: options.textMeasurement, path, presentation: options.presentation }).overflow;
4123
5198
  }
4124
5199
  function flatten(value) {
4125
5200
  if (value == null) return "";
@@ -4135,10 +5210,10 @@ function regionParts(key) {
4135
5210
  };
4136
5211
  const parts = key.split(":");
4137
5212
  if (parts.length === 2) {
4138
- const r = span(parts[0], rows), c = span(parts[1], columns);
5213
+ const r = span(parts[0], rows2), c = span(parts[1], columns);
4139
5214
  if (r && c) return [r, c];
4140
5215
  } else if (parts.length === 1) {
4141
- const r = span(key, rows), c = span(key, columns);
5216
+ const r = span(key, rows2), c = span(key, columns);
4142
5217
  if (r) return [r, [0, 1, 2]];
4143
5218
  if (c) return [[0, 1, 2], c];
4144
5219
  }
@@ -4187,7 +5262,8 @@ function composeSlide(input, options = {}) {
4187
5262
  const scale = Math.min(width, height) / 720;
4188
5263
  const deckDirection = options.direction ?? resolveSlideDirection(options.presentation, options.slideIndex);
4189
5264
  const rtl = deckDirection === "rtl", textDirection = rtl ? "rtl" : void 0;
4190
- const hasCards = record5(slide.design).contentBox ?? options.contentBox ?? false;
5265
+ const hints = resolveDesignHints({ slide, layout, presentation: options.presentation, slideIndex: options.slideIndex, deck: { titleAlignment: options.titleAlignment, contentAlignment: options.contentAlignment, contentBox: options.contentBox } });
5266
+ const hasCards = hints.contentBox ?? false;
4191
5267
  const composition = { ...record5(layout.composition), ...record5(slide.composition) };
4192
5268
  assertComposition(composition);
4193
5269
  const padding = (composition.padding ?? 0.08) * Math.min(width, height);
@@ -4196,15 +5272,13 @@ function composeSlide(input, options = {}) {
4196
5272
  const rasterPadding = (options.textRasterPadding ?? 1) * scale;
4197
5273
  if (!Number.isFinite(rasterPadding) || rasterPadding < 0) throw new RangeError("Text raster padding must be finite and nonnegative.");
4198
5274
  let coverGroup = false;
4199
- const alignmentFor = (field) => (field === "title" || coverGroup && (field === "tag" || field === "subtitle") && record5(slide.design).contentAlignment === void 0 ? record5(slide.design).titleAlignment ?? options.titleAlignment : record5(slide.design).contentAlignment ?? options.contentAlignment) ?? "left";
5275
+ const alignmentFor = (field) => (field === "title" || coverGroup && (field === "tag" || field === "subtitle") && hints.sources.contentAlignment !== "slide" ? hints.titleAlignment : hints.contentAlignment) ?? "left";
4200
5276
  const styleFor = (field, path2) => resolveTextStyle({
4201
- fontFamily: (field === "title" ? options.fonts?.heading : field === "code" ? options.fonts?.code : field === "tag" ? options.fonts?.accent ?? options.fonts?.body : options.fonts?.body) ?? (field === "code" ? "monospace" : "sans-serif"),
5277
+ fontFamily: (field === "title" ? options.fontFamilies?.heading : field === "code" ? options.fontFamilies?.code : field === "tag" ? options.fontFamilies?.accent ?? options.fontFamilies?.body : options.fontFamilies?.body) ?? (field === "code" ? "monospace" : "sans-serif"),
4202
5278
  fontWeight: field === "title" ? 700 : 400,
4203
5279
  path: path2
4204
5280
  }, options.textMeasurement);
4205
- const slideDesign = record5(slide.design), deckDesign = record5(record5(options.presentation).design);
4206
- const designHint = (field) => slideDesign[field] !== void 0 ? { value: slideDesign[field], path: `slides.${options.slideIndex ?? 0}.design.${field}` } : deckDesign[field] !== void 0 ? { value: deckDesign[field], path: `design.${field}` } : void 0;
4207
- const listBullet = designHint("listBullet");
5281
+ const listBullet = hints.listBullet !== void 0 ? { value: hints.listBullet, path: hints.paths.listBullet } : void 0;
4208
5282
  const bulletImage = listBullet?.value === "image" ? (() => {
4209
5283
  const resolved = resolveLogo(options.presentation, slide, { slot: "icon", onDark: options.darkBackground, slideIndex: options.slideIndex });
4210
5284
  return resolved ? { source: resolved.source, path: resolved.path } : void 0;
@@ -4212,9 +5286,9 @@ function composeSlide(input, options = {}) {
4212
5286
  const widthFor = (field, path2) => textWidthMeasurer(styleFor(field, path2), options.textMeasurement);
4213
5287
  const citations = slideCitations(slide, options.slideIndex ?? 0, options.presentation);
4214
5288
  const citationMarker = citations ? (runPath) => citations.markers.get(runPath) : void 0;
4215
- const richOptions = (style) => ({ style, textMeasurement: options.textMeasurement, ...citationMarker ? { citationMarker } : {}, ...rtl ? { direction: "rtl" } : {} });
5289
+ const richOptions = (style) => ({ style, textMeasurement: options.textMeasurement, ...options.fontFamilies?.code ? { codeFontFamily: options.fontFamilies.code } : {}, ...citationMarker ? { citationMarker } : {}, ...rtl ? { direction: "rtl" } : {} });
4216
5290
  const fitPlacedText = (field, value, text2, box, size, minimum, path2, explicitAlignment) => {
4217
- const style = styleFor(field, path2), rich = field === "text" && Array.isArray(value);
5291
+ const style = styleFor(field, path2), rich = (field === "text" || headings.has(field)) && Array.isArray(value);
4218
5292
  if (!options.textMeasurement?.outlineBounds) return rich ? fitRichText(value, box, size, minimum, richOptions(style)) : fitText(text2, box, size, minimum, textWidthMeasurer(style, options.textMeasurement), textDirection);
4219
5293
  const alignment = explicitAlignment ?? alignmentFor(field);
4220
5294
  const richLayout = rich ? richTextLayouter(value, box, size, richOptions(style), minimum) : void 0;
@@ -4267,13 +5341,37 @@ function composeSlide(input, options = {}) {
4267
5341
  const path = `slides.${options.slideIndex ?? 0}`;
4268
5342
  const annotationFit = (value, box, requestedSize, minFontSize, fitPath, alignment) => fitPlacedText("text", value, annotationText(value), box, requestedSize, minFontSize, fitPath, alignment);
4269
5343
  const annotationOptions = { scale, minFontSize: minSize, fit: annotationFit, textStyle: (fitPath) => styleFor("text", fitPath) };
4270
- const slideImageDiagnostics = [];
4271
- const slideImage = resolveSlideImage(slide, layout, options.presentation, width, height, path, padding, scale, slideImageDiagnostics, rtl);
5344
+ const imageDiagnostics = [];
5345
+ const mirrorSide = (side) => !rtl ? side : side === "left" ? "right" : side === "right" ? "left" : side;
5346
+ const backgroundImage = resolveBackgroundImage(slide, options.presentation, options.themeBackground, width, height, path, mirrorSide, imageDiagnostics);
5347
+ const regions = Object.keys(slide).filter((key) => regionParts(key)).sort();
5348
+ const assets = record5(options.presentation).assets;
5349
+ const imageContext = (placement) => ({ fit: hints.imageFit, scale, mirrorSide, diagnostics: imageDiagnostics, assets, ...placement ? { placement } : {} });
4272
5350
  const area = { left: 0, top: 0, right: width, bottom: height };
4273
- if (slideImage?.position === "left") area.left = slideImage.region.width;
4274
- else if (slideImage?.position === "right") area.right = slideImage.region.x;
4275
- else if (slideImage?.position === "top") area.top = slideImage.region.height;
4276
- else if (slideImage?.position === "bottom") area.bottom = slideImage.region.y;
5351
+ const imagePlaceholders = (Array.isArray(layout.placeholders) ? layout.placeholders : []).flatMap((placeholder, index) => record5(placeholder).type === "image" ? [{ placeholder: record5(placeholder), index }] : []);
5352
+ const topImages = regions.length ? [] : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => !Array.isArray(record5(block).blocks) && record5(block).image !== void 0 ? [{ host: record5(block), hostPath: `${path}.blocks.${index}`, block: index }] : []) : slide.image !== void 0 ? [{ host: { type: "image", image: slide.image }, hostPath: path }] : [];
5353
+ const placed = [], usedEdges = /* @__PURE__ */ new Set();
5354
+ topImages.forEach((node, order) => {
5355
+ const slot = imagePlaceholders[order];
5356
+ const own2 = node.block !== void 0 && node.host.placement !== void 0 ? record5(node.host.placement) : void 0;
5357
+ const value = own2 ?? (slot?.placeholder.placement !== void 0 ? record5(slot.placeholder.placement) : void 0);
5358
+ if (!value || !IMAGE_EDGES.includes(value.edge)) return;
5359
+ const edge = mirrorSide(value.edge);
5360
+ if (usedEdges.has(edge)) return;
5361
+ usedEdges.add(edge);
5362
+ const size = finite(value.size, 0.1, 0.9) ?? PLACEMENT_BAND;
5363
+ const across = edge === "left" || edge === "right" ? area.right - area.left : area.bottom - area.top;
5364
+ const band = Math.max(0, Math.min(across, round2((edge === "left" || edge === "right" ? width : height) * size)));
5365
+ const region = edge === "left" ? { x: area.left, y: area.top, width: band, height: area.bottom - area.top } : edge === "right" ? { x: round2(area.right - band), y: area.top, width: band, height: area.bottom - area.top } : edge === "top" ? { x: area.left, y: area.top, width: area.right - area.left, height: band } : { x: area.left, y: round2(area.bottom - band), width: area.right - area.left, height: band };
5366
+ if (edge === "left") area.left += band;
5367
+ else if (edge === "right") area.right = region.x;
5368
+ else if (edge === "top") area.top += band;
5369
+ else area.bottom = region.y;
5370
+ const placement = { edge, size, inset: value.inset === true, path: own2 ? `${node.hostPath}.placement` : `layout.placeholders.${slot.index}.placement` };
5371
+ placed.push({ ...node, placement, region, slot: order });
5372
+ });
5373
+ const placedBlocks = new Set(placed.flatMap((entry) => entry.block !== void 0 ? [entry.block] : []));
5374
+ const placedRoot = placed.some((entry) => entry.block === void 0);
4277
5375
  const items = [], diagnostics = [];
4278
5376
  const measuredFurniture = layoutFurniture(slide, options);
4279
5377
  const furniture = measuredFurniture.configured || measuredFurniture.diagnostics.length ? measuredFurniture : void 0;
@@ -4287,12 +5385,13 @@ function composeSlide(input, options = {}) {
4287
5385
  bodyBottom = footnotes.box.y - gap * 0.5;
4288
5386
  }
4289
5387
  const layoutPlaceholders = Array.isArray(layout.placeholders) ? layout.placeholders : [];
4290
- const headingOnlyLayout = COVER_LAYOUT_IDS.has(String(layout.id ?? "")) || layoutPlaceholders.length > 0 && layoutPlaceholders.every((placeholder) => headings.has(placeholder.type ?? ""));
4291
- const regions = Object.keys(slide).filter((key) => regionParts(key)).sort();
5388
+ const hasLayoutRecord = options.layout !== void 0 && options.layout !== null && typeof options.layout === "object";
5389
+ const headingOnlyLayout = layoutPlaceholders.length > 0 && layoutPlaceholders.every((placeholder) => headings.has(placeholder.type ?? "") || placeholder.type === "image" && typeof placeholder.placement === "object" && placeholder.placement !== null);
4292
5390
  const emptyPayload = (value) => value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
4293
5391
  const emptyHost = (host) => emptyPayload(host.blocks) && fields.every((field) => emptyPayload(host[field]));
4294
- const hasBodyPayload = regions.some((key) => !emptyHost(record5(slide[key]))) || !emptyPayload(slide.blocks) || fields.some((field) => !emptyPayload(slide[field]));
4295
- const isCover = !hasBodyPayload && (headingOnlyLayout || !layout.id && !layoutPlaceholders.some((placeholder) => !headings.has(placeholder.type ?? "")));
5392
+ const flowBlocks = Array.isArray(slide.blocks) ? slide.blocks.filter((_, index) => !placedBlocks.has(index)) : slide.blocks;
5393
+ const hasBodyPayload = regions.some((key) => !emptyHost(record5(slide[key]))) || !emptyPayload(flowBlocks) || fields.some((field) => !(placedRoot && field === "image") && !emptyPayload(slide[field]));
5394
+ const isCover = !hasBodyPayload && (headingOnlyLayout || !hasLayoutRecord);
4296
5395
  coverGroup = isCover;
4297
5396
  let logo;
4298
5397
  if (isCover) {
@@ -4307,12 +5406,12 @@ function composeSlide(input, options = {}) {
4307
5406
  let y = logo ? logo.box.y + logo.box.height + gap : headingTop;
4308
5407
  const headingItems = [];
4309
5408
  for (const field of ["tag", "title", "subtitle"]) {
4310
- if (!slide[field]) continue;
5409
+ if (!slide[field] || Array.isArray(slide[field]) && !annotationText(slide[field])) continue;
4311
5410
  const requested = (field === "title" ? 54 : field === "tag" ? 16 : 25) * scale;
4312
5411
  const maxHeight = Math.max(height * (field === "title" ? 0.26 : field === "subtitle" ? 0.12 : 0.045), minSize * 1.22 + 2 * rasterPadding);
4313
5412
  const box = { x: area.left + padding, y, width: area.right - area.left - padding * 2, height: maxHeight };
4314
- const text2 = fitPlacedText(field, slide[field], String(slide[field]), box, requested, minSize, `${path}.${field}`);
4315
- box.height = Math.min(maxHeight, Math.max(text2.lines.length * text2.lineHeight, text2.placement?.height ?? 0));
5413
+ const text2 = fitPlacedText(field, slide[field], annotationText(slide[field]), box, requested, minSize, `${path}.${field}`);
5414
+ box.height = Math.min(maxHeight, Math.max("richLines" in text2 ? text2.height : text2.lines.length * text2.lineHeight, text2.placement?.height ?? 0));
4316
5415
  if (furniture && box.y + box.height > bodyBottom + 0.01) diagnostics.push({ code: "text-overflow", path: `${path}.${field}`, message: "Repeated furniture leaves too little room for this heading. Change the header/footer or slide design." });
4317
5416
  const item = { path: `${path}.${field}`, field, type: "text", value: slide[field], payload: { text: slide[field] }, box, text: text2, textStyle: styleFor(field, `${path}.${field}`), composition, alignment: alignmentFor(field) };
4318
5417
  headingItems.push(item);
@@ -4330,6 +5429,30 @@ function composeSlide(input, options = {}) {
4330
5429
  y = last.box.y + last.box.height + gap;
4331
5430
  } else y += gap * 0.5;
4332
5431
  }
5432
+ for (const entry of placed) {
5433
+ const { host, hostPath, region, placement } = entry;
5434
+ let frameArea = placement.inset ? { x: region.x + padding, y: region.y + padding, width: Math.max(scale, region.width - 2 * padding), height: Math.max(scale, region.height - 2 * padding) } : { ...region };
5435
+ const caption = host.caption !== void 0 && entry.block !== void 0 ? layoutCaption(host.caption, roundBox(frameArea), `${hostPath}.caption`, annotationOptions) : void 0;
5436
+ if (caption) {
5437
+ frameArea = caption.mediaBox;
5438
+ diagnostics.push(...caption.diagnostics);
5439
+ }
5440
+ const image = composeImage(host, hostPath, region, frameArea, imageContext(placement));
5441
+ const type = host.type ?? "image";
5442
+ items.push({
5443
+ path: `${hostPath}.image`,
5444
+ field: "image",
5445
+ type,
5446
+ value: host.image,
5447
+ payload: imagePayload(host),
5448
+ box: { ...region },
5449
+ image,
5450
+ textStyle: styleFor("image", `${hostPath}.image`),
5451
+ composition,
5452
+ alignment: alignmentFor("image"),
5453
+ ...caption ? { caption } : {}
5454
+ });
5455
+ }
4333
5456
  const contentBox = { x: area.left + padding, y, width: area.right - area.left - padding * 2, height: Math.max(scale, bodyBottom - y) };
4334
5457
  const collect = (host, basePath, depth = 0, ancestors = []) => {
4335
5458
  if (Array.isArray(host.blocks)) {
@@ -4353,12 +5476,13 @@ function composeSlide(input, options = {}) {
4353
5476
  type: host.type ?? kind(field),
4354
5477
  value: fieldValue(field),
4355
5478
  path: `${basePath}.${field}`,
4356
- payload: { type: host.type ?? kind(field), [field]: fieldValue(field), ...host.numbering !== void 0 && (field === "items" || field === "bullets") ? { numbering: host.numbering } : {} },
5479
+ payload: field === "image" ? imagePayload(host) : { type: host.type ?? kind(field), [field]: fieldValue(field), ...host.numbering !== void 0 && (field === "items" || field === "bullets") ? { numbering: host.numbering } : {} },
5480
+ ...field === "image" ? { host, hostPath: basePath } : {},
4357
5481
  ...captioned.length === 1 && captioned[0] === field ? { caption: host.caption, captionPath: `${basePath}.caption` } : {}
4358
5482
  }));
4359
5483
  };
4360
5484
  const regionsInReadingOrder = visualReadingOrder(regions.map((key) => ({ key, box: regionBox(regionParts(key), contentBox, gap) }))).map((entry) => entry.key);
4361
- const pending = regions.length ? regionsInReadingOrder.flatMap((key) => collect(record5(slide[key]), `${path}.${key}`).map((item) => ({ ...item, region: regionParts(key) }))) : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => collect(record5(block), `${path}.blocks.${index}`)) : collect(slideImage?.replacesContent ? { ...slide, image: void 0 } : slide, path);
5485
+ const pending = regions.length ? regionsInReadingOrder.flatMap((key) => collect(record5(slide[key]), `${path}.${key}`).map((item) => ({ ...item, region: regionParts(key) }))) : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => placedBlocks.has(index) ? [] : collect(record5(block), `${path}.blocks.${index}`)) : collect(placedRoot ? { ...slide, image: void 0 } : slide, path);
4362
5486
  const groups = [], flows = [];
4363
5487
  const decisions = options.explain ? [] : void 0;
4364
5488
  const inheritedSettings = (parent, own2 = {}) => ({
@@ -4377,22 +5501,23 @@ function composeSlide(input, options = {}) {
4377
5501
  return acceptedBox({ x: frame.x + padding2, y: frame.y + padding2, width: frame.width - 2 * padding2, height: frame.height - 2 * padding2 });
4378
5502
  };
4379
5503
  const measureQuote = (node, box, settings) => layoutQuote(node.value, acceptedBox(box), {
4380
- fonts: options.fonts,
5504
+ fontFamilies: options.fontFamilies,
4381
5505
  textMeasurement: options.textMeasurement,
4382
5506
  scale,
4383
5507
  minFontSize: settings.minFontSize,
4384
5508
  path: node.path,
4385
- direction: textDirection
5509
+ direction: textDirection,
5510
+ ...citationMarker ? { citationMarker } : {}
4386
5511
  });
4387
5512
  const measureCode = (node, box, settings) => layoutCode(node.value, acceptedBox(box), {
4388
- fonts: options.fonts,
5513
+ fontFamilies: options.fontFamilies,
4389
5514
  textMeasurement: options.textMeasurement,
4390
5515
  scale,
4391
5516
  minFontSize: settings.minFontSize,
4392
5517
  path: node.path
4393
5518
  });
4394
5519
  const measureMetric = (node, box, settings) => layoutMetric(node.value, acceptedBox(box), {
4395
- fonts: options.fonts,
5520
+ fontFamilies: options.fontFamilies,
4396
5521
  textMeasurement: options.textMeasurement,
4397
5522
  scale,
4398
5523
  minFontSize: settings.minFontSize,
@@ -4402,7 +5527,7 @@ function composeSlide(input, options = {}) {
4402
5527
  direction: textDirection
4403
5528
  });
4404
5529
  const measureTimeline = (node, box, settings) => layoutTimeline(node.value, acceptedBox(box), {
4405
- fonts: options.fonts,
5530
+ fontFamilies: options.fontFamilies,
4406
5531
  textMeasurement: options.textMeasurement,
4407
5532
  scale,
4408
5533
  minFontSize: settings.minFontSize,
@@ -4514,6 +5639,7 @@ function composeSlide(input, options = {}) {
4514
5639
  const timelineLayout = node.field === "timeline" ? measureTimeline(node, box, settings) : void 0;
4515
5640
  const internal = quoteLayout ?? codeLayout ?? metricLayout ?? timelineLayout, body = internal?.parts.find((part) => part.role === "body" || part.role === "value");
4516
5641
  const text2 = internal ? body?.fit : textValue !== void 0 ? fitContent(node.field, node.value, textValue, box, 25 * scale, snapFontSizeUp((settings.minFontSize ?? 16) * scale), node.path, node.payload.numbering) : void 0;
5642
+ const image = node.field === "image" ? composeImage(node.host ?? {}, node.hostPath ?? node.path, box, box, imageContext()) : void 0;
4517
5643
  items.push({
4518
5644
  path: node.path,
4519
5645
  field: node.field,
@@ -4521,6 +5647,7 @@ function composeSlide(input, options = {}) {
4521
5647
  value: node.value,
4522
5648
  payload: node.payload,
4523
5649
  box: internal ? acceptedBox(box) : box,
5650
+ ...image ? { image } : {},
4524
5651
  ...frameBox ? { frameBox } : {},
4525
5652
  text: text2,
4526
5653
  textStyle: body?.style ?? styleFor(node.field, node.path),
@@ -4538,19 +5665,18 @@ function composeSlide(input, options = {}) {
4538
5665
  });
4539
5666
  };
4540
5667
  const placeholders = Array.isArray(layout.placeholders) ? layout.placeholders.filter((p) => !headings.has(p.type)) : [];
4541
- if (slideImage?.replacesContent) {
4542
- const picture = placeholders.findIndex((p) => p.type === "picture");
4543
- if (picture >= 0) placeholders.splice(picture, 1);
5668
+ const placedSlots = new Set(placed.flatMap((entry) => imagePlaceholders[entry.slot] ? [imagePlaceholders[entry.slot].placeholder] : []));
5669
+ if (placedSlots.size) {
5670
+ for (let index = placeholders.length - 1; index >= 0; index--) if (placedSlots.has(placeholders[index])) placeholders.splice(index, 1);
4544
5671
  }
4545
5672
  const ownMode = record5(slide.composition).mode;
4546
- const direction = designHint("contentDirection")?.value;
4547
- const directionMode = direction === "vertical" ? "column" : direction === "horizontal" ? "row" : void 0;
4548
- const layoutDirectionMode = layout.slideLayoutDirection === "Vertical" ? "column" : layout.slideLayoutDirection === "Horizontal" ? "row" : "auto";
4549
- const chartHint = designHint("chartPrimary")?.value ?? (typeof layout.contentTypeChartPrimary === "string" ? layout.contentTypeChartPrimary.toLowerCase() : void 0);
5673
+ const direction = hints.contentDirection;
5674
+ const directionMode = direction === "vertical" ? "column" : direction === "horizontal" ? "row" : "auto";
5675
+ const chartHint = hints.chartPrimary;
4550
5676
  const chartSide = chartHint === "left" || chartHint === "right" || chartHint === "top" || chartHint === "bottom" ? chartHint : void 0;
4551
5677
  const chartIndex = pending.findIndex((node) => !node.children && node.field === "chart");
4552
5678
  const chartPrimary = chartSide !== void 0 && !ownMode && !regions.length && chartIndex >= 0 && pending.some((node) => node.children || node.field !== "chart") ? chartSide : void 0;
4553
- const rootSettings = chartPrimary ? { ...composition, mode: chartPrimary === "left" || chartPrimary === "right" ? "row" : "column", columns: void 0, weights: chartPrimary === "left" || chartPrimary === "top" ? [3, 2] : [2, 3] } : { ...composition, mode: composition.mode ?? directionMode ?? layoutDirectionMode };
5679
+ const rootSettings = chartPrimary ? { ...composition, mode: chartPrimary === "left" || chartPrimary === "right" ? "row" : "column", columns: void 0, weights: chartPrimary === "left" || chartPrimary === "top" ? [3, 2] : [2, 3] } : { ...composition, mode: composition.mode ?? directionMode };
4554
5680
  if (chartPrimary) {
4555
5681
  const primary = pending[chartIndex], rest = pending.filter((_, index) => index !== chartIndex);
4556
5682
  const container = { field: "blocks", type: "group", value: rest.map((node) => node.payload), path, payload: {}, children: rest, composition: {}, synthetic: true };
@@ -4594,8 +5720,8 @@ function composeSlide(input, options = {}) {
4594
5720
  unmeasuredPayloads: items.filter((item) => !headings.has(item.field) && !item.quoteLayout && !item.codeLayout && !item.metricLayout && !item.timelineLayout && !["text", "items", "bullets", "table"].includes(item.field)).map((item) => item.path)
4595
5721
  } : void 0;
4596
5722
  if (failures.length) throw new OPFCompositionError(failures, explanation);
4597
- diagnostics.push(...slideImageDiagnostics, ...numberingDiagnostics);
4598
- return { width, height, contentBox, items, groups, flows, diagnostics, composition, ...furniture ? { furniture } : {}, ...slideImage ? { slideImage } : {}, ...logo ? { logo } : {}, ...rtl ? { direction: "rtl" } : {}, ...footnotes ? { footnotes } : {}, ...explanation ? { explanation } : {} };
5723
+ diagnostics.push(...imageDiagnostics, ...numberingDiagnostics);
5724
+ return { width, height, contentBox, items, groups, flows, diagnostics, composition, design: hints, ...furniture ? { furniture } : {}, ...backgroundImage ? { backgroundImage } : {}, ...logo ? { logo } : {}, ...rtl ? { direction: "rtl" } : {}, ...footnotes ? { footnotes } : {}, ...explanation ? { explanation } : {} };
4599
5725
  }
4600
5726
  function resolveCanvasDimensions(input) {
4601
5727
  const presets = {
@@ -4604,6 +5730,9 @@ function resolveCanvasDimensions(input) {
4604
5730
  standard: [10, 7.5],
4605
5731
  "4:3": [10, 7.5],
4606
5732
  "16:10": [10, 6.25],
5733
+ "1:1": [7.5, 7.5],
5734
+ "4:5": [7.5, 9.375],
5735
+ "9:16": [7.5, 40 / 3],
4607
5736
  letter: [11, 8.5],
4608
5737
  a4: [11.69, 8.27]
4609
5738
  };
@@ -4615,4 +5744,4 @@ function resolveCanvasDimensions(input) {
4615
5744
  return { width, height };
4616
5745
  }
4617
5746
 
4618
- export { CAPTIONABLE_FIELDS, CAPTION_FONT_RATIO, CAPTION_MAX_RATIO, CHART_SERIES_MIN_DIFFERENCE, CHART_SERIES_MIN_LIGHTNESS_STEP, CITATION_MARKER_RAISE, CITATION_MARKER_SCALE, DEFAULT_CHART_LABEL_SEPARATOR, DEFAULT_FONT_SCHEME, DEFAULT_FURNITURE_DATE_FORMAT, DEFAULT_SLIDE_NUMBER_FORMAT, DEFAULT_VARIABLE_DATE_FORMAT, FONT_SIZE_GRID_PER_PX, FOOTNOTE_MAX_RATIO, MAX_COMPOSITION_DEPTH, MAX_NUMBERING_LEVELS, MAX_NUMBERING_VALUE, MAX_ROMAN_VALUE, NUMBERING_STYLES, NUMBERING_SUFFIXES, OPFCompositionError, OPFVariableError, PICTURE_BULLET_SCALE, VARIABLE_KINDS, annotationText, bareIdPattern, captionSettings, catalogIds, chartColorForFill, chartLabelText, chartNumber, chartNumberFixesByCell, chartOptionSupport, chartOptionTarget, chartPaletteForFill, citationMarkerText, coerceVariableValue, collectCitations, colorContrast, composeSlide, datasetDiagnostics, deprecatedCatalogIds, excelNumberFormat, fitList, fitRichText, fitText, formatChartLabelNumber, formatChartLabelPercent, formatDataNumber, formatFurnitureDate, formatListNumber, formatSlideNumber, formatVariableNumber, hasContentVariables, inlineChartData, inlineDatasets, inlineTableData, instantiateForValidation, intrinsicImageSize, isDatasetRef, isRecord, isTemplate, isXYChartType, layoutCaption, layoutCode, layoutFootnotes, layoutFurniture, layoutMetric, layoutQuote, layoutTable, layoutTimeline, listNumbers, listVariables, measureText, measureTextOutline, normalizeHexColor, numberFormatError, numberFormatFromExcel, numberingAtLevel, numberingFindings, numberingStyleDraws, paragraphDirection, paragraphDirectionAt, pathFor, physicalAlignment, placeTextLines, promotedRegionKeys, readingRows, referencesSlide, resolveCanvasDimensions, resolveChartData, resolveChartOptions, resolveColorRef, resolveFontFamilies, resolveFontSchemeReference, resolveLogo, resolveNumbering, resolveScriptFonts, resolveSlideDirection, resolveSocialProfile, resolveTableData, resolveTextStyle, resolveVariables, scriptFontRole, sliceNumberedItems, slideCitations, slideImageShape, snapFontSizeDown, snapFontSizeUp, suggestChartNumberFix, tableCellDisplayValue, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, unusedDatasets, variableDeclarations, visitContentPayloads, visualReadingOrder, walkCitationRuns, wrapText };
5747
+ export { CAPTIONABLE_FIELDS, CAPTION_FONT_RATIO, CAPTION_MAX_RATIO, CHART_HIGHLIGHT_MUTED_MIN_CONTRAST, CHART_HIGHLIGHT_MUTED_MIX, CHART_SERIES_MIN_DIFFERENCE, CHART_SERIES_MIN_LIGHTNESS_STEP, CHART_TYPES, CITATION_MARKER_RAISE, CITATION_MARKER_SCALE, CODE_HIGHLIGHT_LANGUAGES, CODE_HIGHLIGHT_MAX_LENGTH, CODE_PANEL_BACKGROUND, CODE_PANEL_FOREGROUND, CODE_SYNTAX_MIN_CONTRAST, DARK_BACKGROUND_LUMINANCE, DEFAULT_CHART_LABEL_SEPARATOR, DEFAULT_FURNITURE_DATE_FORMAT, DEFAULT_SLIDE_NUMBER_FORMAT, DEFAULT_VARIABLE_DATE_FORMAT, DESIGN_HINT_KEYS, ENGINE_DEFAULT_CHART_TYPES, ENGINE_DEFAULT_COLOR_SCHEME, ENGINE_DEFAULT_FONT_SCHEME, ENGINE_DEFAULT_THEME, FONT_SIZE_GRID_PER_PX, FOOTNOTE_MAX_RATIO, LANGUAGES, LAYOUT_BODY_KINDS, MAX_COMPOSITION_DEPTH, MAX_NUMBERING_LEVELS, MAX_NUMBERING_VALUE, MAX_ROMAN_VALUE, METRIC_TREND_MIN_CONTRAST, METRIC_TREND_SHAPES, NUMBERING_STYLES, NUMBERING_SUFFIXES, OPFCompositionError, OPFVariableError, PATTERN_PRESETS, PATTERN_PRESET_ALIASES, PATTERN_TILE_SIZE, PICTURE_BULLET_SCALE, SOCIAL_PLATFORMS, SURFACE_ALT_MIN_CONTRAST, SURFACE_ALT_MIX, TIMELINE_OUTLINE_MIN_CONTRAST, TIMELINE_STATUSES, TIMELINE_TEXT_MIN_CONTRAST, VARIABLE_KINDS, annotationText, captionSettings, chartColorForFill, chartHighlightColors, chartHighlightMarks, chartLabelText, chartNumber, chartNumberFixesByCell, chartOptionSupport, chartOptionTarget, chartPaletteForFill, citationMarkerText, codeHighlightBands, codeHighlightColors, codeHighlightLines, codeHighlightSlice, codeLineNumbers, codeLineRuns, codeSyntaxPalette, codeSyntaxPaletteForScheme, coerceVariableValue, collectCitations, colorContrast, composeSlide, datasetDiagnostics, defaultSlideBackground, fitImage, fitList, fitRichText, fitText, formatChartLabelNumber, formatChartLabelPercent, formatDataNumber, formatFurnitureDate, formatListNumber, formatSlideNumber, formatVariableNumber, fromExcelNumberFormat, hasContentVariables, imageBackground, imageShape, inlineChartData, inlineDatasets, inlineTableData, instantiateForValidation, intrinsicImageAspect, intrinsicImageSize, isDarkColor, isDatasetRef, isRecord, isTemplate, isXYChartType, layoutCaption, layoutCode, layoutContent, layoutFootnotes, layoutFurniture, layoutMetric, layoutQuote, layoutTable, layoutTimeline, layoutWatermark, listBuiltinVariables, listNumbers, listVariables, measureText, measureTextOutline, metricTrendColor, metricTrendMark, metricTrendPoints, normalizeHexColor, normalizeLanguageFamily, numberFormatError, numberingAtLevel, numberingFindings, numberingStyleDraws, paragraphDirection, paragraphDirectionAt, pathFor, patternBitmap, patternRuns, physicalAlignment, placeTextLines, promotedRegionKeys, readingRows, referencesSlide, resolveCanvasDimensions, resolveChartData, resolveChartOptions, resolveCodeLanguage, resolveColorRef, resolveColorRoles, resolveDesignHints, resolveDesignRecords, resolveFontFamilies, resolveFontScheme, resolveLogo, resolveNumbering, resolvePatternPreset, resolveScriptFonts, resolveSlideDirection, resolveSocialProfile, resolveTableData, resolveTextStyle, resolveVariables, scriptFontRole, sliceNumberedItems, slideCitations, snapFontSizeDown, snapFontSizeUp, suggestChartNumberFix, surfaceAltColor, tableCellDisplayValue, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, timelineMarkerShapes, timelineTextColor, toExcelNumberFormat, tokenizeCode, unusedDatasets, variableDeclarations, visitContentPayloads, visualReadingOrder, walkCitationRuns, wrapText };