@openpresentation/opf 0.18.3 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (763) hide show
  1. package/README.md +18 -17
  2. package/dist/browser.js +18 -20
  3. package/dist/{catalog-refs-BSfGELpt.d.ts → catalog-refs-CSHevLn1.d.ts} +1 -1
  4. package/dist/{chunk-KA3ZPFVT.js → chunk-65GDO6TJ.js} +96 -40
  5. package/dist/{chunk-JCOSZTOI.js → chunk-A6COIVTD.js} +7 -2
  6. package/dist/{chunk-ZCFSDSUX.js → chunk-AK4UXIRP.js} +1 -1
  7. package/dist/{chunk-WXSPETQ6.js → chunk-F7PLNWHQ.js} +25 -3
  8. package/dist/{chunk-MSFE2HUK.js → chunk-FGUQHD37.js} +16 -13
  9. package/dist/{chunk-GVOLSWAJ.js → chunk-GRN3U5JT.js} +5 -5
  10. package/dist/{chunk-TRELE6I6.js → chunk-HBFRNOP4.js} +1 -1
  11. package/dist/{chunk-R7KIASS4.js → chunk-LRPSMQ62.js} +1 -1
  12. package/dist/chunk-OOT5AY4V.js +16 -0
  13. package/dist/{chunk-FO3WGS4R.js → chunk-OVBGGGKO.js} +25 -16
  14. package/dist/{chunk-2PEWUUBR.js → chunk-R5T4H4ZV.js} +350 -314
  15. package/dist/{chunk-L5YACLWK.js → chunk-SEUJIS55.js} +2 -2
  16. package/dist/{chunk-ECP7QPGK.js → chunk-SIQWYDFF.js} +6 -6
  17. package/dist/chunk-UJSAR6GF.js +181 -0
  18. package/dist/{chunk-IM337HP5.js → chunk-V3RGXJJS.js} +4 -5
  19. package/dist/{chunk-WHHLGDCQ.js → chunk-WHKFIFN7.js} +1 -1
  20. package/dist/{chunk-K5EG3UMS.js → chunk-XWMKAJSS.js} +46 -17
  21. package/dist/{chunk-PNINP5IF.js → chunk-YAHPQRVU.js} +1 -1
  22. package/dist/{chunk-MBU42S5Y.js → chunk-ZPCKGGI6.js} +1152 -273
  23. package/dist/{composition-C-OoqvAr.d.ts → composition-DilAHoWM.d.ts} +385 -99
  24. package/dist/composition.d.ts +2 -2
  25. package/dist/composition.js +1 -2
  26. package/dist/conversion-NJQHH4QW.js +19 -0
  27. package/dist/{conversion-BxZbBd_0.d.ts → conversion-k9l5pQsq.d.ts} +11 -11
  28. package/dist/convert.d.ts +3 -3
  29. package/dist/convert.js +7 -9
  30. package/dist/data.d.ts +1 -1
  31. package/dist/data.js +2 -3
  32. package/dist/{deck-report-DiDf_Vew.d.ts → deck-report-D19fyuNu.d.ts} +3 -3
  33. package/dist/deck.d.ts +6 -6
  34. package/dist/deck.js +10 -12
  35. package/dist/diff.js +5 -7
  36. package/dist/docs.js +27 -21
  37. package/dist/examples.d.ts +1 -1
  38. package/dist/examples.js +23853 -20994
  39. package/dist/font-policy.js +1 -1
  40. package/dist/format.js +2 -2
  41. package/dist/index.d.ts +22 -21
  42. package/dist/index.js +24 -27
  43. package/dist/markdown.d.ts +4 -4
  44. package/dist/markdown.js +7 -9
  45. package/dist/node-engine.d.ts +26 -9
  46. package/dist/node-engine.js +23 -24
  47. package/dist/{pagination-BaUjDrTz.d.ts → pagination-BNj5UQn5.d.ts} +3 -3
  48. package/dist/pagination.d.ts +3 -3
  49. package/dist/pagination.js +4 -6
  50. package/dist/patch.js +4 -6
  51. package/dist/{presentation-81rNihF0.d.ts → presentation-B_e2Djga.d.ts} +35 -19
  52. package/dist/repo-readme.js +1 -1
  53. package/dist/schemas.d.ts +2 -18
  54. package/dist/schemas.js +1 -1
  55. package/dist/spec/README.md +12 -19
  56. package/dist/spec/reference/engine-vocabularies.json +1 -1
  57. package/dist/spec/reference/font-policy.json +25 -3
  58. package/dist/spec/schemas/catalog-index.schema.json +3 -3
  59. package/dist/spec/schemas/catalog-manifest.schema.json +1 -1
  60. package/dist/spec/schemas/chart-type.schema.json +2 -2
  61. package/dist/spec/schemas/language.schema.json +1 -1
  62. package/dist/spec/schemas/layout-preview-index.schema.json +25 -11
  63. package/dist/spec/schemas/layout.schema.json +193 -272
  64. package/dist/spec/schemas/opf.schema.json +63 -18
  65. package/dist/spec/schemas/social-platform.schema.json +1 -1
  66. package/dist/spec/schemas/theme.schema.json +60 -0
  67. package/dist/spec-files.d.ts +2 -2
  68. package/dist/spec-files.js +1 -1
  69. package/dist/types.d.ts +115 -40
  70. package/dist/{validation-types-PbGDrNUr.d.ts → validation-types-CWhPuYUt.d.ts} +2 -2
  71. package/dist/validator-Cse-AD32.d.ts +73 -0
  72. package/dist/validator.d.ts +6 -60
  73. package/dist/validator.js +3 -5
  74. package/dist/yaml.d.ts +4 -4
  75. package/dist/yaml.js +7 -9
  76. package/package.json +6 -9
  77. package/dist/catalog-schemas-CinPh5WA.d.ts +0 -12
  78. package/dist/catalog.d.ts +0 -91
  79. package/dist/catalog.js +0 -3
  80. package/dist/chunk-HXHOZ7AH.js +0 -4937
  81. package/dist/chunk-SPFV27O5.js +0 -210
  82. package/dist/chunk-TRDXRRQK.js +0 -17
  83. package/dist/chunk-WCG3THTD.js +0 -23712
  84. package/dist/conversion-4CLOEG6O.js +0 -21
  85. package/dist/spec/catalogs/audiences/academic.json +0 -24
  86. package/dist/spec/catalogs/audiences/all-hands.json +0 -25
  87. package/dist/spec/catalogs/audiences/board.json +0 -24
  88. package/dist/spec/catalogs/audiences/candidates.json +0 -23
  89. package/dist/spec/catalogs/audiences/customer.json +0 -25
  90. package/dist/spec/catalogs/audiences/engineering-team.json +0 -23
  91. package/dist/spec/catalogs/audiences/executive.json +0 -24
  92. package/dist/spec/catalogs/audiences/general-public.json +0 -25
  93. package/dist/spec/catalogs/audiences/index.json +0 -105
  94. package/dist/spec/catalogs/audiences/internal-team.json +0 -25
  95. package/dist/spec/catalogs/audiences/investor.json +0 -25
  96. package/dist/spec/catalogs/audiences/marketing.json +0 -25
  97. package/dist/spec/catalogs/audiences/media.json +0 -24
  98. package/dist/spec/catalogs/audiences/partner.json +0 -25
  99. package/dist/spec/catalogs/audiences/regulatory.json +0 -25
  100. package/dist/spec/catalogs/audiences/sales.json +0 -25
  101. package/dist/spec/catalogs/audiences/technical.json +0 -25
  102. package/dist/spec/catalogs/chart-types/100pct-stacked-area.json +0 -21
  103. package/dist/spec/catalogs/chart-types/100pct-stacked-bar.json +0 -22
  104. package/dist/spec/catalogs/chart-types/100pct-stacked-column.json +0 -22
  105. package/dist/spec/catalogs/chart-types/area.json +0 -20
  106. package/dist/spec/catalogs/chart-types/bar.json +0 -22
  107. package/dist/spec/catalogs/chart-types/box-and-whisker.json +0 -21
  108. package/dist/spec/catalogs/chart-types/column.json +0 -22
  109. package/dist/spec/catalogs/chart-types/combo.json +0 -37
  110. package/dist/spec/catalogs/chart-types/doughnut.json +0 -20
  111. package/dist/spec/catalogs/chart-types/filled-radar.json +0 -21
  112. package/dist/spec/catalogs/chart-types/funnel.json +0 -21
  113. package/dist/spec/catalogs/chart-types/histogram.json +0 -21
  114. package/dist/spec/catalogs/chart-types/index.json +0 -171
  115. package/dist/spec/catalogs/chart-types/line-with-markers.json +0 -21
  116. package/dist/spec/catalogs/chart-types/line.json +0 -20
  117. package/dist/spec/catalogs/chart-types/pareto.json +0 -22
  118. package/dist/spec/catalogs/chart-types/pie.json +0 -20
  119. package/dist/spec/catalogs/chart-types/radar-with-markers.json +0 -21
  120. package/dist/spec/catalogs/chart-types/radar.json +0 -21
  121. package/dist/spec/catalogs/chart-types/scatter.json +0 -21
  122. package/dist/spec/catalogs/chart-types/stacked-area.json +0 -21
  123. package/dist/spec/catalogs/chart-types/stacked-bar.json +0 -22
  124. package/dist/spec/catalogs/chart-types/stacked-column.json +0 -22
  125. package/dist/spec/catalogs/chart-types/stacked-line-with-markers.json +0 -22
  126. package/dist/spec/catalogs/chart-types/stacked-line.json +0 -21
  127. package/dist/spec/catalogs/chart-types/treemap.json +0 -21
  128. package/dist/spec/catalogs/chart-types/waterfall.json +0 -21
  129. package/dist/spec/catalogs/chart-types/world.json +0 -21
  130. package/dist/spec/catalogs/color-schemes/black-and-white.json +0 -26
  131. package/dist/spec/catalogs/color-schemes/bold-red.json +0 -26
  132. package/dist/spec/catalogs/color-schemes/boost.json +0 -26
  133. package/dist/spec/catalogs/color-schemes/burnt-orange.json +0 -26
  134. package/dist/spec/catalogs/color-schemes/cool-horizon.json +0 -26
  135. package/dist/spec/catalogs/color-schemes/corporate-blue.json +0 -26
  136. package/dist/spec/catalogs/color-schemes/deep-purple.json +0 -26
  137. package/dist/spec/catalogs/color-schemes/forest-green.json +0 -26
  138. package/dist/spec/catalogs/color-schemes/golden-yellow.json +0 -26
  139. package/dist/spec/catalogs/color-schemes/index.json +0 -79
  140. package/dist/spec/catalogs/color-schemes/luxury.json +0 -26
  141. package/dist/spec/catalogs/color-schemes/pastel-red.json +0 -26
  142. package/dist/spec/catalogs/color-schemes/slate-gray.json +0 -26
  143. package/dist/spec/catalogs/color-schemes/steel-blue.json +0 -26
  144. package/dist/spec/catalogs/color-schemes/vibes.json +0 -26
  145. package/dist/spec/catalogs/font-schemes/angsana-new.json +0 -15
  146. package/dist/spec/catalogs/font-schemes/aparajita.json +0 -16
  147. package/dist/spec/catalogs/font-schemes/aptos.json +0 -13
  148. package/dist/spec/catalogs/font-schemes/arabic-typesetting.json +0 -15
  149. package/dist/spec/catalogs/font-schemes/arial.json +0 -13
  150. package/dist/spec/catalogs/font-schemes/batang.json +0 -15
  151. package/dist/spec/catalogs/font-schemes/bookman.json +0 -13
  152. package/dist/spec/catalogs/font-schemes/calibri.json +0 -13
  153. package/dist/spec/catalogs/font-schemes/century-schoolbook.json +0 -13
  154. package/dist/spec/catalogs/font-schemes/consolas.json +0 -14
  155. package/dist/spec/catalogs/font-schemes/constantia.json +0 -13
  156. package/dist/spec/catalogs/font-schemes/courier-new.json +0 -14
  157. package/dist/spec/catalogs/font-schemes/daunpenh.json +0 -15
  158. package/dist/spec/catalogs/font-schemes/david.json +0 -15
  159. package/dist/spec/catalogs/font-schemes/dilleniaupc.json +0 -15
  160. package/dist/spec/catalogs/font-schemes/fangsong.json +0 -15
  161. package/dist/spec/catalogs/font-schemes/garamond.json +0 -13
  162. package/dist/spec/catalogs/font-schemes/gautami.json +0 -15
  163. package/dist/spec/catalogs/font-schemes/georgia.json +0 -13
  164. package/dist/spec/catalogs/font-schemes/gisha.json +0 -16
  165. package/dist/spec/catalogs/font-schemes/grandview.json +0 -13
  166. package/dist/spec/catalogs/font-schemes/gungsuh.json +0 -15
  167. package/dist/spec/catalogs/font-schemes/impact.json +0 -13
  168. package/dist/spec/catalogs/font-schemes/index.json +0 -454
  169. package/dist/spec/catalogs/font-schemes/kalinga.json +0 -15
  170. package/dist/spec/catalogs/font-schemes/kartika.json +0 -15
  171. package/dist/spec/catalogs/font-schemes/khmer-ui.json +0 -15
  172. package/dist/spec/catalogs/font-schemes/latha.json +0 -15
  173. package/dist/spec/catalogs/font-schemes/lucida-sans.json +0 -13
  174. package/dist/spec/catalogs/font-schemes/malgun-gothic.json +0 -15
  175. package/dist/spec/catalogs/font-schemes/mangal.json +0 -17
  176. package/dist/spec/catalogs/font-schemes/meiryo.json +0 -15
  177. package/dist/spec/catalogs/font-schemes/microsoft-jhenghei.json +0 -15
  178. package/dist/spec/catalogs/font-schemes/microsoft-yahei.json +0 -18
  179. package/dist/spec/catalogs/font-schemes/mingliu.json +0 -15
  180. package/dist/spec/catalogs/font-schemes/miriam.json +0 -15
  181. package/dist/spec/catalogs/font-schemes/montserrat.json +0 -13
  182. package/dist/spec/catalogs/font-schemes/ms-mincho.json +0 -15
  183. package/dist/spec/catalogs/font-schemes/nirmala-ui.json +0 -15
  184. package/dist/spec/catalogs/font-schemes/noto-naksh-arabic.json +0 -15
  185. package/dist/spec/catalogs/font-schemes/noto-nastaliq-urdu.json +0 -16
  186. package/dist/spec/catalogs/font-schemes/noto-sans-arabic.json +0 -17
  187. package/dist/spec/catalogs/font-schemes/noto-sans-armenian.json +0 -15
  188. package/dist/spec/catalogs/font-schemes/noto-sans-bengali.json +0 -16
  189. package/dist/spec/catalogs/font-schemes/noto-sans-devangari.json +0 -16
  190. package/dist/spec/catalogs/font-schemes/noto-sans-ethiopic.json +0 -15
  191. package/dist/spec/catalogs/font-schemes/noto-sans-georgian.json +0 -15
  192. package/dist/spec/catalogs/font-schemes/noto-sans-gujarati.json +0 -15
  193. package/dist/spec/catalogs/font-schemes/noto-sans-gurmukhi.json +0 -15
  194. package/dist/spec/catalogs/font-schemes/noto-sans-hebrew.json +0 -15
  195. package/dist/spec/catalogs/font-schemes/noto-sans-jp.json +0 -15
  196. package/dist/spec/catalogs/font-schemes/noto-sans-kannada.json +0 -15
  197. package/dist/spec/catalogs/font-schemes/noto-sans-khmer.json +0 -15
  198. package/dist/spec/catalogs/font-schemes/noto-sans-kr.json +0 -15
  199. package/dist/spec/catalogs/font-schemes/noto-sans-malayalam.json +0 -15
  200. package/dist/spec/catalogs/font-schemes/noto-sans-mongolian.json +0 -15
  201. package/dist/spec/catalogs/font-schemes/noto-sans-oriya.json +0 -15
  202. package/dist/spec/catalogs/font-schemes/noto-sans-sc.json +0 -18
  203. package/dist/spec/catalogs/font-schemes/noto-sans-tamil.json +0 -15
  204. package/dist/spec/catalogs/font-schemes/noto-sans-tc.json +0 -15
  205. package/dist/spec/catalogs/font-schemes/noto-sans-telugu.json +0 -15
  206. package/dist/spec/catalogs/font-schemes/noto-sans-thai.json +0 -15
  207. package/dist/spec/catalogs/font-schemes/noto-sans.json +0 -18
  208. package/dist/spec/catalogs/font-schemes/nyala.json +0 -15
  209. package/dist/spec/catalogs/font-schemes/open-sans.json +0 -13
  210. package/dist/spec/catalogs/font-schemes/pmingliu.json +0 -15
  211. package/dist/spec/catalogs/font-schemes/poppins.json +0 -13
  212. package/dist/spec/catalogs/font-schemes/pt-serif.json +0 -13
  213. package/dist/spec/catalogs/font-schemes/raavi.json +0 -15
  214. package/dist/spec/catalogs/font-schemes/raleway.json +0 -13
  215. package/dist/spec/catalogs/font-schemes/roboto.json +0 -13
  216. package/dist/spec/catalogs/font-schemes/rockwell.json +0 -13
  217. package/dist/spec/catalogs/font-schemes/sakkal-majalla.json +0 -17
  218. package/dist/spec/catalogs/font-schemes/seaford.json +0 -13
  219. package/dist/spec/catalogs/font-schemes/segoe-ui-light.json +0 -13
  220. package/dist/spec/catalogs/font-schemes/segoe-ui.json +0 -13
  221. package/dist/spec/catalogs/font-schemes/shonar-bangla.json +0 -16
  222. package/dist/spec/catalogs/font-schemes/shruti.json +0 -15
  223. package/dist/spec/catalogs/font-schemes/simsun.json +0 -15
  224. package/dist/spec/catalogs/font-schemes/skeena.json +0 -13
  225. package/dist/spec/catalogs/font-schemes/sylfaen.json +0 -16
  226. package/dist/spec/catalogs/font-schemes/tahoma.json +0 -13
  227. package/dist/spec/catalogs/font-schemes/tenorite.json +0 -13
  228. package/dist/spec/catalogs/font-schemes/times-new-roman.json +0 -13
  229. package/dist/spec/catalogs/font-schemes/traditional-arabic.json +0 -17
  230. package/dist/spec/catalogs/font-schemes/trebuchet-ms.json +0 -13
  231. package/dist/spec/catalogs/font-schemes/tunga.json +0 -15
  232. package/dist/spec/catalogs/font-schemes/verdana.json +0 -13
  233. package/dist/spec/catalogs/font-schemes/vrinda.json +0 -15
  234. package/dist/spec/catalogs/font-schemes/yu-gothic.json +0 -15
  235. package/dist/spec/catalogs/languages/afrikaans.json +0 -12
  236. package/dist/spec/catalogs/languages/albanian.json +0 -12
  237. package/dist/spec/catalogs/languages/amharic.json +0 -12
  238. package/dist/spec/catalogs/languages/arabic.json +0 -12
  239. package/dist/spec/catalogs/languages/armenian.json +0 -12
  240. package/dist/spec/catalogs/languages/aymara.json +0 -12
  241. package/dist/spec/catalogs/languages/azerbaijani.json +0 -12
  242. package/dist/spec/catalogs/languages/bengali.json +0 -12
  243. package/dist/spec/catalogs/languages/berber-latin.json +0 -12
  244. package/dist/spec/catalogs/languages/bosnian-latin.json +0 -12
  245. package/dist/spec/catalogs/languages/bulgarian.json +0 -12
  246. package/dist/spec/catalogs/languages/catalan.json +0 -12
  247. package/dist/spec/catalogs/languages/cebuano.json +0 -12
  248. package/dist/spec/catalogs/languages/chinese-simplified.json +0 -12
  249. package/dist/spec/catalogs/languages/chinese-traditional.json +0 -12
  250. package/dist/spec/catalogs/languages/chittagonian.json +0 -12
  251. package/dist/spec/catalogs/languages/croatian.json +0 -12
  252. package/dist/spec/catalogs/languages/czech.json +0 -12
  253. package/dist/spec/catalogs/languages/danish.json +0 -12
  254. package/dist/spec/catalogs/languages/dutch.json +0 -12
  255. package/dist/spec/catalogs/languages/english-au.json +0 -12
  256. package/dist/spec/catalogs/languages/english-ca.json +0 -12
  257. package/dist/spec/catalogs/languages/english-gb.json +0 -12
  258. package/dist/spec/catalogs/languages/english-in.json +0 -12
  259. package/dist/spec/catalogs/languages/english-us.json +0 -12
  260. package/dist/spec/catalogs/languages/english.json +0 -12
  261. package/dist/spec/catalogs/languages/estonian.json +0 -12
  262. package/dist/spec/catalogs/languages/filipino.json +0 -12
  263. package/dist/spec/catalogs/languages/finnish.json +0 -12
  264. package/dist/spec/catalogs/languages/french.json +0 -12
  265. package/dist/spec/catalogs/languages/fulfulde.json +0 -12
  266. package/dist/spec/catalogs/languages/galician.json +0 -12
  267. package/dist/spec/catalogs/languages/georgian.json +0 -12
  268. package/dist/spec/catalogs/languages/german.json +0 -12
  269. package/dist/spec/catalogs/languages/greek.json +0 -12
  270. package/dist/spec/catalogs/languages/gujarati.json +0 -12
  271. package/dist/spec/catalogs/languages/hausa.json +0 -12
  272. package/dist/spec/catalogs/languages/hebrew.json +0 -12
  273. package/dist/spec/catalogs/languages/hindi.json +0 -12
  274. package/dist/spec/catalogs/languages/hungarian.json +0 -12
  275. package/dist/spec/catalogs/languages/igbo.json +0 -12
  276. package/dist/spec/catalogs/languages/index.json +0 -567
  277. package/dist/spec/catalogs/languages/indonesian.json +0 -12
  278. package/dist/spec/catalogs/languages/italian.json +0 -12
  279. package/dist/spec/catalogs/languages/japanese.json +0 -12
  280. package/dist/spec/catalogs/languages/kannada.json +0 -12
  281. package/dist/spec/catalogs/languages/kazakh.json +0 -12
  282. package/dist/spec/catalogs/languages/khmer.json +0 -12
  283. package/dist/spec/catalogs/languages/kinyarwanda.json +0 -12
  284. package/dist/spec/catalogs/languages/korean.json +0 -12
  285. package/dist/spec/catalogs/languages/kurmanji.json +0 -12
  286. package/dist/spec/catalogs/languages/latvian.json +0 -12
  287. package/dist/spec/catalogs/languages/lithuanian.json +0 -12
  288. package/dist/spec/catalogs/languages/macedonian.json +0 -12
  289. package/dist/spec/catalogs/languages/malagasy.json +0 -12
  290. package/dist/spec/catalogs/languages/malay.json +0 -12
  291. package/dist/spec/catalogs/languages/malayalam.json +0 -12
  292. package/dist/spec/catalogs/languages/maori.json +0 -12
  293. package/dist/spec/catalogs/languages/marathi.json +0 -12
  294. package/dist/spec/catalogs/languages/mongolian.json +0 -12
  295. package/dist/spec/catalogs/languages/nepali.json +0 -12
  296. package/dist/spec/catalogs/languages/norwegian.json +0 -12
  297. package/dist/spec/catalogs/languages/odia.json +0 -12
  298. package/dist/spec/catalogs/languages/oromo.json +0 -12
  299. package/dist/spec/catalogs/languages/pashto.json +0 -12
  300. package/dist/spec/catalogs/languages/persian.json +0 -12
  301. package/dist/spec/catalogs/languages/polish.json +0 -12
  302. package/dist/spec/catalogs/languages/portuguese.json +0 -12
  303. package/dist/spec/catalogs/languages/punjabi-gurmukhi.json +0 -12
  304. package/dist/spec/catalogs/languages/punjabi-shahmukhi.json +0 -12
  305. package/dist/spec/catalogs/languages/romanian.json +0 -12
  306. package/dist/spec/catalogs/languages/russian.json +0 -12
  307. package/dist/spec/catalogs/languages/serbian-cyrillic.json +0 -12
  308. package/dist/spec/catalogs/languages/serbian-latin.json +0 -12
  309. package/dist/spec/catalogs/languages/shona.json +0 -12
  310. package/dist/spec/catalogs/languages/slovak.json +0 -12
  311. package/dist/spec/catalogs/languages/slovenian.json +0 -12
  312. package/dist/spec/catalogs/languages/somali.json +0 -12
  313. package/dist/spec/catalogs/languages/spanish.json +0 -12
  314. package/dist/spec/catalogs/languages/swahili.json +0 -12
  315. package/dist/spec/catalogs/languages/swedish.json +0 -12
  316. package/dist/spec/catalogs/languages/tagalog.json +0 -12
  317. package/dist/spec/catalogs/languages/tajik.json +0 -12
  318. package/dist/spec/catalogs/languages/tamil.json +0 -12
  319. package/dist/spec/catalogs/languages/telugu.json +0 -12
  320. package/dist/spec/catalogs/languages/thai.json +0 -12
  321. package/dist/spec/catalogs/languages/turkish.json +0 -12
  322. package/dist/spec/catalogs/languages/ukrainian.json +0 -12
  323. package/dist/spec/catalogs/languages/urdu.json +0 -12
  324. package/dist/spec/catalogs/languages/uzbek-latin.json +0 -12
  325. package/dist/spec/catalogs/languages/vietnamese-quoc-ngu.json +0 -12
  326. package/dist/spec/catalogs/languages/xhosa.json +0 -12
  327. package/dist/spec/catalogs/languages/yoruba.json +0 -12
  328. package/dist/spec/catalogs/languages/zulu.json +0 -12
  329. package/dist/spec/catalogs/layouts/action-plan.json +0 -29
  330. package/dist/spec/catalogs/layouts/agenda.json +0 -28
  331. package/dist/spec/catalogs/layouts/appendix-index.json +0 -30
  332. package/dist/spec/catalogs/layouts/architecture-stack.json +0 -29
  333. package/dist/spec/catalogs/layouts/assumptions-dependencies.json +0 -29
  334. package/dist/spec/catalogs/layouts/before-after.json +0 -35
  335. package/dist/spec/catalogs/layouts/benchmark-target-table.json +0 -29
  336. package/dist/spec/catalogs/layouts/blank.json +0 -16
  337. package/dist/spec/catalogs/layouts/bullet-list.json +0 -32
  338. package/dist/spec/catalogs/layouts/business-model-canvas.json +0 -94
  339. package/dist/spec/catalogs/layouts/capability-map.json +0 -80
  340. package/dist/spec/catalogs/layouts/case-study.json +0 -29
  341. package/dist/spec/catalogs/layouts/chapter-recap.json +0 -28
  342. package/dist/spec/catalogs/layouts/chart-1x-title-center.json +0 -30
  343. package/dist/spec/catalogs/layouts/chart-1x.json +0 -34
  344. package/dist/spec/catalogs/layouts/chart-2x-title-center.json +0 -36
  345. package/dist/spec/catalogs/layouts/chart-2x-vertical-title-left.json +0 -37
  346. package/dist/spec/catalogs/layouts/chart-2x.json +0 -65
  347. package/dist/spec/catalogs/layouts/chart-3x-bottom-vertical-title-left.json +0 -52
  348. package/dist/spec/catalogs/layouts/chart-3x-left-title-center.json +0 -51
  349. package/dist/spec/catalogs/layouts/chart-3x-left.json +0 -46
  350. package/dist/spec/catalogs/layouts/chart-3x-right-title-center.json +0 -51
  351. package/dist/spec/catalogs/layouts/chart-3x-right.json +0 -46
  352. package/dist/spec/catalogs/layouts/chart-3x-title-center.json +0 -39
  353. package/dist/spec/catalogs/layouts/chart-3x-top-vertical-title-left.json +0 -52
  354. package/dist/spec/catalogs/layouts/chart-3x.json +0 -83
  355. package/dist/spec/catalogs/layouts/circular-lifecycle.json +0 -29
  356. package/dist/spec/catalogs/layouts/code-1x.json +0 -29
  357. package/dist/spec/catalogs/layouts/comparison.json +0 -35
  358. package/dist/spec/catalogs/layouts/competitive-landscape.json +0 -30
  359. package/dist/spec/catalogs/layouts/customer-journey.json +0 -30
  360. package/dist/spec/catalogs/layouts/customer-logos.json +0 -32
  361. package/dist/spec/catalogs/layouts/dashboard.json +0 -67
  362. package/dist/spec/catalogs/layouts/data-visualization.json +0 -39
  363. package/dist/spec/catalogs/layouts/decision-tree.json +0 -30
  364. package/dist/spec/catalogs/layouts/detailed-data-table.json +0 -35
  365. package/dist/spec/catalogs/layouts/ecosystem-map.json +0 -30
  366. package/dist/spec/catalogs/layouts/executive-decision.json +0 -32
  367. package/dist/spec/catalogs/layouts/executive-summary.json +0 -32
  368. package/dist/spec/catalogs/layouts/extract/canonical.json +0 -575
  369. package/dist/spec/catalogs/layouts/faq.json +0 -29
  370. package/dist/spec/catalogs/layouts/feature-comparison-matrix.json +0 -29
  371. package/dist/spec/catalogs/layouts/forecast-scenario.json +0 -39
  372. package/dist/spec/catalogs/layouts/funnel-pyramid.json +0 -32
  373. package/dist/spec/catalogs/layouts/gantt-project-plan.json +0 -32
  374. package/dist/spec/catalogs/layouts/geographic-map.json +0 -30
  375. package/dist/spec/catalogs/layouts/heatmap-cohort.json +0 -32
  376. package/dist/spec/catalogs/layouts/hub-and-spoke.json +0 -29
  377. package/dist/spec/catalogs/layouts/icon-grid.json +0 -30
  378. package/dist/spec/catalogs/layouts/image-1x-crop-title-center.json +0 -32
  379. package/dist/spec/catalogs/layouts/image-1x-crop-title-left.json +0 -32
  380. package/dist/spec/catalogs/layouts/image-1x-crop.json +0 -27
  381. package/dist/spec/catalogs/layouts/image-1x-fit-title-center.json +0 -32
  382. package/dist/spec/catalogs/layouts/image-1x.json +0 -32
  383. package/dist/spec/catalogs/layouts/image-2x-crop-title-center.json +0 -38
  384. package/dist/spec/catalogs/layouts/image-2x-crop-vertical-title-left.json +0 -39
  385. package/dist/spec/catalogs/layouts/image-2x-crop-vertical.json +0 -34
  386. package/dist/spec/catalogs/layouts/image-2x-crop.json +0 -33
  387. package/dist/spec/catalogs/layouts/image-2x-fit-title-center.json +0 -38
  388. package/dist/spec/catalogs/layouts/image-2x-fit-vertical-title-left.json +0 -39
  389. package/dist/spec/catalogs/layouts/image-2x-fit-vertical.json +0 -34
  390. package/dist/spec/catalogs/layouts/image-2x.json +0 -63
  391. package/dist/spec/catalogs/layouts/image-3x-crop-title-center.json +0 -41
  392. package/dist/spec/catalogs/layouts/image-3x-crop-vertical-title-left.json +0 -42
  393. package/dist/spec/catalogs/layouts/image-3x-crop-vertical.json +0 -37
  394. package/dist/spec/catalogs/layouts/image-3x-crop.json +0 -36
  395. package/dist/spec/catalogs/layouts/image-3x-fit-title-center.json +0 -41
  396. package/dist/spec/catalogs/layouts/image-3x-fit-vertical-title-left.json +0 -42
  397. package/dist/spec/catalogs/layouts/image-3x-fit-vertical.json +0 -37
  398. package/dist/spec/catalogs/layouts/image-3x-fit.json +0 -36
  399. package/dist/spec/catalogs/layouts/image-3x.json +0 -81
  400. package/dist/spec/catalogs/layouts/image-focus.json +0 -30
  401. package/dist/spec/catalogs/layouts/image-only-1x-crop-title-center.json +0 -31
  402. package/dist/spec/catalogs/layouts/image-only-1x-fit-title-center.json +0 -31
  403. package/dist/spec/catalogs/layouts/image-only-2x-crop-title-center.json +0 -37
  404. package/dist/spec/catalogs/layouts/image-only-2x-crop-vertical-title-left.json +0 -38
  405. package/dist/spec/catalogs/layouts/image-only-2x-crop-vertical.json +0 -33
  406. package/dist/spec/catalogs/layouts/image-only-2x-fit-title-center.json +0 -37
  407. package/dist/spec/catalogs/layouts/image-only-2x-fit-vertical-title-left.json +0 -38
  408. package/dist/spec/catalogs/layouts/image-only-2x-fit-vertical.json +0 -33
  409. package/dist/spec/catalogs/layouts/image-only-3x-crop-title-center.json +0 -40
  410. package/dist/spec/catalogs/layouts/image-only-3x-crop-vertical-title-left.json +0 -41
  411. package/dist/spec/catalogs/layouts/image-only-3x-crop-vertical.json +0 -36
  412. package/dist/spec/catalogs/layouts/image-only-3x-crop.json +0 -35
  413. package/dist/spec/catalogs/layouts/image-only-3x-fit-title-center.json +0 -40
  414. package/dist/spec/catalogs/layouts/image-only-3x-fit-vertical-title-left.json +0 -41
  415. package/dist/spec/catalogs/layouts/image-only-3x-fit-vertical.json +0 -36
  416. package/dist/spec/catalogs/layouts/image-only-3x-fit.json +0 -35
  417. package/dist/spec/catalogs/layouts/index.json +0 -1399
  418. package/dist/spec/catalogs/layouts/key-takeaway.json +0 -25
  419. package/dist/spec/catalogs/layouts/kpi-scorecard.json +0 -83
  420. package/dist/spec/catalogs/layouts/list-1x-box-title-center.json +0 -32
  421. package/dist/spec/catalogs/layouts/list-1x-box-vertical-title-center.json +0 -33
  422. package/dist/spec/catalogs/layouts/list-1x-box-vertical-title-left.json +0 -33
  423. package/dist/spec/catalogs/layouts/list-1x-box-vertical.json +0 -28
  424. package/dist/spec/catalogs/layouts/list-1x-box.json +0 -27
  425. package/dist/spec/catalogs/layouts/list-1x-itemimage-title-center.json +0 -32
  426. package/dist/spec/catalogs/layouts/list-1x-itemimage-vertical-title-center.json +0 -33
  427. package/dist/spec/catalogs/layouts/list-1x-title-center.json +0 -31
  428. package/dist/spec/catalogs/layouts/list-1x-vertical-title-center.json +0 -32
  429. package/dist/spec/catalogs/layouts/list-1x.json +0 -29
  430. package/dist/spec/catalogs/layouts/list-2x-box-title-center.json +0 -38
  431. package/dist/spec/catalogs/layouts/list-2x-box-vertical-title-center.json +0 -39
  432. package/dist/spec/catalogs/layouts/list-2x-box-vertical-title-left.json +0 -39
  433. package/dist/spec/catalogs/layouts/list-2x-box-vertical.json +0 -34
  434. package/dist/spec/catalogs/layouts/list-2x-box.json +0 -33
  435. package/dist/spec/catalogs/layouts/list-2x-itemimage-title-center.json +0 -38
  436. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical-title-center.json +0 -39
  437. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical-title-left.json +0 -39
  438. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical.json +0 -34
  439. package/dist/spec/catalogs/layouts/list-2x-title-center.json +0 -37
  440. package/dist/spec/catalogs/layouts/list-2x-vertical-title-center.json +0 -38
  441. package/dist/spec/catalogs/layouts/list-2x-vertical-title-left.json +0 -38
  442. package/dist/spec/catalogs/layouts/list-2x-vertical.json +0 -33
  443. package/dist/spec/catalogs/layouts/list-2x.json +0 -35
  444. package/dist/spec/catalogs/layouts/list-3x-box-title-center.json +0 -41
  445. package/dist/spec/catalogs/layouts/list-3x-box-vertical-title-center.json +0 -42
  446. package/dist/spec/catalogs/layouts/list-3x-box-vertical-title-left.json +0 -42
  447. package/dist/spec/catalogs/layouts/list-3x-box-vertical.json +0 -37
  448. package/dist/spec/catalogs/layouts/list-3x-box.json +0 -36
  449. package/dist/spec/catalogs/layouts/list-3x-itemimage-title-center.json +0 -41
  450. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical-title-center.json +0 -42
  451. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical-title-left.json +0 -42
  452. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical.json +0 -37
  453. package/dist/spec/catalogs/layouts/list-3x-itemimage.json +0 -36
  454. package/dist/spec/catalogs/layouts/list-3x-title-center.json +0 -40
  455. package/dist/spec/catalogs/layouts/list-3x-vertical-title-center.json +0 -41
  456. package/dist/spec/catalogs/layouts/list-3x-vertical-title-left.json +0 -41
  457. package/dist/spec/catalogs/layouts/list-3x-vertical.json +0 -36
  458. package/dist/spec/catalogs/layouts/list-3x.json +0 -38
  459. package/dist/spec/catalogs/layouts/list-4x-box-title-center.json +0 -45
  460. package/dist/spec/catalogs/layouts/list-4x-box-vertical-title-center.json +0 -45
  461. package/dist/spec/catalogs/layouts/list-4x-box-vertical-title-left.json +0 -45
  462. package/dist/spec/catalogs/layouts/list-4x-box-vertical.json +0 -40
  463. package/dist/spec/catalogs/layouts/list-4x-box.json +0 -40
  464. package/dist/spec/catalogs/layouts/list-4x-itemimage-title-center.json +0 -45
  465. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical-title-center.json +0 -45
  466. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical-title-left.json +0 -45
  467. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical.json +0 -40
  468. package/dist/spec/catalogs/layouts/list-4x-title-center.json +0 -44
  469. package/dist/spec/catalogs/layouts/list-4x-vertical-title-center.json +0 -44
  470. package/dist/spec/catalogs/layouts/list-4x-vertical-title-left.json +0 -44
  471. package/dist/spec/catalogs/layouts/list-4x-vertical.json +0 -39
  472. package/dist/spec/catalogs/layouts/list-4x.json +0 -42
  473. package/dist/spec/catalogs/layouts/list-5x-box-title-center.json +0 -48
  474. package/dist/spec/catalogs/layouts/list-5x-box-vertical-title-center.json +0 -50
  475. package/dist/spec/catalogs/layouts/list-5x-box-vertical-title-left.json +0 -50
  476. package/dist/spec/catalogs/layouts/list-5x-box-vertical.json +0 -45
  477. package/dist/spec/catalogs/layouts/list-5x-box.json +0 -43
  478. package/dist/spec/catalogs/layouts/list-5x-itemimage-title-center.json +0 -48
  479. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical-title-center.json +0 -48
  480. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical-title-left.json +0 -48
  481. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical.json +0 -43
  482. package/dist/spec/catalogs/layouts/list-5x-title-center.json +0 -47
  483. package/dist/spec/catalogs/layouts/list-5x-vertical-title-center.json +0 -47
  484. package/dist/spec/catalogs/layouts/list-5x-vertical-title-left.json +0 -47
  485. package/dist/spec/catalogs/layouts/list-5x-vertical.json +0 -42
  486. package/dist/spec/catalogs/layouts/list-5x.json +0 -45
  487. package/dist/spec/catalogs/layouts/list-6x-box-title-center.json +0 -51
  488. package/dist/spec/catalogs/layouts/list-6x-box-vertical-title-center.json +0 -53
  489. package/dist/spec/catalogs/layouts/list-6x-box-vertical-title-left.json +0 -53
  490. package/dist/spec/catalogs/layouts/list-6x-box-vertical.json +0 -48
  491. package/dist/spec/catalogs/layouts/list-6x-box.json +0 -46
  492. package/dist/spec/catalogs/layouts/list-6x-itemimage-title-center.json +0 -51
  493. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical-title-center.json +0 -51
  494. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical-title-left.json +0 -51
  495. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical.json +0 -46
  496. package/dist/spec/catalogs/layouts/list-6x-title-center.json +0 -50
  497. package/dist/spec/catalogs/layouts/list-6x-vertical-title-center.json +0 -50
  498. package/dist/spec/catalogs/layouts/list-6x-vertical-title-left.json +0 -50
  499. package/dist/spec/catalogs/layouts/list-6x-vertical.json +0 -45
  500. package/dist/spec/catalogs/layouts/list-6x.json +0 -48
  501. package/dist/spec/catalogs/layouts/logic-tree.json +0 -98
  502. package/dist/spec/catalogs/layouts/market-size.json +0 -53
  503. package/dist/spec/catalogs/layouts/matrix-quadrant.json +0 -42
  504. package/dist/spec/catalogs/layouts/media-1x.json +0 -29
  505. package/dist/spec/catalogs/layouts/network-dependency-map.json +0 -30
  506. package/dist/spec/catalogs/layouts/number-1x-box-title-center.json +0 -30
  507. package/dist/spec/catalogs/layouts/number-1x-box.json +0 -25
  508. package/dist/spec/catalogs/layouts/number-1x-title-center.json +0 -29
  509. package/dist/spec/catalogs/layouts/number-1x.json +0 -28
  510. package/dist/spec/catalogs/layouts/number-2x-box-title-center.json +0 -36
  511. package/dist/spec/catalogs/layouts/number-2x-box.json +0 -31
  512. package/dist/spec/catalogs/layouts/number-2x-title-center.json +0 -35
  513. package/dist/spec/catalogs/layouts/number-2x.json +0 -34
  514. package/dist/spec/catalogs/layouts/number-3x-box-title-center.json +0 -39
  515. package/dist/spec/catalogs/layouts/number-3x-box.json +0 -34
  516. package/dist/spec/catalogs/layouts/number-3x-title-center.json +0 -38
  517. package/dist/spec/catalogs/layouts/number-3x.json +0 -37
  518. package/dist/spec/catalogs/layouts/number-4x-box-title-center.json +0 -43
  519. package/dist/spec/catalogs/layouts/number-4x-box.json +0 -38
  520. package/dist/spec/catalogs/layouts/number-4x-title-center.json +0 -42
  521. package/dist/spec/catalogs/layouts/number-4x.json +0 -41
  522. package/dist/spec/catalogs/layouts/number-5x-box-title-center.json +0 -46
  523. package/dist/spec/catalogs/layouts/number-5x-box.json +0 -41
  524. package/dist/spec/catalogs/layouts/number-5x-title-center.json +0 -45
  525. package/dist/spec/catalogs/layouts/number-5x.json +0 -44
  526. package/dist/spec/catalogs/layouts/number-6x-box-title-center.json +0 -49
  527. package/dist/spec/catalogs/layouts/number-6x-box.json +0 -44
  528. package/dist/spec/catalogs/layouts/number-6x-title-center.json +0 -48
  529. package/dist/spec/catalogs/layouts/number-6x.json +0 -47
  530. package/dist/spec/catalogs/layouts/one-column-explainer.json +0 -29
  531. package/dist/spec/catalogs/layouts/org-chart.json +0 -86
  532. package/dist/spec/catalogs/layouts/persona-grid.json +0 -30
  533. package/dist/spec/catalogs/layouts/photo-grid.json +0 -43
  534. package/dist/spec/catalogs/layouts/pricing-table.json +0 -29
  535. package/dist/spec/catalogs/layouts/process-flow.json +0 -29
  536. package/dist/spec/catalogs/layouts/product-feature.json +0 -30
  537. package/dist/spec/catalogs/layouts/pros-cons.json +0 -35
  538. package/dist/spec/catalogs/layouts/qa-discussion.json +0 -30
  539. package/dist/spec/catalogs/layouts/quote-1x.json +0 -23
  540. package/dist/spec/catalogs/layouts/quote-highlight.json +0 -29
  541. package/dist/spec/catalogs/layouts/raci-matrix.json +0 -29
  542. package/dist/spec/catalogs/layouts/risk-heatmap.json +0 -29
  543. package/dist/spec/catalogs/layouts/roadmap.json +0 -29
  544. package/dist/spec/catalogs/layouts/screenshot-walkthrough.json +0 -30
  545. package/dist/spec/catalogs/layouts/section-divider.json +0 -28
  546. package/dist/spec/catalogs/layouts/single-message-statement.json +0 -25
  547. package/dist/spec/catalogs/layouts/stats-metrics.json +0 -39
  548. package/dist/spec/catalogs/layouts/status-rag.json +0 -29
  549. package/dist/spec/catalogs/layouts/swimlane-process.json +0 -30
  550. package/dist/spec/catalogs/layouts/swot-analysis.json +0 -42
  551. package/dist/spec/catalogs/layouts/table-1x.json +0 -29
  552. package/dist/spec/catalogs/layouts/team-bio.json +0 -30
  553. package/dist/spec/catalogs/layouts/testimonial-grid.json +0 -38
  554. package/dist/spec/catalogs/layouts/text-1x-box-title-center.json +0 -31
  555. package/dist/spec/catalogs/layouts/text-1x-box-title-left.json +0 -31
  556. package/dist/spec/catalogs/layouts/text-1x-center-box-title-center.json +0 -31
  557. package/dist/spec/catalogs/layouts/text-1x-center-box-title-left.json +0 -31
  558. package/dist/spec/catalogs/layouts/text-1x-center-box.json +0 -26
  559. package/dist/spec/catalogs/layouts/text-1x-center-title-center.json +0 -30
  560. package/dist/spec/catalogs/layouts/text-1x-center-title-left.json +0 -30
  561. package/dist/spec/catalogs/layouts/text-1x-center.json +0 -25
  562. package/dist/spec/catalogs/layouts/text-1x-left-box.json +0 -26
  563. package/dist/spec/catalogs/layouts/text-1x-title-center.json +0 -30
  564. package/dist/spec/catalogs/layouts/text-1x.json +0 -23
  565. package/dist/spec/catalogs/layouts/text-2x-box-title-center.json +0 -37
  566. package/dist/spec/catalogs/layouts/text-2x-box-vertical-title-left.json +0 -37
  567. package/dist/spec/catalogs/layouts/text-2x-center-box-title-center.json +0 -37
  568. package/dist/spec/catalogs/layouts/text-2x-center-box-vertical-title-left.json +0 -37
  569. package/dist/spec/catalogs/layouts/text-2x-center-box.json +0 -32
  570. package/dist/spec/catalogs/layouts/text-2x-center-title-center.json +0 -36
  571. package/dist/spec/catalogs/layouts/text-2x-center-vertical-title-left.json +0 -36
  572. package/dist/spec/catalogs/layouts/text-2x-center.json +0 -31
  573. package/dist/spec/catalogs/layouts/text-2x-left-box.json +0 -32
  574. package/dist/spec/catalogs/layouts/text-2x-title-center.json +0 -36
  575. package/dist/spec/catalogs/layouts/text-2x-vertical-title-left.json +0 -36
  576. package/dist/spec/catalogs/layouts/text-2x.json +0 -29
  577. package/dist/spec/catalogs/layouts/text-3x-box-title-center.json +0 -40
  578. package/dist/spec/catalogs/layouts/text-3x-box-vertical-title-left.json +0 -41
  579. package/dist/spec/catalogs/layouts/text-3x-center-box-title-center.json +0 -40
  580. package/dist/spec/catalogs/layouts/text-3x-center-box-vertical-title-left.json +0 -41
  581. package/dist/spec/catalogs/layouts/text-3x-center-box.json +0 -35
  582. package/dist/spec/catalogs/layouts/text-3x-center-title-center.json +0 -39
  583. package/dist/spec/catalogs/layouts/text-3x-center-vertical-title-left.json +0 -40
  584. package/dist/spec/catalogs/layouts/text-3x-center.json +0 -34
  585. package/dist/spec/catalogs/layouts/text-3x-left-box.json +0 -35
  586. package/dist/spec/catalogs/layouts/text-3x-left.json +0 -34
  587. package/dist/spec/catalogs/layouts/text-3x-title-center.json +0 -39
  588. package/dist/spec/catalogs/layouts/text-3x-vertical-title-left.json +0 -40
  589. package/dist/spec/catalogs/layouts/text-3x.json +0 -32
  590. package/dist/spec/catalogs/layouts/thank-you-cta.json +0 -28
  591. package/dist/spec/catalogs/layouts/three-column.json +0 -39
  592. package/dist/spec/catalogs/layouts/timeline-1x.json +0 -23
  593. package/dist/spec/catalogs/layouts/timeline.json +0 -32
  594. package/dist/spec/catalogs/layouts/title-center-box.json +0 -27
  595. package/dist/spec/catalogs/layouts/title-center-image-bottom.json +0 -34
  596. package/dist/spec/catalogs/layouts/title-center-image-top.json +0 -34
  597. package/dist/spec/catalogs/layouts/title-center.json +0 -26
  598. package/dist/spec/catalogs/layouts/title-left-image-bottom.json +0 -34
  599. package/dist/spec/catalogs/layouts/title-left-image-left.json +0 -34
  600. package/dist/spec/catalogs/layouts/title-left-image-right.json +0 -34
  601. package/dist/spec/catalogs/layouts/title-left-image-top.json +0 -34
  602. package/dist/spec/catalogs/layouts/title-slide.json +0 -28
  603. package/dist/spec/catalogs/layouts/title-subtitle.json +0 -23
  604. package/dist/spec/catalogs/layouts/title.json +0 -20
  605. package/dist/spec/catalogs/layouts/two-column.json +0 -36
  606. package/dist/spec/catalogs/layouts/venn-overlap.json +0 -29
  607. package/dist/spec/catalogs/layouts/waterfall-bridge.json +0 -39
  608. package/dist/spec/catalogs/layouts/wheel-radial.json +0 -29
  609. package/dist/spec/catalogs/manifest.json +0 -111
  610. package/dist/spec/catalogs/narratives/board-meeting.json +0 -192
  611. package/dist/spec/catalogs/narratives/business-narrative.json +0 -87
  612. package/dist/spec/catalogs/narratives/business-review.json +0 -119
  613. package/dist/spec/catalogs/narratives/capacity-planning.json +0 -88
  614. package/dist/spec/catalogs/narratives/challenge-resolution.json +0 -80
  615. package/dist/spec/catalogs/narratives/change-story.json +0 -64
  616. package/dist/spec/catalogs/narratives/classic-story.json +0 -78
  617. package/dist/spec/catalogs/narratives/company-intro.json +0 -96
  618. package/dist/spec/catalogs/narratives/conference-talk.json +0 -54
  619. package/dist/spec/catalogs/narratives/data-story.json +0 -65
  620. package/dist/spec/catalogs/narratives/early-startup-pitch.json +0 -119
  621. package/dist/spec/catalogs/narratives/educate.json +0 -95
  622. package/dist/spec/catalogs/narratives/employee-review.json +0 -87
  623. package/dist/spec/catalogs/narratives/failure-analysis.json +0 -104
  624. package/dist/spec/catalogs/narratives/focus.json +0 -120
  625. package/dist/spec/catalogs/narratives/golden-circle.json +0 -50
  626. package/dist/spec/catalogs/narratives/heros-journey.json +0 -64
  627. package/dist/spec/catalogs/narratives/index.json +0 -1041
  628. package/dist/spec/catalogs/narratives/innovation.json +0 -96
  629. package/dist/spec/catalogs/narratives/justice.json +0 -112
  630. package/dist/spec/catalogs/narratives/marketing-strategy.json +0 -111
  631. package/dist/spec/catalogs/narratives/performance-improvement-plan.json +0 -87
  632. package/dist/spec/catalogs/narratives/performance-review.json +0 -111
  633. package/dist/spec/catalogs/narratives/persuade.json +0 -94
  634. package/dist/spec/catalogs/narratives/persuasive-sales.json +0 -87
  635. package/dist/spec/catalogs/narratives/pitch-deck.json +0 -107
  636. package/dist/spec/catalogs/narratives/problem-solution.json +0 -61
  637. package/dist/spec/catalogs/narratives/product-launch.json +0 -104
  638. package/dist/spec/catalogs/narratives/project-proposal.json +0 -104
  639. package/dist/spec/catalogs/narratives/pyramid-principle.json +0 -48
  640. package/dist/spec/catalogs/narratives/qbr.json +0 -85
  641. package/dist/spec/catalogs/narratives/rags-to-riches.json +0 -80
  642. package/dist/spec/catalogs/narratives/reveal.json +0 -87
  643. package/dist/spec/catalogs/narratives/scqa.json +0 -55
  644. package/dist/spec/catalogs/narratives/situation-complication-resolution.json +0 -56
  645. package/dist/spec/catalogs/narratives/sparkline.json +0 -56
  646. package/dist/spec/catalogs/narratives/star-method.json +0 -56
  647. package/dist/spec/catalogs/narratives/status-update.json +0 -72
  648. package/dist/spec/catalogs/narratives/strategic-advisory.json +0 -85
  649. package/dist/spec/catalogs/narratives/strategic-narrative.json +0 -61
  650. package/dist/spec/catalogs/narratives/survey-analysis.json +0 -104
  651. package/dist/spec/catalogs/narratives/survival-story.json +0 -103
  652. package/dist/spec/catalogs/narratives/transformation-arc.json +0 -50
  653. package/dist/spec/catalogs/narratives/trend-analysis.json +0 -79
  654. package/dist/spec/catalogs/narratives/underdog-victory.json +0 -87
  655. package/dist/spec/catalogs/narratives/venture-pitch.json +0 -109
  656. package/dist/spec/catalogs/narratives/vision-roadmap.json +0 -65
  657. package/dist/spec/catalogs/narratives/weekly-progress.json +0 -103
  658. package/dist/spec/catalogs/narratives/what-so-what-now-what.json +0 -48
  659. package/dist/spec/catalogs/purposes/align.json +0 -16
  660. package/dist/spec/catalogs/purposes/decide.json +0 -16
  661. package/dist/spec/catalogs/purposes/educate.json +0 -16
  662. package/dist/spec/catalogs/purposes/index.json +0 -63
  663. package/dist/spec/catalogs/purposes/inform.json +0 -16
  664. package/dist/spec/catalogs/purposes/persuade.json +0 -16
  665. package/dist/spec/catalogs/purposes/pitch.json +0 -16
  666. package/dist/spec/catalogs/purposes/plan.json +0 -16
  667. package/dist/spec/catalogs/purposes/report.json +0 -16
  668. package/dist/spec/catalogs/purposes/sell.json +0 -16
  669. package/dist/spec/catalogs/social-platforms/bluesky.json +0 -14
  670. package/dist/spec/catalogs/social-platforms/facebook.json +0 -14
  671. package/dist/spec/catalogs/social-platforms/github.json +0 -15
  672. package/dist/spec/catalogs/social-platforms/index.json +0 -69
  673. package/dist/spec/catalogs/social-platforms/instagram.json +0 -13
  674. package/dist/spec/catalogs/social-platforms/linkedin.json +0 -15
  675. package/dist/spec/catalogs/social-platforms/mastodon.json +0 -14
  676. package/dist/spec/catalogs/social-platforms/threads.json +0 -13
  677. package/dist/spec/catalogs/social-platforms/tiktok.json +0 -14
  678. package/dist/spec/catalogs/social-platforms/x.json +0 -14
  679. package/dist/spec/catalogs/social-platforms/youtube.json +0 -14
  680. package/dist/spec/catalogs/themes/bold.json +0 -13
  681. package/dist/spec/catalogs/themes/classic.json +0 -13
  682. package/dist/spec/catalogs/themes/dark.json +0 -13
  683. package/dist/spec/catalogs/themes/index.json +0 -33
  684. package/dist/spec/catalogs/themes/minimal.json +0 -13
  685. package/dist/spec/catalogs/tones/authoritative.json +0 -31
  686. package/dist/spec/catalogs/tones/casual.json +0 -31
  687. package/dist/spec/catalogs/tones/conversational.json +0 -31
  688. package/dist/spec/catalogs/tones/formal.json +0 -31
  689. package/dist/spec/catalogs/tones/index.json +0 -51
  690. package/dist/spec/catalogs/tones/inspirational.json +0 -31
  691. package/dist/spec/catalogs/tones/persuasive.json +0 -32
  692. package/dist/spec/catalogs/tones/technical.json +0 -31
  693. package/dist/spec/previews/layouts/action-plan.html +0 -1
  694. package/dist/spec/previews/layouts/agenda.html +0 -1
  695. package/dist/spec/previews/layouts/appendix-index.html +0 -1
  696. package/dist/spec/previews/layouts/architecture-stack.html +0 -1
  697. package/dist/spec/previews/layouts/assumptions-dependencies.html +0 -1
  698. package/dist/spec/previews/layouts/before-after.html +0 -1
  699. package/dist/spec/previews/layouts/benchmark-target-table.html +0 -1
  700. package/dist/spec/previews/layouts/bullet-list.html +0 -1
  701. package/dist/spec/previews/layouts/business-model-canvas.html +0 -1
  702. package/dist/spec/previews/layouts/capability-map.html +0 -1
  703. package/dist/spec/previews/layouts/case-study.html +0 -1
  704. package/dist/spec/previews/layouts/chapter-recap.html +0 -1
  705. package/dist/spec/previews/layouts/circular-lifecycle.html +0 -1
  706. package/dist/spec/previews/layouts/comparison.html +0 -1
  707. package/dist/spec/previews/layouts/competitive-landscape.html +0 -1
  708. package/dist/spec/previews/layouts/customer-journey.html +0 -1
  709. package/dist/spec/previews/layouts/customer-logos.html +0 -1
  710. package/dist/spec/previews/layouts/dashboard.html +0 -1
  711. package/dist/spec/previews/layouts/data-visualization.html +0 -1
  712. package/dist/spec/previews/layouts/decision-tree.html +0 -1
  713. package/dist/spec/previews/layouts/detailed-data-table.html +0 -1
  714. package/dist/spec/previews/layouts/ecosystem-map.html +0 -1
  715. package/dist/spec/previews/layouts/executive-decision.html +0 -1
  716. package/dist/spec/previews/layouts/executive-summary.html +0 -1
  717. package/dist/spec/previews/layouts/faq.html +0 -1
  718. package/dist/spec/previews/layouts/feature-comparison-matrix.html +0 -1
  719. package/dist/spec/previews/layouts/forecast-scenario.html +0 -1
  720. package/dist/spec/previews/layouts/funnel-pyramid.html +0 -1
  721. package/dist/spec/previews/layouts/gantt-project-plan.html +0 -1
  722. package/dist/spec/previews/layouts/geographic-map.html +0 -1
  723. package/dist/spec/previews/layouts/heatmap-cohort.html +0 -1
  724. package/dist/spec/previews/layouts/hub-and-spoke.html +0 -1
  725. package/dist/spec/previews/layouts/icon-grid.html +0 -1
  726. package/dist/spec/previews/layouts/image-focus.html +0 -1
  727. package/dist/spec/previews/layouts/index.json +0 -357
  728. package/dist/spec/previews/layouts/key-takeaway.html +0 -1
  729. package/dist/spec/previews/layouts/kpi-scorecard.html +0 -1
  730. package/dist/spec/previews/layouts/logic-tree.html +0 -1
  731. package/dist/spec/previews/layouts/market-size.html +0 -1
  732. package/dist/spec/previews/layouts/matrix-quadrant.html +0 -1
  733. package/dist/spec/previews/layouts/network-dependency-map.html +0 -1
  734. package/dist/spec/previews/layouts/one-column-explainer.html +0 -1
  735. package/dist/spec/previews/layouts/org-chart.html +0 -1
  736. package/dist/spec/previews/layouts/persona-grid.html +0 -1
  737. package/dist/spec/previews/layouts/photo-grid.html +0 -1
  738. package/dist/spec/previews/layouts/pricing-table.html +0 -1
  739. package/dist/spec/previews/layouts/process-flow.html +0 -1
  740. package/dist/spec/previews/layouts/product-feature.html +0 -1
  741. package/dist/spec/previews/layouts/pros-cons.html +0 -1
  742. package/dist/spec/previews/layouts/qa-discussion.html +0 -1
  743. package/dist/spec/previews/layouts/quote-highlight.html +0 -1
  744. package/dist/spec/previews/layouts/raci-matrix.html +0 -1
  745. package/dist/spec/previews/layouts/risk-heatmap.html +0 -1
  746. package/dist/spec/previews/layouts/roadmap.html +0 -1
  747. package/dist/spec/previews/layouts/screenshot-walkthrough.html +0 -1
  748. package/dist/spec/previews/layouts/section-divider.html +0 -1
  749. package/dist/spec/previews/layouts/single-message-statement.html +0 -1
  750. package/dist/spec/previews/layouts/stats-metrics.html +0 -1
  751. package/dist/spec/previews/layouts/status-rag.html +0 -1
  752. package/dist/spec/previews/layouts/swimlane-process.html +0 -1
  753. package/dist/spec/previews/layouts/swot-analysis.html +0 -1
  754. package/dist/spec/previews/layouts/team-bio.html +0 -1
  755. package/dist/spec/previews/layouts/testimonial-grid.html +0 -1
  756. package/dist/spec/previews/layouts/thank-you-cta.html +0 -1
  757. package/dist/spec/previews/layouts/three-column.html +0 -1
  758. package/dist/spec/previews/layouts/timeline.html +0 -1
  759. package/dist/spec/previews/layouts/title-slide.html +0 -1
  760. package/dist/spec/previews/layouts/two-column.html +0 -1
  761. package/dist/spec/previews/layouts/venn-overlap.html +0 -1
  762. package/dist/spec/previews/layouts/waterfall-bridge.html +0 -1
  763. package/dist/spec/previews/layouts/wheel-radial.html +0 -1
@@ -1,5 +1,3 @@
1
- import { checkCatalogsOption, resolveReference, unresolvedReference, provenanceOf } from './chunk-SPFV27O5.js';
2
-
3
1
  // src/table.ts
4
2
  var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
5
3
  function tableGrid(value, path = "table") {
@@ -1187,10 +1185,10 @@ function slideSectionDiagnostics(presentation, uses) {
1187
1185
  const out = [];
1188
1186
  presentation.slides.forEach((slide, index) => {
1189
1187
  if (!isRecord(slide) || typeof slide.section === "string" && slide.section !== "") return;
1190
- const own2 = `/slides/${index}/`;
1188
+ const own3 = `/slides/${index}/`;
1191
1189
  const design = isRecord(slide.design) ? slide.design : {};
1192
1190
  const inherited = ["header", "footer"].filter((kind2) => design[kind2] === void 0).map((kind2) => `/design/${kind2}/`);
1193
- const where = paths.find((path) => path.startsWith(own2) || inherited.some((prefix) => path.startsWith(prefix)));
1191
+ const where = paths.find((path) => path.startsWith(own3) || inherited.some((prefix) => path.startsWith(prefix)));
1194
1192
  if (where === void 0) return;
1195
1193
  out.push({ code: "variable-builtin-missing", severity: "warning", path: `/slides/${index}`, id: "slide.section", message: `Slide ${index + 1} has no section, so '{{slide.section}}' (used at ${where}) resolves to nothing on it; give the slide a section or remove the token.` });
1196
1194
  });
@@ -1989,7 +1987,8 @@ function intrinsicImageAspect(value, assets) {
1989
1987
  }
1990
1988
 
1991
1989
  // src/design-hints.ts
1992
- var DESIGN_HINT_KEYS = ["titleAlignment", "contentAlignment", "contentBox", "contentDirection", "chartPrimary", "imageFit", "listBullet"];
1990
+ var DESIGN_HINT_KEYS = ["titleAlignment", "contentAlignment", "contentBox", "contentDirection", "chartPrimary", "imageFit", "listBullet", "mirror"];
1991
+ var THEME_DESIGN_KEYS = ["titleAlignment", "contentAlignment", "contentBox", "contentDirection", "imageFit", "listBullet"];
1993
1992
  var ALIGNMENTS = ["left", "center", "right"];
1994
1993
  var VALUES = {
1995
1994
  titleAlignment: ALIGNMENTS,
@@ -1998,12 +1997,14 @@ var VALUES = {
1998
1997
  contentDirection: ["horizontal", "vertical"],
1999
1998
  chartPrimary: ["none", "top", "bottom", "left", "right"],
2000
1999
  imageFit: ["cover", "contain", "stretch"],
2001
- listBullet: ["character", "image"]
2000
+ listBullet: ["character", "image"],
2001
+ mirror: "boolean"
2002
2002
  };
2003
+ var themeKeys = new Set(THEME_DESIGN_KEYS);
2003
2004
  var accepts = (key, value) => VALUES[key] === "boolean" ? typeof value === "boolean" : VALUES[key].includes(value);
2004
2005
  var object = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
2005
2006
  function resolveDesignHints(options = {}) {
2006
- const slide = object(object(options.slide).design), host = object(options.deck), deck = object(object(options.presentation).design), layout = object(object(options.layout).design);
2007
+ const slide = object(object(options.slide).design), host = object(options.deck), deck = object(object(options.presentation).design), theme = object(object(options.theme).design), layout = object(object(options.layout).design);
2007
2008
  const index = options.slideIndex ?? 0;
2008
2009
  const result = { sources: {}, paths: {} };
2009
2010
  const set2 = (key, value, source, path) => {
@@ -2015,6 +2016,7 @@ function resolveDesignHints(options = {}) {
2015
2016
  if (accepts(key, slide[key])) set2(key, slide[key], "slide", `slides.${index}.design.${key}`);
2016
2017
  else if (accepts(key, host[key])) set2(key, host[key], "deck", `design.${key}`);
2017
2018
  else if (accepts(key, deck[key])) set2(key, deck[key], "deck", `design.${key}`);
2019
+ else if (themeKeys.has(key) && accepts(key, theme[key])) set2(key, theme[key], "theme", slide.theme !== void 0 ? `slides.${index}.design.theme` : "design.theme");
2018
2020
  else if (accepts(key, layout[key])) set2(key, layout[key], "layout", `slides.${index}.layout`);
2019
2021
  }
2020
2022
  return result;
@@ -2043,73 +2045,441 @@ function readingRows(items) {
2043
2045
  return rows3.map((row) => row.items.sort((a, b) => index.get(a) - index.get(b)));
2044
2046
  }
2045
2047
 
2046
- // src/layout-content.ts
2047
- var LAYOUT_BODY_KINDS = ["text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
2048
- var MAX_PLACEHOLDER_GROUP_DEPTH = 3;
2049
- var bodyKinds = new Set(LAYOUT_BODY_KINDS);
2048
+ // src/layout-template.ts
2049
+ var REGION_KINDS = ["text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline", "group"];
2050
+ var REGION_ROLES = ["primary", "secondary", "media", "supporting"];
2051
+ var REGION_FLOWS = ["none", "grid", "column", "auto"];
2052
+ var REGION_ANCHORS = ["top", "middle", "bottom"];
2053
+ var HEADING_AREAS = ["title", "subtitle"];
2054
+ var RESERVED_REGION_NAMES = ["title", "subtitle", "tag", "auto", "left", "center", "right", "top", "middle", "bottom"];
2055
+ var MAX_TEMPLATE_TRACKS = 12;
2056
+ var MAX_REGION_BLOCKS = 12;
2057
+ var AUTO_LAYOUT = "auto";
2058
+ var OPFLayoutTemplateError = class extends RangeError {
2059
+ constructor(issues) {
2060
+ super(`The layout template is invalid: ${issues.map((issue) => `${issue.path || "/"}: ${issue.message}`).join("; ")}`);
2061
+ this.issues = issues;
2062
+ this.name = "OPFLayoutTemplateError";
2063
+ }
2064
+ issues;
2065
+ code = "layout-template";
2066
+ };
2067
+ var NAME = /^[a-z][a-z0-9-]*$/;
2050
2068
  var record4 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
2051
- function isPlaceholderGroup(placeholder) {
2052
- return record4(placeholder).type === "group";
2053
- }
2054
- function layoutSlots(layout, base = "layout.placeholders") {
2055
- const walk2 = (entries, path, depth) => (Array.isArray(entries) ? entries : []).map((entry, index) => {
2056
- const placeholder = record4(entry), slotPath = `${path}.${index}`;
2057
- const type = typeof placeholder.type === "string" ? placeholder.type : "";
2058
- if (type !== "group") {
2059
- if (depth > 0 && !bodyKinds.has(type)) throw new RangeError(`${slotPath}: a placeholder group holds body regions only, not '${type}'.`);
2060
- return { type, path: slotPath, depth, placeholder };
2061
- }
2062
- if (depth >= MAX_PLACEHOLDER_GROUP_DEPTH) throw new RangeError(`${slotPath}: placeholder groups nest at most ${MAX_PLACEHOLDER_GROUP_DEPTH} levels inside a layout record.`);
2063
- if (!Array.isArray(placeholder.placeholders) || !placeholder.placeholders.length) throw new RangeError(`${slotPath}: a placeholder group needs at least one placeholder.`);
2064
- return { type, path: slotPath, depth, placeholder, children: walk2(placeholder.placeholders, `${slotPath}.placeholders`, depth + 1) };
2065
- });
2066
- return walk2(layout?.placeholders, base, 0);
2069
+ var pointerSegment = (segment2) => segment2.replaceAll("~", "~0").replaceAll("/", "~1");
2070
+ var reserved = new Set(RESERVED_REGION_NAMES);
2071
+ var headingNames = new Set(HEADING_AREAS);
2072
+ var positive = (value) => typeof value === "number" && Number.isFinite(value) && value > 0;
2073
+ function isLayoutTemplate(layout) {
2074
+ return Object.hasOwn(record4(layout), "areas");
2075
+ }
2076
+ function layoutRegion(name, value) {
2077
+ const entry = record4(value);
2078
+ const accepts2 = Array.isArray(entry.accepts) ? [...new Set(entry.accepts.filter((kind2) => REGION_KINDS.includes(kind2)))] : [];
2079
+ const flow = REGION_FLOWS.includes(entry.flow) ? entry.flow : "auto";
2080
+ const max = Number.isInteger(entry.max) && entry.max >= 1 && entry.max <= MAX_REGION_BLOCKS ? entry.max : flow === "none" ? 1 : 6;
2081
+ return {
2082
+ name,
2083
+ accepts: accepts2,
2084
+ role: REGION_ROLES.includes(entry.role) ? entry.role : "primary",
2085
+ flow,
2086
+ max,
2087
+ bleed: entry.bleed === true,
2088
+ listColumns: entry.listColumns === "auto" ? "auto" : 1,
2089
+ anchor: REGION_ANCHORS.includes(entry.anchor) ? entry.anchor : "top",
2090
+ empty: entry.empty === "keep" ? "keep" : "collapse"
2091
+ };
2067
2092
  }
2068
- function layoutLeaves(layout) {
2069
- const leaves = [];
2070
- const visit = (slots) => {
2071
- for (const slot of slots) slot.children ? visit(slot.children) : leaves.push({ type: slot.type, path: slot.path, depth: slot.depth, placeholder: slot.placeholder });
2093
+ function parse(layout) {
2094
+ const value = record4(layout);
2095
+ const issues = [];
2096
+ const grid = (code, path, message) => issues.push({ code, path, message });
2097
+ const areas = value.areas;
2098
+ if (!Array.isArray(areas) || !areas.length) {
2099
+ grid("layout-template", "/areas", "a template needs 1 to 12 rows of area names");
2100
+ return { issues };
2101
+ }
2102
+ if (areas.length > MAX_TEMPLATE_TRACKS) grid("layout-template", "/areas", `a template has at most ${MAX_TEMPLATE_TRACKS} rows; this one has ${areas.length}`);
2103
+ const cells = areas.map((row, index) => {
2104
+ if (typeof row !== "string") {
2105
+ grid("layout-template", `/areas/${index}`, "each row is a string of area names");
2106
+ return [];
2107
+ }
2108
+ const words = row.trim().split(/\s+/).filter(Boolean);
2109
+ if (!words.length) grid("layout-template", `/areas/${index}`, 'a row needs at least one area name or "."');
2110
+ for (const word of words) if (word !== "." && !NAME.test(word)) grid("layout-template", `/areas/${index}`, `'${word}' is not an area name (lowercase letters, digits and hyphens, starting with a letter) or "."`);
2111
+ return words;
2112
+ });
2113
+ const width = cells[0]?.length ?? 0;
2114
+ cells.forEach((row, index) => {
2115
+ if (index > 0 && row.length !== width && row.length) grid("layout-template", `/areas/${index}`, `every row has the same number of cells; row ${index + 1} has ${row.length}, row 1 has ${width}`);
2116
+ });
2117
+ if (width > MAX_TEMPLATE_TRACKS) grid("layout-template", "/areas", `a template has at most ${MAX_TEMPLATE_TRACKS} columns; this one has ${width}`);
2118
+ const columns2 = value.columns === void 0 ? Array.from({ length: width }, () => 1) : value.columns;
2119
+ const rows3 = value.rows === void 0 ? Array.from({ length: cells.length }, () => 1) : value.rows;
2120
+ if (!Array.isArray(columns2) || columns2.length !== width || !columns2.every(positive)) grid("layout-template", "/columns", `columns needs one positive number per cell of a row (${width})`);
2121
+ if (!Array.isArray(rows3) || rows3.length !== cells.length || !rows3.every((size) => size === "auto" || positive(size))) grid("layout-template", "/rows", `rows needs one positive number or "auto" per row (${cells.length})`);
2122
+ if (issues.length) return { issues };
2123
+ const bounds = /* @__PURE__ */ new Map();
2124
+ cells.forEach((row, r) => {
2125
+ row.forEach((name, c) => {
2126
+ if (name === ".") return;
2127
+ const found = bounds.get(name);
2128
+ if (!found) bounds.set(name, { top: r, left: c, bottom: r, right: c, count: 1 });
2129
+ else {
2130
+ found.top = Math.min(found.top, r);
2131
+ found.left = Math.min(found.left, c);
2132
+ found.bottom = Math.max(found.bottom, r);
2133
+ found.right = Math.max(found.right, c);
2134
+ found.count++;
2135
+ }
2136
+ });
2137
+ });
2138
+ const list = [];
2139
+ for (const [name, box] of bounds) {
2140
+ const filled = (box.bottom - box.top + 1) * (box.right - box.left + 1);
2141
+ let rectangle = filled === box.count;
2142
+ for (let r = box.top; rectangle && r <= box.bottom; r++) for (let c = box.left; c <= box.right; c++) if (cells[r][c] !== name) {
2143
+ rectangle = false;
2144
+ break;
2145
+ }
2146
+ if (!rectangle) {
2147
+ grid("layout-template", "/areas", `the cells of '${name}' do not form one filled rectangle`);
2148
+ continue;
2149
+ }
2150
+ list.push({ name, row: box.top, column: box.left, rowSpan: box.bottom - box.top + 1, columnSpan: box.right - box.left + 1, heading: headingNames.has(name) });
2151
+ }
2152
+ if (issues.length) return { issues };
2153
+ list.sort((a, b) => a.row - b.row || a.column - b.column);
2154
+ const entries = record4(value.regions);
2155
+ const region = (path, message) => grid("layout-region", path, message);
2156
+ if (value.regions !== void 0 && (value.regions === null || typeof value.regions !== "object" || Array.isArray(value.regions))) region("/regions", "regions is an object keyed by region name");
2157
+ for (const name of Object.keys(entries)) {
2158
+ if (reserved.has(name)) region(`/regions/${pointerSegment(name)}`, `'${name}' is reserved and cannot name a region (reserved: ${RESERVED_REGION_NAMES.join(", ")})`);
2159
+ else if (!bounds.has(name)) region(`/regions/${pointerSegment(name)}`, `region '${name}' has no area in areas`);
2160
+ }
2161
+ for (const area of list) {
2162
+ if (area.heading) continue;
2163
+ if (reserved.has(area.name)) {
2164
+ if (!Object.hasOwn(entries, area.name)) region("/areas", `'${area.name}' is reserved and cannot name a body area (reserved: ${RESERVED_REGION_NAMES.join(", ")})`);
2165
+ continue;
2166
+ }
2167
+ if (!Object.hasOwn(entries, area.name)) region("/regions", `body area '${area.name}' has no entry in regions`);
2168
+ }
2169
+ if (bounds.has("subtitle") && !bounds.has("title")) region("/areas", "a 'subtitle' area needs a 'title' area");
2170
+ for (const [name, entry] of Object.entries(entries)) {
2171
+ const raw = record4(entry);
2172
+ if (raw.flow === "none" && raw.max !== void 0 && raw.max !== 1) region(`/regions/${pointerSegment(name)}/max`, `a region with flow "none" holds one block; max must be 1, not ${JSON.stringify(raw.max)}`);
2173
+ }
2174
+ const regions = list.filter((area) => !area.heading && !reserved.has(area.name) && Object.hasOwn(entries, area.name)).map((area) => layoutRegion(area.name, entries[area.name]));
2175
+ for (const entry of regions) if (!entry.accepts.length) region(`/regions/${pointerSegment(entry.name)}/accepts`, `region '${entry.name}' accepts no content kind`);
2176
+ if (value.overflowRegion !== void 0 && !regions.some((entry) => entry.name === value.overflowRegion)) region("/overflowRegion", `overflowRegion ${JSON.stringify(value.overflowRegion)} is not a region of this layout`);
2177
+ if (issues.length) return { issues };
2178
+ const overflowRegion = typeof value.overflowRegion === "string" ? value.overflowRegion : regions.find((entry) => entry.role === "primary" && entry.flow !== "none")?.name;
2179
+ return {
2180
+ issues,
2181
+ template: {
2182
+ rows: rows3.slice(),
2183
+ columns: columns2.slice(),
2184
+ grid: cells,
2185
+ areas: list,
2186
+ regions,
2187
+ ...overflowRegion !== void 0 ? { overflowRegion } : {},
2188
+ title: bounds.has("title"),
2189
+ subtitle: bounds.has("subtitle")
2190
+ }
2072
2191
  };
2073
- visit(layoutSlots(layout));
2074
- return leaves;
2075
2192
  }
2076
- function layoutStructure(layout) {
2077
- const describe = (slots) => slots.map((slot) => {
2078
- if (!slot.children) return slot.type;
2079
- const mode = record4(slot.placeholder.composition).mode;
2080
- return `${typeof mode === "string" && mode !== "auto" ? mode : "group"} (${describe(slot.children)})`;
2081
- }).join(", ");
2082
- return describe(layoutSlots(layout));
2193
+ function layoutTemplateIssues(layout) {
2194
+ return isLayoutTemplate(layout) ? parse(layout).issues : [];
2083
2195
  }
2084
- function hasPlaceholderGroups(layout) {
2085
- return Array.isArray(layout?.placeholders) && layout.placeholders.some(isPlaceholderGroup);
2196
+ function layoutTemplate(layout) {
2197
+ const parsed = parse(layout);
2198
+ if (!parsed.template) throw new OPFLayoutTemplateError(parsed.issues);
2199
+ return parsed.template;
2086
2200
  }
2087
- function layoutContent(layout) {
2088
- const heading = { title: false, subtitle: false, tag: false };
2089
- const counts = /* @__PURE__ */ new Map();
2090
- let count = 0;
2091
- const visit = (entries, depth) => {
2092
- for (const entry of Array.isArray(entries) ? entries : []) {
2093
- const type = record4(entry).type;
2094
- if (type === "group") {
2095
- if (depth < MAX_PLACEHOLDER_GROUP_DEPTH) visit(record4(entry).placeholders, depth + 1);
2096
- continue;
2097
- }
2098
- if (type === "title" || type === "subtitle" || type === "tag") {
2099
- if (depth === 0) heading[type] = true;
2100
- } else if (typeof type === "string" && bodyKinds.has(type)) {
2101
- counts.set(type, (counts.get(type) ?? 0) + 1);
2102
- count += 1;
2103
- }
2201
+
2202
+ // src/bind-regions.ts
2203
+ var FIELDS = ["text", "items", "bullets", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
2204
+ var FIELD_KINDS = { text: "text", bullets: "text", items: "list", image: "image", video: "video", chart: "chart", table: "table", code: "code", metric: "metric", quote: "quote", timeline: "timeline" };
2205
+ var IMAGE_EDGES = ["left", "right", "top", "bottom"];
2206
+ var PROMOTED_REGION_KEY = /^(top|middle|bottom)(\+(top|middle|bottom))*(:(left|center|right)(\+(left|center|right))*)?$|^(left|center|right)(\+(left|center|right))*$/;
2207
+ var record5 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
2208
+ var empty = (value) => value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
2209
+ function blockKind(block) {
2210
+ const value = record5(block);
2211
+ if (Array.isArray(value.blocks)) return "group";
2212
+ if (typeof value.type === "string" && value.type !== "group" && Object.values(FIELD_KINDS).includes(value.type)) return value.type;
2213
+ const field = FIELDS.find((name) => value[name] !== void 0);
2214
+ return field ? FIELD_KINDS[field] : "text";
2215
+ }
2216
+ function leafKinds(block, into = /* @__PURE__ */ new Set(), depth = 0) {
2217
+ if (depth > 32) return into;
2218
+ for (const child of Array.isArray(block.blocks) ? block.blocks : []) {
2219
+ const value = record5(child);
2220
+ if (Array.isArray(value.blocks)) leafKinds(value, into, depth + 1);
2221
+ else into.add(blockKind(value));
2222
+ }
2223
+ return into;
2224
+ }
2225
+ function regionAccepts(region, block) {
2226
+ const kind2 = blockKind(block);
2227
+ if (region.accepts.includes(kind2)) return true;
2228
+ if (kind2 !== "group") return false;
2229
+ const kinds = leafKinds(record5(block));
2230
+ return kinds.size > 0 && [...kinds].every((leaf) => region.accepts.includes(leaf));
2231
+ }
2232
+ function placedImageBlocks(slide) {
2233
+ const value = record5(slide);
2234
+ const placed = /* @__PURE__ */ new Set();
2235
+ if (!Array.isArray(value.blocks) || Object.keys(value).some((key) => PROMOTED_REGION_KEY.test(key))) return placed;
2236
+ const used = /* @__PURE__ */ new Set();
2237
+ value.blocks.forEach((block, index) => {
2238
+ const host = record5(block);
2239
+ if (Array.isArray(host.blocks) || host.image === void 0 || host.placement === void 0) return;
2240
+ const edge = record5(host.placement).edge;
2241
+ if (!IMAGE_EDGES.includes(edge) || used.has(edge)) return;
2242
+ used.add(edge);
2243
+ placed.add(index);
2244
+ });
2245
+ return placed;
2246
+ }
2247
+ function rootNodes(slide, slideIndex = 0) {
2248
+ const value = record5(slide), base = `slides.${slideIndex}`;
2249
+ if (Array.isArray(value.blocks)) {
2250
+ const placed = placedImageBlocks(value);
2251
+ return value.blocks.flatMap((block, index) => {
2252
+ const host = record5(block);
2253
+ if (placed.has(index)) return [];
2254
+ if (!Array.isArray(host.blocks) && FIELDS.every((field) => empty(host[field]))) return [];
2255
+ if (Array.isArray(host.blocks) && !host.blocks.length) return [];
2256
+ return [{ path: `${base}.blocks.${index}`, kind: blockKind(host), block: index, value: host }];
2257
+ });
2258
+ }
2259
+ const nodes = [];
2260
+ for (const field of FIELDS) {
2261
+ if (empty(value[field]) || field === "bullets" && !empty(value.text)) continue;
2262
+ const fields2 = field === "text" && !empty(value.bullets) ? ["text", "bullets"] : [field];
2263
+ nodes.push({ path: `${base}.${field}`, kind: FIELD_KINDS[field], fields: fields2, value: Object.fromEntries(fields2.map((name) => [name, value[name]])) });
2264
+ }
2265
+ return nodes;
2266
+ }
2267
+ function regionRoleRank(role, kind2) {
2268
+ const media = kind2 === "image" || kind2 === "video";
2269
+ return media ? { media: 0, primary: 1, secondary: 2, supporting: 3 }[role] : { primary: 0, secondary: 1, supporting: 2, media: 3 }[role];
2270
+ }
2271
+ function bindRegions(slide, layout, options = {}) {
2272
+ const template = layoutTemplate(layout);
2273
+ const value = record5(slide), index = options.slideIndex ?? 0;
2274
+ const regions = template.regions.map((region) => ({ name: region.name, blocks: [], overflow: [] }));
2275
+ const result = { regions, below: [], diagnostics: [] };
2276
+ if (Object.keys(value).some((key) => PROMOTED_REGION_KEY.test(key))) return result;
2277
+ const byName = new Map(template.regions.map((region, order2) => [region.name, { region, binding: regions[order2], order: order2 }]));
2278
+ const room = (name) => {
2279
+ const entry = byName.get(name);
2280
+ return entry.binding.blocks.length < entry.region.max;
2281
+ };
2282
+ const nodes = rootNodes(value, index);
2283
+ const rest = [];
2284
+ for (const node of nodes) {
2285
+ const pin = node.block !== void 0 ? node.value.region : void 0;
2286
+ if (typeof pin !== "string") {
2287
+ rest.push(node);
2288
+ continue;
2289
+ }
2290
+ const target = byName.get(pin), pinPath = `${node.path}.region`;
2291
+ if (!target) result.diagnostics.push({ code: "region-unknown", path: pinPath, region: pin, message: `The layout has no region '${pin}'; the block is placed by its kind instead.` });
2292
+ else if (!regionAccepts(target.region, node.value)) result.diagnostics.push({ code: "region-kind", path: pinPath, region: pin, message: `Region '${pin}' does not accept ${node.kind} content (it accepts ${target.region.accepts.join(", ")}); the block is placed by its kind instead.` });
2293
+ else if (!room(pin)) result.diagnostics.push({ code: "region-full", path: pinPath, region: pin, message: `Region '${pin}' already holds its ${target.region.max} block${target.region.max === 1 ? "" : "s"}; the block is placed by its kind instead.` });
2294
+ else {
2295
+ target.binding.blocks.push({ path: node.path, kind: node.kind, block: node.block, pinned: true });
2296
+ continue;
2297
+ }
2298
+ rest.push(node);
2299
+ }
2300
+ const overflowName = template.overflowRegion;
2301
+ for (const node of rest) {
2302
+ const bound = { path: node.path, kind: node.kind, ...node.block !== void 0 ? { block: node.block } : {}, ...node.fields ? { fields: node.fields } : {} };
2303
+ let best;
2304
+ for (const [name, entry] of byName) {
2305
+ if (!regionAccepts(entry.region, node.value) || !room(name)) continue;
2306
+ const rank = regionRoleRank(entry.region.role, node.kind);
2307
+ if (!best || rank < best.rank || rank === best.rank && entry.order < best.order) best = { rank, order: entry.order, name };
2308
+ }
2309
+ if (best) {
2310
+ byName.get(best.name).binding.blocks.push(bound);
2311
+ continue;
2312
+ }
2313
+ if (overflowName === void 0) {
2314
+ result.below.push(bound);
2315
+ result.diagnostics.push({ code: "layout-unplaced", path: node.path, message: "No region of the layout takes this block; it is drawn below the layout's grid. Choose another layout, pin it to a region, or paginate." });
2316
+ continue;
2317
+ }
2318
+ const overflow = byName.get(overflowName);
2319
+ if (room(overflowName)) {
2320
+ overflow.binding.blocks.push(bound);
2321
+ continue;
2104
2322
  }
2323
+ overflow.binding.overflow.push(bound);
2324
+ result.diagnostics.push({ code: "layout-unplaced", path: node.path, region: overflowName, message: `No region of the layout has room for this block; it is drawn in '${overflowName}' beyond its ${overflow.region.max} block${overflow.region.max === 1 ? "" : "s"}. Paginate to move it to a continuation slide, choose another layout, or remove a block.` });
2325
+ }
2326
+ const order = new Map(nodes.map((node, position) => [node.path, position]));
2327
+ for (const binding of regions) binding.blocks.sort((a, b) => order.get(a.path) - order.get(b.path));
2328
+ return result;
2329
+ }
2330
+
2331
+ // src/template-geometry.ts
2332
+ function gridFlowShape(count, landscape) {
2333
+ if (!Number.isInteger(count) || count < 1) return { columns: 1, rows: 0, perRow: [] };
2334
+ let columns2;
2335
+ if (landscape) columns2 = count <= 3 ? count : count === 4 ? 2 : count <= 6 ? 3 : 4;
2336
+ else columns2 = count <= 3 ? 1 : count <= 6 ? 2 : Math.ceil(count / 3);
2337
+ const rows3 = Math.ceil(count / columns2);
2338
+ const perRow = Array.from({ length: rows3 }, (_, row) => Math.min(columns2, count - row * columns2));
2339
+ return { columns: columns2, rows: rows3, perRow };
2340
+ }
2341
+ function flowShape(arrangement, count, landscape) {
2342
+ if (count < 1) return { columns: 1, rows: 0, perRow: [] };
2343
+ if (arrangement === "row") return { columns: count, rows: 1, perRow: [count] };
2344
+ if (arrangement === "column") return { columns: 1, rows: count, perRow: Array.from({ length: count }, () => 1) };
2345
+ return gridFlowShape(count, landscape);
2346
+ }
2347
+ function flowCells(shape, box, requestedGap) {
2348
+ if (!shape.rows) return { cells: [], gap: requestedGap };
2349
+ const gap = Math.max(0, Math.min(requestedGap, box.width / (shape.columns * 2), box.height / (shape.rows * 2)));
2350
+ const width = (box.width - gap * (shape.columns - 1)) / shape.columns;
2351
+ const height = (box.height - gap * (shape.rows - 1)) / shape.rows;
2352
+ const cells = [];
2353
+ shape.perRow.forEach((count, row) => {
2354
+ const used = count * width + (count - 1) * gap, start = box.x + (box.width - used) / 2;
2355
+ for (let column = 0; column < count; column++) cells.push({ x: count === shape.columns ? box.x + column * (width + gap) : start + column * (width + gap), y: box.y + row * (height + gap), width, height });
2356
+ });
2357
+ return { cells, gap };
2358
+ }
2359
+ function columnWidths(sizes, total, gap) {
2360
+ const sum = sizes.reduce((a, b) => a + b, 0);
2361
+ const rest = Math.max(0, total - Math.max(0, sizes.length - 1) * gap);
2362
+ return sizes.map((size) => sum > 0 ? rest * size / sum : 0);
2363
+ }
2364
+ function collapseAreas(grid, empty2, heading, absorbs = () => true) {
2365
+ const owner = grid.map((row) => [...row]);
2366
+ const joined = /* @__PURE__ */ new Map();
2367
+ const rect = (name) => {
2368
+ let top = Infinity, left = Infinity, bottom = -1, right = -1;
2369
+ owner.forEach((row, r) => {
2370
+ row.forEach((cell, c) => {
2371
+ if (cell === name) {
2372
+ top = Math.min(top, r);
2373
+ left = Math.min(left, c);
2374
+ bottom = Math.max(bottom, r);
2375
+ right = Math.max(right, c);
2376
+ }
2377
+ });
2378
+ });
2379
+ return bottom < 0 ? void 0 : { row: top, column: left, rowSpan: bottom - top + 1, columnSpan: right - left + 1 };
2105
2380
  };
2106
- visit(layout?.placeholders, 0);
2107
- let kind2 = "title", best = 0;
2108
- for (const [candidate, total] of counts) if (total > best) {
2109
- kind2 = candidate;
2110
- best = total;
2381
+ const order = [];
2382
+ for (const row of owner) for (const cell of row) if (cell !== "." && !order.includes(cell)) order.push(cell);
2383
+ const pending = order.filter((name) => empty2.has(name));
2384
+ let changed = true;
2385
+ while (changed) {
2386
+ changed = false;
2387
+ for (const name of pending) {
2388
+ if (joined.has(name)) continue;
2389
+ const own3 = rect(name);
2390
+ if (!own3) continue;
2391
+ const neighbour = (side) => {
2392
+ const cells = [];
2393
+ if (side === "start" || side === "end") {
2394
+ const column = side === "start" ? own3.column - 1 : own3.column + own3.columnSpan;
2395
+ if (column < 0 || column >= (owner[0]?.length ?? 0)) return void 0;
2396
+ for (let r = own3.row; r < own3.row + own3.rowSpan; r++) cells.push(owner[r][column]);
2397
+ } else {
2398
+ const row = side === "above" ? own3.row - 1 : own3.row + own3.rowSpan;
2399
+ if (row < 0 || row >= owner.length) return void 0;
2400
+ for (let c = own3.column; c < own3.column + own3.columnSpan; c++) cells.push(owner[row][c]);
2401
+ }
2402
+ const candidate = cells[0];
2403
+ if (candidate === void 0 || candidate === "." || candidate === name || cells.some((cell) => cell !== candidate)) return void 0;
2404
+ if (empty2.has(candidate) || !absorbs(candidate)) return void 0;
2405
+ const other = rect(candidate);
2406
+ const fits = side === "start" || side === "end" ? other.row === own3.row && other.rowSpan === own3.rowSpan : other.column === own3.column && other.columnSpan === own3.columnSpan;
2407
+ return fits ? candidate : void 0;
2408
+ };
2409
+ const sides = ["start", "end", "below", "above"];
2410
+ let target;
2411
+ for (const body of [true, false]) {
2412
+ for (const side of sides) {
2413
+ const candidate = neighbour(side);
2414
+ if (candidate !== void 0 && heading(candidate) !== body) {
2415
+ target = candidate;
2416
+ break;
2417
+ }
2418
+ }
2419
+ if (target !== void 0) break;
2420
+ }
2421
+ if (target === void 0) continue;
2422
+ for (const row of owner) row.forEach((cell, c) => {
2423
+ if (cell === name) row[c] = target;
2424
+ });
2425
+ joined.set(name, target);
2426
+ changed = true;
2427
+ }
2111
2428
  }
2112
- return { kind: kind2, count, heading };
2429
+ return { grid: owner, joined };
2430
+ }
2431
+ function areaRects(grid) {
2432
+ const rects = /* @__PURE__ */ new Map();
2433
+ grid.forEach((row, r) => {
2434
+ row.forEach((name, c) => {
2435
+ if (name === ".") return;
2436
+ const found = rects.get(name);
2437
+ if (!found) rects.set(name, { row: r, column: c, rowSpan: 1, columnSpan: 1 });
2438
+ else {
2439
+ found.rowSpan = Math.max(found.rowSpan, r - found.row + 1);
2440
+ found.columnSpan = Math.max(found.columnSpan, c - found.column + 1);
2441
+ }
2442
+ });
2443
+ });
2444
+ return rects;
2445
+ }
2446
+ function listColumnBreaks(heights, levels, count) {
2447
+ const n = heights.length;
2448
+ if (count <= 1 || n < 2) return [];
2449
+ const allowed = Array.from({ length: n }, (_, index) => index > 0 && (levels[index] ?? 0) === 0);
2450
+ const prefix = [0];
2451
+ for (const height of heights) prefix.push(prefix.at(-1) + height);
2452
+ const span = (from, to) => prefix[to] - prefix[from];
2453
+ const memo = /* @__PURE__ */ new Map();
2454
+ const solve = (start, columns2) => {
2455
+ const key = `${start}:${columns2}`;
2456
+ const found = memo.get(key);
2457
+ if (found) return found;
2458
+ let best = { cost: span(start, n), breaks: [] };
2459
+ if (columns2 > 1) for (let next = start + 1; next < n; next++) {
2460
+ if (!allowed[next]) continue;
2461
+ const rest = solve(next, columns2 - 1);
2462
+ const cost = Math.max(span(start, next), rest.cost);
2463
+ if (cost < best.cost - 1e-9) best = { cost, breaks: [next, ...rest.breaks] };
2464
+ }
2465
+ memo.set(key, best);
2466
+ return best;
2467
+ };
2468
+ return solve(0, count).breaks;
2469
+ }
2470
+ function allocateRows(rows3, total, gap) {
2471
+ const auto = rows3.map((row) => row.size === "auto" ? Math.max(0, Math.min(row.need, row.kind === "below" ? total : total / 2)) : 0);
2472
+ const visible = rows3.filter((row, index) => row.size !== "auto" || auto[index] > 0).length;
2473
+ const headings2 = rows3.reduce((sum, row, index) => sum + (row.kind === "heading" ? auto[index] : 0), 0);
2474
+ const space = Math.max(0, total - headings2 - Math.max(0, visible - 1) * gap);
2475
+ const numeric = rows3.reduce((sum, row) => sum + (row.size === "auto" ? 0 : row.size), 0);
2476
+ const numericNeed = rows3.reduce((sum, row) => sum + (row.size === "auto" ? 0 : Math.max(0, row.need)), 0);
2477
+ const reserve = numeric > 0 ? Math.min(numericNeed, space / 2) : 0;
2478
+ const body = rows3.reduce((sum, row, index) => sum + (row.size === "auto" && row.kind !== "heading" ? auto[index] : 0), 0);
2479
+ const factor = body > space - reserve && body > 0 ? Math.max(0, space - reserve) / body : 1;
2480
+ const heights = rows3.map((row, index) => row.size === "auto" ? row.kind === "heading" ? auto[index] : auto[index] * factor : 0);
2481
+ const rest = Math.max(0, space - heights.reduce((sum, height, index) => sum + (rows3[index].kind === "heading" ? 0 : height), 0));
2482
+ return rows3.map((row, index) => row.size === "auto" ? heights[index] : numeric > 0 ? rest * row.size / numeric : 0);
2113
2483
  }
2114
2484
 
2115
2485
  // src/direction.ts
@@ -2152,6 +2522,215 @@ function paragraphDirectionAt(text2, deckDirection) {
2152
2522
  };
2153
2523
  }
2154
2524
 
2525
+ // src/catalog-refs.ts
2526
+ var catalogKinds = ["layouts", "themes", "colorSchemes", "fontSchemes", "narratives", "audiences", "purposes", "tones"];
2527
+ var CATALOG_REFERENCE_PATTERN = /^(?:([a-z][a-z0-9-]*):)?([a-z][a-z0-9-]*)$/;
2528
+ var CATALOG_GROUP_PATTERN = /^[a-z][a-z0-9-]*$/;
2529
+ function provenanceOf(found) {
2530
+ const { record: _record, ...provenance } = found;
2531
+ return provenance;
2532
+ }
2533
+ var OPFCatalogsOptionError = class extends TypeError {
2534
+ code = "invalid-catalogs";
2535
+ constructor(entry, detail) {
2536
+ super(`${entry}: the catalogs option must be an array of registered catalogs ({ source, <kind>: { <id>: record } } with known catalog kinds); ${detail}.`);
2537
+ this.name = "OPFCatalogsOptionError";
2538
+ }
2539
+ };
2540
+ function checkCatalogsOption(catalogs, entry) {
2541
+ if (catalogs === void 0) return [];
2542
+ if (!Array.isArray(catalogs)) throw new OPFCatalogsOptionError(entry, `got ${catalogs === null ? "null" : typeof catalogs}`);
2543
+ catalogs.forEach((catalog, index) => {
2544
+ if (!isRec(catalog) || typeof catalog.source !== "string") throw new OPFCatalogsOptionError(entry, `catalogs[${index}] is not an object with a string source`);
2545
+ for (const [kind2, records] of Object.entries(catalog)) {
2546
+ if (kind2 === "source") continue;
2547
+ if (!catalogKinds.includes(kind2)) throw new OPFCatalogsOptionError(entry, `catalogs[${index}].${kind2} is not a catalog kind`);
2548
+ if (!isRec(records)) throw new OPFCatalogsOptionError(entry, `catalogs[${index}].${kind2} is not an object of records keyed by id`);
2549
+ }
2550
+ });
2551
+ return catalogs;
2552
+ }
2553
+ var OPFUnresolvedReferenceError = class extends Error {
2554
+ diagnostics;
2555
+ constructor(diagnostics) {
2556
+ super(diagnostics.map((diagnostic) => diagnostic.message).join(" "));
2557
+ this.name = "OPFUnresolvedReferenceError";
2558
+ this.diagnostics = diagnostics;
2559
+ }
2560
+ };
2561
+ var isRec = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2562
+ var rec = (value) => isRec(value) ? value : {};
2563
+ var own2 = (value, key) => Object.hasOwn(value, key);
2564
+ function parseReference(reference) {
2565
+ if (typeof reference !== "string") return void 0;
2566
+ const match = CATALOG_REFERENCE_PATTERN.exec(reference);
2567
+ if (!match) return void 0;
2568
+ const [, group, id] = match;
2569
+ return group === void 0 ? { id } : { group, id };
2570
+ }
2571
+ function groupsOf(document) {
2572
+ return rec(rec(document).catalogs);
2573
+ }
2574
+ function catalogGroupDeclared(document, name) {
2575
+ const groups = groupsOf(document);
2576
+ return own2(groups, name) && (isRec(groups[name]) || name === "default" && groups[name] === false);
2577
+ }
2578
+ function catalogGroupSource(document, name, options = {}) {
2579
+ if (name === "custom") return void 0;
2580
+ const group = groupsOf(document)[name];
2581
+ if (name === "default") {
2582
+ if (group === false) return void 0;
2583
+ const source2 = rec(group).source;
2584
+ return typeof source2 === "string" ? source2 : options.catalogs?.[0]?.source;
2585
+ }
2586
+ const source = rec(group).source;
2587
+ return typeof source === "string" ? source : void 0;
2588
+ }
2589
+ function registeredCatalog(source, options = {}) {
2590
+ if (source === void 0) return void 0;
2591
+ return options.catalogs?.find((catalog) => catalog?.source === source);
2592
+ }
2593
+ function lookupInGroup(document, kind2, group, id, reference, options = {}) {
2594
+ const groups = groupsOf(document);
2595
+ if (group === "default" && groups.default === false) return void 0;
2596
+ if (group !== "default" && group !== "custom" && !isRec(groups[group])) return void 0;
2597
+ const source = catalogGroupSource(document, group, options);
2598
+ const embedded = rec(rec(groups[group])[kind2]);
2599
+ if (own2(embedded, id) && isRec(embedded[id])) {
2600
+ return { kind: kind2, reference, id, group, ...source !== void 0 ? { source } : {}, origin: "document", record: embedded[id] };
2601
+ }
2602
+ if (group === "custom") return void 0;
2603
+ const hosted = registeredCatalog(source, options)?.[kind2];
2604
+ if (hosted && own2(hosted, id) && isRec(hosted[id])) {
2605
+ return { kind: kind2, reference, id, group, ...source !== void 0 ? { source } : {}, origin: "host", record: hosted[id] };
2606
+ }
2607
+ return void 0;
2608
+ }
2609
+ function resolveReference(document, kind2, reference, options = {}) {
2610
+ checkCatalogsOption(options.catalogs, "resolveReference");
2611
+ const parsed = parseReference(reference);
2612
+ if (!parsed) return void 0;
2613
+ const written = reference;
2614
+ if (parsed.group !== void 0) return lookupInGroup(document, kind2, parsed.group, parsed.id, written, options);
2615
+ const order = [...new Set([options.group, "custom", "default"].filter((group) => typeof group === "string"))];
2616
+ for (const group of order) {
2617
+ const found = lookupInGroup(document, kind2, group, parsed.id, written, options);
2618
+ if (found) return found;
2619
+ }
2620
+ return void 0;
2621
+ }
2622
+ var KIND_NOUNS = {
2623
+ layouts: "Layout",
2624
+ themes: "Theme",
2625
+ colorSchemes: "Colour scheme",
2626
+ fontSchemes: "Font scheme",
2627
+ narratives: "Narrative",
2628
+ audiences: "Audience",
2629
+ purposes: "Purpose",
2630
+ tones: "Tone"
2631
+ };
2632
+ function unresolvedReference(document, kind2, reference, path, options = {}) {
2633
+ const parsed = parseReference(reference);
2634
+ const group = parsed?.group ?? "default";
2635
+ const source = catalogGroupSource(document, group, options);
2636
+ const noun = KIND_NOUNS[kind2];
2637
+ const where = parsed?.group !== void 0 && !catalogGroupDeclared(document, parsed.group) ? `the document declares no catalogs.${parsed.group} group` : group === "custom" ? "it is not in catalogs.custom" : group === "default" && groupsOf(document).default === false ? "it is not in catalogs.custom and catalogs.default is false" : source === void 0 ? `it is not embedded in catalogs.${group === "default" ? "custom or catalogs.default" : group} and no catalog is registered for it` : `it is not embedded in catalogs.${group === "default" ? "custom or catalogs.default" : group} and the catalog registered for ${source} ${registeredCatalog(source, options) ? "has no such record" : "is not registered"}`;
2638
+ const fallback = kind2 === "layouts" ? "automatic" : "engine-default";
2639
+ return {
2640
+ code: "unresolved-reference",
2641
+ kind: kind2,
2642
+ reference,
2643
+ path,
2644
+ group,
2645
+ ...source !== void 0 ? { source } : {},
2646
+ fallback,
2647
+ message: `${noun} '${reference}' resolves nowhere: ${where}; ${fallback === "automatic" ? "the slide composes automatically" : "the engine default is used"}.`
2648
+ };
2649
+ }
2650
+ var pushReference = (sites, kind2, value, path, group) => {
2651
+ if (typeof value === "string" && parseReference(value)) sites.push({ kind: kind2, reference: value, path, ...group !== void 0 ? { group } : {} });
2652
+ };
2653
+ var pushObjectReference = (sites, kind2, value, path, group) => {
2654
+ if (typeof value === "string") pushReference(sites, kind2, value, path, group);
2655
+ else if (isRec(value)) pushReference(sites, kind2, value.id, [...path, "id"], group);
2656
+ };
2657
+ function designSites(sites, design, path) {
2658
+ if (!isRec(design)) return;
2659
+ pushReference(sites, "themes", design.theme, [...path, "theme"]);
2660
+ pushObjectReference(sites, "colorSchemes", design.colorScheme, [...path, "colorScheme"]);
2661
+ pushObjectReference(sites, "fontSchemes", design.fontScheme, [...path, "fontScheme"]);
2662
+ }
2663
+ function recordReferenceSites(kind2, record9, path, group) {
2664
+ const sites = [];
2665
+ if (kind2 === "themes" && isRec(record9)) {
2666
+ pushObjectReference(sites, "colorSchemes", record9.colorScheme, [...path, "colorScheme"], group);
2667
+ pushObjectReference(sites, "fontSchemes", record9.fontScheme, [...path, "fontScheme"], group);
2668
+ }
2669
+ return sites;
2670
+ }
2671
+ function catalogReferenceSites(document, options = {}) {
2672
+ const deck = rec(document);
2673
+ const sites = [];
2674
+ pushReference(sites, "narratives", deck.narrative, ["narrative"]);
2675
+ if (Array.isArray(deck.audience)) deck.audience.forEach((entry, index) => {
2676
+ pushObjectReference(sites, "audiences", entry, ["audience", index]);
2677
+ });
2678
+ else pushObjectReference(sites, "audiences", deck.audience, ["audience"]);
2679
+ pushObjectReference(sites, "purposes", deck.purpose, ["purpose"]);
2680
+ pushObjectReference(sites, "tones", deck.tone, ["tone"]);
2681
+ if (isRec(deck.language)) {
2682
+ pushReference(sites, "fontSchemes", deck.language.fontScheme, ["language", "fontScheme"]);
2683
+ pushReference(sites, "fontSchemes", deck.language.googleFontScheme, ["language", "googleFontScheme"]);
2684
+ }
2685
+ designSites(sites, deck.design, ["design"]);
2686
+ if (options.slides !== false && Array.isArray(deck.slides))
2687
+ deck.slides.forEach((slide, index) => {
2688
+ if (!isRec(slide)) return;
2689
+ if (slide.layout !== "auto") pushReference(sites, "layouts", slide.layout, ["slides", index, "layout"]);
2690
+ designSites(sites, slide.design, ["slides", index, "design"]);
2691
+ });
2692
+ if (options.records !== false)
2693
+ for (const [group, value] of Object.entries(groupsOf(document))) {
2694
+ if (!isRec(value)) continue;
2695
+ for (const kind2 of catalogKinds)
2696
+ for (const [id, record9] of Object.entries(rec(value[kind2]))) sites.push(...recordReferenceSites(kind2, record9, ["catalogs", group, kind2, id], group));
2697
+ }
2698
+ return sites;
2699
+ }
2700
+ var dottedPath = (path) => path.join(".");
2701
+ var pointerPath = (path) => path.length ? `/${path.map((part) => String(part).replaceAll("~", "~0").replaceAll("/", "~1")).join("/")}` : "";
2702
+ function catalogRecords(document, kind2, options = {}) {
2703
+ checkCatalogsOption(options.catalogs, "catalogRecords");
2704
+ const result = [];
2705
+ const seen = /* @__PURE__ */ new Set();
2706
+ const add = (entry) => {
2707
+ if (seen.has(entry.reference)) return;
2708
+ seen.add(entry.reference);
2709
+ result.push(entry);
2710
+ };
2711
+ const groups = groupsOf(document);
2712
+ const names = [.../* @__PURE__ */ new Set(["custom", "default", ...Object.keys(groups)])];
2713
+ for (const group of names) {
2714
+ if (group === "default" && groups.default === false) continue;
2715
+ if (group !== "custom" && group !== "default" && !isRec(groups[group])) continue;
2716
+ const prefix = group === "custom" || group === "default" ? "" : `${group}:`;
2717
+ for (const id of Object.keys(rec(rec(groups[group])[kind2]))) {
2718
+ const found = lookupInGroup(document, kind2, group, id, `${prefix}${id}`, options);
2719
+ if (found) add(found);
2720
+ }
2721
+ if (group === "custom") continue;
2722
+ const hosted = registeredCatalog(catalogGroupSource(document, group, options), options)?.[kind2];
2723
+ for (const id of Object.keys(hosted ?? {})) {
2724
+ const found = lookupInGroup(document, kind2, group, id, `${prefix}${id}`, options);
2725
+ if (found) add(found);
2726
+ }
2727
+ }
2728
+ return result;
2729
+ }
2730
+ function embeddedCopy(record9) {
2731
+ return Object.fromEntries(Object.entries(rec(record9)).filter(([key]) => key !== "$schema" && key !== "id" && !key.startsWith("x-")).map(([key, value]) => [key, structuredClone(value)]));
2732
+ }
2733
+
2155
2734
  // src/generated/engine-data.ts
2156
2735
  var engineDefaultsSource = {
2157
2736
  "theme": {
@@ -2198,10 +2777,10 @@ var SOCIAL_PLATFORMS = engineVocabulariesSource.socialPlatforms;
2198
2777
  var LANGUAGES = engineVocabulariesSource.languages;
2199
2778
 
2200
2779
  // src/design-records.ts
2201
- var isRec = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2202
- var rec = (value) => isRec(value) ? value : {};
2780
+ var isRec2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2781
+ var rec2 = (value) => isRec2(value) ? value : {};
2203
2782
  function resolveRecordReference(document, kind2, reference, path, fallback, options, diagnostics) {
2204
- const object2 = isRec(reference) ? reference : void 0;
2783
+ const object2 = isRec2(reference) ? reference : void 0;
2205
2784
  const id = typeof reference === "string" ? reference : typeof object2?.id === "string" ? object2.id : void 0;
2206
2785
  if (id === void 0) return { record: { ...fallback, ...object2 } };
2207
2786
  const found = resolveReference(document, kind2, id, options);
@@ -2210,27 +2789,27 @@ function resolveRecordReference(document, kind2, reference, path, fallback, opti
2210
2789
  }
2211
2790
  function resolveDesignRecords(document, slideIndex, options = {}) {
2212
2791
  checkCatalogsOption(options.catalogs, "resolveDesignRecords");
2213
- const deck = rec(document);
2792
+ const deck = rec2(document);
2214
2793
  const slides = Array.isArray(deck.slides) ? deck.slides : [];
2215
- const own2 = slideIndex === void 0 ? {} : rec(rec(slides[slideIndex]).design);
2216
- const shared = rec(deck.design);
2217
- const design = { ...shared, ...own2 };
2794
+ const own3 = slideIndex === void 0 ? {} : rec2(rec2(slides[slideIndex]).design);
2795
+ const shared = rec2(deck.design);
2796
+ const design = { ...shared, ...own3 };
2218
2797
  const slidePath = `slides.${slideIndex}.design`;
2219
2798
  const diagnostics = [];
2220
- const themePath = own2.theme !== void 0 ? `${slidePath}.theme` : "design.theme";
2799
+ const themePath = own3.theme !== void 0 ? `${slidePath}.theme` : "design.theme";
2221
2800
  const themeFound = typeof design.theme === "string" ? resolveReference(document, "themes", design.theme, options) : void 0;
2222
2801
  if (typeof design.theme === "string" && !themeFound) diagnostics.push(unresolvedReference(document, "themes", design.theme, themePath, options));
2223
2802
  const theme = themeFound ? { ...themeFound.record } : { ...ENGINE_DEFAULT_THEME };
2224
2803
  const inTheme = { ...options, ...themeFound ? { group: themeFound.group } : {} };
2225
2804
  const inThemePath = (key) => themeFound?.origin === "document" ? `catalogs.${themeFound.group}.themes.${themeFound.id}.${key}` : themePath;
2226
2805
  const colorFromDesign = design.colorScheme !== void 0;
2227
- const colorSchemePath = own2.colorScheme !== void 0 ? `${slidePath}.colorScheme` : shared.colorScheme !== void 0 ? "design.colorScheme" : inThemePath("colorScheme");
2806
+ const colorSchemePath = own3.colorScheme !== void 0 ? `${slidePath}.colorScheme` : shared.colorScheme !== void 0 ? "design.colorScheme" : inThemePath("colorScheme");
2228
2807
  const color = resolveRecordReference(document, "colorSchemes", colorFromDesign ? design.colorScheme : theme.colorScheme, colorFromDesign ? colorSchemePath : inThemePath("colorScheme"), ENGINE_DEFAULT_COLOR_SCHEME, colorFromDesign ? options : inTheme, diagnostics);
2229
2808
  const fontFromDesign = design.fontScheme !== void 0;
2230
- const fontSchemePath = own2.fontScheme !== void 0 ? `${slidePath}.fontScheme` : shared.fontScheme !== void 0 ? "design.fontScheme" : inThemePath("fontScheme");
2809
+ const fontSchemePath = own3.fontScheme !== void 0 ? `${slidePath}.fontScheme` : shared.fontScheme !== void 0 ? "design.fontScheme" : inThemePath("fontScheme");
2231
2810
  const font = resolveRecordReference(document, "fontSchemes", fontFromDesign ? design.fontScheme : theme.fontScheme, fontSchemePath, ENGINE_DEFAULT_FONT_SCHEME, fontFromDesign ? options : inTheme, diagnostics);
2232
2811
  const fontReference = fontFromDesign ? design.fontScheme : theme.fontScheme;
2233
- const fontSchemeReference = typeof fontReference === "string" ? fontReference : isRec(fontReference) && typeof fontReference.id === "string" ? fontReference.id : void 0;
2812
+ const fontSchemeReference = typeof fontReference === "string" ? fontReference : isRec2(fontReference) && typeof fontReference.id === "string" ? fontReference.id : void 0;
2234
2813
  const provenance = {
2235
2814
  ...themeFound ? { theme: provenanceOf(themeFound) } : {},
2236
2815
  ...color.provenance ? { colorScheme: color.provenance } : {},
@@ -2551,11 +3130,11 @@ function listNumbers(items, numbering) {
2551
3130
  const object2 = isObject(item) ? item : void 0;
2552
3131
  const level = object2?.level === void 0 ? 0 : object2.level;
2553
3132
  if (typeof level !== "number" || !Number.isInteger(level) || level < 0) throw new RangeError("List levels must be nonnegative integers.");
2554
- const own2 = object2?.start;
2555
- 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}.`);
3133
+ const own3 = object2?.start;
3134
+ if (own3 !== void 0 && (typeof own3 !== "number" || !Number.isInteger(own3) || own3 < 1 || own3 > MAX_NUMBERING_VALUE)) throw new RangeError(`A list item start must be an integer from 1 to ${MAX_NUMBERING_VALUE}.`);
2556
3135
  const { style: authored, start, suffix } = numberingAtLevel(levels, level);
2557
3136
  const previous = counters[level];
2558
- const value = own2 ?? (previous === void 0 ? start : previous + 1);
3137
+ const value = own3 ?? (previous === void 0 ? start : previous + 1);
2559
3138
  counters[level] = value;
2560
3139
  counters.length = level + 1;
2561
3140
  const adapted = !numberingStyleDraws(authored, value);
@@ -3624,8 +4203,8 @@ function codeSyntaxPalette(theme = {}, options = {}) {
3624
4203
  return palette;
3625
4204
  }
3626
4205
  function codeSyntaxPaletteForScheme(scheme, options = {}) {
3627
- const record7 = scheme && typeof scheme === "object" ? scheme : {};
3628
- const pick = (role, slot, fallback) => normalize(record7[role]) ?? normalize(record7[slot]) ?? fallback;
4206
+ const record9 = scheme && typeof scheme === "object" ? scheme : {};
4207
+ const pick = (role, slot, fallback) => normalize(record9[role]) ?? normalize(record9[slot]) ?? fallback;
3629
4208
  return codeSyntaxPalette({ primary: pick("primary", "accent1", "#2563EB"), secondary: pick("secondary", "accent2", "#0F766E"), accent: pick("accent", "accent3", "#F59E0B") }, options);
3630
4209
  }
3631
4210
 
@@ -3777,8 +4356,8 @@ var blend = (from, to, amount) => {
3777
4356
  return toHex(a.map((value, index) => value + (b[index] - value) * amount));
3778
4357
  };
3779
4358
  function codeHighlightColors(scheme, palette = codeSyntaxPaletteForScheme(scheme)) {
3780
- const record7 = scheme && typeof scheme === "object" ? scheme : {};
3781
- const primary = normalize(record7.primary) ?? normalize(record7.accent1) ?? "#2563EB";
4359
+ const record9 = scheme && typeof scheme === "object" ? scheme : {};
4360
+ const primary = normalize(record9.primary) ?? normalize(record9.accent1) ?? "#2563EB";
3782
4361
  const [hue, saturation] = toHsl(primary);
3783
4362
  const tint = fromHsl(hue, Math.min(saturation, 0.7), 0.45);
3784
4363
  const band = blend(CODE_PANEL_BACKGROUND, tint, CODE_HIGHLIGHT_BAND_TINT);
@@ -3975,7 +4554,7 @@ var CAPTION_FONT_RATIO = 0.6;
3975
4554
  var CAPTION_MAX_RATIO = 0.35;
3976
4555
  var FOOTNOTE_MAX_RATIO = 0.35;
3977
4556
  var CAPTIONABLE_FIELDS = Object.freeze(["image", "chart", "table", "video"]);
3978
- var record5 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
4557
+ var record6 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
3979
4558
  var isRecord3 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
3980
4559
  var round = (value) => Math.round(value * 1e6) / 1e6 || value;
3981
4560
  var regionKey = /^(top|middle|bottom|left|center|right)([+:]|$)/;
@@ -3983,7 +4562,7 @@ var TEXT_FIELDS = ["text", "items", "bullets"];
3983
4562
  var HEADING_FIELDS = ["tag", "title", "subtitle"];
3984
4563
  function annotationText(value) {
3985
4564
  if (typeof value === "string") return value;
3986
- if (Array.isArray(value)) return value.map((run) => typeof run === "string" ? run : record5(run).text ?? "").join("");
4565
+ if (Array.isArray(value)) return value.map((run) => typeof run === "string" ? run : record6(run).text ?? "").join("");
3987
4566
  if (isRecord3(value) && value.text !== void 0) return annotationText(value.text);
3988
4567
  return value === void 0 || value === null ? "" : String(value);
3989
4568
  }
@@ -4015,7 +4594,7 @@ function walkCitationRuns(slide, basePath, visit) {
4015
4594
  });
4016
4595
  };
4017
4596
  const host = (node, path, depth) => {
4018
- const payload = record5(node);
4597
+ const payload = record6(node);
4019
4598
  if (Array.isArray(payload.blocks)) {
4020
4599
  if (depth > 32) return;
4021
4600
  payload.blocks.forEach((block, index) => {
@@ -4030,7 +4609,7 @@ function walkCitationRuns(slide, basePath, visit) {
4030
4609
  }
4031
4610
  if (isRecord3(payload.quote)) runs(payload.quote.text, `${path}.quote.text`);
4032
4611
  };
4033
- const value = record5(slide);
4612
+ const value = record6(slide);
4034
4613
  for (const field of HEADING_FIELDS) runs(value[field], `${basePath}.${field}`);
4035
4614
  const regions = Object.keys(value).filter((key) => regionKey.test(key)).sort();
4036
4615
  if (regions.length) {
@@ -4047,7 +4626,7 @@ function walkCitationRuns(slide, basePath, visit) {
4047
4626
  }
4048
4627
  var citationMarkerText = (numbers) => numbers.join(",");
4049
4628
  function referenceList(presentation) {
4050
- const list = record5(presentation).references;
4629
+ const list = record6(presentation).references;
4051
4630
  return Array.isArray(list) ? list.filter((item) => isRecord3(item) && typeof item.id === "string") : [];
4052
4631
  }
4053
4632
  function numberSlide(slide, slideIndex, references, numbering) {
@@ -4080,7 +4659,7 @@ function numberSlide(slide, slideIndex, references, numbering) {
4080
4659
  }
4081
4660
  function collectCitations(presentation) {
4082
4661
  const references = referenceList(presentation), numbering = { notes: [], byId: /* @__PURE__ */ new Map() }, slides = /* @__PURE__ */ new Map();
4083
- const list = record5(presentation).slides;
4662
+ const list = record6(presentation).slides;
4084
4663
  if (Array.isArray(list)) list.forEach((slide, index) => {
4085
4664
  const result = numberSlide(slide, index, references, numbering);
4086
4665
  if (result) slides.set(index, result);
@@ -4090,7 +4669,7 @@ function collectCitations(presentation) {
4090
4669
  }
4091
4670
  function slideCitations(slide, slideIndex, presentation) {
4092
4671
  const references = referenceList(presentation), numbering = { notes: [], byId: /* @__PURE__ */ new Map() };
4093
- const list = record5(presentation).slides;
4672
+ const list = record6(presentation).slides;
4094
4673
  if (Array.isArray(list)) for (let index = 0; index < Math.min(slideIndex, list.length); index += 1) numberSlide(list[index], index, references, numbering);
4095
4674
  return numberSlide(slide, slideIndex, references, numbering);
4096
4675
  }
@@ -4153,12 +4732,39 @@ function referencesSlide(presentation, options = {}) {
4153
4732
  return { title, items };
4154
4733
  }
4155
4734
 
4735
+ // src/layout-content.ts
4736
+ var LAYOUT_BODY_KINDS = ["text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
4737
+ var record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
4738
+ function layoutStructure(layout) {
4739
+ if (!isLayoutTemplate(layout)) return "";
4740
+ return templateAreas(layout).map((entry) => entry.region ? `${entry.name} (${entry.region.flow}: ${entry.region.accepts.join(", ")})` : entry.name).join(", ");
4741
+ }
4742
+ function layoutContent(layout) {
4743
+ const areas = isLayoutTemplate(layout) ? templateAreas(layout) : [];
4744
+ const regions = areas.flatMap((entry) => entry.region ? [entry.region] : []);
4745
+ const lead = regions.find((region) => region.role === "primary") ?? regions[0];
4746
+ const leadKind = lead?.accepts.find((kind2) => kind2 !== "group");
4747
+ const title = areas.some((entry) => entry.name === "title");
4748
+ return { kind: leadKind ?? "title", count: regions.length, heading: { title, subtitle: title || areas.some((entry) => entry.name === "subtitle"), tag: title } };
4749
+ }
4750
+ function templateAreas(layout) {
4751
+ const value = record7(layout), regions = record7(value.regions);
4752
+ const rows3 = Array.isArray(value.areas) ? value.areas.filter((row) => typeof row === "string") : [];
4753
+ const seen = /* @__PURE__ */ new Set(), out = [];
4754
+ for (const row of rows3) for (const name of row.trim().split(/\s+/)) {
4755
+ if (!name || name === "." || seen.has(name)) continue;
4756
+ seen.add(name);
4757
+ out.push(name === "title" || name === "subtitle" || !Object.hasOwn(regions, name) ? { name } : { name, region: layoutRegion(name, regions[name]) });
4758
+ }
4759
+ return out;
4760
+ }
4761
+
4156
4762
  // src/composition.ts
4157
4763
  var MAX_COMPOSITION_DEPTH = 32;
4158
4764
  var FALLBACK_CODE_FAMILY = "Roboto Mono";
4159
4765
  var DEFAULT_FONT_FAMILIES = { heading: String(ENGINE_DEFAULT_FONT_SCHEME.major), body: String(ENGINE_DEFAULT_FONT_SCHEME.minor) };
4160
4766
  function resolveFontFamilies(input) {
4161
- const scheme = record6(input);
4767
+ const scheme = record8(input);
4162
4768
  const family = (value) => typeof value === "string" && value ? value : void 0;
4163
4769
  const accent = family(scheme.accent);
4164
4770
  return {
@@ -4229,12 +4835,6 @@ function translateTextFit(fit, dy) {
4229
4835
  }
4230
4836
  };
4231
4837
  }
4232
- var FIELD_KINDS = { text: "text", bullets: "text", items: "list", image: "image", video: "video", chart: "chart", table: "table", code: "code", metric: "metric", quote: "quote", timeline: "timeline" };
4233
- function chartPrimaryLayout(side, kinds) {
4234
- const first = side === "left" || side === "top";
4235
- const group = { type: "group", composition: {}, placeholders: kinds.map((type) => ({ type })) };
4236
- return { composition: { mode: side === "left" || side === "right" ? "row" : "column", weights: first ? [3, 2] : [2, 3] }, placeholders: first ? [{ type: "chart" }, group] : [group, { type: "chart" }] };
4237
- }
4238
4838
  var OPFCompositionError = class extends Error {
4239
4839
  constructor(diagnostics, explanation) {
4240
4840
  super("Slide content does not fit its composition.");
@@ -4250,11 +4850,11 @@ var fields = ["text", "items", "bullets", "image", "video", "chart", "table", "c
4250
4850
  var headings = /* @__PURE__ */ new Set(["title", "subtitle", "tag"]);
4251
4851
  var rows2 = ["top", "middle", "bottom"];
4252
4852
  var columns = ["left", "center", "right"];
4253
- var record6 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
4853
+ var record8 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
4254
4854
  var kind = (field) => field === "items" ? "list" : field === "bullets" ? "text" : field;
4255
4855
  var round2 = (value) => Math.round(value * 1e6) / 1e6 || value;
4256
4856
  var PLACEMENT_BAND = 0.5;
4257
- var IMAGE_EDGES = ["left", "right", "top", "bottom"];
4857
+ var IMAGE_EDGES2 = ["left", "right", "top", "bottom"];
4258
4858
  var IMAGE_FITS = ["cover", "contain", "stretch"];
4259
4859
  var BACKGROUND_FITS = ["cover", "contain", "stretch", "tile"];
4260
4860
  var IMAGE_SOURCE = /^(asset:|https:\/\/|data:|\.\/|\.\.\/)/;
@@ -4269,7 +4869,7 @@ var pathNumber = (value) => String(round2(value));
4269
4869
  var IMAGE_SHAPES = { rectangle: "rect", rounded: "roundRect", circle: "ellipse", hexagon: "hexagon" };
4270
4870
  var roundBox = (box) => ({ x: round2(box.x), y: round2(box.y), width: round2(box.width), height: round2(box.height) });
4271
4871
  var imageFocus = (value) => {
4272
- const focus = record6(value), x = finite(focus.x, 0, 1), y = finite(focus.y, 0, 1);
4872
+ const focus = record8(value), x = finite(focus.x, 0, 1), y = finite(focus.y, 0, 1);
4273
4873
  return x !== void 0 && y !== void 0 ? { x, y } : { x: 0.5, y: 0.5 };
4274
4874
  };
4275
4875
  function imageShape(kind2, box, cornerRadius = 1 / 6) {
@@ -4310,7 +4910,7 @@ function fitImage(frame, fit, aspect, focus = { x: 0.5, y: 0.5 }) {
4310
4910
  }
4311
4911
  function imageBackground(value) {
4312
4912
  if (typeof value === "string") return IMAGE_SOURCE.test(value) ? { src: value, fit: "cover", focus: { x: 0.5, y: 0.5 } } : void 0;
4313
- const background = record6(value);
4913
+ const background = record8(value);
4314
4914
  if (background.type !== "image" || typeof background.src !== "string" || !background.src) return void 0;
4315
4915
  const opacity = finite(background.opacity, 0, 1);
4316
4916
  return {
@@ -4325,13 +4925,13 @@ function imageBackground(value) {
4325
4925
  }
4326
4926
  function composeRecolor(value) {
4327
4927
  if (value === "grayscale") return { type: "grayscale" };
4328
- const duotone = record6(value);
4928
+ const duotone = record8(value);
4329
4929
  return duotone.dark !== void 0 && duotone.light !== void 0 ? { type: "duotone", dark: duotone.dark, light: duotone.light } : void 0;
4330
4930
  }
4331
4931
  function composeOverlay(value, frame, shape, path, mirrorSide, diagnostics) {
4332
- const overlay = record6(value), opacity = finite(overlay.opacity, 0, 1);
4932
+ const overlay = record8(value), opacity = finite(overlay.opacity, 0, 1);
4333
4933
  if (overlay.color === void 0 || opacity === void 0) return void 0;
4334
- const edge = IMAGE_EDGES.includes(overlay.edge) ? mirrorSide(overlay.edge) : void 0;
4934
+ const edge = IMAGE_EDGES2.includes(overlay.edge) ? mirrorSide(overlay.edge) : void 0;
4335
4935
  if (edge && shape.kind !== "rectangle") {
4336
4936
  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." });
4337
4937
  return void 0;
@@ -4354,7 +4954,7 @@ function composeImage(host, hostPath, region, frameArea, context) {
4354
4954
  const focus = imageFocus(host.focus);
4355
4955
  const shape = imageShape(kindName, box, finite(host.cornerRadius, 0, 0.5));
4356
4956
  const result = { region: roundBox(region), box, fit, focus, shape };
4357
- const border = record6(host.border), borderWidth = finite(border.width, 0, 64);
4957
+ const border = record8(host.border), borderWidth = finite(border.width, 0, 64);
4358
4958
  if (border.color !== void 0 && borderWidth) result.border = { color: border.color, width: round2(borderWidth * scale) };
4359
4959
  const opacity = finite(host.opacity, 0, 1);
4360
4960
  if (opacity !== void 0 && opacity < 1) result.opacity = opacity;
@@ -4368,8 +4968,8 @@ function composeImage(host, hostPath, region, frameArea, context) {
4368
4968
  return result;
4369
4969
  }
4370
4970
  function resolveBackgroundImage(slide, presentation, themeBackground, width, height, path, mirrorSide, diagnostics) {
4371
- const own2 = record6(slide.design), deck = record6(record6(presentation).design);
4372
- const [value, at3] = own2.background !== void 0 ? [own2.background, `${path}.design.background`] : deck.background !== void 0 ? [deck.background, "design.background"] : [themeBackground, "theme"];
4971
+ const own3 = record8(slide.design), deck = record8(record8(presentation).design);
4972
+ const [value, at3] = own3.background !== void 0 ? [own3.background, `${path}.design.background`] : deck.background !== void 0 ? [deck.background, "design.background"] : [themeBackground, "theme"];
4373
4973
  const background = imageBackground(value);
4374
4974
  if (!background) return void 0;
4375
4975
  const box = { x: 0, y: 0, width, height };
@@ -4379,7 +4979,7 @@ function resolveBackgroundImage(slide, presentation, themeBackground, width, hei
4379
4979
  if (recolor) result.recolor = recolor;
4380
4980
  const overlay = composeOverlay(background.overlay, box, imageShape("rectangle", box), `${at3}.overlay`, mirrorSide, diagnostics);
4381
4981
  if (overlay) result.overlay = overlay;
4382
- const aspect = background.fit === "tile" ? void 0 : intrinsicImageAspect(background.src, record6(presentation).assets);
4982
+ const aspect = background.fit === "tile" ? void 0 : intrinsicImageAspect(background.src, record8(presentation).assets);
4383
4983
  if (aspect) result.picture = fitImage(box, background.fit, aspect, background.focus);
4384
4984
  return result;
4385
4985
  }
@@ -4410,8 +5010,8 @@ function breaksInsideWord(text2, fit) {
4410
5010
  });
4411
5011
  }
4412
5012
  function layoutFurniture(input, options = {}) {
4413
- const slide = record6(input), width = options.width ?? 1280, height = options.height ?? 720, scale = Math.min(width, height) / 720;
4414
- const settings = { ...record6(record6(options.layout).composition), ...record6(slide.composition) };
5013
+ const slide = record8(input), width = options.width ?? 1280, height = options.height ?? 720, scale = Math.min(width, height) / 720;
5014
+ const settings = { ...record8(record8(options.layout).composition), ...record8(slide.composition) };
4415
5015
  assertComposition(settings);
4416
5016
  const furnitureRtl = (options.direction ?? resolveSlideDirection(options.presentation, options.slideIndex)) === "rtl";
4417
5017
  const minimum = snapFontSizeUp((settings.minFontSize ?? 16) * scale), size = gridFontSize(13 * scale, minimum), padding = (options.textRasterPadding ?? 2) * scale;
@@ -4423,13 +5023,13 @@ function layoutFurniture(input, options = {}) {
4423
5023
  if (options.date !== void 0 && (typeof options.date !== "string" || !parseIsoDate(options.date))) throw new RangeError("The furniture date option must be an ISO YYYY-MM-DD calendar date.");
4424
5024
  const outlines = options.textMeasurement?.outlineBounds !== void 0, parts = [], diagnostics = [];
4425
5025
  const sourceRoot = `slides.${options.slideIndex ?? 0}`, organizations = Array.isArray(options.presentation?.organization) ? options.presentation.organization : [options.presentation?.organization];
4426
- const primaryIndex = organizations.findIndex((item) => record6(item).role === "primary"), organizationIndex2 = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
4427
- const organization = record6(organizations[organizationIndex2]), organizationRoot = Array.isArray(options.presentation?.organization) ? `organization.${organizationIndex2}` : "organization";
5026
+ const primaryIndex = organizations.findIndex((item) => record8(item).role === "primary"), organizationIndex2 = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
5027
+ const organization = record8(organizations[organizationIndex2]), organizationRoot = Array.isArray(options.presentation?.organization) ? `organization.${organizationIndex2}` : "organization";
4428
5028
  const fontFamily = options.fontFamilies?.body ?? "sans-serif";
4429
5029
  let headerBottom = 0, footerTop = height, configured = false;
4430
5030
  const error = (path, message, code = "text-overflow") => diagnostics.push({ code, path, message });
4431
5031
  for (const kind2 of ["header", "footer"]) {
4432
- const local = record6(slide.design)[kind2] !== void 0, value = local ? record6(slide.design)[kind2] : options.presentation?.design?.[kind2];
5032
+ const local = record8(slide.design)[kind2] !== void 0, value = local ? record8(slide.design)[kind2] : options.presentation?.design?.[kind2];
4433
5033
  if (value === void 0 || value === false) continue;
4434
5034
  const root = local ? `${sourceRoot}.design.${kind2}` : `design.${kind2}`;
4435
5035
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Header/footer content must be an object or false.");
@@ -4437,7 +5037,7 @@ function layoutFurniture(input, options = {}) {
4437
5037
  const zones = [];
4438
5038
  for (const [index, zone] of ["left", "center", "right"].entries()) {
4439
5039
  const side = furnitureRtl && zone !== "center" ? zone === "left" ? "right" : "left" : zone;
4440
- const content = record6(record6(value)[zone]), path = `${root}.${zone}`, x = width * (0.07 + (furnitureRtl ? 2 - index : index) * 0.3), zoneWidth = width * 0.26;
5040
+ const content = record8(record8(value)[zone]), path = `${root}.${zone}`, x = width * (0.07 + (furnitureRtl ? 2 - index : index) * 0.3), zoneWidth = width * 0.26;
4441
5041
  const pending = [];
4442
5042
  const add = (field, text2, generated = false, sourcePath, extras = {}) => {
4443
5043
  if (text2 === void 0) return;
@@ -4446,7 +5046,7 @@ function layoutFurniture(input, options = {}) {
4446
5046
  pending.push({ type: "text", field, text: text2, generated, sourcePath: sourcePath ?? (!generated ? partPath : void 0), extras, partPath, style: resolveTextStyle({ fontFamily, fontWeight: 400, italic: false, path: partPath }, options.textMeasurement) });
4447
5047
  };
4448
5048
  const addImage = (source, sourcePath, reference) => {
4449
- const imageHeight = Math.max(32 * scale, Math.min(height * 0.05, 72 * scale)), imageWidth = Math.min(zoneWidth, imageHeight * (intrinsicImageAspect(source, record6(options.presentation).assets) ?? 1));
5049
+ const imageHeight = Math.max(32 * scale, Math.min(height * 0.05, 72 * scale)), imageWidth = Math.min(zoneWidth, imageHeight * (intrinsicImageAspect(source, record8(options.presentation).assets) ?? 1));
4450
5050
  pending.push({ type: "image", sourcePath, image: source, ...reference !== void 0 ? { reference } : {}, width: imageWidth, height: imageHeight });
4451
5051
  };
4452
5052
  if (content.image !== void 0) {
@@ -4465,7 +5065,7 @@ function layoutFurniture(input, options = {}) {
4465
5065
  add("text", resolved.text, false, void 0, { fields: resolved.fields });
4466
5066
  } else add("text", content.text);
4467
5067
  if (content.socials === true) {
4468
- const links = Object.entries(record6(organization.socials)).filter(([, value2]) => typeof value2 === "string" && value2.trim()).map(([platform, value2]) => ({ platform, sourcePath: `${organizationRoot}.socials.${platform}`, ...resolveSocialProfile(platform, value2, "organization") }));
5068
+ const links = Object.entries(record8(organization.socials)).filter(([, value2]) => typeof value2 === "string" && value2.trim()).map(([platform, value2]) => ({ platform, sourcePath: `${organizationRoot}.socials.${platform}`, ...resolveSocialProfile(platform, value2, "organization") }));
4469
5069
  if (links.length) add("socials", links.map((link) => link.text).join("\n"), true, `${organizationRoot}.socials`, { links });
4470
5070
  else error(`${path}.socials`, "Generated social profiles need a primary organization with socials.", "unresolved-content");
4471
5071
  }
@@ -4572,11 +5172,22 @@ function layoutFurniture(input, options = {}) {
4572
5172
  var textSegments = new Intl.Segmenter("und", { granularity: "grapheme" });
4573
5173
  var WRAP_TOLERANCE = 0.01;
4574
5174
  var HANGING_SPACE = /[^\S\r\n\u00a0\u202f\ufeff]/u;
5175
+ var SCRIPT_WIDTH_FACTORS = [
5176
+ [/\p{Script=Tamil}/u, 1.53],
5177
+ [/\p{Script=Malayalam}/u, 1.76],
5178
+ [/\p{Script=Sinhala}/u, 1.44],
5179
+ [/\p{Script=Myanmar}/u, 1.18],
5180
+ [/\p{Script=Ethiopic}/u, 1.13],
5181
+ [/\p{Script=Georgian}/u, 1.28]
5182
+ ];
4575
5183
  function measureText(text2, fontSize) {
4576
5184
  let units = 0;
4577
5185
  for (const character of text2) {
4578
- if (/\p{Mark}|\u200d|\ufe0f/u.test(character)) continue;
4579
- units += character === " " ? 0.32 : /[A-Z0-9]/.test(character) ? 0.62 : character.codePointAt(0) > 11904 ? 1 : 0.54;
5186
+ if (/\p{Mn}|\p{Me}|\u200d|\ufe0f/u.test(character)) continue;
5187
+ if (/\p{Mc}/u.test(character) && /\p{Script=Latin}|\p{Script=Han}|\p{Script=Hangul}|\p{Script=Hiragana}|\p{Script=Katakana}/u.test(character)) continue;
5188
+ const base = character === " " ? 0.32 : /[A-Z0-9]/.test(character) ? 0.62 : character.codePointAt(0) > 11904 ? 1 : 0.54;
5189
+ const factor = SCRIPT_WIDTH_FACTORS.find(([script]) => script.test(character))?.[1] ?? 1;
5190
+ units += base * factor;
4580
5191
  }
4581
5192
  return units * fontSize;
4582
5193
  }
@@ -5067,19 +5678,19 @@ function fitSourceText(text2, box, size, minimum, step, measure, prose = false,
5067
5678
  const layout = (fontSize) => {
5068
5679
  const tabWidth = measure(" ", fontSize) * 4;
5069
5680
  if (!Number.isFinite(tabWidth) || text2.includes(" ") && tabWidth <= 0) throw new RangeError("Text tabs require a positive finite measured space advance.");
5070
- const measureLine = (start2, end2, record7 = false) => {
5681
+ const measureLine = (start2, end2, record9 = false) => {
5071
5682
  let x = 0, offset = start2;
5072
5683
  const segments = [];
5073
5684
  for (const [index, segment2] of text2.slice(start2, end2).split(" ").entries()) {
5074
5685
  if (index) {
5075
5686
  const next = (Math.floor(x / tabWidth + 1e-9) + 1) * tabWidth;
5076
- if (record7) segments.push({ kind: "tab", start: offset, end: offset + 1, x, width: next - x });
5687
+ if (record9) segments.push({ kind: "tab", start: offset, end: offset + 1, x, width: next - x });
5077
5688
  x = next;
5078
5689
  offset++;
5079
5690
  }
5080
5691
  if (segment2) {
5081
5692
  const advance = measure(segment2, fontSize);
5082
- if (record7) segments.push({ kind: "text", start: offset, end: offset + segment2.length, x, width: advance });
5693
+ if (record9) segments.push({ kind: "text", start: offset, end: offset + segment2.length, x, width: advance });
5083
5694
  x += advance;
5084
5695
  offset += segment2.length;
5085
5696
  }
@@ -5436,12 +6047,12 @@ function fitList(input, box, requestedSize = 25, minFontSize = 16, options = { s
5436
6047
  function contentText(field, value) {
5437
6048
  if (field === "text" || headings.has(field)) return flatten(value);
5438
6049
  if (field === "items" || field === "bullets") return (Array.isArray(value) ? value : [value]).map((item) => {
5439
- const entry = record6(item);
6050
+ const entry = record8(item);
5440
6051
  return `\u2022 ${flatten(item)}${entry.description ? `
5441
6052
  ${flatten(entry.description)}` : ""}`;
5442
6053
  }).join("\n");
5443
- if (field === "code") return flatten(record6(value).source ?? value);
5444
- if (field === "quote") return flatten(record6(value).text ?? value);
6054
+ if (field === "code") return flatten(record8(value).source ?? value);
6055
+ if (field === "quote") return flatten(record8(value).text ?? value);
5445
6056
  return void 0;
5446
6057
  }
5447
6058
  function layoutTable(value, box, options = {}) {
@@ -5512,7 +6123,7 @@ function flatten(value) {
5512
6123
  if (value == null) return "";
5513
6124
  if (typeof value !== "object") return String(value);
5514
6125
  if (Array.isArray(value)) return value.map(flatten).join("");
5515
- const item = record6(value);
6126
+ const item = record8(value);
5516
6127
  return flatten(item.text ?? item.value ?? item.source ?? JSON.stringify(value));
5517
6128
  }
5518
6129
  function regionParts(key) {
@@ -5567,16 +6178,43 @@ function assertComposition(value) {
5567
6178
  if (value.weights !== void 0 && (!Array.isArray(value.weights) || !value.weights.length || value.weights.length > 12 || value.weights.some((weight) => !Number.isFinite(weight) || weight <= 0 || weight > 100))) throw new RangeError("Invalid composition.weights.");
5568
6179
  if (value.overflow !== void 0 && !["warn", "error"].includes(value.overflow)) throw new RangeError("Invalid composition.overflow.");
5569
6180
  }
6181
+ var LAYOUT_MASTER = /* @__PURE__ */ Symbol("opf.layoutMaster");
6182
+ function mergeListColumns(columns2) {
6183
+ const fits = columns2.map((column) => column.text), first = fits[0];
6184
+ const directions = fits.flatMap((fit) => fit.directions ?? []);
6185
+ return { ...first, listEntries: fits.flatMap((fit) => fit.listEntries), lines: fits.flatMap((fit) => fit.lines), height: Math.max(...fits.map((fit) => fit.height)), overflow: fits.some((fit) => fit.overflow), ...first.directions ? { directions } : {} };
6186
+ }
6187
+ function composeLayoutAreas(layout, options = {}) {
6188
+ const template = layoutTemplate(layout), source = record8(layout);
6189
+ const kept = { ...source, regions: Object.fromEntries(Object.entries(record8(source.regions)).map(([name, value]) => [name, { ...record8(value), empty: "keep" }])) };
6190
+ const { mirror, bleed = true, placements = [], ...compose } = options;
6191
+ const slide = {
6192
+ ...template.title ? { title: "Title", subtitle: "Subtitle" } : {},
6193
+ ...placements.length ? { blocks: placements.map((placement) => ({ image: "https://example.invalid/placeholder.png", placement: { ...placement } })) } : {},
6194
+ ...mirror !== void 0 ? { design: { mirror } } : {}
6195
+ };
6196
+ const result = composeSlide(slide, { ...compose, layout: kept, [LAYOUT_MASTER]: true });
6197
+ const areas = template.areas.map((area) => {
6198
+ if (area.heading) {
6199
+ const found = result.headingAreas?.find((entry) => entry.name === area.name);
6200
+ return { name: area.name, heading: true, box: found ? { ...found.box } : { x: 0, y: 0, width: 0, height: 0 }, ...found?.parts ? { parts: found.parts } : {} };
6201
+ }
6202
+ const region = result.regions.find((entry) => entry.name === area.name);
6203
+ return { name: area.name, heading: false, box: { ...!bleed && region.areaBox ? region.areaBox : region.box } };
6204
+ });
6205
+ return { contentBox: { ...result.contentBox }, areas };
6206
+ }
5570
6207
  function composeSlide(input, options = {}) {
5571
- const slide = record6(input), layout = record6(options.layout);
6208
+ const slide = record8(input), layout = record8(options.layout);
5572
6209
  const width = options.width ?? 1280, height = options.height ?? 720;
5573
6210
  if (![width, height].every((value) => Number.isFinite(value) && value > 0)) throw new RangeError("Canvas dimensions must be finite and positive.");
5574
6211
  const scale = Math.min(width, height) / 720;
5575
6212
  const deckDirection = options.direction ?? resolveSlideDirection(options.presentation, options.slideIndex);
5576
6213
  const rtl = deckDirection === "rtl", textDirection = rtl ? "rtl" : void 0;
5577
- const hints = resolveDesignHints({ slide, layout, presentation: options.presentation, slideIndex: options.slideIndex, deck: { titleAlignment: options.titleAlignment, contentAlignment: options.contentAlignment, contentBox: options.contentBox } });
6214
+ const template = isLayoutTemplate(layout) ? layoutTemplate(layout) : void 0;
6215
+ const hints = resolveDesignHints({ slide, layout, theme: { design: options.themeDesign }, presentation: options.presentation, slideIndex: options.slideIndex, deck: { titleAlignment: options.titleAlignment, contentAlignment: options.contentAlignment, contentBox: options.contentBox } });
5578
6216
  const hasCards = hints.contentBox ?? false;
5579
- const composition = { ...record6(layout.composition), ...record6(slide.composition) };
6217
+ const composition = { ...record8(layout.composition), ...record8(slide.composition) };
5580
6218
  assertComposition(composition);
5581
6219
  const padding = (composition.padding ?? 0.08) * Math.min(width, height);
5582
6220
  const gap = (composition.gap ?? 1 / 30) * Math.min(width, height);
@@ -5657,17 +6295,15 @@ function composeSlide(input, options = {}) {
5657
6295
  const mirrorSide = (side) => !rtl ? side : side === "left" ? "right" : side === "right" ? "left" : side;
5658
6296
  const backgroundImage = resolveBackgroundImage(slide, options.presentation, options.themeBackground, width, height, path, mirrorSide, imageDiagnostics);
5659
6297
  const regions = Object.keys(slide).filter((key) => regionParts(key)).sort();
5660
- const assets = record6(options.presentation).assets;
6298
+ const assets = record8(options.presentation).assets;
5661
6299
  const imageContext = (placement) => ({ fit: hints.imageFit, scale, mirrorSide, diagnostics: imageDiagnostics, assets, ...placement ? { placement } : {} });
5662
6300
  const area = { left: 0, top: 0, right: width, bottom: height };
5663
- const imagePlaceholders = layoutLeaves(layout).flatMap((leaf) => leaf.type === "image" ? [{ placeholder: leaf.placeholder, path: leaf.path, depth: leaf.depth }] : []);
5664
- const topImages = regions.length ? [] : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => !Array.isArray(record6(block).blocks) && record6(block).image !== void 0 ? [{ host: record6(block), hostPath: `${path}.blocks.${index}`, block: index }] : []) : slide.image !== void 0 ? [{ host: { type: "image", image: slide.image }, hostPath: path }] : [];
6301
+ const topImages = regions.length ? [] : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => !Array.isArray(record8(block).blocks) && record8(block).image !== void 0 ? [{ host: record8(block), hostPath: `${path}.blocks.${index}`, block: index }] : []) : slide.image !== void 0 ? [{ host: { type: "image", image: slide.image }, hostPath: path }] : [];
5665
6302
  const placed = [], usedEdges = /* @__PURE__ */ new Set();
5666
- topImages.forEach((node, order) => {
5667
- const slot = imagePlaceholders[order];
5668
- const own2 = node.block !== void 0 && node.host.placement !== void 0 ? record6(node.host.placement) : void 0;
5669
- const value = own2 ?? (slot?.depth === 0 && slot.placeholder.placement !== void 0 ? record6(slot.placeholder.placement) : void 0);
5670
- if (!value || !IMAGE_EDGES.includes(value.edge)) return;
6303
+ topImages.forEach((node) => {
6304
+ const own3 = node.block !== void 0 && node.host.placement !== void 0 ? record8(node.host.placement) : void 0;
6305
+ const value = own3;
6306
+ if (!value || !IMAGE_EDGES2.includes(value.edge)) return;
5671
6307
  const edge = mirrorSide(value.edge);
5672
6308
  if (usedEdges.has(edge)) return;
5673
6309
  usedEdges.add(edge);
@@ -5679,8 +6315,8 @@ function composeSlide(input, options = {}) {
5679
6315
  else if (edge === "right") area.right = region.x;
5680
6316
  else if (edge === "top") area.top += band;
5681
6317
  else area.bottom = region.y;
5682
- const placement = { edge, size, inset: value.inset === true, path: own2 ? `${node.hostPath}.placement` : `${slot.path}.placement` };
5683
- placed.push({ ...node, placement, region, slot: order });
6318
+ const placement = { edge, size, inset: value.inset === true, path: `${node.hostPath}.placement` };
6319
+ placed.push({ ...node, placement, region });
5684
6320
  });
5685
6321
  const placedBlocks = new Set(placed.flatMap((entry) => entry.block !== void 0 ? [entry.block] : []));
5686
6322
  const placedRoot = placed.some((entry) => entry.block === void 0);
@@ -5696,17 +6332,16 @@ function composeSlide(input, options = {}) {
5696
6332
  diagnostics.push(...footnotes.diagnostics);
5697
6333
  bodyBottom = footnotes.box.y - gap * 0.5;
5698
6334
  }
5699
- const layoutPlaceholders = Array.isArray(layout.placeholders) ? layout.placeholders : [];
5700
6335
  const hasLayoutRecord = options.layout !== void 0 && options.layout !== null && typeof options.layout === "object";
5701
- const headingOnlyLayout = layoutPlaceholders.length > 0 && layoutPlaceholders.every((placeholder) => headings.has(placeholder.type ?? "") || placeholder.type === "image" && typeof placeholder.placement === "object" && placeholder.placement !== null);
5702
6336
  const emptyPayload = (value) => value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
5703
6337
  const emptyHost = (host) => emptyPayload(host.blocks) && fields.every((field) => emptyPayload(host[field]));
5704
6338
  const flowBlocks = Array.isArray(slide.blocks) ? slide.blocks.filter((_, index) => !placedBlocks.has(index)) : slide.blocks;
5705
- const hasBodyPayload = regions.some((key) => !emptyHost(record6(slide[key]))) || !emptyPayload(flowBlocks) || fields.some((field) => !(placedRoot && field === "image") && !emptyPayload(slide[field]));
5706
- const isCover = !hasBodyPayload && (headingOnlyLayout || !hasLayoutRecord);
6339
+ const hasBodyPayload = regions.some((key) => !emptyHost(record8(slide[key]))) || !emptyPayload(flowBlocks) || fields.some((field) => !(placedRoot && field === "image") && !emptyPayload(slide[field]));
6340
+ const useTemplate = template !== void 0 && !regions.length;
6341
+ const isCover = !hasBodyPayload && (useTemplate || !hasLayoutRecord);
5707
6342
  coverGroup = isCover;
5708
6343
  let logo;
5709
- if (isCover) {
6344
+ if (isCover && options[LAYOUT_MASTER] !== true) {
5710
6345
  const resolved = resolveLogo(options.presentation, slide, { shape: "full", onDark: options.darkBackground, slideIndex: options.slideIndex });
5711
6346
  if (resolved) {
5712
6347
  const logoHeight = 56 * scale;
@@ -5717,7 +6352,7 @@ function composeSlide(input, options = {}) {
5717
6352
  }
5718
6353
  let y = logo ? logo.box.y + logo.box.height + gap : headingTop;
5719
6354
  const headingItems = [];
5720
- for (const field of ["tag", "title", "subtitle"]) {
6355
+ for (const field of useTemplate ? [] : ["tag", "title", "subtitle"]) {
5721
6356
  if (!slide[field] || Array.isArray(slide[field]) && !annotationText(slide[field])) continue;
5722
6357
  const requested = (field === "title" ? 54 : field === "tag" ? 16 : 25) * scale;
5723
6358
  const maxHeight = Math.max(height * (field === "title" ? 0.26 : field === "subtitle" ? 0.12 : 0.045), minSize * 1.22 + 2 * rasterPadding);
@@ -5769,7 +6404,7 @@ function composeSlide(input, options = {}) {
5769
6404
  const collect = (host, basePath, depth = 0, ancestors = []) => {
5770
6405
  if (Array.isArray(host.blocks)) {
5771
6406
  if (depth >= MAX_COMPOSITION_DEPTH || ancestors.includes(host)) throw new RangeError(`Content groups must be acyclic and nest at most ${MAX_COMPOSITION_DEPTH} levels.`);
5772
- const settings = record6(host.composition);
6407
+ const settings = record8(host.composition);
5773
6408
  assertComposition(settings);
5774
6409
  return [{
5775
6410
  field: "blocks",
@@ -5778,7 +6413,7 @@ function composeSlide(input, options = {}) {
5778
6413
  path: basePath,
5779
6414
  payload: host,
5780
6415
  composition: settings,
5781
- children: host.blocks.flatMap((block, index) => collect(record6(block), `${basePath}.blocks.${index}`, depth + 1, [...ancestors, host]))
6416
+ children: host.blocks.flatMap((block, index) => collect(record8(block), `${basePath}.blocks.${index}`, depth + 1, [...ancestors, host]))
5782
6417
  }];
5783
6418
  }
5784
6419
  const captioned = host.caption !== void 0 ? fields.filter((field) => host[field] !== void 0 && CAPTIONABLE_FIELDS.includes(field)) : [];
@@ -5788,27 +6423,27 @@ function composeSlide(input, options = {}) {
5788
6423
  type: host.type ?? kind(field),
5789
6424
  value: fieldValue(field),
5790
6425
  path: `${basePath}.${field}`,
5791
- payload: field === "image" ? imagePayload(host) : { type: host.type ?? kind(field), [field]: fieldValue(field), ...host.numbering !== void 0 && (field === "items" || field === "bullets") ? { numbering: host.numbering } : {} },
6426
+ payload: field === "image" ? imagePayload(host) : { type: host.type ?? kind(field), [field]: fieldValue(field), ...host.numbering !== void 0 && (field === "items" || field === "bullets") ? { numbering: host.numbering } : {}, ...host.columns !== void 0 && (field === "items" || field === "bullets") ? { columns: host.columns } : {} },
5792
6427
  ...field === "image" ? { host, hostPath: basePath } : {},
5793
6428
  ...captioned.length === 1 && captioned[0] === field ? { caption: host.caption, captionPath: `${basePath}.caption` } : {}
5794
6429
  }));
5795
6430
  };
5796
6431
  const regionsInReadingOrder = visualReadingOrder(regions.map((key) => ({ key, box: regionBox(regionParts(key), contentBox, gap) }))).map((entry) => entry.key);
5797
- const pending = regions.length ? regionsInReadingOrder.flatMap((key) => collect(record6(slide[key]), `${path}.${key}`).map((item) => ({ ...item, region: regionParts(key) }))) : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => placedBlocks.has(index) ? [] : collect(record6(block), `${path}.blocks.${index}`)) : collect(placedRoot ? { ...slide, image: void 0 } : slide, path);
6432
+ const pending = regions.length ? regionsInReadingOrder.flatMap((key) => collect(record8(slide[key]), `${path}.${key}`).map((item) => ({ ...item, region: regionParts(key) }))) : Array.isArray(slide.blocks) ? slide.blocks.flatMap((block, index) => placedBlocks.has(index) ? [] : collect(record8(block), `${path}.blocks.${index}`)) : collect(placedRoot ? { ...slide, image: void 0 } : slide, path);
5798
6433
  const groups = [], flows = [];
5799
6434
  const decisions = options.explain ? [] : void 0;
5800
- const inheritedSettings = (parent, own2 = {}) => ({
6435
+ const inheritedSettings = (parent, own3 = {}) => ({
5801
6436
  minFontSize: parent.minFontSize,
5802
- ...own2,
5803
- overflow: parent.overflow === "error" ? "error" : own2.overflow ?? parent.overflow
6437
+ ...own3,
6438
+ overflow: parent.overflow === "error" ? "error" : own3.overflow ?? parent.overflow
5804
6439
  });
5805
6440
  const inset = (box, settings) => {
5806
6441
  const amount = (settings.padding ?? 0) * Math.min(box.width, box.height);
5807
6442
  return { x: box.x + amount, y: box.y + amount, width: box.width - amount * 2, height: box.height - amount * 2 };
5808
6443
  };
5809
6444
  const acceptedBox = (box) => ({ x: round2(box.x), y: round2(box.y), width: round2(box.width), height: round2(box.height) });
5810
- const payloadBox = (box) => {
5811
- if (!hasCards) return box;
6445
+ const payloadBox = (box, cards = hasCards) => {
6446
+ if (!cards) return box;
5812
6447
  const frame = acceptedBox(box), padding2 = Math.min(12 * scale, frame.width / 4, frame.height / 4);
5813
6448
  return acceptedBox({ x: frame.x + padding2, y: frame.y + padding2, width: frame.width - 2 * padding2, height: frame.height - 2 * padding2 });
5814
6449
  };
@@ -5892,24 +6527,13 @@ function composeSlide(input, options = {}) {
5892
6527
  };
5893
6528
  const scoreNode = (node, box, settings, penalties) => {
5894
6529
  if (!node.children) return leafScore(node, box, settings, penalties);
5895
- const own2 = inheritedSettings(settings, node.composition), area2 = inset(box, own2), slotCount = Math.max(node.children.length, node.reserved ?? 0);
5896
- const cols = defaultColumns(slotCount, area2, own2);
5897
- const boxes = gridBoxes(slotCount, area2, cols, (own2.gap ?? 1 / 30) * Math.min(box.width, box.height), own2.weights ?? [], modeFor(own2) === "column");
5898
- return node.children.reduce((score, child, index) => score + scoreNode(child, boxes[index], own2, penalties), 0);
6530
+ const own3 = inheritedSettings(settings, node.composition), area2 = inset(box, own3), slotCount = Math.max(node.children.length, 0);
6531
+ const cols = defaultColumns(slotCount, area2, own3);
6532
+ const boxes = gridBoxes(slotCount, area2, cols, (own3.gap ?? 1 / 30) * Math.min(box.width, box.height), own3.weights ?? [], modeFor(own3) === "column");
6533
+ return node.children.reduce((score, child, index) => score + scoreNode(child, boxes[index], own3, penalties), 0);
5899
6534
  };
5900
- const slots = [];
5901
- const emptySlots = (entries, boxes, settings) => entries.forEach((entry, index) => {
5902
- const box = boxes[index];
5903
- if (!box) return;
5904
- slots.push({ path: entry.path, type: entry.type, depth: entry.depth, box: acceptedBox(box) });
5905
- if (!entry.children) return;
5906
- const own2 = inheritedSettings(settings, record6(entry.placeholder.composition)), inner = inset(box, own2);
5907
- const cols = defaultColumns(entry.children.length, inner, own2);
5908
- const mirror = (cell) => rtl ? { ...cell, x: inner.x + inner.width - (cell.x - inner.x) - cell.width } : cell;
5909
- emptySlots(entry.children, gridBoxes(entry.children.length, inner, cols, (own2.gap ?? 1 / 30) * Math.min(box.width, box.height), own2.weights ?? [], modeFor(own2) === "column").map(mirror), own2);
5910
- });
5911
- const arrange = (nodes, area2, settings, reserved = 0, gapOverride, containerPath = path, recorded = true, template) => {
5912
- const count = Math.max(nodes.length, reserved);
6535
+ const arrange = (nodes, area2, settings, reserved2 = 0, gapOverride, containerPath = path, recorded = true) => {
6536
+ const count = Math.max(nodes.length, reserved2);
5913
6537
  if (!count) return;
5914
6538
  const mode = modeFor(settings), localGap = (settings.gap ?? 1 / 30) * Math.min(area2.width, area2.height);
5915
6539
  const actualGap = gapOverride ?? (settings === rootSettings ? gap : localGap);
@@ -5920,9 +6544,9 @@ function composeSlide(input, options = {}) {
5920
6544
  let best = Infinity;
5921
6545
  for (let candidate = 1; candidate <= Math.min(count, settings.columns ?? 6); candidate++) {
5922
6546
  const boxes2 = gridBoxes(count, area2, candidate, actualGap, settings.weights ?? [], false);
5923
- const emptySlots2 = (Math.ceil(count / candidate) * candidate - count) * 2;
5924
- const penalties = candidates ? { cellProportions: 0, fontReduction: 0, textOverflow: 0, tableOverflow: 0, smallCells: 0, emptySlots: emptySlots2 } : void 0;
5925
- const score = nodes.reduce((sum, node, i) => sum + scoreNode(node, boxes2[i], settings, penalties), 0) + emptySlots2;
6547
+ const emptySlots = (Math.ceil(count / candidate) * candidate - count) * 2;
6548
+ const penalties = candidates ? { cellProportions: 0, fontReduction: 0, textOverflow: 0, tableOverflow: 0, smallCells: 0, emptySlots } : void 0;
6549
+ const score = nodes.reduce((sum, node, i) => sum + scoreNode(node, boxes2[i], settings, penalties), 0) + emptySlots;
5926
6550
  if (penalties && candidates) candidates.push({ columns: candidate, rows: Math.ceil(count / candidate), score, penalties });
5927
6551
  if (score < best) {
5928
6552
  best = score;
@@ -5940,114 +6564,370 @@ function composeSlide(input, options = {}) {
5940
6564
  const grid = gridGeometry(count, area2, cols, actualGap, settings.weights ?? [], mode === "column");
5941
6565
  const mirrored = (box) => rtl ? { ...box, x: area2.x + area2.width - (box.x - area2.x) - box.width } : box;
5942
6566
  const boxes = grid.boxes.map(mirrored);
5943
- if (template) emptySlots(template.slice(nodes.length), boxes.slice(nodes.length), settings);
5944
6567
  if (recorded && !hasRegions) flows.push({ path: containerPath, box: { ...area2 }, composition: { ...settings }, columns: rtl ? grid.columns.map((track) => ({ offset: area2.width - track.offset - track.size, size: track.size })) : grid.columns, rows: grid.rows, gap: grid.gap, itemCount: nodes.length, slotCount: count });
5945
6568
  nodes.forEach((node, index) => {
5946
- let box = node.region ? mirrored(regionBox(node.region, area2, actualGap)) : boxes[index];
5947
- if (node.slot) slots.push({ path: node.slot.path, type: node.slot.type, depth: node.slot.depth, box: acceptedBox(box), ...node.slot.children ? {} : { content: node.path } });
5948
- if (node.children) {
5949
- const own2 = inheritedSettings(settings, node.composition), inner = inset(box, own2);
5950
- if (!node.synthetic) groups.push({ path: node.path, box, contentBox: inner, composition: own2 });
5951
- arrange(node.children, inner, own2, node.reserved ?? 0, (own2.gap ?? 1 / 30) * Math.min(box.width, box.height), node.path, !node.synthetic, node.slots);
5952
- } else {
5953
- const frameBox = hasCards ? acceptedBox(box) : void 0;
5954
- box = payloadBox(box);
5955
- const caption = captionOf(node, box);
5956
- if (caption) {
5957
- box = caption.mediaBox;
5958
- diagnostics.push(...caption.diagnostics);
6569
+ const box = node.region ? mirrored(regionBox(node.region, area2, actualGap)) : boxes[index];
6570
+ placeNode(node, box, settings);
6571
+ });
6572
+ };
6573
+ let regionTag, templateCell = false;
6574
+ const placeNode = (node, box, settings, cards = hasCards, listColumns) => {
6575
+ if (node.children) {
6576
+ const own3 = inheritedSettings(settings, node.composition), inner = inset(box, own3);
6577
+ if (!node.synthetic) groups.push({ path: node.path, box, contentBox: inner, composition: own3 });
6578
+ arrange(node.children, inner, own3, 0, (own3.gap ?? 1 / 30) * Math.min(box.width, box.height), node.path, !node.synthetic);
6579
+ return;
6580
+ }
6581
+ const frameBox = cards ? acceptedBox(box) : void 0;
6582
+ box = payloadBox(box, cards);
6583
+ const caption = captionOf(node, box);
6584
+ if (caption) {
6585
+ box = caption.mediaBox;
6586
+ diagnostics.push(...caption.diagnostics);
6587
+ }
6588
+ const textValue = contentText(node.field, node.value);
6589
+ const quoteLayout = node.field === "quote" ? measureQuote(node, box, settings) : void 0;
6590
+ const codeLayout = node.field === "code" ? measureCode(node, box, settings) : void 0;
6591
+ const metricLayout = node.field === "metric" ? measureMetric(node, box, settings) : void 0;
6592
+ const timelineLayout = node.field === "timeline" ? measureTimeline(node, box, settings) : void 0;
6593
+ const internal = quoteLayout ?? codeLayout ?? metricLayout ?? timelineLayout, body = internal?.parts.find((part) => part.role === "body" || part.role === "value");
6594
+ const columns2 = textValue !== void 0 && !internal ? listColumnsFor(node, box, settings, listColumns) : void 0;
6595
+ const text2 = internal ? body?.fit : columns2 ? columns2.length > 1 ? mergeListColumns(columns2) : columns2[0].text : textValue !== void 0 ? fitContent(node.field, node.value, textValue, box, 25 * scale, snapFontSizeUp((settings.minFontSize ?? 16) * scale), node.path, node.payload.numbering) : void 0;
6596
+ const image = node.field === "image" ? composeImage(node.host ?? {}, node.hostPath ?? node.path, box, box, imageContext()) : void 0;
6597
+ items.push({
6598
+ path: node.path,
6599
+ field: node.field,
6600
+ type: node.type,
6601
+ value: node.value,
6602
+ payload: node.payload,
6603
+ box: internal ? acceptedBox(box) : box,
6604
+ ...image ? { image } : {},
6605
+ ...frameBox ? { frameBox } : {},
6606
+ text: text2,
6607
+ textStyle: body?.style ?? styleFor(node.field, node.path),
6608
+ composition: settings,
6609
+ alignment: alignmentFor(node.field),
6610
+ ...quoteLayout ? { quoteLayout } : {},
6611
+ ...codeLayout ? { codeLayout } : {},
6612
+ ...metricLayout ? { metricLayout } : {},
6613
+ ...timelineLayout ? { timelineLayout } : {},
6614
+ ...bulletImage && node.payload.numbering === void 0 && (node.field === "items" || node.field === "bullets") ? { bulletImage } : {},
6615
+ ...caption ? { caption } : {},
6616
+ ...regionTag !== void 0 ? { region: regionTag } : {},
6617
+ ...columns2 && columns2.length > 1 ? { listColumns: columns2 } : {}
6618
+ });
6619
+ if (box.width < 100 * scale || !templateCell && box.height < 60 * scale) diagnostics.push({ code: "small-cell", path: node.path, message: "Content cell is too small for comfortable reading; use fewer blocks or a different composition." });
6620
+ };
6621
+ const listColumnsFor = (node, box, settings, regionMode) => {
6622
+ if (node.field !== "items" && node.field !== "bullets") return void 0;
6623
+ const values = node.value;
6624
+ if (!Array.isArray(values) || values.length < 2) return void 0;
6625
+ const own3 = node.payload.columns;
6626
+ const mode = own3 === "auto" || own3 === 1 || own3 === 2 || own3 === 3 ? own3 : regionMode;
6627
+ if (mode === void 0 || mode === 1) return void 0;
6628
+ const start = 25 * scale, floor = snapFontSizeUp((settings.minFontSize ?? 16) * scale);
6629
+ const numbering = node.payload.numbering;
6630
+ const listOptions = { ...richOptions(styleFor(node.field, node.path)), ...numbering !== void 0 ? { numbering } : bulletImage ? { bulletImage } : {} };
6631
+ const columnGap = (count2) => Math.min(gap, box.width / (count2 * 2));
6632
+ const columnBoxes = (count2) => {
6633
+ const between = columnGap(count2), columnWidth = (box.width - between * (count2 - 1)) / count2;
6634
+ const ordered = Array.from({ length: count2 }, (_, index) => ({ x: box.x + index * (columnWidth + between), y: box.y, width: columnWidth, height: box.height }));
6635
+ return rtl ? ordered.map((cell) => ({ ...cell, x: box.x + box.width - (cell.x - box.x) - cell.width })) : ordered;
6636
+ };
6637
+ const chunk = (from, to) => numbering !== void 0 ? sliceNumberedItems(values, numbering, from, to) : values.slice(from, to);
6638
+ const sourcePaths = (index) => {
6639
+ const source = values[index], object2 = source !== null && typeof source === "object" && !Array.isArray(source);
6640
+ return { textPath: `${node.path}.${index}${object2 ? ".text" : ""}`, descriptionPath: `${node.path}.${index}.description` };
6641
+ };
6642
+ const renumber = (fit, from) => ({ ...fit, listEntries: fit.listEntries.map((entry) => ({ ...entry, index: entry.index + from, ...sourcePaths(entry.index + from) })) });
6643
+ const split = (count2, size2, minimum) => {
6644
+ const boxes = columnBoxes(count2);
6645
+ const whole = fitList(values, { ...boxes[0], height: 1e6 }, start, start, listOptions);
6646
+ const first = whole.listEntries[0].textBox.y;
6647
+ const heights = whole.listEntries.map((entry, index) => (whole.listEntries[index + 1]?.textBox.y ?? first + whole.height) - entry.textBox.y);
6648
+ const breaks = [0, ...listColumnBreaks(heights, whole.listEntries.map((entry) => entry.level), count2), values.length];
6649
+ return boxes.slice(0, breaks.length - 1).map((cell, index) => ({ box: cell, start: breaks[index], end: breaks[index + 1], text: renumber(fitList(chunk(breaks[index], breaks[index + 1]), cell, size2, minimum, listOptions), breaks[index]) }));
6650
+ };
6651
+ const quarter = width / 4;
6652
+ const counts = typeof mode === "number" ? [mode] : [2, 3].filter((count2) => (box.width - columnGap(count2) * (count2 - 1)) / count2 >= quarter);
6653
+ if (mode === "auto") {
6654
+ if (!fitList(values, box, start, start, listOptions).overflow) return void 0;
6655
+ for (const count2 of counts) {
6656
+ const columns2 = split(count2, start, start);
6657
+ if (columns2.every((column) => !column.text.overflow)) return columns2;
6658
+ }
6659
+ }
6660
+ const count = counts.at(-1);
6661
+ if (count === void 0) return void 0;
6662
+ const shrunk = split(count, start, floor);
6663
+ const size = Math.min(...shrunk.map((column) => column.text.fontSize));
6664
+ return shrunk.map((column) => ({ ...column, text: renumber(fitList(chunk(column.start, column.end), column.box, size, size, listOptions), column.start) }));
6665
+ };
6666
+ const LONG_LINES = 6, LONG_CODE_LINES = 12, startSize = 25 * scale;
6667
+ const estimatedLines = (value, cellWidth, size) => flatten(value).split("\n").reduce((sum, paragraph) => sum + Math.max(1, wrapText(paragraph, Math.max(1, cellWidth), size).length), 0);
6668
+ const isLong = (node, cellWidth) => {
6669
+ if (node.children) return node.children.some((child) => isLong(child, cellWidth));
6670
+ if (node.field === "text") return estimatedLines(node.value, cellWidth, startSize) > LONG_LINES;
6671
+ if (node.field === "items" || node.field === "bullets") {
6672
+ let lines = 0;
6673
+ for (const entry of Array.isArray(node.value) ? node.value : []) {
6674
+ const object2 = entry !== null && typeof entry === "object" && !Array.isArray(entry) ? entry : void 0;
6675
+ const indent = startSize * 1.1 * (1 + (typeof object2?.level === "number" ? object2.level : 0));
6676
+ lines += estimatedLines(object2 ? object2.text : entry, cellWidth - indent, startSize);
6677
+ if (object2?.description !== void 0) lines += estimatedLines(object2.description, cellWidth - indent, startSize * 0.82);
6678
+ }
6679
+ return lines > LONG_LINES;
6680
+ }
6681
+ if (node.field === "quote") return estimatedLines(typeof node.value === "string" ? node.value : record8(node.value).text, cellWidth, startSize) > LONG_LINES;
6682
+ if (node.field === "table") {
6683
+ const value = record8(node.value);
6684
+ return (Array.isArray(value.rows) ? value.rows.length + (Array.isArray(value.columns) ? 1 : 0) : 0) > LONG_LINES;
6685
+ }
6686
+ if (node.field === "code") return String(typeof node.value === "string" ? node.value : record8(node.value).source ?? "").split("\n").length > LONG_CODE_LINES;
6687
+ return false;
6688
+ };
6689
+ const naturalHeight = (node, cellWidth, cards) => {
6690
+ const pad = cards ? 2 * Math.min(12 * scale, cellWidth / 4) : 0, inner = Math.max(scale, cellWidth - pad);
6691
+ if (node.children) return node.children.reduce((sum, child) => sum + naturalHeight(child, cellWidth, false), 0) + gap * Math.max(0, node.children.length - 1) + pad;
6692
+ let content;
6693
+ if (node.field === "text" || node.field === "items" || node.field === "bullets") {
6694
+ const fit = fitContent(node.field, node.value, contentText(node.field, node.value) ?? "", { x: 0, y: 0, width: inner, height: 1e6 }, startSize, startSize, node.path, node.payload.numbering);
6695
+ content = "height" in fit && typeof fit.height === "number" ? fit.height : fit.lines.length * fit.lineHeight;
6696
+ } else if (node.field === "quote") content = estimatedLines(typeof node.value === "string" ? node.value : record8(node.value).text, inner, 32 * scale) * 32 * 1.22 * scale + 2 * 20 * 1.22 * scale;
6697
+ else if (node.field === "code") content = String(typeof node.value === "string" ? node.value : record8(node.value).source ?? "").split("\n").length * 18 * 1.4 * scale + 24 * scale;
6698
+ else if (node.field === "metric") content = 150 * scale;
6699
+ else if (node.field === "timeline") content = 170 * scale;
6700
+ else if (node.field === "table") {
6701
+ const value = record8(node.value);
6702
+ content = ((Array.isArray(value.rows) ? value.rows.length : 4) + 1) * 36 * scale;
6703
+ } else content = inner / 1.6;
6704
+ return content + (node.caption !== void 0 ? 32 * scale : 0) + pad;
6705
+ };
6706
+ const templateRegions = [], headingAreas = [];
6707
+ const requestedTemplateGap = gap;
6708
+ const composeTemplate = () => {
6709
+ const plan2 = template, frame = contentBox;
6710
+ const binding = bindRegions(slide, layout, { slideIndex: options.slideIndex ?? 0 });
6711
+ for (const entry of binding.diagnostics) diagnostics.push({ code: entry.code, path: entry.path, message: entry.message, ...entry.region !== void 0 ? { region: entry.region } : {} });
6712
+ const unitOf = (bound) => {
6713
+ const host = bound.block !== void 0 ? record8(slide.blocks[bound.block]) : { ...Object.fromEntries((bound.fields ?? []).map((field) => [field, slide[field]])), ...Object.fromEntries(["type", "caption", "numbering"].filter((key) => slide[key] !== void 0).map((key) => [key, slide[key]])) };
6714
+ const parts = collect(host, bound.block !== void 0 ? `${path}.blocks.${bound.block}` : path);
6715
+ return parts.length === 1 ? parts[0] : { field: "blocks", type: "group", value: parts.map((part) => part.payload), path: bound.path, payload: {}, children: parts, composition: { mode: "column" }, synthetic: true };
6716
+ };
6717
+ const contents = new Map(binding.regions.map((entry) => [entry.name, [...entry.blocks, ...entry.overflow].map(unitOf)]));
6718
+ const BELOW = "(below)";
6719
+ const belowUnits = binding.below.map(unitOf);
6720
+ const belowRegion = { name: BELOW, accepts: [], role: "supporting", flow: "auto", max: belowUnits.length, bleed: false, listColumns: 1, anchor: "top", empty: "collapse" };
6721
+ const unitsOf = (name) => name === BELOW ? belowUnits : contents.get(name) ?? [];
6722
+ const shown = (field) => !!slide[field] && !(Array.isArray(slide[field]) && !annotationText(slide[field]));
6723
+ const titleFields = ["tag", "title", ...plan2.subtitle ? [] : ["subtitle"]].filter(shown);
6724
+ const subtitleFields = plan2.subtitle && shown("subtitle") ? ["subtitle"] : [];
6725
+ const columnCount = plan2.columns.length;
6726
+ const cells = plan2.grid.map((row) => [...row]);
6727
+ const rowSizes = [...plan2.rows];
6728
+ const implicitTitle = !plan2.title && titleFields.length > 0;
6729
+ if (implicitTitle) {
6730
+ cells.unshift(Array.from({ length: columnCount }, () => "title"));
6731
+ rowSizes.unshift("auto");
6732
+ }
6733
+ if (belowUnits.length) {
6734
+ cells.push(Array.from({ length: columnCount }, () => BELOW));
6735
+ rowSizes.push("auto");
6736
+ }
6737
+ const gap2 = Math.max(0, Math.min(requestedTemplateGap, frame.width / (columnCount * 2), frame.height / (rowSizes.length * 2)));
6738
+ const regionOf = new Map(plan2.regions.map((region) => [region.name, region]));
6739
+ const empty2 = /* @__PURE__ */ new Set();
6740
+ for (const region of plan2.regions) if (!unitsOf(region.name).length && region.empty !== "keep") empty2.add(region.name);
6741
+ if (plan2.title && !titleFields.length) empty2.add("title");
6742
+ if (plan2.subtitle && !subtitleFields.length) empty2.add("subtitle");
6743
+ const collapsed = collapseAreas(cells, empty2, (name) => name === "title" || name === "subtitle", (name) => name !== BELOW);
6744
+ const rects = areaRects(collapsed.grid), ownRects = areaRects(cells);
6745
+ const widths = columnWidths(plan2.columns, frame.width, gap2);
6746
+ const columnX = [];
6747
+ widths.reduce((x, size) => {
6748
+ columnX.push(x);
6749
+ return x + size + gap2;
6750
+ }, 0);
6751
+ const spanWidth = (rect) => widths.slice(rect.column, rect.column + rect.columnSpan).reduce((a, b) => a + b, 0) + gap2 * (rect.columnSpan - 1);
6752
+ const headingItemsAt = (fields2, x, y2, areaWidth) => {
6753
+ const list = [];
6754
+ let top = y2;
6755
+ for (const field of fields2) {
6756
+ const requested = (field === "title" ? 54 : field === "tag" ? 16 : 25) * scale;
6757
+ const maxHeight = Math.max(height * (field === "title" ? 0.26 : field === "subtitle" ? 0.12 : 0.045), minSize * 1.22 + 2 * rasterPadding);
6758
+ const box = { x, y: top, width: areaWidth, height: maxHeight };
6759
+ const text2 = fitPlacedText(field, slide[field], annotationText(slide[field]), box, requested, minSize, `${path}.${field}`);
6760
+ box.height = Math.min(maxHeight, Math.max("richLines" in text2 ? text2.height : text2.lines.length * text2.lineHeight, text2.placement?.height ?? 0));
6761
+ list.push({ 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) });
6762
+ top += box.height + gap2 * 0.5;
6763
+ }
6764
+ return list;
6765
+ };
6766
+ const groupHeight = (list) => list.length ? list.at(-1).box.y + list.at(-1).box.height - list[0].box.y : 0;
6767
+ const arrangementOf = (region, units, cell) => {
6768
+ if (direction !== void 0 && region.flow !== "none") return direction === "horizontal" ? "row" : "column";
6769
+ const flow = region.flow === "none" && units.length > 1 ? "auto" : region.flow;
6770
+ if (flow === "none" || flow === "column") return "column";
6771
+ if (flow === "grid") return "grid";
6772
+ const shape = gridFlowShape(units.length, cell.width >= cell.height);
6773
+ const cards = hasCards && !region.bleed;
6774
+ const cellWidth = (cell.width - gap2 * (shape.columns - 1)) / shape.columns - (cards ? 2 * Math.min(12 * scale, cell.width / 4) : 0);
6775
+ return units.some((unit) => isLong(unit, cellWidth)) ? "column" : "grid";
6776
+ };
6777
+ const regionNeed = (name, areaWidth) => {
6778
+ const units = unitsOf(name), region = name === BELOW ? belowRegion : regionOf.get(name);
6779
+ if (!units.length) return region.empty === "keep" ? 2 * startSize * 1.22 + (hasCards && !region.bleed ? 2 * Math.min(12 * scale, areaWidth / 4) : 0) : 0;
6780
+ const shape = flowShape(arrangementOf(region, units, { width: areaWidth, height: areaWidth / 4 }), units.length, true);
6781
+ const cellWidth = (areaWidth - gap2 * (shape.columns - 1)) / shape.columns, cards = hasCards && !region.bleed;
6782
+ let total = 0, index = 0;
6783
+ for (const count of shape.perRow) {
6784
+ let row = 0;
6785
+ for (let k = 0; k < count; k++) row = Math.max(row, naturalHeight(units[index++], cellWidth, cards));
6786
+ total += row;
6787
+ }
6788
+ return total + gap2 * Math.max(0, shape.rows - 1);
6789
+ };
6790
+ const areaNeed = (name, rect) => name === "title" ? groupHeight(headingItemsAt(titleFields, 0, 0, spanWidth(rect))) : name === "subtitle" ? groupHeight(headingItemsAt(subtitleFields, 0, 0, spanWidth(rect))) : regionNeed(name, spanWidth(rect));
6791
+ const demands = rowSizes.map((size, row) => {
6792
+ let need = 0, heading = false, below = false;
6793
+ for (const [name, rect] of rects) {
6794
+ if (size === "auto" ? rect.row !== row || rect.rowSpan !== 1 : row < rect.row || row >= rect.row + rect.rowSpan) continue;
6795
+ if (size !== "auto" && rect.rowSpan > 1 && rowSizes.slice(rect.row, rect.row + rect.rowSpan).some((entry) => entry === "auto")) continue;
6796
+ const value = areaNeed(name, rect) / rect.rowSpan;
6797
+ if (value > need) {
6798
+ need = value;
6799
+ heading = name === "title" || name === "subtitle";
6800
+ below = name === BELOW;
5959
6801
  }
5960
- const textValue = contentText(node.field, node.value);
5961
- const quoteLayout = node.field === "quote" ? measureQuote(node, box, settings) : void 0;
5962
- const codeLayout = node.field === "code" ? measureCode(node, box, settings) : void 0;
5963
- const metricLayout = node.field === "metric" ? measureMetric(node, box, settings) : void 0;
5964
- const timelineLayout = node.field === "timeline" ? measureTimeline(node, box, settings) : void 0;
5965
- const internal = quoteLayout ?? codeLayout ?? metricLayout ?? timelineLayout, body = internal?.parts.find((part) => part.role === "body" || part.role === "value");
5966
- 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;
5967
- const image = node.field === "image" ? composeImage(node.host ?? {}, node.hostPath ?? node.path, box, box, imageContext()) : void 0;
5968
- items.push({
5969
- path: node.path,
5970
- field: node.field,
5971
- type: node.type,
5972
- value: node.value,
5973
- payload: node.payload,
5974
- box: internal ? acceptedBox(box) : box,
5975
- ...image ? { image } : {},
5976
- ...frameBox ? { frameBox } : {},
5977
- text: text2,
5978
- textStyle: body?.style ?? styleFor(node.field, node.path),
5979
- composition: settings,
5980
- alignment: alignmentFor(node.field),
5981
- ...quoteLayout ? { quoteLayout } : {},
5982
- ...codeLayout ? { codeLayout } : {},
5983
- ...metricLayout ? { metricLayout } : {},
5984
- ...timelineLayout ? { timelineLayout } : {},
5985
- ...bulletImage && node.payload.numbering === void 0 && (node.field === "items" || node.field === "bullets") ? { bulletImage } : {},
5986
- ...caption ? { caption } : {}
5987
- });
5988
- if (box.width < 100 * scale || box.height < 60 * scale) diagnostics.push({ code: "small-cell", path: node.path, message: "Content cell is too small for comfortable reading; use fewer blocks or a different composition." });
5989
6802
  }
6803
+ return { size, need, kind: heading ? "heading" : below ? "below" : "body" };
5990
6804
  });
6805
+ const heights = allocateRows(demands, frame.height, gap2);
6806
+ const rowY = [];
6807
+ heights.reduce((y2, size, row) => {
6808
+ rowY.push(size > 0 || !heights.slice(0, row).some((above) => above > 0) ? y2 : y2 - gap2);
6809
+ return size > 0 ? y2 + size + gap2 : y2;
6810
+ }, 0);
6811
+ const logical = (rect) => {
6812
+ const last = rect.row + rect.rowSpan - 1, y2 = frame.y + rowY[rect.row];
6813
+ return { x: frame.x + columnX[rect.column], y: y2, width: spanWidth(rect), height: Math.max(0, frame.y + rowY[last] + heights[last] - y2) };
6814
+ };
6815
+ const flip = hints.mirror === true !== rtl;
6816
+ const physical = (cell) => flip ? { ...cell, x: frame.x + frame.width - (cell.x - frame.x) - cell.width } : cell;
6817
+ const bleed = (cell) => {
6818
+ const near = (a, b) => Math.abs(a - b) < 0.01;
6819
+ const left = near(cell.x, frame.x) ? area.left : cell.x, top = near(cell.y, frame.y) ? area.top : cell.y;
6820
+ const right = near(cell.x + cell.width, frame.x + frame.width) ? area.right : cell.x + cell.width;
6821
+ const bottom = near(cell.y + cell.height, frame.y + frame.height) ? area.bottom : cell.y + cell.height;
6822
+ return { x: left, y: top, width: right - left, height: bottom - top };
6823
+ };
6824
+ const placeHeadings = (name, fields2) => {
6825
+ const rect = rects.get(name), original = ownRects.get(name);
6826
+ if (!rect) {
6827
+ if (original) headingAreas.push({ name, box: roundBox(physical(logical(original))), collapsed: true });
6828
+ return;
6829
+ }
6830
+ const cell = physical(logical(rect));
6831
+ const list = headingItemsAt(fields2, cell.x, cell.y, cell.width);
6832
+ const centred = !rowSizes.slice(rect.row, rect.row + rect.rowSpan).every((size) => size === "auto");
6833
+ const shift = centred ? Math.max(0, (cell.height - groupHeight(list)) / 2) : 0;
6834
+ for (const item of list) {
6835
+ if (shift) {
6836
+ item.box.y += shift;
6837
+ if (item.text) item.text = translateTextFit(item.text, shift);
6838
+ }
6839
+ if (furniture && item.box.y + item.box.height > bodyBottom + 0.01) diagnostics.push({ code: "text-overflow", path: item.path, message: "Repeated furniture leaves too little room for this heading. Change the header/footer or slide design." });
6840
+ items.push(item);
6841
+ }
6842
+ let parts;
6843
+ const upper = list.filter((item) => item.field !== "subtitle"), lower = list.find((item) => item.field === "subtitle");
6844
+ if (name === "title" && !plan2.subtitle && list.length) {
6845
+ const bottom = cell.y + cell.height, last = upper.at(-1);
6846
+ const split = Math.min(bottom, lower ? lower.box.y : last.box.y + last.box.height + gap2 * 0.5);
6847
+ const titleBottom = Math.max(cell.y, last ? last.box.y + last.box.height : split - gap2 * 0.5);
6848
+ parts = { title: roundBox({ x: cell.x, y: cell.y, width: cell.width, height: titleBottom - cell.y }), subtitle: roundBox({ x: cell.x, y: split, width: cell.width, height: Math.max(0, bottom - split) }) };
6849
+ }
6850
+ headingAreas.push({ name, box: roundBox(cell), ...name === "title" && implicitTitle ? { implicit: true } : {}, ...parts ? { parts } : {} });
6851
+ };
6852
+ placeHeadings("title", titleFields);
6853
+ if (plan2.subtitle) placeHeadings("subtitle", subtitleFields);
6854
+ const slideComposition = record8(slide.composition);
6855
+ const overridden = ["mode", "columns", "weights"].some((key) => slideComposition[key] !== void 0) ? plan2.regions.find((region) => region.role === "primary" && region.flow !== "none")?.name : void 0;
6856
+ const settings = { ...composition };
6857
+ const placeRegion = (region, units, area2) => {
6858
+ regionTag = region.name === BELOW ? void 0 : region.name;
6859
+ const cell = { ...area2, width: Math.max(scale, area2.width), height: Math.max(scale, area2.height) };
6860
+ templateCell = true;
6861
+ try {
6862
+ const cards = hasCards && !region.bleed;
6863
+ if (region.name === overridden) {
6864
+ arrange(units, cell, { ...settings, mode: slideComposition.mode ?? "auto" }, 0, gap2, path, true);
6865
+ return "composition";
6866
+ }
6867
+ const arrangement = arrangementOf(region, units, cell);
6868
+ let boxes = flowCells(flowShape(arrangement, units.length, cell.width >= cell.height), cell, gap2).cells;
6869
+ if (arrangement === "column" && region.anchor !== "top" && units.every((unit) => !unit.children && (unit.field === "text" || unit.field === "items" || unit.field === "bullets"))) {
6870
+ const naturals = units.map((unit) => naturalHeight(unit, cell.width, cards) + 2 * rasterPadding + scale);
6871
+ const used = naturals.reduce((a, b) => a + b, 0) + gap2 * (units.length - 1);
6872
+ if (used < cell.height) {
6873
+ let y2 = cell.y + (region.anchor === "middle" ? (cell.height - used) / 2 : cell.height - used);
6874
+ boxes = naturals.map((size) => {
6875
+ const next = { x: cell.x, y: y2, width: cell.width, height: size };
6876
+ y2 += size + gap2;
6877
+ return next;
6878
+ });
6879
+ }
6880
+ }
6881
+ if (rtl) boxes = boxes.map((box) => ({ ...box, x: cell.x + cell.width - (box.x - cell.x) - box.width }));
6882
+ units.forEach((unit, index) => {
6883
+ placeNode(unit, boxes[index], settings, cards, region.listColumns);
6884
+ });
6885
+ return arrangement;
6886
+ } finally {
6887
+ regionTag = void 0;
6888
+ templateCell = false;
6889
+ }
6890
+ };
6891
+ for (const region of plan2.regions) {
6892
+ const units = unitsOf(region.name), bound = binding.regions.find((entry) => entry.name === region.name);
6893
+ const rect = rects.get(region.name);
6894
+ let cell = physical(logical(rect ?? ownRects.get(region.name)));
6895
+ const areaBox = region.bleed && rect ? roundBox(cell) : void 0;
6896
+ if (region.bleed && rect) cell = bleed(cell);
6897
+ const arrangement = units.length && rect ? placeRegion(region, units, cell) : void 0;
6898
+ templateRegions.push({
6899
+ name: region.name,
6900
+ box: roundBox(cell),
6901
+ accepts: [...region.accepts],
6902
+ role: region.role,
6903
+ flow: region.flow,
6904
+ max: region.max,
6905
+ anchor: region.anchor,
6906
+ ...arrangement ? { arrangement } : {},
6907
+ content: bound.blocks.map((block) => block.path),
6908
+ ...bound.overflow.length ? { overflow: bound.overflow.map((block) => block.path) } : {},
6909
+ ...collapsed.joined.has(region.name) ? { collapsed: true } : {},
6910
+ ...region.bleed ? { bleed: true } : {},
6911
+ ...areaBox ? { areaBox } : {}
6912
+ });
6913
+ }
6914
+ if (belowUnits.length) placeRegion(belowRegion, belowUnits, physical(logical(rects.get(BELOW))));
5991
6915
  };
5992
- const placeholders = Array.isArray(layout.placeholders) ? layout.placeholders.filter((p) => !headings.has(p.type)) : [];
5993
- const placedSlots = new Set(placed.flatMap((entry) => imagePlaceholders[entry.slot] ? [imagePlaceholders[entry.slot].placeholder] : []));
5994
- if (placedSlots.size) {
5995
- for (let index = placeholders.length - 1; index >= 0; index--) if (placedSlots.has(placeholders[index])) placeholders.splice(index, 1);
5996
- }
5997
- const ownMode = record6(slide.composition).mode;
6916
+ const ownMode = record8(slide.composition).mode;
5998
6917
  const direction = hints.contentDirection;
5999
6918
  const directionMode = direction === "vertical" ? "column" : direction === "horizontal" ? "row" : "auto";
6000
6919
  const chartHint = hints.chartPrimary;
6001
6920
  const chartSide = chartHint === "left" || chartHint === "right" || chartHint === "top" || chartHint === "bottom" ? chartHint : void 0;
6002
6921
  const chartIndex = pending.findIndex((node) => !node.children && node.field === "chart");
6003
- const chartPrimary = chartSide !== void 0 && !ownMode && !regions.length && chartIndex >= 0 && pending.some((node) => node.children || node.field !== "chart") ? chartSide : void 0;
6004
- const kindOf = (node) => node.children ? node.children[0] ? kindOf(node.children[0]) : "text" : FIELD_KINDS[node.field] ?? "text";
6005
- const sugar = chartPrimary ? chartPrimaryLayout(chartPrimary, pending.filter((_, index) => index !== chartIndex).map(kindOf)) : void 0;
6006
- const rootSettings = sugar ? { ...composition, ...sugar.composition, columns: void 0 } : { ...composition, mode: composition.mode ?? directionMode };
6007
- const recordSlots = sugar ? [] : layoutSlots(layout).filter((slot) => !headings.has(slot.type) && !placedSlots.has(slot.placeholder));
6008
- const templated = !sugar && !regions.length && recordSlots.some((slot) => slot.children) && pending.every((node) => !node.children);
6009
- const fillSlots = (entries, queue, cursor, recordSlot) => {
6010
- const nodes = [];
6011
- for (const entry of entries) {
6012
- if (cursor.next >= queue.length) break;
6013
- if (!entry.children) {
6014
- nodes.push({ ...queue[cursor.next++], ...recordSlot ? { slot: entry } : {} });
6015
- continue;
6016
- }
6017
- const own2 = record6(entry.placeholder.composition);
6018
- assertComposition(own2);
6019
- const children = fillSlots(entry.children, queue, cursor, recordSlot);
6020
- nodes.push({
6021
- field: "blocks",
6022
- type: "group",
6023
- value: children.map((child) => child.payload),
6024
- path,
6025
- payload: {},
6026
- children,
6027
- composition: own2,
6028
- synthetic: true,
6029
- reserved: own2.mode ? 0 : entry.children.length,
6030
- ...recordSlot ? { slot: entry, slots: entry.children } : {}
6031
- });
6032
- }
6033
- return nodes;
6034
- };
6035
- if (sugar) {
6922
+ const chartPrimary = chartSide !== void 0 && !useTemplate && !ownMode && !regions.length && chartIndex >= 0 && pending.some((node) => node.children || node.field !== "chart") ? chartSide : void 0;
6923
+ const firstChart = chartPrimary === "left" || chartPrimary === "top";
6924
+ const rootSettings = chartPrimary ? { ...composition, mode: chartPrimary === "left" || chartPrimary === "right" ? "row" : "column", weights: firstChart ? [3, 2] : [2, 3], columns: void 0 } : { ...composition, mode: composition.mode ?? directionMode };
6925
+ if (useTemplate) composeTemplate();
6926
+ else if (chartPrimary) {
6036
6927
  const primary = pending[chartIndex], rest = pending.filter((_, index) => index !== chartIndex);
6037
- const queue = chartPrimary === "left" || chartPrimary === "top" ? [primary, ...rest] : [...rest, primary];
6038
- arrange(fillSlots(layoutSlots(sugar, "design.chartPrimary"), queue, { next: 0 }, false), contentBox, rootSettings, 0);
6039
- } else if (templated) {
6040
- const cursor = { next: 0 };
6041
- const nodes = fillSlots(recordSlots, pending, cursor, true);
6042
- arrange([...nodes, ...pending.slice(cursor.next)], contentBox, rootSettings, composition.mode ? 0 : placeholders.length, void 0, path, true, recordSlots);
6043
- const order = /* @__PURE__ */ new Map();
6044
- const number = (entries) => entries.forEach((entry) => {
6045
- order.set(entry.path, order.size);
6046
- if (entry.children) number(entry.children);
6047
- });
6048
- number(recordSlots);
6049
- slots.sort((a, b) => order.get(a.path) - order.get(b.path));
6050
- } else arrange(pending, contentBox, rootSettings, composition.mode ? 0 : placeholders.length);
6928
+ const support = { field: "blocks", type: "group", value: rest.map((node) => node.payload), path, payload: {}, children: rest, composition: {}, synthetic: true };
6929
+ arrange(firstChart ? [primary, support] : [support, primary], contentBox, rootSettings, 0);
6930
+ } else arrange(pending, contentBox, rootSettings, 0);
6051
6931
  if (listBullet?.value === "image" && !bulletImage && items.some((item) => (item.field === "items" || item.field === "bullets") && item.payload.numbering === void 0)) {
6052
6932
  diagnostics.push({ code: "unresolved-content", path: listBullet.path, message: "Picture bullets (listBullet: image) need an organization logo (the primary organization, or the one design.logo names); the marker glyph is drawn instead." });
6053
6933
  }
@@ -6087,8 +6967,7 @@ function composeSlide(input, options = {}) {
6087
6967
  } : void 0;
6088
6968
  if (failures.length) throw new OPFCompositionError(failures, explanation);
6089
6969
  diagnostics.push(...imageDiagnostics, ...numberingDiagnostics);
6090
- for (const slot of slots) for (const key of ["x", "y", "width", "height"]) slot.box[key] = round2(slot.box[key]);
6091
- return { width, height, contentBox, items, groups, flows, ...slots.length ? { slots } : {}, diagnostics, composition, design: hints, ...furniture ? { furniture } : {}, ...backgroundImage ? { backgroundImage } : {}, ...logo ? { logo } : {}, ...rtl ? { direction: "rtl" } : {}, ...footnotes ? { footnotes } : {}, ...explanation ? { explanation } : {} };
6970
+ return { width, height, contentBox, items, groups, flows, ...useTemplate ? { regions: templateRegions, headingAreas } : {}, diagnostics, composition, design: hints, ...furniture ? { furniture } : {}, ...backgroundImage ? { backgroundImage } : {}, ...logo ? { logo } : {}, ...rtl ? { direction: "rtl" } : {}, ...footnotes ? { footnotes } : {}, ...explanation ? { explanation } : {} };
6092
6971
  }
6093
6972
  function resolveCanvasDimensions(input) {
6094
6973
  const presets = {
@@ -6103,7 +6982,7 @@ function resolveCanvasDimensions(input) {
6103
6982
  letter: [11, 8.5],
6104
6983
  a4: [11.69, 8.27]
6105
6984
  };
6106
- const value = record6(input);
6985
+ const value = record8(input);
6107
6986
  const preset = presets[typeof input === "string" ? input : value.preset] ?? presets.widescreen;
6108
6987
  const width = (value.widthInches ?? preset[0]) * 96;
6109
6988
  const height = (value.heightInches ?? preset[1]) * 96;
@@ -6111,4 +6990,4 @@ function resolveCanvasDimensions(input) {
6111
6990
  return { width, height };
6112
6991
  }
6113
6992
 
6114
- 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_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, FURNITURE_GAP, FURNITURE_IMAGE_SHARE, LANGUAGES, LAYOUT_BODY_KINDS, LOGO_SHAPES, MAX_COMPOSITION_DEPTH, MAX_NUMBERING_LEVELS, MAX_NUMBERING_VALUE, MAX_PLACEHOLDER_GROUP_DEPTH, 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, SLIDE_SCOPED_BUILTINS, 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, chartPrimaryLayout, citationMarkerText, codeHighlightBands, codeHighlightColors, codeHighlightLines, codeHighlightSlice, codeLineNumbers, codeLineRuns, codeSyntaxPalette, codeSyntaxPaletteForScheme, coerceVariableValue, collectCitations, colorContrast, composeSlide, datasetDiagnostics, defaultSlideBackground, fitImage, fitList, fitRichText, fitText, formatChartLabelNumber, formatChartLabelPercent, formatDataNumber, formatFurnitureDate, formatListNumber, formatVariableNumber, fromExcelNumberFormat, hasContentVariables, hasPlaceholderGroups, imageBackground, imageShape, inlineChartData, inlineDatasets, inlineTableData, instantiateForValidation, intrinsicImageAspect, intrinsicImageSize, isDarkColor, isDatasetRef, isPlaceholderGroup, isRecord, isTemplate, isXYChartType, layoutCaption, layoutCode, layoutContent, layoutFootnotes, layoutFurniture, layoutLeaves, layoutMetric, layoutQuote, layoutSlots, layoutStructure, 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, resolveSlideVariables, resolveSocialProfile, resolveTableData, resolveTextStyle, resolveVariables, scriptFontRole, sliceNumberedItems, slideCitations, slideTokenSpans, snapFontSizeDown, snapFontSizeUp, suggestChartNumberFix, surfaceAltColor, tableCellDisplayValue, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, timelineMarkerShapes, timelineTextColor, toExcelNumberFormat, tokenizeCode, unusedDatasets, usesSlideBuiltin, variableDeclarations, visitContentPayloads, visualReadingOrder, walkCitationRuns, wrapText };
6993
+ export { AUTO_LAYOUT, CAPTIONABLE_FIELDS, CAPTION_FONT_RATIO, CAPTION_MAX_RATIO, CATALOG_GROUP_PATTERN, CATALOG_REFERENCE_PATTERN, 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_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, FURNITURE_GAP, FURNITURE_IMAGE_SHARE, HEADING_AREAS, LANGUAGES, LAYOUT_BODY_KINDS, LOGO_SHAPES, MAX_COMPOSITION_DEPTH, MAX_NUMBERING_LEVELS, MAX_NUMBERING_VALUE, MAX_REGION_BLOCKS, MAX_ROMAN_VALUE, MAX_TEMPLATE_TRACKS, METRIC_TREND_MIN_CONTRAST, METRIC_TREND_SHAPES, NUMBERING_STYLES, NUMBERING_SUFFIXES, OPFCatalogsOptionError, OPFCompositionError, OPFLayoutTemplateError, OPFUnresolvedReferenceError, OPFVariableError, PATTERN_PRESETS, PATTERN_PRESET_ALIASES, PATTERN_TILE_SIZE, PICTURE_BULLET_SCALE, PROMOTED_REGION_KEY, REGION_ANCHORS, REGION_FLOWS, REGION_KINDS, REGION_ROLES, RESERVED_REGION_NAMES, SLIDE_SCOPED_BUILTINS, SOCIAL_PLATFORMS, SURFACE_ALT_MIN_CONTRAST, SURFACE_ALT_MIX, THEME_DESIGN_KEYS, TIMELINE_OUTLINE_MIN_CONTRAST, TIMELINE_STATUSES, TIMELINE_TEXT_MIN_CONTRAST, VARIABLE_KINDS, allocateRows, annotationText, bindRegions, blockKind, captionSettings, catalogGroupDeclared, catalogGroupSource, catalogKinds, catalogRecords, catalogReferenceSites, chartColorForFill, chartHighlightColors, chartHighlightMarks, chartLabelText, chartNumber, chartNumberFixesByCell, chartOptionSupport, chartOptionTarget, chartPaletteForFill, checkCatalogsOption, citationMarkerText, codeHighlightBands, codeHighlightColors, codeHighlightLines, codeHighlightSlice, codeLineNumbers, codeLineRuns, codeSyntaxPalette, codeSyntaxPaletteForScheme, coerceVariableValue, collectCitations, colorContrast, composeLayoutAreas, composeSlide, datasetDiagnostics, defaultSlideBackground, dottedPath, embeddedCopy, fitImage, fitList, fitRichText, fitText, formatChartLabelNumber, formatChartLabelPercent, formatDataNumber, formatFurnitureDate, formatListNumber, formatVariableNumber, fromExcelNumberFormat, gridFlowShape, hasContentVariables, imageBackground, imageShape, inlineChartData, inlineDatasets, inlineTableData, instantiateForValidation, intrinsicImageAspect, intrinsicImageSize, isDarkColor, isDatasetRef, isLayoutTemplate, isRecord, isTemplate, isXYChartType, layoutCaption, layoutCode, layoutContent, layoutFootnotes, layoutFurniture, layoutMetric, layoutQuote, layoutRegion, layoutStructure, layoutTable, layoutTemplate, layoutTemplateIssues, layoutTimeline, layoutWatermark, listBuiltinVariables, listColumnBreaks, listNumbers, listVariables, measureText, measureTextOutline, metricTrendColor, metricTrendMark, metricTrendPoints, normalizeHexColor, normalizeLanguageFamily, numberFormatError, numberingAtLevel, numberingFindings, numberingStyleDraws, paragraphDirection, paragraphDirectionAt, parseReference, pathFor, patternBitmap, patternRuns, physicalAlignment, placeTextLines, placedImageBlocks, pointerPath, promotedRegionKeys, provenanceOf, readingRows, recordReferenceSites, referencesSlide, regionAccepts, regionRoleRank, registeredCatalog, resolveCanvasDimensions, resolveChartData, resolveChartOptions, resolveCodeLanguage, resolveColorRef, resolveColorRoles, resolveDesignHints, resolveDesignRecords, resolveFontFamilies, resolveFontScheme, resolveLogo, resolveNumbering, resolvePatternPreset, resolveReference, resolveScriptFonts, resolveSlideDirection, resolveSlideVariables, resolveSocialProfile, resolveTableData, resolveTextStyle, resolveVariables, rootNodes, scriptFontRole, sliceNumberedItems, slideCitations, slideTokenSpans, snapFontSizeDown, snapFontSizeUp, suggestChartNumberFix, surfaceAltColor, tableCellDisplayValue, tableGrid, tableRowBoundaries, textColorForFill, textWidthMeasurer, timelineMarkerShapes, timelineTextColor, toExcelNumberFormat, tokenizeCode, unresolvedReference, unusedDatasets, usesSlideBuiltin, variableDeclarations, visitContentPayloads, visualReadingOrder, walkCitationRuns, wrapText };