@openpresentation/opf 0.14.0 → 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. package/README.md +24 -38
  2. package/dist/catalog-refs-BSfGELpt.d.ts +128 -0
  3. package/dist/catalog-schemas-CinPh5WA.d.ts +12 -0
  4. package/dist/catalog.d.ts +91 -0
  5. package/dist/{chunk-XOZ4KMSR.js → catalog.js} +16514 -8800
  6. package/dist/{chart-data-B_3z9VTb.d.ts → chart-data-BnNqgnC-.d.ts} +1 -1
  7. package/dist/{chunk-LS2FMPI5.js → chunk-2CJPC4HI.js} +760 -851
  8. package/dist/{chunk-4VJDTF55.js → chunk-374R35TJ.js} +1 -1
  9. package/dist/{chunk-UPQQD7MA.js → chunk-3JG4YXWF.js} +7 -5
  10. package/dist/{chunk-4LDGKLUC.js → chunk-3RKB4RDJ.js} +1 -1
  11. package/dist/{chunk-BFLVSVA7.js → chunk-5FTUIDUH.js} +1 -1
  12. package/dist/{chunk-D3TY4TT6.js → chunk-HXHOZ7AH.js} +1407 -154
  13. package/dist/{chunk-6OXY2CP3.js → chunk-O744SXXA.js} +319 -162
  14. package/dist/{chunk-JDJBDYSR.js → chunk-QDI75P2M.js} +194 -846
  15. package/dist/chunk-SPFV27O5.js +210 -0
  16. package/dist/chunk-TRDXRRQK.js +17 -0
  17. package/dist/{chunk-Z65B2B77.js → chunk-TWQJLI6E.js} +2 -2
  18. package/dist/{chunk-Q2TCMN56.js → chunk-U4J75TRG.js} +1 -1
  19. package/dist/{chunk-XIZUK2XM.js → chunk-UBFJ2QHH.js} +5 -3
  20. package/dist/{chunk-CSQHPVGL.js → chunk-VGAOJEY7.js} +1 -1
  21. package/dist/{chunk-5ZU6JAPP.js → chunk-ZPU46TFA.js} +1 -1
  22. package/dist/{composition-_WEwBe2a.d.ts → composition-D2tghM82.d.ts} +233 -108
  23. package/dist/composition.d.ts +3 -2
  24. package/dist/composition.js +2 -2
  25. package/dist/convert.d.ts +14 -17
  26. package/dist/convert.js +36 -39
  27. package/dist/data.d.ts +1 -1
  28. package/dist/data.js +3 -3
  29. package/dist/diff.d.ts +1 -1
  30. package/dist/diff.js +7 -7
  31. package/dist/docs.js +29 -29
  32. package/dist/examples.d.ts +1 -1
  33. package/dist/examples.js +48431 -3697
  34. package/dist/{finding-C_por275.d.ts → finding-CT_f_vbD.d.ts} +2 -2
  35. package/dist/format.js +2 -2
  36. package/dist/index.d.ts +225 -76
  37. package/dist/index.js +341 -258
  38. package/dist/json-BFSdESOE.d.ts +19 -0
  39. package/dist/markdown.d.ts +19 -7
  40. package/dist/markdown.js +9 -9
  41. package/dist/{pagination-BZpXLvFL.d.ts → pagination-wedbe7eq.d.ts} +31 -31
  42. package/dist/pagination.d.ts +4 -5
  43. package/dist/pagination.js +6 -6
  44. package/dist/patch.d.ts +1 -1
  45. package/dist/patch.js +6 -6
  46. package/dist/{presentation-C5eHkevA.d.ts → presentation-CDKQVkyI.d.ts} +382 -550
  47. package/dist/repo-readme.js +1 -1
  48. package/dist/schemas.d.ts +284 -1
  49. package/dist/schemas.js +1 -1
  50. package/dist/spec/README.md +1 -1
  51. package/dist/spec/catalogs/font-schemes/angsana-new.json +1 -1
  52. package/dist/spec/catalogs/font-schemes/aparajita.json +2 -2
  53. package/dist/spec/catalogs/font-schemes/arabic-typesetting.json +1 -1
  54. package/dist/spec/catalogs/font-schemes/batang.json +1 -1
  55. package/dist/spec/catalogs/font-schemes/daunpenh.json +1 -1
  56. package/dist/spec/catalogs/font-schemes/david.json +1 -1
  57. package/dist/spec/catalogs/font-schemes/dilleniaupc.json +1 -1
  58. package/dist/spec/catalogs/font-schemes/fangsong.json +1 -1
  59. package/dist/spec/catalogs/font-schemes/gautami.json +1 -1
  60. package/dist/spec/catalogs/font-schemes/gisha.json +2 -2
  61. package/dist/spec/catalogs/font-schemes/gungsuh.json +1 -1
  62. package/dist/spec/catalogs/font-schemes/index.json +1 -1
  63. package/dist/spec/catalogs/font-schemes/kalinga.json +1 -1
  64. package/dist/spec/catalogs/font-schemes/kartika.json +1 -1
  65. package/dist/spec/catalogs/font-schemes/khmer-ui.json +1 -1
  66. package/dist/spec/catalogs/font-schemes/latha.json +1 -1
  67. package/dist/spec/catalogs/font-schemes/malgun-gothic.json +1 -1
  68. package/dist/spec/catalogs/font-schemes/mangal.json +3 -3
  69. package/dist/spec/catalogs/font-schemes/meiryo.json +1 -1
  70. package/dist/spec/catalogs/font-schemes/microsoft-jhenghei.json +1 -1
  71. package/dist/spec/catalogs/font-schemes/microsoft-yahei.json +4 -4
  72. package/dist/spec/catalogs/font-schemes/mingliu.json +1 -1
  73. package/dist/spec/catalogs/font-schemes/miriam.json +1 -1
  74. package/dist/spec/catalogs/font-schemes/ms-mincho.json +1 -1
  75. package/dist/spec/catalogs/font-schemes/nirmala-ui.json +1 -1
  76. package/dist/spec/catalogs/font-schemes/noto-naksh-arabic.json +1 -1
  77. package/dist/spec/catalogs/font-schemes/noto-nastaliq-urdu.json +2 -2
  78. package/dist/spec/catalogs/font-schemes/noto-sans-arabic.json +3 -3
  79. package/dist/spec/catalogs/font-schemes/noto-sans-armenian.json +1 -1
  80. package/dist/spec/catalogs/font-schemes/noto-sans-bengali.json +2 -2
  81. package/dist/spec/catalogs/font-schemes/noto-sans-devangari.json +2 -2
  82. package/dist/spec/catalogs/font-schemes/noto-sans-ethiopic.json +1 -1
  83. package/dist/spec/catalogs/font-schemes/noto-sans-georgian.json +1 -1
  84. package/dist/spec/catalogs/font-schemes/noto-sans-gujarati.json +1 -1
  85. package/dist/spec/catalogs/font-schemes/noto-sans-gurmukhi.json +1 -1
  86. package/dist/spec/catalogs/font-schemes/noto-sans-hebrew.json +1 -1
  87. package/dist/spec/catalogs/font-schemes/noto-sans-jp.json +1 -1
  88. package/dist/spec/catalogs/font-schemes/noto-sans-kannada.json +1 -1
  89. package/dist/spec/catalogs/font-schemes/noto-sans-khmer.json +1 -1
  90. package/dist/spec/catalogs/font-schemes/noto-sans-kr.json +1 -1
  91. package/dist/spec/catalogs/font-schemes/noto-sans-malayalam.json +1 -1
  92. package/dist/spec/catalogs/font-schemes/noto-sans-mongolian.json +1 -1
  93. package/dist/spec/catalogs/font-schemes/noto-sans-oriya.json +1 -1
  94. package/dist/spec/catalogs/font-schemes/noto-sans-sc.json +4 -4
  95. package/dist/spec/catalogs/font-schemes/noto-sans-tamil.json +1 -1
  96. package/dist/spec/catalogs/font-schemes/noto-sans-tc.json +1 -1
  97. package/dist/spec/catalogs/font-schemes/noto-sans-telugu.json +1 -1
  98. package/dist/spec/catalogs/font-schemes/noto-sans-thai.json +1 -1
  99. package/dist/spec/catalogs/font-schemes/noto-sans.json +4 -4
  100. package/dist/spec/catalogs/font-schemes/nyala.json +1 -1
  101. package/dist/spec/catalogs/font-schemes/pmingliu.json +1 -1
  102. package/dist/spec/catalogs/font-schemes/raavi.json +1 -1
  103. package/dist/spec/catalogs/font-schemes/sakkal-majalla.json +3 -3
  104. package/dist/spec/catalogs/font-schemes/shonar-bangla.json +2 -2
  105. package/dist/spec/catalogs/font-schemes/shruti.json +1 -1
  106. package/dist/spec/catalogs/font-schemes/simsun.json +1 -1
  107. package/dist/spec/catalogs/font-schemes/sylfaen.json +2 -2
  108. package/dist/spec/catalogs/font-schemes/traditional-arabic.json +3 -3
  109. package/dist/spec/catalogs/font-schemes/tunga.json +1 -1
  110. package/dist/spec/catalogs/font-schemes/vrinda.json +1 -1
  111. package/dist/spec/catalogs/font-schemes/yu-gothic.json +1 -1
  112. package/dist/spec/catalogs/layouts/capability-map.json +1 -4
  113. package/dist/spec/catalogs/layouts/chart-1x-title-center.json +30 -0
  114. package/dist/spec/catalogs/layouts/chart-2x-title-center.json +36 -0
  115. package/dist/spec/catalogs/layouts/chart-2x-vertical-title-left.json +37 -0
  116. package/dist/spec/catalogs/layouts/chart-3x-bottom-vertical-title-left.json +46 -0
  117. package/dist/spec/catalogs/layouts/chart-3x-left-title-center.json +45 -0
  118. package/dist/spec/catalogs/layouts/chart-3x-left.json +40 -0
  119. package/dist/spec/catalogs/layouts/chart-3x-right-title-center.json +45 -0
  120. package/dist/spec/catalogs/layouts/chart-3x-right.json +40 -0
  121. package/dist/spec/catalogs/layouts/chart-3x-title-center.json +39 -0
  122. package/dist/spec/catalogs/layouts/chart-3x-top-vertical-title-left.json +46 -0
  123. package/dist/spec/catalogs/layouts/competitive-landscape.json +1 -4
  124. package/dist/spec/catalogs/layouts/customer-journey.json +1 -4
  125. package/dist/spec/catalogs/layouts/decision-tree.json +1 -4
  126. package/dist/spec/catalogs/layouts/ecosystem-map.json +1 -4
  127. package/dist/spec/catalogs/layouts/extract/canonical.json +0 -9
  128. package/dist/spec/catalogs/layouts/geographic-map.json +1 -4
  129. package/dist/spec/catalogs/layouts/icon-grid.json +1 -4
  130. package/dist/spec/catalogs/layouts/image-1x-crop-title-center.json +32 -0
  131. package/dist/spec/catalogs/layouts/image-1x-crop-title-left.json +32 -0
  132. package/dist/spec/catalogs/layouts/image-1x-crop.json +27 -0
  133. package/dist/spec/catalogs/layouts/image-1x-fit-title-center.json +32 -0
  134. package/dist/spec/catalogs/layouts/image-1x.json +3 -0
  135. package/dist/spec/catalogs/layouts/image-2x-crop-title-center.json +38 -0
  136. package/dist/spec/catalogs/layouts/image-2x-crop-vertical-title-left.json +39 -0
  137. package/dist/spec/catalogs/layouts/image-2x-crop-vertical.json +34 -0
  138. package/dist/spec/catalogs/layouts/image-2x-crop.json +33 -0
  139. package/dist/spec/catalogs/layouts/image-2x-fit-title-center.json +38 -0
  140. package/dist/spec/catalogs/layouts/image-2x-fit-vertical-title-left.json +39 -0
  141. package/dist/spec/catalogs/layouts/image-2x-fit-vertical.json +34 -0
  142. package/dist/spec/catalogs/layouts/image-2x.json +3 -0
  143. package/dist/spec/catalogs/layouts/image-3x-crop-title-center.json +41 -0
  144. package/dist/spec/catalogs/layouts/image-3x-crop-vertical-title-left.json +42 -0
  145. package/dist/spec/catalogs/layouts/image-3x-crop-vertical.json +37 -0
  146. package/dist/spec/catalogs/layouts/image-3x-crop.json +36 -0
  147. package/dist/spec/catalogs/layouts/image-3x-fit-title-center.json +41 -0
  148. package/dist/spec/catalogs/layouts/image-3x-fit-vertical-title-left.json +42 -0
  149. package/dist/spec/catalogs/layouts/image-3x-fit-vertical.json +37 -0
  150. package/dist/spec/catalogs/layouts/image-3x-fit.json +36 -0
  151. package/dist/spec/catalogs/layouts/image-3x.json +3 -0
  152. package/dist/spec/catalogs/layouts/image-focus.json +3 -6
  153. package/dist/spec/catalogs/layouts/image-only-1x-crop-title-center.json +31 -0
  154. package/dist/spec/catalogs/layouts/image-only-1x-fit-title-center.json +31 -0
  155. package/dist/spec/catalogs/layouts/image-only-2x-crop-title-center.json +37 -0
  156. package/dist/spec/catalogs/layouts/image-only-2x-crop-vertical-title-left.json +38 -0
  157. package/dist/spec/catalogs/layouts/image-only-2x-crop-vertical.json +33 -0
  158. package/dist/spec/catalogs/layouts/image-only-2x-fit-title-center.json +37 -0
  159. package/dist/spec/catalogs/layouts/image-only-2x-fit-vertical-title-left.json +38 -0
  160. package/dist/spec/catalogs/layouts/image-only-2x-fit-vertical.json +33 -0
  161. package/dist/spec/catalogs/layouts/image-only-3x-crop-title-center.json +40 -0
  162. package/dist/spec/catalogs/layouts/image-only-3x-crop-vertical-title-left.json +41 -0
  163. package/dist/spec/catalogs/layouts/image-only-3x-crop-vertical.json +36 -0
  164. package/dist/spec/catalogs/layouts/image-only-3x-crop.json +35 -0
  165. package/dist/spec/catalogs/layouts/image-only-3x-fit-title-center.json +40 -0
  166. package/dist/spec/catalogs/layouts/image-only-3x-fit-vertical-title-left.json +41 -0
  167. package/dist/spec/catalogs/layouts/image-only-3x-fit-vertical.json +36 -0
  168. package/dist/spec/catalogs/layouts/image-only-3x-fit.json +35 -0
  169. package/dist/spec/catalogs/layouts/index.json +1041 -151
  170. package/dist/spec/catalogs/layouts/list-1x-box-title-center.json +32 -0
  171. package/dist/spec/catalogs/layouts/list-1x-box-vertical-title-center.json +33 -0
  172. package/dist/spec/catalogs/layouts/list-1x-box-vertical-title-left.json +33 -0
  173. package/dist/spec/catalogs/layouts/list-1x-box-vertical.json +28 -0
  174. package/dist/spec/catalogs/layouts/list-1x-box.json +27 -0
  175. package/dist/spec/catalogs/layouts/list-1x-itemimage-title-center.json +32 -0
  176. package/dist/spec/catalogs/layouts/list-1x-itemimage-vertical-title-center.json +33 -0
  177. package/dist/spec/catalogs/layouts/list-1x-title-center.json +31 -0
  178. package/dist/spec/catalogs/layouts/list-1x-vertical-title-center.json +32 -0
  179. package/dist/spec/catalogs/layouts/list-2x-box-title-center.json +38 -0
  180. package/dist/spec/catalogs/layouts/list-2x-box-vertical-title-center.json +39 -0
  181. package/dist/spec/catalogs/layouts/list-2x-box-vertical-title-left.json +39 -0
  182. package/dist/spec/catalogs/layouts/list-2x-box-vertical.json +34 -0
  183. package/dist/spec/catalogs/layouts/list-2x-box.json +33 -0
  184. package/dist/spec/catalogs/layouts/list-2x-itemimage-title-center.json +38 -0
  185. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical-title-center.json +39 -0
  186. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical-title-left.json +39 -0
  187. package/dist/spec/catalogs/layouts/list-2x-itemimage-vertical.json +34 -0
  188. package/dist/spec/catalogs/layouts/list-2x-title-center.json +37 -0
  189. package/dist/spec/catalogs/layouts/list-2x-vertical-title-center.json +38 -0
  190. package/dist/spec/catalogs/layouts/list-2x-vertical-title-left.json +38 -0
  191. package/dist/spec/catalogs/layouts/list-2x-vertical.json +33 -0
  192. package/dist/spec/catalogs/layouts/list-3x-box-title-center.json +41 -0
  193. package/dist/spec/catalogs/layouts/list-3x-box-vertical-title-center.json +42 -0
  194. package/dist/spec/catalogs/layouts/list-3x-box-vertical-title-left.json +42 -0
  195. package/dist/spec/catalogs/layouts/list-3x-box-vertical.json +37 -0
  196. package/dist/spec/catalogs/layouts/list-3x-box.json +36 -0
  197. package/dist/spec/catalogs/layouts/list-3x-itemimage-title-center.json +41 -0
  198. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical-title-center.json +42 -0
  199. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical-title-left.json +42 -0
  200. package/dist/spec/catalogs/layouts/list-3x-itemimage-vertical.json +37 -0
  201. package/dist/spec/catalogs/layouts/list-3x-itemimage.json +36 -0
  202. package/dist/spec/catalogs/layouts/list-3x-title-center.json +40 -0
  203. package/dist/spec/catalogs/layouts/list-3x-vertical-title-center.json +41 -0
  204. package/dist/spec/catalogs/layouts/list-3x-vertical-title-left.json +41 -0
  205. package/dist/spec/catalogs/layouts/list-3x-vertical.json +36 -0
  206. package/dist/spec/catalogs/layouts/list-4x-box-title-center.json +45 -0
  207. package/dist/spec/catalogs/layouts/list-4x-box-vertical-title-center.json +45 -0
  208. package/dist/spec/catalogs/layouts/list-4x-box-vertical-title-left.json +45 -0
  209. package/dist/spec/catalogs/layouts/list-4x-box-vertical.json +40 -0
  210. package/dist/spec/catalogs/layouts/list-4x-box.json +40 -0
  211. package/dist/spec/catalogs/layouts/list-4x-itemimage-title-center.json +45 -0
  212. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical-title-center.json +45 -0
  213. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical-title-left.json +45 -0
  214. package/dist/spec/catalogs/layouts/list-4x-itemimage-vertical.json +40 -0
  215. package/dist/spec/catalogs/layouts/list-4x-title-center.json +44 -0
  216. package/dist/spec/catalogs/layouts/list-4x-vertical-title-center.json +44 -0
  217. package/dist/spec/catalogs/layouts/list-4x-vertical-title-left.json +44 -0
  218. package/dist/spec/catalogs/layouts/list-4x-vertical.json +39 -0
  219. package/dist/spec/catalogs/layouts/list-5x-box-title-center.json +48 -0
  220. package/dist/spec/catalogs/layouts/list-5x-box-vertical-title-center.json +50 -0
  221. package/dist/spec/catalogs/layouts/list-5x-box-vertical-title-left.json +50 -0
  222. package/dist/spec/catalogs/layouts/list-5x-box-vertical.json +45 -0
  223. package/dist/spec/catalogs/layouts/list-5x-box.json +43 -0
  224. package/dist/spec/catalogs/layouts/list-5x-itemimage-title-center.json +48 -0
  225. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical-title-center.json +48 -0
  226. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical-title-left.json +48 -0
  227. package/dist/spec/catalogs/layouts/list-5x-itemimage-vertical.json +43 -0
  228. package/dist/spec/catalogs/layouts/list-5x-title-center.json +47 -0
  229. package/dist/spec/catalogs/layouts/list-5x-vertical-title-center.json +47 -0
  230. package/dist/spec/catalogs/layouts/list-5x-vertical-title-left.json +47 -0
  231. package/dist/spec/catalogs/layouts/list-5x-vertical.json +42 -0
  232. package/dist/spec/catalogs/layouts/list-6x-box-title-center.json +51 -0
  233. package/dist/spec/catalogs/layouts/list-6x-box-vertical-title-center.json +53 -0
  234. package/dist/spec/catalogs/layouts/list-6x-box-vertical-title-left.json +53 -0
  235. package/dist/spec/catalogs/layouts/list-6x-box-vertical.json +48 -0
  236. package/dist/spec/catalogs/layouts/list-6x-box.json +46 -0
  237. package/dist/spec/catalogs/layouts/list-6x-itemimage-title-center.json +51 -0
  238. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical-title-center.json +51 -0
  239. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical-title-left.json +51 -0
  240. package/dist/spec/catalogs/layouts/list-6x-itemimage-vertical.json +46 -0
  241. package/dist/spec/catalogs/layouts/list-6x-title-center.json +50 -0
  242. package/dist/spec/catalogs/layouts/list-6x-vertical-title-center.json +50 -0
  243. package/dist/spec/catalogs/layouts/list-6x-vertical-title-left.json +50 -0
  244. package/dist/spec/catalogs/layouts/list-6x-vertical.json +45 -0
  245. package/dist/spec/catalogs/layouts/network-dependency-map.json +1 -4
  246. package/dist/spec/catalogs/layouts/number-1x-box-title-center.json +30 -0
  247. package/dist/spec/catalogs/layouts/number-1x-box.json +25 -0
  248. package/dist/spec/catalogs/layouts/number-1x-title-center.json +29 -0
  249. package/dist/spec/catalogs/layouts/number-2x-box-title-center.json +36 -0
  250. package/dist/spec/catalogs/layouts/number-2x-box.json +31 -0
  251. package/dist/spec/catalogs/layouts/number-2x-title-center.json +35 -0
  252. package/dist/spec/catalogs/layouts/number-3x-box-title-center.json +39 -0
  253. package/dist/spec/catalogs/layouts/number-3x-box.json +34 -0
  254. package/dist/spec/catalogs/layouts/number-3x-title-center.json +38 -0
  255. package/dist/spec/catalogs/layouts/number-4x-box-title-center.json +43 -0
  256. package/dist/spec/catalogs/layouts/number-4x-box.json +38 -0
  257. package/dist/spec/catalogs/layouts/number-4x-title-center.json +42 -0
  258. package/dist/spec/catalogs/layouts/number-5x-box-title-center.json +46 -0
  259. package/dist/spec/catalogs/layouts/number-5x-box.json +41 -0
  260. package/dist/spec/catalogs/layouts/number-5x-title-center.json +45 -0
  261. package/dist/spec/catalogs/layouts/number-6x-box-title-center.json +49 -0
  262. package/dist/spec/catalogs/layouts/number-6x-box.json +44 -0
  263. package/dist/spec/catalogs/layouts/number-6x-title-center.json +48 -0
  264. package/dist/spec/catalogs/layouts/persona-grid.json +1 -4
  265. package/dist/spec/catalogs/layouts/photo-grid.json +1 -4
  266. package/dist/spec/catalogs/layouts/product-feature.json +1 -4
  267. package/dist/spec/catalogs/layouts/screenshot-walkthrough.json +1 -4
  268. package/dist/spec/catalogs/layouts/swimlane-process.json +1 -4
  269. package/dist/spec/catalogs/layouts/team-bio.json +1 -4
  270. package/dist/spec/catalogs/layouts/text-1x-box-title-center.json +31 -0
  271. package/dist/spec/catalogs/layouts/text-1x-box-title-left.json +31 -0
  272. package/dist/spec/catalogs/layouts/text-1x-center-box-title-center.json +31 -0
  273. package/dist/spec/catalogs/layouts/text-1x-center-box-title-left.json +31 -0
  274. package/dist/spec/catalogs/layouts/text-1x-center-box.json +26 -0
  275. package/dist/spec/catalogs/layouts/text-1x-center-title-center.json +30 -0
  276. package/dist/spec/catalogs/layouts/text-1x-center-title-left.json +30 -0
  277. package/dist/spec/catalogs/layouts/text-1x-center.json +25 -0
  278. package/dist/spec/catalogs/layouts/text-1x-left-box.json +26 -0
  279. package/dist/spec/catalogs/layouts/text-1x-title-center.json +30 -0
  280. package/dist/spec/catalogs/layouts/text-2x-box-title-center.json +37 -0
  281. package/dist/spec/catalogs/layouts/text-2x-box-vertical-title-left.json +37 -0
  282. package/dist/spec/catalogs/layouts/text-2x-center-box-title-center.json +37 -0
  283. package/dist/spec/catalogs/layouts/text-2x-center-box-vertical-title-left.json +37 -0
  284. package/dist/spec/catalogs/layouts/text-2x-center-box.json +32 -0
  285. package/dist/spec/catalogs/layouts/text-2x-center-title-center.json +36 -0
  286. package/dist/spec/catalogs/layouts/text-2x-center-vertical-title-left.json +36 -0
  287. package/dist/spec/catalogs/layouts/text-2x-center.json +31 -0
  288. package/dist/spec/catalogs/layouts/text-2x-left-box.json +32 -0
  289. package/dist/spec/catalogs/layouts/text-2x-title-center.json +36 -0
  290. package/dist/spec/catalogs/layouts/text-2x-vertical-title-left.json +36 -0
  291. package/dist/spec/catalogs/layouts/text-3x-box-title-center.json +40 -0
  292. package/dist/spec/catalogs/layouts/text-3x-box-vertical-title-left.json +41 -0
  293. package/dist/spec/catalogs/layouts/text-3x-center-box-title-center.json +40 -0
  294. package/dist/spec/catalogs/layouts/text-3x-center-box-vertical-title-left.json +41 -0
  295. package/dist/spec/catalogs/layouts/text-3x-center-box.json +35 -0
  296. package/dist/spec/catalogs/layouts/text-3x-center-title-center.json +39 -0
  297. package/dist/spec/catalogs/layouts/text-3x-center-vertical-title-left.json +40 -0
  298. package/dist/spec/catalogs/layouts/text-3x-center.json +34 -0
  299. package/dist/spec/catalogs/layouts/text-3x-left-box.json +35 -0
  300. package/dist/spec/catalogs/layouts/text-3x-left.json +34 -0
  301. package/dist/spec/catalogs/layouts/text-3x-title-center.json +39 -0
  302. package/dist/spec/catalogs/layouts/text-3x-vertical-title-left.json +40 -0
  303. package/dist/spec/catalogs/layouts/title-center-box.json +27 -0
  304. package/dist/spec/catalogs/layouts/title-center-image-bottom.json +34 -0
  305. package/dist/spec/catalogs/layouts/title-center-image-top.json +34 -0
  306. package/dist/spec/catalogs/layouts/title-center.json +26 -0
  307. package/dist/spec/catalogs/layouts/title-left-image-bottom.json +34 -0
  308. package/dist/spec/catalogs/layouts/title-left-image-left.json +34 -0
  309. package/dist/spec/catalogs/layouts/title-left-image-right.json +34 -0
  310. package/dist/spec/catalogs/layouts/title-left-image-top.json +34 -0
  311. package/dist/spec/catalogs/manifest.json +18 -18
  312. package/dist/spec/catalogs/narratives/heros-journey.json +1 -1
  313. package/dist/spec/catalogs/narratives/index.json +1 -1
  314. package/dist/spec/openapi.yaml +3 -3
  315. package/dist/spec/reference/engine-defaults.json +22 -30
  316. package/dist/spec/reference/engine-vocabularies.json +1577 -0
  317. package/dist/spec/schemas/audience.schema.json +5 -26
  318. package/dist/spec/schemas/catalog-manifest.schema.json +3 -3
  319. package/dist/spec/schemas/chart-type.schema.json +2 -35
  320. package/dist/spec/schemas/color-scheme.schema.json +3 -24
  321. package/dist/spec/schemas/finding.schema.json +1 -1
  322. package/dist/spec/schemas/font-scheme.schema.json +6 -37
  323. package/dist/spec/schemas/language.schema.json +7 -28
  324. package/dist/spec/schemas/layout.schema.json +56 -51
  325. package/dist/spec/schemas/narrative.schema.json +4 -24
  326. package/dist/spec/schemas/opf.schema.json +399 -368
  327. package/dist/spec/schemas/purpose.schema.json +5 -26
  328. package/dist/spec/schemas/social-platform.schema.json +2 -23
  329. package/dist/spec/schemas/theme.schema.json +9 -37
  330. package/dist/spec/schemas/tone.schema.json +4 -25
  331. package/dist/spec-files.d.ts +1 -1
  332. package/dist/spec-files.js +1 -1
  333. package/dist/types.d.ts +1125 -4
  334. package/dist/{validation-types-zh03LeZy.d.ts → validation-types-BOcY9GTs.d.ts} +7 -7
  335. package/dist/validator.d.ts +15 -12
  336. package/dist/validator.js +5 -5
  337. package/dist/yaml.d.ts +22 -7
  338. package/dist/yaml.js +10 -9
  339. package/package.json +5 -9
  340. package/dist/catalogs-D-yyQWCQ.d.ts +0 -1343
  341. package/dist/catalogs.d.ts +0 -2
  342. package/dist/catalogs.js +0 -2
  343. package/dist/chunk-PIQXLBBJ.js +0 -445
  344. package/dist/chunk-S5W34SIJ.js +0 -1
  345. package/dist/previews.d.ts +0 -40
  346. package/dist/previews.js +0 -1
  347. package/dist/schemas-DDpqAgyS.d.ts +0 -284
  348. package/dist/spec/catalogs/layouts/image-bleed.json +0 -20
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://openpresentation.org/schema/opf/v1",
4
4
  "title": "Presentation",
5
- "description": "Open-source JSON format for describing PowerPoint presentations. Agents describe narratives, content, audience, reusable assets, and design — the engine handles OOXML complexity.\n\nFields that reference catalog records (narrative, language, tone, audience, purpose, design.theme / design.theme.id, design.colorScheme / design.colorScheme.id, design.fontScheme / design.fontScheme.id, Slide.layout, Chart.type, Organization.socials / Speaker.socials) resolve through the catalog system: inline 'catalogs.<kind>.records[]' on the document → 'catalogs.<kind>.source' on the document → engine defaults → the default catalog at https://www.pptx.gallery/<kind>. The default catalog is published by pptx.gallery: the index at https://www.pptx.gallery/<kind>/index.json (also GET https://www.pptx.gallery/<kind> with Accept: application/json) and each record at https://www.pptx.gallery/<kind>/<id>.json. Engines resolve it from the pinned snapshot bundled in @openpresentation/opf (spec/catalogs, pinned by spec/catalogs/manifest.json) and never fetch it at run time; fetching a document's catalogs.<kind>.source is an explicit opt-in by the caller. Every reference resolves to the catalog record's 'id' field. When an OPF document omits a reference entirely, the engine falls back to engine defaults (see /spec/reference/engine-defaults.json for a reference example). The defaults file is engine configuration; it is not part of the OPF document contract and has no JSON Schema.\n\nMost catalog references accept the bare 'id' as a string for the common case (e.g. narrative = 'classic-story', design.colorScheme = 'cool-horizon'). Audience, purpose, tone, design, and language object forms use 'id' as a base catalog reference plus inline overrides. Asset references use 'asset:<id>' strings that point into the top-level assets registry, and content color fields (rich-text runs, styled table cells) accept hex values, color-scheme slot/role names, or 'var:<id>' references into the top-level variables map.",
5
+ "description": "Open-source JSON format for describing PowerPoint presentations. Agents describe narratives, content, audience, reusable assets, and design — the engine handles OOXML complexity.\n\nContent references (Slide.layout, design.theme, design.colorScheme / design.colorScheme.id, design.fontScheme / design.fontScheme.id, narrative, audience, purpose and tone, and the colorScheme / fontScheme a theme record names) point at catalog records. Each is a bare 'id' or a 'name:id' whose prefix names a group in 'catalogs'. A bare id resolves in catalogs.custom, then in the records embedded under catalogs.default, then in the catalog the host registered for catalogs.default.source (or the host's default catalog when 'default' is omitted); 'name:id' resolves in catalogs.<name>, then in the catalog the host registered for its source. A reference that resolves nowhere is the warning opf/unresolved-reference, and the slide uses automatic composition or the engine default. Engines never fetch a catalog: a saved document embeds every record it uses, and hosts register any other catalog by its source string. See docs/default-catalog.md.\n\nchart.type, the language tag and the keys of Organization.socials / Speaker.socials are engine vocabularies, validated directly with no catalog lookup. When a document names no theme, colour scheme or font scheme, every engine uses the same small engine defaults (spec/reference/engine-defaults.json). Asset references use 'asset:<id>' strings that point into the top-level assets registry, and content color fields (rich-text runs, styled table cells) accept hex values, color-scheme slot/role names, or 'var:<id>' references into the top-level variables map.",
6
6
  "type": "object",
7
7
  "required": ["slides"],
8
8
  "additionalProperties": false,
@@ -76,17 +76,22 @@
76
76
  "minItems": 1
77
77
  }
78
78
  ],
79
- "description": "Intended audiences for the presentation. Accepts any of:\n- A single string shorthand: free-form description ('Series B investors'), an audiences catalog id ('executive'), an HTTPS URL, or a 'pkg:' reference.\n- A single inline Audience object, like purpose and tone, for custom audience metadata or catalog-backed overrides. Object form mirrors https://openpresentation.org/schema/opf-audience/v1 without '$schema'.\n- An array of string shorthands and/or inline Audience objects, for more than one audience.\n\nResolution order for catalog ids and references: inline catalogs.audiences.records[] → catalogs.audiences.source → default catalog at https://www.pptx.gallery/audiences.",
79
+ "description": "Intended audiences for the presentation. Accepts any of:\n- A single string: an audiences reference ('executive', or 'acme:board' for a record of the catalogs.acme group), or free-form text ('Series B investors'). A string that is a bare id or 'name:id' is a reference; any other string is free text and is never looked up.\n- A single inline Audience object, for custom audience metadata or overrides on a referenced record. Object form has the fields of https://openpresentation.org/schema/opf-audience/v1.\n- An array of strings and/or inline Audience objects, for more than one audience.\n\nA reference resolves like every content reference (see catalogs); one that resolves nowhere is the warning opf/unresolved-reference. Nothing is drawn from the audience.",
80
80
  "examples": [
81
81
  "executive",
82
82
  "Biology Students and Wildlife Enthusiasts",
83
83
  ["executive"],
84
84
  ["board", "c-suite"],
85
85
  { "id": "executive", "attentionBudgetMinutes": 20 },
86
- ["Series B investors", "https://acme.com/decks/audiences/acme-board.json"],
86
+ ["Series B investors", "acme:board"],
87
87
  [
88
88
  { "id": "executive", "attentionBudgetMinutes": 20 },
89
- { "name": "Regional Sales Leaders", "seniority": "director", "technicalFluency": "medium", "decisionPower": "advisory" }
89
+ {
90
+ "name": "Regional Sales Leaders",
91
+ "seniority": "director",
92
+ "technicalFluency": "medium",
93
+ "decisionPower": "advisory"
94
+ }
90
95
  ]
91
96
  ]
92
97
  },
@@ -95,51 +100,39 @@
95
100
  { "type": "string" },
96
101
  { "$ref": "#/$defs/Purpose" }
97
102
  ],
98
- "description": "Primary goal of the presentation. Accepts either:\n- A string shorthand: free-form goal ('Raise a Series B round of $30M'), a purposes catalog id ('decide', 'align'), an HTTPS URL, or a 'pkg:' reference.\n- An inline Purpose object for custom purpose metadata or catalog-backed overrides. Object form mirrors https://openpresentation.org/schema/opf-purpose/v1 without '$schema'.\n\nResolution order for catalog ids and references: inline catalogs.purposes.records[] → catalogs.purposes.source → default catalog at https://www.pptx.gallery/purposes.",
103
+ "description": "Primary goal of the presentation. Accepts either:\n- A string: a purposes reference ('decide', or 'acme:fundraise' for a record of the catalogs.acme group), or a free-form goal ('Raise a Series B round of $30M'). A string that is a bare id or 'name:id' is a reference; any other string is free text and is never looked up.\n- An inline Purpose object for custom purpose metadata or overrides on a referenced record. Object form has the fields of https://openpresentation.org/schema/opf-purpose/v1.\n\nA reference resolves like every content reference (see catalogs); one that resolves nowhere is the warning opf/unresolved-reference. Nothing is drawn from the purpose.",
99
104
  "examples": [
100
105
  "Raise a Series B round of $30M",
101
106
  "align",
102
107
  "educate",
103
- "https://acme.com/decks/purposes/fundraise.json",
104
- "pkg:@acme/decks/purposes/fundraise",
108
+ "acme:fundraise",
105
109
  { "id": "decide", "outcome": "Approve the Q4 hiring plan" },
106
110
  { "name": "Secure renewal", "outcome": "Customer signs a 12-month renewal" }
107
111
  ]
108
112
  },
109
113
  "language": {
110
- "oneOf": [
111
- { "type": "string" },
112
- { "$ref": "#/$defs/Language" }
113
- ],
114
- "description": "Language for the presentation content. Accepts either:\n- A string shorthand: a BCP-47 language tag ('en-US', 'en-GB', 'ja-JP', 'fr'), a languages catalog id ('english', 'japanese'), an HTTPS URL, or a 'pkg:' reference.\n- An inline Language object for custom language metadata or catalog-backed overrides. Object form mirrors https://openpresentation.org/schema/opf-language/v1 without '$schema'.\n\nResolution order for catalog ids and references: inline catalogs.languages.records[] → catalogs.languages.source → default catalog at https://www.pptx.gallery/languages.",
114
+ "oneOf": [{ "$ref": "#/$defs/LanguageTag" }, { "$ref": "#/$defs/Language" }],
115
+ "description": "Language of the presentation content, an engine vocabulary: a BCP-47 language tag, validated directly with no catalog lookup. Accepts either:\n- A BCP-47 tag ('en-US', 'en-GB', 'ja', 'zh-Hans', 'ar-SA').\n- An inline Language object: a 'bcp47' tag plus overrides of what engines know about it (name, ooxmlLang, script, direction, the script font schemes).\n\nEngines know the script, base direction, OOXML language tag and default script fonts of the tags in spec/reference/engine-vocabularies.json; any other well-formed tag is accepted and its script is inferred from the tag. Language names and descriptions are catalog display metadata, not part of the document.",
115
116
  "examples": [
116
117
  "en-US",
117
118
  "en-GB",
118
119
  "es-MX",
119
- "ja-JP",
120
+ "ja",
120
121
  "fr",
121
- "english",
122
- "japanese",
123
- "https://acme.com/decks/languages/en-acme.json",
124
- "pkg:@acme/decks/languages/en-acme",
125
- { "id": "english", "bcp47": "en-US", "fontScheme": "aptos", "googleFontScheme": "roboto" },
122
+ { "bcp47": "en-US", "fontScheme": "aptos", "googleFontScheme": "roboto" },
126
123
  { "bcp47": "ar-SA", "name": "Arabic (Saudi Arabia)", "direction": "rtl", "script": "Arab" }
127
124
  ]
128
125
  },
129
126
  "tone": {
130
- "oneOf": [
131
- { "type": "string" },
132
- { "$ref": "#/$defs/Tone" }
133
- ],
134
- "description": "Desired tone for the presentation. Accepts either:\n- A string shorthand: a tones catalog id ('formal'), an HTTPS URL, or a 'pkg:' reference.\n- An inline Tone object for custom tone metadata or catalog-backed overrides. Object form mirrors https://openpresentation.org/schema/opf-tone/v1 without '$schema'.\n\nResolution order for catalog ids and references: inline catalogs.tones.records[] → catalogs.tones.source → default catalog at https://www.pptx.gallery/tones.",
127
+ "oneOf": [{ "$ref": "#/$defs/CatalogReference" }, { "$ref": "#/$defs/Tone" }],
128
+ "description": "Desired tone for the presentation. Accepts either:\n- A tones reference: a bare id ('formal') or 'name:id' for a record of a named catalogs group.\n- An inline Tone object for custom tone metadata or overrides on a referenced record. Object form has the fields of https://openpresentation.org/schema/opf-tone/v1.\n\nA reference resolves like every content reference (see catalogs); one that resolves nowhere is the warning opf/unresolved-reference. Nothing is drawn from the tone.",
135
129
  "examples": [
136
130
  "formal",
137
131
  "casual",
138
132
  "inspirational",
139
133
  "technical",
140
134
  "persuasive",
141
- "https://acme.com/decks/tones/acme-voice.json",
142
- "pkg:@acme/decks/tones/acme-voice",
135
+ "acme:house-voice",
143
136
  { "id": "formal", "voiceCues": ["Use precise, concise language."] },
144
137
  { "name": "Founder direct", "voiceCues": ["Use first person sparingly.", "Make the ask concrete."] }
145
138
  ]
@@ -188,16 +181,9 @@
188
181
  "default": false
189
182
  },
190
183
  "narrative": {
191
- "type": "string",
192
- "description": "The deck's narrative plan, by reference: the 'id' of a 'narratives' catalog record, an HTTPS URL pointing at a record file, or a 'pkg:' reference to a locally-installed package. The deck holds only this pointer; the plan (the arc, its beats and what each beat must do) lives in the catalog record, which validates against https://openpresentation.org/schema/opf-narrative/v1. A custom narrative is a record in catalogs.narratives.records, referenced here by its id.\n\nSlides link themselves to beats with slides[].beat. Core validate warns about a slides[].beat id the resolved narrative does not define and about a root 'duration' outside its 'duration' range, and reports a beat that no slide references. The preview and the PPTX export draw nothing from the narrative; opf-pptx stores the reference for round-trip.\n\nResolution order: inline catalogs.narratives.records[] → catalogs.narratives.source → default catalog at https://www.pptx.gallery/narratives. Unknown ids produce a validation warning, not an error.\n\nDeck-level concerns that are not part of the storyline (audience, tone, takeaway, duration) live as siblings on the presentation root.",
193
- "examples": [
194
- "classic-story",
195
- "problem-solution",
196
- "scqa",
197
- "pitch-deck",
198
- "https://acme.com/decks/narratives/founder-pitch.json",
199
- "pkg:@acme/decks/narratives/founder-pitch"
200
- ]
184
+ "$ref": "#/$defs/CatalogReference",
185
+ "description": "The deck's narrative plan, by reference: a bare narratives id ('classic-story') or 'name:id' for a record of a named catalogs group ('acme:founder-pitch'). The deck holds only this pointer; the plan (the arc, its beats and what each beat must do) lives in the record, which has the fields of https://openpresentation.org/schema/opf-narrative/v1. A narrative the document defines itself is a record in catalogs.custom.narratives, referenced here by its key.\n\nSlides link themselves to beats with slides[].beat. Core validate warns about a slides[].beat id the resolved narrative does not define and about a root 'duration' outside its 'duration' range, and reports a beat that no slide references. The preview and the PPTX export draw nothing from the narrative; opf-pptx stores the reference for round-trip.\n\nThe reference resolves like every content reference (see catalogs); one that resolves nowhere is the warning opf/unresolved-reference, never an error.\n\nDeck-level concerns that are not part of the storyline (audience, tone, takeaway, duration) live as siblings on the presentation root.",
186
+ "examples": ["classic-story", "problem-solution", "scqa", "pitch-deck", "acme:founder-pitch"]
201
187
  },
202
188
  "slides": {
203
189
  "type": "array",
@@ -221,7 +207,7 @@
221
207
  },
222
208
  "catalogs": {
223
209
  "$ref": "#/$defs/Catalogs",
224
- "description": "Optional per-kind catalog overrides. Each kind may declare a non-default 'source' and/or inline 'records' that override or supplement the default catalog at https://www.pptx.gallery/<kind>. References elsewhere in the document (e.g. design.theme, narrative) resolve through this section before falling back to the default catalog."
210
+ "description": "The catalog records this document embeds, grouped by the catalog they came from: 'default' (the catalog bare ids come from), 'custom' (records the document defines itself) and any number of named catalogs ('acme', referenced as 'acme:<id>'). A saved document embeds every record it references, so it renders the same with no catalog registered. See Catalogs."
225
211
  },
226
212
  "extensions": {
227
213
  "type": "object",
@@ -284,16 +270,15 @@
284
270
  },
285
271
  "Audience": {
286
272
  "type": "object",
287
- "description": "Inline audience metadata for the presentation. Use 'id' to reference an audiences catalog record and override selected fields, or use 'name' for a custom inline audience.",
273
+ "description": "Inline audience metadata for the presentation. Use 'id' to reference an audiences record (a bare id or 'name:id') and override selected fields, or use 'name' for a custom inline audience.",
288
274
  "anyOf": [
289
275
  { "required": ["id"] },
290
276
  { "required": ["name"] }
291
277
  ],
292
278
  "properties": {
293
279
  "id": {
294
- "type": "string",
295
- "pattern": "^[a-z][a-z0-9-]*$",
296
- "description": "Optional audiences catalog id to resolve before applying inline overrides.",
280
+ "$ref": "#/$defs/CatalogReference",
281
+ "description": "Optional audiences reference (a bare id or 'name:id') resolved before applying the inline overrides.",
297
282
  "examples": ["executive", "board", "engineering-team"]
298
283
  },
299
284
  "name": {
@@ -331,12 +316,12 @@
331
316
  "recommendedNarratives": {
332
317
  "type": "array",
333
318
  "items": { "type": "string" },
334
- "description": "Soft cross-link: narrative-catalog ids that work well for this audience."
319
+ "description": "Soft cross-link: narrative ids that work well for this audience, for picker UIs. Never resolved, embedded or validated as references."
335
320
  },
336
321
  "recommendedTones": {
337
322
  "type": "array",
338
323
  "items": { "type": "string" },
339
- "description": "Soft cross-link: tone-catalog ids that work well for this audience."
324
+ "description": "Soft cross-link: tone ids that work well for this audience, for picker UIs. Never resolved, embedded or validated as references."
340
325
  },
341
326
  "tags": {
342
327
  "type": "array",
@@ -347,16 +332,15 @@
347
332
  },
348
333
  "Purpose": {
349
334
  "type": "object",
350
- "description": "Inline purpose metadata for the presentation. Use 'id' to reference a purposes catalog record and override selected fields, or use 'name' for a custom inline purpose.",
335
+ "description": "Inline purpose metadata for the presentation. Use 'id' to reference a purposes record (a bare id or 'name:id') and override selected fields, or use 'name' for a custom inline purpose.",
351
336
  "anyOf": [
352
337
  { "required": ["id"] },
353
338
  { "required": ["name"] }
354
339
  ],
355
340
  "properties": {
356
341
  "id": {
357
- "type": "string",
358
- "pattern": "^[a-z][a-z0-9-]*$",
359
- "description": "Optional purposes catalog id to resolve before applying inline overrides.",
342
+ "$ref": "#/$defs/CatalogReference",
343
+ "description": "Optional purposes reference (a bare id or 'name:id') resolved before applying the inline overrides.",
360
344
  "examples": ["inform", "decide", "align", "persuade", "educate"]
361
345
  },
362
346
  "name": {
@@ -383,12 +367,12 @@
383
367
  "recommendedNarratives": {
384
368
  "type": "array",
385
369
  "items": { "type": "string" },
386
- "description": "Soft cross-link: narrative-catalog ids that work well for this purpose."
370
+ "description": "Soft cross-link: narrative ids that work well for this purpose, for picker UIs. Never resolved, embedded or validated as references."
387
371
  },
388
372
  "recommendedTones": {
389
373
  "type": "array",
390
374
  "items": { "type": "string" },
391
- "description": "Soft cross-link: tone-catalog ids that work well for this purpose."
375
+ "description": "Soft cross-link: tone ids that work well for this purpose, for picker UIs. Never resolved, embedded or validated as references."
392
376
  },
393
377
  "tags": {
394
378
  "type": "array",
@@ -399,31 +383,23 @@
399
383
  },
400
384
  "Language": {
401
385
  "type": "object",
402
- "description": "Inline language metadata for the presentation. Use 'id' to reference a languages catalog record and override selected fields, or use 'bcp47' for a custom language tag without a catalog record.",
403
- "anyOf": [
404
- { "required": ["id"] },
405
- { "required": ["bcp47"] }
406
- ],
386
+ "description": "Inline language metadata for the presentation: a BCP-47 'bcp47' tag plus overrides of what engines know about it. Languages are an engine vocabulary, not catalog records, so there is no 'id'.",
387
+ "required": ["bcp47"],
388
+ "not": { "required": ["id"] },
407
389
  "properties": {
408
- "id": {
409
- "type": "string",
410
- "pattern": "^[a-z][a-z0-9-]*$",
411
- "description": "Optional languages catalog id to resolve before applying inline overrides.",
412
- "examples": ["english", "japanese", "chinese-simplified", "english-uk"]
413
- },
414
390
  "name": {
415
391
  "type": "string",
416
392
  "description": "Human-readable language name.",
417
393
  "examples": ["English", "English (United Kingdom)", "Arabic (Saudi Arabia)"]
418
394
  },
419
395
  "bcp47": {
420
- "type": "string",
396
+ "$ref": "#/$defs/LanguageTag",
421
397
  "description": "BCP-47 language tag used for locale-aware rendering, proofing, and accessibility metadata. Use 'en-GB' for UK English; 'en-UK' is not a valid BCP-47 region form.",
422
398
  "examples": ["en", "en-US", "en-GB", "ar-SA", "zh-Hans"]
423
399
  },
424
400
  "ooxmlLang": {
425
401
  "type": "string",
426
- "description": "Curated culture tag for OOXML text-run language attributes (a:rPr/@lang, a:endParaRPr/@lang), in the language-[Script-]REGION form Office recognizes (e.g. 'ja-JP', 'ar-SA', 'ms-MY', 'nb-NO', 'fil-PH', 'zh-CN'). Engines emit it instead of 'bcp47' when the document names the language by catalog id or by a tag without a region; a region-bearing tag written by the author is emitted as written. Curated rather than inferred so output does not depend on the runtime's locale data.",
402
+ "description": "Culture tag for OOXML text-run language attributes (a:rPr/@lang, a:endParaRPr/@lang), in the language-[Script-]REGION form Office recognizes (e.g. 'ja-JP', 'ar-SA', 'ms-MY', 'nb-NO', 'fil-PH', 'zh-CN'). Without it, engines emit the curated tag of their language vocabulary (spec/reference/engine-vocabularies.json) for a tag without a region, and a region-bearing tag as written. Curated rather than inferred so output does not depend on the runtime's locale data.",
427
403
  "examples": ["en-US", "ja-JP", "ar-SA", "ms-MY", "nb-NO", "zh-CN"]
428
404
  },
429
405
  "code": {
@@ -434,20 +410,20 @@
434
410
  "direction": {
435
411
  "type": "string",
436
412
  "enum": ["ltr", "rtl"],
437
- "description": "Base text direction for the language. When omitted, engines derive it from the script: Arabic (Arab), Hebrew (Hebr), Syriac (Syrc), Thaana (Thaa), N'Ko (Nkoo), Adlam (Adlm), Samaritan (Samr), Mandaic (Mand) and Hanifi Rohingya (Rohg) are right-to-left; every other script is left-to-right. Bundled language records state it explicitly."
413
+ "description": "Base text direction for the language. When omitted, engines derive it from the script: Arabic (Arab), Hebrew (Hebr), Syriac (Syrc), Thaana (Thaa), N'Ko (Nkoo), Adlam (Adlm), Samaritan (Samr), Mandaic (Mand) and Hanifi Rohingya (Rohg) are right-to-left; every other script is left-to-right. The engine language vocabulary (spec/reference/engine-vocabularies.json) states it for the tags it knows."
438
414
  },
439
415
  "script": {
440
416
  "type": "string",
441
- "description": "ISO 15924 script code of the language's writing system. The script selects the OOXML font slot the language's text uses: East Asian scripts (Hans, Hant, Hani, Jpan, Kore, Hang, Hira, Kana, Bopo, Yiii) use the eastAsian slot; complex scripts (for example Arab, Hebr, Syrc, Thaa, Deva, Beng, Guru, Gujr, Orya, Taml, Telu, Knda, Mlym, Sinh, Thai, Laoo, Tibt, Mymr, Khmr, Mong) use the complexScript slot; every other script (Latn, Cyrl, Grek, Armn, Geor, Ethi, ...) uses the latin slot. When omitted, engines infer it from the BCP-47 tag. Bundled language records state it explicitly. See docs/programs/font-fidelity-everywhere/script-font-model.md.",
417
+ "description": "ISO 15924 script code of the language's writing system. The script selects the OOXML font slot the language's text uses: East Asian scripts (Hans, Hant, Hani, Jpan, Kore, Hang, Hira, Kana, Bopo, Yiii) use the eastAsian slot; complex scripts (for example Arab, Hebr, Syrc, Thaa, Deva, Beng, Guru, Gujr, Orya, Taml, Telu, Knda, Mlym, Sinh, Thai, Laoo, Tibt, Mymr, Khmr, Mong) use the complexScript slot; every other script (Latn, Cyrl, Grek, Armn, Geor, Ethi, ...) uses the latin slot. When omitted, engines infer it from the BCP-47 tag. The engine language vocabulary (spec/reference/engine-vocabularies.json) states it for the tags it knows. See docs/programs/font-fidelity-everywhere/script-font-model.md.",
442
418
  "examples": ["Latn", "Cyrl", "Grek", "Arab", "Hebr", "Jpan", "Kore", "Hans", "Hant", "Deva", "Thai"]
443
419
  },
444
420
  "fontScheme": {
445
- "type": "string",
446
- "description": "Default font-scheme id for this language when targeting PowerPoint output. Resolves against catalogs.fontSchemes the same way design.fontScheme or design.fontScheme.id does. Its major/minor families fill the language's script slot (eastAsian or complexScript, chosen by 'script') unless the effective design font scheme sets that slot itself; the latin slot always follows the design font scheme."
421
+ "$ref": "#/$defs/CatalogReference",
422
+ "description": "Font-scheme reference (a bare id or 'name:id') for this language's script slot when targeting PowerPoint output. Its major/minor families fill the language's script slot (eastAsian or complexScript, chosen by 'script') unless the effective design font scheme sets that slot itself; the latin slot always follows the design font scheme. Without it, engines use the default script fonts of their language vocabulary."
447
423
  },
448
424
  "googleFontScheme": {
449
- "type": "string",
450
- "description": "Default font-scheme id for this language when targeting Google Slides output. Resolves against catalogs.fontSchemes the same way design.fontScheme or design.fontScheme.id does. Used in place of 'fontScheme' when resolving script fonts for Google Slides output."
425
+ "$ref": "#/$defs/CatalogReference",
426
+ "description": "Font-scheme reference (a bare id or 'name:id') used in place of 'fontScheme' when resolving script fonts for Google Slides output."
451
427
  },
452
428
  "summary": {
453
429
  "type": "string",
@@ -466,16 +442,15 @@
466
442
  },
467
443
  "Tone": {
468
444
  "type": "object",
469
- "description": "Inline tone metadata for the presentation. Use 'id' to reference a tones catalog record and override selected fields, or use 'name' for a custom inline tone.",
445
+ "description": "Inline tone metadata for the presentation. Use 'id' to reference a tones record (a bare id or 'name:id') and override selected fields, or use 'name' for a custom inline tone.",
470
446
  "anyOf": [
471
447
  { "required": ["id"] },
472
448
  { "required": ["name"] }
473
449
  ],
474
450
  "properties": {
475
451
  "id": {
476
- "type": "string",
477
- "pattern": "^[a-z][a-z0-9-]*$",
478
- "description": "Optional tones catalog id to resolve before applying inline overrides.",
452
+ "$ref": "#/$defs/CatalogReference",
453
+ "description": "Optional tones reference (a bare id or 'name:id') resolved before applying the inline overrides.",
479
454
  "examples": ["formal", "casual", "technical", "persuasive"]
480
455
  },
481
456
  "name": {
@@ -508,7 +483,7 @@
508
483
  "recommendedNarratives": {
509
484
  "type": "array",
510
485
  "items": { "type": "string" },
511
- "description": "Soft cross-link: narrative-catalog ids this tone pairs well with."
486
+ "description": "Soft cross-link: narrative ids this tone pairs well with, for picker UIs. Never resolved, embedded or validated as references."
512
487
  },
513
488
  "tags": {
514
489
  "type": "array",
@@ -642,7 +617,7 @@
642
617
  },
643
618
  "Socials": {
644
619
  "type": "object",
645
- "description": "Social media handles or URLs, keyed by platform id from the 'socialPlatforms' catalog. Each value is a string — either a full URL or a platform handle (e.g., '@acme'). The catalog record for each platform carries the URL pattern and handle prefix that engines use to render and link the profile URL, plus brand color and themed icons as catalog metadata for authoring UIs (engines render the profile URL, not icons or brand colors).\n\nKeys resolve to the 'id' of a 'socialPlatforms' catalog record. Resolution order: inline catalogs.socialPlatforms.records[] → catalogs.socialPlatforms.source → default catalog at https://www.pptx.gallery/social-platforms. Unknown platform keys render with engine fallbacks (the raw value as text). Used both for organization and speaker records.",
620
+ "description": "Social media handles or URLs, keyed by platform. The keys are an engine vocabulary validated directly (no catalog lookup): engines link a handle with the platform's URL pattern and handle prefix (spec/reference/engine-vocabularies.json). Each value is a string, either a full URL or a platform handle (e.g., '@acme'). Brand colours and icons are catalog display metadata for authoring UIs; engines render the profile URL, not icons or brand colours. Used both for organization and speaker records.",
646
621
  "additionalProperties": {
647
622
  "type": "string",
648
623
  "description": "Handle or URL for the platform identified by the property key."
@@ -660,8 +635,8 @@
660
635
  }
661
636
  ],
662
637
  "propertyNames": {
663
- "pattern": "^[a-z][a-z0-9-]*$",
664
- "description": "Platform id (lowercase kebab-case). Common ids include 'linkedin', 'x', 'github', 'youtube', 'instagram', 'facebook', 'tiktok', 'threads', 'mastodon', 'bluesky'."
638
+ "enum": ["linkedin", "x", "github", "youtube", "instagram", "facebook", "tiktok", "threads", "mastodon", "bluesky"],
639
+ "description": "Platform key, one of the engine's social platforms."
665
640
  }
666
641
  },
667
642
  "Design": {
@@ -669,29 +644,16 @@
669
644
  "description": "Visual design system applied to the presentation; individual slides may override fields via Slide.design.",
670
645
  "properties": {
671
646
  "theme": {
672
- "oneOf": [
673
- { "type": "string" },
674
- { "$ref": "#/$defs/Theme" }
675
- ],
676
- "description": "Theme for the deck. Accepts two forms:\n- String shorthand: 'design.theme = \"minimal\"'. Bare id, HTTPS URL, or 'pkg:' reference resolved as the 'id' of a 'themes' catalog record.\n- Object form: a Theme with an optional 'id' base reference plus theme-level overrides.\n\nInline overrides on design.colorScheme / design.fontScheme / design.background / design.dimensions take precedence over the resolved theme.\n\nResolution order: inline catalogs.themes.records[] -> catalogs.themes.source -> default catalog at https://www.pptx.gallery/themes.",
677
- "examples": [
678
- "minimal",
679
- "classic",
680
- "dark",
681
- "bold",
682
- "corporate-minimal",
683
- "ocean-depth",
684
- "https://acme.com/decks/themes/acme-brand.json",
685
- "pkg:@acme/decks/themes/acme-brand",
686
- { "id": "minimal", "background": "dark1", "dimensions": "widescreen" }
687
- ]
647
+ "$ref": "#/$defs/CatalogReference",
648
+ "description": "Theme for the deck: a themes reference, a bare id ('minimal') or 'name:id' ('acme:brand'). The theme supplies the default colour scheme, font scheme, background and dimensions; design.colorScheme, design.fontScheme, design.background and design.dimensions override it field by field. A reference that resolves nowhere is the warning opf/unresolved-reference and engines use the engine default theme.",
649
+ "examples": ["minimal", "classic", "dark", "bold", "acme:brand"]
688
650
  },
689
651
  "colorScheme": {
690
652
  "oneOf": [
691
653
  { "type": "string" },
692
654
  { "$ref": "#/$defs/ColorScheme" }
693
655
  ],
694
- "description": "Color scheme for the presentation. Accepts two forms:\n- String shorthand: 'design.colorScheme = \"cool-horizon\"'. Bare id, HTTPS URL, or 'pkg:' reference resolved as the 'id' of a 'colorSchemes' catalog record.\n- Object form: a ColorScheme with an optional 'id' base reference plus slot/role overrides.\n\nResolution order: inline catalogs.colorSchemes.records[] -> catalogs.colorSchemes.source -> default catalog at https://www.pptx.gallery/color-schemes.",
656
+ "description": "Color scheme for the presentation. Accepts two forms:\n- A colorSchemes reference: a bare id ('cool-horizon') or 'name:id' ('acme:ocean').\n- Object form: a ColorScheme with an optional 'id' reference as the base plus slot/role overrides. Without 'id', the overrides apply on top of the engine default colour scheme.\n\nWithout either, the theme's colorScheme applies, then the engine default colour scheme.",
695
657
  "examples": [
696
658
  "cool-horizon",
697
659
  "boost",
@@ -704,7 +666,7 @@
704
666
  { "type": "string" },
705
667
  { "$ref": "#/$defs/FontScheme" }
706
668
  ],
707
- "description": "Font scheme for heading, body, accent, and code text. Accepts two forms:\n- String shorthand: 'design.fontScheme = \"aptos\"'. Bare id, HTTPS URL, or 'pkg:' reference resolved as the 'id' of a 'fontSchemes' catalog record.\n- Object form: a FontScheme with an optional 'id' base reference plus pair/role overrides.\n\nResolution order: inline catalogs.fontSchemes.records[] -> catalogs.fontSchemes.source -> default catalog at https://www.pptx.gallery/font-schemes.",
669
+ "description": "Font scheme for heading, body, accent, and code text. Accepts two forms:\n- A fontSchemes reference: a bare id ('aptos') or 'name:id' ('acme:inter').\n- Object form: a FontScheme with an optional 'id' reference as the base plus pair/role overrides.\n\nWithout either, the theme's fontScheme applies, then the engine default font scheme.",
708
670
  "examples": [
709
671
  "aptos",
710
672
  "tenorite",
@@ -724,7 +686,7 @@
724
686
  { "$ref": "#/$defs/BackgroundShortcut" },
725
687
  { "$ref": "#/$defs/Background" }
726
688
  ],
727
- "description": "Default slide background applied across the deck unless overridden on a slide. String shorthand accepts theme slots ('light1', 'light2', 'dark1', 'dark2') or hex colors; object forms support theme, solid, gradient, image, or pattern fills.",
689
+ "description": "Default slide background applied across the deck unless overridden on a slide (slides.N.design.background); the resolved theme's background is the fallback. A background is the only canvas fill and never moves content. String shorthand accepts theme slots ('light1', 'light2', 'dark1', 'dark2'), hex colors, or an image source starting with 'asset:', 'https://', 'data:', './' or '../' (a cover image); object forms support theme, solid, gradient, image, or pattern fills.",
728
690
  "examples": ["dark1", "#ffff00", { "type": "theme", "slot": "light1" }]
729
691
  },
730
692
  "logo": {
@@ -780,108 +742,6 @@
780
742
  "type": "boolean",
781
743
  "description": "Whether body/content regions are rendered inside a visible card or surface. Effective value: the slide's design, then the deck's design, then the layout record's design.contentBox, then the engine default."
782
744
  },
783
- "slideImage": {
784
- "oneOf": [
785
- { "$ref": "#/$defs/Asset" },
786
- {
787
- "type": "object",
788
- "additionalProperties": false,
789
- "required": ["position"],
790
- "properties": {
791
- "src": {
792
- "type": "string",
793
- "description": "Source for the slide-level image. When omitted in a design override, the object only configures how a slide-level image should be placed when one is supplied by a content payload, asset, or renderer convention."
794
- },
795
- "position": {
796
- "type": "string",
797
- "enum": ["background", "top", "bottom", "left", "right"],
798
- "description": "Where the slide-level image sits relative to the content. 'background' is a full-bleed image behind the content. The other positions give the image a band along that edge (see size) and compose headings and content in the rest of the slide."
799
- },
800
- "alt": {
801
- "type": "string",
802
- "description": "Alternative text for the slide-level image. Overrides the alt text of a referenced asset."
803
- },
804
- "fill": {
805
- "type": "string",
806
- "enum": ["crop", "fit"],
807
- "description": "How the image fills its frame: 'crop' covers the frame from the center; 'fit' shows the whole image centered inside it. Overrides design.imageFill for this image. Default: design.imageFill, else 'crop'."
808
- },
809
- "size": {
810
- "type": "number",
811
- "minimum": 0.1,
812
- "maximum": 0.9,
813
- "description": "Share of the slide width (left/right) or height (top/bottom) given to the image band. Ignored for 'background'. Default 0.5."
814
- },
815
- "inset": {
816
- "type": "boolean",
817
- "description": "Place the frame inside the slide padding instead of edge to edge, like a card. Default false."
818
- },
819
- "aspectRatio": {
820
- "type": "number",
821
- "exclusiveMinimum": 0,
822
- "maximum": 10,
823
- "description": "Width-to-height ratio of the frame. The frame becomes the largest centered box with this ratio inside the band or slide, for example 2.39 for a cinematic letterbox or 0.5 for a phone-shaped frame. 'circle' always uses 1."
824
- },
825
- "shape": {
826
- "type": "string",
827
- "enum": ["rectangle", "rounded", "circle", "hexagon"],
828
- "description": "Mask applied to the frame, exported as the picture's native preset geometry (rect, roundRect, ellipse, hexagon). 'circle' makes the frame square. Default 'rectangle'."
829
- },
830
- "cornerRadius": {
831
- "type": "number",
832
- "minimum": 0,
833
- "maximum": 0.5,
834
- "description": "Corner radius for shape 'rounded' as a fraction of the frame's shorter side. Default 0.16667, PowerPoint's roundRect default."
835
- },
836
- "border": {
837
- "type": "object",
838
- "additionalProperties": false,
839
- "required": ["color", "width"],
840
- "properties": {
841
- "color": { "$ref": "#/$defs/ColorRef", "description": "Line color: a hex color, a color-scheme slot or role name, or a 'var:<id>' variable reference." },
842
- "width": { "type": "number", "minimum": 0, "maximum": 64, "description": "Line width in reference pixels at a 720-pixel short edge, centered on the frame outline like a native picture line. 0 removes the line." }
843
- },
844
- "description": "Solid line along the frame's shape. A thick dark border on a rounded portrait frame gives a device bezel."
845
- },
846
- "opacity": {
847
- "type": "number",
848
- "minimum": 0,
849
- "maximum": 1,
850
- "description": "Image opacity from 0 to 1, exported as a native alphaModFix. The border and overlay keep their own opacity. Default 1."
851
- },
852
- "recolor": {
853
- "oneOf": [
854
- { "type": "string", "const": "grayscale", "description": "Replace each pixel with its luminance, exported as native a:grayscl." },
855
- {
856
- "type": "object",
857
- "additionalProperties": false,
858
- "required": ["dark", "light"],
859
- "properties": {
860
- "dark": { "$ref": "#/$defs/ColorRef", "description": "Color at luminance 0." },
861
- "light": { "$ref": "#/$defs/ColorRef", "description": "Color at luminance 1." }
862
- },
863
- "description": "Duotone: map each pixel's luminance linearly from dark to light, exported as native a:duotone."
864
- }
865
- ],
866
- "description": "Color treatment for the image pixels. Luminance uses Rec. 601 weights (0.299, 0.587, 0.114) on sRGB values."
867
- },
868
- "overlay": {
869
- "type": "object",
870
- "additionalProperties": false,
871
- "required": ["color", "opacity"],
872
- "properties": {
873
- "color": { "$ref": "#/$defs/ColorRef", "description": "Overlay fill color." },
874
- "opacity": { "type": "number", "minimum": 0, "maximum": 1, "description": "Overlay fill opacity." },
875
- "edge": { "type": "string", "enum": ["top", "bottom", "left", "right"], "description": "Cover only a band along this edge of the frame, for example a caption strip. Rectangle frames only; other shapes report unsupported-image-treatment and draw no overlay. Omit to cover the whole frame." },
876
- "size": { "type": "number", "minimum": 0.05, "maximum": 1, "description": "Band share of the frame for an edge overlay. Default 0.3." }
877
- },
878
- "description": "Solid scrim drawn over the image in the frame's shape, beneath headings and content, for example to keep overlaid text readable. Exported as a native shape above the picture."
879
- }
880
- }
881
- }
882
- ],
883
- "description": "Optional slide-level image, separate from content images. It applies to a slide that sets its own design.slideImage, and to slides whose layout record sets design.slideImage or whose root image is the same source as a deck-level value. A root image with the same source becomes the slide image instead of a content item. Blur, shadows, soft edges, background removal and device artwork are not part of the treatment vocabulary; see docs/image-treatments.md."
884
- },
885
745
  "contentDirection": {
886
746
  "type": "string",
887
747
  "enum": ["horizontal", "vertical"],
@@ -892,10 +752,10 @@
892
752
  "enum": ["none", "top", "bottom", "left", "right"],
893
753
  "description": "Where the primary chart sits relative to supporting content. Effective value: slide design, then deck design, then the layout record's design.chartPrimary. When the slide has no promoted regions and no composition.mode of its own, and its root nodes mix at least one chart with other content, the first chart becomes a primary track and the other nodes form one synthetic sub-grid: 'left'/'right' is a two-track row and 'top'/'bottom' a two-track column, weighted 3:2 in favor of the chart; explicit root columns and weights are ignored while it applies. 'none' (the default) keeps the ordinary automatic grid with equal weight."
894
754
  },
895
- "imageFill": {
755
+ "imageFit": {
896
756
  "type": "string",
897
- "enum": ["crop", "fit"],
898
- "description": "How images fill their allocated region: crop covers the region, fit shows the whole image. Effective value: the slide's design, then the deck's design, then the layout record's design.imageFill, then the engine default."
757
+ "enum": ["cover", "contain", "stretch"],
758
+ "description": "Default fit of image blocks (and Slide.image) that set no fit of their own: 'cover' fills the frame and crops what overflows around the block's focus, 'contain' shows the whole picture centered in the frame, 'stretch' scales it to the frame exactly. Effective value: the slide's design, then the deck's design, then the layout record's design.imageFit, then 'cover'. Backgrounds set their own fit."
899
759
  },
900
760
  "listBullet": {
901
761
  "type": "string",
@@ -904,75 +764,14 @@
904
764
  }
905
765
  }
906
766
  },
907
- "Theme": {
908
- "type": "object",
909
- "description": "Theme bundle used by the design system. In design.theme, 'id' resolves a themes catalog record as the base; any sibling fields override the resolved theme. The string shorthand on design.theme is equivalent to setting only 'id'.",
910
- "properties": {
911
- "id": {
912
- "type": "string",
913
- "description": "Theme reference. Resolves to the 'id' of a 'themes' catalog record. Accepts a bare id (lowercase kebab-case, e.g. 'minimal'), an HTTPS URL pointing at a record file, or a 'pkg:' reference. Field overrides on the surrounding Theme object take precedence over the resolved theme.\n\nResolution order: inline catalogs.themes.records[] -> catalogs.themes.source -> default catalog at https://www.pptx.gallery/themes.",
914
- "examples": ["minimal", "classic", "dark", "bold", "https://acme.com/decks/themes/acme-brand.json", "pkg:@acme/decks/themes/acme-brand"]
915
- },
916
- "name": {
917
- "type": "string",
918
- "description": "Human-readable theme name shown in pickers.",
919
- "examples": ["Minimal", "Classic", "Dark", "Bold"]
920
- },
921
- "summary": {
922
- "type": "string",
923
- "description": "One-sentence positioning of the theme - when to reach for it."
924
- },
925
- "description": {
926
- "type": "string",
927
- "description": "Longer prose describing what the theme looks and feels like and the kinds of decks it suits."
928
- },
929
- "colorScheme": {
930
- "oneOf": [
931
- { "type": "string" },
932
- { "$ref": "#/$defs/ColorScheme" }
933
- ],
934
- "description": "Default color scheme for this theme. A string resolves against catalogs.colorSchemes; an object may provide an 'id' base reference plus overrides.",
935
- "examples": ["cool-horizon", { "id": "cool-horizon", "accent1": "#FF6F61" }]
936
- },
937
- "fontScheme": {
938
- "oneOf": [
939
- { "type": "string" },
940
- { "$ref": "#/$defs/FontScheme" }
941
- ],
942
- "description": "Default font scheme for this theme. A string resolves against catalogs.fontSchemes; an object may provide an 'id' base reference plus overrides.",
943
- "examples": ["aptos", { "id": "aptos", "heading": "Inter" }]
944
- },
945
- "background": {
946
- "oneOf": [
947
- { "$ref": "#/$defs/BackgroundShortcut" },
948
- { "$ref": "#/$defs/Background" }
949
- ],
950
- "description": "Default background for this theme. String shorthand accepts theme slots ('light1', 'light2', 'dark1', 'dark2') or hex colors.",
951
- "examples": ["dark1", "#ffff00", { "type": "theme", "slot": "dark2" }]
952
- },
953
- "dimensions": {
954
- "oneOf": [
955
- { "$ref": "#/$defs/DimensionPreset" },
956
- { "$ref": "#/$defs/Dimensions" }
957
- ],
958
- "description": "Default slide size for this theme. A string preset is equivalent to { preset: value }.",
959
- "examples": ["widescreen", { "preset": "16:9" }]
960
- },
961
- "tags": {
962
- "type": "array",
963
- "items": { "type": "string" },
964
- "description": "Free-form labels for filtering and search."
965
- }
966
- }
967
- },
968
767
  "ColorScheme": {
969
768
  "type": "object",
970
- "description": "Color palette used by the design system. Every slot and role is a hex color ('#RGB', '#RRGGBB' or '#RRGGBBAA'); a color-scheme name or a 'var:<id>' reference is not valid here, because those resolve through the scheme. The slot fields (accent1-accent6, dark1, dark2, light1, light2, hyperlink, followedHyperlink) mirror color-scheme.schema.json (https://openpresentation.org/schema/opf-color-scheme/v1) so library records and inline OPF overrides are interchangeable on those fields.\n\nTwo parallel models are supported and may be mixed:\n- OOXML slots - the 12-slot PowerPoint theme model that round-trips directly to OOXML. Use these for full control over the palette as PowerPoint sees it.\n- Abstract roles (primary, secondary, accent, background, surface, text, textSecondary) - OPF-specific semantic aliases the engine maps onto the OOXML slots. Convenient for inline overrides without thinking in slot numbers; not part of the catalog record schema.\n\nIn design.colorScheme, 'id' resolves a colorSchemes catalog record as the base; slot and role overrides on the same object take precedence over the resolved scheme. The string shorthand on design.colorScheme is equivalent to setting only 'id'.",
769
+ "description": "Color palette used by the design system. Every slot and role is a hex color ('#RGB', '#RRGGBB' or '#RRGGBBAA'); a color-scheme name or a 'var:<id>' reference is not valid here, because those resolve through the scheme. The slot fields (accent1-accent6, dark1, dark2, light1, light2, hyperlink, followedHyperlink) mirror color-scheme.schema.json (https://openpresentation.org/schema/opf-color-scheme/v1) so library records and inline OPF overrides are interchangeable on those fields.\n\nTwo parallel models are supported and may be mixed:\n- OOXML slots - the 12-slot PowerPoint theme model that round-trips directly to OOXML. Use these for full control over the palette as PowerPoint sees it.\n- Abstract roles (primary, secondary, accent, background, surface, text, textSecondary) - OPF-specific semantic aliases the engine maps onto the OOXML slots. Convenient for inline overrides without thinking in slot numbers; not part of the catalog record schema.\n\nIn design.colorScheme, 'id' resolves a colorSchemes record as the base; slot and role overrides on the same object take precedence over the resolved scheme. The string form of design.colorScheme is equivalent to setting only 'id'.",
971
770
  "properties": {
972
771
  "id": {
973
- "type": "string",
974
- "description": "Color scheme reference. Resolves to the 'id' of a 'colorSchemes' catalog record. Accepts a bare id (lowercase kebab-case, e.g. 'cool-horizon'), an HTTPS URL pointing at a record file, or a 'pkg:' reference. Slot and role overrides on the surrounding ColorScheme object take precedence over the resolved scheme.\n\nResolution order: inline catalogs.colorSchemes.records[] -> catalogs.colorSchemes.source -> default catalog at https://www.pptx.gallery/color-schemes.",
975
- "examples": ["cool-horizon", "boost", "burnt-orange", "ocean-depth", "corporate-blue", "https://acme.com/decks/color-schemes/acme.json", "pkg:@acme/decks/color-schemes/acme"]
772
+ "$ref": "#/$defs/CatalogReference",
773
+ "description": "Colour-scheme reference (a bare id or 'name:id') resolved as the base; slot and role overrides on the surrounding ColorScheme object take precedence over the resolved scheme.",
774
+ "examples": ["cool-horizon", "boost", "burnt-orange", "ocean-depth", "corporate-blue"]
976
775
  },
977
776
  "accent1": {
978
777
  "$ref": "#/$defs/HexColor",
@@ -1073,12 +872,12 @@
1073
872
  },
1074
873
  "FontScheme": {
1075
874
  "type": "object",
1076
- "description": "Typography selections used by the design system. The pair fields (major, minor) and refinement fields (type, app, languageFamily) mirror font-scheme.schema.json (https://openpresentation.org/schema/opf-font-scheme/v1) so library records and inline OPF overrides are interchangeable on those fields.\n\nTwo parallel models are supported and may be mixed:\n- OOXML pairs (major, minor) - heading and body family names that round-trip directly to PowerPoint majorFont/minorFont entries.\n- Abstract roles (heading, body, accent, code) - OPF-specific font family names the engine maps onto the OOXML pair when serializing. Convenient for inline overrides and for adding accent/code roles that don't have a direct OOXML slot. Catalog records may also carry 'code' (for example the consolas and courier-new records); heading, body and accent are not part of the catalog record schema. A role is a family name only: weight, style and tracking come from the text styles, and PowerPoint has no numeric weight.\n\nIn design.fontScheme, 'id' resolves a fontSchemes catalog record as the base; pair and role overrides on the same object take precedence over the resolved scheme. The string shorthand on design.fontScheme is equivalent to setting only 'id'.",
875
+ "description": "Typography selections used by the design system. The pair fields (major, minor) and refinement fields (type, app, languageFamily) mirror font-scheme.schema.json (https://openpresentation.org/schema/opf-font-scheme/v1) so library records and inline OPF overrides are interchangeable on those fields.\n\nTwo parallel models are supported and may be mixed:\n- OOXML pairs (major, minor) - heading and body family names that round-trip directly to PowerPoint majorFont/minorFont entries.\n- Abstract roles (heading, body, accent, code) - OPF-specific font family names the engine maps onto the OOXML pair when serializing. Convenient for inline overrides and for adding accent/code roles that don't have a direct OOXML slot. Catalog records may also carry 'code' (for example the consolas and courier-new records); heading, body and accent are not part of the catalog record schema. A role is a family name only: weight, style and tracking come from the text styles, and PowerPoint has no numeric weight.\n\nIn design.fontScheme, 'id' resolves a fontSchemes record as the base; pair and role overrides on the same object take precedence over the resolved scheme. The string form of design.fontScheme is equivalent to setting only 'id'.",
1077
876
  "properties": {
1078
877
  "id": {
1079
- "type": "string",
1080
- "description": "Font scheme reference. Resolves to the 'id' of a 'fontSchemes' catalog record. Accepts a bare id (lowercase kebab-case, e.g. 'aptos'), an HTTPS URL pointing at a record file, or a 'pkg:' reference. Field overrides on the surrounding FontScheme object take precedence over the resolved scheme.\n\nResolution order: inline catalogs.fontSchemes.records[] -> catalogs.fontSchemes.source -> default catalog at https://www.pptx.gallery/font-schemes.",
1081
- "examples": ["aptos", "tenorite", "seaford", "noto-sans", "modern-sans", "classic-serif", "https://acme.com/decks/font-schemes/acme.json", "pkg:@acme/decks/font-schemes/acme"]
878
+ "$ref": "#/$defs/CatalogReference",
879
+ "description": "Font-scheme reference (a bare id or 'name:id') resolved as the base; field overrides on the surrounding FontScheme object take precedence over the resolved scheme.",
880
+ "examples": ["aptos", "tenorite", "seaford", "noto-sans", "modern-sans", "classic-serif"]
1082
881
  },
1083
882
  "major": {
1084
883
  "type": "string",
@@ -1155,7 +954,7 @@
1155
954
  },
1156
955
  "code": {
1157
956
  "type": "string",
1158
- "description": "Abstract role: monospaced font family name used for code blocks and for inline code runs (TextRun.code). No direct OOXML slot. Resolution: this override, then the resolved catalog record's 'code' (for example Consolas for the consolas scheme), then the engine fallback Roboto Mono. Heading and body families are never used as the code fallback."
957
+ "description": "Abstract role: monospaced font family name used for code blocks and for inline code runs (TextRun.code). No direct OOXML slot. Resolution: this override, then the resolved font-scheme record's 'code' (for example Consolas for the consolas scheme), then the engine fallback Roboto Mono. Heading and body families are never used as the code fallback."
1159
958
  }
1160
959
  }
1161
960
  },
@@ -1616,10 +1415,17 @@
1616
1415
  "BackgroundShortcut": {
1617
1416
  "oneOf": [
1618
1417
  { "$ref": "#/$defs/ThemeBackgroundSlot" },
1619
- { "$ref": "#/$defs/HexColor" }
1418
+ { "$ref": "#/$defs/HexColor" },
1419
+ { "$ref": "#/$defs/ImageSource" }
1620
1420
  ],
1621
- "description": "String shorthand for a background. Theme slots ('light1', 'light2', 'dark1', 'dark2') are equivalent to { type: 'theme', slot: value }; hex colors are equivalent to { type: 'solid', color: value }.",
1622
- "examples": ["dark1", "light2", "#ffff00"]
1421
+ "description": "String shorthand for a background. Theme slots ('light1', 'light2', 'dark1', 'dark2') are equivalent to { type: 'theme', slot: value }; hex colors are equivalent to { type: 'solid', color: value }; an image source (starting with 'asset:', 'https://', 'data:', './' or '../') is equivalent to { type: 'image', src: value }, a cover image. Any other string is invalid.",
1422
+ "examples": ["dark1", "light2", "#ffff00", "asset:cover-photo", "./images/harbour.jpg"]
1423
+ },
1424
+ "ImageSource": {
1425
+ "type": "string",
1426
+ "pattern": "^(asset:|https://|data:|\\./|\\.\\./)",
1427
+ "description": "An image source in a string shorthand: an 'asset:<id>' reference, an HTTPS URL, a data URI, or a relative path starting with './' or '../' (resolved against the OPF file location).",
1428
+ "examples": ["asset:cover-photo", "https://cdn.acme.com/backgrounds/cover.jpg", "./images/harbour.jpg"]
1623
1429
  },
1624
1430
  "Background": {
1625
1431
  "description": "Background fill applied to slides. Theme backgrounds preserve PowerPoint's color-scheme background choice; other variants represent fixed background fills.",
@@ -1722,44 +1528,170 @@
1722
1528
  },
1723
1529
  "ImageBackground": {
1724
1530
  "type": "object",
1725
- "description": "Fixed image slide background fill.",
1726
- "required": ["type", "image"],
1531
+ "additionalProperties": false,
1532
+ "description": "Picture background: the image fills the whole canvas behind everything and never moves content (to push content aside, use an image block with placement). The string shorthand 'asset:x' (or any image source) is { type: 'image', src: 'asset:x' }, a cover image. Paint order: the colour scheme's default slide background, the picture, then the overlay, then furniture and content.",
1533
+ "required": ["type", "src"],
1727
1534
  "properties": {
1728
1535
  "type": {
1729
1536
  "type": "string",
1730
1537
  "const": "image",
1731
- "description": "Fixed image background fill."
1538
+ "description": "Picture background."
1732
1539
  },
1733
- "image": {
1734
- "type": "object",
1735
- "description": "Image fill definition.",
1736
- "required": ["src"],
1737
- "properties": {
1738
- "src": {
1739
- "type": "string",
1740
- "description": "Source for the background image.",
1741
- "examples": [
1742
- "https://cdn.acme.com/backgrounds/cover.jpg",
1743
- "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA...",
1744
- "./backgrounds/cover.jpg",
1745
- "asset:bg-cover"
1746
- ]
1747
- },
1748
- "fit": {
1749
- "type": "string",
1750
- "enum": ["cover", "contain", "tile"],
1751
- "description": "How the image fills the slide background."
1752
- }
1753
- }
1540
+ "src": {
1541
+ "type": "string",
1542
+ "description": "Source for the background image: an 'asset:<id>' reference, HTTPS URL, data URI, or a relative path resolved against the OPF file location.",
1543
+ "examples": [
1544
+ "https://cdn.acme.com/backgrounds/cover.jpg",
1545
+ "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAA...",
1546
+ "./backgrounds/cover.jpg",
1547
+ "asset:bg-cover"
1548
+ ]
1549
+ },
1550
+ "alt": {
1551
+ "type": "string",
1552
+ "description": "Alternative text. A background with alt is meaningful: PowerPoint export draws it as a full-slide picture at the back that carries the text, so screen readers see it. Without alt it is decorative and exports as the native slide background; the alt text of a referenced asset does not count, so a background is decorative unless it says otherwise."
1553
+ },
1554
+ "fit": {
1555
+ "type": "string",
1556
+ "enum": ["cover", "contain", "stretch", "tile"],
1557
+ "description": "How the picture fills the canvas: 'cover' fills it and crops what overflows around focus; 'contain' shows the whole picture centered over the colour scheme's default background; 'stretch' scales it to the canvas exactly; 'tile' repeats it at its own size from the top-left corner. Default 'cover'."
1558
+ },
1559
+ "focus": {
1560
+ "$ref": "#/$defs/ImageFocus",
1561
+ "description": "Point of the picture to keep in view when 'cover' crops it. Ignored by the other fits."
1754
1562
  },
1755
1563
  "opacity": {
1756
1564
  "type": "number",
1757
1565
  "minimum": 0,
1758
1566
  "maximum": 1,
1759
- "description": "Background opacity from 0 (fully transparent) to 1 (fully opaque)."
1567
+ "description": "Picture opacity from 0 (fully transparent) to 1 (fully opaque); the overlay keeps its own opacity. Default 1."
1568
+ },
1569
+ "recolor": {
1570
+ "$ref": "#/$defs/ImageRecolor",
1571
+ "description": "Grayscale or duotone treatment of the picture's pixels, as on an image block: recolor and opacity apply to the pixels, then the overlay is drawn above."
1572
+ },
1573
+ "overlay": {
1574
+ "$ref": "#/$defs/Overlay",
1575
+ "description": "Scrim over the whole picture or a band along one edge (edge, size), beneath furniture and content, for example to keep a title readable over a busy photo."
1576
+ }
1577
+ },
1578
+ "examples": [
1579
+ { "type": "image", "src": "asset:cover-photo" },
1580
+ { "type": "image", "src": "./images/harbour.jpg", "alt": "Container ships at dawn", "focus": { "x": 0.5, "y": 0.7 }, "overlay": { "color": "dark1", "opacity": 0.4 } }
1581
+ ]
1582
+ },
1583
+ "ImageFocus": {
1584
+ "type": "object",
1585
+ "additionalProperties": false,
1586
+ "required": ["x", "y"],
1587
+ "description": "A point of a picture as fractions of its width and height, from the top-left corner. A cover fit centers this point in the frame as far as the picture still covers the frame, so it always stays in view: { x: 0.5, y: 0.5 } (the default) is a center crop, { x: 0, y: 0 } keeps the top-left corner.",
1588
+ "properties": {
1589
+ "x": { "type": "number", "minimum": 0, "maximum": 1, "description": "Horizontal position, 0 (left edge) to 1 (right edge)." },
1590
+ "y": { "type": "number", "minimum": 0, "maximum": 1, "description": "Vertical position, 0 (top edge) to 1 (bottom edge)." }
1591
+ },
1592
+ "examples": [{ "x": 0.5, "y": 0.7 }]
1593
+ },
1594
+ "Overlay": {
1595
+ "type": "object",
1596
+ "additionalProperties": false,
1597
+ "required": ["color", "opacity"],
1598
+ "description": "Solid scrim over a picture: the whole frame in the frame's shape, or a band along one edge. Shared by image backgrounds and image blocks. Drawn directly above its picture and beneath headings and content; PowerPoint export writes one native shape above the picture.",
1599
+ "properties": {
1600
+ "color": {
1601
+ "$ref": "#/$defs/ColorRef",
1602
+ "description": "Overlay fill color: a hex color (eight-digit hex keeps its alpha), a color-scheme slot or role name, or a 'var:<id>' variable reference."
1603
+ },
1604
+ "opacity": {
1605
+ "type": "number",
1606
+ "minimum": 0,
1607
+ "maximum": 1,
1608
+ "description": "Overlay fill opacity."
1609
+ },
1610
+ "edge": {
1611
+ "type": "string",
1612
+ "enum": ["top", "bottom", "left", "right"],
1613
+ "description": "Cover only a band along this edge of the frame, for example a caption strip. Backgrounds and rectangle image frames only; on another shape the overlay is not drawn and composition reports unsupported-image-treatment. Omit to cover the whole frame. In a right-to-left deck 'left' and 'right' are the start and end sides."
1614
+ },
1615
+ "size": {
1616
+ "type": "number",
1617
+ "minimum": 0.05,
1618
+ "maximum": 1,
1619
+ "description": "Band share of the frame for an edge overlay. Default 0.3. Ignored without edge."
1620
+ }
1621
+ },
1622
+ "examples": [
1623
+ { "color": "dark1", "opacity": 0.4 },
1624
+ { "color": "#000000", "opacity": 0.75, "edge": "bottom", "size": 0.25 }
1625
+ ]
1626
+ },
1627
+ "ImagePlacement": {
1628
+ "type": "object",
1629
+ "additionalProperties": false,
1630
+ "required": ["edge"],
1631
+ "description": "Bleeds an image block to one edge of the slide: the image takes a band along that edge, edge to edge, and the headings and other content compose in the rest of the slide at the normal padding. Only top-level blocks (slides.N.blocks.I) can be placed, at most one per edge; a layout's image placeholder may carry the same placement for the slide's image. Bands are taken in block order, each spanning the free area left by earlier ones. Placement is the only mechanism that moves content aside; a background never does. A slide whose only body is placed images is composed like a cover: its headings center in the free area. In a right-to-left deck 'left' is the start side, drawn at the right.",
1632
+ "properties": {
1633
+ "edge": {
1634
+ "type": "string",
1635
+ "enum": ["left", "right", "top", "bottom"],
1636
+ "description": "The slide edge the image bleeds to."
1637
+ },
1638
+ "size": {
1639
+ "type": "number",
1640
+ "minimum": 0.1,
1641
+ "maximum": 0.9,
1642
+ "description": "Share of the slide width (left, right) or height (top, bottom) given to the band. Default 0.5."
1643
+ },
1644
+ "inset": {
1645
+ "type": "boolean",
1646
+ "description": "Draw the frame inside the slide padding on every side of the band, like a card, instead of edge to edge. Default false."
1647
+ }
1648
+ },
1649
+ "examples": [{ "edge": "left", "size": 0.45 }, { "edge": "right", "size": 0.4, "inset": true }]
1650
+ },
1651
+ "ImageBorder": {
1652
+ "type": "object",
1653
+ "additionalProperties": false,
1654
+ "required": ["color", "width"],
1655
+ "description": "Solid line along the image frame's shape, centered on the outline with a miter join, like a native picture line. A thick dark border on a rounded portrait frame gives a device bezel.",
1656
+ "properties": {
1657
+ "color": {
1658
+ "$ref": "#/$defs/ColorRef",
1659
+ "description": "Line color: a hex color, a color-scheme slot or role name, or a 'var:<id>' variable reference."
1660
+ },
1661
+ "width": {
1662
+ "type": "number",
1663
+ "minimum": 0,
1664
+ "maximum": 64,
1665
+ "description": "Line width in reference pixels at a 720-pixel short edge. 0 removes the line."
1760
1666
  }
1761
1667
  }
1762
1668
  },
1669
+ "ImageRecolor": {
1670
+ "oneOf": [
1671
+ {
1672
+ "type": "string",
1673
+ "const": "grayscale",
1674
+ "description": "Replace each pixel with its luminance, exported as native a:grayscl."
1675
+ },
1676
+ {
1677
+ "type": "object",
1678
+ "additionalProperties": false,
1679
+ "required": ["dark", "light"],
1680
+ "properties": {
1681
+ "dark": {
1682
+ "$ref": "#/$defs/ColorRef",
1683
+ "description": "Color at luminance 0."
1684
+ },
1685
+ "light": {
1686
+ "$ref": "#/$defs/ColorRef",
1687
+ "description": "Color at luminance 1."
1688
+ }
1689
+ },
1690
+ "description": "Duotone: map each pixel's luminance linearly from dark to light, exported as native a:duotone."
1691
+ }
1692
+ ],
1693
+ "description": "Color treatment for the image pixels. Luminance uses Rec. 601 weights (0.299, 0.587, 0.114) on sRGB values."
1694
+ },
1763
1695
  "PatternBackground": {
1764
1696
  "type": "object",
1765
1697
  "description": "Fixed pattern slide background fill.",
@@ -1857,7 +1789,7 @@
1857
1789
  },
1858
1790
  "Watermark": {
1859
1791
  "type": "object",
1860
- "description": "Decorative watermark: an image ('src') or a text stamp ('text'), exactly one of the two, with its opacity. An image is drawn once per slide, contained and centered in a fixed frame (the middle 40% of the slide width and height, from 30% to 70% on each axis). A text watermark is one line of text in the heading font and the theme text color at the given opacity, centered on the slide and rotated 30 degrees counterclockwise (rising to the right), sized to span at most 70% of the slide width and at most 30% of the shorter slide edge in height; it is drawn behind the slide content and above the background and slide image. There is no option to move, scale, rotate or tile either form. PPTX export writes one native picture (image) or one native text box (text) per slide with the opacity as alpha, and import restores the watermark. A string or Asset (no opacity) is the image watermark at opacity 0.08. A watermark object needs opacity and exactly one of src and text; use a plain string or Asset for an image at the default opacity. Use design.watermark = false to disable an inherited watermark.",
1792
+ "description": "Decorative watermark: an image ('src') or a text stamp ('text'), exactly one of the two, with its opacity. An image is drawn once per slide, contained and centered in a fixed frame (the middle 40% of the slide width and height, from 30% to 70% on each axis). A text watermark is one line of text in the heading font and the theme text color at the given opacity, centered on the slide and rotated 30 degrees counterclockwise (rising to the right), sized to span at most 70% of the slide width and at most 30% of the shorter slide edge in height; it is drawn behind the slide content and above the background. There is no option to move, scale, rotate or tile either form. PPTX export writes one native picture (image) or one native text box (text) per slide with the opacity as alpha, and import restores the watermark. A string or Asset (no opacity) is the image watermark at opacity 0.08. A watermark object needs opacity and exactly one of src and text; use a plain string or Asset for an image at the default opacity. Use design.watermark = false to disable an inherited watermark.",
1861
1793
  "additionalProperties": false,
1862
1794
  "required": ["opacity"],
1863
1795
  "oneOf": [
@@ -1987,9 +1919,9 @@
1987
1919
  "description": "Optional reference to one or more beats of the deck's narrative (each value is the id of a beat in the narrative record that the root 'narrative' resolves to). A single string declares the slide's primary beat; an array declares that one slide covers multiple beats. Declares the slide's role in the story arc; does not constrain ordering or structure. Core validate warns about a beat id the resolved narrative does not define, and reports a beat that no slide references. Slides without a beat are valid; multiple slides may share a beat."
1988
1920
  },
1989
1921
  "layout": {
1990
- "type": "string",
1991
- "description": "Optional. Resolves to the 'id' of a 'layouts' catalog record. When omitted, or when it names an id that no inline record, host catalog or default catalog defines, the slide is composed with no layout record: engines arrange title, subtitle, tag and content automatically, a slide with no body payload is a cover (vertically centered), and design hints apply. A layout never changes what a slide contains. An unresolved id is an `unresolved-layout` diagnostic and a `catalog-reference` warning, never an error. Engines must not substitute a different layout for an omitted one. Accepts a bare id (lowercase kebab-case, e.g. 'title-subtitle'), an HTTPS URL pointing at a record file, or a 'pkg:' reference.\n\nResolution order: inline catalogs.layouts.records[] → catalogs.layouts.source → default catalog at https://www.pptx.gallery/layouts.",
1992
- "examples": ["title", "title-subtitle", "text-2x", "chart-3x", "image-bleed", "blank", "https://acme.com/decks/layouts/cover.json", "pkg:@acme/decks/layouts/cover"]
1922
+ "$ref": "#/$defs/CatalogReference",
1923
+ "description": "Optional layout: a layouts reference, a bare id ('title-subtitle') or 'name:id' ('acme:hero'). When omitted, the slide is composed with no layout record: engines arrange title, subtitle, tag and content automatically, a slide with no body payload is a cover (vertically centered), and design hints apply; there is no finding. A reference that resolves nowhere is the warning opf/unresolved-reference (and the 'unresolved-reference' diagnostic of resolveSlideContext), the slide composes automatically, and a strict export fails. A layout never changes what a slide contains, and engines never substitute a different layout.",
1924
+ "examples": ["title", "title-subtitle", "text-2x", "chart-3x", "blank", "acme:hero"]
1993
1925
  },
1994
1926
  "title": {
1995
1927
  "oneOf": [
@@ -2051,7 +1983,7 @@
2051
1983
  },
2052
1984
  "image": {
2053
1985
  "$ref": "#/$defs/Asset",
2054
- "description": "Full-slide image source. Presence of this field infers type 'image'."
1986
+ "description": "Shorthand for one image block: the picture composes as body content, like { type: 'image', image: value }, with the effective design.imageFit. A layout's image placeholder may place it along an edge (placement). For fit, focus, treatments or an explicit placement use an image block in blocks; for a full-slide picture behind the content use design.background. Presence of this field infers type 'image'."
2055
1987
  },
2056
1988
  "video": {
2057
1989
  "$ref": "#/$defs/Asset",
@@ -2343,6 +2275,54 @@
2343
2275
  "asset:img-diagram"
2344
2276
  ]
2345
2277
  },
2278
+ "fit": {
2279
+ "type": "string",
2280
+ "enum": ["cover", "contain", "stretch"],
2281
+ "description": "Image payloads only. How the picture fills its frame: 'cover' fills it and crops what overflows around focus; 'contain' shows the whole picture centered; 'stretch' scales it to the frame exactly. Default: the effective design.imageFit, else 'cover'."
2282
+ },
2283
+ "focus": {
2284
+ "$ref": "#/$defs/ImageFocus",
2285
+ "description": "Image payloads only. Point of the picture to keep in view when 'cover' crops it. Ignored by the other fits."
2286
+ },
2287
+ "aspectRatio": {
2288
+ "type": "number",
2289
+ "exclusiveMinimum": 0,
2290
+ "maximum": 10,
2291
+ "description": "Image payloads only. Width-to-height ratio of the frame: the frame becomes the largest centered box with this ratio inside the block's region, for example 2.39 for a cinematic letterbox or 0.5 for a phone-shaped frame. shape 'circle' always uses 1."
2292
+ },
2293
+ "shape": {
2294
+ "type": "string",
2295
+ "enum": ["rectangle", "rounded", "circle", "hexagon"],
2296
+ "description": "Image payloads only. Mask applied to the frame, exported as the picture's native preset geometry (rect, roundRect, ellipse, hexagon). 'circle' makes the frame square. Default 'rectangle'."
2297
+ },
2298
+ "cornerRadius": {
2299
+ "type": "number",
2300
+ "minimum": 0,
2301
+ "maximum": 0.5,
2302
+ "description": "Image payloads only. Corner radius for shape 'rounded' as a fraction of the frame's shorter side. Default 0.16667, PowerPoint's roundRect default."
2303
+ },
2304
+ "border": {
2305
+ "$ref": "#/$defs/ImageBorder",
2306
+ "description": "Image payloads only. Line along the frame's shape."
2307
+ },
2308
+ "opacity": {
2309
+ "type": "number",
2310
+ "minimum": 0,
2311
+ "maximum": 1,
2312
+ "description": "Image payloads only. Picture opacity from 0 to 1, exported as a native alphaModFix. The border and overlay keep their own opacity. Default 1."
2313
+ },
2314
+ "recolor": {
2315
+ "$ref": "#/$defs/ImageRecolor",
2316
+ "description": "Image payloads only. Grayscale or duotone treatment of the picture's pixels."
2317
+ },
2318
+ "overlay": {
2319
+ "$ref": "#/$defs/Overlay",
2320
+ "description": "Image payloads only. Scrim over the picture in the frame's shape, or a band along one edge of a rectangle frame."
2321
+ },
2322
+ "placement": {
2323
+ "$ref": "#/$defs/ImagePlacement",
2324
+ "description": "Image payloads only, and only on a top-level block (slides.N.blocks.I), at most one per edge. Bleeds the image to one slide edge; the headings and the other blocks compose in the rest of the slide."
2325
+ },
2346
2326
  "video": {
2347
2327
  "$ref": "#/$defs/Asset",
2348
2328
  "description": "Source for a video item. Engines do not play video: the preview draws a placeholder (a play badge with the asset's title or source as its caption), and PPTX export draws the same placeholder as native shapes linked to an http(s) source, with no embedded media. Native playback is out of scope (docs/programs/release-readiness).",
@@ -3124,11 +3104,9 @@
3124
3104
  "properties": {
3125
3105
  "type": {
3126
3106
  "type": "string",
3127
- "description": "Chart type id. Resolves to the id of a chartTypes catalog record; renderers map that record through mappings.openxml and any renderer-specific mapping they understand. The bundled catalog covers the chart types Aspose.Slides officially supports, plus 'combo' (clustered columns with line series, see 'line' and 'secondaryAxis').",
3128
- "examples": [
3129
- "column", "bar", "line", "pie", "doughnut", "area", "scatter", "radar",
3130
- "waterfall", "funnel", "treemap", "stacked-column", "combo"
3131
- ]
3107
+ "enum": ["100pct-stacked-area", "100pct-stacked-bar", "100pct-stacked-column", "area", "bar", "box-and-whisker", "column", "combo", "doughnut", "filled-radar", "funnel", "histogram", "line", "line-with-markers", "pareto", "pie", "radar", "radar-with-markers", "scatter", "stacked-area", "stacked-bar", "stacked-column", "stacked-line", "stacked-line-with-markers", "treemap", "waterfall", "world"],
3108
+ "description": "Chart type, an engine vocabulary validated directly (no catalog lookup): the chart types Aspose.Slides officially supports, plus 'combo' (clustered columns with line series, see 'line' and 'secondaryAxis'). Each engine maps a type to its own chart model; labels and picker groups are catalog display metadata.",
3109
+ "examples": ["column", "bar", "line", "pie", "doughnut", "area", "scatter", "radar", "waterfall", "funnel", "treemap", "stacked-column", "combo"]
3132
3110
  },
3133
3111
  "data": {
3134
3112
  "oneOf": [
@@ -3734,86 +3712,139 @@
3734
3712
  },
3735
3713
  "Catalogs": {
3736
3714
  "type": "object",
3737
- "description": "Catalog overrides for the in-document references. Every property is optional. The default catalog for a kind lives at https://www.pptx.gallery/<kind> (e.g. https://www.pptx.gallery/narratives, https://www.pptx.gallery/themes). pptx.gallery is its canonical publisher: GET https://www.pptx.gallery/<kind>/index.json (or https://www.pptx.gallery/<kind> with Accept: application/json) returns a catalog index (https://openpresentation.org/schema/opf-catalog-index/v1) and https://www.pptx.gallery/<kind>/<id>.json returns one record that validates against the kind's companion schema; publisher metadata sits in top-level 'x-*' members that consumers ignore. Engines resolve the default catalog from the pinned snapshot bundled in @openpresentation/opf (spec/catalogs, pinned to a publisher commit and content hash by spec/catalogs/manifest.json), so resolution is deterministic offline and in the cloud; they do not fetch pptx.gallery at run time. For each kind, declaring a 'source' replaces the default registry and/or 'records' adds inline records that take precedence over anything fetched from a source.\n\nResolution order for any reference (e.g. narrative, design.theme): inline catalogs.<kind>.records[] → catalogs.<kind>.source → default catalog at https://www.pptx.gallery/<kind>. Every reference resolves to the catalog record's 'id' field. References that are themselves URLs or 'pkg:' references skip the catalog lookup and resolve directly.",
3715
+ "description": "The catalog records a document embeds, grouped by the catalog they came from. Each property is a group; inside a group, records are keyed by kind and then by id.\n- 'default': the catalog bare ids come from. It needs a 'source' when it holds records. Omitted: bare ids fall back to the host's default catalog. false: no catalog fallback, so every bare id must be embedded (under 'custom' or 'default').\n- 'custom': the records the document defines itself. It has no source.\n- any other name ('acme'): an extra catalog, identified by its 'source'. The name is the prefix references use ('acme:hero'). Names are lowercase kebab-case; 'default' and 'custom' are reserved.\n\nResolution, for every kind: a bare id resolves in 'custom', then in the records embedded under 'default', then in the catalog the host registered for default.source (the host's default catalog when 'default' is omitted). 'name:id' resolves in that group's records, then in the catalog the host registered for its source. A reference written inside an embedded record (a theme's colorScheme) resolves in that record's own group first. A prefix that names no group is a validation error; a reference that resolves nowhere is the warning opf/unresolved-reference. Engines never fetch a source: hosts register catalogs by their source string, and authoring tools embed every record a document uses when they save it.",
3738
3716
  "properties": {
3739
- "narratives": {
3740
- "$ref": "#/$defs/CatalogEntry",
3741
- "description": "Catalog of narrative templates. Records validate against https://openpresentation.org/schema/opf-narrative/v1. A custom narrative goes in 'catalogs.narratives.records' and is referenced by its id from the root 'narrative'. Default source: https://www.pptx.gallery/narratives."
3717
+ "default": {
3718
+ "oneOf": [
3719
+ {
3720
+ "allOf": [
3721
+ { "$ref": "#/$defs/CatalogGroup" },
3722
+ {
3723
+ "if": {
3724
+ "anyOf": [
3725
+ { "required": ["layouts"] },
3726
+ { "required": ["themes"] },
3727
+ { "required": ["colorSchemes"] },
3728
+ { "required": ["fontSchemes"] },
3729
+ { "required": ["narratives"] },
3730
+ { "required": ["audiences"] },
3731
+ { "required": ["purposes"] },
3732
+ { "required": ["tones"] }
3733
+ ]
3734
+ },
3735
+ "then": { "required": ["source"] }
3736
+ }
3737
+ ]
3738
+ },
3739
+ { "const": false }
3740
+ ],
3741
+ "description": "The catalog bare ids come from: its source and the records of it this document embeds. false turns off the catalog fallback for bare ids.",
3742
+ "examples": [
3743
+ {
3744
+ "source": "https://www.pptx.gallery",
3745
+ "layouts": {
3746
+ "two-column": { "name": "Two column", "placeholders": [{ "type": "title" }, { "type": "text" }, { "type": "text" }] }
3747
+ }
3748
+ },
3749
+ false
3750
+ ]
3751
+ },
3752
+ "custom": {
3753
+ "allOf": [{ "$ref": "#/$defs/CatalogGroup" }, { "not": { "required": ["source"] } }],
3754
+ "description": "Records the document defines itself, referenced by bare id. Checked first for every bare id. Forking a catalog record copies it here under a new id, so the change of ownership is visible."
3755
+ }
3756
+ },
3757
+ "propertyNames": {
3758
+ "pattern": "^[a-z][a-z0-9-]*$",
3759
+ "description": "Group name: lowercase kebab-case. 'default' and 'custom' are reserved."
3760
+ },
3761
+ "additionalProperties": {
3762
+ "allOf": [{ "$ref": "#/$defs/CatalogGroup" }, { "required": ["source"] }],
3763
+ "description": "A named catalog: its source and the records of it this document embeds. References name it as a prefix ('acme:hero')."
3764
+ },
3765
+ "examples": [
3766
+ {
3767
+ "default": {
3768
+ "source": "https://www.pptx.gallery",
3769
+ "themes": { "minimal": { "name": "Minimal", "colorScheme": "cool-horizon", "fontScheme": "aptos" } }
3770
+ },
3771
+ "acme": {
3772
+ "source": "pkg:@acme/opf-catalog",
3773
+ "layouts": { "hero": { "name": "Hero", "placeholders": [{ "type": "title" }] } }
3774
+ },
3775
+ "custom": {
3776
+ "layouts": { "q4-special": { "name": "Q4 special", "placeholders": [{ "type": "title" }, { "type": "chart" }] } }
3777
+ }
3778
+ }
3779
+ ]
3780
+ },
3781
+ "CatalogGroup": {
3782
+ "type": "object",
3783
+ "additionalProperties": false,
3784
+ "description": "One catalog group: the catalog's source and the records of it the document embeds, by kind and then by id.",
3785
+ "properties": {
3786
+ "source": { "$ref": "#/$defs/CatalogSource" },
3787
+ "layouts": {
3788
+ "$ref": "#/$defs/CatalogRecords",
3789
+ "description": "Layout records keyed by id, each with the fields of https://openpresentation.org/schema/opf-layout/v1. Referenced from Slide.layout."
3742
3790
  },
3743
3791
  "themes": {
3744
- "$ref": "#/$defs/CatalogEntry",
3745
- "description": "Catalog of themes. Records validate against https://openpresentation.org/schema/opf-theme/v1. Default source: https://www.pptx.gallery/themes."
3792
+ "$ref": "#/$defs/CatalogRecords",
3793
+ "description": "Theme records keyed by id, each with the fields of https://openpresentation.org/schema/opf-theme/v1. Referenced from design.theme."
3746
3794
  },
3747
3795
  "colorSchemes": {
3748
- "$ref": "#/$defs/CatalogEntry",
3749
- "description": "Catalog of color schemes. Records validate against https://openpresentation.org/schema/opf-color-scheme/v1. Default source: https://www.pptx.gallery/color-schemes."
3796
+ "$ref": "#/$defs/CatalogRecords",
3797
+ "description": "Colour-scheme records keyed by id, each with the fields of https://openpresentation.org/schema/opf-color-scheme/v1. Referenced from design.colorScheme and a theme's colorScheme."
3750
3798
  },
3751
3799
  "fontSchemes": {
3752
- "$ref": "#/$defs/CatalogEntry",
3753
- "description": "Catalog of font schemes. Records validate against https://openpresentation.org/schema/opf-font-scheme/v1. Default source: https://www.pptx.gallery/font-schemes."
3800
+ "$ref": "#/$defs/CatalogRecords",
3801
+ "description": "Font-scheme records keyed by id, each with the fields of https://openpresentation.org/schema/opf-font-scheme/v1. Referenced from design.fontScheme, a theme's fontScheme and a language's font schemes."
3754
3802
  },
3755
- "languages": {
3756
- "$ref": "#/$defs/CatalogEntry",
3757
- "description": "Catalog of languages. Records validate against https://openpresentation.org/schema/opf-language/v1. Default source: https://www.pptx.gallery/languages."
3758
- },
3759
- "layouts": {
3760
- "$ref": "#/$defs/CatalogEntry",
3761
- "description": "Catalog of slide layouts. Records validate against https://openpresentation.org/schema/opf-layout/v1. Default source: https://www.pptx.gallery/layouts."
3762
- },
3763
- "chartTypes": {
3764
- "$ref": "#/$defs/CatalogEntry",
3765
- "description": "Catalog of chart types. Records validate against https://openpresentation.org/schema/opf-chart-type/v1. Default source: https://www.pptx.gallery/chart-types."
3803
+ "narratives": {
3804
+ "$ref": "#/$defs/CatalogRecords",
3805
+ "description": "Narrative records keyed by id, each with the fields of https://openpresentation.org/schema/opf-narrative/v1. Referenced from narrative."
3766
3806
  },
3767
- "tones": {
3768
- "$ref": "#/$defs/CatalogEntry",
3769
- "description": "Catalog of presentation tones. Records validate against https://openpresentation.org/schema/opf-tone/v1. Default source: https://www.pptx.gallery/tones. Referenced from tone."
3807
+ "audiences": {
3808
+ "$ref": "#/$defs/CatalogRecords",
3809
+ "description": "Audience records keyed by id, each with the fields of https://openpresentation.org/schema/opf-audience/v1. Referenced from audience."
3770
3810
  },
3771
3811
  "purposes": {
3772
- "$ref": "#/$defs/CatalogEntry",
3773
- "description": "Catalog of presentation purposes. Records validate against https://openpresentation.org/schema/opf-purpose/v1. Default source: https://www.pptx.gallery/purposes. Referenced from purpose."
3774
- },
3775
- "audiences": {
3776
- "$ref": "#/$defs/CatalogEntry",
3777
- "description": "Catalog of presentation audiences. Records validate against https://openpresentation.org/schema/opf-audience/v1. Default source: https://www.pptx.gallery/audiences. Referenced from audience."
3812
+ "$ref": "#/$defs/CatalogRecords",
3813
+ "description": "Purpose records keyed by id, each with the fields of https://openpresentation.org/schema/opf-purpose/v1. Referenced from purpose."
3778
3814
  },
3779
- "socialPlatforms": {
3780
- "$ref": "#/$defs/CatalogEntry",
3781
- "description": "Catalog of social-media platforms. Records validate against https://openpresentation.org/schema/opf-social-platform/v1. Default source: https://www.pptx.gallery/social-platforms. Referenced via the property keys of any Socials object (Organization.socials, Speaker.socials)."
3815
+ "tones": {
3816
+ "$ref": "#/$defs/CatalogRecords",
3817
+ "description": "Tone records keyed by id, each with the fields of https://openpresentation.org/schema/opf-tone/v1. Referenced from tone."
3782
3818
  }
3783
3819
  }
3784
3820
  },
3785
- "CatalogEntry": {
3821
+ "CatalogSource": {
3822
+ "type": "string",
3823
+ "pattern": "^(?:https://[^\\s]+|pkg:[^\\s]+)$",
3824
+ "description": "Identity of a catalog: an HTTPS URL ('https://www.pptx.gallery') or a package reference ('pkg:@acme/opf-catalog'). It names the catalog; engines never fetch or install it. A host registers the catalog's records under this exact string, and copying slides between documents matches groups by it.",
3825
+ "examples": ["https://www.pptx.gallery", "pkg:@acme/opf-catalog"]
3826
+ },
3827
+ "CatalogRecords": {
3786
3828
  "type": "object",
3787
- "description": "A catalog override for one record kind. 'source' replaces the default registry; 'records' adds inline records that take precedence over anything fetched from a source. Either or both may be provided; both omitted means the kind uses its default catalog.",
3788
- "properties": {
3789
- "source": {
3790
- "oneOf": [
3791
- { "$ref": "#/$defs/CatalogSource" },
3792
- {
3793
- "type": "array",
3794
- "items": { "$ref": "#/$defs/CatalogSource" },
3795
- "minItems": 1,
3796
- "description": "Ordered search path of sources. The engine tries each in order; first match wins. The default catalog for the kind is appended implicitly at the end."
3797
- }
3798
- ],
3799
- "description": "Single source or an ordered search path of sources. When omitted, the engine falls back to the default catalog at https://www.pptx.gallery/<kind>, resolved from its bundled snapshot. Engines never fetch a source. The host loads the records itself and passes them to the renderer and exporter as a 'catalogSources' map from the source string to its records; a source with no entry in that map contributes no records, except the default catalog's own URL and the '@openpresentation/opf' package, which resolve from the bundled snapshot."
3800
- },
3801
- "records": {
3802
- "type": "array",
3803
- "items": { "type": "object" },
3804
- "description": "Inline catalog records embedded in this OPF document. Each record validates against the kind's companion schema (e.g. https://openpresentation.org/schema/opf-narrative/v1 for narratives). Inline records win over anything resolved from 'source' and over the default catalog."
3805
- }
3829
+ "description": "Embedded records of one kind, keyed by id. The key is the record's id; an embedded record carries no '$schema', 'id', origin or digest. Catalog display metadata ('x-*' members) is stripped when a record is embedded.",
3830
+ "propertyNames": { "pattern": "^[a-z][a-z0-9-]*$" },
3831
+ "additionalProperties": {
3832
+ "type": "object",
3833
+ "not": { "anyOf": [{ "required": ["$schema"] }, { "required": ["id"] }] },
3834
+ "description": "One embedded record: the fields of the kind's companion schema without '$schema' and 'id'."
3806
3835
  }
3807
3836
  },
3808
- "CatalogSource": {
3837
+ "CatalogReference": {
3809
3838
  "type": "string",
3810
- "description": "Catalog source location. Accepts:\n- A bare URL pointing at a catalog directory (e.g. 'https://acme.com/decks/narratives'); record ids resolve to '<base>/<id>.json'.\n- A URL pointing at an index file (e.g. 'https://acme.com/decks/narratives/index.json'); records are resolved relative to the index file's directory and the index entries describe what's available. Index files follow https://openpresentation.org/schema/opf-catalog-index/v1; the default catalog's index is https://www.pptx.gallery/<kind>/index.json.\n- A package reference of the form 'pkg:<package>[/<subpath>]'. 'pkg:@openpresentation/opf/...' resolves from the bundled snapshot; any other package reference needs the host to supply its records in 'catalogSources'.\n\nEngines never fetch or install anything for a source: the host supplies the records of every source other than the bundled default, as a 'catalogSources' map from the source string to its records.",
3811
- "examples": [
3812
- "https://www.pptx.gallery/narratives",
3813
- "https://acme.com/decks/narratives/index.json",
3814
- "pkg:@acme/decks/narratives",
3815
- "pkg:pptx-gallery"
3816
- ]
3839
+ "pattern": "^(?:[a-z][a-z0-9-]*:)?[a-z][a-z0-9-]*$",
3840
+ "description": "A content reference: a bare id ('two-column') or 'name:id' ('acme:hero'), where the prefix names a group of 'catalogs'. URLs and 'pkg:' strings are not references; a named catalog group replaces them. See Catalogs for the resolution order.",
3841
+ "examples": ["two-column", "acme:hero", "default:minimal", "custom:q4-special"]
3842
+ },
3843
+ "LanguageTag": {
3844
+ "type": "string",
3845
+ "pattern": "^(?:[A-Za-z]{2,3}|[iIxX])(?:-[A-Za-z0-9]{1,8})*$",
3846
+ "description": "A BCP-47 language tag ('en-US', 'ja', 'zh-Hans', 'sr-Latn-ME'), an engine vocabulary. Use 'en-GB' for UK English; 'en-UK' is not a valid region.",
3847
+ "examples": ["en-US", "en-GB", "ja", "zh-Hans", "ar-SA"]
3817
3848
  },
3818
3849
  "Composition": {
3819
3850
  "type": "object",