@spyglassmc/json 0.3.3 → 0.3.4
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/lib/index.d.ts +1 -2
- package/lib/index.js +2 -2
- package/lib/parser/entry.d.ts +0 -1
- package/lib/parser/entry.js +14 -23
- package/package.json +3 -3
- package/lib/checker/JsonChecker.d.ts +0 -8
- package/lib/checker/JsonChecker.js +0 -2
- package/lib/checker/index.d.ts +0 -3
- package/lib/checker/index.js +0 -3
- package/lib/checker/primitives/boolean.d.ts +0 -4
- package/lib/checker/primitives/boolean.js +0 -9
- package/lib/checker/primitives/index.d.ts +0 -7
- package/lib/checker/primitives/index.js +0 -7
- package/lib/checker/primitives/list.d.ts +0 -10
- package/lib/checker/primitives/list.js +0 -48
- package/lib/checker/primitives/number.d.ts +0 -6
- package/lib/checker/primitives/number.js +0 -31
- package/lib/checker/primitives/object.d.ts +0 -34
- package/lib/checker/primitives/object.js +0 -201
- package/lib/checker/primitives/string.d.ts +0 -12
- package/lib/checker/primitives/string.js +0 -51
- package/lib/checker/primitives/util.d.ts +0 -15
- package/lib/checker/primitives/util.js +0 -73
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
export * as checker from './checker/index.js';
|
|
1
|
+
import * as core from '@spyglassmc/core';
|
|
3
2
|
export * as colorizer from './colorizer/index.js';
|
|
4
3
|
export * as completer from './completer/index.js';
|
|
5
4
|
export * as formatter from './formatter/index.js';
|
package/lib/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* istanbul ignore file */
|
|
2
|
+
import * as core from '@spyglassmc/core';
|
|
2
3
|
import * as colorizer from './colorizer/index.js';
|
|
3
4
|
import * as completer from './completer/index.js';
|
|
4
5
|
import * as formatter from './formatter/index.js';
|
|
5
6
|
import * as parser from './parser/index.js';
|
|
6
|
-
export * as checker from './checker/index.js';
|
|
7
7
|
export * as colorizer from './colorizer/index.js';
|
|
8
8
|
export * as completer from './completer/index.js';
|
|
9
9
|
export * as formatter from './formatter/index.js';
|
|
@@ -13,7 +13,7 @@ export const initialize = ({ meta }) => {
|
|
|
13
13
|
meta.registerLanguage('json', {
|
|
14
14
|
extensions: ['.json', '.mcmeta'],
|
|
15
15
|
triggerCharacters: completer.JsonTriggerCharacters,
|
|
16
|
-
parser: parser.entry,
|
|
16
|
+
parser: core.dumpErrors(parser.entry),
|
|
17
17
|
});
|
|
18
18
|
meta.registerParser('json:entry', parser.entry);
|
|
19
19
|
colorizer.register(meta);
|
package/lib/parser/entry.d.ts
CHANGED
package/lib/parser/entry.js
CHANGED
|
@@ -18,27 +18,18 @@ const LegalNumberStart = new Set([
|
|
|
18
18
|
'9',
|
|
19
19
|
'-',
|
|
20
20
|
]);
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
{ parser: string },
|
|
36
|
-
])(src, ctx);
|
|
37
|
-
if (dumpErrors) {
|
|
38
|
-
ctx.err.dump();
|
|
39
|
-
}
|
|
40
|
-
return result;
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
export const entry = json(true);
|
|
21
|
+
export const entry = (src, ctx) => core.select([
|
|
22
|
+
{ predicate: (src) => src.tryPeek('['), parser: array },
|
|
23
|
+
{
|
|
24
|
+
predicate: (src) => src.tryPeek('false') || src.tryPeek('true'),
|
|
25
|
+
parser: boolean,
|
|
26
|
+
},
|
|
27
|
+
{ predicate: (src) => src.tryPeek('null'), parser: null_ },
|
|
28
|
+
{
|
|
29
|
+
predicate: (src) => LegalNumberStart.has(src.peek()),
|
|
30
|
+
parser: number,
|
|
31
|
+
},
|
|
32
|
+
{ predicate: (src) => src.tryPeek('{'), parser: object },
|
|
33
|
+
{ parser: string },
|
|
34
|
+
])(src, ctx);
|
|
44
35
|
//# sourceMappingURL=entry.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spyglassmc/json",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"url": "https://github.com/SpyglassMC/Spyglass/issues"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@spyglassmc/core": "0.4.
|
|
29
|
-
"@spyglassmc/locales": "0.3.
|
|
28
|
+
"@spyglassmc/core": "0.4.3",
|
|
29
|
+
"@spyglassmc/locales": "0.3.3"
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { CheckerContext } from '@spyglassmc/core';
|
|
2
|
-
import type { JsonNode } from '../node/index.js';
|
|
3
|
-
export interface JsonCheckerContext extends CheckerContext {
|
|
4
|
-
context: string;
|
|
5
|
-
depth?: number;
|
|
6
|
-
}
|
|
7
|
-
export type JsonChecker = (node: JsonNode, ctx: JsonCheckerContext) => void;
|
|
8
|
-
//# sourceMappingURL=JsonChecker.d.ts.map
|
package/lib/checker/index.d.ts
DELETED
package/lib/checker/index.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { localize } from '@spyglassmc/locales';
|
|
2
|
-
import { JsonBooleanNode } from '../../node/index.js';
|
|
3
|
-
export function boolean(node, ctx) {
|
|
4
|
-
node.expectation = [{ type: 'json:boolean', typedoc: 'Boolean' }];
|
|
5
|
-
if (!JsonBooleanNode.is(node)) {
|
|
6
|
-
ctx.err.report(localize('expected', localize('boolean')), node);
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=boolean.js.map
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import type { JsonNode } from '../../node/index.js';
|
|
2
|
-
import type { JsonChecker, JsonCheckerContext } from '../JsonChecker.js';
|
|
3
|
-
export declare function listOf(checker: JsonChecker): JsonChecker;
|
|
4
|
-
type UniqueListOptions = {
|
|
5
|
-
items?: (node: JsonNode) => [string | undefined, JsonNode];
|
|
6
|
-
report?: (node: JsonNode, ctx: JsonCheckerContext) => unknown;
|
|
7
|
-
};
|
|
8
|
-
export declare function uniqueListOf(checker: JsonChecker, options?: UniqueListOptions): JsonChecker;
|
|
9
|
-
export {};
|
|
10
|
-
//# sourceMappingURL=list.d.ts.map
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { localize } from '@spyglassmc/locales';
|
|
2
|
-
import { JsonArrayNode, JsonStringNode } from '../../node/index.js';
|
|
3
|
-
import { expectation } from './util.js';
|
|
4
|
-
export function listOf(checker) {
|
|
5
|
-
return (node, ctx) => {
|
|
6
|
-
node.expectation = [{ type: 'json:array', typedoc: 'Array' }];
|
|
7
|
-
if (!ctx.depth || ctx.depth <= 0) {
|
|
8
|
-
;
|
|
9
|
-
node.expectation[0].items = expectation(checker, ctx);
|
|
10
|
-
}
|
|
11
|
-
if (!JsonArrayNode.is(node)) {
|
|
12
|
-
ctx.err.report(localize('expected', localize('array')), node);
|
|
13
|
-
}
|
|
14
|
-
else {
|
|
15
|
-
node.children
|
|
16
|
-
.filter((e) => e.value)
|
|
17
|
-
.forEach((e) => checker(e.value, ctx));
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
export function uniqueListOf(checker, options = {}) {
|
|
22
|
-
const getItem = options.items ??
|
|
23
|
-
((node) => [JsonStringNode.is(node) ? node.value : undefined, node]);
|
|
24
|
-
const reporter = options.report ??
|
|
25
|
-
((node, ctx) => ctx.err.report(localize('json.checker.item.duplicate'), node, 2 /* ErrorSeverity.Warning */));
|
|
26
|
-
return (node, ctx) => {
|
|
27
|
-
listOf(checker)(node, ctx);
|
|
28
|
-
if (JsonArrayNode.is(node)) {
|
|
29
|
-
const items = new Map();
|
|
30
|
-
const duplicates = new Set();
|
|
31
|
-
node.children.forEach((c) => {
|
|
32
|
-
if (!c.value)
|
|
33
|
-
return;
|
|
34
|
-
const [value, item] = getItem(c.value);
|
|
35
|
-
if (!value)
|
|
36
|
-
return;
|
|
37
|
-
const existing = items.get(value);
|
|
38
|
-
if (existing) {
|
|
39
|
-
duplicates.add(existing);
|
|
40
|
-
duplicates.add(item);
|
|
41
|
-
}
|
|
42
|
-
items.set(value, item);
|
|
43
|
-
});
|
|
44
|
-
duplicates.forEach((node) => reporter(node, ctx));
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=list.js.map
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { JsonChecker } from '../JsonChecker.js';
|
|
2
|
-
export declare const int: JsonChecker;
|
|
3
|
-
export declare const float: JsonChecker;
|
|
4
|
-
export declare const intRange: (min: number | undefined, max: number | undefined) => JsonChecker;
|
|
5
|
-
export declare const floatRange: (min: number | undefined, max: number | undefined) => JsonChecker;
|
|
6
|
-
//# sourceMappingURL=number.d.ts.map
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { localize } from '@spyglassmc/locales';
|
|
2
|
-
import { JsonNumberNode } from '../../node/index.js';
|
|
3
|
-
const number = (type) => (min, max) => {
|
|
4
|
-
return (node, ctx) => {
|
|
5
|
-
const typedoc = 'Number' +
|
|
6
|
-
(min === undefined && max === undefined
|
|
7
|
-
? ''
|
|
8
|
-
: `(${min ?? '-∞'}, ${max ?? '+∞'})`);
|
|
9
|
-
node.expectation = [{ type: 'json:number', typedoc }];
|
|
10
|
-
if (!JsonNumberNode.is(node) ||
|
|
11
|
-
(type === 'integer' && !Number.isInteger(node.value))) {
|
|
12
|
-
ctx.err.report(localize('expected', localize(type)), node);
|
|
13
|
-
}
|
|
14
|
-
else if (min !== undefined &&
|
|
15
|
-
max !== undefined &&
|
|
16
|
-
(node.value < min || node.value > max)) {
|
|
17
|
-
ctx.err.report(localize('expected', localize('number.between', min, max)), node);
|
|
18
|
-
}
|
|
19
|
-
else if (min !== undefined && node.value < min) {
|
|
20
|
-
ctx.err.report(localize('expected', localize('number.>=', min)), node);
|
|
21
|
-
}
|
|
22
|
-
else if (max !== undefined && node.value > max) {
|
|
23
|
-
ctx.err.report(localize('expected', localize('number.<=', max)), node);
|
|
24
|
-
}
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
export const int = number('integer')(undefined, undefined);
|
|
28
|
-
export const float = number('float')(undefined, undefined);
|
|
29
|
-
export const intRange = number('integer');
|
|
30
|
-
export const floatRange = number('float');
|
|
31
|
-
//# sourceMappingURL=number.js.map
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { PairNode } from '@spyglassmc/core';
|
|
2
|
-
import type { JsonNode, JsonStringNode } from '../../node/index.js';
|
|
3
|
-
import type { JsonChecker, JsonCheckerContext } from '../JsonChecker.js';
|
|
4
|
-
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
5
|
-
[key: string]: JsonValue;
|
|
6
|
-
};
|
|
7
|
-
type ComplexProperty = {
|
|
8
|
-
checker: JsonChecker;
|
|
9
|
-
opt?: boolean;
|
|
10
|
-
def?: JsonValue;
|
|
11
|
-
deprecated?: boolean;
|
|
12
|
-
context?: string;
|
|
13
|
-
};
|
|
14
|
-
type CheckerProperty = JsonChecker | ComplexProperty;
|
|
15
|
-
type CheckerRecord = Record<string, CheckerProperty | undefined>;
|
|
16
|
-
type ObjectCheckerOptions = {
|
|
17
|
-
allowUnknownProperties?: boolean;
|
|
18
|
-
};
|
|
19
|
-
export declare function object(): JsonChecker;
|
|
20
|
-
export declare function object(keys: string[], values: (key: string, ctx: JsonCheckerContext) => CheckerProperty | undefined, options?: ObjectCheckerOptions): JsonChecker;
|
|
21
|
-
export declare function object(keys: JsonChecker, values: (key: string, ctx: JsonCheckerContext) => CheckerProperty | undefined, options?: ObjectCheckerOptions): JsonChecker;
|
|
22
|
-
export declare function record(properties: CheckerRecord, options?: ObjectCheckerOptions): JsonChecker;
|
|
23
|
-
export declare function opt(checker?: JsonChecker | ComplexProperty, defaultValue?: JsonValue): ComplexProperty | undefined;
|
|
24
|
-
export declare function deprecate(checker?: JsonChecker | ComplexProperty): ComplexProperty | undefined;
|
|
25
|
-
export declare function dispatch(values: (children: PairNode<JsonStringNode, JsonNode>[], ctx: JsonCheckerContext) => JsonChecker): JsonChecker;
|
|
26
|
-
export declare function dispatch(keyName: string, values: (value: string | undefined, children: PairNode<JsonStringNode, JsonNode>[], ctx: JsonCheckerContext) => JsonChecker): JsonChecker;
|
|
27
|
-
export declare function pick(value: string | undefined, cases: Record<string, CheckerRecord>): CheckerRecord;
|
|
28
|
-
export declare function when(value: string | undefined, values: string[], properties: CheckerRecord, notProperties?: CheckerRecord): CheckerRecord;
|
|
29
|
-
export declare function extract(value: string, children: PairNode<JsonStringNode, JsonNode>[] | undefined): string | undefined;
|
|
30
|
-
export declare function extractNested(wrap: string, value: string, children: PairNode<JsonStringNode, JsonNode>[] | undefined): string | undefined;
|
|
31
|
-
export declare function extractStringArray(value: string, children?: PairNode<JsonStringNode, JsonNode>[] | undefined): readonly string[] | undefined;
|
|
32
|
-
export declare function having(node: JsonNode, ctx: JsonCheckerContext, cases: Record<string, CheckerRecord | (() => CheckerRecord)>): CheckerRecord;
|
|
33
|
-
export {};
|
|
34
|
-
//# sourceMappingURL=object.d.ts.map
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import { Range, ResourceLocation } from '@spyglassmc/core';
|
|
2
|
-
import { localeQuote, localize } from '@spyglassmc/locales';
|
|
3
|
-
import { JsonObjectNode, JsonStringExpectation } from '../../node/index.js';
|
|
4
|
-
import { any, expectation } from './util.js';
|
|
5
|
-
function isComplex(checker) {
|
|
6
|
-
return checker?.checker !== undefined;
|
|
7
|
-
}
|
|
8
|
-
export function object(keys, values, options = {}) {
|
|
9
|
-
return (node, ctx) => {
|
|
10
|
-
node.expectation = [{ type: 'json:object', typedoc: 'Object' }];
|
|
11
|
-
if (!ctx.depth || ctx.depth <= 0) {
|
|
12
|
-
if (Array.isArray(keys) && values) {
|
|
13
|
-
const fields = keys
|
|
14
|
-
.map((key) => [key, values(key, ctx)])
|
|
15
|
-
.filter(([_, v]) => v !== undefined);
|
|
16
|
-
node.expectation[0].fields = fields
|
|
17
|
-
.map(([key, prop]) => {
|
|
18
|
-
return {
|
|
19
|
-
key,
|
|
20
|
-
value: expectation(isComplex(prop) ? prop.checker : prop, ctx),
|
|
21
|
-
...(isComplex(prop) && (prop.opt || prop.deprecated)
|
|
22
|
-
? { opt: true }
|
|
23
|
-
: {}),
|
|
24
|
-
...(isComplex(prop) && prop.deprecated
|
|
25
|
-
? { deprecated: true }
|
|
26
|
-
: {}),
|
|
27
|
-
};
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
else if (typeof keys === 'function' && values) {
|
|
31
|
-
;
|
|
32
|
-
node.expectation[0].keys = expectation(keys, ctx)?.filter(JsonStringExpectation.is);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
if (!JsonObjectNode.is(node)) {
|
|
36
|
-
ctx.err.report(localize('expected', localize('object')), node);
|
|
37
|
-
}
|
|
38
|
-
else if (Array.isArray(keys) && values) {
|
|
39
|
-
const givenKeys = node.children.map((n) => n.key?.value);
|
|
40
|
-
keys.forEach((k) => {
|
|
41
|
-
const value = values(k, ctx);
|
|
42
|
-
if (!value || (isComplex(value) && (value.opt || value.deprecated))) {
|
|
43
|
-
return;
|
|
44
|
-
}
|
|
45
|
-
if (!givenKeys.includes(k)) {
|
|
46
|
-
ctx.err.report(localize('json.checker.property.missing', localeQuote(k)), Range.create(node.range.start, node.range.start + 1));
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
node.children
|
|
50
|
-
.filter((p) => p.key)
|
|
51
|
-
.forEach((prop) => {
|
|
52
|
-
const key = prop.key.value;
|
|
53
|
-
const value = values(key, ctx);
|
|
54
|
-
if (!value || !keys.includes(key)) {
|
|
55
|
-
if (!options.allowUnknownProperties) {
|
|
56
|
-
ctx.err.report(localize('json.checker.property.unknown', localeQuote(key)), prop.key, 2 /* ErrorSeverity.Warning */);
|
|
57
|
-
}
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
if (isComplex(value) && value.deprecated) {
|
|
61
|
-
ctx.err.report(localize('json.checker.property.deprecated', localeQuote(key)), prop.key, 0 /* ErrorSeverity.Hint */, { deprecated: true });
|
|
62
|
-
}
|
|
63
|
-
const context = ctx.context +
|
|
64
|
-
(isComplex(value) && value.context ? `.${value.context}` : '');
|
|
65
|
-
const doc = localize(`json.doc.${context}`);
|
|
66
|
-
const propNode = prop.value !== undefined
|
|
67
|
-
? prop.value
|
|
68
|
-
: { type: 'json:null', range: Range.create(0) };
|
|
69
|
-
const checker = isComplex(value) ? value.checker : value;
|
|
70
|
-
try {
|
|
71
|
-
checker(propNode, { ...ctx, context: `${context}.${key}` });
|
|
72
|
-
}
|
|
73
|
-
catch (e) {
|
|
74
|
-
const pos = ctx.doc.positionAt(prop.range.start);
|
|
75
|
-
ctx.logger.error(`Checking "${key}" at ${pos.line}:${pos.character} in "${ctx.doc.uri}"`, e);
|
|
76
|
-
}
|
|
77
|
-
const defaultValue = isComplex(value) ? value.def : undefined;
|
|
78
|
-
const typedoc = propNode.expectation
|
|
79
|
-
?.map((e) => e.typedoc)
|
|
80
|
-
.join(' | ');
|
|
81
|
-
prop.key.hover =
|
|
82
|
-
`\`\`\`typescript\n${context}.${key}: ${typedoc}\n\`\`\`${doc || defaultValue !== undefined ? '\n******\n ' : ''}${doc}${defaultValue !== undefined
|
|
83
|
-
? `\n\`@default\` ${JSON.stringify(defaultValue)}`
|
|
84
|
-
: ''}`;
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
else if (typeof keys === 'function' && values) {
|
|
88
|
-
node.children
|
|
89
|
-
.filter((p) => p.key)
|
|
90
|
-
.forEach((prop) => {
|
|
91
|
-
keys(prop.key, ctx);
|
|
92
|
-
if (prop.value !== undefined) {
|
|
93
|
-
const value = values(prop.key.value, ctx);
|
|
94
|
-
if (value) {
|
|
95
|
-
const checker = isComplex(value) ? value.checker : value;
|
|
96
|
-
checker(prop.value, ctx);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
export function record(properties, options) {
|
|
104
|
-
return object(Object.keys(properties), (key) => properties[key], options);
|
|
105
|
-
}
|
|
106
|
-
export function opt(checker, defaultValue) {
|
|
107
|
-
if (checker === undefined)
|
|
108
|
-
return undefined;
|
|
109
|
-
return isComplex(checker)
|
|
110
|
-
? { ...checker, opt: true, def: defaultValue }
|
|
111
|
-
: { checker, opt: true, def: defaultValue };
|
|
112
|
-
}
|
|
113
|
-
export function deprecate(checker) {
|
|
114
|
-
if (checker === undefined)
|
|
115
|
-
return undefined;
|
|
116
|
-
return isComplex(checker)
|
|
117
|
-
? { ...checker, deprecated: true }
|
|
118
|
-
: { checker, deprecated: true };
|
|
119
|
-
}
|
|
120
|
-
export function dispatch(arg1, arg2) {
|
|
121
|
-
return (node, ctx) => {
|
|
122
|
-
if (!JsonObjectNode.is(node)) {
|
|
123
|
-
ctx.err.report(localize('expected', localize('object')), node);
|
|
124
|
-
}
|
|
125
|
-
else if (arg2) {
|
|
126
|
-
const dispatcherIndex = node.children.findIndex((p) => p.key?.value === arg1);
|
|
127
|
-
const dispatcher = node.children[dispatcherIndex];
|
|
128
|
-
const value = dispatcher?.value?.type === 'json:string'
|
|
129
|
-
? dispatcher.value.value
|
|
130
|
-
: undefined;
|
|
131
|
-
arg2(value, node.children, ctx)(node, ctx);
|
|
132
|
-
}
|
|
133
|
-
else {
|
|
134
|
-
;
|
|
135
|
-
arg1(node.children, ctx)(node, ctx);
|
|
136
|
-
}
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
export function pick(value, cases) {
|
|
140
|
-
if (value === undefined) {
|
|
141
|
-
return {};
|
|
142
|
-
}
|
|
143
|
-
const properties = cases[ResourceLocation.shorten(value)];
|
|
144
|
-
if (properties === undefined) {
|
|
145
|
-
return {};
|
|
146
|
-
}
|
|
147
|
-
Object.keys(properties).forEach((key) => {
|
|
148
|
-
const p = properties[key];
|
|
149
|
-
if (p === undefined)
|
|
150
|
-
return;
|
|
151
|
-
properties[key] = {
|
|
152
|
-
checker: isComplex(p) ? p.checker : p,
|
|
153
|
-
opt: isComplex(p) ? p.opt : undefined,
|
|
154
|
-
deprecated: isComplex(p) ? p.deprecated : undefined,
|
|
155
|
-
context: ResourceLocation.shorten(value),
|
|
156
|
-
};
|
|
157
|
-
});
|
|
158
|
-
return properties;
|
|
159
|
-
}
|
|
160
|
-
export function when(value, values, properties, notProperties = {}) {
|
|
161
|
-
if (value === undefined) {
|
|
162
|
-
return {};
|
|
163
|
-
}
|
|
164
|
-
if (!values.includes(ResourceLocation.shorten(value))) {
|
|
165
|
-
return notProperties;
|
|
166
|
-
}
|
|
167
|
-
return properties;
|
|
168
|
-
}
|
|
169
|
-
export function extract(value, children) {
|
|
170
|
-
const node = children?.find((p) => p.key?.value === value);
|
|
171
|
-
return node?.value?.type === 'json:string' ? node.value.value : undefined;
|
|
172
|
-
}
|
|
173
|
-
export function extractNested(wrap, value, children) {
|
|
174
|
-
const wrapper = children?.find((p) => p.key?.value === wrap);
|
|
175
|
-
if (wrapper?.value?.type !== 'json:object')
|
|
176
|
-
return undefined;
|
|
177
|
-
const node = wrapper.children?.find((p) => p.key?.value ===
|
|
178
|
-
value);
|
|
179
|
-
return node?.type === 'json:string' ? node.value : undefined;
|
|
180
|
-
}
|
|
181
|
-
export function extractStringArray(value, children) {
|
|
182
|
-
const node = children?.find((p) => p.key?.value === value);
|
|
183
|
-
return node?.value?.type === 'json:array' &&
|
|
184
|
-
node.value.children?.every((n) => n.value?.type === 'json:string')
|
|
185
|
-
? node.value.children.map((n) => n.value.value)
|
|
186
|
-
: undefined;
|
|
187
|
-
}
|
|
188
|
-
export function having(node, ctx, cases) {
|
|
189
|
-
const givenKeys = new Set(JsonObjectNode.is(node) ? node.children.map((n) => n.key?.value) : []);
|
|
190
|
-
const key = Object.keys(cases).find((c) => givenKeys.has(c));
|
|
191
|
-
if (key === undefined) {
|
|
192
|
-
ctx.err.report(localize('json.checker.property.missing', Object.keys(cases)), Range.create(node.range.start, node.range.start + 1));
|
|
193
|
-
return Object.fromEntries(Object.entries(cases).map(([k, v]) => [
|
|
194
|
-
k,
|
|
195
|
-
opt(typeof v === 'function' ? any() : v[k] ?? any()),
|
|
196
|
-
]));
|
|
197
|
-
}
|
|
198
|
-
const c = cases[key];
|
|
199
|
-
return typeof c === 'function' ? c() : c;
|
|
200
|
-
}
|
|
201
|
-
//# sourceMappingURL=object.js.map
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { AllCategory, AstNode, Parser, ResourceLocationCategory, SyncChecker, TaggableResourceLocationCategory } from '@spyglassmc/core';
|
|
2
|
-
import { Lazy } from '@spyglassmc/core';
|
|
3
|
-
import type { JsonExpectation } from '../../node/index.js';
|
|
4
|
-
import { JsonStringNode } from '../../node/index.js';
|
|
5
|
-
import type { JsonChecker } from '../JsonChecker.js';
|
|
6
|
-
export declare function resource(id: TaggableResourceLocationCategory, allowTag?: boolean): JsonChecker;
|
|
7
|
-
export declare function resource(id: ResourceLocationCategory | string[], allowTag?: false): JsonChecker;
|
|
8
|
-
export declare function literal(value: AllCategory | readonly string[]): JsonChecker;
|
|
9
|
-
export declare function string<T extends AstNode>(name: string | readonly string[] | undefined, parser: Lazy<Parser<T>>, checker?: Lazy<SyncChecker<T>>, expectation?: Partial<JsonExpectation>): JsonChecker;
|
|
10
|
-
export declare function string(name?: string | readonly string[], parser?: undefined, checker?: Lazy<SyncChecker<JsonStringNode>>, expectation?: Partial<JsonExpectation>): JsonChecker;
|
|
11
|
-
export declare const simpleString: JsonChecker;
|
|
12
|
-
//# sourceMappingURL=string.d.ts.map
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import * as core from '@spyglassmc/core';
|
|
2
|
-
import { Failure, Lazy, ResourceLocation } from '@spyglassmc/core';
|
|
3
|
-
import { localize } from '@spyglassmc/locales';
|
|
4
|
-
import { JsonStringNode } from '../../node/index.js';
|
|
5
|
-
export function resource(id, allowTag = false) {
|
|
6
|
-
return string(id, core.resourceLocation(typeof id === 'string'
|
|
7
|
-
? { category: id, allowTag }
|
|
8
|
-
: { pool: id.map(ResourceLocation.lengthen) }), core.checker.resourceLocation);
|
|
9
|
-
}
|
|
10
|
-
export function literal(value) {
|
|
11
|
-
return typeof value === 'string'
|
|
12
|
-
? string(value, core.symbol(value))
|
|
13
|
-
: string(value, core.literal(...value));
|
|
14
|
-
}
|
|
15
|
-
export function string(name, parser, checker, expectation) {
|
|
16
|
-
return (node, ctx) => {
|
|
17
|
-
node.expectation = [
|
|
18
|
-
{ type: 'json:string', typedoc: typedoc(name), ...expectation },
|
|
19
|
-
];
|
|
20
|
-
if (!JsonStringNode.is(node)) {
|
|
21
|
-
ctx.err.report(localize('expected', localize('string')), node);
|
|
22
|
-
}
|
|
23
|
-
else if (parser) {
|
|
24
|
-
const result = core.parseStringValue(Lazy.resolve(parser), node.value, node.valueMap, ctx);
|
|
25
|
-
if (result !== Failure) {
|
|
26
|
-
node.children = [result];
|
|
27
|
-
result.parent = node;
|
|
28
|
-
if (checker) {
|
|
29
|
-
Lazy.resolve(checker)(result, ctx);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
else if (checker) {
|
|
34
|
-
Lazy.resolve(checker)(node, ctx);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function typedoc(id) {
|
|
39
|
-
if (!id) {
|
|
40
|
-
return 'String';
|
|
41
|
-
}
|
|
42
|
-
if (typeof id === 'string') {
|
|
43
|
-
return `String("${id}")`;
|
|
44
|
-
}
|
|
45
|
-
return (id
|
|
46
|
-
.slice(0, 10)
|
|
47
|
-
.map((e) => `"${e}"`)
|
|
48
|
-
.join(' | ') + (id.length > 10 ? ' | ...' : ''));
|
|
49
|
-
}
|
|
50
|
-
export const simpleString = string();
|
|
51
|
-
//# sourceMappingURL=string.js.map
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { ErrorSeverity } from '@spyglassmc/core';
|
|
2
|
-
import type { JsonExpectation, JsonNode } from '../../node/index.js';
|
|
3
|
-
import type { JsonChecker, JsonCheckerContext } from '../JsonChecker.js';
|
|
4
|
-
export declare function ref(checker: () => JsonChecker): JsonChecker;
|
|
5
|
-
export declare function as(context: string, checker: JsonChecker): JsonChecker;
|
|
6
|
-
export type AttemptResult = {
|
|
7
|
-
totalErrorSpan: number;
|
|
8
|
-
maxSeverity: ErrorSeverity;
|
|
9
|
-
expectation?: JsonExpectation[];
|
|
10
|
-
updateNodeAndCtx: () => void;
|
|
11
|
-
};
|
|
12
|
-
export declare function attempt(checker: JsonChecker, node: JsonNode, ctx: JsonCheckerContext): AttemptResult;
|
|
13
|
-
export declare function any(checkers?: JsonChecker[]): JsonChecker;
|
|
14
|
-
export declare function expectation(checker: JsonChecker, ctx: JsonCheckerContext): JsonExpectation[] | undefined;
|
|
15
|
-
//# sourceMappingURL=util.d.ts.map
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { ErrorReporter, Range, StateProxy } from '@spyglassmc/core';
|
|
2
|
-
import { arrayToMessage, localize } from '@spyglassmc/locales';
|
|
3
|
-
export function ref(checker) {
|
|
4
|
-
return (node, ctx) => {
|
|
5
|
-
return checker()(node, ctx);
|
|
6
|
-
};
|
|
7
|
-
}
|
|
8
|
-
export function as(context, checker) {
|
|
9
|
-
return (node, ctx) => {
|
|
10
|
-
checker(node, { ...ctx, context });
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
export function attempt(checker, node, ctx) {
|
|
14
|
-
// TODO: The code below is mostly copied from core with some changes to support `expectation`. Could be refactored... I guess.
|
|
15
|
-
const tempCtx = {
|
|
16
|
-
...ctx,
|
|
17
|
-
err: new ErrorReporter(),
|
|
18
|
-
symbols: ctx.symbols.clone(),
|
|
19
|
-
};
|
|
20
|
-
checker(node, tempCtx);
|
|
21
|
-
const tempExpectation = node.expectation;
|
|
22
|
-
StateProxy.undoChanges(node);
|
|
23
|
-
const totalErrorSpan = tempCtx.err.errors
|
|
24
|
-
.map((e) => e.range.end - e.range.start)
|
|
25
|
-
.reduce((a, b) => a + b, 0);
|
|
26
|
-
return {
|
|
27
|
-
totalErrorSpan,
|
|
28
|
-
maxSeverity: Math.max(...tempCtx.err.errors.map((e) => e.severity)),
|
|
29
|
-
expectation: tempExpectation,
|
|
30
|
-
updateNodeAndCtx: () => {
|
|
31
|
-
ctx.err.absorb(tempCtx.err);
|
|
32
|
-
StateProxy.redoChanges(node);
|
|
33
|
-
tempCtx.symbols.applyDelayedEdits();
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
export function any(checkers = []) {
|
|
38
|
-
return (node, ctx) => {
|
|
39
|
-
if (checkers.length === 0) {
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
const attempts = checkers
|
|
43
|
-
.map((checker) => attempt(checker, node, ctx))
|
|
44
|
-
.sort((a, b) => a.maxSeverity - b.maxSeverity ||
|
|
45
|
-
a.totalErrorSpan - b.totalErrorSpan);
|
|
46
|
-
const sameTypeAttempts = attempts.filter((a) => a.expectation?.map((e) => e.type).includes(node.type));
|
|
47
|
-
const allExpectations = attempts
|
|
48
|
-
.filter((a) => a.expectation)
|
|
49
|
-
.flatMap((a) => a.expectation);
|
|
50
|
-
if (sameTypeAttempts.length === 0) {
|
|
51
|
-
const allowedTypes = allExpectations.map((e) => localize(e.type.slice(5)));
|
|
52
|
-
ctx.err.report(localize('expected', arrayToMessage(allowedTypes, false)), node);
|
|
53
|
-
}
|
|
54
|
-
else {
|
|
55
|
-
sameTypeAttempts[0].updateNodeAndCtx();
|
|
56
|
-
}
|
|
57
|
-
node.expectation = allExpectations;
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
export function expectation(checker, ctx) {
|
|
61
|
-
const node = StateProxy.create({
|
|
62
|
-
type: 'json:null',
|
|
63
|
-
range: Range.create(0),
|
|
64
|
-
});
|
|
65
|
-
const tempCtx = {
|
|
66
|
-
...ctx,
|
|
67
|
-
err: new ErrorReporter(),
|
|
68
|
-
depth: (ctx.depth ?? 0) + 1,
|
|
69
|
-
};
|
|
70
|
-
checker(node, tempCtx);
|
|
71
|
-
return node.expectation;
|
|
72
|
-
}
|
|
73
|
-
//# sourceMappingURL=util.js.map
|