@openpresentation/opf 0.18.4 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (760) hide show
  1. package/README.md +18 -17
  2. package/dist/browser.js +17 -19
  3. package/dist/{catalog-refs-BSfGELpt.d.ts → catalog-refs-CSHevLn1.d.ts} +1 -1
  4. package/dist/{chunk-IM337HP5.js → chunk-2AGWO7RM.js} +4 -5
  5. package/dist/{chunk-WHHLGDCQ.js → chunk-2XJUXMBS.js} +1 -1
  6. package/dist/{chunk-JCOSZTOI.js → chunk-32MHL3B3.js} +7 -2
  7. package/dist/{chunk-ECP7QPGK.js → chunk-4FBXVST6.js} +6 -6
  8. package/dist/{chunk-KA3ZPFVT.js → chunk-7QUAOKS6.js} +96 -40
  9. package/dist/{chunk-FO3WGS4R.js → chunk-BDXJYO6R.js} +25 -16
  10. package/dist/chunk-BYEIFHWS.js +16 -0
  11. package/dist/{chunk-K5EG3UMS.js → chunk-JMYM44I4.js} +50 -20
  12. package/dist/{chunk-L5YACLWK.js → chunk-L6RRLN6Q.js} +2 -2
  13. package/dist/{chunk-GVOLSWAJ.js → chunk-NZDWCYDI.js} +5 -5
  14. package/dist/{chunk-R7KIASS4.js → chunk-P6LMWUXV.js} +1 -1
  15. package/dist/{chunk-MSFE2HUK.js → chunk-RFJ5TR3V.js} +16 -13
  16. package/dist/{chunk-PNINP5IF.js → chunk-UA5EROLC.js} +1 -1
  17. package/dist/{chunk-MBU42S5Y.js → chunk-UAXSW6VV.js} +1237 -293
  18. package/dist/chunk-UJSAR6GF.js +181 -0
  19. package/dist/{chunk-2PEWUUBR.js → chunk-VEHLQVGQ.js} +381 -314
  20. package/dist/{chunk-ZCFSDSUX.js → chunk-W7G5LSXI.js} +1 -1
  21. package/dist/{chunk-TRELE6I6.js → chunk-ZU5EQ23T.js} +1 -1
  22. package/dist/{composition-C-OoqvAr.d.ts → composition-MFjGwuN_.d.ts} +395 -99
  23. package/dist/composition.d.ts +2 -2
  24. package/dist/composition.js +1 -2
  25. package/dist/{conversion-BxZbBd_0.d.ts → conversion-DDd1mdIj.d.ts} +11 -11
  26. package/dist/conversion-WHN4D4WH.js +19 -0
  27. package/dist/convert.d.ts +3 -3
  28. package/dist/convert.js +7 -9
  29. package/dist/data.d.ts +1 -1
  30. package/dist/data.js +2 -3
  31. package/dist/{deck-report-DiDf_Vew.d.ts → deck-report-DldBcTHe.d.ts} +3 -3
  32. package/dist/deck.d.ts +6 -6
  33. package/dist/deck.js +10 -12
  34. package/dist/diff.js +5 -7
  35. package/dist/docs.js +34 -22
  36. package/dist/examples.d.ts +1 -1
  37. package/dist/examples.js +27210 -20994
  38. package/dist/format.js +2 -2
  39. package/dist/index.d.ts +22 -21
  40. package/dist/index.js +23 -26
  41. package/dist/markdown.d.ts +4 -4
  42. package/dist/markdown.js +7 -9
  43. package/dist/node-engine.d.ts +27 -9
  44. package/dist/node-engine.js +22 -23
  45. package/dist/{pagination-BaUjDrTz.d.ts → pagination-BKsZIEcA.d.ts} +3 -3
  46. package/dist/pagination.d.ts +3 -3
  47. package/dist/pagination.js +4 -6
  48. package/dist/patch.js +4 -6
  49. package/dist/{presentation-81rNihF0.d.ts → presentation-B_e2Djga.d.ts} +35 -19
  50. package/dist/repo-readme.js +1 -1
  51. package/dist/schemas.d.ts +2 -18
  52. package/dist/schemas.js +1 -1
  53. package/dist/spec/README.md +12 -19
  54. package/dist/spec/reference/engine-vocabularies.json +1 -1
  55. package/dist/spec/schemas/catalog-index.schema.json +3 -3
  56. package/dist/spec/schemas/catalog-manifest.schema.json +1 -1
  57. package/dist/spec/schemas/chart-type.schema.json +2 -2
  58. package/dist/spec/schemas/language.schema.json +1 -1
  59. package/dist/spec/schemas/layout-preview-index.schema.json +25 -11
  60. package/dist/spec/schemas/layout.schema.json +212 -272
  61. package/dist/spec/schemas/opf.schema.json +63 -18
  62. package/dist/spec/schemas/social-platform.schema.json +1 -1
  63. package/dist/spec/schemas/theme.schema.json +60 -0
  64. package/dist/spec-files.d.ts +2 -2
  65. package/dist/spec-files.js +1 -1
  66. package/dist/types.d.ts +115 -40
  67. package/dist/{validation-types-PbGDrNUr.d.ts → validation-types-DtN8X_HZ.d.ts} +2 -2
  68. package/dist/validator-1d29Z3YY.d.ts +73 -0
  69. package/dist/validator.d.ts +6 -60
  70. package/dist/validator.js +3 -5
  71. package/dist/yaml.d.ts +4 -4
  72. package/dist/yaml.js +7 -9
  73. package/package.json +8 -11
  74. package/dist/catalog-schemas-CinPh5WA.d.ts +0 -12
  75. package/dist/catalog.d.ts +0 -91
  76. package/dist/catalog.js +0 -3
  77. package/dist/chunk-HXHOZ7AH.js +0 -4937
  78. package/dist/chunk-SPFV27O5.js +0 -210
  79. package/dist/chunk-TRDXRRQK.js +0 -17
  80. package/dist/chunk-WCG3THTD.js +0 -23712
  81. package/dist/conversion-SHYVL7FC.js +0 -21
  82. package/dist/spec/catalogs/audiences/academic.json +0 -24
  83. package/dist/spec/catalogs/audiences/all-hands.json +0 -25
  84. package/dist/spec/catalogs/audiences/board.json +0 -24
  85. package/dist/spec/catalogs/audiences/candidates.json +0 -23
  86. package/dist/spec/catalogs/audiences/customer.json +0 -25
  87. package/dist/spec/catalogs/audiences/engineering-team.json +0 -23
  88. package/dist/spec/catalogs/audiences/executive.json +0 -24
  89. package/dist/spec/catalogs/audiences/general-public.json +0 -25
  90. package/dist/spec/catalogs/audiences/index.json +0 -105
  91. package/dist/spec/catalogs/audiences/internal-team.json +0 -25
  92. package/dist/spec/catalogs/audiences/investor.json +0 -25
  93. package/dist/spec/catalogs/audiences/marketing.json +0 -25
  94. package/dist/spec/catalogs/audiences/media.json +0 -24
  95. package/dist/spec/catalogs/audiences/partner.json +0 -25
  96. package/dist/spec/catalogs/audiences/regulatory.json +0 -25
  97. package/dist/spec/catalogs/audiences/sales.json +0 -25
  98. package/dist/spec/catalogs/audiences/technical.json +0 -25
  99. package/dist/spec/catalogs/chart-types/100pct-stacked-area.json +0 -21
  100. package/dist/spec/catalogs/chart-types/100pct-stacked-bar.json +0 -22
  101. package/dist/spec/catalogs/chart-types/100pct-stacked-column.json +0 -22
  102. package/dist/spec/catalogs/chart-types/area.json +0 -20
  103. package/dist/spec/catalogs/chart-types/bar.json +0 -22
  104. package/dist/spec/catalogs/chart-types/box-and-whisker.json +0 -21
  105. package/dist/spec/catalogs/chart-types/column.json +0 -22
  106. package/dist/spec/catalogs/chart-types/combo.json +0 -37
  107. package/dist/spec/catalogs/chart-types/doughnut.json +0 -20
  108. package/dist/spec/catalogs/chart-types/filled-radar.json +0 -21
  109. package/dist/spec/catalogs/chart-types/funnel.json +0 -21
  110. package/dist/spec/catalogs/chart-types/histogram.json +0 -21
  111. package/dist/spec/catalogs/chart-types/index.json +0 -171
  112. package/dist/spec/catalogs/chart-types/line-with-markers.json +0 -21
  113. package/dist/spec/catalogs/chart-types/line.json +0 -20
  114. package/dist/spec/catalogs/chart-types/pareto.json +0 -22
  115. package/dist/spec/catalogs/chart-types/pie.json +0 -20
  116. package/dist/spec/catalogs/chart-types/radar-with-markers.json +0 -21
  117. package/dist/spec/catalogs/chart-types/radar.json +0 -21
  118. package/dist/spec/catalogs/chart-types/scatter.json +0 -21
  119. package/dist/spec/catalogs/chart-types/stacked-area.json +0 -21
  120. package/dist/spec/catalogs/chart-types/stacked-bar.json +0 -22
  121. package/dist/spec/catalogs/chart-types/stacked-column.json +0 -22
  122. package/dist/spec/catalogs/chart-types/stacked-line-with-markers.json +0 -22
  123. package/dist/spec/catalogs/chart-types/stacked-line.json +0 -21
  124. package/dist/spec/catalogs/chart-types/treemap.json +0 -21
  125. package/dist/spec/catalogs/chart-types/waterfall.json +0 -21
  126. package/dist/spec/catalogs/chart-types/world.json +0 -21
  127. package/dist/spec/catalogs/color-schemes/black-and-white.json +0 -26
  128. package/dist/spec/catalogs/color-schemes/bold-red.json +0 -26
  129. package/dist/spec/catalogs/color-schemes/boost.json +0 -26
  130. package/dist/spec/catalogs/color-schemes/burnt-orange.json +0 -26
  131. package/dist/spec/catalogs/color-schemes/cool-horizon.json +0 -26
  132. package/dist/spec/catalogs/color-schemes/corporate-blue.json +0 -26
  133. package/dist/spec/catalogs/color-schemes/deep-purple.json +0 -26
  134. package/dist/spec/catalogs/color-schemes/forest-green.json +0 -26
  135. package/dist/spec/catalogs/color-schemes/golden-yellow.json +0 -26
  136. package/dist/spec/catalogs/color-schemes/index.json +0 -79
  137. package/dist/spec/catalogs/color-schemes/luxury.json +0 -26
  138. package/dist/spec/catalogs/color-schemes/pastel-red.json +0 -26
  139. package/dist/spec/catalogs/color-schemes/slate-gray.json +0 -26
  140. package/dist/spec/catalogs/color-schemes/steel-blue.json +0 -26
  141. package/dist/spec/catalogs/color-schemes/vibes.json +0 -26
  142. package/dist/spec/catalogs/font-schemes/angsana-new.json +0 -15
  143. package/dist/spec/catalogs/font-schemes/aparajita.json +0 -16
  144. package/dist/spec/catalogs/font-schemes/aptos.json +0 -13
  145. package/dist/spec/catalogs/font-schemes/arabic-typesetting.json +0 -15
  146. package/dist/spec/catalogs/font-schemes/arial.json +0 -13
  147. package/dist/spec/catalogs/font-schemes/batang.json +0 -15
  148. package/dist/spec/catalogs/font-schemes/bookman.json +0 -13
  149. package/dist/spec/catalogs/font-schemes/calibri.json +0 -13
  150. package/dist/spec/catalogs/font-schemes/century-schoolbook.json +0 -13
  151. package/dist/spec/catalogs/font-schemes/consolas.json +0 -14
  152. package/dist/spec/catalogs/font-schemes/constantia.json +0 -13
  153. package/dist/spec/catalogs/font-schemes/courier-new.json +0 -14
  154. package/dist/spec/catalogs/font-schemes/daunpenh.json +0 -15
  155. package/dist/spec/catalogs/font-schemes/david.json +0 -15
  156. package/dist/spec/catalogs/font-schemes/dilleniaupc.json +0 -15
  157. package/dist/spec/catalogs/font-schemes/fangsong.json +0 -15
  158. package/dist/spec/catalogs/font-schemes/garamond.json +0 -13
  159. package/dist/spec/catalogs/font-schemes/gautami.json +0 -15
  160. package/dist/spec/catalogs/font-schemes/georgia.json +0 -13
  161. package/dist/spec/catalogs/font-schemes/gisha.json +0 -16
  162. package/dist/spec/catalogs/font-schemes/grandview.json +0 -13
  163. package/dist/spec/catalogs/font-schemes/gungsuh.json +0 -15
  164. package/dist/spec/catalogs/font-schemes/impact.json +0 -13
  165. package/dist/spec/catalogs/font-schemes/index.json +0 -454
  166. package/dist/spec/catalogs/font-schemes/kalinga.json +0 -15
  167. package/dist/spec/catalogs/font-schemes/kartika.json +0 -15
  168. package/dist/spec/catalogs/font-schemes/khmer-ui.json +0 -15
  169. package/dist/spec/catalogs/font-schemes/latha.json +0 -15
  170. package/dist/spec/catalogs/font-schemes/lucida-sans.json +0 -13
  171. package/dist/spec/catalogs/font-schemes/malgun-gothic.json +0 -15
  172. package/dist/spec/catalogs/font-schemes/mangal.json +0 -17
  173. package/dist/spec/catalogs/font-schemes/meiryo.json +0 -15
  174. package/dist/spec/catalogs/font-schemes/microsoft-jhenghei.json +0 -15
  175. package/dist/spec/catalogs/font-schemes/microsoft-yahei.json +0 -18
  176. package/dist/spec/catalogs/font-schemes/mingliu.json +0 -15
  177. package/dist/spec/catalogs/font-schemes/miriam.json +0 -15
  178. package/dist/spec/catalogs/font-schemes/montserrat.json +0 -13
  179. package/dist/spec/catalogs/font-schemes/ms-mincho.json +0 -15
  180. package/dist/spec/catalogs/font-schemes/nirmala-ui.json +0 -15
  181. package/dist/spec/catalogs/font-schemes/noto-naksh-arabic.json +0 -15
  182. package/dist/spec/catalogs/font-schemes/noto-nastaliq-urdu.json +0 -16
  183. package/dist/spec/catalogs/font-schemes/noto-sans-arabic.json +0 -17
  184. package/dist/spec/catalogs/font-schemes/noto-sans-armenian.json +0 -15
  185. package/dist/spec/catalogs/font-schemes/noto-sans-bengali.json +0 -16
  186. package/dist/spec/catalogs/font-schemes/noto-sans-devangari.json +0 -16
  187. package/dist/spec/catalogs/font-schemes/noto-sans-ethiopic.json +0 -15
  188. package/dist/spec/catalogs/font-schemes/noto-sans-georgian.json +0 -15
  189. package/dist/spec/catalogs/font-schemes/noto-sans-gujarati.json +0 -15
  190. package/dist/spec/catalogs/font-schemes/noto-sans-gurmukhi.json +0 -15
  191. package/dist/spec/catalogs/font-schemes/noto-sans-hebrew.json +0 -15
  192. package/dist/spec/catalogs/font-schemes/noto-sans-jp.json +0 -15
  193. package/dist/spec/catalogs/font-schemes/noto-sans-kannada.json +0 -15
  194. package/dist/spec/catalogs/font-schemes/noto-sans-khmer.json +0 -15
  195. package/dist/spec/catalogs/font-schemes/noto-sans-kr.json +0 -15
  196. package/dist/spec/catalogs/font-schemes/noto-sans-malayalam.json +0 -15
  197. package/dist/spec/catalogs/font-schemes/noto-sans-mongolian.json +0 -15
  198. package/dist/spec/catalogs/font-schemes/noto-sans-oriya.json +0 -15
  199. package/dist/spec/catalogs/font-schemes/noto-sans-sc.json +0 -18
  200. package/dist/spec/catalogs/font-schemes/noto-sans-tamil.json +0 -15
  201. package/dist/spec/catalogs/font-schemes/noto-sans-tc.json +0 -15
  202. package/dist/spec/catalogs/font-schemes/noto-sans-telugu.json +0 -15
  203. package/dist/spec/catalogs/font-schemes/noto-sans-thai.json +0 -15
  204. package/dist/spec/catalogs/font-schemes/noto-sans.json +0 -18
  205. package/dist/spec/catalogs/font-schemes/nyala.json +0 -15
  206. package/dist/spec/catalogs/font-schemes/open-sans.json +0 -13
  207. package/dist/spec/catalogs/font-schemes/pmingliu.json +0 -15
  208. package/dist/spec/catalogs/font-schemes/poppins.json +0 -13
  209. package/dist/spec/catalogs/font-schemes/pt-serif.json +0 -13
  210. package/dist/spec/catalogs/font-schemes/raavi.json +0 -15
  211. package/dist/spec/catalogs/font-schemes/raleway.json +0 -13
  212. package/dist/spec/catalogs/font-schemes/roboto.json +0 -13
  213. package/dist/spec/catalogs/font-schemes/rockwell.json +0 -13
  214. package/dist/spec/catalogs/font-schemes/sakkal-majalla.json +0 -17
  215. package/dist/spec/catalogs/font-schemes/seaford.json +0 -13
  216. package/dist/spec/catalogs/font-schemes/segoe-ui-light.json +0 -13
  217. package/dist/spec/catalogs/font-schemes/segoe-ui.json +0 -13
  218. package/dist/spec/catalogs/font-schemes/shonar-bangla.json +0 -16
  219. package/dist/spec/catalogs/font-schemes/shruti.json +0 -15
  220. package/dist/spec/catalogs/font-schemes/simsun.json +0 -15
  221. package/dist/spec/catalogs/font-schemes/skeena.json +0 -13
  222. package/dist/spec/catalogs/font-schemes/sylfaen.json +0 -16
  223. package/dist/spec/catalogs/font-schemes/tahoma.json +0 -13
  224. package/dist/spec/catalogs/font-schemes/tenorite.json +0 -13
  225. package/dist/spec/catalogs/font-schemes/times-new-roman.json +0 -13
  226. package/dist/spec/catalogs/font-schemes/traditional-arabic.json +0 -17
  227. package/dist/spec/catalogs/font-schemes/trebuchet-ms.json +0 -13
  228. package/dist/spec/catalogs/font-schemes/tunga.json +0 -15
  229. package/dist/spec/catalogs/font-schemes/verdana.json +0 -13
  230. package/dist/spec/catalogs/font-schemes/vrinda.json +0 -15
  231. package/dist/spec/catalogs/font-schemes/yu-gothic.json +0 -15
  232. package/dist/spec/catalogs/languages/afrikaans.json +0 -12
  233. package/dist/spec/catalogs/languages/albanian.json +0 -12
  234. package/dist/spec/catalogs/languages/amharic.json +0 -12
  235. package/dist/spec/catalogs/languages/arabic.json +0 -12
  236. package/dist/spec/catalogs/languages/armenian.json +0 -12
  237. package/dist/spec/catalogs/languages/aymara.json +0 -12
  238. package/dist/spec/catalogs/languages/azerbaijani.json +0 -12
  239. package/dist/spec/catalogs/languages/bengali.json +0 -12
  240. package/dist/spec/catalogs/languages/berber-latin.json +0 -12
  241. package/dist/spec/catalogs/languages/bosnian-latin.json +0 -12
  242. package/dist/spec/catalogs/languages/bulgarian.json +0 -12
  243. package/dist/spec/catalogs/languages/catalan.json +0 -12
  244. package/dist/spec/catalogs/languages/cebuano.json +0 -12
  245. package/dist/spec/catalogs/languages/chinese-simplified.json +0 -12
  246. package/dist/spec/catalogs/languages/chinese-traditional.json +0 -12
  247. package/dist/spec/catalogs/languages/chittagonian.json +0 -12
  248. package/dist/spec/catalogs/languages/croatian.json +0 -12
  249. package/dist/spec/catalogs/languages/czech.json +0 -12
  250. package/dist/spec/catalogs/languages/danish.json +0 -12
  251. package/dist/spec/catalogs/languages/dutch.json +0 -12
  252. package/dist/spec/catalogs/languages/english-au.json +0 -12
  253. package/dist/spec/catalogs/languages/english-ca.json +0 -12
  254. package/dist/spec/catalogs/languages/english-gb.json +0 -12
  255. package/dist/spec/catalogs/languages/english-in.json +0 -12
  256. package/dist/spec/catalogs/languages/english-us.json +0 -12
  257. package/dist/spec/catalogs/languages/english.json +0 -12
  258. package/dist/spec/catalogs/languages/estonian.json +0 -12
  259. package/dist/spec/catalogs/languages/filipino.json +0 -12
  260. package/dist/spec/catalogs/languages/finnish.json +0 -12
  261. package/dist/spec/catalogs/languages/french.json +0 -12
  262. package/dist/spec/catalogs/languages/fulfulde.json +0 -12
  263. package/dist/spec/catalogs/languages/galician.json +0 -12
  264. package/dist/spec/catalogs/languages/georgian.json +0 -12
  265. package/dist/spec/catalogs/languages/german.json +0 -12
  266. package/dist/spec/catalogs/languages/greek.json +0 -12
  267. package/dist/spec/catalogs/languages/gujarati.json +0 -12
  268. package/dist/spec/catalogs/languages/hausa.json +0 -12
  269. package/dist/spec/catalogs/languages/hebrew.json +0 -12
  270. package/dist/spec/catalogs/languages/hindi.json +0 -12
  271. package/dist/spec/catalogs/languages/hungarian.json +0 -12
  272. package/dist/spec/catalogs/languages/igbo.json +0 -12
  273. package/dist/spec/catalogs/languages/index.json +0 -567
  274. package/dist/spec/catalogs/languages/indonesian.json +0 -12
  275. package/dist/spec/catalogs/languages/italian.json +0 -12
  276. package/dist/spec/catalogs/languages/japanese.json +0 -12
  277. package/dist/spec/catalogs/languages/kannada.json +0 -12
  278. package/dist/spec/catalogs/languages/kazakh.json +0 -12
  279. package/dist/spec/catalogs/languages/khmer.json +0 -12
  280. package/dist/spec/catalogs/languages/kinyarwanda.json +0 -12
  281. package/dist/spec/catalogs/languages/korean.json +0 -12
  282. package/dist/spec/catalogs/languages/kurmanji.json +0 -12
  283. package/dist/spec/catalogs/languages/latvian.json +0 -12
  284. package/dist/spec/catalogs/languages/lithuanian.json +0 -12
  285. package/dist/spec/catalogs/languages/macedonian.json +0 -12
  286. package/dist/spec/catalogs/languages/malagasy.json +0 -12
  287. package/dist/spec/catalogs/languages/malay.json +0 -12
  288. package/dist/spec/catalogs/languages/malayalam.json +0 -12
  289. package/dist/spec/catalogs/languages/maori.json +0 -12
  290. package/dist/spec/catalogs/languages/marathi.json +0 -12
  291. package/dist/spec/catalogs/languages/mongolian.json +0 -12
  292. package/dist/spec/catalogs/languages/nepali.json +0 -12
  293. package/dist/spec/catalogs/languages/norwegian.json +0 -12
  294. package/dist/spec/catalogs/languages/odia.json +0 -12
  295. package/dist/spec/catalogs/languages/oromo.json +0 -12
  296. package/dist/spec/catalogs/languages/pashto.json +0 -12
  297. package/dist/spec/catalogs/languages/persian.json +0 -12
  298. package/dist/spec/catalogs/languages/polish.json +0 -12
  299. package/dist/spec/catalogs/languages/portuguese.json +0 -12
  300. package/dist/spec/catalogs/languages/punjabi-gurmukhi.json +0 -12
  301. package/dist/spec/catalogs/languages/punjabi-shahmukhi.json +0 -12
  302. package/dist/spec/catalogs/languages/romanian.json +0 -12
  303. package/dist/spec/catalogs/languages/russian.json +0 -12
  304. package/dist/spec/catalogs/languages/serbian-cyrillic.json +0 -12
  305. package/dist/spec/catalogs/languages/serbian-latin.json +0 -12
  306. package/dist/spec/catalogs/languages/shona.json +0 -12
  307. package/dist/spec/catalogs/languages/slovak.json +0 -12
  308. package/dist/spec/catalogs/languages/slovenian.json +0 -12
  309. package/dist/spec/catalogs/languages/somali.json +0 -12
  310. package/dist/spec/catalogs/languages/spanish.json +0 -12
  311. package/dist/spec/catalogs/languages/swahili.json +0 -12
  312. package/dist/spec/catalogs/languages/swedish.json +0 -12
  313. package/dist/spec/catalogs/languages/tagalog.json +0 -12
  314. package/dist/spec/catalogs/languages/tajik.json +0 -12
  315. package/dist/spec/catalogs/languages/tamil.json +0 -12
  316. package/dist/spec/catalogs/languages/telugu.json +0 -12
  317. package/dist/spec/catalogs/languages/thai.json +0 -12
  318. package/dist/spec/catalogs/languages/turkish.json +0 -12
  319. package/dist/spec/catalogs/languages/ukrainian.json +0 -12
  320. package/dist/spec/catalogs/languages/urdu.json +0 -12
  321. package/dist/spec/catalogs/languages/uzbek-latin.json +0 -12
  322. package/dist/spec/catalogs/languages/vietnamese-quoc-ngu.json +0 -12
  323. package/dist/spec/catalogs/languages/xhosa.json +0 -12
  324. package/dist/spec/catalogs/languages/yoruba.json +0 -12
  325. package/dist/spec/catalogs/languages/zulu.json +0 -12
  326. package/dist/spec/catalogs/layouts/action-plan.json +0 -29
  327. package/dist/spec/catalogs/layouts/agenda.json +0 -28
  328. package/dist/spec/catalogs/layouts/appendix-index.json +0 -30
  329. package/dist/spec/catalogs/layouts/architecture-stack.json +0 -29
  330. package/dist/spec/catalogs/layouts/assumptions-dependencies.json +0 -29
  331. package/dist/spec/catalogs/layouts/before-after.json +0 -35
  332. package/dist/spec/catalogs/layouts/benchmark-target-table.json +0 -29
  333. package/dist/spec/catalogs/layouts/blank.json +0 -16
  334. package/dist/spec/catalogs/layouts/bullet-list.json +0 -32
  335. package/dist/spec/catalogs/layouts/business-model-canvas.json +0 -94
  336. package/dist/spec/catalogs/layouts/capability-map.json +0 -80
  337. package/dist/spec/catalogs/layouts/case-study.json +0 -29
  338. package/dist/spec/catalogs/layouts/chapter-recap.json +0 -28
  339. package/dist/spec/catalogs/layouts/chart-1x-title-center.json +0 -30
  340. package/dist/spec/catalogs/layouts/chart-1x.json +0 -34
  341. package/dist/spec/catalogs/layouts/chart-2x-title-center.json +0 -36
  342. package/dist/spec/catalogs/layouts/chart-2x-vertical-title-left.json +0 -37
  343. package/dist/spec/catalogs/layouts/chart-2x.json +0 -65
  344. package/dist/spec/catalogs/layouts/chart-3x-bottom-vertical-title-left.json +0 -52
  345. package/dist/spec/catalogs/layouts/chart-3x-left-title-center.json +0 -51
  346. package/dist/spec/catalogs/layouts/chart-3x-left.json +0 -46
  347. package/dist/spec/catalogs/layouts/chart-3x-right-title-center.json +0 -51
  348. package/dist/spec/catalogs/layouts/chart-3x-right.json +0 -46
  349. package/dist/spec/catalogs/layouts/chart-3x-title-center.json +0 -39
  350. package/dist/spec/catalogs/layouts/chart-3x-top-vertical-title-left.json +0 -52
  351. package/dist/spec/catalogs/layouts/chart-3x.json +0 -83
  352. package/dist/spec/catalogs/layouts/circular-lifecycle.json +0 -29
  353. package/dist/spec/catalogs/layouts/code-1x.json +0 -29
  354. package/dist/spec/catalogs/layouts/comparison.json +0 -35
  355. package/dist/spec/catalogs/layouts/competitive-landscape.json +0 -30
  356. package/dist/spec/catalogs/layouts/customer-journey.json +0 -30
  357. package/dist/spec/catalogs/layouts/customer-logos.json +0 -32
  358. package/dist/spec/catalogs/layouts/dashboard.json +0 -67
  359. package/dist/spec/catalogs/layouts/data-visualization.json +0 -39
  360. package/dist/spec/catalogs/layouts/decision-tree.json +0 -30
  361. package/dist/spec/catalogs/layouts/detailed-data-table.json +0 -35
  362. package/dist/spec/catalogs/layouts/ecosystem-map.json +0 -30
  363. package/dist/spec/catalogs/layouts/executive-decision.json +0 -32
  364. package/dist/spec/catalogs/layouts/executive-summary.json +0 -32
  365. package/dist/spec/catalogs/layouts/extract/canonical.json +0 -575
  366. package/dist/spec/catalogs/layouts/faq.json +0 -29
  367. package/dist/spec/catalogs/layouts/feature-comparison-matrix.json +0 -29
  368. package/dist/spec/catalogs/layouts/forecast-scenario.json +0 -39
  369. package/dist/spec/catalogs/layouts/funnel-pyramid.json +0 -32
  370. package/dist/spec/catalogs/layouts/gantt-project-plan.json +0 -32
  371. package/dist/spec/catalogs/layouts/geographic-map.json +0 -30
  372. package/dist/spec/catalogs/layouts/heatmap-cohort.json +0 -32
  373. package/dist/spec/catalogs/layouts/hub-and-spoke.json +0 -29
  374. package/dist/spec/catalogs/layouts/icon-grid.json +0 -30
  375. package/dist/spec/catalogs/layouts/image-1x-crop-title-center.json +0 -32
  376. package/dist/spec/catalogs/layouts/image-1x-crop-title-left.json +0 -32
  377. package/dist/spec/catalogs/layouts/image-1x-crop.json +0 -27
  378. package/dist/spec/catalogs/layouts/image-1x-fit-title-center.json +0 -32
  379. package/dist/spec/catalogs/layouts/image-1x.json +0 -32
  380. package/dist/spec/catalogs/layouts/image-2x-crop-title-center.json +0 -38
  381. package/dist/spec/catalogs/layouts/image-2x-crop-vertical-title-left.json +0 -39
  382. package/dist/spec/catalogs/layouts/image-2x-crop-vertical.json +0 -34
  383. package/dist/spec/catalogs/layouts/image-2x-crop.json +0 -33
  384. package/dist/spec/catalogs/layouts/image-2x-fit-title-center.json +0 -38
  385. package/dist/spec/catalogs/layouts/image-2x-fit-vertical-title-left.json +0 -39
  386. package/dist/spec/catalogs/layouts/image-2x-fit-vertical.json +0 -34
  387. package/dist/spec/catalogs/layouts/image-2x.json +0 -63
  388. package/dist/spec/catalogs/layouts/image-3x-crop-title-center.json +0 -41
  389. package/dist/spec/catalogs/layouts/image-3x-crop-vertical-title-left.json +0 -42
  390. package/dist/spec/catalogs/layouts/image-3x-crop-vertical.json +0 -37
  391. package/dist/spec/catalogs/layouts/image-3x-crop.json +0 -36
  392. package/dist/spec/catalogs/layouts/image-3x-fit-title-center.json +0 -41
  393. package/dist/spec/catalogs/layouts/image-3x-fit-vertical-title-left.json +0 -42
  394. package/dist/spec/catalogs/layouts/image-3x-fit-vertical.json +0 -37
  395. package/dist/spec/catalogs/layouts/image-3x-fit.json +0 -36
  396. package/dist/spec/catalogs/layouts/image-3x.json +0 -81
  397. package/dist/spec/catalogs/layouts/image-focus.json +0 -30
  398. package/dist/spec/catalogs/layouts/image-only-1x-crop-title-center.json +0 -31
  399. package/dist/spec/catalogs/layouts/image-only-1x-fit-title-center.json +0 -31
  400. package/dist/spec/catalogs/layouts/image-only-2x-crop-title-center.json +0 -37
  401. package/dist/spec/catalogs/layouts/image-only-2x-crop-vertical-title-left.json +0 -38
  402. package/dist/spec/catalogs/layouts/image-only-2x-crop-vertical.json +0 -33
  403. package/dist/spec/catalogs/layouts/image-only-2x-fit-title-center.json +0 -37
  404. package/dist/spec/catalogs/layouts/image-only-2x-fit-vertical-title-left.json +0 -38
  405. package/dist/spec/catalogs/layouts/image-only-2x-fit-vertical.json +0 -33
  406. package/dist/spec/catalogs/layouts/image-only-3x-crop-title-center.json +0 -40
  407. package/dist/spec/catalogs/layouts/image-only-3x-crop-vertical-title-left.json +0 -41
  408. package/dist/spec/catalogs/layouts/image-only-3x-crop-vertical.json +0 -36
  409. package/dist/spec/catalogs/layouts/image-only-3x-crop.json +0 -35
  410. package/dist/spec/catalogs/layouts/image-only-3x-fit-title-center.json +0 -40
  411. package/dist/spec/catalogs/layouts/image-only-3x-fit-vertical-title-left.json +0 -41
  412. package/dist/spec/catalogs/layouts/image-only-3x-fit-vertical.json +0 -36
  413. package/dist/spec/catalogs/layouts/image-only-3x-fit.json +0 -35
  414. package/dist/spec/catalogs/layouts/index.json +0 -1399
  415. package/dist/spec/catalogs/layouts/key-takeaway.json +0 -25
  416. package/dist/spec/catalogs/layouts/kpi-scorecard.json +0 -83
  417. package/dist/spec/catalogs/layouts/list-1x-box-title-center.json +0 -32
  418. package/dist/spec/catalogs/layouts/list-1x-box-vertical-title-center.json +0 -33
  419. package/dist/spec/catalogs/layouts/list-1x-box-vertical-title-left.json +0 -33
  420. package/dist/spec/catalogs/layouts/list-1x-box-vertical.json +0 -28
  421. package/dist/spec/catalogs/layouts/list-1x-box.json +0 -27
  422. package/dist/spec/catalogs/layouts/list-1x-itemimage-title-center.json +0 -32
  423. package/dist/spec/catalogs/layouts/list-1x-itemimage-vertical-title-center.json +0 -33
  424. package/dist/spec/catalogs/layouts/list-1x-title-center.json +0 -31
  425. package/dist/spec/catalogs/layouts/list-1x-vertical-title-center.json +0 -32
  426. package/dist/spec/catalogs/layouts/list-1x.json +0 -29
  427. package/dist/spec/catalogs/layouts/list-2x-box-title-center.json +0 -38
  428. package/dist/spec/catalogs/layouts/list-2x-box-vertical-title-center.json +0 -39
  429. package/dist/spec/catalogs/layouts/list-2x-box-vertical-title-left.json +0 -39
  430. package/dist/spec/catalogs/layouts/list-2x-box-vertical.json +0 -34
  431. package/dist/spec/catalogs/layouts/list-2x-box.json +0 -33
  432. package/dist/spec/catalogs/layouts/list-2x-itemimage-title-center.json +0 -38
  433. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical-title-center.json +0 -39
  434. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical-title-left.json +0 -39
  435. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical.json +0 -34
  436. package/dist/spec/catalogs/layouts/list-2x-title-center.json +0 -37
  437. package/dist/spec/catalogs/layouts/list-2x-vertical-title-center.json +0 -38
  438. package/dist/spec/catalogs/layouts/list-2x-vertical-title-left.json +0 -38
  439. package/dist/spec/catalogs/layouts/list-2x-vertical.json +0 -33
  440. package/dist/spec/catalogs/layouts/list-2x.json +0 -35
  441. package/dist/spec/catalogs/layouts/list-3x-box-title-center.json +0 -41
  442. package/dist/spec/catalogs/layouts/list-3x-box-vertical-title-center.json +0 -42
  443. package/dist/spec/catalogs/layouts/list-3x-box-vertical-title-left.json +0 -42
  444. package/dist/spec/catalogs/layouts/list-3x-box-vertical.json +0 -37
  445. package/dist/spec/catalogs/layouts/list-3x-box.json +0 -36
  446. package/dist/spec/catalogs/layouts/list-3x-itemimage-title-center.json +0 -41
  447. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical-title-center.json +0 -42
  448. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical-title-left.json +0 -42
  449. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical.json +0 -37
  450. package/dist/spec/catalogs/layouts/list-3x-itemimage.json +0 -36
  451. package/dist/spec/catalogs/layouts/list-3x-title-center.json +0 -40
  452. package/dist/spec/catalogs/layouts/list-3x-vertical-title-center.json +0 -41
  453. package/dist/spec/catalogs/layouts/list-3x-vertical-title-left.json +0 -41
  454. package/dist/spec/catalogs/layouts/list-3x-vertical.json +0 -36
  455. package/dist/spec/catalogs/layouts/list-3x.json +0 -38
  456. package/dist/spec/catalogs/layouts/list-4x-box-title-center.json +0 -45
  457. package/dist/spec/catalogs/layouts/list-4x-box-vertical-title-center.json +0 -45
  458. package/dist/spec/catalogs/layouts/list-4x-box-vertical-title-left.json +0 -45
  459. package/dist/spec/catalogs/layouts/list-4x-box-vertical.json +0 -40
  460. package/dist/spec/catalogs/layouts/list-4x-box.json +0 -40
  461. package/dist/spec/catalogs/layouts/list-4x-itemimage-title-center.json +0 -45
  462. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical-title-center.json +0 -45
  463. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical-title-left.json +0 -45
  464. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical.json +0 -40
  465. package/dist/spec/catalogs/layouts/list-4x-title-center.json +0 -44
  466. package/dist/spec/catalogs/layouts/list-4x-vertical-title-center.json +0 -44
  467. package/dist/spec/catalogs/layouts/list-4x-vertical-title-left.json +0 -44
  468. package/dist/spec/catalogs/layouts/list-4x-vertical.json +0 -39
  469. package/dist/spec/catalogs/layouts/list-4x.json +0 -42
  470. package/dist/spec/catalogs/layouts/list-5x-box-title-center.json +0 -48
  471. package/dist/spec/catalogs/layouts/list-5x-box-vertical-title-center.json +0 -50
  472. package/dist/spec/catalogs/layouts/list-5x-box-vertical-title-left.json +0 -50
  473. package/dist/spec/catalogs/layouts/list-5x-box-vertical.json +0 -45
  474. package/dist/spec/catalogs/layouts/list-5x-box.json +0 -43
  475. package/dist/spec/catalogs/layouts/list-5x-itemimage-title-center.json +0 -48
  476. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical-title-center.json +0 -48
  477. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical-title-left.json +0 -48
  478. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical.json +0 -43
  479. package/dist/spec/catalogs/layouts/list-5x-title-center.json +0 -47
  480. package/dist/spec/catalogs/layouts/list-5x-vertical-title-center.json +0 -47
  481. package/dist/spec/catalogs/layouts/list-5x-vertical-title-left.json +0 -47
  482. package/dist/spec/catalogs/layouts/list-5x-vertical.json +0 -42
  483. package/dist/spec/catalogs/layouts/list-5x.json +0 -45
  484. package/dist/spec/catalogs/layouts/list-6x-box-title-center.json +0 -51
  485. package/dist/spec/catalogs/layouts/list-6x-box-vertical-title-center.json +0 -53
  486. package/dist/spec/catalogs/layouts/list-6x-box-vertical-title-left.json +0 -53
  487. package/dist/spec/catalogs/layouts/list-6x-box-vertical.json +0 -48
  488. package/dist/spec/catalogs/layouts/list-6x-box.json +0 -46
  489. package/dist/spec/catalogs/layouts/list-6x-itemimage-title-center.json +0 -51
  490. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical-title-center.json +0 -51
  491. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical-title-left.json +0 -51
  492. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical.json +0 -46
  493. package/dist/spec/catalogs/layouts/list-6x-title-center.json +0 -50
  494. package/dist/spec/catalogs/layouts/list-6x-vertical-title-center.json +0 -50
  495. package/dist/spec/catalogs/layouts/list-6x-vertical-title-left.json +0 -50
  496. package/dist/spec/catalogs/layouts/list-6x-vertical.json +0 -45
  497. package/dist/spec/catalogs/layouts/list-6x.json +0 -48
  498. package/dist/spec/catalogs/layouts/logic-tree.json +0 -98
  499. package/dist/spec/catalogs/layouts/market-size.json +0 -53
  500. package/dist/spec/catalogs/layouts/matrix-quadrant.json +0 -42
  501. package/dist/spec/catalogs/layouts/media-1x.json +0 -29
  502. package/dist/spec/catalogs/layouts/network-dependency-map.json +0 -30
  503. package/dist/spec/catalogs/layouts/number-1x-box-title-center.json +0 -30
  504. package/dist/spec/catalogs/layouts/number-1x-box.json +0 -25
  505. package/dist/spec/catalogs/layouts/number-1x-title-center.json +0 -29
  506. package/dist/spec/catalogs/layouts/number-1x.json +0 -28
  507. package/dist/spec/catalogs/layouts/number-2x-box-title-center.json +0 -36
  508. package/dist/spec/catalogs/layouts/number-2x-box.json +0 -31
  509. package/dist/spec/catalogs/layouts/number-2x-title-center.json +0 -35
  510. package/dist/spec/catalogs/layouts/number-2x.json +0 -34
  511. package/dist/spec/catalogs/layouts/number-3x-box-title-center.json +0 -39
  512. package/dist/spec/catalogs/layouts/number-3x-box.json +0 -34
  513. package/dist/spec/catalogs/layouts/number-3x-title-center.json +0 -38
  514. package/dist/spec/catalogs/layouts/number-3x.json +0 -37
  515. package/dist/spec/catalogs/layouts/number-4x-box-title-center.json +0 -43
  516. package/dist/spec/catalogs/layouts/number-4x-box.json +0 -38
  517. package/dist/spec/catalogs/layouts/number-4x-title-center.json +0 -42
  518. package/dist/spec/catalogs/layouts/number-4x.json +0 -41
  519. package/dist/spec/catalogs/layouts/number-5x-box-title-center.json +0 -46
  520. package/dist/spec/catalogs/layouts/number-5x-box.json +0 -41
  521. package/dist/spec/catalogs/layouts/number-5x-title-center.json +0 -45
  522. package/dist/spec/catalogs/layouts/number-5x.json +0 -44
  523. package/dist/spec/catalogs/layouts/number-6x-box-title-center.json +0 -49
  524. package/dist/spec/catalogs/layouts/number-6x-box.json +0 -44
  525. package/dist/spec/catalogs/layouts/number-6x-title-center.json +0 -48
  526. package/dist/spec/catalogs/layouts/number-6x.json +0 -47
  527. package/dist/spec/catalogs/layouts/one-column-explainer.json +0 -29
  528. package/dist/spec/catalogs/layouts/org-chart.json +0 -86
  529. package/dist/spec/catalogs/layouts/persona-grid.json +0 -30
  530. package/dist/spec/catalogs/layouts/photo-grid.json +0 -43
  531. package/dist/spec/catalogs/layouts/pricing-table.json +0 -29
  532. package/dist/spec/catalogs/layouts/process-flow.json +0 -29
  533. package/dist/spec/catalogs/layouts/product-feature.json +0 -30
  534. package/dist/spec/catalogs/layouts/pros-cons.json +0 -35
  535. package/dist/spec/catalogs/layouts/qa-discussion.json +0 -30
  536. package/dist/spec/catalogs/layouts/quote-1x.json +0 -23
  537. package/dist/spec/catalogs/layouts/quote-highlight.json +0 -29
  538. package/dist/spec/catalogs/layouts/raci-matrix.json +0 -29
  539. package/dist/spec/catalogs/layouts/risk-heatmap.json +0 -29
  540. package/dist/spec/catalogs/layouts/roadmap.json +0 -29
  541. package/dist/spec/catalogs/layouts/screenshot-walkthrough.json +0 -30
  542. package/dist/spec/catalogs/layouts/section-divider.json +0 -28
  543. package/dist/spec/catalogs/layouts/single-message-statement.json +0 -25
  544. package/dist/spec/catalogs/layouts/stats-metrics.json +0 -39
  545. package/dist/spec/catalogs/layouts/status-rag.json +0 -29
  546. package/dist/spec/catalogs/layouts/swimlane-process.json +0 -30
  547. package/dist/spec/catalogs/layouts/swot-analysis.json +0 -42
  548. package/dist/spec/catalogs/layouts/table-1x.json +0 -29
  549. package/dist/spec/catalogs/layouts/team-bio.json +0 -30
  550. package/dist/spec/catalogs/layouts/testimonial-grid.json +0 -38
  551. package/dist/spec/catalogs/layouts/text-1x-box-title-center.json +0 -31
  552. package/dist/spec/catalogs/layouts/text-1x-box-title-left.json +0 -31
  553. package/dist/spec/catalogs/layouts/text-1x-center-box-title-center.json +0 -31
  554. package/dist/spec/catalogs/layouts/text-1x-center-box-title-left.json +0 -31
  555. package/dist/spec/catalogs/layouts/text-1x-center-box.json +0 -26
  556. package/dist/spec/catalogs/layouts/text-1x-center-title-center.json +0 -30
  557. package/dist/spec/catalogs/layouts/text-1x-center-title-left.json +0 -30
  558. package/dist/spec/catalogs/layouts/text-1x-center.json +0 -25
  559. package/dist/spec/catalogs/layouts/text-1x-left-box.json +0 -26
  560. package/dist/spec/catalogs/layouts/text-1x-title-center.json +0 -30
  561. package/dist/spec/catalogs/layouts/text-1x.json +0 -23
  562. package/dist/spec/catalogs/layouts/text-2x-box-title-center.json +0 -37
  563. package/dist/spec/catalogs/layouts/text-2x-box-vertical-title-left.json +0 -37
  564. package/dist/spec/catalogs/layouts/text-2x-center-box-title-center.json +0 -37
  565. package/dist/spec/catalogs/layouts/text-2x-center-box-vertical-title-left.json +0 -37
  566. package/dist/spec/catalogs/layouts/text-2x-center-box.json +0 -32
  567. package/dist/spec/catalogs/layouts/text-2x-center-title-center.json +0 -36
  568. package/dist/spec/catalogs/layouts/text-2x-center-vertical-title-left.json +0 -36
  569. package/dist/spec/catalogs/layouts/text-2x-center.json +0 -31
  570. package/dist/spec/catalogs/layouts/text-2x-left-box.json +0 -32
  571. package/dist/spec/catalogs/layouts/text-2x-title-center.json +0 -36
  572. package/dist/spec/catalogs/layouts/text-2x-vertical-title-left.json +0 -36
  573. package/dist/spec/catalogs/layouts/text-2x.json +0 -29
  574. package/dist/spec/catalogs/layouts/text-3x-box-title-center.json +0 -40
  575. package/dist/spec/catalogs/layouts/text-3x-box-vertical-title-left.json +0 -41
  576. package/dist/spec/catalogs/layouts/text-3x-center-box-title-center.json +0 -40
  577. package/dist/spec/catalogs/layouts/text-3x-center-box-vertical-title-left.json +0 -41
  578. package/dist/spec/catalogs/layouts/text-3x-center-box.json +0 -35
  579. package/dist/spec/catalogs/layouts/text-3x-center-title-center.json +0 -39
  580. package/dist/spec/catalogs/layouts/text-3x-center-vertical-title-left.json +0 -40
  581. package/dist/spec/catalogs/layouts/text-3x-center.json +0 -34
  582. package/dist/spec/catalogs/layouts/text-3x-left-box.json +0 -35
  583. package/dist/spec/catalogs/layouts/text-3x-left.json +0 -34
  584. package/dist/spec/catalogs/layouts/text-3x-title-center.json +0 -39
  585. package/dist/spec/catalogs/layouts/text-3x-vertical-title-left.json +0 -40
  586. package/dist/spec/catalogs/layouts/text-3x.json +0 -32
  587. package/dist/spec/catalogs/layouts/thank-you-cta.json +0 -28
  588. package/dist/spec/catalogs/layouts/three-column.json +0 -39
  589. package/dist/spec/catalogs/layouts/timeline-1x.json +0 -23
  590. package/dist/spec/catalogs/layouts/timeline.json +0 -32
  591. package/dist/spec/catalogs/layouts/title-center-box.json +0 -27
  592. package/dist/spec/catalogs/layouts/title-center-image-bottom.json +0 -34
  593. package/dist/spec/catalogs/layouts/title-center-image-top.json +0 -34
  594. package/dist/spec/catalogs/layouts/title-center.json +0 -26
  595. package/dist/spec/catalogs/layouts/title-left-image-bottom.json +0 -34
  596. package/dist/spec/catalogs/layouts/title-left-image-left.json +0 -34
  597. package/dist/spec/catalogs/layouts/title-left-image-right.json +0 -34
  598. package/dist/spec/catalogs/layouts/title-left-image-top.json +0 -34
  599. package/dist/spec/catalogs/layouts/title-slide.json +0 -28
  600. package/dist/spec/catalogs/layouts/title-subtitle.json +0 -23
  601. package/dist/spec/catalogs/layouts/title.json +0 -20
  602. package/dist/spec/catalogs/layouts/two-column.json +0 -36
  603. package/dist/spec/catalogs/layouts/venn-overlap.json +0 -29
  604. package/dist/spec/catalogs/layouts/waterfall-bridge.json +0 -39
  605. package/dist/spec/catalogs/layouts/wheel-radial.json +0 -29
  606. package/dist/spec/catalogs/manifest.json +0 -111
  607. package/dist/spec/catalogs/narratives/board-meeting.json +0 -192
  608. package/dist/spec/catalogs/narratives/business-narrative.json +0 -87
  609. package/dist/spec/catalogs/narratives/business-review.json +0 -119
  610. package/dist/spec/catalogs/narratives/capacity-planning.json +0 -88
  611. package/dist/spec/catalogs/narratives/challenge-resolution.json +0 -80
  612. package/dist/spec/catalogs/narratives/change-story.json +0 -64
  613. package/dist/spec/catalogs/narratives/classic-story.json +0 -78
  614. package/dist/spec/catalogs/narratives/company-intro.json +0 -96
  615. package/dist/spec/catalogs/narratives/conference-talk.json +0 -54
  616. package/dist/spec/catalogs/narratives/data-story.json +0 -65
  617. package/dist/spec/catalogs/narratives/early-startup-pitch.json +0 -119
  618. package/dist/spec/catalogs/narratives/educate.json +0 -95
  619. package/dist/spec/catalogs/narratives/employee-review.json +0 -87
  620. package/dist/spec/catalogs/narratives/failure-analysis.json +0 -104
  621. package/dist/spec/catalogs/narratives/focus.json +0 -120
  622. package/dist/spec/catalogs/narratives/golden-circle.json +0 -50
  623. package/dist/spec/catalogs/narratives/heros-journey.json +0 -64
  624. package/dist/spec/catalogs/narratives/index.json +0 -1041
  625. package/dist/spec/catalogs/narratives/innovation.json +0 -96
  626. package/dist/spec/catalogs/narratives/justice.json +0 -112
  627. package/dist/spec/catalogs/narratives/marketing-strategy.json +0 -111
  628. package/dist/spec/catalogs/narratives/performance-improvement-plan.json +0 -87
  629. package/dist/spec/catalogs/narratives/performance-review.json +0 -111
  630. package/dist/spec/catalogs/narratives/persuade.json +0 -94
  631. package/dist/spec/catalogs/narratives/persuasive-sales.json +0 -87
  632. package/dist/spec/catalogs/narratives/pitch-deck.json +0 -107
  633. package/dist/spec/catalogs/narratives/problem-solution.json +0 -61
  634. package/dist/spec/catalogs/narratives/product-launch.json +0 -104
  635. package/dist/spec/catalogs/narratives/project-proposal.json +0 -104
  636. package/dist/spec/catalogs/narratives/pyramid-principle.json +0 -48
  637. package/dist/spec/catalogs/narratives/qbr.json +0 -85
  638. package/dist/spec/catalogs/narratives/rags-to-riches.json +0 -80
  639. package/dist/spec/catalogs/narratives/reveal.json +0 -87
  640. package/dist/spec/catalogs/narratives/scqa.json +0 -55
  641. package/dist/spec/catalogs/narratives/situation-complication-resolution.json +0 -56
  642. package/dist/spec/catalogs/narratives/sparkline.json +0 -56
  643. package/dist/spec/catalogs/narratives/star-method.json +0 -56
  644. package/dist/spec/catalogs/narratives/status-update.json +0 -72
  645. package/dist/spec/catalogs/narratives/strategic-advisory.json +0 -85
  646. package/dist/spec/catalogs/narratives/strategic-narrative.json +0 -61
  647. package/dist/spec/catalogs/narratives/survey-analysis.json +0 -104
  648. package/dist/spec/catalogs/narratives/survival-story.json +0 -103
  649. package/dist/spec/catalogs/narratives/transformation-arc.json +0 -50
  650. package/dist/spec/catalogs/narratives/trend-analysis.json +0 -79
  651. package/dist/spec/catalogs/narratives/underdog-victory.json +0 -87
  652. package/dist/spec/catalogs/narratives/venture-pitch.json +0 -109
  653. package/dist/spec/catalogs/narratives/vision-roadmap.json +0 -65
  654. package/dist/spec/catalogs/narratives/weekly-progress.json +0 -103
  655. package/dist/spec/catalogs/narratives/what-so-what-now-what.json +0 -48
  656. package/dist/spec/catalogs/purposes/align.json +0 -16
  657. package/dist/spec/catalogs/purposes/decide.json +0 -16
  658. package/dist/spec/catalogs/purposes/educate.json +0 -16
  659. package/dist/spec/catalogs/purposes/index.json +0 -63
  660. package/dist/spec/catalogs/purposes/inform.json +0 -16
  661. package/dist/spec/catalogs/purposes/persuade.json +0 -16
  662. package/dist/spec/catalogs/purposes/pitch.json +0 -16
  663. package/dist/spec/catalogs/purposes/plan.json +0 -16
  664. package/dist/spec/catalogs/purposes/report.json +0 -16
  665. package/dist/spec/catalogs/purposes/sell.json +0 -16
  666. package/dist/spec/catalogs/social-platforms/bluesky.json +0 -14
  667. package/dist/spec/catalogs/social-platforms/facebook.json +0 -14
  668. package/dist/spec/catalogs/social-platforms/github.json +0 -15
  669. package/dist/spec/catalogs/social-platforms/index.json +0 -69
  670. package/dist/spec/catalogs/social-platforms/instagram.json +0 -13
  671. package/dist/spec/catalogs/social-platforms/linkedin.json +0 -15
  672. package/dist/spec/catalogs/social-platforms/mastodon.json +0 -14
  673. package/dist/spec/catalogs/social-platforms/threads.json +0 -13
  674. package/dist/spec/catalogs/social-platforms/tiktok.json +0 -14
  675. package/dist/spec/catalogs/social-platforms/x.json +0 -14
  676. package/dist/spec/catalogs/social-platforms/youtube.json +0 -14
  677. package/dist/spec/catalogs/themes/bold.json +0 -13
  678. package/dist/spec/catalogs/themes/classic.json +0 -13
  679. package/dist/spec/catalogs/themes/dark.json +0 -13
  680. package/dist/spec/catalogs/themes/index.json +0 -33
  681. package/dist/spec/catalogs/themes/minimal.json +0 -13
  682. package/dist/spec/catalogs/tones/authoritative.json +0 -31
  683. package/dist/spec/catalogs/tones/casual.json +0 -31
  684. package/dist/spec/catalogs/tones/conversational.json +0 -31
  685. package/dist/spec/catalogs/tones/formal.json +0 -31
  686. package/dist/spec/catalogs/tones/index.json +0 -51
  687. package/dist/spec/catalogs/tones/inspirational.json +0 -31
  688. package/dist/spec/catalogs/tones/persuasive.json +0 -32
  689. package/dist/spec/catalogs/tones/technical.json +0 -31
  690. package/dist/spec/previews/layouts/action-plan.html +0 -1
  691. package/dist/spec/previews/layouts/agenda.html +0 -1
  692. package/dist/spec/previews/layouts/appendix-index.html +0 -1
  693. package/dist/spec/previews/layouts/architecture-stack.html +0 -1
  694. package/dist/spec/previews/layouts/assumptions-dependencies.html +0 -1
  695. package/dist/spec/previews/layouts/before-after.html +0 -1
  696. package/dist/spec/previews/layouts/benchmark-target-table.html +0 -1
  697. package/dist/spec/previews/layouts/bullet-list.html +0 -1
  698. package/dist/spec/previews/layouts/business-model-canvas.html +0 -1
  699. package/dist/spec/previews/layouts/capability-map.html +0 -1
  700. package/dist/spec/previews/layouts/case-study.html +0 -1
  701. package/dist/spec/previews/layouts/chapter-recap.html +0 -1
  702. package/dist/spec/previews/layouts/circular-lifecycle.html +0 -1
  703. package/dist/spec/previews/layouts/comparison.html +0 -1
  704. package/dist/spec/previews/layouts/competitive-landscape.html +0 -1
  705. package/dist/spec/previews/layouts/customer-journey.html +0 -1
  706. package/dist/spec/previews/layouts/customer-logos.html +0 -1
  707. package/dist/spec/previews/layouts/dashboard.html +0 -1
  708. package/dist/spec/previews/layouts/data-visualization.html +0 -1
  709. package/dist/spec/previews/layouts/decision-tree.html +0 -1
  710. package/dist/spec/previews/layouts/detailed-data-table.html +0 -1
  711. package/dist/spec/previews/layouts/ecosystem-map.html +0 -1
  712. package/dist/spec/previews/layouts/executive-decision.html +0 -1
  713. package/dist/spec/previews/layouts/executive-summary.html +0 -1
  714. package/dist/spec/previews/layouts/faq.html +0 -1
  715. package/dist/spec/previews/layouts/feature-comparison-matrix.html +0 -1
  716. package/dist/spec/previews/layouts/forecast-scenario.html +0 -1
  717. package/dist/spec/previews/layouts/funnel-pyramid.html +0 -1
  718. package/dist/spec/previews/layouts/gantt-project-plan.html +0 -1
  719. package/dist/spec/previews/layouts/geographic-map.html +0 -1
  720. package/dist/spec/previews/layouts/heatmap-cohort.html +0 -1
  721. package/dist/spec/previews/layouts/hub-and-spoke.html +0 -1
  722. package/dist/spec/previews/layouts/icon-grid.html +0 -1
  723. package/dist/spec/previews/layouts/image-focus.html +0 -1
  724. package/dist/spec/previews/layouts/index.json +0 -357
  725. package/dist/spec/previews/layouts/key-takeaway.html +0 -1
  726. package/dist/spec/previews/layouts/kpi-scorecard.html +0 -1
  727. package/dist/spec/previews/layouts/logic-tree.html +0 -1
  728. package/dist/spec/previews/layouts/market-size.html +0 -1
  729. package/dist/spec/previews/layouts/matrix-quadrant.html +0 -1
  730. package/dist/spec/previews/layouts/network-dependency-map.html +0 -1
  731. package/dist/spec/previews/layouts/one-column-explainer.html +0 -1
  732. package/dist/spec/previews/layouts/org-chart.html +0 -1
  733. package/dist/spec/previews/layouts/persona-grid.html +0 -1
  734. package/dist/spec/previews/layouts/photo-grid.html +0 -1
  735. package/dist/spec/previews/layouts/pricing-table.html +0 -1
  736. package/dist/spec/previews/layouts/process-flow.html +0 -1
  737. package/dist/spec/previews/layouts/product-feature.html +0 -1
  738. package/dist/spec/previews/layouts/pros-cons.html +0 -1
  739. package/dist/spec/previews/layouts/qa-discussion.html +0 -1
  740. package/dist/spec/previews/layouts/quote-highlight.html +0 -1
  741. package/dist/spec/previews/layouts/raci-matrix.html +0 -1
  742. package/dist/spec/previews/layouts/risk-heatmap.html +0 -1
  743. package/dist/spec/previews/layouts/roadmap.html +0 -1
  744. package/dist/spec/previews/layouts/screenshot-walkthrough.html +0 -1
  745. package/dist/spec/previews/layouts/section-divider.html +0 -1
  746. package/dist/spec/previews/layouts/single-message-statement.html +0 -1
  747. package/dist/spec/previews/layouts/stats-metrics.html +0 -1
  748. package/dist/spec/previews/layouts/status-rag.html +0 -1
  749. package/dist/spec/previews/layouts/swimlane-process.html +0 -1
  750. package/dist/spec/previews/layouts/swot-analysis.html +0 -1
  751. package/dist/spec/previews/layouts/team-bio.html +0 -1
  752. package/dist/spec/previews/layouts/testimonial-grid.html +0 -1
  753. package/dist/spec/previews/layouts/thank-you-cta.html +0 -1
  754. package/dist/spec/previews/layouts/three-column.html +0 -1
  755. package/dist/spec/previews/layouts/timeline.html +0 -1
  756. package/dist/spec/previews/layouts/title-slide.html +0 -1
  757. package/dist/spec/previews/layouts/two-column.html +0 -1
  758. package/dist/spec/previews/layouts/venn-overlap.html +0 -1
  759. package/dist/spec/previews/layouts/waterfall-bridge.html +0 -1
  760. 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,447 @@ 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 (!Array.isArray(row)) {
2105
+ grid("layout-template", `/areas/${index}`, "each row is an array of area names; use nested arrays instead of space-separated strings");
2106
+ return [];
2107
+ }
2108
+ const words = [];
2109
+ if (!row.length) grid("layout-template", `/areas/${index}`, 'a row needs at least one area name or "."');
2110
+ row.forEach((cell, column) => {
2111
+ if (typeof cell !== "string") grid("layout-template", `/areas/${index}/${column}`, 'each cell is one area name or "."');
2112
+ else {
2113
+ words.push(cell);
2114
+ if (cell !== "." && !NAME.test(cell)) grid("layout-template", `/areas/${index}/${column}`, `'${cell}' is not an area name (lowercase letters, digits and hyphens, starting with a letter) or "."`);
2115
+ }
2116
+ });
2117
+ return words;
2118
+ });
2119
+ const width = cells[0]?.length ?? 0;
2120
+ cells.forEach((row, index) => {
2121
+ 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}`);
2122
+ });
2123
+ if (width > MAX_TEMPLATE_TRACKS) grid("layout-template", "/areas", `a template has at most ${MAX_TEMPLATE_TRACKS} columns; this one has ${width}`);
2124
+ const columns2 = value.columns === void 0 ? Array.from({ length: width }, () => 1) : value.columns;
2125
+ const rows3 = value.rows === void 0 ? Array.from({ length: cells.length }, () => 1) : value.rows;
2126
+ 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})`);
2127
+ 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})`);
2128
+ if (issues.length) return { issues };
2129
+ const bounds = /* @__PURE__ */ new Map();
2130
+ cells.forEach((row, r) => {
2131
+ row.forEach((name, c) => {
2132
+ if (name === ".") return;
2133
+ const found = bounds.get(name);
2134
+ if (!found) bounds.set(name, { top: r, left: c, bottom: r, right: c, count: 1 });
2135
+ else {
2136
+ found.top = Math.min(found.top, r);
2137
+ found.left = Math.min(found.left, c);
2138
+ found.bottom = Math.max(found.bottom, r);
2139
+ found.right = Math.max(found.right, c);
2140
+ found.count++;
2141
+ }
2142
+ });
2143
+ });
2144
+ const list = [];
2145
+ for (const [name, box] of bounds) {
2146
+ const filled = (box.bottom - box.top + 1) * (box.right - box.left + 1);
2147
+ let rectangle = filled === box.count;
2148
+ for (let r = box.top; rectangle && r <= box.bottom; r++) for (let c = box.left; c <= box.right; c++) if (cells[r][c] !== name) {
2149
+ rectangle = false;
2150
+ break;
2151
+ }
2152
+ if (!rectangle) {
2153
+ grid("layout-template", "/areas", `the cells of '${name}' do not form one filled rectangle`);
2154
+ continue;
2155
+ }
2156
+ 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) });
2157
+ }
2158
+ if (issues.length) return { issues };
2159
+ list.sort((a, b) => a.row - b.row || a.column - b.column);
2160
+ const entries = record4(value.regions);
2161
+ const region = (path, message) => grid("layout-region", path, message);
2162
+ 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");
2163
+ for (const name of Object.keys(entries)) {
2164
+ if (reserved.has(name)) region(`/regions/${pointerSegment(name)}`, `'${name}' is reserved and cannot name a region (reserved: ${RESERVED_REGION_NAMES.join(", ")})`);
2165
+ else if (!bounds.has(name)) region(`/regions/${pointerSegment(name)}`, `region '${name}' has no area in areas`);
2166
+ }
2167
+ for (const area of list) {
2168
+ if (area.heading) continue;
2169
+ if (reserved.has(area.name)) {
2170
+ if (!Object.hasOwn(entries, area.name)) region("/areas", `'${area.name}' is reserved and cannot name a body area (reserved: ${RESERVED_REGION_NAMES.join(", ")})`);
2171
+ continue;
2172
+ }
2173
+ if (!Object.hasOwn(entries, area.name)) region("/regions", `body area '${area.name}' has no entry in regions`);
2174
+ }
2175
+ if (bounds.has("subtitle") && !bounds.has("title")) region("/areas", "a 'subtitle' area needs a 'title' area");
2176
+ for (const [name, entry] of Object.entries(entries)) {
2177
+ const raw = record4(entry);
2178
+ 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)}`);
2179
+ }
2180
+ const regions = list.filter((area) => !area.heading && !reserved.has(area.name) && Object.hasOwn(entries, area.name)).map((area) => layoutRegion(area.name, entries[area.name]));
2181
+ for (const entry of regions) if (!entry.accepts.length) region(`/regions/${pointerSegment(entry.name)}/accepts`, `region '${entry.name}' accepts no content kind`);
2182
+ 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`);
2183
+ if (issues.length) return { issues };
2184
+ const overflowRegion = typeof value.overflowRegion === "string" ? value.overflowRegion : regions.find((entry) => entry.role === "primary" && entry.flow !== "none")?.name;
2185
+ return {
2186
+ issues,
2187
+ template: {
2188
+ rows: rows3.slice(),
2189
+ columns: columns2.slice(),
2190
+ grid: cells,
2191
+ areas: list,
2192
+ regions,
2193
+ ...overflowRegion !== void 0 ? { overflowRegion } : {},
2194
+ title: bounds.has("title"),
2195
+ subtitle: bounds.has("subtitle")
2196
+ }
2072
2197
  };
2073
- visit(layoutSlots(layout));
2074
- return leaves;
2075
2198
  }
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));
2199
+ function layoutTemplateIssues(layout) {
2200
+ return isLayoutTemplate(layout) ? parse(layout).issues : [];
2083
2201
  }
2084
- function hasPlaceholderGroups(layout) {
2085
- return Array.isArray(layout?.placeholders) && layout.placeholders.some(isPlaceholderGroup);
2202
+ function layoutTemplate(layout) {
2203
+ const parsed = parse(layout);
2204
+ if (!parsed.template) throw new OPFLayoutTemplateError(parsed.issues);
2205
+ return parsed.template;
2086
2206
  }
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
- }
2207
+
2208
+ // src/bind-regions.ts
2209
+ var FIELDS = ["text", "items", "bullets", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
2210
+ 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" };
2211
+ var IMAGE_EDGES = ["left", "right", "top", "bottom"];
2212
+ var PROMOTED_REGION_KEY = /^(top|middle|bottom)(\+(top|middle|bottom))*(:(left|center|right)(\+(left|center|right))*)?$|^(left|center|right)(\+(left|center|right))*$/;
2213
+ var record5 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
2214
+ var empty = (value) => value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
2215
+ function blockKind(block) {
2216
+ const value = record5(block);
2217
+ if (Array.isArray(value.blocks)) return "group";
2218
+ if (typeof value.type === "string" && value.type !== "group" && Object.values(FIELD_KINDS).includes(value.type)) return value.type;
2219
+ const field = FIELDS.find((name) => value[name] !== void 0);
2220
+ return field ? FIELD_KINDS[field] : "text";
2221
+ }
2222
+ function leafKinds(block, into = /* @__PURE__ */ new Set(), depth = 0) {
2223
+ if (depth > 32) return into;
2224
+ for (const child of Array.isArray(block.blocks) ? block.blocks : []) {
2225
+ const value = record5(child);
2226
+ if (Array.isArray(value.blocks)) leafKinds(value, into, depth + 1);
2227
+ else into.add(blockKind(value));
2228
+ }
2229
+ return into;
2230
+ }
2231
+ function regionAccepts(region, block) {
2232
+ const kind2 = blockKind(block);
2233
+ if (region.accepts.includes(kind2)) return true;
2234
+ if (kind2 !== "group") return false;
2235
+ const kinds = leafKinds(record5(block));
2236
+ return kinds.size > 0 && [...kinds].every((leaf) => region.accepts.includes(leaf));
2237
+ }
2238
+ function placedImageBlocks(slide) {
2239
+ const value = record5(slide);
2240
+ const placed = /* @__PURE__ */ new Set();
2241
+ if (!Array.isArray(value.blocks) || Object.keys(value).some((key) => PROMOTED_REGION_KEY.test(key))) return placed;
2242
+ const used = /* @__PURE__ */ new Set();
2243
+ value.blocks.forEach((block, index) => {
2244
+ const host = record5(block);
2245
+ if (Array.isArray(host.blocks) || host.image === void 0 || host.placement === void 0) return;
2246
+ const edge = record5(host.placement).edge;
2247
+ if (!IMAGE_EDGES.includes(edge) || used.has(edge)) return;
2248
+ used.add(edge);
2249
+ placed.add(index);
2250
+ });
2251
+ return placed;
2252
+ }
2253
+ function rootNodes(slide, slideIndex = 0) {
2254
+ const value = record5(slide), base = `slides.${slideIndex}`;
2255
+ if (Array.isArray(value.blocks)) {
2256
+ const placed = placedImageBlocks(value);
2257
+ return value.blocks.flatMap((block, index) => {
2258
+ const host = record5(block);
2259
+ if (placed.has(index)) return [];
2260
+ if (!Array.isArray(host.blocks) && FIELDS.every((field) => empty(host[field]))) return [];
2261
+ if (Array.isArray(host.blocks) && !host.blocks.length) return [];
2262
+ return [{ path: `${base}.blocks.${index}`, kind: blockKind(host), block: index, value: host }];
2263
+ });
2264
+ }
2265
+ const nodes = [];
2266
+ for (const field of FIELDS) {
2267
+ if (empty(value[field]) || field === "bullets" && !empty(value.text)) continue;
2268
+ const fields2 = field === "text" && !empty(value.bullets) ? ["text", "bullets"] : [field];
2269
+ nodes.push({ path: `${base}.${field}`, kind: FIELD_KINDS[field], fields: fields2, value: Object.fromEntries(fields2.map((name) => [name, value[name]])) });
2270
+ }
2271
+ return nodes;
2272
+ }
2273
+ function regionRoleRank(role, kind2) {
2274
+ const media = kind2 === "image" || kind2 === "video";
2275
+ return media ? { media: 0, primary: 1, secondary: 2, supporting: 3 }[role] : { primary: 0, secondary: 1, supporting: 2, media: 3 }[role];
2276
+ }
2277
+ function bindRegions(slide, layout, options = {}) {
2278
+ const template = layoutTemplate(layout);
2279
+ const value = record5(slide), index = options.slideIndex ?? 0;
2280
+ const regions = template.regions.map((region) => ({ name: region.name, blocks: [], overflow: [] }));
2281
+ const result = { regions, below: [], diagnostics: [] };
2282
+ if (Object.keys(value).some((key) => PROMOTED_REGION_KEY.test(key))) return result;
2283
+ const byName = new Map(template.regions.map((region, order2) => [region.name, { region, binding: regions[order2], order: order2 }]));
2284
+ const room = (name) => {
2285
+ const entry = byName.get(name);
2286
+ return entry.binding.blocks.length < entry.region.max;
2287
+ };
2288
+ const nodes = rootNodes(value, index);
2289
+ const rest = [];
2290
+ for (const node of nodes) {
2291
+ const pin = node.block !== void 0 ? node.value.region : void 0;
2292
+ if (typeof pin !== "string") {
2293
+ rest.push(node);
2294
+ continue;
2104
2295
  }
2296
+ const target = byName.get(pin), pinPath = `${node.path}.region`;
2297
+ 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.` });
2298
+ 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.` });
2299
+ 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.` });
2300
+ else {
2301
+ target.binding.blocks.push({ path: node.path, kind: node.kind, block: node.block, pinned: true });
2302
+ continue;
2303
+ }
2304
+ rest.push(node);
2305
+ }
2306
+ const overflowName = template.overflowRegion;
2307
+ for (const node of rest) {
2308
+ const bound = { path: node.path, kind: node.kind, ...node.block !== void 0 ? { block: node.block } : {}, ...node.fields ? { fields: node.fields } : {} };
2309
+ let best;
2310
+ for (const [name, entry] of byName) {
2311
+ if (!regionAccepts(entry.region, node.value) || !room(name)) continue;
2312
+ const rank = regionRoleRank(entry.region.role, node.kind);
2313
+ if (!best || rank < best.rank || rank === best.rank && entry.order < best.order) best = { rank, order: entry.order, name };
2314
+ }
2315
+ if (best) {
2316
+ byName.get(best.name).binding.blocks.push(bound);
2317
+ continue;
2318
+ }
2319
+ if (overflowName === void 0) {
2320
+ result.below.push(bound);
2321
+ 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." });
2322
+ continue;
2323
+ }
2324
+ const overflow = byName.get(overflowName);
2325
+ if (room(overflowName)) {
2326
+ overflow.binding.blocks.push(bound);
2327
+ continue;
2328
+ }
2329
+ overflow.binding.overflow.push(bound);
2330
+ 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.` });
2331
+ }
2332
+ const order = new Map(nodes.map((node, position) => [node.path, position]));
2333
+ for (const binding of regions) binding.blocks.sort((a, b) => order.get(a.path) - order.get(b.path));
2334
+ return result;
2335
+ }
2336
+
2337
+ // src/template-geometry.ts
2338
+ function gridFlowShape(count, landscape) {
2339
+ if (!Number.isInteger(count) || count < 1) return { columns: 1, rows: 0, perRow: [] };
2340
+ let columns2;
2341
+ if (landscape) columns2 = count <= 3 ? count : count === 4 ? 2 : count <= 6 ? 3 : 4;
2342
+ else columns2 = count <= 3 ? 1 : count <= 6 ? 2 : Math.ceil(count / 3);
2343
+ const rows3 = Math.ceil(count / columns2);
2344
+ const perRow = Array.from({ length: rows3 }, (_, row) => Math.min(columns2, count - row * columns2));
2345
+ return { columns: columns2, rows: rows3, perRow };
2346
+ }
2347
+ function flowShape(arrangement, count, landscape) {
2348
+ if (count < 1) return { columns: 1, rows: 0, perRow: [] };
2349
+ if (arrangement === "row") return { columns: count, rows: 1, perRow: [count] };
2350
+ if (arrangement === "column") return { columns: 1, rows: count, perRow: Array.from({ length: count }, () => 1) };
2351
+ return gridFlowShape(count, landscape);
2352
+ }
2353
+ function flowCells(shape, box, requestedGap) {
2354
+ if (!shape.rows) return { cells: [], gap: requestedGap };
2355
+ const gap = Math.max(0, Math.min(requestedGap, box.width / (shape.columns * 2), box.height / (shape.rows * 2)));
2356
+ const width = (box.width - gap * (shape.columns - 1)) / shape.columns;
2357
+ const height = (box.height - gap * (shape.rows - 1)) / shape.rows;
2358
+ const cells = [];
2359
+ shape.perRow.forEach((count, row) => {
2360
+ const used = count * width + (count - 1) * gap, start = box.x + (box.width - used) / 2;
2361
+ 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 });
2362
+ });
2363
+ return { cells, gap };
2364
+ }
2365
+ function columnWidths(sizes, total, gap) {
2366
+ const sum = sizes.reduce((a, b) => a + b, 0);
2367
+ const rest = Math.max(0, total - Math.max(0, sizes.length - 1) * gap);
2368
+ return sizes.map((size) => sum > 0 ? rest * size / sum : 0);
2369
+ }
2370
+ function collapseAreas(grid, empty2, heading, absorbs = () => true) {
2371
+ const owner = grid.map((row) => [...row]);
2372
+ const joined = /* @__PURE__ */ new Map();
2373
+ const rect = (name) => {
2374
+ let top = Infinity, left = Infinity, bottom = -1, right = -1;
2375
+ owner.forEach((row, r) => {
2376
+ row.forEach((cell, c) => {
2377
+ if (cell === name) {
2378
+ top = Math.min(top, r);
2379
+ left = Math.min(left, c);
2380
+ bottom = Math.max(bottom, r);
2381
+ right = Math.max(right, c);
2382
+ }
2383
+ });
2384
+ });
2385
+ return bottom < 0 ? void 0 : { row: top, column: left, rowSpan: bottom - top + 1, columnSpan: right - left + 1 };
2105
2386
  };
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;
2387
+ const order = [];
2388
+ for (const row of owner) for (const cell of row) if (cell !== "." && !order.includes(cell)) order.push(cell);
2389
+ const pending = order.filter((name) => empty2.has(name));
2390
+ let changed = true;
2391
+ while (changed) {
2392
+ changed = false;
2393
+ for (const name of pending) {
2394
+ if (joined.has(name)) continue;
2395
+ const own3 = rect(name);
2396
+ if (!own3) continue;
2397
+ const neighbour = (side) => {
2398
+ const cells = [];
2399
+ if (side === "start" || side === "end") {
2400
+ const column = side === "start" ? own3.column - 1 : own3.column + own3.columnSpan;
2401
+ if (column < 0 || column >= (owner[0]?.length ?? 0)) return void 0;
2402
+ for (let r = own3.row; r < own3.row + own3.rowSpan; r++) cells.push(owner[r][column]);
2403
+ } else {
2404
+ const row = side === "above" ? own3.row - 1 : own3.row + own3.rowSpan;
2405
+ if (row < 0 || row >= owner.length) return void 0;
2406
+ for (let c = own3.column; c < own3.column + own3.columnSpan; c++) cells.push(owner[row][c]);
2407
+ }
2408
+ const candidate = cells[0];
2409
+ if (candidate === void 0 || candidate === "." || candidate === name || cells.some((cell) => cell !== candidate)) return void 0;
2410
+ if (empty2.has(candidate) || !absorbs(candidate)) return void 0;
2411
+ const other = rect(candidate);
2412
+ const fits = side === "start" || side === "end" ? other.row === own3.row && other.rowSpan === own3.rowSpan : other.column === own3.column && other.columnSpan === own3.columnSpan;
2413
+ return fits ? candidate : void 0;
2414
+ };
2415
+ const sides = ["start", "end", "below", "above"];
2416
+ let target;
2417
+ for (const body of [true, false]) {
2418
+ for (const side of sides) {
2419
+ const candidate = neighbour(side);
2420
+ if (candidate !== void 0 && heading(candidate) !== body) {
2421
+ target = candidate;
2422
+ break;
2423
+ }
2424
+ }
2425
+ if (target !== void 0) break;
2426
+ }
2427
+ if (target === void 0) continue;
2428
+ for (const row of owner) row.forEach((cell, c) => {
2429
+ if (cell === name) row[c] = target;
2430
+ });
2431
+ joined.set(name, target);
2432
+ changed = true;
2433
+ }
2111
2434
  }
2112
- return { kind: kind2, count, heading };
2435
+ return { grid: owner, joined };
2436
+ }
2437
+ function areaRects(grid) {
2438
+ const rects = /* @__PURE__ */ new Map();
2439
+ grid.forEach((row, r) => {
2440
+ row.forEach((name, c) => {
2441
+ if (name === ".") return;
2442
+ const found = rects.get(name);
2443
+ if (!found) rects.set(name, { row: r, column: c, rowSpan: 1, columnSpan: 1 });
2444
+ else {
2445
+ found.rowSpan = Math.max(found.rowSpan, r - found.row + 1);
2446
+ found.columnSpan = Math.max(found.columnSpan, c - found.column + 1);
2447
+ }
2448
+ });
2449
+ });
2450
+ return rects;
2451
+ }
2452
+ function listColumnBreaks(heights, levels, count) {
2453
+ const n = heights.length;
2454
+ if (count <= 1 || n < 2) return [];
2455
+ const allowed = Array.from({ length: n }, (_, index) => index > 0 && (levels[index] ?? 0) === 0);
2456
+ const prefix = [0];
2457
+ for (const height of heights) prefix.push(prefix.at(-1) + height);
2458
+ const span = (from, to) => prefix[to] - prefix[from];
2459
+ const memo = /* @__PURE__ */ new Map();
2460
+ const solve = (start, columns2) => {
2461
+ const key = `${start}:${columns2}`;
2462
+ const found = memo.get(key);
2463
+ if (found) return found;
2464
+ let best = { cost: span(start, n), breaks: [] };
2465
+ if (columns2 > 1) for (let next = start + 1; next < n; next++) {
2466
+ if (!allowed[next]) continue;
2467
+ const rest = solve(next, columns2 - 1);
2468
+ const cost = Math.max(span(start, next), rest.cost);
2469
+ if (cost < best.cost - 1e-9) best = { cost, breaks: [next, ...rest.breaks] };
2470
+ }
2471
+ memo.set(key, best);
2472
+ return best;
2473
+ };
2474
+ return solve(0, count).breaks;
2475
+ }
2476
+ function allocateRows(rows3, total, gap) {
2477
+ const auto = rows3.map((row) => row.size === "auto" ? Math.max(0, Math.min(row.need, row.kind === "below" ? total : total / 2)) : 0);
2478
+ const visible = rows3.filter((row, index) => row.size !== "auto" || auto[index] > 0).length;
2479
+ const headings2 = rows3.reduce((sum, row, index) => sum + (row.kind === "heading" ? auto[index] : 0), 0);
2480
+ const space = Math.max(0, total - headings2 - Math.max(0, visible - 1) * gap);
2481
+ const numeric = rows3.reduce((sum, row) => sum + (row.size === "auto" ? 0 : row.size), 0);
2482
+ const numericNeed = rows3.reduce((sum, row) => sum + (row.size === "auto" ? 0 : Math.max(0, row.need)), 0);
2483
+ const reserve = numeric > 0 ? Math.min(numericNeed, space / 2) : 0;
2484
+ const body = rows3.reduce((sum, row, index) => sum + (row.size === "auto" && row.kind !== "heading" ? auto[index] : 0), 0);
2485
+ const factor = body > space - reserve && body > 0 ? Math.max(0, space - reserve) / body : 1;
2486
+ const heights = rows3.map((row, index) => row.size === "auto" ? row.kind === "heading" ? auto[index] : auto[index] * factor : 0);
2487
+ const rest = Math.max(0, space - heights.reduce((sum, height, index) => sum + (rows3[index].kind === "heading" ? 0 : height), 0));
2488
+ return rows3.map((row, index) => row.size === "auto" ? heights[index] : numeric > 0 ? rest * row.size / numeric : 0);
2113
2489
  }
2114
2490
 
2115
2491
  // src/direction.ts
@@ -2152,6 +2528,215 @@ function paragraphDirectionAt(text2, deckDirection) {
2152
2528
  };
2153
2529
  }
2154
2530
 
2531
+ // src/catalog-refs.ts
2532
+ var catalogKinds = ["layouts", "themes", "colorSchemes", "fontSchemes", "narratives", "audiences", "purposes", "tones"];
2533
+ var CATALOG_REFERENCE_PATTERN = /^(?:([a-z][a-z0-9-]*):)?([a-z][a-z0-9-]*)$/;
2534
+ var CATALOG_GROUP_PATTERN = /^[a-z][a-z0-9-]*$/;
2535
+ function provenanceOf(found) {
2536
+ const { record: _record, ...provenance } = found;
2537
+ return provenance;
2538
+ }
2539
+ var OPFCatalogsOptionError = class extends TypeError {
2540
+ code = "invalid-catalogs";
2541
+ constructor(entry, detail) {
2542
+ super(`${entry}: the catalogs option must be an array of registered catalogs ({ source, <kind>: { <id>: record } } with known catalog kinds); ${detail}.`);
2543
+ this.name = "OPFCatalogsOptionError";
2544
+ }
2545
+ };
2546
+ function checkCatalogsOption(catalogs, entry) {
2547
+ if (catalogs === void 0) return [];
2548
+ if (!Array.isArray(catalogs)) throw new OPFCatalogsOptionError(entry, `got ${catalogs === null ? "null" : typeof catalogs}`);
2549
+ catalogs.forEach((catalog, index) => {
2550
+ if (!isRec(catalog) || typeof catalog.source !== "string") throw new OPFCatalogsOptionError(entry, `catalogs[${index}] is not an object with a string source`);
2551
+ for (const [kind2, records] of Object.entries(catalog)) {
2552
+ if (kind2 === "source") continue;
2553
+ if (!catalogKinds.includes(kind2)) throw new OPFCatalogsOptionError(entry, `catalogs[${index}].${kind2} is not a catalog kind`);
2554
+ if (!isRec(records)) throw new OPFCatalogsOptionError(entry, `catalogs[${index}].${kind2} is not an object of records keyed by id`);
2555
+ }
2556
+ });
2557
+ return catalogs;
2558
+ }
2559
+ var OPFUnresolvedReferenceError = class extends Error {
2560
+ diagnostics;
2561
+ constructor(diagnostics) {
2562
+ super(diagnostics.map((diagnostic) => diagnostic.message).join(" "));
2563
+ this.name = "OPFUnresolvedReferenceError";
2564
+ this.diagnostics = diagnostics;
2565
+ }
2566
+ };
2567
+ var isRec = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2568
+ var rec = (value) => isRec(value) ? value : {};
2569
+ var own2 = (value, key) => Object.hasOwn(value, key);
2570
+ function parseReference(reference) {
2571
+ if (typeof reference !== "string") return void 0;
2572
+ const match = CATALOG_REFERENCE_PATTERN.exec(reference);
2573
+ if (!match) return void 0;
2574
+ const [, group, id] = match;
2575
+ return group === void 0 ? { id } : { group, id };
2576
+ }
2577
+ function groupsOf(document) {
2578
+ return rec(rec(document).catalogs);
2579
+ }
2580
+ function catalogGroupDeclared(document, name) {
2581
+ const groups = groupsOf(document);
2582
+ return own2(groups, name) && (isRec(groups[name]) || name === "default" && groups[name] === false);
2583
+ }
2584
+ function catalogGroupSource(document, name, options = {}) {
2585
+ if (name === "custom") return void 0;
2586
+ const group = groupsOf(document)[name];
2587
+ if (name === "default") {
2588
+ if (group === false) return void 0;
2589
+ const source2 = rec(group).source;
2590
+ return typeof source2 === "string" ? source2 : options.catalogs?.[0]?.source;
2591
+ }
2592
+ const source = rec(group).source;
2593
+ return typeof source === "string" ? source : void 0;
2594
+ }
2595
+ function registeredCatalog(source, options = {}) {
2596
+ if (source === void 0) return void 0;
2597
+ return options.catalogs?.find((catalog) => catalog?.source === source);
2598
+ }
2599
+ function lookupInGroup(document, kind2, group, id, reference, options = {}) {
2600
+ const groups = groupsOf(document);
2601
+ if (group === "default" && groups.default === false) return void 0;
2602
+ if (group !== "default" && group !== "custom" && !isRec(groups[group])) return void 0;
2603
+ const source = catalogGroupSource(document, group, options);
2604
+ const embedded = rec(rec(groups[group])[kind2]);
2605
+ if (own2(embedded, id) && isRec(embedded[id])) {
2606
+ return { kind: kind2, reference, id, group, ...source !== void 0 ? { source } : {}, origin: "document", record: embedded[id] };
2607
+ }
2608
+ if (group === "custom") return void 0;
2609
+ const hosted = registeredCatalog(source, options)?.[kind2];
2610
+ if (hosted && own2(hosted, id) && isRec(hosted[id])) {
2611
+ return { kind: kind2, reference, id, group, ...source !== void 0 ? { source } : {}, origin: "host", record: hosted[id] };
2612
+ }
2613
+ return void 0;
2614
+ }
2615
+ function resolveReference(document, kind2, reference, options = {}) {
2616
+ checkCatalogsOption(options.catalogs, "resolveReference");
2617
+ const parsed = parseReference(reference);
2618
+ if (!parsed) return void 0;
2619
+ const written = reference;
2620
+ if (parsed.group !== void 0) return lookupInGroup(document, kind2, parsed.group, parsed.id, written, options);
2621
+ const order = [...new Set([options.group, "custom", "default"].filter((group) => typeof group === "string"))];
2622
+ for (const group of order) {
2623
+ const found = lookupInGroup(document, kind2, group, parsed.id, written, options);
2624
+ if (found) return found;
2625
+ }
2626
+ return void 0;
2627
+ }
2628
+ var KIND_NOUNS = {
2629
+ layouts: "Layout",
2630
+ themes: "Theme",
2631
+ colorSchemes: "Colour scheme",
2632
+ fontSchemes: "Font scheme",
2633
+ narratives: "Narrative",
2634
+ audiences: "Audience",
2635
+ purposes: "Purpose",
2636
+ tones: "Tone"
2637
+ };
2638
+ function unresolvedReference(document, kind2, reference, path, options = {}) {
2639
+ const parsed = parseReference(reference);
2640
+ const group = parsed?.group ?? "default";
2641
+ const source = catalogGroupSource(document, group, options);
2642
+ const noun = KIND_NOUNS[kind2];
2643
+ 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"}`;
2644
+ const fallback = kind2 === "layouts" ? "automatic" : "engine-default";
2645
+ return {
2646
+ code: "unresolved-reference",
2647
+ kind: kind2,
2648
+ reference,
2649
+ path,
2650
+ group,
2651
+ ...source !== void 0 ? { source } : {},
2652
+ fallback,
2653
+ message: `${noun} '${reference}' resolves nowhere: ${where}; ${fallback === "automatic" ? "the slide composes automatically" : "the engine default is used"}.`
2654
+ };
2655
+ }
2656
+ var pushReference = (sites, kind2, value, path, group) => {
2657
+ if (typeof value === "string" && parseReference(value)) sites.push({ kind: kind2, reference: value, path, ...group !== void 0 ? { group } : {} });
2658
+ };
2659
+ var pushObjectReference = (sites, kind2, value, path, group) => {
2660
+ if (typeof value === "string") pushReference(sites, kind2, value, path, group);
2661
+ else if (isRec(value)) pushReference(sites, kind2, value.id, [...path, "id"], group);
2662
+ };
2663
+ function designSites(sites, design, path) {
2664
+ if (!isRec(design)) return;
2665
+ pushReference(sites, "themes", design.theme, [...path, "theme"]);
2666
+ pushObjectReference(sites, "colorSchemes", design.colorScheme, [...path, "colorScheme"]);
2667
+ pushObjectReference(sites, "fontSchemes", design.fontScheme, [...path, "fontScheme"]);
2668
+ }
2669
+ function recordReferenceSites(kind2, record9, path, group) {
2670
+ const sites = [];
2671
+ if (kind2 === "themes" && isRec(record9)) {
2672
+ pushObjectReference(sites, "colorSchemes", record9.colorScheme, [...path, "colorScheme"], group);
2673
+ pushObjectReference(sites, "fontSchemes", record9.fontScheme, [...path, "fontScheme"], group);
2674
+ }
2675
+ return sites;
2676
+ }
2677
+ function catalogReferenceSites(document, options = {}) {
2678
+ const deck = rec(document);
2679
+ const sites = [];
2680
+ pushReference(sites, "narratives", deck.narrative, ["narrative"]);
2681
+ if (Array.isArray(deck.audience)) deck.audience.forEach((entry, index) => {
2682
+ pushObjectReference(sites, "audiences", entry, ["audience", index]);
2683
+ });
2684
+ else pushObjectReference(sites, "audiences", deck.audience, ["audience"]);
2685
+ pushObjectReference(sites, "purposes", deck.purpose, ["purpose"]);
2686
+ pushObjectReference(sites, "tones", deck.tone, ["tone"]);
2687
+ if (isRec(deck.language)) {
2688
+ pushReference(sites, "fontSchemes", deck.language.fontScheme, ["language", "fontScheme"]);
2689
+ pushReference(sites, "fontSchemes", deck.language.googleFontScheme, ["language", "googleFontScheme"]);
2690
+ }
2691
+ designSites(sites, deck.design, ["design"]);
2692
+ if (options.slides !== false && Array.isArray(deck.slides))
2693
+ deck.slides.forEach((slide, index) => {
2694
+ if (!isRec(slide)) return;
2695
+ if (slide.layout !== "auto") pushReference(sites, "layouts", slide.layout, ["slides", index, "layout"]);
2696
+ designSites(sites, slide.design, ["slides", index, "design"]);
2697
+ });
2698
+ if (options.records !== false)
2699
+ for (const [group, value] of Object.entries(groupsOf(document))) {
2700
+ if (!isRec(value)) continue;
2701
+ for (const kind2 of catalogKinds)
2702
+ for (const [id, record9] of Object.entries(rec(value[kind2]))) sites.push(...recordReferenceSites(kind2, record9, ["catalogs", group, kind2, id], group));
2703
+ }
2704
+ return sites;
2705
+ }
2706
+ var dottedPath = (path) => path.join(".");
2707
+ var pointerPath = (path) => path.length ? `/${path.map((part) => String(part).replaceAll("~", "~0").replaceAll("/", "~1")).join("/")}` : "";
2708
+ function catalogRecords(document, kind2, options = {}) {
2709
+ checkCatalogsOption(options.catalogs, "catalogRecords");
2710
+ const result = [];
2711
+ const seen = /* @__PURE__ */ new Set();
2712
+ const add = (entry) => {
2713
+ if (seen.has(entry.reference)) return;
2714
+ seen.add(entry.reference);
2715
+ result.push(entry);
2716
+ };
2717
+ const groups = groupsOf(document);
2718
+ const names = [.../* @__PURE__ */ new Set(["custom", "default", ...Object.keys(groups)])];
2719
+ for (const group of names) {
2720
+ if (group === "default" && groups.default === false) continue;
2721
+ if (group !== "custom" && group !== "default" && !isRec(groups[group])) continue;
2722
+ const prefix = group === "custom" || group === "default" ? "" : `${group}:`;
2723
+ for (const id of Object.keys(rec(rec(groups[group])[kind2]))) {
2724
+ const found = lookupInGroup(document, kind2, group, id, `${prefix}${id}`, options);
2725
+ if (found) add(found);
2726
+ }
2727
+ if (group === "custom") continue;
2728
+ const hosted = registeredCatalog(catalogGroupSource(document, group, options), options)?.[kind2];
2729
+ for (const id of Object.keys(hosted ?? {})) {
2730
+ const found = lookupInGroup(document, kind2, group, id, `${prefix}${id}`, options);
2731
+ if (found) add(found);
2732
+ }
2733
+ }
2734
+ return result;
2735
+ }
2736
+ function embeddedCopy(record9) {
2737
+ return Object.fromEntries(Object.entries(rec(record9)).filter(([key]) => key !== "$schema" && key !== "id" && !key.startsWith("x-")).map(([key, value]) => [key, structuredClone(value)]));
2738
+ }
2739
+
2155
2740
  // src/generated/engine-data.ts
2156
2741
  var engineDefaultsSource = {
2157
2742
  "theme": {
@@ -2198,10 +2783,10 @@ var SOCIAL_PLATFORMS = engineVocabulariesSource.socialPlatforms;
2198
2783
  var LANGUAGES = engineVocabulariesSource.languages;
2199
2784
 
2200
2785
  // src/design-records.ts
2201
- var isRec = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2202
- var rec = (value) => isRec(value) ? value : {};
2786
+ var isRec2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
2787
+ var rec2 = (value) => isRec2(value) ? value : {};
2203
2788
  function resolveRecordReference(document, kind2, reference, path, fallback, options, diagnostics) {
2204
- const object2 = isRec(reference) ? reference : void 0;
2789
+ const object2 = isRec2(reference) ? reference : void 0;
2205
2790
  const id = typeof reference === "string" ? reference : typeof object2?.id === "string" ? object2.id : void 0;
2206
2791
  if (id === void 0) return { record: { ...fallback, ...object2 } };
2207
2792
  const found = resolveReference(document, kind2, id, options);
@@ -2210,27 +2795,27 @@ function resolveRecordReference(document, kind2, reference, path, fallback, opti
2210
2795
  }
2211
2796
  function resolveDesignRecords(document, slideIndex, options = {}) {
2212
2797
  checkCatalogsOption(options.catalogs, "resolveDesignRecords");
2213
- const deck = rec(document);
2798
+ const deck = rec2(document);
2214
2799
  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 };
2800
+ const own3 = slideIndex === void 0 ? {} : rec2(rec2(slides[slideIndex]).design);
2801
+ const shared = rec2(deck.design);
2802
+ const design = { ...shared, ...own3 };
2218
2803
  const slidePath = `slides.${slideIndex}.design`;
2219
2804
  const diagnostics = [];
2220
- const themePath = own2.theme !== void 0 ? `${slidePath}.theme` : "design.theme";
2805
+ const themePath = own3.theme !== void 0 ? `${slidePath}.theme` : "design.theme";
2221
2806
  const themeFound = typeof design.theme === "string" ? resolveReference(document, "themes", design.theme, options) : void 0;
2222
2807
  if (typeof design.theme === "string" && !themeFound) diagnostics.push(unresolvedReference(document, "themes", design.theme, themePath, options));
2223
2808
  const theme = themeFound ? { ...themeFound.record } : { ...ENGINE_DEFAULT_THEME };
2224
2809
  const inTheme = { ...options, ...themeFound ? { group: themeFound.group } : {} };
2225
2810
  const inThemePath = (key) => themeFound?.origin === "document" ? `catalogs.${themeFound.group}.themes.${themeFound.id}.${key}` : themePath;
2226
2811
  const colorFromDesign = design.colorScheme !== void 0;
2227
- const colorSchemePath = own2.colorScheme !== void 0 ? `${slidePath}.colorScheme` : shared.colorScheme !== void 0 ? "design.colorScheme" : inThemePath("colorScheme");
2812
+ const colorSchemePath = own3.colorScheme !== void 0 ? `${slidePath}.colorScheme` : shared.colorScheme !== void 0 ? "design.colorScheme" : inThemePath("colorScheme");
2228
2813
  const color = resolveRecordReference(document, "colorSchemes", colorFromDesign ? design.colorScheme : theme.colorScheme, colorFromDesign ? colorSchemePath : inThemePath("colorScheme"), ENGINE_DEFAULT_COLOR_SCHEME, colorFromDesign ? options : inTheme, diagnostics);
2229
2814
  const fontFromDesign = design.fontScheme !== void 0;
2230
- const fontSchemePath = own2.fontScheme !== void 0 ? `${slidePath}.fontScheme` : shared.fontScheme !== void 0 ? "design.fontScheme" : inThemePath("fontScheme");
2815
+ const fontSchemePath = own3.fontScheme !== void 0 ? `${slidePath}.fontScheme` : shared.fontScheme !== void 0 ? "design.fontScheme" : inThemePath("fontScheme");
2231
2816
  const font = resolveRecordReference(document, "fontSchemes", fontFromDesign ? design.fontScheme : theme.fontScheme, fontSchemePath, ENGINE_DEFAULT_FONT_SCHEME, fontFromDesign ? options : inTheme, diagnostics);
2232
2817
  const fontReference = fontFromDesign ? design.fontScheme : theme.fontScheme;
2233
- const fontSchemeReference = typeof fontReference === "string" ? fontReference : isRec(fontReference) && typeof fontReference.id === "string" ? fontReference.id : void 0;
2818
+ const fontSchemeReference = typeof fontReference === "string" ? fontReference : isRec2(fontReference) && typeof fontReference.id === "string" ? fontReference.id : void 0;
2234
2819
  const provenance = {
2235
2820
  ...themeFound ? { theme: provenanceOf(themeFound) } : {},
2236
2821
  ...color.provenance ? { colorScheme: color.provenance } : {},
@@ -2551,11 +3136,11 @@ function listNumbers(items, numbering) {
2551
3136
  const object2 = isObject(item) ? item : void 0;
2552
3137
  const level = object2?.level === void 0 ? 0 : object2.level;
2553
3138
  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}.`);
3139
+ const own3 = object2?.start;
3140
+ 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
3141
  const { style: authored, start, suffix } = numberingAtLevel(levels, level);
2557
3142
  const previous = counters[level];
2558
- const value = own2 ?? (previous === void 0 ? start : previous + 1);
3143
+ const value = own3 ?? (previous === void 0 ? start : previous + 1);
2559
3144
  counters[level] = value;
2560
3145
  counters.length = level + 1;
2561
3146
  const adapted = !numberingStyleDraws(authored, value);
@@ -2720,6 +3305,7 @@ function resolveColorRoles(colorScheme, options = {}) {
2720
3305
  background,
2721
3306
  surface,
2722
3307
  surfaceAlt: surfaceAltColor(surface, text2),
3308
+ border: dark ? "#475569" : "#CBD5E1",
2723
3309
  text: text2,
2724
3310
  textSecondary: keepAlpha(colorScheme.textSecondary) ?? (dark ? slot("light2", "#E2E8F0") : slot("dark2", "#334155")),
2725
3311
  hyperlink: readableLink(slot("hyperlink", DEFAULT_HYPERLINK), background, text2),
@@ -3624,8 +4210,8 @@ function codeSyntaxPalette(theme = {}, options = {}) {
3624
4210
  return palette;
3625
4211
  }
3626
4212
  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;
4213
+ const record9 = scheme && typeof scheme === "object" ? scheme : {};
4214
+ const pick = (role, slot, fallback) => normalize(record9[role]) ?? normalize(record9[slot]) ?? fallback;
3629
4215
  return codeSyntaxPalette({ primary: pick("primary", "accent1", "#2563EB"), secondary: pick("secondary", "accent2", "#0F766E"), accent: pick("accent", "accent3", "#F59E0B") }, options);
3630
4216
  }
3631
4217
 
@@ -3777,8 +4363,8 @@ var blend = (from, to, amount) => {
3777
4363
  return toHex(a.map((value, index) => value + (b[index] - value) * amount));
3778
4364
  };
3779
4365
  function codeHighlightColors(scheme, palette = codeSyntaxPaletteForScheme(scheme)) {
3780
- const record7 = scheme && typeof scheme === "object" ? scheme : {};
3781
- const primary = normalize(record7.primary) ?? normalize(record7.accent1) ?? "#2563EB";
4366
+ const record9 = scheme && typeof scheme === "object" ? scheme : {};
4367
+ const primary = normalize(record9.primary) ?? normalize(record9.accent1) ?? "#2563EB";
3782
4368
  const [hue, saturation] = toHsl(primary);
3783
4369
  const tint = fromHsl(hue, Math.min(saturation, 0.7), 0.45);
3784
4370
  const band = blend(CODE_PANEL_BACKGROUND, tint, CODE_HIGHLIGHT_BAND_TINT);
@@ -3975,7 +4561,7 @@ var CAPTION_FONT_RATIO = 0.6;
3975
4561
  var CAPTION_MAX_RATIO = 0.35;
3976
4562
  var FOOTNOTE_MAX_RATIO = 0.35;
3977
4563
  var CAPTIONABLE_FIELDS = Object.freeze(["image", "chart", "table", "video"]);
3978
- var record5 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
4564
+ var record6 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
3979
4565
  var isRecord3 = (value) => !!value && typeof value === "object" && !Array.isArray(value);
3980
4566
  var round = (value) => Math.round(value * 1e6) / 1e6 || value;
3981
4567
  var regionKey = /^(top|middle|bottom|left|center|right)([+:]|$)/;
@@ -3983,7 +4569,7 @@ var TEXT_FIELDS = ["text", "items", "bullets"];
3983
4569
  var HEADING_FIELDS = ["tag", "title", "subtitle"];
3984
4570
  function annotationText(value) {
3985
4571
  if (typeof value === "string") return value;
3986
- if (Array.isArray(value)) return value.map((run) => typeof run === "string" ? run : record5(run).text ?? "").join("");
4572
+ if (Array.isArray(value)) return value.map((run) => typeof run === "string" ? run : record6(run).text ?? "").join("");
3987
4573
  if (isRecord3(value) && value.text !== void 0) return annotationText(value.text);
3988
4574
  return value === void 0 || value === null ? "" : String(value);
3989
4575
  }
@@ -4015,7 +4601,7 @@ function walkCitationRuns(slide, basePath, visit) {
4015
4601
  });
4016
4602
  };
4017
4603
  const host = (node, path, depth) => {
4018
- const payload = record5(node);
4604
+ const payload = record6(node);
4019
4605
  if (Array.isArray(payload.blocks)) {
4020
4606
  if (depth > 32) return;
4021
4607
  payload.blocks.forEach((block, index) => {
@@ -4030,7 +4616,7 @@ function walkCitationRuns(slide, basePath, visit) {
4030
4616
  }
4031
4617
  if (isRecord3(payload.quote)) runs(payload.quote.text, `${path}.quote.text`);
4032
4618
  };
4033
- const value = record5(slide);
4619
+ const value = record6(slide);
4034
4620
  for (const field of HEADING_FIELDS) runs(value[field], `${basePath}.${field}`);
4035
4621
  const regions = Object.keys(value).filter((key) => regionKey.test(key)).sort();
4036
4622
  if (regions.length) {
@@ -4047,7 +4633,7 @@ function walkCitationRuns(slide, basePath, visit) {
4047
4633
  }
4048
4634
  var citationMarkerText = (numbers) => numbers.join(",");
4049
4635
  function referenceList(presentation) {
4050
- const list = record5(presentation).references;
4636
+ const list = record6(presentation).references;
4051
4637
  return Array.isArray(list) ? list.filter((item) => isRecord3(item) && typeof item.id === "string") : [];
4052
4638
  }
4053
4639
  function numberSlide(slide, slideIndex, references, numbering) {
@@ -4080,7 +4666,7 @@ function numberSlide(slide, slideIndex, references, numbering) {
4080
4666
  }
4081
4667
  function collectCitations(presentation) {
4082
4668
  const references = referenceList(presentation), numbering = { notes: [], byId: /* @__PURE__ */ new Map() }, slides = /* @__PURE__ */ new Map();
4083
- const list = record5(presentation).slides;
4669
+ const list = record6(presentation).slides;
4084
4670
  if (Array.isArray(list)) list.forEach((slide, index) => {
4085
4671
  const result = numberSlide(slide, index, references, numbering);
4086
4672
  if (result) slides.set(index, result);
@@ -4090,7 +4676,7 @@ function collectCitations(presentation) {
4090
4676
  }
4091
4677
  function slideCitations(slide, slideIndex, presentation) {
4092
4678
  const references = referenceList(presentation), numbering = { notes: [], byId: /* @__PURE__ */ new Map() };
4093
- const list = record5(presentation).slides;
4679
+ const list = record6(presentation).slides;
4094
4680
  if (Array.isArray(list)) for (let index = 0; index < Math.min(slideIndex, list.length); index += 1) numberSlide(list[index], index, references, numbering);
4095
4681
  return numberSlide(slide, slideIndex, references, numbering);
4096
4682
  }
@@ -4153,12 +4739,39 @@ function referencesSlide(presentation, options = {}) {
4153
4739
  return { title, items };
4154
4740
  }
4155
4741
 
4742
+ // src/layout-content.ts
4743
+ var LAYOUT_BODY_KINDS = ["text", "list", "image", "video", "chart", "table", "code", "metric", "quote", "timeline"];
4744
+ var record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
4745
+ function layoutStructure(layout) {
4746
+ if (!isLayoutTemplate(layout)) return "";
4747
+ return templateAreas(layout).map((entry) => entry.region ? `${entry.name} (${entry.region.flow}: ${entry.region.accepts.join(", ")})` : entry.name).join(", ");
4748
+ }
4749
+ function layoutContent(layout) {
4750
+ const areas = isLayoutTemplate(layout) ? templateAreas(layout) : [];
4751
+ const regions = areas.flatMap((entry) => entry.region ? [entry.region] : []);
4752
+ const lead = regions.find((region) => region.role === "primary") ?? regions[0];
4753
+ const leadKind = lead?.accepts.find((kind2) => kind2 !== "group");
4754
+ const title = areas.some((entry) => entry.name === "title");
4755
+ return { kind: leadKind ?? "title", count: regions.length, heading: { title, subtitle: title || areas.some((entry) => entry.name === "subtitle"), tag: title } };
4756
+ }
4757
+ function templateAreas(layout) {
4758
+ const value = record7(layout), regions = record7(value.regions);
4759
+ const rows3 = Array.isArray(value.areas) ? value.areas.filter((row) => Array.isArray(row) && row.every((cell) => typeof cell === "string")) : [];
4760
+ const seen = /* @__PURE__ */ new Set(), out = [];
4761
+ for (const row of rows3) for (const name of row) {
4762
+ if (!name || name === "." || seen.has(name)) continue;
4763
+ seen.add(name);
4764
+ out.push(name === "title" || name === "subtitle" || !Object.hasOwn(regions, name) ? { name } : { name, region: layoutRegion(name, regions[name]) });
4765
+ }
4766
+ return out;
4767
+ }
4768
+
4156
4769
  // src/composition.ts
4157
4770
  var MAX_COMPOSITION_DEPTH = 32;
4158
4771
  var FALLBACK_CODE_FAMILY = "Roboto Mono";
4159
4772
  var DEFAULT_FONT_FAMILIES = { heading: String(ENGINE_DEFAULT_FONT_SCHEME.major), body: String(ENGINE_DEFAULT_FONT_SCHEME.minor) };
4160
4773
  function resolveFontFamilies(input) {
4161
- const scheme = record6(input);
4774
+ const scheme = record8(input);
4162
4775
  const family = (value) => typeof value === "string" && value ? value : void 0;
4163
4776
  const accent = family(scheme.accent);
4164
4777
  return {
@@ -4229,12 +4842,6 @@ function translateTextFit(fit, dy) {
4229
4842
  }
4230
4843
  };
4231
4844
  }
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
4845
  var OPFCompositionError = class extends Error {
4239
4846
  constructor(diagnostics, explanation) {
4240
4847
  super("Slide content does not fit its composition.");
@@ -4250,11 +4857,11 @@ var fields = ["text", "items", "bullets", "image", "video", "chart", "table", "c
4250
4857
  var headings = /* @__PURE__ */ new Set(["title", "subtitle", "tag"]);
4251
4858
  var rows2 = ["top", "middle", "bottom"];
4252
4859
  var columns = ["left", "center", "right"];
4253
- var record6 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
4860
+ var record8 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
4254
4861
  var kind = (field) => field === "items" ? "list" : field === "bullets" ? "text" : field;
4255
4862
  var round2 = (value) => Math.round(value * 1e6) / 1e6 || value;
4256
4863
  var PLACEMENT_BAND = 0.5;
4257
- var IMAGE_EDGES = ["left", "right", "top", "bottom"];
4864
+ var IMAGE_EDGES2 = ["left", "right", "top", "bottom"];
4258
4865
  var IMAGE_FITS = ["cover", "contain", "stretch"];
4259
4866
  var BACKGROUND_FITS = ["cover", "contain", "stretch", "tile"];
4260
4867
  var IMAGE_SOURCE = /^(asset:|https:\/\/|data:|\.\/|\.\.\/)/;
@@ -4269,7 +4876,7 @@ var pathNumber = (value) => String(round2(value));
4269
4876
  var IMAGE_SHAPES = { rectangle: "rect", rounded: "roundRect", circle: "ellipse", hexagon: "hexagon" };
4270
4877
  var roundBox = (box) => ({ x: round2(box.x), y: round2(box.y), width: round2(box.width), height: round2(box.height) });
4271
4878
  var imageFocus = (value) => {
4272
- const focus = record6(value), x = finite(focus.x, 0, 1), y = finite(focus.y, 0, 1);
4879
+ const focus = record8(value), x = finite(focus.x, 0, 1), y = finite(focus.y, 0, 1);
4273
4880
  return x !== void 0 && y !== void 0 ? { x, y } : { x: 0.5, y: 0.5 };
4274
4881
  };
4275
4882
  function imageShape(kind2, box, cornerRadius = 1 / 6) {
@@ -4310,7 +4917,7 @@ function fitImage(frame, fit, aspect, focus = { x: 0.5, y: 0.5 }) {
4310
4917
  }
4311
4918
  function imageBackground(value) {
4312
4919
  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);
4920
+ const background = record8(value);
4314
4921
  if (background.type !== "image" || typeof background.src !== "string" || !background.src) return void 0;
4315
4922
  const opacity = finite(background.opacity, 0, 1);
4316
4923
  return {
@@ -4325,13 +4932,13 @@ function imageBackground(value) {
4325
4932
  }
4326
4933
  function composeRecolor(value) {
4327
4934
  if (value === "grayscale") return { type: "grayscale" };
4328
- const duotone = record6(value);
4935
+ const duotone = record8(value);
4329
4936
  return duotone.dark !== void 0 && duotone.light !== void 0 ? { type: "duotone", dark: duotone.dark, light: duotone.light } : void 0;
4330
4937
  }
4331
4938
  function composeOverlay(value, frame, shape, path, mirrorSide, diagnostics) {
4332
- const overlay = record6(value), opacity = finite(overlay.opacity, 0, 1);
4939
+ const overlay = record8(value), opacity = finite(overlay.opacity, 0, 1);
4333
4940
  if (overlay.color === void 0 || opacity === void 0) return void 0;
4334
- const edge = IMAGE_EDGES.includes(overlay.edge) ? mirrorSide(overlay.edge) : void 0;
4941
+ const edge = IMAGE_EDGES2.includes(overlay.edge) ? mirrorSide(overlay.edge) : void 0;
4335
4942
  if (edge && shape.kind !== "rectangle") {
4336
4943
  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
4944
  return void 0;
@@ -4354,7 +4961,7 @@ function composeImage(host, hostPath, region, frameArea, context) {
4354
4961
  const focus = imageFocus(host.focus);
4355
4962
  const shape = imageShape(kindName, box, finite(host.cornerRadius, 0, 0.5));
4356
4963
  const result = { region: roundBox(region), box, fit, focus, shape };
4357
- const border = record6(host.border), borderWidth = finite(border.width, 0, 64);
4964
+ const border = record8(host.border), borderWidth = finite(border.width, 0, 64);
4358
4965
  if (border.color !== void 0 && borderWidth) result.border = { color: border.color, width: round2(borderWidth * scale) };
4359
4966
  const opacity = finite(host.opacity, 0, 1);
4360
4967
  if (opacity !== void 0 && opacity < 1) result.opacity = opacity;
@@ -4368,8 +4975,8 @@ function composeImage(host, hostPath, region, frameArea, context) {
4368
4975
  return result;
4369
4976
  }
4370
4977
  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"];
4978
+ const own3 = record8(slide.design), deck = record8(record8(presentation).design);
4979
+ const [value, at3] = own3.background !== void 0 ? [own3.background, `${path}.design.background`] : deck.background !== void 0 ? [deck.background, "design.background"] : [themeBackground, "theme"];
4373
4980
  const background = imageBackground(value);
4374
4981
  if (!background) return void 0;
4375
4982
  const box = { x: 0, y: 0, width, height };
@@ -4379,7 +4986,7 @@ function resolveBackgroundImage(slide, presentation, themeBackground, width, hei
4379
4986
  if (recolor) result.recolor = recolor;
4380
4987
  const overlay = composeOverlay(background.overlay, box, imageShape("rectangle", box), `${at3}.overlay`, mirrorSide, diagnostics);
4381
4988
  if (overlay) result.overlay = overlay;
4382
- const aspect = background.fit === "tile" ? void 0 : intrinsicImageAspect(background.src, record6(presentation).assets);
4989
+ const aspect = background.fit === "tile" ? void 0 : intrinsicImageAspect(background.src, record8(presentation).assets);
4383
4990
  if (aspect) result.picture = fitImage(box, background.fit, aspect, background.focus);
4384
4991
  return result;
4385
4992
  }
@@ -4410,8 +5017,8 @@ function breaksInsideWord(text2, fit) {
4410
5017
  });
4411
5018
  }
4412
5019
  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) };
5020
+ const slide = record8(input), width = options.width ?? 1280, height = options.height ?? 720, scale = Math.min(width, height) / 720;
5021
+ const settings = { ...record8(record8(options.layout).composition), ...record8(slide.composition) };
4415
5022
  assertComposition(settings);
4416
5023
  const furnitureRtl = (options.direction ?? resolveSlideDirection(options.presentation, options.slideIndex)) === "rtl";
4417
5024
  const minimum = snapFontSizeUp((settings.minFontSize ?? 16) * scale), size = gridFontSize(13 * scale, minimum), padding = (options.textRasterPadding ?? 2) * scale;
@@ -4423,13 +5030,13 @@ function layoutFurniture(input, options = {}) {
4423
5030
  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
5031
  const outlines = options.textMeasurement?.outlineBounds !== void 0, parts = [], diagnostics = [];
4425
5032
  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";
5033
+ const primaryIndex = organizations.findIndex((item) => record8(item).role === "primary"), organizationIndex2 = primaryIndex >= 0 ? primaryIndex : organizations.findIndex(Boolean);
5034
+ const organization = record8(organizations[organizationIndex2]), organizationRoot = Array.isArray(options.presentation?.organization) ? `organization.${organizationIndex2}` : "organization";
4428
5035
  const fontFamily = options.fontFamilies?.body ?? "sans-serif";
4429
5036
  let headerBottom = 0, footerTop = height, configured = false;
4430
5037
  const error = (path, message, code = "text-overflow") => diagnostics.push({ code, path, message });
4431
5038
  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];
5039
+ const local = record8(slide.design)[kind2] !== void 0, value = local ? record8(slide.design)[kind2] : options.presentation?.design?.[kind2];
4433
5040
  if (value === void 0 || value === false) continue;
4434
5041
  const root = local ? `${sourceRoot}.design.${kind2}` : `design.${kind2}`;
4435
5042
  if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Header/footer content must be an object or false.");
@@ -4437,7 +5044,7 @@ function layoutFurniture(input, options = {}) {
4437
5044
  const zones = [];
4438
5045
  for (const [index, zone] of ["left", "center", "right"].entries()) {
4439
5046
  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;
5047
+ const content = record8(record8(value)[zone]), path = `${root}.${zone}`, x = width * (0.07 + (furnitureRtl ? 2 - index : index) * 0.3), zoneWidth = width * 0.26;
4441
5048
  const pending = [];
4442
5049
  const add = (field, text2, generated = false, sourcePath, extras = {}) => {
4443
5050
  if (text2 === void 0) return;
@@ -4446,7 +5053,7 @@ function layoutFurniture(input, options = {}) {
4446
5053
  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
5054
  };
4448
5055
  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));
5056
+ 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
5057
  pending.push({ type: "image", sourcePath, image: source, ...reference !== void 0 ? { reference } : {}, width: imageWidth, height: imageHeight });
4451
5058
  };
4452
5059
  if (content.image !== void 0) {
@@ -4465,7 +5072,7 @@ function layoutFurniture(input, options = {}) {
4465
5072
  add("text", resolved.text, false, void 0, { fields: resolved.fields });
4466
5073
  } else add("text", content.text);
4467
5074
  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") }));
5075
+ 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
5076
  if (links.length) add("socials", links.map((link) => link.text).join("\n"), true, `${organizationRoot}.socials`, { links });
4470
5077
  else error(`${path}.socials`, "Generated social profiles need a primary organization with socials.", "unresolved-content");
4471
5078
  }
@@ -4572,11 +5179,22 @@ function layoutFurniture(input, options = {}) {
4572
5179
  var textSegments = new Intl.Segmenter("und", { granularity: "grapheme" });
4573
5180
  var WRAP_TOLERANCE = 0.01;
4574
5181
  var HANGING_SPACE = /[^\S\r\n\u00a0\u202f\ufeff]/u;
5182
+ var SCRIPT_WIDTH_FACTORS = [
5183
+ [/\p{Script=Tamil}/u, 1.53],
5184
+ [/\p{Script=Malayalam}/u, 1.76],
5185
+ [/\p{Script=Sinhala}/u, 1.44],
5186
+ [/\p{Script=Myanmar}/u, 1.18],
5187
+ [/\p{Script=Ethiopic}/u, 1.13],
5188
+ [/\p{Script=Georgian}/u, 1.28]
5189
+ ];
4575
5190
  function measureText(text2, fontSize) {
4576
5191
  let units = 0;
4577
5192
  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;
5193
+ if (/\p{Mn}|\p{Me}|\u200d|\ufe0f/u.test(character)) continue;
5194
+ 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;
5195
+ const base = character === " " ? 0.32 : /[A-Z0-9]/.test(character) ? 0.62 : character.codePointAt(0) > 11904 ? 1 : 0.54;
5196
+ const factor = SCRIPT_WIDTH_FACTORS.find(([script]) => script.test(character))?.[1] ?? 1;
5197
+ units += base * factor;
4580
5198
  }
4581
5199
  return units * fontSize;
4582
5200
  }
@@ -4727,6 +5345,22 @@ function layoutQuote(value, box, options = {}) {
4727
5345
  photoFits = selected.photoFits;
4728
5346
  }
4729
5347
  }
5348
+ if (body.fit && !body.fit.overflow && photoFits && (!attribution || attribution.fit && !attribution.fit.overflow)) {
5349
+ body.box.height = body.fit.placement?.height ?? heightOf(body.fit);
5350
+ const footerTop = body.box.y + body.box.height + 18;
5351
+ const previousTop = Math.min(attribution?.box.y ?? Infinity, photo?.box.y ?? Infinity);
5352
+ if (Number.isFinite(previousTop)) {
5353
+ const shift = footerTop - previousTop;
5354
+ if (attribution) {
5355
+ attribution.box.y += shift;
5356
+ attribution.fit = translateTextFit(attribution.fit, shift);
5357
+ }
5358
+ if (photo) {
5359
+ photo.box.y += shift;
5360
+ photo.shape = imageShape("circle", photo.box);
5361
+ }
5362
+ }
5363
+ }
4730
5364
  if (hasPhoto && !photo) photoFits = false;
4731
5365
  for (const part of parts) {
4732
5366
  const area = part.box;
@@ -4746,7 +5380,11 @@ function layoutQuote(value, box, options = {}) {
4746
5380
  report("part-overlap", path, ["body", "footer"], "Quote body and photo overlap; do not accept this layout without more space.");
4747
5381
  }
4748
5382
  if (diagnostics.length && options.overflow === "error") throw new OPFCompositionError(diagnostics);
4749
- return { algorithm: "quote-flow-v1", textMeasurement: options.textMeasurement ? "provided" : "estimated", parts, ...photo ? { photo } : {}, diagnostics, overflow: diagnostics.length > 0 };
5383
+ const occupiedParts = parts.filter((part) => part.fit).map((part) => ({ ...part.box, height: part.fit.placement?.height ?? heightOf(part.fit) }));
5384
+ if (photo) occupiedParts.push(photo.box);
5385
+ const bottom = Math.max(box.y, ...occupiedParts.map((area) => area.y + area.height));
5386
+ const bounds = { x: box.x, y: box.y, width: box.width, height: bottom - box.y };
5387
+ return { bounds, algorithm: "quote-flow-v1", textMeasurement: options.textMeasurement ? "provided" : "estimated", parts, ...photo ? { photo } : {}, diagnostics, overflow: diagnostics.length > 0 };
4750
5388
  }
4751
5389
  function layoutMetric(value, box, options = {}) {
4752
5390
  const scalar = typeof value === "string" || typeof value === "number";
@@ -4797,16 +5435,16 @@ function layoutMetric(value, box, options = {}) {
4797
5435
  let outline = null;
4798
5436
  for (const segment2 of line.segments) {
4799
5437
  if (segment2.kind !== "text") continue;
4800
- const bounds = measureTextOutline(part.text.slice(segment2.start, segment2.end), fit.fontSize, part.style, options.textMeasurement);
4801
- if (!bounds) continue;
4802
- const next = { ...bounds, x: segment2.x + bounds.x };
5438
+ const bounds2 = measureTextOutline(part.text.slice(segment2.start, segment2.end), fit.fontSize, part.style, options.textMeasurement);
5439
+ if (!bounds2) continue;
5440
+ const next = { ...bounds2, x: segment2.x + bounds2.x };
4803
5441
  if (!outline) outline = next;
4804
5442
  else {
4805
- const right = Math.max(outline.x + outline.width, next.x + next.width), bottom = Math.max(outline.y + outline.height, next.y + next.height);
5443
+ const right = Math.max(outline.x + outline.width, next.x + next.width), bottom2 = Math.max(outline.y + outline.height, next.y + next.height);
4806
5444
  outline.x = Math.min(outline.x, next.x);
4807
5445
  outline.y = Math.min(outline.y, next.y);
4808
5446
  outline.width = right - outline.x;
4809
- outline.height = bottom - outline.y;
5447
+ outline.height = bottom2 - outline.y;
4810
5448
  }
4811
5449
  }
4812
5450
  return { width: line.width, y: index * fit.lineHeight, baseline: fit.fontSize + index * fit.lineHeight, height: fit.lineHeight, outline };
@@ -4916,7 +5554,9 @@ function layoutMetric(value, box, options = {}) {
4916
5554
  }
4917
5555
  }
4918
5556
  if (diagnostics.length && options.overflow === "error") throw new OPFCompositionError(diagnostics);
4919
- return { algorithm: "metric-flow-v1", alignment, textMeasurement: options.textMeasurement ? "provided" : "estimated", arrangement: selected.arrangement, ...metric.sentiment === void 0 ? {} : { sentiment: metric.sentiment }, attempts, parts, diagnostics, overflow: diagnostics.length > 0 };
5557
+ const bottom = Math.max(box.y, ...visible.map((part) => part.box.y + occupied(part.fit)));
5558
+ const bounds = { x: box.x, y: box.y, width: box.width, height: bottom - box.y };
5559
+ return { bounds, algorithm: "metric-flow-v1", alignment, textMeasurement: options.textMeasurement ? "provided" : "estimated", arrangement: selected.arrangement, ...metric.sentiment === void 0 ? {} : { sentiment: metric.sentiment }, attempts, parts, diagnostics, overflow: diagnostics.length > 0 };
4920
5560
  }
4921
5561
  var TIMELINE_STATUS_VALUES = ["done", "current", "planned"];
4922
5562
  var TIMELINE_RING_RATIO = 1.6;
@@ -4942,9 +5582,9 @@ function layoutTimeline(value, box, options = {}) {
4942
5582
  add("name", timeline.name, `${path}.name`, 24, 700);
4943
5583
  add("description", timeline.description, `${path}.description`, 18, 400);
4944
5584
  timeline.events.forEach((event, index) => {
4945
- add("when", event.when, `${eventPath(index)}.when`, 16, 500, index);
4946
- add("what", event.what, `${eventPath(index)}.what`, 16, 500, index);
4947
- add("event-description", event.description, `${eventPath(index)}.description`, 16, 500, index);
5585
+ add("when", event.when, `${eventPath(index)}.when`, 18, 500, index);
5586
+ add("what", event.what, `${eventPath(index)}.what`, 22, 600, index);
5587
+ add("event-description", event.description, `${eventPath(index)}.description`, 18, 400, index);
4948
5588
  });
4949
5589
  const metadata = [], events = timeline.events.map(() => []);
4950
5590
  for (const part of source) if (part.eventIndex === void 0) metadata.push(part);
@@ -4998,6 +5638,7 @@ function layoutTimeline(value, box, options = {}) {
4998
5638
  const accepted = { ...part, box: area, alignment, fit };
4999
5639
  parts.push(accepted);
5000
5640
  if (fit.overflow) report(accepted, "text-fit", "Timeline field exceeds its readable width; increase its space or split the timeline.");
5641
+ if (breaksInsideWord(part.text, fit)) report(accepted, "text-fit", "Timeline field would split a word; use a wider vertical arrangement or paginate events.");
5001
5642
  if (area.x < box.x - 0.01 || area.y < box.y - 0.01 || area.x + area.width > box.x + box.width + 0.01 || area.y + area.height > box.y + box.height + 0.01) report(accepted, "part-outside-cell", "Timeline field extends outside its cell; increase the cell or paginate events.", Math.max(area.x + area.width - box.x - box.width, area.y + area.height - box.y - box.height));
5002
5643
  return accepted;
5003
5644
  };
@@ -5015,27 +5656,35 @@ function layoutTimeline(value, box, options = {}) {
5015
5656
  };
5016
5657
  if (arrangement === "alternating") {
5017
5658
  const width = box.width / Math.max(2, count), step = (box.width - width) / Math.max(1, count - 1), start = count === 1 ? box.x + box.width / 2 : box.x + width / 2;
5018
- const lineY = y + Math.max(scale, available) * 0.46;
5659
+ const fieldGap = 4 * scale, clearance = 24 * scale;
5660
+ const heights = events.map((fields2) => fields2.reduce((height, part) => height + measure(part, gridFontSize(part.requestedFontSize - reduction * scale, minimum), width, "center").height, 0) + Math.max(0, fields2.length - 1) * fieldGap);
5661
+ const markerExtent = hasRing ? ringRadius + strokeWidth / 2 : radius;
5662
+ const upper = Math.max(markerExtent, ...heights.filter((_, index) => index % 2 === 0).map((height) => height + clearance));
5663
+ const lower = Math.max(markerExtent, ...heights.filter((_, index) => index % 2 === 1).map((height) => height + clearance));
5664
+ const lineY = y + Math.max(0, (available - upper - lower) / 2) + upper;
5019
5665
  events.forEach((fields2, index) => {
5020
- const x = start + (rtl ? count - 1 - index : index) * step, top = index % 2 === 0 ? y : lineY + 24 * scale, bottom = index % 2 === 0 ? lineY - 24 * scale : box.y + box.height;
5666
+ const x = start + (rtl ? count - 1 - index : index) * step, top = index % 2 === 0 ? lineY - clearance - heights[index] : lineY + clearance, bottom = index % 2 === 0 ? lineY - clearance : box.y + box.height;
5021
5667
  markers.push(marker(index, x, lineY));
5022
5668
  let cursor = top;
5023
- for (const part of fields2) {
5669
+ for (const [fieldIndex, part] of fields2.entries()) {
5024
5670
  const placed = place(part, x - width / 2, cursor, width, "center");
5025
5671
  cursor += placed.box.height;
5026
5672
  if (cursor > bottom + 0.01) report(placed, "event-space", "Timeline event labels exceed their side of the connector; change the arrangement or paginate events.", cursor - bottom);
5673
+ if (fieldIndex < fields2.length - 1) cursor += fieldGap;
5027
5674
  }
5028
5675
  });
5029
5676
  } else {
5030
- const lead = hasRing ? ringRadius + strokeWidth / 2 : radius, gap = 24 * scale + (lead - radius);
5677
+ const outlined = timeline.events.some((event) => event.status === "planned");
5678
+ const lead = hasRing ? ringRadius + strokeWidth / 2 : radius + (outlined ? strokeWidth / 2 : 0), gap = 2 * lead + 12 * scale;
5031
5679
  const x = rtl ? box.x + box.width - lead : box.x + lead, textX = rtl ? box.x : box.x + gap, width = box.width - gap;
5032
5680
  events.forEach((fields2, index) => {
5033
5681
  const top = y;
5034
5682
  let first2;
5035
- for (const part of fields2) {
5683
+ for (const [fieldIndex, part] of fields2.entries()) {
5036
5684
  const placed = place(part, textX, y, width, "left");
5037
5685
  first2 ??= placed;
5038
5686
  y += placed.box.height;
5687
+ if (fieldIndex < fields2.length - 1) y += 4 * scale;
5039
5688
  }
5040
5689
  markers.push(marker(index, x, top + Math.min(first2?.box.height ?? 2 * radius, 2 * radius) / 2));
5041
5690
  y += 16 * scale;
@@ -5067,19 +5716,19 @@ function fitSourceText(text2, box, size, minimum, step, measure, prose = false,
5067
5716
  const layout = (fontSize) => {
5068
5717
  const tabWidth = measure(" ", fontSize) * 4;
5069
5718
  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) => {
5719
+ const measureLine = (start2, end2, record9 = false) => {
5071
5720
  let x = 0, offset = start2;
5072
5721
  const segments = [];
5073
5722
  for (const [index, segment2] of text2.slice(start2, end2).split(" ").entries()) {
5074
5723
  if (index) {
5075
5724
  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 });
5725
+ if (record9) segments.push({ kind: "tab", start: offset, end: offset + 1, x, width: next - x });
5077
5726
  x = next;
5078
5727
  offset++;
5079
5728
  }
5080
5729
  if (segment2) {
5081
5730
  const advance = measure(segment2, fontSize);
5082
- if (record7) segments.push({ kind: "text", start: offset, end: offset + segment2.length, x, width: advance });
5731
+ if (record9) segments.push({ kind: "text", start: offset, end: offset + segment2.length, x, width: advance });
5083
5732
  x += advance;
5084
5733
  offset += segment2.length;
5085
5734
  }
@@ -5358,7 +6007,10 @@ function richTextLayouter(input, box, requestedSize, options, minimum = 0) {
5358
6007
  return layout;
5359
6008
  }
5360
6009
  var PICTURE_BULLET_SCALE = 0.65;
5361
- function fitList(input, box, requestedSize = 25, minFontSize = 16, options = { style: { fontFamily: "sans-serif", fontWeight: 400 } }) {
6010
+ function contentNominalSize(field) {
6011
+ return field === "items" || field === "bullets" ? 32 : 25;
6012
+ }
6013
+ function fitList(input, box, requestedSize = contentNominalSize("items"), minFontSize = 16, options = { style: { fontFamily: "sans-serif", fontWeight: 400 } }) {
5362
6014
  if (!Array.isArray(input) || ![box.width, box.height, requestedSize, minFontSize].every((value) => Number.isFinite(value) && value > 0)) throw new RangeError("List content, dimensions and font sizes must be valid.");
5363
6015
  const source = input.map((value, index) => {
5364
6016
  const object2 = typeof value === "object" && !Array.isArray(value) ? value : void 0;
@@ -5436,12 +6088,12 @@ function fitList(input, box, requestedSize = 25, minFontSize = 16, options = { s
5436
6088
  function contentText(field, value) {
5437
6089
  if (field === "text" || headings.has(field)) return flatten(value);
5438
6090
  if (field === "items" || field === "bullets") return (Array.isArray(value) ? value : [value]).map((item) => {
5439
- const entry = record6(item);
6091
+ const entry = record8(item);
5440
6092
  return `\u2022 ${flatten(item)}${entry.description ? `
5441
6093
  ${flatten(entry.description)}` : ""}`;
5442
6094
  }).join("\n");
5443
- if (field === "code") return flatten(record6(value).source ?? value);
5444
- if (field === "quote") return flatten(record6(value).text ?? value);
6095
+ if (field === "code") return flatten(record8(value).source ?? value);
6096
+ if (field === "quote") return flatten(record8(value).text ?? value);
5445
6097
  return void 0;
5446
6098
  }
5447
6099
  function layoutTable(value, box, options = {}) {
@@ -5450,6 +6102,11 @@ function layoutTable(value, box, options = {}) {
5450
6102
  const inline = inlineTableData(value, options.presentation);
5451
6103
  const grid = tableGrid(inline, options.path ?? "table");
5452
6104
  if (grid.issues.length) throw new RangeError(`${grid.issues[0].path}: ${grid.issues[0].message}`);
6105
+ const numeric = new Set(grid.rows.flat().filter((cell) => !cell.header && typeof cell.value === "number" && Number.isFinite(cell.value)));
6106
+ const numericColumns = new Set(Array.from({ length: grid.columnCount }, (_, column) => column).filter((column) => {
6107
+ const body = grid.rows.flat().filter((cell) => !cell.header && cell.column === column && cell.value !== null && cell.value !== void 0);
6108
+ return body.length > 0 && body.every((cell) => cell.colSpan === 1 && numeric.has(cell));
6109
+ }));
5453
6110
  const formats = resolveTableData(inline).formats;
5454
6111
  for (const row of grid.rows) for (const cell of row) {
5455
6112
  if (cell.header) continue;
@@ -5461,7 +6118,9 @@ function layoutTable(value, box, options = {}) {
5461
6118
  const padding = { top: 8, right: 10, bottom: 4, left: 10, ...cell.style.padding };
5462
6119
  const width = cellWidth * cell.colSpan - (padding.left + padding.right) * scale;
5463
6120
  const style = { fontFamily: options.fontFamily ?? "sans-serif", fontWeight: cell.header ? 700 : 400, italic: false, path: cell.valuePath };
5464
- return { ...cell, padding, width, textStyle: style };
6121
+ const numericDefault = numeric.has(cell) || cell.header && cell.colSpan === 1 && numericColumns.has(cell.column);
6122
+ const alignment = cell.style.align ?? options.alignment ?? (numericDefault ? options.direction === "rtl" ? "left" : "right" : "left");
6123
+ return { ...cell, padding, width, textStyle: style, alignment };
5465
6124
  });
5466
6125
  const cellMinimum = (cell) => Array.isArray(cell.value) ? richMinimum(cell.value, requested, minimum) : minimum;
5467
6126
  const fitCell = (cell, height, min) => {
@@ -5501,7 +6160,7 @@ function layoutTable(value, box, options = {}) {
5501
6160
  const offset = cell.style.verticalAlign === "bottom" ? Math.max(0, available - height) : cell.style.verticalAlign === "middle" ? Math.max(0, (available - height) / 2) : 0;
5502
6161
  const textBox = { x: cellBox.x + cell.padding.left * scale, y: cellBox.y + cell.padding.top * scale + offset, width: Math.max(scale, cell.width), height: Math.max(scale, available - offset) };
5503
6162
  overflow ||= cell.width <= 0 || available <= 0 || fit.overflow;
5504
- rows3[cell.row].cells.push({ value: cell.value, input: cell.input, path: cell.valuePath, sourcePath: cell.path, style: cell.style, row: cell.row, column: cell.column, rowSpan: cell.rowSpan, colSpan: cell.colSpan, header: cell.header, rich: Array.isArray(cell.value), box: cellBox, textBox, textStyle: resolveTextStyle(cell.textStyle, options.textMeasurement), fit, ...fit.directions ? { direction: fit.directions[0] } : {} });
6163
+ rows3[cell.row].cells.push({ value: cell.value, input: cell.input, path: cell.valuePath, sourcePath: cell.path, style: cell.style, alignment: cell.alignment, row: cell.row, column: cell.column, rowSpan: cell.rowSpan, colSpan: cell.colSpan, header: cell.header, rich: Array.isArray(cell.value), box: cellBox, textBox, textStyle: resolveTextStyle(cell.textStyle, options.textMeasurement), fit, ...fit.directions ? { direction: fit.directions[0] } : {} });
5505
6164
  }
5506
6165
  return { rows: rows3, columnCount, height: sum(heights), overflow };
5507
6166
  }
@@ -5512,7 +6171,7 @@ function flatten(value) {
5512
6171
  if (value == null) return "";
5513
6172
  if (typeof value !== "object") return String(value);
5514
6173
  if (Array.isArray(value)) return value.map(flatten).join("");
5515
- const item = record6(value);
6174
+ const item = record8(value);
5516
6175
  return flatten(item.text ?? item.value ?? item.source ?? JSON.stringify(value));
5517
6176
  }
5518
6177
  function regionParts(key) {
@@ -5567,16 +6226,43 @@ function assertComposition(value) {
5567
6226
  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
6227
  if (value.overflow !== void 0 && !["warn", "error"].includes(value.overflow)) throw new RangeError("Invalid composition.overflow.");
5569
6228
  }
6229
+ var LAYOUT_MASTER = /* @__PURE__ */ Symbol("opf.layoutMaster");
6230
+ function mergeListColumns(columns2) {
6231
+ const fits = columns2.map((column) => column.text), first = fits[0];
6232
+ const directions = fits.flatMap((fit) => fit.directions ?? []);
6233
+ 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 } : {} };
6234
+ }
6235
+ function composeLayoutAreas(layout, options = {}) {
6236
+ const template = layoutTemplate(layout), source = record8(layout);
6237
+ const kept = { ...source, regions: Object.fromEntries(Object.entries(record8(source.regions)).map(([name, value]) => [name, { ...record8(value), empty: "keep" }])) };
6238
+ const { mirror, bleed = true, placements = [], ...compose } = options;
6239
+ const slide = {
6240
+ ...template.title ? { title: "Title", subtitle: "Subtitle" } : {},
6241
+ ...placements.length ? { blocks: placements.map((placement) => ({ image: "https://example.invalid/placeholder.png", placement: { ...placement } })) } : {},
6242
+ ...mirror !== void 0 ? { design: { mirror } } : {}
6243
+ };
6244
+ const result = composeSlide(slide, { ...compose, layout: kept, [LAYOUT_MASTER]: true });
6245
+ const areas = template.areas.map((area) => {
6246
+ if (area.heading) {
6247
+ const found = result.headingAreas?.find((entry) => entry.name === area.name);
6248
+ return { name: area.name, heading: true, box: found ? { ...found.box } : { x: 0, y: 0, width: 0, height: 0 }, ...found?.parts ? { parts: found.parts } : {} };
6249
+ }
6250
+ const region = result.regions.find((entry) => entry.name === area.name);
6251
+ return { name: area.name, heading: false, box: { ...!bleed && region.areaBox ? region.areaBox : region.box } };
6252
+ });
6253
+ return { contentBox: { ...result.contentBox }, areas };
6254
+ }
5570
6255
  function composeSlide(input, options = {}) {
5571
- const slide = record6(input), layout = record6(options.layout);
6256
+ const slide = record8(input), layout = record8(options.layout);
5572
6257
  const width = options.width ?? 1280, height = options.height ?? 720;
5573
6258
  if (![width, height].every((value) => Number.isFinite(value) && value > 0)) throw new RangeError("Canvas dimensions must be finite and positive.");
5574
6259
  const scale = Math.min(width, height) / 720;
5575
6260
  const deckDirection = options.direction ?? resolveSlideDirection(options.presentation, options.slideIndex);
5576
6261
  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 } });
6262
+ const template = isLayoutTemplate(layout) ? layoutTemplate(layout) : void 0;
6263
+ 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
6264
  const hasCards = hints.contentBox ?? false;
5579
- const composition = { ...record6(layout.composition), ...record6(slide.composition) };
6265
+ const composition = { ...record8(layout.composition), ...record8(slide.composition) };
5580
6266
  assertComposition(composition);
5581
6267
  const padding = (composition.padding ?? 0.08) * Math.min(width, height);
5582
6268
  const gap = (composition.gap ?? 1 / 30) * Math.min(width, height);
@@ -5657,17 +6343,15 @@ function composeSlide(input, options = {}) {
5657
6343
  const mirrorSide = (side) => !rtl ? side : side === "left" ? "right" : side === "right" ? "left" : side;
5658
6344
  const backgroundImage = resolveBackgroundImage(slide, options.presentation, options.themeBackground, width, height, path, mirrorSide, imageDiagnostics);
5659
6345
  const regions = Object.keys(slide).filter((key) => regionParts(key)).sort();
5660
- const assets = record6(options.presentation).assets;
6346
+ const assets = record8(options.presentation).assets;
5661
6347
  const imageContext = (placement) => ({ fit: hints.imageFit, scale, mirrorSide, diagnostics: imageDiagnostics, assets, ...placement ? { placement } : {} });
5662
6348
  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 }] : [];
6349
+ 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
6350
  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;
6351
+ topImages.forEach((node) => {
6352
+ const own3 = node.block !== void 0 && node.host.placement !== void 0 ? record8(node.host.placement) : void 0;
6353
+ const value = own3;
6354
+ if (!value || !IMAGE_EDGES2.includes(value.edge)) return;
5671
6355
  const edge = mirrorSide(value.edge);
5672
6356
  if (usedEdges.has(edge)) return;
5673
6357
  usedEdges.add(edge);
@@ -5679,8 +6363,8 @@ function composeSlide(input, options = {}) {
5679
6363
  else if (edge === "right") area.right = region.x;
5680
6364
  else if (edge === "top") area.top += band;
5681
6365
  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 });
6366
+ const placement = { edge, size, inset: value.inset === true, path: `${node.hostPath}.placement` };
6367
+ placed.push({ ...node, placement, region });
5684
6368
  });
5685
6369
  const placedBlocks = new Set(placed.flatMap((entry) => entry.block !== void 0 ? [entry.block] : []));
5686
6370
  const placedRoot = placed.some((entry) => entry.block === void 0);
@@ -5696,17 +6380,16 @@ function composeSlide(input, options = {}) {
5696
6380
  diagnostics.push(...footnotes.diagnostics);
5697
6381
  bodyBottom = footnotes.box.y - gap * 0.5;
5698
6382
  }
5699
- const layoutPlaceholders = Array.isArray(layout.placeholders) ? layout.placeholders : [];
5700
6383
  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
6384
  const emptyPayload = (value) => value === void 0 || value === null || value === "" || Array.isArray(value) && value.length === 0;
5703
6385
  const emptyHost = (host) => emptyPayload(host.blocks) && fields.every((field) => emptyPayload(host[field]));
5704
6386
  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);
6387
+ const hasBodyPayload = regions.some((key) => !emptyHost(record8(slide[key]))) || !emptyPayload(flowBlocks) || fields.some((field) => !(placedRoot && field === "image") && !emptyPayload(slide[field]));
6388
+ const useTemplate = template !== void 0 && !regions.length;
6389
+ const isCover = !hasBodyPayload && (useTemplate || !hasLayoutRecord);
5707
6390
  coverGroup = isCover;
5708
6391
  let logo;
5709
- if (isCover) {
6392
+ if (isCover && options[LAYOUT_MASTER] !== true) {
5710
6393
  const resolved = resolveLogo(options.presentation, slide, { shape: "full", onDark: options.darkBackground, slideIndex: options.slideIndex });
5711
6394
  if (resolved) {
5712
6395
  const logoHeight = 56 * scale;
@@ -5717,7 +6400,7 @@ function composeSlide(input, options = {}) {
5717
6400
  }
5718
6401
  let y = logo ? logo.box.y + logo.box.height + gap : headingTop;
5719
6402
  const headingItems = [];
5720
- for (const field of ["tag", "title", "subtitle"]) {
6403
+ for (const field of useTemplate ? [] : ["tag", "title", "subtitle"]) {
5721
6404
  if (!slide[field] || Array.isArray(slide[field]) && !annotationText(slide[field])) continue;
5722
6405
  const requested = (field === "title" ? 54 : field === "tag" ? 16 : 25) * scale;
5723
6406
  const maxHeight = Math.max(height * (field === "title" ? 0.26 : field === "subtitle" ? 0.12 : 0.045), minSize * 1.22 + 2 * rasterPadding);
@@ -5769,7 +6452,7 @@ function composeSlide(input, options = {}) {
5769
6452
  const collect = (host, basePath, depth = 0, ancestors = []) => {
5770
6453
  if (Array.isArray(host.blocks)) {
5771
6454
  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);
6455
+ const settings = record8(host.composition);
5773
6456
  assertComposition(settings);
5774
6457
  return [{
5775
6458
  field: "blocks",
@@ -5778,7 +6461,7 @@ function composeSlide(input, options = {}) {
5778
6461
  path: basePath,
5779
6462
  payload: host,
5780
6463
  composition: settings,
5781
- children: host.blocks.flatMap((block, index) => collect(record6(block), `${basePath}.blocks.${index}`, depth + 1, [...ancestors, host]))
6464
+ children: host.blocks.flatMap((block, index) => collect(record8(block), `${basePath}.blocks.${index}`, depth + 1, [...ancestors, host]))
5782
6465
  }];
5783
6466
  }
5784
6467
  const captioned = host.caption !== void 0 ? fields.filter((field) => host[field] !== void 0 && CAPTIONABLE_FIELDS.includes(field)) : [];
@@ -5788,27 +6471,27 @@ function composeSlide(input, options = {}) {
5788
6471
  type: host.type ?? kind(field),
5789
6472
  value: fieldValue(field),
5790
6473
  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 } : {} },
6474
+ 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
6475
  ...field === "image" ? { host, hostPath: basePath } : {},
5793
6476
  ...captioned.length === 1 && captioned[0] === field ? { caption: host.caption, captionPath: `${basePath}.caption` } : {}
5794
6477
  }));
5795
6478
  };
5796
6479
  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);
6480
+ 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
6481
  const groups = [], flows = [];
5799
6482
  const decisions = options.explain ? [] : void 0;
5800
- const inheritedSettings = (parent, own2 = {}) => ({
6483
+ const inheritedSettings = (parent, own3 = {}) => ({
5801
6484
  minFontSize: parent.minFontSize,
5802
- ...own2,
5803
- overflow: parent.overflow === "error" ? "error" : own2.overflow ?? parent.overflow
6485
+ ...own3,
6486
+ overflow: parent.overflow === "error" ? "error" : own3.overflow ?? parent.overflow
5804
6487
  });
5805
6488
  const inset = (box, settings) => {
5806
6489
  const amount = (settings.padding ?? 0) * Math.min(box.width, box.height);
5807
6490
  return { x: box.x + amount, y: box.y + amount, width: box.width - amount * 2, height: box.height - amount * 2 };
5808
6491
  };
5809
6492
  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;
6493
+ const payloadBox = (box, cards = hasCards) => {
6494
+ if (!cards) return box;
5812
6495
  const frame = acceptedBox(box), padding2 = Math.min(12 * scale, frame.width / 4, frame.height / 4);
5813
6496
  return acceptedBox({ x: frame.x + padding2, y: frame.y + padding2, width: frame.width - 2 * padding2, height: frame.height - 2 * padding2 });
5814
6497
  };
@@ -5867,8 +6550,8 @@ function composeSlide(input, options = {}) {
5867
6550
  penalties.textOverflow += internal.overflow ? 1e3 : 0;
5868
6551
  }
5869
6552
  } else if (text2) {
5870
- const fit = fitContent(node.field, node.value, text2, box, 25 * scale, snapFontSizeUp((settings.minFontSize ?? 16) * scale), node.path, node.payload.numbering);
5871
- const reduction = Math.max(0, snapFontSizeDown(25 * scale) - fit.fontSize) / scale;
6553
+ const fit = fitContent(node.field, node.value, text2, box, contentNominalSize(node.field) * scale, snapFontSizeUp((settings.minFontSize ?? 16) * scale), node.path, node.payload.numbering);
6554
+ const reduction = Math.max(0, snapFontSizeDown(contentNominalSize(node.field) * scale) - fit.fontSize) / scale;
5872
6555
  score += reduction + (fit.overflow ? 1e3 : 0);
5873
6556
  if (penalties) {
5874
6557
  penalties.fontReduction += reduction;
@@ -5892,24 +6575,13 @@ function composeSlide(input, options = {}) {
5892
6575
  };
5893
6576
  const scoreNode = (node, box, settings, penalties) => {
5894
6577
  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);
6578
+ const own3 = inheritedSettings(settings, node.composition), area2 = inset(box, own3), slotCount = Math.max(node.children.length, 0);
6579
+ const cols = defaultColumns(slotCount, area2, own3);
6580
+ const boxes = gridBoxes(slotCount, area2, cols, (own3.gap ?? 1 / 30) * Math.min(box.width, box.height), own3.weights ?? [], modeFor(own3) === "column");
6581
+ return node.children.reduce((score, child, index) => score + scoreNode(child, boxes[index], own3, penalties), 0);
5899
6582
  };
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);
6583
+ const arrange = (nodes, area2, settings, reserved2 = 0, gapOverride, containerPath = path, recorded = true) => {
6584
+ const count = Math.max(nodes.length, reserved2);
5913
6585
  if (!count) return;
5914
6586
  const mode = modeFor(settings), localGap = (settings.gap ?? 1 / 30) * Math.min(area2.width, area2.height);
5915
6587
  const actualGap = gapOverride ?? (settings === rootSettings ? gap : localGap);
@@ -5920,9 +6592,9 @@ function composeSlide(input, options = {}) {
5920
6592
  let best = Infinity;
5921
6593
  for (let candidate = 1; candidate <= Math.min(count, settings.columns ?? 6); candidate++) {
5922
6594
  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;
6595
+ const emptySlots = (Math.ceil(count / candidate) * candidate - count) * 2;
6596
+ const penalties = candidates ? { cellProportions: 0, fontReduction: 0, textOverflow: 0, tableOverflow: 0, smallCells: 0, emptySlots } : void 0;
6597
+ const score = nodes.reduce((sum, node, i) => sum + scoreNode(node, boxes2[i], settings, penalties), 0) + emptySlots;
5926
6598
  if (penalties && candidates) candidates.push({ columns: candidate, rows: Math.ceil(count / candidate), score, penalties });
5927
6599
  if (score < best) {
5928
6600
  best = score;
@@ -5940,114 +6612,387 @@ function composeSlide(input, options = {}) {
5940
6612
  const grid = gridGeometry(count, area2, cols, actualGap, settings.weights ?? [], mode === "column");
5941
6613
  const mirrored = (box) => rtl ? { ...box, x: area2.x + area2.width - (box.x - area2.x) - box.width } : box;
5942
6614
  const boxes = grid.boxes.map(mirrored);
5943
- if (template) emptySlots(template.slice(nodes.length), boxes.slice(nodes.length), settings);
5944
6615
  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
6616
  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);
6617
+ const box = node.region ? mirrored(regionBox(node.region, area2, actualGap)) : boxes[index];
6618
+ placeNode(node, box, settings);
6619
+ });
6620
+ };
6621
+ let regionTag, templateCell = false;
6622
+ const placeNode = (node, box, settings, cards = hasCards, listColumns, metricReferenceHeight) => {
6623
+ if (node.children) {
6624
+ const own3 = inheritedSettings(settings, node.composition), inner = inset(box, own3);
6625
+ if (!node.synthetic) groups.push({ path: node.path, box, contentBox: inner, composition: own3 });
6626
+ arrange(node.children, inner, own3, 0, (own3.gap ?? 1 / 30) * Math.min(box.width, box.height), node.path, !node.synthetic);
6627
+ return;
6628
+ }
6629
+ const frameBox = cards ? acceptedBox(box) : void 0;
6630
+ const metricHeight = metricReferenceHeight === void 0 ? void 0 : payloadBox({ ...box, height: metricReferenceHeight }, cards).height;
6631
+ box = payloadBox(box, cards);
6632
+ const caption = captionOf(node, box);
6633
+ if (caption) {
6634
+ box = caption.mediaBox;
6635
+ diagnostics.push(...caption.diagnostics);
6636
+ }
6637
+ const textValue = contentText(node.field, node.value);
6638
+ const quoteLayout = node.field === "quote" ? measureQuote(node, box, settings) : void 0;
6639
+ const codeLayout = node.field === "code" ? measureCode(node, box, settings) : void 0;
6640
+ const metricLayout = node.field === "metric" ? measureMetric(node, { ...box, height: metricHeight ?? box.height }, settings) : void 0;
6641
+ const timelineLayout = node.field === "timeline" ? measureTimeline(node, box, settings) : void 0;
6642
+ const internal = quoteLayout ?? codeLayout ?? metricLayout ?? timelineLayout, body = internal?.parts.find((part) => part.role === "body" || part.role === "value");
6643
+ const columns2 = textValue !== void 0 && !internal ? listColumnsFor(node, box, settings, listColumns) : void 0;
6644
+ const text2 = internal ? body?.fit : columns2 ? columns2.length > 1 ? mergeListColumns(columns2) : columns2[0].text : textValue !== void 0 ? fitContent(node.field, node.value, textValue, box, contentNominalSize(node.field) * scale, snapFontSizeUp((settings.minFontSize ?? 16) * scale), node.path, node.payload.numbering) : void 0;
6645
+ const image = node.field === "image" ? composeImage(node.host ?? {}, node.hostPath ?? node.path, box, box, imageContext()) : void 0;
6646
+ items.push({
6647
+ path: node.path,
6648
+ field: node.field,
6649
+ type: node.type,
6650
+ value: node.value,
6651
+ payload: node.payload,
6652
+ box: internal ? acceptedBox(box) : box,
6653
+ ...image ? { image } : {},
6654
+ ...frameBox ? { frameBox } : {},
6655
+ text: text2,
6656
+ textStyle: body?.style ?? styleFor(node.field, node.path),
6657
+ composition: settings,
6658
+ alignment: alignmentFor(node.field),
6659
+ ...quoteLayout ? { quoteLayout } : {},
6660
+ ...codeLayout ? { codeLayout } : {},
6661
+ ...metricLayout ? { metricLayout } : {},
6662
+ ...timelineLayout ? { timelineLayout } : {},
6663
+ ...bulletImage && node.payload.numbering === void 0 && (node.field === "items" || node.field === "bullets") ? { bulletImage } : {},
6664
+ ...caption ? { caption } : {},
6665
+ ...regionTag !== void 0 ? { region: regionTag } : {},
6666
+ ...columns2 && columns2.length > 1 ? { listColumns: columns2 } : {}
6667
+ });
6668
+ 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." });
6669
+ };
6670
+ const listColumnsFor = (node, box, settings, regionMode) => {
6671
+ if (node.field !== "items" && node.field !== "bullets") return void 0;
6672
+ const values = node.value;
6673
+ if (!Array.isArray(values) || values.length < 2) return void 0;
6674
+ const own3 = node.payload.columns;
6675
+ const mode = own3 === "auto" || own3 === 1 || own3 === 2 || own3 === 3 ? own3 : regionMode;
6676
+ if (mode === void 0 || mode === 1) return void 0;
6677
+ const start = contentNominalSize(node.field) * scale, floor = snapFontSizeUp((settings.minFontSize ?? 16) * scale);
6678
+ const numbering = node.payload.numbering;
6679
+ const listOptions = { ...richOptions(styleFor(node.field, node.path)), ...numbering !== void 0 ? { numbering } : bulletImage ? { bulletImage } : {} };
6680
+ const columnGap = (count2) => Math.min(gap, box.width / (count2 * 2));
6681
+ const columnBoxes = (count2) => {
6682
+ const between = columnGap(count2), columnWidth = (box.width - between * (count2 - 1)) / count2;
6683
+ const ordered = Array.from({ length: count2 }, (_, index) => ({ x: box.x + index * (columnWidth + between), y: box.y, width: columnWidth, height: box.height }));
6684
+ return rtl ? ordered.map((cell) => ({ ...cell, x: box.x + box.width - (cell.x - box.x) - cell.width })) : ordered;
6685
+ };
6686
+ const chunk = (from, to) => numbering !== void 0 ? sliceNumberedItems(values, numbering, from, to) : values.slice(from, to);
6687
+ const sourcePaths = (index) => {
6688
+ const source = values[index], object2 = source !== null && typeof source === "object" && !Array.isArray(source);
6689
+ return { textPath: `${node.path}.${index}${object2 ? ".text" : ""}`, descriptionPath: `${node.path}.${index}.description` };
6690
+ };
6691
+ const renumber = (fit, from) => ({ ...fit, listEntries: fit.listEntries.map((entry) => ({ ...entry, index: entry.index + from, ...sourcePaths(entry.index + from) })) });
6692
+ const split = (count2, size2, minimum) => {
6693
+ const boxes = columnBoxes(count2);
6694
+ const whole = fitList(values, { ...boxes[0], height: 1e6 }, start, start, listOptions);
6695
+ const first = whole.listEntries[0].textBox.y;
6696
+ const heights = whole.listEntries.map((entry, index) => (whole.listEntries[index + 1]?.textBox.y ?? first + whole.height) - entry.textBox.y);
6697
+ const breaks = [0, ...listColumnBreaks(heights, whole.listEntries.map((entry) => entry.level), count2), values.length];
6698
+ 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]) }));
6699
+ };
6700
+ const quarter = width / 4;
6701
+ const counts = typeof mode === "number" ? [mode] : [2, 3].filter((count2) => (box.width - columnGap(count2) * (count2 - 1)) / count2 >= quarter);
6702
+ if (mode === "auto") {
6703
+ if (!fitList(values, box, start, start, listOptions).overflow) return void 0;
6704
+ for (const count2 of counts) {
6705
+ const columns2 = split(count2, start, start);
6706
+ if (columns2.every((column) => !column.text.overflow)) return columns2;
6707
+ }
6708
+ }
6709
+ const count = counts.at(-1);
6710
+ if (count === void 0) return void 0;
6711
+ const shrunk = split(count, start, floor);
6712
+ const size = Math.min(...shrunk.map((column) => column.text.fontSize));
6713
+ return shrunk.map((column) => ({ ...column, text: renumber(fitList(chunk(column.start, column.end), column.box, size, size, listOptions), column.start) }));
6714
+ };
6715
+ const LONG_LINES = 6, LONG_CODE_LINES = 12, startSize = 25 * scale;
6716
+ 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);
6717
+ const isLong = (node, cellWidth) => {
6718
+ if (node.children) return node.children.some((child) => isLong(child, cellWidth));
6719
+ if (node.field === "text") return estimatedLines(node.value, cellWidth, startSize) > LONG_LINES;
6720
+ if (node.field === "items" || node.field === "bullets") {
6721
+ const listSize = contentNominalSize(node.field) * scale;
6722
+ let lines = 0;
6723
+ for (const entry of Array.isArray(node.value) ? node.value : []) {
6724
+ const object2 = entry !== null && typeof entry === "object" && !Array.isArray(entry) ? entry : void 0;
6725
+ const indent = listSize * 1.1 * (1 + (typeof object2?.level === "number" ? object2.level : 0));
6726
+ lines += estimatedLines(object2 ? object2.text : entry, cellWidth - indent, listSize);
6727
+ if (object2?.description !== void 0) lines += estimatedLines(object2.description, cellWidth - indent, listSize * 0.82);
6728
+ }
6729
+ return lines > LONG_LINES;
6730
+ }
6731
+ if (node.field === "quote") return estimatedLines(typeof node.value === "string" ? node.value : record8(node.value).text, cellWidth, startSize) > LONG_LINES;
6732
+ if (node.field === "table") {
6733
+ const value = record8(node.value);
6734
+ return (Array.isArray(value.rows) ? value.rows.length + (Array.isArray(value.columns) ? 1 : 0) : 0) > LONG_LINES;
6735
+ }
6736
+ if (node.field === "code") return String(typeof node.value === "string" ? node.value : record8(node.value).source ?? "").split("\n").length > LONG_CODE_LINES;
6737
+ return false;
6738
+ };
6739
+ const naturalHeight = (node, cellWidth, cards, metricReferenceHeight, naturalSettings = composition) => {
6740
+ const pad = cards ? 2 * Math.min(12 * scale, cellWidth / 4) : 0, inner = Math.max(scale, cellWidth - pad);
6741
+ if (node.children) return node.children.reduce((sum, child) => sum + naturalHeight(child, cellWidth, false), 0) + gap * Math.max(0, node.children.length - 1) + pad;
6742
+ let content;
6743
+ if (node.field === "text" || node.field === "items" || node.field === "bullets") {
6744
+ const size = contentNominalSize(node.field) * scale;
6745
+ const fit = fitContent(node.field, node.value, contentText(node.field, node.value) ?? "", { x: 0, y: 0, width: inner, height: 1e6 }, size, size, node.path, node.payload.numbering);
6746
+ content = "height" in fit && typeof fit.height === "number" ? fit.height : fit.lines.length * fit.lineHeight;
6747
+ } else if (node.field === "quote") content = measureQuote(node, { x: 0, y: 0, width: inner, height: 1e6 }, naturalSettings).bounds.height + 18;
6748
+ 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;
6749
+ else if (node.field === "metric") content = measureMetric(node, { x: 0, y: 0, width: inner, height: metricReferenceHeight === void 0 ? 1e6 : Math.max(scale, metricReferenceHeight - pad) }, naturalSettings).bounds.height;
6750
+ else if (node.field === "timeline") content = 170 * scale;
6751
+ else if (node.field === "table") {
6752
+ const value = record8(node.value);
6753
+ content = ((Array.isArray(value.rows) ? value.rows.length : 4) + 1) * 36 * scale;
6754
+ } else content = inner / 1.6;
6755
+ return content + (node.caption !== void 0 ? 32 * scale : 0) + pad;
6756
+ };
6757
+ const templateRegions = [], headingAreas = [];
6758
+ const requestedTemplateGap = gap;
6759
+ const composeTemplate = () => {
6760
+ const plan2 = template, frame = contentBox;
6761
+ const binding = bindRegions(slide, layout, { slideIndex: options.slideIndex ?? 0 });
6762
+ for (const entry of binding.diagnostics) diagnostics.push({ code: entry.code, path: entry.path, message: entry.message, ...entry.region !== void 0 ? { region: entry.region } : {} });
6763
+ const unitOf = (bound) => {
6764
+ 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]])) };
6765
+ const parts = collect(host, bound.block !== void 0 ? `${path}.blocks.${bound.block}` : path);
6766
+ 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 };
6767
+ };
6768
+ const contents = new Map(binding.regions.map((entry) => [entry.name, [...entry.blocks, ...entry.overflow].map(unitOf)]));
6769
+ const BELOW = "(below)";
6770
+ const belowUnits = binding.below.map(unitOf);
6771
+ const belowRegion = { name: BELOW, accepts: [], role: "supporting", flow: "auto", max: belowUnits.length, bleed: false, listColumns: 1, anchor: "top", empty: "collapse" };
6772
+ const unitsOf = (name) => name === BELOW ? belowUnits : contents.get(name) ?? [];
6773
+ const shown = (field) => !!slide[field] && !(Array.isArray(slide[field]) && !annotationText(slide[field]));
6774
+ const titleFields = ["tag", "title", ...plan2.subtitle ? [] : ["subtitle"]].filter(shown);
6775
+ const subtitleFields = plan2.subtitle && shown("subtitle") ? ["subtitle"] : [];
6776
+ const columnCount = plan2.columns.length;
6777
+ const cells = plan2.grid.map((row) => [...row]);
6778
+ const rowSizes = [...plan2.rows];
6779
+ const implicitTitle = !plan2.title && titleFields.length > 0;
6780
+ if (implicitTitle) {
6781
+ cells.unshift(Array.from({ length: columnCount }, () => "title"));
6782
+ rowSizes.unshift("auto");
6783
+ }
6784
+ if (belowUnits.length) {
6785
+ cells.push(Array.from({ length: columnCount }, () => BELOW));
6786
+ rowSizes.push("auto");
6787
+ }
6788
+ const gap2 = Math.max(0, Math.min(requestedTemplateGap, frame.width / (columnCount * 2), frame.height / (rowSizes.length * 2)));
6789
+ const regionOf = new Map(plan2.regions.map((region) => [region.name, region]));
6790
+ const empty2 = /* @__PURE__ */ new Set();
6791
+ for (const region of plan2.regions) if (!unitsOf(region.name).length && region.empty !== "keep") empty2.add(region.name);
6792
+ if (plan2.title && !titleFields.length) empty2.add("title");
6793
+ if (plan2.subtitle && !subtitleFields.length) empty2.add("subtitle");
6794
+ const collapsed = collapseAreas(cells, empty2, (name) => name === "title" || name === "subtitle", (name) => name !== BELOW);
6795
+ const rects = areaRects(collapsed.grid), ownRects = areaRects(cells);
6796
+ const widths = columnWidths(plan2.columns, frame.width, gap2);
6797
+ const columnX = [];
6798
+ widths.reduce((x, size) => {
6799
+ columnX.push(x);
6800
+ return x + size + gap2;
6801
+ }, 0);
6802
+ const spanWidth = (rect) => widths.slice(rect.column, rect.column + rect.columnSpan).reduce((a, b) => a + b, 0) + gap2 * (rect.columnSpan - 1);
6803
+ const headingItemsAt = (fields2, x, y2, areaWidth) => {
6804
+ const list = [];
6805
+ let top = y2;
6806
+ for (const field of fields2) {
6807
+ const requested = (field === "title" ? 54 : field === "tag" ? 16 : 25) * scale;
6808
+ const maxHeight = Math.max(height * (field === "title" ? 0.26 : field === "subtitle" ? 0.12 : 0.045), minSize * 1.22 + 2 * rasterPadding);
6809
+ const box = { x, y: top, width: areaWidth, height: maxHeight };
6810
+ const text2 = fitPlacedText(field, slide[field], annotationText(slide[field]), box, requested, minSize, `${path}.${field}`);
6811
+ box.height = Math.min(maxHeight, Math.max("richLines" in text2 ? text2.height : text2.lines.length * text2.lineHeight, text2.placement?.height ?? 0));
6812
+ 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) });
6813
+ top += box.height + gap2 * 0.5;
6814
+ }
6815
+ return list;
6816
+ };
6817
+ const groupHeight = (list) => list.length ? list.at(-1).box.y + list.at(-1).box.height - list[0].box.y : 0;
6818
+ const arrangementOf = (region, units, cell) => {
6819
+ if (direction !== void 0 && region.flow !== "none") return direction === "horizontal" ? "row" : "column";
6820
+ const flow = region.flow === "none" && units.length > 1 ? "auto" : region.flow;
6821
+ if (flow === "none" || flow === "column") return "column";
6822
+ if (flow === "grid") return "grid";
6823
+ const shape = gridFlowShape(units.length, cell.width >= cell.height);
6824
+ const cards = hasCards && !region.bleed;
6825
+ const cellWidth = (cell.width - gap2 * (shape.columns - 1)) / shape.columns - (cards ? 2 * Math.min(12 * scale, cell.width / 4) : 0);
6826
+ return units.some((unit) => isLong(unit, cellWidth)) ? "column" : "grid";
6827
+ };
6828
+ const regionNeed = (name, areaWidth) => {
6829
+ const units = unitsOf(name), region = name === BELOW ? belowRegion : regionOf.get(name);
6830
+ if (!units.length) return region.empty === "keep" ? 2 * startSize * 1.22 + (hasCards && !region.bleed ? 2 * Math.min(12 * scale, areaWidth / 4) : 0) : 0;
6831
+ const shape = flowShape(arrangementOf(region, units, { width: areaWidth, height: areaWidth / 4 }), units.length, true);
6832
+ const cellWidth = (areaWidth - gap2 * (shape.columns - 1)) / shape.columns, cards = hasCards && !region.bleed;
6833
+ let total = 0, index = 0;
6834
+ for (const count of shape.perRow) {
6835
+ let row = 0;
6836
+ for (let k = 0; k < count; k++) row = Math.max(row, naturalHeight(units[index++], cellWidth, cards));
6837
+ total += row;
6838
+ }
6839
+ return total + gap2 * Math.max(0, shape.rows - 1);
6840
+ };
6841
+ 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));
6842
+ const demands = rowSizes.map((size, row) => {
6843
+ let need = 0, heading = false, below = false;
6844
+ for (const [name, rect] of rects) {
6845
+ if (size === "auto" ? rect.row !== row || rect.rowSpan !== 1 : row < rect.row || row >= rect.row + rect.rowSpan) continue;
6846
+ if (size !== "auto" && rect.rowSpan > 1 && rowSizes.slice(rect.row, rect.row + rect.rowSpan).some((entry) => entry === "auto")) continue;
6847
+ const value = areaNeed(name, rect) / rect.rowSpan;
6848
+ if (value > need) {
6849
+ need = value;
6850
+ heading = name === "title" || name === "subtitle";
6851
+ below = name === BELOW;
5959
6852
  }
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
6853
  }
6854
+ return { size, need, kind: heading ? "heading" : below ? "below" : "body" };
5990
6855
  });
6856
+ const heights = allocateRows(demands, frame.height, gap2);
6857
+ const rowY = [];
6858
+ heights.reduce((y2, size, row) => {
6859
+ rowY.push(size > 0 || !heights.slice(0, row).some((above) => above > 0) ? y2 : y2 - gap2);
6860
+ return size > 0 ? y2 + size + gap2 : y2;
6861
+ }, 0);
6862
+ const logical = (rect) => {
6863
+ const last = rect.row + rect.rowSpan - 1, y2 = frame.y + rowY[rect.row];
6864
+ return { x: frame.x + columnX[rect.column], y: y2, width: spanWidth(rect), height: Math.max(0, frame.y + rowY[last] + heights[last] - y2) };
6865
+ };
6866
+ const flip = hints.mirror === true !== rtl;
6867
+ const physical = (cell) => flip ? { ...cell, x: frame.x + frame.width - (cell.x - frame.x) - cell.width } : cell;
6868
+ const bleed = (cell) => {
6869
+ const near = (a, b) => Math.abs(a - b) < 0.01;
6870
+ const left = near(cell.x, frame.x) ? area.left : cell.x, top = near(cell.y, frame.y) ? area.top : cell.y;
6871
+ const right = near(cell.x + cell.width, frame.x + frame.width) ? area.right : cell.x + cell.width;
6872
+ const bottom = near(cell.y + cell.height, frame.y + frame.height) ? area.bottom : cell.y + cell.height;
6873
+ return { x: left, y: top, width: right - left, height: bottom - top };
6874
+ };
6875
+ const placeHeadings = (name, fields2) => {
6876
+ const rect = rects.get(name), original = ownRects.get(name);
6877
+ if (!rect) {
6878
+ if (original) headingAreas.push({ name, box: roundBox(physical(logical(original))), collapsed: true });
6879
+ return;
6880
+ }
6881
+ const cell = physical(logical(rect));
6882
+ const list = headingItemsAt(fields2, cell.x, cell.y, cell.width);
6883
+ const centred = !rowSizes.slice(rect.row, rect.row + rect.rowSpan).every((size) => size === "auto");
6884
+ const shift = centred ? Math.max(0, (cell.height - groupHeight(list)) / 2) : 0;
6885
+ for (const item of list) {
6886
+ if (shift) {
6887
+ item.box.y += shift;
6888
+ if (item.text) item.text = translateTextFit(item.text, shift);
6889
+ }
6890
+ 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." });
6891
+ items.push(item);
6892
+ }
6893
+ let parts;
6894
+ const upper = list.filter((item) => item.field !== "subtitle"), lower = list.find((item) => item.field === "subtitle");
6895
+ if (name === "title" && !plan2.subtitle && list.length) {
6896
+ const bottom = cell.y + cell.height, last = upper.at(-1);
6897
+ const split = Math.min(bottom, lower ? lower.box.y : last.box.y + last.box.height + gap2 * 0.5);
6898
+ const titleBottom = Math.max(cell.y, last ? last.box.y + last.box.height : split - gap2 * 0.5);
6899
+ 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) }) };
6900
+ }
6901
+ headingAreas.push({ name, box: roundBox(cell), ...name === "title" && implicitTitle ? { implicit: true } : {}, ...parts ? { parts } : {} });
6902
+ };
6903
+ placeHeadings("title", titleFields);
6904
+ if (plan2.subtitle) placeHeadings("subtitle", subtitleFields);
6905
+ const slideComposition = record8(slide.composition);
6906
+ const overridden = ["mode", "columns", "weights"].some((key) => slideComposition[key] !== void 0) ? plan2.regions.find((region) => region.role === "primary" && region.flow !== "none")?.name : void 0;
6907
+ const settings = { ...composition };
6908
+ const placeRegion = (region, units, area2) => {
6909
+ regionTag = region.name === BELOW ? void 0 : region.name;
6910
+ const cell = { ...area2, width: Math.max(scale, area2.width), height: Math.max(scale, area2.height) };
6911
+ templateCell = true;
6912
+ try {
6913
+ const cards = hasCards && !region.bleed;
6914
+ if (region.name === overridden) {
6915
+ arrange(units, cell, { ...settings, mode: slideComposition.mode ?? "auto" }, 0, gap2, path, true);
6916
+ return "composition";
6917
+ }
6918
+ const arrangement = arrangementOf(region, units, cell);
6919
+ let boxes = flowCells(flowShape(arrangement, units.length, cell.width >= cell.height), cell, gap2).cells;
6920
+ const referenceHeights = boxes.map((box) => box.height);
6921
+ if (arrangement === "column" && region.anchor !== "top" && units.every((unit) => !unit.children && (unit.field === "text" || unit.field === "items" || unit.field === "bullets" || !unit.caption && (unit.field === "quote" || unit.field === "metric")))) {
6922
+ const naturals = units.map((unit, index) => naturalHeight(unit, cell.width, cards, referenceHeights[index], settings) + 2 * rasterPadding + scale);
6923
+ const used = naturals.reduce((a, b) => a + b, 0) + gap2 * (units.length - 1);
6924
+ if (used < cell.height) {
6925
+ let y2 = cell.y + (region.anchor === "middle" ? (cell.height - used) / 2 : cell.height - used);
6926
+ boxes = naturals.map((size) => {
6927
+ const next = { x: cell.x, y: y2, width: cell.width, height: size };
6928
+ y2 += size + gap2;
6929
+ return next;
6930
+ });
6931
+ }
6932
+ }
6933
+ if ((arrangement === "grid" || arrangement === "row") && region.anchor !== "top") {
6934
+ const naturals = boxes.map((box, index) => {
6935
+ const unit = units[index];
6936
+ return unit.children || unit.caption || !["text", "items", "bullets", "quote", "metric"].includes(unit.field) ? void 0 : naturalHeight(unit, box.width, cards, referenceHeights[index], settings) + 2 * rasterPadding + scale;
6937
+ });
6938
+ boxes = boxes.map((box, index) => {
6939
+ const height2 = naturals[index];
6940
+ if (height2 === void 0 || height2 >= box.height) return box;
6941
+ const rowHeight = Math.max(...boxes.flatMap((peer, peerIndex) => peer.y === box.y && naturals[peerIndex] !== void 0 ? [naturals[peerIndex]] : []));
6942
+ const spare = Math.max(0, box.height - rowHeight);
6943
+ return { ...box, y: box.y + (region.anchor === "middle" ? spare / 2 : spare), height: height2 };
6944
+ });
6945
+ }
6946
+ if (rtl) boxes = boxes.map((box) => ({ ...box, x: cell.x + cell.width - (box.x - cell.x) - box.width }));
6947
+ units.forEach((unit, index) => {
6948
+ placeNode(unit, boxes[index], settings, cards, region.listColumns, region.anchor === "top" ? void 0 : referenceHeights[index]);
6949
+ });
6950
+ return arrangement;
6951
+ } finally {
6952
+ regionTag = void 0;
6953
+ templateCell = false;
6954
+ }
6955
+ };
6956
+ for (const region of plan2.regions) {
6957
+ const units = unitsOf(region.name), bound = binding.regions.find((entry) => entry.name === region.name);
6958
+ const rect = rects.get(region.name);
6959
+ let cell = physical(logical(rect ?? ownRects.get(region.name)));
6960
+ const areaBox = region.bleed && rect ? roundBox(cell) : void 0;
6961
+ if (region.bleed && rect) cell = bleed(cell);
6962
+ const arrangement = units.length && rect ? placeRegion(region, units, cell) : void 0;
6963
+ templateRegions.push({
6964
+ name: region.name,
6965
+ box: roundBox(cell),
6966
+ accepts: [...region.accepts],
6967
+ role: region.role,
6968
+ flow: region.flow,
6969
+ max: region.max,
6970
+ anchor: region.anchor,
6971
+ ...arrangement ? { arrangement } : {},
6972
+ content: bound.blocks.map((block) => block.path),
6973
+ ...bound.overflow.length ? { overflow: bound.overflow.map((block) => block.path) } : {},
6974
+ ...collapsed.joined.has(region.name) ? { collapsed: true } : {},
6975
+ ...region.bleed ? { bleed: true } : {},
6976
+ ...areaBox ? { areaBox } : {}
6977
+ });
6978
+ }
6979
+ if (belowUnits.length) placeRegion(belowRegion, belowUnits, physical(logical(rects.get(BELOW))));
5991
6980
  };
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;
6981
+ const ownMode = record8(slide.composition).mode;
5998
6982
  const direction = hints.contentDirection;
5999
6983
  const directionMode = direction === "vertical" ? "column" : direction === "horizontal" ? "row" : "auto";
6000
6984
  const chartHint = hints.chartPrimary;
6001
6985
  const chartSide = chartHint === "left" || chartHint === "right" || chartHint === "top" || chartHint === "bottom" ? chartHint : void 0;
6002
6986
  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) {
6987
+ const chartPrimary = chartSide !== void 0 && !useTemplate && !ownMode && !regions.length && chartIndex >= 0 && pending.some((node) => node.children || node.field !== "chart") ? chartSide : void 0;
6988
+ const firstChart = chartPrimary === "left" || chartPrimary === "top";
6989
+ 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 };
6990
+ if (useTemplate) composeTemplate();
6991
+ else if (chartPrimary) {
6036
6992
  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);
6993
+ const support = { field: "blocks", type: "group", value: rest.map((node) => node.payload), path, payload: {}, children: rest, composition: {}, synthetic: true };
6994
+ arrange(firstChart ? [primary, support] : [support, primary], contentBox, rootSettings, 0);
6995
+ } else arrange(pending, contentBox, rootSettings, 0);
6051
6996
  if (listBullet?.value === "image" && !bulletImage && items.some((item) => (item.field === "items" || item.field === "bullets") && item.payload.numbering === void 0)) {
6052
6997
  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
6998
  }
@@ -6087,8 +7032,7 @@ function composeSlide(input, options = {}) {
6087
7032
  } : void 0;
6088
7033
  if (failures.length) throw new OPFCompositionError(failures, explanation);
6089
7034
  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 } : {} };
7035
+ 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
7036
  }
6093
7037
  function resolveCanvasDimensions(input) {
6094
7038
  const presets = {
@@ -6103,7 +7047,7 @@ function resolveCanvasDimensions(input) {
6103
7047
  letter: [11, 8.5],
6104
7048
  a4: [11.69, 8.27]
6105
7049
  };
6106
- const value = record6(input);
7050
+ const value = record8(input);
6107
7051
  const preset = presets[typeof input === "string" ? input : value.preset] ?? presets.widescreen;
6108
7052
  const width = (value.widthInches ?? preset[0]) * 96;
6109
7053
  const height = (value.heightInches ?? preset[1]) * 96;
@@ -6111,4 +7055,4 @@ function resolveCanvasDimensions(input) {
6111
7055
  return { width, height };
6112
7056
  }
6113
7057
 
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 };
7058
+ 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 };