@spyglassmc/json 0.3.2 → 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 CHANGED
@@ -1,5 +1,4 @@
1
- import type * as core from '@spyglassmc/core';
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);
@@ -1,7 +1,7 @@
1
1
  import type { DeepReadonly, ItemNode, PairNode } from '@spyglassmc/core';
2
2
  import * as core from '@spyglassmc/core';
3
- export declare type JsonNode = JsonObjectNode | JsonArrayNode | JsonStringNode | JsonNumberNode | JsonBooleanNode | JsonNullNode;
4
- export declare type JsonRelatedNode = JsonNode | JsonPairNode | JsonItemNode;
3
+ export type JsonNode = JsonObjectNode | JsonArrayNode | JsonStringNode | JsonNumberNode | JsonBooleanNode | JsonNullNode;
4
+ export type JsonRelatedNode = JsonNode | JsonPairNode | JsonItemNode;
5
5
  export declare namespace JsonNode {
6
6
  function is(node: core.AstNode): node is JsonNode;
7
7
  function isRelated(node: core.AstNode): node is JsonRelatedNode;
@@ -9,7 +9,7 @@ export declare namespace JsonNode {
9
9
  interface JsonBaseAstNode {
10
10
  expectation?: JsonExpectation[];
11
11
  }
12
- export declare type JsonExpectation = JsonObjectExpectation | JsonArrayExpectation | JsonStringExpectation | JsonNumberExpectation | JsonBooleanExpectation;
12
+ export type JsonExpectation = JsonObjectExpectation | JsonArrayExpectation | JsonStringExpectation | JsonNumberExpectation | JsonBooleanExpectation;
13
13
  export declare namespace JsonExpectation {
14
14
  function isArray(e: DeepReadonly<JsonExpectation>): e is DeepReadonly<JsonArrayExpectation>;
15
15
  function isObject(e: DeepReadonly<JsonExpectation>): e is DeepReadonly<JsonObjectExpectation>;
@@ -35,7 +35,7 @@ export declare namespace JsonObjectNode {
35
35
  function is(obj: object | undefined): obj is JsonObjectNode;
36
36
  function mock(range: core.RangeLike): JsonObjectNode;
37
37
  }
38
- export declare type JsonPairNode = PairNode<JsonStringNode, JsonNode>;
38
+ export type JsonPairNode = PairNode<JsonStringNode, JsonNode>;
39
39
  export declare namespace JsonPairNode {
40
40
  function is(obj: object): obj is JsonPairNode;
41
41
  }
@@ -50,7 +50,7 @@ export declare namespace JsonArrayNode {
50
50
  function is(obj: object | undefined): obj is JsonArrayNode;
51
51
  function mock(range: core.RangeLike): JsonArrayNode;
52
52
  }
53
- export declare type JsonItemNode = ItemNode<JsonNode>;
53
+ export type JsonItemNode = ItemNode<JsonNode>;
54
54
  export declare namespace JsonItemNode {
55
55
  function is(obj: object): obj is JsonItemNode;
56
56
  }
@@ -1,5 +1,4 @@
1
1
  import * as core from '@spyglassmc/core';
2
2
  import type { JsonNode } from '../node/index.js';
3
- export declare function json(dumpErrors?: boolean): core.Parser<JsonNode>;
4
3
  export declare const entry: core.Parser<JsonNode>;
5
4
  //# sourceMappingURL=entry.d.ts.map
@@ -18,24 +18,18 @@ const LegalNumberStart = new Set([
18
18
  '9',
19
19
  '-',
20
20
  ]);
21
- export function json(dumpErrors = false) {
22
- return (src, ctx) => {
23
- const result = core.select([
24
- { predicate: (src) => src.tryPeek('['), parser: array },
25
- {
26
- predicate: (src) => src.tryPeek('false') || src.tryPeek('true'),
27
- parser: boolean,
28
- },
29
- { predicate: (src) => src.tryPeek('null'), parser: null_ },
30
- { predicate: (src) => LegalNumberStart.has(src.peek()), parser: number },
31
- { predicate: (src) => src.tryPeek('{'), parser: object },
32
- { parser: string },
33
- ])(src, ctx);
34
- if (dumpErrors) {
35
- ctx.err.dump();
36
- }
37
- return result;
38
- };
39
- }
40
- 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);
41
35
  //# sourceMappingURL=entry.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spyglassmc/json",
3
- "version": "0.3.2",
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.1",
29
- "@spyglassmc/locales": "0.3.1"
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 declare type JsonChecker = (node: JsonNode, ctx: JsonCheckerContext) => void;
8
- //# sourceMappingURL=JsonChecker.d.ts.map
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=JsonChecker.js.map
@@ -1,3 +0,0 @@
1
- export * from './JsonChecker.js';
2
- export * from './primitives/index.js';
3
- //# sourceMappingURL=index.d.ts.map
@@ -1,3 +0,0 @@
1
- export * from './JsonChecker.js';
2
- export * from './primitives/index.js';
3
- //# sourceMappingURL=index.js.map
@@ -1,4 +0,0 @@
1
- import type { JsonNode } from '../../node/index.js';
2
- import type { JsonCheckerContext } from '../JsonChecker.js';
3
- export declare function boolean(node: JsonNode, ctx: JsonCheckerContext): void;
4
- //# sourceMappingURL=boolean.d.ts.map
@@ -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,7 +0,0 @@
1
- export * from './boolean.js';
2
- export * from './list.js';
3
- export * from './number.js';
4
- export * from './object.js';
5
- export * from './string.js';
6
- export * from './util.js';
7
- //# sourceMappingURL=index.d.ts.map
@@ -1,7 +0,0 @@
1
- export * from './boolean.js';
2
- export * from './list.js';
3
- export * from './number.js';
4
- export * from './object.js';
5
- export * from './string.js';
6
- export * from './util.js';
7
- //# sourceMappingURL=index.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
- declare 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
- declare type JsonValue = string | number | boolean | null | JsonValue[] | {
5
- [key: string]: JsonValue;
6
- };
7
- declare type ComplexProperty = {
8
- checker: JsonChecker;
9
- opt?: boolean;
10
- def?: JsonValue;
11
- deprecated?: boolean;
12
- context?: string;
13
- };
14
- declare type CheckerProperty = JsonChecker | ComplexProperty;
15
- declare type CheckerRecord = Record<string, CheckerProperty | undefined>;
16
- declare 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,198 +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.map(([key, prop]) => {
17
- return {
18
- key,
19
- value: expectation(isComplex(prop) ? prop.checker : prop, ctx),
20
- ...(isComplex(prop) && (prop.opt || prop.deprecated)
21
- ? { opt: true }
22
- : {}),
23
- ...(isComplex(prop) && prop.deprecated
24
- ? { deprecated: true }
25
- : {}),
26
- };
27
- });
28
- }
29
- else if (typeof keys === 'function' && values) {
30
- ;
31
- node.expectation[0].keys = expectation(keys, ctx)?.filter(JsonStringExpectation.is);
32
- }
33
- }
34
- if (!JsonObjectNode.is(node)) {
35
- ctx.err.report(localize('expected', localize('object')), node);
36
- }
37
- else if (Array.isArray(keys) && values) {
38
- const givenKeys = node.children.map((n) => n.key?.value);
39
- keys.forEach((k) => {
40
- const value = values(k, ctx);
41
- if (!value || (isComplex(value) && (value.opt || value.deprecated))) {
42
- return;
43
- }
44
- if (!givenKeys.includes(k)) {
45
- ctx.err.report(localize('json.checker.property.missing', localeQuote(k)), Range.create(node.range.start, node.range.start + 1));
46
- }
47
- });
48
- node.children
49
- .filter((p) => p.key)
50
- .forEach((prop) => {
51
- const key = prop.key.value;
52
- const value = values(key, ctx);
53
- if (!value || !keys.includes(key)) {
54
- if (!options.allowUnknownProperties) {
55
- ctx.err.report(localize('json.checker.property.unknown', localeQuote(key)), prop.key, 2 /* ErrorSeverity.Warning */);
56
- }
57
- return;
58
- }
59
- if (isComplex(value) && value.deprecated) {
60
- ctx.err.report(localize('json.checker.property.deprecated', localeQuote(key)), prop.key, 0 /* ErrorSeverity.Hint */, { deprecated: true });
61
- }
62
- const context = ctx.context +
63
- (isComplex(value) && value.context ? `.${value.context}` : '');
64
- const doc = localize(`json.doc.${context}`);
65
- const propNode = prop.value !== undefined
66
- ? prop.value
67
- : { type: 'json:null', range: Range.create(0) };
68
- const checker = isComplex(value) ? value.checker : value;
69
- try {
70
- checker(propNode, { ...ctx, context: `${context}.${key}` });
71
- }
72
- catch (e) {
73
- const pos = ctx.doc.positionAt(prop.range.start);
74
- ctx.logger.error(`Checking "${key}" at ${pos.line}:${pos.character} in "${ctx.doc.uri}"`, e);
75
- }
76
- const defaultValue = isComplex(value) ? value.def : undefined;
77
- const typedoc = propNode.expectation
78
- ?.map((e) => e.typedoc)
79
- .join(' | ');
80
- prop.key.hover = `\`\`\`typescript\n${context}.${key}: ${typedoc}\n\`\`\`${doc || defaultValue !== undefined ? '\n******\n ' : ''}${doc}${defaultValue !== undefined
81
- ? `\n\`@default\` ${JSON.stringify(defaultValue)}`
82
- : ''}`;
83
- });
84
- }
85
- else if (typeof keys === 'function' && values) {
86
- node.children
87
- .filter((p) => p.key)
88
- .forEach((prop) => {
89
- keys(prop.key, ctx);
90
- if (prop.value !== undefined) {
91
- const value = values(prop.key.value, ctx);
92
- if (value) {
93
- const checker = isComplex(value) ? value.checker : value;
94
- checker(prop.value, ctx);
95
- }
96
- }
97
- });
98
- }
99
- };
100
- }
101
- export function record(properties, options) {
102
- return object(Object.keys(properties), (key) => properties[key], options);
103
- }
104
- export function opt(checker, defaultValue) {
105
- if (checker === undefined)
106
- return undefined;
107
- return isComplex(checker)
108
- ? { ...checker, opt: true, def: defaultValue }
109
- : { checker, opt: true, def: defaultValue };
110
- }
111
- export function deprecate(checker) {
112
- if (checker === undefined)
113
- return undefined;
114
- return isComplex(checker)
115
- ? { ...checker, deprecated: true }
116
- : { checker, deprecated: true };
117
- }
118
- export function dispatch(arg1, arg2) {
119
- return (node, ctx) => {
120
- if (!JsonObjectNode.is(node)) {
121
- ctx.err.report(localize('expected', localize('object')), node);
122
- }
123
- else if (arg2) {
124
- const dispatcherIndex = node.children.findIndex((p) => p.key?.value === arg1);
125
- const dispatcher = node.children[dispatcherIndex];
126
- const value = dispatcher?.value?.type === 'json:string'
127
- ? dispatcher.value.value
128
- : undefined;
129
- arg2(value, node.children, ctx)(node, ctx);
130
- }
131
- else {
132
- ;
133
- arg1(node.children, ctx)(node, ctx);
134
- }
135
- };
136
- }
137
- export function pick(value, cases) {
138
- if (value === undefined) {
139
- return {};
140
- }
141
- const properties = cases[ResourceLocation.shorten(value)];
142
- if (properties === undefined) {
143
- return {};
144
- }
145
- Object.keys(properties).forEach((key) => {
146
- const p = properties[key];
147
- if (p === undefined)
148
- return;
149
- properties[key] = {
150
- checker: isComplex(p) ? p.checker : p,
151
- opt: isComplex(p) ? p.opt : undefined,
152
- deprecated: isComplex(p) ? p.deprecated : undefined,
153
- context: ResourceLocation.shorten(value),
154
- };
155
- });
156
- return properties;
157
- }
158
- export function when(value, values, properties, notProperties = {}) {
159
- if (value === undefined) {
160
- return {};
161
- }
162
- if (!values.includes(ResourceLocation.shorten(value))) {
163
- return notProperties;
164
- }
165
- return properties;
166
- }
167
- export function extract(value, children) {
168
- const node = children?.find((p) => p.key?.value === value);
169
- return node?.value?.type === 'json:string' ? node.value.value : undefined;
170
- }
171
- export function extractNested(wrap, value, children) {
172
- const wrapper = children?.find((p) => p.key?.value === wrap);
173
- if (wrapper?.value?.type !== 'json:object')
174
- return undefined;
175
- const node = wrapper.children?.find((p) => p.key?.value === value);
176
- return node?.type === 'json:string' ? node.value : undefined;
177
- }
178
- export function extractStringArray(value, children) {
179
- const node = children?.find((p) => p.key?.value === value);
180
- return node?.value?.type === 'json:array' &&
181
- node.value.children?.every((n) => n.value?.type === 'json:string')
182
- ? node.value.children.map((n) => n.value.value)
183
- : undefined;
184
- }
185
- export function having(node, ctx, cases) {
186
- const givenKeys = new Set(JsonObjectNode.is(node) ? node.children.map((n) => n.key?.value) : []);
187
- const key = Object.keys(cases).find((c) => givenKeys.has(c));
188
- if (key === undefined) {
189
- ctx.err.report(localize('json.checker.property.missing', Object.keys(cases)), Range.create(node.range.start, node.range.start + 1));
190
- return Object.fromEntries(Object.entries(cases).map(([k, v]) => [
191
- k,
192
- opt(typeof v === 'function' ? any() : v[k] ?? any()),
193
- ]));
194
- }
195
- const c = cases[key];
196
- return typeof c === 'function' ? c() : c;
197
- }
198
- //# 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 declare 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,72 +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 || a.totalErrorSpan - b.totalErrorSpan);
45
- const sameTypeAttempts = attempts.filter((a) => a.expectation?.map((e) => e.type).includes(node.type));
46
- const allExpectations = attempts
47
- .filter((a) => a.expectation)
48
- .flatMap((a) => a.expectation);
49
- if (sameTypeAttempts.length === 0) {
50
- const allowedTypes = allExpectations.map((e) => localize(e.type.slice(5)));
51
- ctx.err.report(localize('expected', arrayToMessage(allowedTypes, false)), node);
52
- }
53
- else {
54
- sameTypeAttempts[0].updateNodeAndCtx();
55
- }
56
- node.expectation = allExpectations;
57
- };
58
- }
59
- export function expectation(checker, ctx) {
60
- const node = StateProxy.create({
61
- type: 'json:null',
62
- range: Range.create(0),
63
- });
64
- const tempCtx = {
65
- ...ctx,
66
- err: new ErrorReporter(),
67
- depth: (ctx.depth ?? 0) + 1,
68
- };
69
- checker(node, tempCtx);
70
- return node.expectation;
71
- }
72
- //# sourceMappingURL=util.js.map