@openpresentation/opf 0.2.2 → 0.3.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.
package/dist/types.d.ts CHANGED
@@ -1,6 +1,7 @@
1
- export { P as Presentation, V as ValidationIssue, a as ValidationResult } from './validator-MwlR2F56.js';
1
+ export { P as Presentation } from './presentation-C8BOK0-5.js';
2
2
  export { CatalogKind } from './catalogs.js';
3
3
  export { SchemaName } from './schemas.js';
4
+ export { ValidationIssue, ValidationResult } from './validator.js';
4
5
 
5
6
  /**
6
7
  * Schema for audience records in the pptx.gallery library. Each record names an audience archetype (e.g. 'executives', 'engineering-team', 'investors') and carries seniority, technical-fluency, decision-power, and attention-budget hints used by AI-driven generation. Audiences are referenced from OPF documents via audience; the engine resolves the reference against catalogs.audiences (inline) → catalogs.audiences.source → the default catalog at https://www.pptx.gallery/audiences. The audience field also accepts free-form strings; this catalog is for engine-aware audience archetypes that carry generation hints.
@@ -1,3 +1,40 @@
1
- import './catalogs.js';
2
- export { O as OPFValidationError, S as SchemaOrKind, V as ValidationIssue, a as ValidationResult, b as assertValid, c as assertValidCatalogRecord, d as assertValidPresentation, v as validate, e as validateCatalogRecord, f as validatePresentation } from './validator-MwlR2F56.js';
3
- import './schemas.js';
1
+ import { CatalogKind } from './catalogs.js';
2
+ import { SchemaName } from './schemas.js';
3
+ import { P as Presentation } from './presentation-C8BOK0-5.js';
4
+
5
+ type JsonPrimitive = string | number | boolean | null;
6
+ type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
7
+ interface JsonObject {
8
+ readonly [key: string]: JsonValue;
9
+ }
10
+ type JsonSchema = JsonObject;
11
+
12
+ interface ValidationIssue {
13
+ path: string;
14
+ message: string;
15
+ keyword: string;
16
+ schemaPath: string;
17
+ params: Record<string, unknown>;
18
+ }
19
+ interface ValidationResult {
20
+ valid: boolean;
21
+ errors: ValidationIssue[];
22
+ /** Advisory issues such as unknown catalog ids. Warnings never affect `valid`. */
23
+ warnings: ValidationIssue[];
24
+ schemaName?: SchemaName;
25
+ catalogKind?: CatalogKind;
26
+ }
27
+ type SchemaOrKind = SchemaName | CatalogKind | JsonSchema;
28
+ declare class OPFValidationError extends Error {
29
+ readonly issues: ValidationIssue[];
30
+ readonly result: ValidationResult;
31
+ constructor(result: ValidationResult);
32
+ }
33
+ declare function validate(value: unknown, schemaOrKind?: SchemaOrKind): ValidationResult;
34
+ declare function assertValid<T = unknown>(value: T, schemaOrKind?: SchemaOrKind): T;
35
+ declare function validatePresentation(value: unknown): ValidationResult;
36
+ declare function assertValidPresentation(value: unknown): asserts value is Presentation;
37
+ declare function validateCatalogRecord(kind: CatalogKind, value: unknown): ValidationResult;
38
+ declare function assertValidCatalogRecord(kind: CatalogKind, value: unknown): void;
39
+
40
+ export { OPFValidationError, type SchemaOrKind, type ValidationIssue, type ValidationResult, assertValid, assertValidCatalogRecord, assertValidPresentation, validate, validateCatalogRecord, validatePresentation };
package/dist/validator.js CHANGED
@@ -16,6 +16,411 @@ var catalogSchemaNames = {
16
16
  fontSchemes: "fontScheme"
17
17
  };
18
18
 
19
+ // src/generated/catalog-ids.ts
20
+ var catalogIds = {
21
+ audiences: [
22
+ "executives",
23
+ "board",
24
+ "engineering-team",
25
+ "investors",
26
+ "customers",
27
+ "sales-team",
28
+ "marketing-team",
29
+ "all-hands",
30
+ "candidates",
31
+ "regulators"
32
+ ],
33
+ purposes: [
34
+ "inform",
35
+ "decide",
36
+ "align",
37
+ "persuade",
38
+ "educate",
39
+ "report",
40
+ "pitch",
41
+ "sell",
42
+ "plan"
43
+ ],
44
+ tones: [
45
+ "formal",
46
+ "casual",
47
+ "inspirational",
48
+ "technical",
49
+ "persuasive",
50
+ "authoritative",
51
+ "conversational"
52
+ ],
53
+ themes: [
54
+ "bold",
55
+ "classic",
56
+ "dark",
57
+ "minimal"
58
+ ],
59
+ layouts: [
60
+ "blank",
61
+ "chart-1x",
62
+ "chart-2x",
63
+ "chart-3x",
64
+ "code-1x",
65
+ "image-1x",
66
+ "image-2x",
67
+ "image-3x",
68
+ "image-bleed",
69
+ "list-1x",
70
+ "list-2x",
71
+ "list-3x",
72
+ "list-4x",
73
+ "list-5x",
74
+ "list-6x",
75
+ "media-1x",
76
+ "number-1x",
77
+ "number-2x",
78
+ "number-3x",
79
+ "number-4x",
80
+ "number-5x",
81
+ "number-6x",
82
+ "table-1x",
83
+ "text-1x",
84
+ "text-2x",
85
+ "text-3x",
86
+ "title",
87
+ "title-subtitle"
88
+ ],
89
+ chartTypes: [
90
+ "100pct-bullet-bar",
91
+ "100pct-bullet-bar-2x",
92
+ "100pct-bullet-bar-3x",
93
+ "100pct-bullet-column",
94
+ "100pct-bullet-column-2x",
95
+ "100pct-bullet-column-3x",
96
+ "100pct-progress-bar",
97
+ "100pct-stacked-area-2x",
98
+ "100pct-stacked-area-3x",
99
+ "100pct-stacked-bar-2x",
100
+ "100pct-stacked-bar-3x",
101
+ "100pct-stacked-column-2x",
102
+ "100pct-stacked-column-3x",
103
+ "area",
104
+ "australia",
105
+ "bar",
106
+ "box-and-whisker",
107
+ "box-and-whisker-2x",
108
+ "box-and-whisker-3x",
109
+ "bullet-bar",
110
+ "bullet-bar-2x",
111
+ "bullet-bar-3x",
112
+ "bullet-column",
113
+ "bullet-column-2x",
114
+ "bullet-column-3x",
115
+ "canada",
116
+ "clustered-bar-2x",
117
+ "clustered-column",
118
+ "column",
119
+ "dot-plot",
120
+ "dot-plot-2x",
121
+ "dot-plot-3x",
122
+ "dot-plot-4x",
123
+ "dot-plot-5x",
124
+ "dot-plot-6x",
125
+ "doughnut",
126
+ "dumbbell",
127
+ "filled-radar",
128
+ "funnel",
129
+ "histogram",
130
+ "line",
131
+ "line-2x",
132
+ "line-3x",
133
+ "line-with-high-low",
134
+ "line-with-high-low-and-markers",
135
+ "line-with-markers",
136
+ "line-with-markers-2x",
137
+ "line-with-markers-3x",
138
+ "pareto",
139
+ "pie",
140
+ "radar",
141
+ "radar-with-markers",
142
+ "scatter",
143
+ "sparkline",
144
+ "sparkline-2x",
145
+ "sparkline-3x",
146
+ "sparkline-4x",
147
+ "sparkline-5x",
148
+ "sparkline-6x",
149
+ "stacked-area-2x",
150
+ "stacked-area-3x",
151
+ "stacked-bar-2x",
152
+ "stacked-bar-3x",
153
+ "stacked-column-2x",
154
+ "stacked-column-3x",
155
+ "stacked-line-2x",
156
+ "stacked-line-3x",
157
+ "stacked-line-with-markers-2x",
158
+ "stacked-line-with-markers-3x",
159
+ "treemap",
160
+ "treemap-2x",
161
+ "treemap-3x",
162
+ "united-kingdom",
163
+ "united-states",
164
+ "waterfall",
165
+ "world"
166
+ ],
167
+ narratives: [
168
+ "problem-solution",
169
+ "scqa",
170
+ "strategic-narrative",
171
+ "golden-circle",
172
+ "conference-talk",
173
+ "transformation-arc",
174
+ "pitch-deck",
175
+ "early-startup-pitch",
176
+ "venture-pitch",
177
+ "persuasive-sales",
178
+ "company-intro",
179
+ "marketing-strategy",
180
+ "product-launch",
181
+ "strategic-advisory",
182
+ "challenge-resolution",
183
+ "project-proposal",
184
+ "failure-analysis",
185
+ "classic-story",
186
+ "business-narrative",
187
+ "rags-to-riches",
188
+ "underdog-victory",
189
+ "survival-story",
190
+ "educate",
191
+ "persuade",
192
+ "reveal",
193
+ "justice",
194
+ "innovation",
195
+ "focus",
196
+ "qbr",
197
+ "business-review",
198
+ "board-meeting",
199
+ "weekly-progress",
200
+ "status-update",
201
+ "performance-review",
202
+ "survey-analysis",
203
+ "trend-analysis",
204
+ "employee-review",
205
+ "performance-improvement-plan",
206
+ "capacity-planning"
207
+ ],
208
+ socialPlatforms: [
209
+ "linkedin",
210
+ "x",
211
+ "github",
212
+ "youtube",
213
+ "instagram",
214
+ "facebook",
215
+ "tiktok",
216
+ "threads",
217
+ "mastodon",
218
+ "bluesky"
219
+ ],
220
+ languages: [
221
+ "afrikaans",
222
+ "albanian",
223
+ "amharic",
224
+ "arabic",
225
+ "armenian",
226
+ "aymara",
227
+ "azerbaijani",
228
+ "bengali",
229
+ "berber-latin",
230
+ "bosnian-latin",
231
+ "bulgarian",
232
+ "catalan",
233
+ "cebuano",
234
+ "chinese-simplified",
235
+ "chinese-traditional",
236
+ "chittagonian",
237
+ "croatian",
238
+ "czech",
239
+ "danish",
240
+ "dutch",
241
+ "english",
242
+ "english-au",
243
+ "english-ca",
244
+ "english-gb",
245
+ "english-in",
246
+ "english-us",
247
+ "estonian",
248
+ "filipino",
249
+ "finnish",
250
+ "french",
251
+ "fulfulde",
252
+ "galician",
253
+ "georgian",
254
+ "german",
255
+ "greek",
256
+ "gujarati",
257
+ "hausa",
258
+ "hebrew",
259
+ "hindi",
260
+ "hungarian",
261
+ "igbo",
262
+ "indonesian",
263
+ "italian",
264
+ "japanese",
265
+ "kannada",
266
+ "kazakh",
267
+ "khmer",
268
+ "kinyarwanda",
269
+ "korean",
270
+ "kurmanji",
271
+ "latvian",
272
+ "lithuanian",
273
+ "macedonian",
274
+ "malagasy",
275
+ "malay",
276
+ "malayalam",
277
+ "maori",
278
+ "marathi",
279
+ "mongolian",
280
+ "nepali",
281
+ "norwegian",
282
+ "odia",
283
+ "oromo",
284
+ "pashto",
285
+ "persian",
286
+ "polish",
287
+ "portuguese",
288
+ "punjabi-gurmukhi",
289
+ "punjabi-shahmukhi",
290
+ "romanian",
291
+ "russian",
292
+ "serbian-cyrillic",
293
+ "serbian-latin",
294
+ "shona",
295
+ "slovak",
296
+ "slovenian",
297
+ "somali",
298
+ "spanish",
299
+ "swahili",
300
+ "swedish",
301
+ "tagalog",
302
+ "tajik",
303
+ "tamil",
304
+ "telugu",
305
+ "thai",
306
+ "turkish",
307
+ "ukrainian",
308
+ "urdu",
309
+ "uzbek-latin",
310
+ "vietnamese-quoc-ngu",
311
+ "xhosa",
312
+ "yoruba",
313
+ "zulu"
314
+ ],
315
+ colorSchemes: [
316
+ "black-and-white",
317
+ "bold-red",
318
+ "boost",
319
+ "burnt-orange",
320
+ "cool-horizon",
321
+ "corporate-blue",
322
+ "deep-purple",
323
+ "forest-green",
324
+ "golden-yellow",
325
+ "luxury",
326
+ "pastel-red",
327
+ "slate-gray",
328
+ "steel-blue",
329
+ "vibes"
330
+ ],
331
+ fontSchemes: [
332
+ "angsana-new",
333
+ "aparajita",
334
+ "aptos",
335
+ "arabic-typesetting",
336
+ "arial",
337
+ "batang",
338
+ "bookman",
339
+ "calibri",
340
+ "century-schoolbook",
341
+ "consolas",
342
+ "constantia",
343
+ "courier-new",
344
+ "daunpenh",
345
+ "david",
346
+ "dilleniaupc",
347
+ "fangsong",
348
+ "garamond",
349
+ "gautami",
350
+ "georgia",
351
+ "gisha",
352
+ "grandview",
353
+ "gungsuh",
354
+ "impact",
355
+ "kalinga",
356
+ "kartika",
357
+ "khmer-ui",
358
+ "latha",
359
+ "lucida-sans",
360
+ "malgun-gothic",
361
+ "mangal",
362
+ "meiryo",
363
+ "microsoft-jhenghei",
364
+ "microsoft-yahei",
365
+ "mingliu",
366
+ "miriam",
367
+ "montserrat",
368
+ "ms-mincho",
369
+ "nirmala-ui",
370
+ "noto-naksh-arabic",
371
+ "noto-nastaliq-urdu",
372
+ "noto-sans",
373
+ "noto-sans-arabic",
374
+ "noto-sans-armenian",
375
+ "noto-sans-bengali",
376
+ "noto-sans-devangari",
377
+ "noto-sans-ethiopic",
378
+ "noto-sans-georgian",
379
+ "noto-sans-gujarati",
380
+ "noto-sans-gurmukhi",
381
+ "noto-sans-hebrew",
382
+ "noto-sans-jp",
383
+ "noto-sans-kannada",
384
+ "noto-sans-khmer",
385
+ "noto-sans-kr",
386
+ "noto-sans-malayalam",
387
+ "noto-sans-mongolian",
388
+ "noto-sans-oriya",
389
+ "noto-sans-sc",
390
+ "noto-sans-tamil",
391
+ "noto-sans-tc",
392
+ "noto-sans-telugu",
393
+ "noto-sans-thai",
394
+ "nyala",
395
+ "open-sans",
396
+ "pmingliu",
397
+ "poppins",
398
+ "pt-serif",
399
+ "raavi",
400
+ "raleway",
401
+ "roboto",
402
+ "rockwell",
403
+ "sakkal-majalla",
404
+ "seaford",
405
+ "segoe-ui",
406
+ "segoe-ui-light",
407
+ "shonar-bangla",
408
+ "shruti",
409
+ "simsun",
410
+ "skeena",
411
+ "sylfaen",
412
+ "tahoma",
413
+ "tenorite",
414
+ "times-new-roman",
415
+ "traditional-arabic",
416
+ "trebuchet-ms",
417
+ "tunga",
418
+ "verdana",
419
+ "vrinda",
420
+ "yu-gothic"
421
+ ]
422
+ };
423
+
19
424
  // src/generated/schemas.ts
20
425
  var presentation = {
21
426
  "$schema": "https://json-schema.org/draft/2020-12/schema",
@@ -6660,6 +7065,126 @@ function validatePresentationSemantics(value) {
6660
7065
  });
6661
7066
  return issues;
6662
7067
  }
7068
+ var bareIdPattern = /^[a-z0-9][a-z0-9-]*$/;
7069
+ function inlineCatalogEntry(context, kind) {
7070
+ const catalogsField = context.document.catalogs;
7071
+ if (!isRecord(catalogsField)) {
7072
+ return void 0;
7073
+ }
7074
+ const entry = catalogsField[kind];
7075
+ return isRecord(entry) ? entry : void 0;
7076
+ }
7077
+ function unknownIdWarning(kind, value, path, context) {
7078
+ if (typeof value !== "string" || !bareIdPattern.test(value)) {
7079
+ return void 0;
7080
+ }
7081
+ if (context) {
7082
+ const entry = inlineCatalogEntry(context, kind);
7083
+ if (entry) {
7084
+ if (Array.isArray(entry.records) && entry.records.some((record) => isRecord(record) && record.id === value)) {
7085
+ return void 0;
7086
+ }
7087
+ if (typeof entry.source === "string") {
7088
+ return void 0;
7089
+ }
7090
+ }
7091
+ }
7092
+ if (catalogIds[kind].includes(value)) {
7093
+ return void 0;
7094
+ }
7095
+ return semanticIssue(path, `unknown ${kind} catalog id '${value}'`, { kind, id: value });
7096
+ }
7097
+ function referenceObjectWarning(kind, value, path, context) {
7098
+ if (typeof value === "string") {
7099
+ return unknownIdWarning(kind, value, path, context);
7100
+ }
7101
+ if (isRecord(value)) {
7102
+ return unknownIdWarning(kind, value.id, pathFor(path, "id"), context);
7103
+ }
7104
+ return void 0;
7105
+ }
7106
+ function pushIfDefined(issues, issue) {
7107
+ if (issue) {
7108
+ issues.push(issue);
7109
+ }
7110
+ }
7111
+ function designReferenceWarnings(design, path, context) {
7112
+ if (!isRecord(design)) {
7113
+ return [];
7114
+ }
7115
+ const issues = [];
7116
+ pushIfDefined(issues, referenceObjectWarning("themes", design.theme, pathFor(path, "theme"), context));
7117
+ pushIfDefined(issues, referenceObjectWarning("colorSchemes", design.colorScheme, pathFor(path, "colorScheme"), context));
7118
+ pushIfDefined(issues, referenceObjectWarning("fontSchemes", design.fontScheme, pathFor(path, "fontScheme"), context));
7119
+ if (isRecord(design.theme)) {
7120
+ const themePath = pathFor(path, "theme");
7121
+ pushIfDefined(issues, referenceObjectWarning("colorSchemes", design.theme.colorScheme, pathFor(themePath, "colorScheme"), context));
7122
+ pushIfDefined(issues, referenceObjectWarning("fontSchemes", design.theme.fontScheme, pathFor(themePath, "fontScheme"), context));
7123
+ }
7124
+ return issues;
7125
+ }
7126
+ function chartTypeWarnings(payload, path, context) {
7127
+ if (!isRecord(payload)) {
7128
+ return [];
7129
+ }
7130
+ const issues = [];
7131
+ if (isRecord(payload.chart)) {
7132
+ pushIfDefined(issues, unknownIdWarning("chartTypes", payload.chart.type, `${pathFor(path, "chart")}/type`, context));
7133
+ }
7134
+ if (Array.isArray(payload.blocks)) {
7135
+ payload.blocks.forEach((block, index) => {
7136
+ issues.push(...chartTypeWarnings(block, `${pathFor(path, "blocks")}/${index}`, context));
7137
+ });
7138
+ }
7139
+ return issues;
7140
+ }
7141
+ function presentationReferenceWarnings(value) {
7142
+ if (!isRecord(value) || !Array.isArray(value.slides)) {
7143
+ return [];
7144
+ }
7145
+ const context = { document: value };
7146
+ const issues = [];
7147
+ if (typeof value.narrative === "string") {
7148
+ pushIfDefined(issues, unknownIdWarning("narratives", value.narrative, "/narrative", context));
7149
+ }
7150
+ issues.push(...designReferenceWarnings(value.design, "/design", context));
7151
+ value.slides.forEach((slide, index) => {
7152
+ if (!isRecord(slide)) {
7153
+ return;
7154
+ }
7155
+ const slidePath = `/slides/${index}`;
7156
+ issues.push(...designReferenceWarnings(slide.design, pathFor(slidePath, "design"), context));
7157
+ issues.push(...chartTypeWarnings(slide, slidePath, context));
7158
+ for (const key of Object.keys(slide)) {
7159
+ if (promotedRegionKeySet.has(key)) {
7160
+ issues.push(...chartTypeWarnings(slide[key], pathFor(slidePath, key), context));
7161
+ }
7162
+ }
7163
+ });
7164
+ return issues;
7165
+ }
7166
+ var catalogCrossLinkFields = {
7167
+ audience: { recommendedNarratives: "narratives", recommendedTones: "tones" },
7168
+ purpose: { recommendedNarratives: "narratives", recommendedTones: "tones" },
7169
+ tone: { recommendedNarratives: "narratives" }
7170
+ };
7171
+ function catalogCrossLinkWarnings(schemaName, value) {
7172
+ const fields = catalogCrossLinkFields[schemaName];
7173
+ if (!fields || !isRecord(value)) {
7174
+ return [];
7175
+ }
7176
+ const issues = [];
7177
+ for (const [field, kind] of Object.entries(fields)) {
7178
+ const links = value[field];
7179
+ if (!Array.isArray(links)) {
7180
+ continue;
7181
+ }
7182
+ links.forEach((link, index) => {
7183
+ pushIfDefined(issues, unknownIdWarning(kind, link, `${pathFor("/", field)}/${index}`));
7184
+ });
7185
+ }
7186
+ return issues;
7187
+ }
6663
7188
  function validateLanguageSemantics(value) {
6664
7189
  if (!isRecord(value)) {
6665
7190
  return [];
@@ -6675,14 +7200,20 @@ function validate(value, schemaOrKind = "presentation") {
6675
7200
  const resolved = resolveValidator(schemaOrKind);
6676
7201
  const valid = resolved.validate(value) === true;
6677
7202
  const errors = valid ? [] : (resolved.validate.errors ?? []).map(toIssue);
7203
+ const warnings = [];
6678
7204
  if (resolved.schemaName === "presentation") {
6679
7205
  errors.push(...validatePresentationSemantics(value));
7206
+ warnings.push(...presentationReferenceWarnings(value));
6680
7207
  } else if (resolved.schemaName === "language") {
6681
7208
  errors.push(...validateLanguageSemantics(value));
6682
7209
  }
7210
+ if (resolved.schemaName) {
7211
+ warnings.push(...catalogCrossLinkWarnings(resolved.schemaName, value));
7212
+ }
6683
7213
  return {
6684
7214
  valid: errors.length === 0,
6685
7215
  errors,
7216
+ warnings,
6686
7217
  schemaName: resolved.schemaName,
6687
7218
  catalogKind: resolved.catalogKind
6688
7219
  };