@openpresentation/opf 0.24.2 → 0.26.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +1 -1
  2. package/dist/browser.js +17 -17
  3. package/dist/{chunk-JHSTEBPC.js → chunk-3OE6PZIC.js} +5 -5
  4. package/dist/{chunk-33OBLTKZ.js → chunk-EQ6S5SEZ.js} +1 -1
  5. package/dist/{chunk-BN3A5TVI.js → chunk-F4HFDP6I.js} +206 -123
  6. package/dist/{chunk-ZFNKRZZQ.js → chunk-F5ABHDUX.js} +6 -6
  7. package/dist/{chunk-UIKXX5EX.js → chunk-FITOGMR3.js} +2 -2
  8. package/dist/{chunk-5PHLSH4E.js → chunk-GS37EBPQ.js} +1 -1
  9. package/dist/{chunk-RP2KIC7W.js → chunk-IC6OPLMU.js} +2 -2
  10. package/dist/{chunk-RE4F2USA.js → chunk-IWFXFWGD.js} +1 -1
  11. package/dist/{chunk-RQACV2FR.js → chunk-IY5SCRTV.js} +1 -1
  12. package/dist/{chunk-RXKXY75X.js → chunk-LU6XM5JQ.js} +1 -1
  13. package/dist/{chunk-H77YYHPL.js → chunk-MJ57RSYO.js} +5 -5
  14. package/dist/{chunk-DRCN5PFH.js → chunk-NJRFCM4H.js} +6 -6
  15. package/dist/{chunk-F6CDJTSE.js → chunk-P7S3ORB4.js} +9 -9
  16. package/dist/{chunk-F7PLNWHQ.js → chunk-PJSPHHRK.js} +1 -1
  17. package/dist/{chunk-4I3XPRAO.js → chunk-TKQ2VFV5.js} +1 -1
  18. package/dist/{chunk-6WDLGY25.js → chunk-WW62PPYV.js} +4 -4
  19. package/dist/{chunk-H5GFPQAS.js → chunk-X7RANZWP.js} +2 -2
  20. package/dist/{chunk-N3ZPLGK5.js → chunk-XRMV2GMB.js} +365 -266
  21. package/dist/{composition-qX-igJe5.d.ts → composition-Daqvi-GV.d.ts} +47 -28
  22. package/dist/composition.d.ts +1 -1
  23. package/dist/composition.js +1 -1
  24. package/dist/conversion-AJEJJHLO.js +19 -0
  25. package/dist/{conversion-O0XSW0ZV.d.ts → conversion-Dh8Q4RiX.d.ts} +5 -5
  26. package/dist/convert.d.ts +2 -2
  27. package/dist/convert.js +7 -7
  28. package/dist/data.d.ts +1 -1
  29. package/dist/data.js +2 -2
  30. package/dist/{deck-report-CJ6gd_6-.d.ts → deck-report-DHaboWbM.d.ts} +2 -2
  31. package/dist/deck.d.ts +5 -5
  32. package/dist/deck.js +10 -10
  33. package/dist/diff.js +5 -5
  34. package/dist/docs.js +27 -27
  35. package/dist/examples.d.ts +1 -1
  36. package/dist/examples.js +9555 -15758
  37. package/dist/font-policy.js +1 -1
  38. package/dist/format.js +2 -2
  39. package/dist/index.d.ts +11 -11
  40. package/dist/index.js +21 -21
  41. package/dist/markdown.d.ts +3 -3
  42. package/dist/markdown.js +7 -7
  43. package/dist/node-engine.d.ts +7 -7
  44. package/dist/node-engine.js +21 -21
  45. package/dist/{pagination-LiWxhbsz.d.ts → pagination-R8YFwVj7.d.ts} +1 -1
  46. package/dist/pagination.d.ts +2 -2
  47. package/dist/pagination.js +4 -4
  48. package/dist/patch.js +4 -4
  49. package/dist/{presentation-Dn-fm0iY.d.ts → presentation-Bwo8Ko6D.d.ts} +1 -1
  50. package/dist/repo-readme.js +1 -1
  51. package/dist/schemas.d.ts +8 -0
  52. package/dist/schemas.js +1 -1
  53. package/dist/spec/README.md +2 -2
  54. package/dist/spec/reference/font-policy.json +1 -1
  55. package/dist/spec/schemas/layout.schema.json +175 -88
  56. package/dist/spec/schemas/opf.schema.json +4 -4
  57. package/dist/types.d.ts +72 -24
  58. package/dist/{validation-types-CzPKoKWo.d.ts → validation-types-JW8e06ee.d.ts} +1 -1
  59. package/dist/{validator-BuAV_HUo.d.ts → validator-Dym2zYVK.d.ts} +3 -3
  60. package/dist/validator.d.ts +4 -4
  61. package/dist/validator.js +3 -3
  62. package/dist/yaml.d.ts +3 -3
  63. package/dist/yaml.js +7 -7
  64. package/package.json +18 -18
  65. package/dist/conversion-MTGISXNM.js +0 -19
@@ -2,13 +2,13 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://openpresentation.org/schema/opf-layout/v2",
4
4
  "title": "Slide Layout",
5
- "description": "Schema for slide-layout records (OPF 0.19). A layout is a grid template: 'areas' names the cells of a grid using nested row arrays, 'columns' and 'rows' size its tracks, and 'regions' says, for every body area, which content kinds it takes and how several blocks share it. Slide content stays flat: engines bind a slide's blocks to the regions by reading order, role and kind (bindRegions in @openpresentation/opf), a block may pin itself to a region with 'region', and an empty region collapses into a neighbour. Built-in and custom layouts are records of this one schema; a custom layout is embedded under catalogs.custom.layouts or shipped in a catalog. Documents reference a layout from Slide.layout; a slide without a layout, with layout 'auto', or whose layout resolves nowhere composes automatically.\n\nA document references a record as a bare id or 'name:id' and resolves it in its own catalogs groups first, then in the catalog the host registered for the group's source; engines never fetch a catalog. A published record file carries '$schema' and 'id'; the copy a document embeds under catalogs.<group>.<kind>.<id> carries neither (the key is the id) and no 'x-*' display metadata.",
5
+ "description": "Schema for slide-layout records. A layout is one ordered list of regions, declared once, in reading order: 'direction' says whether the record's 'regions' sit side by side (row) or are stacked (column), and each region says which content kinds it takes and how several blocks share it. A split is an entry that nests a second list the other way, which is how a layout gets two dimensions. 'title' and 'subtitle' are reserved heading regions. Engines compile the list into a grid of tracks (the guillotine partition it describes). Slide content stays flat: engines bind a slide's blocks to the regions by reading order, role and kind (bindRegions in @openpresentation/opf), a block may pin itself to a region with 'region', and an empty region collapses into a neighbour. Built-in and custom layouts are records of this one schema; a custom layout is embedded under catalogs.custom.layouts or shipped in a catalog. Documents reference a layout from Slide.layout; a slide without a layout, with layout 'auto', or whose layout resolves nowhere composes automatically.\n\nA document references a record as a bare id or 'name:id' and resolves it in its own catalogs groups first, then in the catalog the host registered for the group's source; engines never fetch a catalog. A published record file carries '$schema' and 'id'; the copy a document embeds under catalogs.<group>.<kind>.<id> carries neither (the key is the id) and no 'x-*' display metadata.",
6
6
  "type": "object",
7
7
  "required": [
8
8
  "$schema",
9
9
  "id",
10
10
  "name",
11
- "areas"
11
+ "regions"
12
12
  ],
13
13
  "properties": {
14
14
  "$schema": {
@@ -58,105 +58,76 @@
58
58
  "$ref": "#/$defs/DesignHints",
59
59
  "description": "The layout's design defaults, with the same keys and values as the deck's design and a slide's design (a slide overrides exactly what its layout sets, by the same name). An absent key means the layout has no opinion. Per key the slide's design wins, then the deck's design, then the resolved theme's design, then this record's design, then the engine default. Composition, the renderer and the PPTX exporter all read the one result."
60
60
  },
61
- "areas": {
62
- "type": "array",
63
- "minItems": 1,
64
- "maxItems": 12,
65
- "items": {
66
- "type": "array",
67
- "minItems": 1,
68
- "maxItems": 12,
69
- "items": {
70
- "type": "string",
71
- "pattern": "^(?:[a-z][a-z0-9-]*|\\.)$"
72
- }
73
- },
74
- "description": "The grid as nested arrays: each inner array is a row, each string is one cell, and a name repeated over adjacent cells spans them; '.' is an empty cell. Cells are lowercase names ([a-z][a-z0-9-]*) or '.', and every row has the same number of cells (at most 12 rows and 12 columns). A name's cells must form one filled rectangle. 'title' and 'subtitle' are heading areas: 'title' holds the slide's heading group (tag, title and subtitle, stacked) and a 'subtitle' area takes the subtitle out of it; they have no regions entry, and a 'subtitle' area needs a 'title' area. A layout with no 'title' area gets an implicit auto row on top for a slide that has headings. Every other name is a body region and needs an entry in 'regions'. The grid rules a schema cannot express are the validate finding opf/layout-template.",
61
+ "direction": {
62
+ "type": "string",
63
+ "enum": [
64
+ "row",
65
+ "column"
66
+ ],
67
+ "description": "How the record's 'regions' are laid out: 'row' places them side by side, left to right in reading order; 'column' stacks them top to bottom. Default 'column'.",
75
68
  "examples": [
76
- [
77
- [
78
- "title"
79
- ],
80
- [
81
- "body"
82
- ]
83
- ],
84
- [
85
- [
86
- "title",
87
- "title"
88
- ],
89
- [
90
- "timeline",
91
- "notes"
92
- ],
93
- [
94
- "timeline",
95
- "metrics"
96
- ]
97
- ]
69
+ "row",
70
+ "column"
98
71
  ]
99
72
  },
100
- "columns": {
73
+ "anchor": {
74
+ "type": "string",
75
+ "enum": [
76
+ "top",
77
+ "middle",
78
+ "bottom"
79
+ ],
80
+ "description": "Vertical position of the content of every body region when it is shorter than the region. A split's 'anchor' replaces it for the regions under that split, and a region's own 'anchor' replaces both. Only 'anchor' is inherited, and only by body regions: the heading regions 'title' and 'subtitle' never take it, and the other region rules stay per region. Default 'top'."
81
+ },
82
+ "regions": {
101
83
  "type": "array",
102
84
  "minItems": 1,
103
85
  "maxItems": 12,
104
86
  "items": {
105
- "type": "number",
106
- "exclusiveMinimum": 0,
107
- "maximum": 100
87
+ "$ref": "#/$defs/RegionEntry"
108
88
  },
109
- "description": "Relative column widths, one per cell of a row; the columns share the content width in proportion, separated by the gap. Omitted: all 1. Columns are numbers only.",
89
+ "description": "The record's regions in reading order: 1 to 12 entries, each a region ({ name, size?, ...rules }) or a split ({ direction, regions, size?, anchor? }). Every region is declared once, here, with its content rules; a block can target a body region with 'region': '<name>'. Names are unique across the whole record. 'size' is a number above 0 and up to 100 (default 1) that siblings share in proportion, separated by the gap; 'auto' is the height the content needs, allowed only in a column. 'title' and 'subtitle' are heading regions that take only a size (default auto in a column, 1 in a row): 'title' holds the slide's heading group (tag, title and subtitle, stacked) and a 'subtitle' region takes the subtitle out of it, and a 'subtitle' needs a 'title'. A record with no 'title' region gets an implicit auto row on top for a slide that has headings. Splits nest at most three levels (the record's own list is level 1). Rules the schema cannot express (a reserved or repeated name, a 'subtitle' without a 'title', 'auto' outside a column, nesting too deep, more than 12 rows or columns once compiled) are the validate findings opf/layout-template and opf/layout-region.",
110
90
  "examples": [
111
91
  [
112
- 1,
113
- 1
114
- ],
115
- [
116
- 3,
117
- 2
118
- ]
119
- ]
120
- },
121
- "rows": {
122
- "type": "array",
123
- "minItems": 1,
124
- "maxItems": 12,
125
- "items": {
126
- "oneOf": [
127
92
  {
128
- "type": "number",
129
- "exclusiveMinimum": 0,
130
- "maximum": 100
93
+ "name": "main",
94
+ "size": 2,
95
+ "accepts": [
96
+ "text"
97
+ ]
131
98
  },
132
99
  {
133
- "const": "auto"
100
+ "name": "aside",
101
+ "size": 1,
102
+ "accepts": [
103
+ "metric"
104
+ ]
134
105
  }
135
- ]
136
- },
137
- "description": "Relative row heights, one per string of 'areas'. 'auto' is the height the row's content needs at the starting text size (at most half the content box; areas that span several rows do not size it); the numeric rows share the rest in proportion. An auto row whose areas are all empty has no height. Omitted: all 1.",
138
- "examples": [
139
- [
140
- "auto",
141
- 1
142
106
  ],
143
107
  [
144
- "auto",
145
- 1,
146
- "auto"
108
+ {
109
+ "name": "title"
110
+ },
111
+ {
112
+ "direction": "row",
113
+ "regions": [
114
+ {
115
+ "name": "first",
116
+ "accepts": [
117
+ "text"
118
+ ]
119
+ },
120
+ {
121
+ "name": "second",
122
+ "accepts": [
123
+ "text"
124
+ ]
125
+ }
126
+ ]
127
+ }
147
128
  ]
148
129
  ]
149
130
  },
150
- "regions": {
151
- "type": "object",
152
- "propertyNames": {
153
- "pattern": "^[a-z][a-z0-9-]*$"
154
- },
155
- "additionalProperties": {
156
- "$ref": "#/$defs/Region"
157
- },
158
- "description": "One entry per body area, keyed by the area's name. Region names may not be 'title', 'subtitle', 'tag', 'auto' or one of the promoted-region words ('left', 'center', 'right', 'top', 'middle', 'bottom'), so a Markdown block's region= option stays unambiguous. Region rules the schema cannot express (an area without a region, a region without an area, a reserved name) are the validate finding opf/layout-region."
159
- },
160
131
  "overflowRegion": {
161
132
  "type": "string",
162
133
  "pattern": "^[a-z][a-z0-9-]*$",
@@ -219,15 +190,128 @@
219
190
  "$ref": "#/$defs/Composition"
220
191
  }
221
192
  },
193
+ "patternProperties": {
194
+ "^x-": {}
195
+ },
196
+ "additionalProperties": false,
222
197
  "$defs": {
223
- "Region": {
198
+ "RegionEntry": {
199
+ "description": "One entry of a regions list: a heading region, a body region or a split.",
200
+ "oneOf": [
201
+ {
202
+ "$ref": "#/$defs/HeadingRegion"
203
+ },
204
+ {
205
+ "$ref": "#/$defs/Region"
206
+ },
207
+ {
208
+ "$ref": "#/$defs/Split"
209
+ }
210
+ ]
211
+ },
212
+ "RegionSize": {
213
+ "oneOf": [
214
+ {
215
+ "type": "number",
216
+ "exclusiveMinimum": 0,
217
+ "maximum": 100
218
+ },
219
+ {
220
+ "const": "auto"
221
+ }
222
+ ],
223
+ "description": "The region's or split's share along its parent's direction: a number above 0 and up to 100 that siblings share in proportion (the gap is taken out first), default 1; or 'auto', the length the content needs at the starting text size (at most half the content box; a split sized auto is as tall as its tallest content, and every row of a column split sized auto is auto too; auto regions with no content take no space). 'auto' is allowed only on an entry of a column; in a row it is the validate finding opf/layout-template. The default for a heading region is 'auto' in a column and 1 in a row.",
224
+ "examples": [
225
+ 1,
226
+ 2,
227
+ "auto"
228
+ ]
229
+ },
230
+ "HeadingRegion": {
231
+ "type": "object",
232
+ "additionalProperties": false,
233
+ "required": [
234
+ "name"
235
+ ],
236
+ "description": "A reserved heading region: 'title' holds the slide's heading group (tag, title and subtitle, stacked) and 'subtitle' takes the subtitle out of it. A heading region takes only a size. At most one of each; a 'subtitle' needs a 'title'.",
237
+ "properties": {
238
+ "name": {
239
+ "type": "string",
240
+ "enum": [
241
+ "title",
242
+ "subtitle"
243
+ ],
244
+ "description": "'title' or 'subtitle'."
245
+ },
246
+ "size": {
247
+ "$ref": "#/$defs/RegionSize"
248
+ }
249
+ }
250
+ },
251
+ "Split": {
224
252
  "type": "object",
225
253
  "additionalProperties": false,
226
254
  "required": [
227
- "accepts"
255
+ "direction",
256
+ "regions"
228
257
  ],
229
- "description": "One body region of a layout: which content it takes and how several blocks share it.",
258
+ "description": "A split nests a list of regions the other way inside one cell of its parent: a row of regions inside a column, or a column inside a row. It has no name; its regions are declared in reading order like the record's own. Splits nest at most three levels (the record's own list is level 1).",
230
259
  "properties": {
260
+ "direction": {
261
+ "type": "string",
262
+ "enum": [
263
+ "row",
264
+ "column"
265
+ ],
266
+ "description": "How the split's 'regions' are laid out: 'row' side by side, 'column' stacked."
267
+ },
268
+ "regions": {
269
+ "type": "array",
270
+ "minItems": 1,
271
+ "maxItems": 12,
272
+ "items": {
273
+ "$ref": "#/$defs/RegionEntry"
274
+ },
275
+ "description": "The split's regions in reading order: 1 to 12 regions and splits."
276
+ },
277
+ "size": {
278
+ "$ref": "#/$defs/RegionSize"
279
+ },
280
+ "anchor": {
281
+ "type": "string",
282
+ "enum": [
283
+ "top",
284
+ "middle",
285
+ "bottom"
286
+ ],
287
+ "description": "Vertical position of the content of every body region under this split, unless the region sets its own. The heading regions 'title' and 'subtitle' never inherit it."
288
+ }
289
+ }
290
+ },
291
+ "Region": {
292
+ "type": "object",
293
+ "additionalProperties": false,
294
+ "description": "One body region of a layout: its name, its share of the space and the rules for which content it takes and how several blocks share it.",
295
+ "properties": {
296
+ "name": {
297
+ "type": "string",
298
+ "pattern": "^[a-z][a-z0-9-]*$",
299
+ "not": {
300
+ "enum": [
301
+ "title",
302
+ "subtitle"
303
+ ]
304
+ },
305
+ "description": "The region's name, lowercase kebab-case, unique across the whole record. A block targets it with 'region': '<name>'. It may not be 'title' (those are heading regions), 'tag', 'auto' or one of the promoted-region words ('left', 'center', 'right', 'top', 'middle', 'bottom'), so a Markdown block's region= option stays unambiguous: the validate finding opf/layout-region.",
306
+ "examples": [
307
+ "main",
308
+ "aside",
309
+ "chart"
310
+ ]
311
+ },
312
+ "size": {
313
+ "$ref": "#/$defs/RegionSize"
314
+ },
231
315
  "accepts": {
232
316
  "type": "array",
233
317
  "minItems": 1,
@@ -248,7 +332,7 @@
248
332
  "group"
249
333
  ]
250
334
  },
251
- "description": "Content kinds the region takes: the body content kinds, and 'group' for a content group of any content. A group is also accepted where every one of its leaf kinds is.",
335
+ "description": "Content kinds the region takes: the body content kinds, and 'group' for a content group of any content. A group is also accepted where every one of its leaf kinds is. Omitted: every body content kind and 'group'.",
252
336
  "examples": [
253
337
  [
254
338
  "text",
@@ -308,7 +392,7 @@
308
392
  "middle",
309
393
  "bottom"
310
394
  ],
311
- "description": "Vertical position of the region's content when it is shorter than the region. Default 'top'."
395
+ "description": "Vertical position of the region's content when it is shorter than the region. Replaces the 'anchor' of the record and of the splits around it. Default: the nearest of those that sets one, else 'top'."
312
396
  },
313
397
  "empty": {
314
398
  "type": "string",
@@ -318,7 +402,10 @@
318
402
  ],
319
403
  "description": "What the region does on a slide that gives it no content: 'collapse' (default) joins its cells to a neighbouring area that shares the full length of one of its edges and is not itself empty; 'keep' leaves the space."
320
404
  }
321
- }
405
+ },
406
+ "required": [
407
+ "name"
408
+ ]
322
409
  },
323
410
  "DesignHints": {
324
411
  "type": "object",
@@ -3819,7 +3819,7 @@
3819
3819
  {
3820
3820
  "source": "https://www.pptx.gallery",
3821
3821
  "layouts": {
3822
- "two-column": { "name": "Two column", "areas": [["title", "title"], ["primary", "secondary"]], "regions": { "primary": { "accepts": ["text"] }, "secondary": { "accepts": ["text"] } } }
3822
+ "two-column": { "name": "Two column", "regions": [{ "name": "title" }, { "direction": "row", "regions": [{ "name": "primary", "accepts": ["text"] }, { "name": "secondary", "accepts": ["text"] }] }] }
3823
3823
  }
3824
3824
  },
3825
3825
  false
@@ -3846,10 +3846,10 @@
3846
3846
  },
3847
3847
  "acme": {
3848
3848
  "source": "pkg:@acme/opf-catalog",
3849
- "layouts": { "hero": { "name": "Hero", "areas": [["title"]] } }
3849
+ "layouts": { "hero": { "name": "Hero", "regions": [{ "name": "title" }] } }
3850
3850
  },
3851
3851
  "custom": {
3852
- "layouts": { "q4-special": { "name": "Q4 special", "areas": [["title"], ["chart"]], "regions": { "chart": { "accepts": ["chart"], "flow": "none" } } } }
3852
+ "layouts": { "q4-special": { "name": "Q4 special", "regions": [{ "name": "title" }, { "name": "chart", "accepts": ["chart"], "flow": "none" }] } }
3853
3853
  }
3854
3854
  }
3855
3855
  ]
@@ -3925,7 +3925,7 @@
3925
3925
  "Composition": {
3926
3926
  "type": "object",
3927
3927
  "additionalProperties": false,
3928
- "description": "Automatic slide and content-group arrangement. Nested content groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions. A v2 layout defines its grid through areas, tracks and regions; its composition supports gap, padding, minFontSize and overflow rather than mode, columns or weights.",
3928
+ "description": "Automatic slide and content-group arrangement. Nested content groups arrange their children independently, inheriting only minFontSize and overflow. Explicit promoted regions retain their positions. A layout defines its grid as one ordered list of regions; its composition supports gap, padding, minFontSize and overflow rather than mode, columns or weights.",
3929
3929
  "properties": {
3930
3930
  "mode": {
3931
3931
  "type": "string",
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { P as Presentation } from './presentation-Dn-fm0iY.js';
1
+ export { P as Presentation } from './presentation-Bwo8Ko6D.js';
2
2
  export { b as CatalogKind } from './catalog-refs-CSHevLn1.js';
3
3
  export { SchemaName } from './schemas.js';
4
4
  export { a as Finding, d as FindingCategory, e as FindingFix, f as FindingFocus, b as FindingLocation, F as FindingReport, c as FindingSeverity, g as FindingSuggestion, J as JsonPatchOperation, V as ValidationIssue } from './finding-l9dlQ2NF.js';
@@ -368,7 +368,21 @@ interface ColorVariant {
368
368
  }
369
369
 
370
370
  /**
371
- * Schema for slide-layout records (OPF 0.19). A layout is a grid template: 'areas' names the cells of a grid using nested row arrays, 'columns' and 'rows' size its tracks, and 'regions' says, for every body area, which content kinds it takes and how several blocks share it. Slide content stays flat: engines bind a slide's blocks to the regions by reading order, role and kind (bindRegions in @openpresentation/opf), a block may pin itself to a region with 'region', and an empty region collapses into a neighbour. Built-in and custom layouts are records of this one schema; a custom layout is embedded under catalogs.custom.layouts or shipped in a catalog. Documents reference a layout from Slide.layout; a slide without a layout, with layout 'auto', or whose layout resolves nowhere composes automatically.
371
+ * One entry of a regions list: a heading region, a body region or a split.
372
+ *
373
+ * This interface was referenced by `Layout`'s JSON-Schema
374
+ * via the `definition` "RegionEntry".
375
+ */
376
+ type RegionEntry = (HeadingRegion | Region | Split);
377
+ /**
378
+ * The region's or split's share along its parent's direction: a number above 0 and up to 100 that siblings share in proportion (the gap is taken out first), default 1; or 'auto', the length the content needs at the starting text size (at most half the content box; a split sized auto is as tall as its tallest content, and every row of a column split sized auto is auto too; auto regions with no content take no space). 'auto' is allowed only on an entry of a column; in a row it is the validate finding opf/layout-template. The default for a heading region is 'auto' in a column and 1 in a row.
379
+ *
380
+ * This interface was referenced by `Layout`'s JSON-Schema
381
+ * via the `definition` "RegionSize".
382
+ */
383
+ type RegionSize = (number | "auto");
384
+ /**
385
+ * Schema for slide-layout records. A layout is one ordered list of regions, declared once, in reading order: 'direction' says whether the record's 'regions' sit side by side (row) or are stacked (column), and each region says which content kinds it takes and how several blocks share it. A split is an entry that nests a second list the other way, which is how a layout gets two dimensions. 'title' and 'subtitle' are reserved heading regions. Engines compile the list into a grid of tracks (the guillotine partition it describes). Slide content stays flat: engines bind a slide's blocks to the regions by reading order, role and kind (bindRegions in @openpresentation/opf), a block may pin itself to a region with 'region', and an empty region collapses into a neighbour. Built-in and custom layouts are records of this one schema; a custom layout is embedded under catalogs.custom.layouts or shipped in a catalog. Documents reference a layout from Slide.layout; a slide without a layout, with layout 'auto', or whose layout resolves nowhere composes automatically.
372
386
  *
373
387
  * A document references a record as a bare id or 'name:id' and resolves it in its own catalogs groups first, then in the catalog the host registered for the group's source; engines never fetch a catalog. A published record file carries '$schema' and 'id'; the copy a document embeds under catalogs.<group>.<kind>.<id> carries neither (the key is the id) and no 'x-*' display metadata.
374
388
  */
@@ -395,32 +409,20 @@ interface Layout {
395
409
  description?: string;
396
410
  design?: DesignHints;
397
411
  /**
398
- * The grid as nested arrays: each inner array is a row, each string is one cell, and a name repeated over adjacent cells spans them; '.' is an empty cell. Cells are lowercase names ([a-z][a-z0-9-]*) or '.', and every row has the same number of cells (at most 12 rows and 12 columns). A name's cells must form one filled rectangle. 'title' and 'subtitle' are heading areas: 'title' holds the slide's heading group (tag, title and subtitle, stacked) and a 'subtitle' area takes the subtitle out of it; they have no regions entry, and a 'subtitle' area needs a 'title' area. A layout with no 'title' area gets an implicit auto row on top for a slide that has headings. Every other name is a body region and needs an entry in 'regions'. The grid rules a schema cannot express are the validate finding opf/layout-template.
399
- *
400
- * @minItems 1
401
- * @maxItems 12
412
+ * How the record's 'regions' are laid out: 'row' places them side by side, left to right in reading order; 'column' stacks them top to bottom. Default 'column'.
402
413
  */
403
- areas: [[string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]]] | [[string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]], [string, ...(string)[]]];
414
+ direction?: ("row" | "column");
404
415
  /**
405
- * Relative column widths, one per cell of a row; the columns share the content width in proportion, separated by the gap. Omitted: all 1. Columns are numbers only.
406
- *
407
- * @minItems 1
408
- * @maxItems 12
416
+ * Vertical position of the content of every body region when it is shorter than the region. A split's 'anchor' replaces it for the regions under that split, and a region's own 'anchor' replaces both. Only 'anchor' is inherited, and only by body regions: the heading regions 'title' and 'subtitle' never take it, and the other region rules stay per region. Default 'top'.
409
417
  */
410
- columns?: [number] | [number, number] | [number, number, number] | [number, number, number, number] | [number, number, number, number, number] | [number, number, number, number, number, number] | [number, number, number, number, number, number, number] | [number, number, number, number, number, number, number, number] | [number, number, number, number, number, number, number, number, number] | [number, number, number, number, number, number, number, number, number, number] | [number, number, number, number, number, number, number, number, number, number, number] | [number, number, number, number, number, number, number, number, number, number, number, number];
418
+ anchor?: ("top" | "middle" | "bottom");
411
419
  /**
412
- * Relative row heights, one per string of 'areas'. 'auto' is the height the row's content needs at the starting text size (at most half the content box; areas that span several rows do not size it); the numeric rows share the rest in proportion. An auto row whose areas are all empty has no height. Omitted: all 1.
420
+ * The record's regions in reading order: 1 to 12 entries, each a region ({ name, size?, ...rules }) or a split ({ direction, regions, size?, anchor? }). Every region is declared once, here, with its content rules; a block can target a body region with 'region': '<name>'. Names are unique across the whole record. 'size' is a number above 0 and up to 100 (default 1) that siblings share in proportion, separated by the gap; 'auto' is the height the content needs, allowed only in a column. 'title' and 'subtitle' are heading regions that take only a size (default auto in a column, 1 in a row): 'title' holds the slide's heading group (tag, title and subtitle, stacked) and a 'subtitle' region takes the subtitle out of it, and a 'subtitle' needs a 'title'. A record with no 'title' region gets an implicit auto row on top for a slide that has headings. Splits nest at most three levels (the record's own list is level 1). Rules the schema cannot express (a reserved or repeated name, a 'subtitle' without a 'title', 'auto' outside a column, nesting too deep, more than 12 rows or columns once compiled) are the validate findings opf/layout-template and opf/layout-region.
413
421
  *
414
422
  * @minItems 1
415
423
  * @maxItems 12
416
424
  */
417
- rows?: [(number | "auto")] | [(number | "auto"), (number | "auto")] | [(number | "auto"), (number | "auto"), (number | "auto")] | [(number | "auto"), (number | "auto"), (number | "auto"), (number | "auto")] | [(number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto")] | [(number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto")] | [(number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto")] | [(number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto")] | [(number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto")] | [(number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto")] | [(number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto")] | [(number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto"), (number | "auto")];
418
- /**
419
- * One entry per body area, keyed by the area's name. Region names may not be 'title', 'subtitle', 'tag', 'auto' or one of the promoted-region words ('left', 'center', 'right', 'top', 'middle', 'bottom'), so a Markdown block's region= option stays unambiguous. Region rules the schema cannot express (an area without a region, a region without an area, a reserved name) are the validate finding opf/layout-region.
420
- */
421
- regions?: {
422
- [k: string]: Region;
423
- };
425
+ regions: [RegionEntry] | [RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry];
424
426
  /**
425
427
  * The region where content that no region accepts goes, whatever its 'accepts', while it has room; content beyond every region's room is drawn there too, with the warning opf/layout-unplaced. Omitted: the first primary region (in reading order) whose flow is not 'none'.
426
428
  */
@@ -448,6 +450,10 @@ interface Layout {
448
450
  [k: string]: unknown;
449
451
  };
450
452
  composition?: Composition;
453
+ /**
454
+ * This interface was referenced by `Layout`'s JSON-Schema definition
455
+ * via the `patternProperty` "^x-".
456
+ */
451
457
  [k: string]: unknown;
452
458
  }
453
459
  /**
@@ -488,18 +494,36 @@ interface DesignHints {
488
494
  mirror?: boolean;
489
495
  }
490
496
  /**
491
- * One body region of a layout: which content it takes and how several blocks share it.
497
+ * A reserved heading region: 'title' holds the slide's heading group (tag, title and subtitle, stacked) and 'subtitle' takes the subtitle out of it. A heading region takes only a size. At most one of each; a 'subtitle' needs a 'title'.
498
+ *
499
+ * This interface was referenced by `Layout`'s JSON-Schema
500
+ * via the `definition` "HeadingRegion".
501
+ */
502
+ interface HeadingRegion {
503
+ /**
504
+ * 'title' or 'subtitle'.
505
+ */
506
+ name: ("title" | "subtitle");
507
+ size?: RegionSize;
508
+ }
509
+ /**
510
+ * One body region of a layout: its name, its share of the space and the rules for which content it takes and how several blocks share it.
492
511
  *
493
512
  * This interface was referenced by `Layout`'s JSON-Schema
494
513
  * via the `definition` "Region".
495
514
  */
496
515
  interface Region {
497
516
  /**
498
- * Content kinds the region takes: the body content kinds, and 'group' for a content group of any content. A group is also accepted where every one of its leaf kinds is.
517
+ * The region's name, lowercase kebab-case, unique across the whole record. A block targets it with 'region': '<name>'. It may not be 'title' (those are heading regions), 'tag', 'auto' or one of the promoted-region words ('left', 'center', 'right', 'top', 'middle', 'bottom'), so a Markdown block's region= option stays unambiguous: the validate finding opf/layout-region.
518
+ */
519
+ name: string;
520
+ size?: RegionSize;
521
+ /**
522
+ * Content kinds the region takes: the body content kinds, and 'group' for a content group of any content. A group is also accepted where every one of its leaf kinds is. Omitted: every body content kind and 'group'.
499
523
  *
500
524
  * @minItems 1
501
525
  */
502
- accepts: [("text" | "list" | "image" | "video" | "chart" | "table" | "code" | "metric" | "quote" | "timeline" | "group"), ...(("text" | "list" | "image" | "video" | "chart" | "table" | "code" | "metric" | "quote" | "timeline" | "group"))[]];
526
+ accepts?: [("text" | "list" | "image" | "video" | "chart" | "table" | "code" | "metric" | "quote" | "timeline" | "group"), ...(("text" | "list" | "image" | "video" | "chart" | "table" | "code" | "metric" | "quote" | "timeline" | "group"))[]];
503
527
  /**
504
528
  * Which content the region wants first. Binding gives a picture (image, video) to a media region first, then primary, secondary, supporting; every other kind to a primary region first, then secondary, supporting, media; of two equal regions the first in reading order fills first. A supporting region receives content only when no primary or secondary region that accepts it has room, or by a pin. Default 'primary'.
505
529
  */
@@ -521,7 +545,7 @@ interface Region {
521
545
  */
522
546
  listColumns?: ("auto" | 1);
523
547
  /**
524
- * Vertical position of the region's content when it is shorter than the region. Default 'top'.
548
+ * Vertical position of the region's content when it is shorter than the region. Replaces the 'anchor' of the record and of the splits around it. Default: the nearest of those that sets one, else 'top'.
525
549
  */
526
550
  anchor?: ("top" | "middle" | "bottom");
527
551
  /**
@@ -529,6 +553,30 @@ interface Region {
529
553
  */
530
554
  empty?: ("collapse" | "keep");
531
555
  }
556
+ /**
557
+ * A split nests a list of regions the other way inside one cell of its parent: a row of regions inside a column, or a column inside a row. It has no name; its regions are declared in reading order like the record's own. Splits nest at most three levels (the record's own list is level 1).
558
+ *
559
+ * This interface was referenced by `Layout`'s JSON-Schema
560
+ * via the `definition` "Split".
561
+ */
562
+ interface Split {
563
+ /**
564
+ * How the split's 'regions' are laid out: 'row' side by side, 'column' stacked.
565
+ */
566
+ direction: ("row" | "column");
567
+ /**
568
+ * The split's regions in reading order: 1 to 12 regions and splits.
569
+ *
570
+ * @minItems 1
571
+ * @maxItems 12
572
+ */
573
+ regions: [RegionEntry] | [RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry] | [RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry, RegionEntry];
574
+ size?: RegionSize;
575
+ /**
576
+ * Vertical position of the content of every body region under this split, unless the region sets its own. The heading regions 'title' and 'subtitle' never inherit it.
577
+ */
578
+ anchor?: ("top" | "middle" | "bottom");
579
+ }
532
580
  /**
533
581
  * Only 'gap', 'padding', 'minFontSize' and 'overflow', with their 0.18 meaning. A template's regions replace composition.mode, columns and weights.
534
582
  */
@@ -1,5 +1,5 @@
1
1
  import { C as Catalog } from './catalog-refs-CSHevLn1.js';
2
- import { T as TextMeasurement } from './composition-qX-igJe5.js';
2
+ import { T as TextMeasurement } from './composition-Daqvi-GV.js';
3
3
  import { c as FindingSeverity, F as FindingReport } from './finding-l9dlQ2NF.js';
4
4
  import { J as JsonPrimitive } from './json-BFSdESOE.js';
5
5
 
@@ -1,8 +1,8 @@
1
1
  import { b as CatalogKind } from './catalog-refs-CSHevLn1.js';
2
2
  import { SchemaName } from './schemas.js';
3
3
  import { a as Finding } from './finding-l9dlQ2NF.js';
4
- import { P as Presentation } from './presentation-Dn-fm0iY.js';
5
- import { b as ValidationThresholds, c as ValidationRuleInfo, V as ValidationReport, a as ValidateOptions } from './validation-types-CzPKoKWo.js';
4
+ import { P as Presentation } from './presentation-Bwo8Ko6D.js';
5
+ import { b as ValidationThresholds, c as ValidationRuleInfo, V as ValidationReport, a as ValidateOptions } from './validation-types-JW8e06ee.js';
6
6
 
7
7
  /**
8
8
  * RR-78: the version of the catalog record schemas (spec/schemas/<kind>.schema.json) this core reads. A catalog package
@@ -10,7 +10,7 @@ import { b as ValidationThresholds, c as ValidationRuleInfo, V as ValidationRepo
10
10
  * @openpresentation/gallery does); the Node defaults refuse a gallery that targets another one. A record schema change that
11
11
  * old records no longer validate against raises it.
12
12
  */
13
- declare const CATALOG_SCHEMA = 3;
13
+ declare const CATALOG_SCHEMA = 4;
14
14
  /** Kinds of catalog display metadata: published by catalogs for pickers, never referenced by documents. */
15
15
  declare const catalogDisplayKinds: readonly ["chartTypes", "languages", "socialPlatforms"];
16
16
  type CatalogDisplayKind = (typeof catalogDisplayKinds)[number];
@@ -1,9 +1,9 @@
1
- export { D as DEFAULT_VALIDATION_THRESHOLDS, O as OPFValidationError, c as assertValid, d as assertValidCatalogRecord, g as findValidationRule, p as promotedRegionKeys, v as validate, h as validateCatalogRecord, i as validationRules } from './validator-BuAV_HUo.js';
1
+ export { D as DEFAULT_VALIDATION_THRESHOLDS, O as OPFValidationError, c as assertValid, d as assertValidCatalogRecord, g as findValidationRule, p as promotedRegionKeys, v as validate, h as validateCatalogRecord, i as validationRules } from './validator-Dym2zYVK.js';
2
2
  import './finding-l9dlQ2NF.js';
3
- import './presentation-Dn-fm0iY.js';
4
- export { C as Contract, d as ValidateFonts, a as ValidateOptions, e as ValidationCategory, f as ValidationChecks, V as ValidationReport, g as ValidationRuleCost, c as ValidationRuleInfo, b as ValidationThresholds, v as validationCategories } from './validation-types-CzPKoKWo.js';
3
+ import './presentation-Bwo8Ko6D.js';
4
+ export { C as Contract, d as ValidateFonts, a as ValidateOptions, e as ValidationCategory, f as ValidationChecks, V as ValidationReport, g as ValidationRuleCost, c as ValidationRuleInfo, b as ValidationThresholds, v as validationCategories } from './validation-types-JW8e06ee.js';
5
5
  import './catalog-refs-CSHevLn1.js';
6
6
  import './schemas.js';
7
7
  import './json-BFSdESOE.js';
8
- import './composition-qX-igJe5.js';
8
+ import './composition-Daqvi-GV.js';
9
9
  import './chart-data-BnNqgnC-.js';
package/dist/validator.js CHANGED
@@ -1,3 +1,3 @@
1
- export { DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, validate, validateCatalogRecord, validationCategories, validationRules } from './chunk-F6CDJTSE.js';
2
- export { promotedRegionKeys } from './chunk-N3ZPLGK5.js';
3
- import './chunk-BN3A5TVI.js';
1
+ export { DEFAULT_VALIDATION_THRESHOLDS, OPFValidationError, assertValid, assertValidCatalogRecord, findValidationRule, validate, validateCatalogRecord, validationCategories, validationRules } from './chunk-P7S3ORB4.js';
2
+ export { promotedRegionKeys } from './chunk-XRMV2GMB.js';
3
+ import './chunk-F4HFDP6I.js';
package/dist/yaml.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { C as Catalog } from './catalog-refs-CSHevLn1.js';
2
- import { P as Presentation } from './presentation-Dn-fm0iY.js';
3
- import { a as ValidateOptions, V as ValidationReport } from './validation-types-CzPKoKWo.js';
2
+ import { P as Presentation } from './presentation-Bwo8Ko6D.js';
3
+ import { a as ValidateOptions, V as ValidationReport } from './validation-types-JW8e06ee.js';
4
4
  import { a as Finding, b as FindingLocation } from './finding-l9dlQ2NF.js';
5
- import './composition-qX-igJe5.js';
5
+ import './composition-Daqvi-GV.js';
6
6
  import './chart-data-BnNqgnC-.js';
7
7
  import './json-BFSdESOE.js';
8
8