@openpresentation/opf 0.2.2 → 0.4.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 (90) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +74 -3
  3. package/dist/catalogs-x1oFFQnd.d.ts +1198 -0
  4. package/dist/catalogs.d.ts +2 -32413
  5. package/dist/catalogs.js +1 -18505
  6. package/dist/chunk-75N5I6M4.js +229 -0
  7. package/dist/chunk-EMTMQRX4.js +1007 -0
  8. package/dist/chunk-GCXOU5MZ.js +6515 -0
  9. package/dist/chunk-HJNJHB5H.js +454 -0
  10. package/dist/chunk-OZULJBSG.js +3368 -0
  11. package/dist/chunk-PIQXLBBJ.js +445 -0
  12. package/dist/chunk-SOSOBKQ2.js +145 -0
  13. package/dist/chunk-TWMRZ43O.js +18576 -0
  14. package/dist/composition.d.ts +190 -0
  15. package/dist/composition.js +1 -0
  16. package/dist/data.d.ts +32 -0
  17. package/dist/data.js +1 -0
  18. package/dist/docs.d.ts +17 -0
  19. package/dist/docs.js +120 -0
  20. package/dist/examples.d.ts +43 -0
  21. package/dist/examples.js +44828 -0
  22. package/dist/index.d.ts +7 -4
  23. package/dist/index.js +8 -29015
  24. package/dist/pagination.d.ts +52 -0
  25. package/dist/pagination.js +5 -0
  26. package/dist/{validator-MwlR2F56.d.ts → presentation-BjP4yTQ1.d.ts} +87 -40
  27. package/dist/previews.js +1 -447
  28. package/dist/repo-readme.d.ts +4 -0
  29. package/dist/repo-readme.js +7 -0
  30. package/dist/schemas-C1DxapX2.d.ts +206 -0
  31. package/dist/schemas.d.ts +1 -12373
  32. package/dist/schemas.js +1 -6275
  33. package/dist/spec/README.md +57 -0
  34. package/dist/spec/catalogs/audiences/engineering-team.json +1 -1
  35. package/dist/spec/catalogs/audiences/index.json +1 -1
  36. package/dist/spec/catalogs/chart-types/index.json +1 -1
  37. package/dist/spec/catalogs/color-schemes/index.json +1 -1
  38. package/dist/spec/catalogs/font-schemes/index.json +1 -1
  39. package/dist/spec/catalogs/languages/index.json +1 -1
  40. package/dist/spec/catalogs/layouts/chart-1x.json +4 -1
  41. package/dist/spec/catalogs/layouts/chart-2x.json +5 -1
  42. package/dist/spec/catalogs/layouts/chart-3x.json +5 -1
  43. package/dist/spec/catalogs/layouts/code-1x.json +4 -1
  44. package/dist/spec/catalogs/layouts/extract/canonical.json +94 -21
  45. package/dist/spec/catalogs/layouts/image-1x.json +4 -1
  46. package/dist/spec/catalogs/layouts/image-2x.json +5 -1
  47. package/dist/spec/catalogs/layouts/image-3x.json +5 -1
  48. package/dist/spec/catalogs/layouts/index.json +1 -1
  49. package/dist/spec/catalogs/layouts/list-2x.json +4 -1
  50. package/dist/spec/catalogs/layouts/list-3x.json +4 -1
  51. package/dist/spec/catalogs/layouts/list-4x.json +5 -1
  52. package/dist/spec/catalogs/layouts/list-5x.json +5 -1
  53. package/dist/spec/catalogs/layouts/list-6x.json +5 -1
  54. package/dist/spec/catalogs/layouts/media-1x.json +4 -1
  55. package/dist/spec/catalogs/layouts/number-2x.json +4 -1
  56. package/dist/spec/catalogs/layouts/number-3x.json +4 -1
  57. package/dist/spec/catalogs/layouts/number-4x.json +5 -1
  58. package/dist/spec/catalogs/layouts/number-5x.json +5 -1
  59. package/dist/spec/catalogs/layouts/number-6x.json +5 -1
  60. package/dist/spec/catalogs/layouts/table-1x.json +4 -1
  61. package/dist/spec/catalogs/layouts/text-2x.json +4 -1
  62. package/dist/spec/catalogs/layouts/text-3x.json +4 -1
  63. package/dist/spec/catalogs/narratives/index.json +2 -2
  64. package/dist/spec/catalogs/purposes/index.json +1 -1
  65. package/dist/spec/catalogs/social-platforms/index.json +1 -1
  66. package/dist/spec/catalogs/themes/index.json +1 -1
  67. package/dist/spec/catalogs/tones/casual.json +1 -1
  68. package/dist/spec/catalogs/tones/conversational.json +1 -1
  69. package/dist/spec/catalogs/tones/index.json +1 -1
  70. package/dist/spec/catalogs/tones/technical.json +1 -1
  71. package/dist/spec/openapi.yaml +66 -26
  72. package/dist/spec/previews/layouts/index.json +71 -71
  73. package/dist/spec/schemas/catalog-index.schema.json +53 -0
  74. package/dist/spec/schemas/layout-preview-index.schema.json +54 -0
  75. package/dist/spec/schemas/layout.schema.json +63 -0
  76. package/dist/spec/schemas/opf.schema.json +182 -3
  77. package/dist/spec-files.d.ts +14 -2386
  78. package/dist/spec-files.js +1 -3349
  79. package/dist/types.d.ts +4 -1102
  80. package/dist/types.js +0 -2
  81. package/dist/validator.d.ts +33 -3
  82. package/dist/validator.js +4 -6712
  83. package/package.json +29 -4
  84. package/dist/catalogs.js.map +0 -1
  85. package/dist/index.js.map +0 -1
  86. package/dist/previews.js.map +0 -1
  87. package/dist/schemas.js.map +0 -1
  88. package/dist/spec-files.js.map +0 -1
  89. package/dist/types.js.map +0 -1
  90. package/dist/validator.js.map +0 -1
@@ -22,7 +22,7 @@
22
22
  "If you take one thing from this section, take this."
23
23
  ],
24
24
  "recommendedNarratives": [
25
- "all-hands",
25
+ "focus",
26
26
  "company-intro",
27
27
  "weekly-progress",
28
28
  "performance-review"
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://openpresentation.org/schema/opf-tone-index/v1",
2
+ "$schema": "https://openpresentation.org/schema/opf-catalog-index/v1",
3
3
  "version": "1",
4
4
  "description": "Catalog of presentation tones available in the openpresentation.org catalog. Each entry is a lightweight summary; full tone records (voice cues, anti-patterns, sample phrases) live in the per-id JSON files alongside this index. Tones are referenced from OPF documents via tone.",
5
5
  "records": [
@@ -25,7 +25,7 @@
25
25
  "challenge-resolution",
26
26
  "innovation",
27
27
  "conference-talk",
28
- "engineering-update"
28
+ "status-update"
29
29
  ],
30
30
  "tags": ["technical", "engineering", "research"]
31
31
  }
@@ -1,32 +1,32 @@
1
1
  openapi: 3.1.0
2
2
  info:
3
- title: pptx.dev API
3
+ title: OPF Service API Reference
4
4
  version: "1.0.0"
5
5
  description: |
6
- REST API for parsing, validating, converting, generating, and rendering presentations.
6
+ Reference REST API shape for downstream services that parse, validate, convert, generate, or render presentations with OPF.
7
7
  OPF (Open Presentation Format) is the JSON contract; schema URL: `https://openpresentation.org/schema/opf/v1`.
8
8
 
9
- **Authentication:** Send `Authorization: Bearer <Clerk API key>` on every request, or use a signed-in browser session (Studio). `POST /v1/preview` is anonymous (IP rate-limited) for the OPF Playground.
9
+ OpenPresentation does not host this API. Implementers may use this contract as a starting point for their own hosted services, internal tools, or self-hosted deployments.
10
10
 
11
- Human-readable docs: [pptx.dev/docs](https://www.pptx.dev/docs)
11
+ **Authentication:** Send `Authorization: Bearer <token>` on authenticated requests. `POST /v1/preview` is shown as an optional unauthenticated preview endpoint for services that choose to expose one.
12
12
  contact:
13
- name: pptx.dev
14
- url: https://www.pptx.dev
13
+ name: OpenPresentation
14
+ url: https://openpresentation.org
15
15
  license:
16
16
  name: MIT
17
17
  url: https://opensource.org/licenses/MIT
18
18
 
19
19
  servers:
20
- - url: https://api.pptx.dev
21
- description: Production API
20
+ - url: https://api.example.com
21
+ description: Downstream service endpoint
22
22
  - url: http://localhost:3000/api
23
- description: Local Next.js App Router (`/api` prefix)
23
+ description: Example local development endpoint
24
24
 
25
25
  tags:
26
26
  - name: playground
27
- description: Anonymous OPF playground helpers (IP rate limits)
27
+ description: Optional unauthenticated OPF preview helpers
28
28
  - name: validate
29
- description: OPF schema validation (no billing for validation)
29
+ description: OPF schema validation
30
30
  - name: parse
31
31
  description: Upload and inspect .pptx files
32
32
  - name: convert
@@ -57,18 +57,13 @@ paths:
57
57
  summary: Minimal OPF
58
58
  value:
59
59
  $schema: "https://openpresentation.org/schema/opf/v1"
60
- meta:
61
- title: Example
60
+ name: Example
62
61
  design:
63
- theme: corporate-minimal
62
+ theme: minimal
64
63
  slides:
65
64
  - id: s1
66
- layout: title-slide
67
- elements:
68
- - id: h1
69
- type: text
70
- content:
71
- text: Hello
65
+ layout: title
66
+ title: Hello
72
67
  responses:
73
68
  "200":
74
69
  description: Validation result
@@ -421,7 +416,7 @@ components:
421
416
  bearerAuth:
422
417
  type: http
423
418
  scheme: bearer
424
- description: Clerk user or org API key (`ppx_…`), or session cookie from signed-in Studio user.
419
+ description: Service-defined bearer token.
425
420
 
426
421
  parameters:
427
422
  ParseId:
@@ -479,18 +474,63 @@ components:
479
474
 
480
475
  OpfDocument:
481
476
  type: object
482
- description: OPF v1 document. See https://www.pptx.dev/docs/opf for field reference.
477
+ description: |
478
+ OPF v1 document. See https://openpresentation.org/schema/opf/v1 for the canonical schema.
479
+ This is a loose property sketch for API tooling, not a full mirror of the schema — deck identity
480
+ lives in `name` (there is no `meta` wrapper and no root `title`); slide content is authored via
481
+ content-kind fields (`text`, `items`, `bullets`, `image`, `chart`, `table`, `code`, `metric`,
482
+ `quote`, `timeline`, `blocks`) or promoted region keys, not a generic `elements` array.
483
483
  additionalProperties: true
484
+ required: [slides]
484
485
  properties:
485
486
  $schema:
486
487
  type: string
487
488
  const: "https://openpresentation.org/schema/opf/v1"
488
- meta:
489
+ name:
490
+ type: string
491
+ description: Display name of the presentation (deck identity, not slide content).
492
+ design:
489
493
  type: object
490
494
  additionalProperties: true
491
- design:
495
+ description: Optional design system (theme, colorScheme, fontScheme, dimensions, background, logo, header, footer, etc).
496
+ assets:
497
+ type: object
498
+ additionalProperties: true
499
+ description: Optional reusable asset registry referenced elsewhere via `asset:<id>` strings.
500
+ catalogs:
492
501
  type: object
493
502
  additionalProperties: true
503
+ description: Optional per-kind catalog overrides (inline records and/or a non-default source).
504
+ narrative:
505
+ description: Structured storyline. A bare catalog id string, or an inline narrative object.
506
+ oneOf:
507
+ - type: string
508
+ - type: object
509
+ additionalProperties: true
510
+ audience:
511
+ description: Intended audience(s). A string shorthand, or an array of strings/inline audience objects.
512
+ oneOf:
513
+ - type: string
514
+ - type: array
515
+ items: {}
516
+ purpose:
517
+ description: Primary goal of the presentation. A string shorthand, or an inline purpose object.
518
+ oneOf:
519
+ - type: string
520
+ - type: object
521
+ additionalProperties: true
522
+ tone:
523
+ description: Desired tone. A string shorthand, or an inline tone object.
524
+ oneOf:
525
+ - type: string
526
+ - type: object
527
+ additionalProperties: true
528
+ language:
529
+ description: Presentation language. A BCP-47 tag or catalog id string, or an inline language object.
530
+ oneOf:
531
+ - type: string
532
+ - type: object
533
+ additionalProperties: true
494
534
  slides:
495
535
  type: array
496
536
  items:
@@ -604,7 +644,7 @@ components:
604
644
  type: string
605
645
  filename:
606
646
  type: string
607
- description: Suggested download filename including extension (resolved from meta.filename or title).
647
+ description: Suggested download filename including extension (resolved from the OPF document's `filename` or a slug of its `name`).
608
648
  subtitle:
609
649
  type: string
610
650
  design:
@@ -653,7 +693,7 @@ components:
653
693
  type: string
654
694
  filename:
655
695
  type: string
656
- description: Suggested output filename including extension (from meta.filename or title slug).
696
+ description: Suggested output filename including extension (from the OPF document's `filename` or a slug of its `name`).
657
697
  slideCount:
658
698
  type: integer
659
699
  validationWarnings:
@@ -1,357 +1,357 @@
1
1
  {
2
2
  "$schema": "https://openpresentation.org/schema/opf-layout-preview-index/v1",
3
3
  "version": "1",
4
- "description": "Catalog of static HTML previews for slide layouts. Each preview is a self-contained Tailwind-styled snippet sized to fill a 16:9 thumbnail. Consumers should provide the standard pptx.gallery CSS variables (--background, --foreground, --card, --muted, --muted-foreground, --accent, --border) on a parent element.",
4
+ "description": "Vendored gallery of static HTML previews for slide archetypes (e.g. 'swot-analysis', 'agenda', 'org-chart') — a subject-matter taxonomy for picker thumbnails, distinct from and non-overlapping with the structural layout catalog at spec/catalogs/layouts/ (e.g. 'title', 'chart-2x'); preview ids here do not correspond to layout catalog ids. Each preview is a self-contained Tailwind-styled snippet sized to fill a 16:9 thumbnail. Consumers should provide the standard pptx.gallery CSS variables (--background, --foreground, --card, --muted, --muted-foreground, --accent, --border) on a parent element. Generated from the sibling pptx-gallery repo via packages/javascript/scripts/render-layout-previews.mjs; treat the HTML files here as committed, read-only build output.",
5
5
  "records": [
6
6
  {
7
7
  "id": "action-plan",
8
8
  "file": "action-plan.html",
9
- "bytes": 1940
9
+ "bytes": 1941
10
10
  },
11
11
  {
12
12
  "id": "agenda",
13
13
  "file": "agenda.html",
14
- "bytes": 1196
14
+ "bytes": 1197
15
15
  },
16
16
  {
17
17
  "id": "appendix-index",
18
18
  "file": "appendix-index.html",
19
- "bytes": 1678
19
+ "bytes": 1679
20
20
  },
21
21
  {
22
22
  "id": "architecture-stack",
23
23
  "file": "architecture-stack.html",
24
- "bytes": 1656
24
+ "bytes": 1657
25
25
  },
26
26
  {
27
27
  "id": "assumptions-dependencies",
28
28
  "file": "assumptions-dependencies.html",
29
- "bytes": 1977
29
+ "bytes": 1978
30
30
  },
31
31
  {
32
32
  "id": "before-after",
33
33
  "file": "before-after.html",
34
- "bytes": 475
34
+ "bytes": 476
35
35
  },
36
36
  {
37
37
  "id": "benchmark-target-table",
38
38
  "file": "benchmark-target-table.html",
39
- "bytes": 1984
39
+ "bytes": 1985
40
40
  },
41
41
  {
42
42
  "id": "bullet-list",
43
43
  "file": "bullet-list.html",
44
- "bytes": 1028
44
+ "bytes": 1029
45
45
  },
46
46
  {
47
47
  "id": "business-model-canvas",
48
48
  "file": "business-model-canvas.html",
49
- "bytes": 2734
49
+ "bytes": 2735
50
50
  },
51
51
  {
52
52
  "id": "capability-map",
53
53
  "file": "capability-map.html",
54
- "bytes": 2343
54
+ "bytes": 2344
55
55
  },
56
56
  {
57
57
  "id": "case-study",
58
58
  "file": "case-study.html",
59
- "bytes": 1476
59
+ "bytes": 1477
60
60
  },
61
61
  {
62
62
  "id": "chapter-recap",
63
63
  "file": "chapter-recap.html",
64
- "bytes": 1682
64
+ "bytes": 1683
65
65
  },
66
66
  {
67
67
  "id": "circular-lifecycle",
68
68
  "file": "circular-lifecycle.html",
69
- "bytes": 1796
69
+ "bytes": 1797
70
70
  },
71
71
  {
72
72
  "id": "comparison",
73
73
  "file": "comparison.html",
74
- "bytes": 1304
74
+ "bytes": 1305
75
75
  },
76
76
  {
77
77
  "id": "competitive-landscape",
78
78
  "file": "competitive-landscape.html",
79
- "bytes": 1377
79
+ "bytes": 1378
80
80
  },
81
81
  {
82
82
  "id": "customer-journey",
83
83
  "file": "customer-journey.html",
84
- "bytes": 2024
84
+ "bytes": 2025
85
85
  },
86
86
  {
87
87
  "id": "customer-logos",
88
88
  "file": "customer-logos.html",
89
- "bytes": 2222
89
+ "bytes": 2223
90
90
  },
91
91
  {
92
92
  "id": "dashboard",
93
93
  "file": "dashboard.html",
94
- "bytes": 1582
94
+ "bytes": 1583
95
95
  },
96
96
  {
97
97
  "id": "data-visualization",
98
98
  "file": "data-visualization.html",
99
- "bytes": 506
99
+ "bytes": 507
100
100
  },
101
101
  {
102
102
  "id": "decision-tree",
103
103
  "file": "decision-tree.html",
104
- "bytes": 1869
104
+ "bytes": 1870
105
105
  },
106
106
  {
107
107
  "id": "detailed-data-table",
108
108
  "file": "detailed-data-table.html",
109
- "bytes": 4158
109
+ "bytes": 4159
110
110
  },
111
111
  {
112
112
  "id": "ecosystem-map",
113
113
  "file": "ecosystem-map.html",
114
- "bytes": 2026
114
+ "bytes": 2027
115
115
  },
116
116
  {
117
117
  "id": "executive-decision",
118
118
  "file": "executive-decision.html",
119
- "bytes": 1229
119
+ "bytes": 1230
120
120
  },
121
121
  {
122
122
  "id": "executive-summary",
123
123
  "file": "executive-summary.html",
124
- "bytes": 1699
124
+ "bytes": 1700
125
125
  },
126
126
  {
127
127
  "id": "faq",
128
128
  "file": "faq.html",
129
- "bytes": 530
129
+ "bytes": 531
130
130
  },
131
131
  {
132
132
  "id": "feature-comparison-matrix",
133
133
  "file": "feature-comparison-matrix.html",
134
- "bytes": 3035
134
+ "bytes": 3036
135
135
  },
136
136
  {
137
137
  "id": "forecast-scenario",
138
138
  "file": "forecast-scenario.html",
139
- "bytes": 997
139
+ "bytes": 998
140
140
  },
141
141
  {
142
142
  "id": "funnel-pyramid",
143
143
  "file": "funnel-pyramid.html",
144
- "bytes": 462
144
+ "bytes": 463
145
145
  },
146
146
  {
147
147
  "id": "gantt-project-plan",
148
148
  "file": "gantt-project-plan.html",
149
- "bytes": 1912
149
+ "bytes": 1913
150
150
  },
151
151
  {
152
152
  "id": "geographic-map",
153
153
  "file": "geographic-map.html",
154
- "bytes": 1388
154
+ "bytes": 1389
155
155
  },
156
156
  {
157
157
  "id": "heatmap-cohort",
158
158
  "file": "heatmap-cohort.html",
159
- "bytes": 2763
159
+ "bytes": 2764
160
160
  },
161
161
  {
162
162
  "id": "hub-and-spoke",
163
163
  "file": "hub-and-spoke.html",
164
- "bytes": 2331
164
+ "bytes": 2332
165
165
  },
166
166
  {
167
167
  "id": "icon-grid",
168
168
  "file": "icon-grid.html",
169
- "bytes": 1125
169
+ "bytes": 1126
170
170
  },
171
171
  {
172
172
  "id": "image-focus",
173
173
  "file": "image-focus.html",
174
- "bytes": 230
174
+ "bytes": 231
175
175
  },
176
176
  {
177
177
  "id": "key-takeaway",
178
178
  "file": "key-takeaway.html",
179
- "bytes": 393
179
+ "bytes": 394
180
180
  },
181
181
  {
182
182
  "id": "kpi-scorecard",
183
183
  "file": "kpi-scorecard.html",
184
- "bytes": 1633
184
+ "bytes": 1634
185
185
  },
186
186
  {
187
187
  "id": "logic-tree",
188
188
  "file": "logic-tree.html",
189
- "bytes": 1531
189
+ "bytes": 1532
190
190
  },
191
191
  {
192
192
  "id": "market-size",
193
193
  "file": "market-size.html",
194
- "bytes": 1100
194
+ "bytes": 1101
195
195
  },
196
196
  {
197
197
  "id": "matrix-quadrant",
198
198
  "file": "matrix-quadrant.html",
199
- "bytes": 644
199
+ "bytes": 645
200
200
  },
201
201
  {
202
202
  "id": "network-dependency-map",
203
203
  "file": "network-dependency-map.html",
204
- "bytes": 1816
204
+ "bytes": 1817
205
205
  },
206
206
  {
207
207
  "id": "one-column-explainer",
208
208
  "file": "one-column-explainer.html",
209
- "bytes": 1263
209
+ "bytes": 1264
210
210
  },
211
211
  {
212
212
  "id": "org-chart",
213
213
  "file": "org-chart.html",
214
- "bytes": 2565
214
+ "bytes": 2566
215
215
  },
216
216
  {
217
217
  "id": "persona-grid",
218
218
  "file": "persona-grid.html",
219
- "bytes": 1770
219
+ "bytes": 1771
220
220
  },
221
221
  {
222
222
  "id": "photo-grid",
223
223
  "file": "photo-grid.html",
224
- "bytes": 254
224
+ "bytes": 255
225
225
  },
226
226
  {
227
227
  "id": "pricing-table",
228
228
  "file": "pricing-table.html",
229
- "bytes": 2171
229
+ "bytes": 2172
230
230
  },
231
231
  {
232
232
  "id": "process-flow",
233
233
  "file": "process-flow.html",
234
- "bytes": 1057
234
+ "bytes": 1058
235
235
  },
236
236
  {
237
237
  "id": "product-feature",
238
238
  "file": "product-feature.html",
239
- "bytes": 405
239
+ "bytes": 406
240
240
  },
241
241
  {
242
242
  "id": "pros-cons",
243
243
  "file": "pros-cons.html",
244
- "bytes": 1846
244
+ "bytes": 1847
245
245
  },
246
246
  {
247
247
  "id": "qa-discussion",
248
248
  "file": "qa-discussion.html",
249
- "bytes": 945
249
+ "bytes": 946
250
250
  },
251
251
  {
252
252
  "id": "quote-highlight",
253
253
  "file": "quote-highlight.html",
254
- "bytes": 373
254
+ "bytes": 374
255
255
  },
256
256
  {
257
257
  "id": "raci-matrix",
258
258
  "file": "raci-matrix.html",
259
- "bytes": 4854
259
+ "bytes": 4855
260
260
  },
261
261
  {
262
262
  "id": "risk-heatmap",
263
263
  "file": "risk-heatmap.html",
264
- "bytes": 1264
264
+ "bytes": 1265
265
265
  },
266
266
  {
267
267
  "id": "roadmap",
268
268
  "file": "roadmap.html",
269
- "bytes": 819
269
+ "bytes": 820
270
270
  },
271
271
  {
272
272
  "id": "screenshot-walkthrough",
273
273
  "file": "screenshot-walkthrough.html",
274
- "bytes": 1808
274
+ "bytes": 1809
275
275
  },
276
276
  {
277
277
  "id": "section-divider",
278
278
  "file": "section-divider.html",
279
- "bytes": 255
279
+ "bytes": 256
280
280
  },
281
281
  {
282
282
  "id": "single-message-statement",
283
283
  "file": "single-message-statement.html",
284
- "bytes": 419
284
+ "bytes": 420
285
285
  },
286
286
  {
287
287
  "id": "stats-metrics",
288
288
  "file": "stats-metrics.html",
289
- "bytes": 570
289
+ "bytes": 571
290
290
  },
291
291
  {
292
292
  "id": "status-rag",
293
293
  "file": "status-rag.html",
294
- "bytes": 1678
294
+ "bytes": 1679
295
295
  },
296
296
  {
297
297
  "id": "swimlane-process",
298
298
  "file": "swimlane-process.html",
299
- "bytes": 1815
299
+ "bytes": 1816
300
300
  },
301
301
  {
302
302
  "id": "swot-analysis",
303
303
  "file": "swot-analysis.html",
304
- "bytes": 1112
304
+ "bytes": 1113
305
305
  },
306
306
  {
307
307
  "id": "team-bio",
308
308
  "file": "team-bio.html",
309
- "bytes": 1527
309
+ "bytes": 1528
310
310
  },
311
311
  {
312
312
  "id": "testimonial-grid",
313
313
  "file": "testimonial-grid.html",
314
- "bytes": 1374
314
+ "bytes": 1375
315
315
  },
316
316
  {
317
317
  "id": "thank-you-cta",
318
318
  "file": "thank-you-cta.html",
319
- "bytes": 314
319
+ "bytes": 315
320
320
  },
321
321
  {
322
322
  "id": "three-column",
323
323
  "file": "three-column.html",
324
- "bytes": 857
324
+ "bytes": 858
325
325
  },
326
326
  {
327
327
  "id": "timeline",
328
328
  "file": "timeline.html",
329
- "bytes": 1189
329
+ "bytes": 1190
330
330
  },
331
331
  {
332
332
  "id": "title-slide",
333
333
  "file": "title-slide.html",
334
- "bytes": 279
334
+ "bytes": 280
335
335
  },
336
336
  {
337
337
  "id": "two-column",
338
338
  "file": "two-column.html",
339
- "bytes": 600
339
+ "bytes": 601
340
340
  },
341
341
  {
342
342
  "id": "venn-overlap",
343
343
  "file": "venn-overlap.html",
344
- "bytes": 943
344
+ "bytes": 944
345
345
  },
346
346
  {
347
347
  "id": "waterfall-bridge",
348
348
  "file": "waterfall-bridge.html",
349
- "bytes": 1068
349
+ "bytes": 1069
350
350
  },
351
351
  {
352
352
  "id": "wheel-radial",
353
353
  "file": "wheel-radial.html",
354
- "bytes": 2159
354
+ "bytes": 2160
355
355
  }
356
356
  ]
357
357
  }
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://openpresentation.org/schema/opf-catalog-index/v1",
4
+ "title": "Catalog Index",
5
+ "description": "Generic shape shared by every `spec/catalogs/<kind>/index.json` file in the OPF repo. An index is a lightweight, ordered summary of the full-record JSON files that live alongside it: each entry names the record's stable id, a human-readable name, and the record's filename, plus whatever extra summary fields are useful for picker UIs (e.g. `summary`, `tags`, `bcp47`, `durationRange`). This schema describes the repo-internal catalog index files themselves, not OPF documents or individual catalog records — it is not part of the OPF document contract and is intentionally excluded from the package's published/typed schema surface.",
6
+ "type": "object",
7
+ "required": ["$schema", "version", "description", "records"],
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "$schema": {
11
+ "type": "string",
12
+ "const": "https://openpresentation.org/schema/opf-catalog-index/v1"
13
+ },
14
+ "version": {
15
+ "type": "string",
16
+ "description": "Index format version, as a string.",
17
+ "examples": ["1"]
18
+ },
19
+ "description": {
20
+ "type": "string",
21
+ "description": "Human-readable description of what this catalog kind holds and how entries are ordered."
22
+ },
23
+ "records": {
24
+ "type": "array",
25
+ "description": "Ordered list of lightweight record summaries. Order defines the catalog's canonical/display order; full record data lives in the sibling JSON file named by `file`.",
26
+ "items": { "$ref": "#/$defs/IndexRecord" }
27
+ }
28
+ },
29
+ "$defs": {
30
+ "IndexRecord": {
31
+ "type": "object",
32
+ "description": "Lightweight summary of one catalog record. Additional per-kind fields (e.g. `summary`, `tags`, `bcp47`, `durationRange`, `group`, `label`) are allowed and vary by catalog kind.",
33
+ "required": ["id", "name", "file"],
34
+ "additionalProperties": true,
35
+ "properties": {
36
+ "id": {
37
+ "type": "string",
38
+ "description": "Stable identifier, matching the `id` field inside the record file named by `file`.",
39
+ "pattern": "^[a-z][a-z0-9-]*$"
40
+ },
41
+ "name": {
42
+ "type": "string",
43
+ "description": "Human-readable name shown in pickers."
44
+ },
45
+ "file": {
46
+ "type": "string",
47
+ "description": "Filename of the full record, relative to this index file's directory.",
48
+ "pattern": "^[^/]+\\.json$"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }