@patterkit/core 0.4.1 → 0.5.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/index.cjs +20 -0
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +21 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -167,6 +167,12 @@ function validateProject(input) {
|
|
|
167
167
|
const sceneGameIds = /* @__PURE__ */ new Map();
|
|
168
168
|
const jumps = [];
|
|
169
169
|
const castNames = new Set((project.cast ?? []).map((c) => c.name));
|
|
170
|
+
const qualifierIds = new Set((0, import_model.projectQualifiers)(project).map((q) => q.gameId));
|
|
171
|
+
const checkQualifier = (beat, what) => {
|
|
172
|
+
if (beat.kind === "line" && beat.qualifier !== void 0 && !qualifierIds.has(beat.qualifier)) {
|
|
173
|
+
issues.push({ code: "unknown-qualifier", message: `${what} '${beat.id}' qualifier '${beat.qualifier}' is not in the project's qualifiers`, id: beat.id });
|
|
174
|
+
}
|
|
175
|
+
};
|
|
170
176
|
const checkTags = (tags, where, id) => {
|
|
171
177
|
for (const t of tags ?? []) {
|
|
172
178
|
if (typeof t !== "string" || t.length === 0 || /[\s,]/.test(t)) {
|
|
@@ -290,6 +296,7 @@ function validateProject(input) {
|
|
|
290
296
|
if (p.kind === "line" && p.character && !castNames.has(p.character)) {
|
|
291
297
|
issues.push({ code: "unknown-character", message: `prompt '${p.id}' speaker '${p.character}' is not in the project cast`, id: p.id });
|
|
292
298
|
}
|
|
299
|
+
checkQualifier(p, "prompt");
|
|
293
300
|
}
|
|
294
301
|
}
|
|
295
302
|
if (fallbacks > 1) {
|
|
@@ -319,6 +326,7 @@ function validateProject(input) {
|
|
|
319
326
|
id: beat.id
|
|
320
327
|
});
|
|
321
328
|
}
|
|
329
|
+
checkQualifier(beat, "beat");
|
|
322
330
|
}
|
|
323
331
|
if (node.jump) jumps.push({ to: node.jump.to, from: node.id });
|
|
324
332
|
});
|
|
@@ -391,6 +399,18 @@ function validateProjectFile(project, issues) {
|
|
|
391
399
|
if (project.recordingStatuses) {
|
|
392
400
|
checkLadderNames(project.recordingStatuses.map((s) => s.name), "recordingStatuses", issues);
|
|
393
401
|
}
|
|
402
|
+
const seenQualifiers = /* @__PURE__ */ new Set();
|
|
403
|
+
for (const q of project.qualifiers ?? []) {
|
|
404
|
+
if (typeof q.name !== "string" || !q.name.trim()) {
|
|
405
|
+
issues.push({ code: "invalid-qualifier", message: `qualifier '${String(q.gameId)}' has no name` });
|
|
406
|
+
}
|
|
407
|
+
if (typeof q.gameId !== "string" || !(0, import_model2.isValidGameId)(q.gameId)) {
|
|
408
|
+
issues.push({ code: "invalid-qualifier", message: `qualifier '${String(q.name)}' address '${String(q.gameId)}' is invalid (lowercase letters, digits, hyphens; no leading/trailing hyphen)` });
|
|
409
|
+
} else if (seenQualifiers.has(q.gameId)) {
|
|
410
|
+
issues.push({ code: "invalid-qualifier", message: `qualifier address '${q.gameId}' is used more than once` });
|
|
411
|
+
}
|
|
412
|
+
if (typeof q.gameId === "string") seenQualifiers.add(q.gameId);
|
|
413
|
+
}
|
|
394
414
|
for (const [kind, fields] of Object.entries(project.gameDataFields ?? {})) {
|
|
395
415
|
const seen = /* @__PURE__ */ new Set();
|
|
396
416
|
for (const f of fields ?? []) {
|
package/dist/index.d.cts
CHANGED
|
@@ -26,7 +26,7 @@ interface StringifyOptions {
|
|
|
26
26
|
declare function canonicalStringify(value: unknown, opts?: StringifyOptions): string;
|
|
27
27
|
|
|
28
28
|
interface ValidationIssue {
|
|
29
|
-
code: "duplicate-id" | "missing-id" | "malformed-node" | "missing-name" | "empty-scene" | "empty-snippet" | "empty-container" | "dangling-jump" | "jump-into-non-addressable" | "invalid-gameid" | "duplicate-gameid" | "unknown-character" | "invalid-temporary" | "invalid-declaration" | "invalid-status-ladder" | "invalid-locales" | "invalid-captions" | "missing-prompt" | "invalid-prompt" | "multiple-fallbacks" | "choice-can-empty" | "invalid-status-value" | "unknown-doc-class" | "invalid-tag" | "invalid-gamedata-field" | "jump-cycle";
|
|
29
|
+
code: "duplicate-id" | "missing-id" | "malformed-node" | "missing-name" | "empty-scene" | "empty-snippet" | "empty-container" | "dangling-jump" | "jump-into-non-addressable" | "invalid-gameid" | "duplicate-gameid" | "unknown-character" | "unknown-qualifier" | "invalid-qualifier" | "invalid-temporary" | "invalid-declaration" | "invalid-status-ladder" | "invalid-locales" | "invalid-captions" | "missing-prompt" | "invalid-prompt" | "multiple-fallbacks" | "choice-can-empty" | "invalid-status-value" | "unknown-doc-class" | "invalid-tag" | "invalid-gamedata-field" | "jump-cycle";
|
|
30
30
|
message: string;
|
|
31
31
|
/** Id of the offending node/beat, where applicable. */
|
|
32
32
|
id?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ interface StringifyOptions {
|
|
|
26
26
|
declare function canonicalStringify(value: unknown, opts?: StringifyOptions): string;
|
|
27
27
|
|
|
28
28
|
interface ValidationIssue {
|
|
29
|
-
code: "duplicate-id" | "missing-id" | "malformed-node" | "missing-name" | "empty-scene" | "empty-snippet" | "empty-container" | "dangling-jump" | "jump-into-non-addressable" | "invalid-gameid" | "duplicate-gameid" | "unknown-character" | "invalid-temporary" | "invalid-declaration" | "invalid-status-ladder" | "invalid-locales" | "invalid-captions" | "missing-prompt" | "invalid-prompt" | "multiple-fallbacks" | "choice-can-empty" | "invalid-status-value" | "unknown-doc-class" | "invalid-tag" | "invalid-gamedata-field" | "jump-cycle";
|
|
29
|
+
code: "duplicate-id" | "missing-id" | "malformed-node" | "missing-name" | "empty-scene" | "empty-snippet" | "empty-container" | "dangling-jump" | "jump-into-non-addressable" | "invalid-gameid" | "duplicate-gameid" | "unknown-character" | "unknown-qualifier" | "invalid-qualifier" | "invalid-temporary" | "invalid-declaration" | "invalid-status-ladder" | "invalid-locales" | "invalid-captions" | "missing-prompt" | "invalid-prompt" | "multiple-fallbacks" | "choice-can-empty" | "invalid-status-value" | "unknown-doc-class" | "invalid-tag" | "invalid-gamedata-field" | "jump-cycle";
|
|
30
30
|
message: string;
|
|
31
31
|
/** Id of the offending node/beat, where applicable. */
|
|
32
32
|
id?: string;
|
package/dist/index.js
CHANGED
|
@@ -55,7 +55,7 @@ ${indent}}`;
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// src/validate.ts
|
|
58
|
-
import { walkNodes, DEFAULT_WRITING_STATUSES, DEFAULT_RECORDING_STATUSES, DEFAULT_DOCUMENTATION_CLASSES } from "@patterkit/model";
|
|
58
|
+
import { walkNodes, DEFAULT_WRITING_STATUSES, DEFAULT_RECORDING_STATUSES, DEFAULT_DOCUMENTATION_CLASSES, projectQualifiers } from "@patterkit/model";
|
|
59
59
|
import { isValidGameId, effectiveGameId } from "@patterkit/model";
|
|
60
60
|
import { isValidPropertyName, propertyNameify, RESERVED_PROPERTY_NAMES } from "@patterkit/model";
|
|
61
61
|
function choiceLoopsBack(choice, ...targets) {
|
|
@@ -129,6 +129,12 @@ function validateProject(input) {
|
|
|
129
129
|
const sceneGameIds = /* @__PURE__ */ new Map();
|
|
130
130
|
const jumps = [];
|
|
131
131
|
const castNames = new Set((project.cast ?? []).map((c) => c.name));
|
|
132
|
+
const qualifierIds = new Set(projectQualifiers(project).map((q) => q.gameId));
|
|
133
|
+
const checkQualifier = (beat, what) => {
|
|
134
|
+
if (beat.kind === "line" && beat.qualifier !== void 0 && !qualifierIds.has(beat.qualifier)) {
|
|
135
|
+
issues.push({ code: "unknown-qualifier", message: `${what} '${beat.id}' qualifier '${beat.qualifier}' is not in the project's qualifiers`, id: beat.id });
|
|
136
|
+
}
|
|
137
|
+
};
|
|
132
138
|
const checkTags = (tags, where, id) => {
|
|
133
139
|
for (const t of tags ?? []) {
|
|
134
140
|
if (typeof t !== "string" || t.length === 0 || /[\s,]/.test(t)) {
|
|
@@ -252,6 +258,7 @@ function validateProject(input) {
|
|
|
252
258
|
if (p.kind === "line" && p.character && !castNames.has(p.character)) {
|
|
253
259
|
issues.push({ code: "unknown-character", message: `prompt '${p.id}' speaker '${p.character}' is not in the project cast`, id: p.id });
|
|
254
260
|
}
|
|
261
|
+
checkQualifier(p, "prompt");
|
|
255
262
|
}
|
|
256
263
|
}
|
|
257
264
|
if (fallbacks > 1) {
|
|
@@ -281,6 +288,7 @@ function validateProject(input) {
|
|
|
281
288
|
id: beat.id
|
|
282
289
|
});
|
|
283
290
|
}
|
|
291
|
+
checkQualifier(beat, "beat");
|
|
284
292
|
}
|
|
285
293
|
if (node.jump) jumps.push({ to: node.jump.to, from: node.id });
|
|
286
294
|
});
|
|
@@ -353,6 +361,18 @@ function validateProjectFile(project, issues) {
|
|
|
353
361
|
if (project.recordingStatuses) {
|
|
354
362
|
checkLadderNames(project.recordingStatuses.map((s) => s.name), "recordingStatuses", issues);
|
|
355
363
|
}
|
|
364
|
+
const seenQualifiers = /* @__PURE__ */ new Set();
|
|
365
|
+
for (const q of project.qualifiers ?? []) {
|
|
366
|
+
if (typeof q.name !== "string" || !q.name.trim()) {
|
|
367
|
+
issues.push({ code: "invalid-qualifier", message: `qualifier '${String(q.gameId)}' has no name` });
|
|
368
|
+
}
|
|
369
|
+
if (typeof q.gameId !== "string" || !isValidGameId(q.gameId)) {
|
|
370
|
+
issues.push({ code: "invalid-qualifier", message: `qualifier '${String(q.name)}' address '${String(q.gameId)}' is invalid (lowercase letters, digits, hyphens; no leading/trailing hyphen)` });
|
|
371
|
+
} else if (seenQualifiers.has(q.gameId)) {
|
|
372
|
+
issues.push({ code: "invalid-qualifier", message: `qualifier address '${q.gameId}' is used more than once` });
|
|
373
|
+
}
|
|
374
|
+
if (typeof q.gameId === "string") seenQualifiers.add(q.gameId);
|
|
375
|
+
}
|
|
356
376
|
for (const [kind, fields] of Object.entries(project.gameDataFields ?? {})) {
|
|
357
377
|
const seen = /* @__PURE__ */ new Set();
|
|
358
378
|
for (const f of fields ?? []) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patterkit/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Patter core: stable id generation, readable-handle computation, canonical (de)serialisation, and the structural validator.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@patterkit/model": "0.
|
|
37
|
+
"@patterkit/model": "0.11.0",
|
|
38
38
|
"@wildwinter/toolkit": "^0.1.0",
|
|
39
39
|
"json5": "^2.2.3"
|
|
40
40
|
}
|