@eslint/json 0.11.0 → 0.13.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/README.md +72 -33
- package/dist/cjs/index.cjs +295 -139
- package/dist/cjs/index.d.cts +117 -77
- package/dist/cjs/types.cts +22 -68
- package/dist/esm/index.d.ts +117 -77
- package/dist/esm/index.js +295 -139
- package/dist/esm/types.d.ts +11 -49
- package/dist/esm/types.ts +22 -68
- package/package.json +23 -11
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
|
|
2
|
+
/**
|
|
3
|
+
* @import { DocumentNode, AnyNode, Token, MemberNode } from "@humanwhocodes/momoa"
|
|
4
|
+
* @import { SourceLocation, FileProblem, DirectiveType, RulesConfig, Language, OkParseResult, ParseResult, File } from "@eslint/core"
|
|
5
|
+
* @import { JSONSyntaxElement, JSONRuleDefinition } from "./types.ts"
|
|
6
|
+
*/
|
|
1
7
|
'use strict';
|
|
2
8
|
|
|
3
9
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
@@ -16,19 +22,8 @@ var naturalCompare = require('natural-compare');
|
|
|
16
22
|
// Types
|
|
17
23
|
//-----------------------------------------------------------------------------
|
|
18
24
|
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
/** @typedef {import("@humanwhocodes/momoa").Token} JSONToken */
|
|
22
|
-
/** @typedef {import("@eslint/core").SourceRange} SourceRange */
|
|
23
|
-
/** @typedef {import("@eslint/core").SourceLocation} SourceLocation */
|
|
24
|
-
/** @typedef {import("@eslint/core").File} File */
|
|
25
|
-
/** @typedef {import("@eslint/core").TraversalStep} TraversalStep */
|
|
26
|
-
/** @typedef {import("@eslint/core").VisitTraversalStep} VisitTraversalStep */
|
|
27
|
-
/** @typedef {import("@eslint/core").FileProblem} FileProblem */
|
|
28
|
-
/** @typedef {import("@eslint/core").DirectiveType} DirectiveType */
|
|
29
|
-
/** @typedef {import("@eslint/core").RulesConfig} RulesConfig */
|
|
30
|
-
/** @typedef {import("./types.ts").IJSONSourceCode} IJSONSourceCode */
|
|
31
|
-
/** @typedef {import("./types.ts").JSONSyntaxElement} JSONSyntaxElement */
|
|
25
|
+
/**
|
|
26
|
+
*/
|
|
32
27
|
|
|
33
28
|
//-----------------------------------------------------------------------------
|
|
34
29
|
// Helpers
|
|
@@ -45,14 +40,14 @@ const INLINE_CONFIG =
|
|
|
45
40
|
class JSONTraversalStep extends pluginKit.VisitNodeStep {
|
|
46
41
|
/**
|
|
47
42
|
* The target of the step.
|
|
48
|
-
* @type {
|
|
43
|
+
* @type {AnyNode}
|
|
49
44
|
*/
|
|
50
45
|
target = undefined;
|
|
51
46
|
|
|
52
47
|
/**
|
|
53
48
|
* Creates a new instance.
|
|
54
49
|
* @param {Object} options The options for the step.
|
|
55
|
-
* @param {
|
|
50
|
+
* @param {AnyNode} options.target The target of the step.
|
|
56
51
|
* @param {1|2} options.phase The phase of the step.
|
|
57
52
|
* @param {Array<any>} options.args The arguments of the step.
|
|
58
53
|
*/
|
|
@@ -63,13 +58,44 @@ class JSONTraversalStep extends pluginKit.VisitNodeStep {
|
|
|
63
58
|
}
|
|
64
59
|
}
|
|
65
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Processes tokens to extract comments and their starting tokens.
|
|
63
|
+
* @param {Array<Token>} tokens The tokens to process.
|
|
64
|
+
* @returns {{ comments: Array<Token>, starts: Map<number, number>, ends: Map<number, number>}}
|
|
65
|
+
* An object containing an array of comments, a map of starting token range to token index, and
|
|
66
|
+
* a map of ending token range to token index.
|
|
67
|
+
*/
|
|
68
|
+
function processTokens(tokens) {
|
|
69
|
+
/** @type {Array<Token>} */
|
|
70
|
+
const comments = [];
|
|
71
|
+
|
|
72
|
+
/** @type {Map<number, number>} */
|
|
73
|
+
const starts = new Map();
|
|
74
|
+
|
|
75
|
+
/** @type {Map<number, number>} */
|
|
76
|
+
const ends = new Map();
|
|
77
|
+
|
|
78
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
79
|
+
const token = tokens[i];
|
|
80
|
+
|
|
81
|
+
if (token.type.endsWith("Comment")) {
|
|
82
|
+
comments.push(token);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
starts.set(token.range[0], i);
|
|
86
|
+
ends.set(token.range[1], i);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return { comments, starts, ends };
|
|
90
|
+
}
|
|
91
|
+
|
|
66
92
|
//-----------------------------------------------------------------------------
|
|
67
93
|
// Exports
|
|
68
94
|
//-----------------------------------------------------------------------------
|
|
69
95
|
|
|
70
96
|
/**
|
|
71
97
|
* JSON Source Code Object
|
|
72
|
-
* @
|
|
98
|
+
* @extends {TextSourceCodeBase<{LangOptions: JSONLanguageOptions, RootNode: DocumentNode, SyntaxElementWithLoc: JSONSyntaxElement, ConfigNode: Token}>}
|
|
73
99
|
*/
|
|
74
100
|
class JSONSourceCode extends pluginKit.TextSourceCodeBase {
|
|
75
101
|
/**
|
|
@@ -80,13 +106,13 @@ class JSONSourceCode extends pluginKit.TextSourceCodeBase {
|
|
|
80
106
|
|
|
81
107
|
/**
|
|
82
108
|
* Cache of parent nodes.
|
|
83
|
-
* @type {WeakMap<
|
|
109
|
+
* @type {WeakMap<AnyNode, AnyNode>}
|
|
84
110
|
*/
|
|
85
111
|
#parents = new WeakMap();
|
|
86
112
|
|
|
87
113
|
/**
|
|
88
114
|
* Collection of inline configuration comments.
|
|
89
|
-
* @type {Array<
|
|
115
|
+
* @type {Array<Token>}
|
|
90
116
|
*/
|
|
91
117
|
#inlineConfigComments;
|
|
92
118
|
|
|
@@ -97,11 +123,23 @@ class JSONSourceCode extends pluginKit.TextSourceCodeBase {
|
|
|
97
123
|
ast = undefined;
|
|
98
124
|
|
|
99
125
|
/**
|
|
100
|
-
* The comment
|
|
101
|
-
* @type {Array<
|
|
126
|
+
* The comment tokens in the source code.
|
|
127
|
+
* @type {Array<Token>|undefined}
|
|
102
128
|
*/
|
|
103
129
|
comments;
|
|
104
130
|
|
|
131
|
+
/**
|
|
132
|
+
* A map of token start positions to their corresponding index.
|
|
133
|
+
* @type {Map<number, number>}
|
|
134
|
+
*/
|
|
135
|
+
#tokenStarts;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* A map of token end positions to their corresponding index.
|
|
139
|
+
* @type {Map<number, number>}
|
|
140
|
+
*/
|
|
141
|
+
#tokenEnds;
|
|
142
|
+
|
|
105
143
|
/**
|
|
106
144
|
* Creates a new instance.
|
|
107
145
|
* @param {Object} options The options for the instance.
|
|
@@ -111,14 +149,16 @@ class JSONSourceCode extends pluginKit.TextSourceCodeBase {
|
|
|
111
149
|
constructor({ text, ast }) {
|
|
112
150
|
super({ text, ast });
|
|
113
151
|
this.ast = ast;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
152
|
+
|
|
153
|
+
const { comments, starts, ends } = processTokens(this.ast.tokens ?? []);
|
|
154
|
+
this.comments = comments;
|
|
155
|
+
this.#tokenStarts = starts;
|
|
156
|
+
this.#tokenEnds = ends;
|
|
117
157
|
}
|
|
118
158
|
|
|
119
159
|
/**
|
|
120
160
|
* Returns the value of the given comment.
|
|
121
|
-
* @param {
|
|
161
|
+
* @param {Token} comment The comment to get the value of.
|
|
122
162
|
* @returns {string} The value of the comment.
|
|
123
163
|
* @throws {Error} When an unexpected comment type is passed.
|
|
124
164
|
*/
|
|
@@ -137,7 +177,7 @@ class JSONSourceCode extends pluginKit.TextSourceCodeBase {
|
|
|
137
177
|
/**
|
|
138
178
|
* Returns an array of all inline configuration nodes found in the
|
|
139
179
|
* source code.
|
|
140
|
-
* @returns {Array<
|
|
180
|
+
* @returns {Array<Token>} An array of all inline configuration nodes.
|
|
141
181
|
*/
|
|
142
182
|
getInlineConfigNodes() {
|
|
143
183
|
if (!this.#inlineConfigComments) {
|
|
@@ -248,8 +288,8 @@ class JSONSourceCode extends pluginKit.TextSourceCodeBase {
|
|
|
248
288
|
|
|
249
289
|
/**
|
|
250
290
|
* Returns the parent of the given node.
|
|
251
|
-
* @param {
|
|
252
|
-
* @returns {
|
|
291
|
+
* @param {AnyNode} node The node to get the parent of.
|
|
292
|
+
* @returns {AnyNode|undefined} The parent of the node.
|
|
253
293
|
*/
|
|
254
294
|
getParent(node) {
|
|
255
295
|
return this.#parents.get(node);
|
|
@@ -270,12 +310,15 @@ class JSONSourceCode extends pluginKit.TextSourceCodeBase {
|
|
|
270
310
|
|
|
271
311
|
for (const { node, parent, phase } of momoa.iterator(this.ast)) {
|
|
272
312
|
if (parent) {
|
|
273
|
-
this.#parents.set(
|
|
313
|
+
this.#parents.set(
|
|
314
|
+
/** @type {AnyNode} */ (node),
|
|
315
|
+
/** @type {AnyNode} */ (parent),
|
|
316
|
+
);
|
|
274
317
|
}
|
|
275
318
|
|
|
276
319
|
steps.push(
|
|
277
320
|
new JSONTraversalStep({
|
|
278
|
-
target: node,
|
|
321
|
+
target: /** @type {AnyNode} */ (node),
|
|
279
322
|
phase: phase === "enter" ? 1 : 2,
|
|
280
323
|
args: [node, parent],
|
|
281
324
|
}),
|
|
@@ -284,10 +327,89 @@ class JSONSourceCode extends pluginKit.TextSourceCodeBase {
|
|
|
284
327
|
|
|
285
328
|
return steps;
|
|
286
329
|
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* Gets the token before the given node or token, optionally including comments.
|
|
333
|
+
* @param {AnyNode|Token} nodeOrToken The node or token to get the previous token for.
|
|
334
|
+
* @param {Object} [options] Options object.
|
|
335
|
+
* @param {boolean} [options.includeComments] If true, return comments when they are present.
|
|
336
|
+
* @returns {Token|null} The previous token or comment, or null if there is none.
|
|
337
|
+
*/
|
|
338
|
+
getTokenBefore(nodeOrToken, { includeComments = false } = {}) {
|
|
339
|
+
const index = this.#tokenStarts.get(nodeOrToken.range[0]);
|
|
340
|
+
|
|
341
|
+
if (index === undefined) {
|
|
342
|
+
return null;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
let previousIndex = index - 1;
|
|
346
|
+
if (previousIndex < 0) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const tokens = this.ast.tokens;
|
|
351
|
+
let tokenOrComment = tokens[previousIndex];
|
|
352
|
+
|
|
353
|
+
if (includeComments) {
|
|
354
|
+
return tokenOrComment;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// skip comments
|
|
358
|
+
while (tokenOrComment?.type.endsWith("Comment")) {
|
|
359
|
+
previousIndex--;
|
|
360
|
+
|
|
361
|
+
if (previousIndex < 0) {
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
tokenOrComment = tokens[previousIndex];
|
|
366
|
+
}
|
|
367
|
+
return tokenOrComment;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Gets the token after the given node or token, skipping any comments unless includeComments is true.
|
|
372
|
+
* @param {AnyNode|Token} nodeOrToken The node or token to get the next token for.
|
|
373
|
+
* @param {Object} [options] Options object.
|
|
374
|
+
* @param {boolean} [options.includeComments=false] If true, return comments when they are present.
|
|
375
|
+
* @returns {Token|null} The next token or comment, or null if there is none.
|
|
376
|
+
*/
|
|
377
|
+
getTokenAfter(nodeOrToken, { includeComments = false } = {}) {
|
|
378
|
+
const index = this.#tokenEnds.get(nodeOrToken.range[1]);
|
|
379
|
+
|
|
380
|
+
if (index === undefined) {
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
let nextIndex = index + 1;
|
|
385
|
+
const tokens = this.ast.tokens;
|
|
386
|
+
if (nextIndex >= tokens.length) {
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
let tokenOrComment = tokens[nextIndex];
|
|
391
|
+
|
|
392
|
+
if (includeComments) {
|
|
393
|
+
return tokenOrComment;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// skip comments
|
|
397
|
+
while (tokenOrComment?.type.endsWith("Comment")) {
|
|
398
|
+
nextIndex++;
|
|
399
|
+
|
|
400
|
+
if (nextIndex >= tokens.length) {
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
tokenOrComment = tokens[nextIndex];
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return tokenOrComment;
|
|
408
|
+
}
|
|
287
409
|
}
|
|
288
410
|
|
|
289
411
|
/**
|
|
290
|
-
* @
|
|
412
|
+
* @fileoverview The JSONLanguage class.
|
|
291
413
|
* @author Nicholas C. Zakas
|
|
292
414
|
*/
|
|
293
415
|
|
|
@@ -296,11 +418,14 @@ class JSONSourceCode extends pluginKit.TextSourceCodeBase {
|
|
|
296
418
|
// Types
|
|
297
419
|
//-----------------------------------------------------------------------------
|
|
298
420
|
|
|
299
|
-
/**
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
421
|
+
/**
|
|
422
|
+
*
|
|
423
|
+
* @typedef {OkParseResult<DocumentNode>} JSONOkParseResult
|
|
424
|
+
* @typedef {ParseResult<DocumentNode>} JSONParseResult
|
|
425
|
+
*
|
|
426
|
+
* @typedef {Object} JSONLanguageOptions
|
|
427
|
+
* @property {boolean} [allowTrailingCommas] Whether to allow trailing commas in JSONC mode.
|
|
428
|
+
*/
|
|
304
429
|
|
|
305
430
|
//-----------------------------------------------------------------------------
|
|
306
431
|
// Exports
|
|
@@ -308,7 +433,7 @@ class JSONSourceCode extends pluginKit.TextSourceCodeBase {
|
|
|
308
433
|
|
|
309
434
|
/**
|
|
310
435
|
* JSON Language Object
|
|
311
|
-
* @implements {
|
|
436
|
+
* @implements {Language<{ LangOptions: JSONLanguageOptions; Code: JSONSourceCode; RootNode: DocumentNode; Node: AnyNode }>}
|
|
312
437
|
*/
|
|
313
438
|
class JSONLanguage {
|
|
314
439
|
/**
|
|
@@ -385,7 +510,7 @@ class JSONLanguage {
|
|
|
385
510
|
* Parses the given file into an AST.
|
|
386
511
|
* @param {File} file The virtual file to parse.
|
|
387
512
|
* @param {{languageOptions: JSONLanguageOptions}} context The options to use for parsing.
|
|
388
|
-
* @returns {
|
|
513
|
+
* @returns {JSONParseResult} The result of parsing.
|
|
389
514
|
*/
|
|
390
515
|
parse(file, context) {
|
|
391
516
|
// Note: BOM already removed
|
|
@@ -433,7 +558,7 @@ class JSONLanguage {
|
|
|
433
558
|
/**
|
|
434
559
|
* Creates a new `JSONSourceCode` object from the given information.
|
|
435
560
|
* @param {File} file The virtual file to create a `JSONSourceCode` object from.
|
|
436
|
-
* @param {
|
|
561
|
+
* @param {JSONOkParseResult} parseResult The result returned from `parse()`.
|
|
437
562
|
* @returns {JSONSourceCode} The new `JSONSourceCode` object.
|
|
438
563
|
*/
|
|
439
564
|
createSourceCode(file, parseResult) {
|
|
@@ -445,6 +570,13 @@ class JSONLanguage {
|
|
|
445
570
|
/* eslint-enable class-methods-use-this -- Required to complete interface. */
|
|
446
571
|
}
|
|
447
572
|
|
|
573
|
+
const rules$1 = /** @type {const} */ ({
|
|
574
|
+
"json/no-duplicate-keys": "error",
|
|
575
|
+
"json/no-empty-keys": "error",
|
|
576
|
+
"json/no-unnormalized-keys": "error",
|
|
577
|
+
"json/no-unsafe-values": "error"
|
|
578
|
+
});
|
|
579
|
+
|
|
448
580
|
/**
|
|
449
581
|
* @fileoverview Rule to prevent duplicate keys in JSON.
|
|
450
582
|
* @author Nicholas C. Zakas
|
|
@@ -454,9 +586,11 @@ class JSONLanguage {
|
|
|
454
586
|
// Type Definitions
|
|
455
587
|
//-----------------------------------------------------------------------------
|
|
456
588
|
|
|
457
|
-
/**
|
|
458
|
-
|
|
459
|
-
|
|
589
|
+
/**
|
|
590
|
+
*
|
|
591
|
+
* @typedef {"duplicateKey"} NoDuplicateKeysMessageIds
|
|
592
|
+
* @typedef {JSONRuleDefinition<{ MessageIds: NoDuplicateKeysMessageIds }>} NoDuplicateKeysRuleDefinition
|
|
593
|
+
*/
|
|
460
594
|
|
|
461
595
|
//-----------------------------------------------------------------------------
|
|
462
596
|
// Rule Definition
|
|
@@ -468,7 +602,9 @@ const rule$5 = {
|
|
|
468
602
|
type: "problem",
|
|
469
603
|
|
|
470
604
|
docs: {
|
|
605
|
+
recommended: true,
|
|
471
606
|
description: "Disallow duplicate keys in JSON objects",
|
|
607
|
+
url: "https://github.com/eslint/json/tree/main/docs/rules/no-duplicate-keys.md",
|
|
472
608
|
},
|
|
473
609
|
|
|
474
610
|
messages: {
|
|
@@ -523,8 +659,11 @@ const rule$5 = {
|
|
|
523
659
|
// Type Definitions
|
|
524
660
|
//-----------------------------------------------------------------------------
|
|
525
661
|
|
|
526
|
-
/**
|
|
527
|
-
|
|
662
|
+
/**
|
|
663
|
+
*
|
|
664
|
+
* @typedef {"emptyKey"} NoEmptyKeysMessageIds
|
|
665
|
+
* @typedef {JSONRuleDefinition<{ MessageIds: NoEmptyKeysMessageIds }>} NoEmptyKeysRuleDefinition
|
|
666
|
+
*/
|
|
528
667
|
|
|
529
668
|
//-----------------------------------------------------------------------------
|
|
530
669
|
// Rule Definition
|
|
@@ -536,7 +675,9 @@ const rule$4 = {
|
|
|
536
675
|
type: "problem",
|
|
537
676
|
|
|
538
677
|
docs: {
|
|
678
|
+
recommended: true,
|
|
539
679
|
description: "Disallow empty keys in JSON objects",
|
|
680
|
+
url: "https://github.com/eslint/json/tree/main/docs/rules/no-empty-keys.md",
|
|
540
681
|
},
|
|
541
682
|
|
|
542
683
|
messages: {
|
|
@@ -563,6 +704,80 @@ const rule$4 = {
|
|
|
563
704
|
},
|
|
564
705
|
};
|
|
565
706
|
|
|
707
|
+
/**
|
|
708
|
+
* @fileoverview Rule to detect unnormalized keys in JSON.
|
|
709
|
+
* @author Bradley Meck Farias
|
|
710
|
+
*/
|
|
711
|
+
|
|
712
|
+
//-----------------------------------------------------------------------------
|
|
713
|
+
// Type Definitions
|
|
714
|
+
//-----------------------------------------------------------------------------
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
*
|
|
718
|
+
* @typedef {"unnormalizedKey"} NoUnnormalizedKeysMessageIds
|
|
719
|
+
* @typedef {{ form: string }} NoUnnormalizedKeysOptions
|
|
720
|
+
* @typedef {JSONRuleDefinition<{ RuleOptions: [NoUnnormalizedKeysOptions], MessageIds: NoUnnormalizedKeysMessageIds }>} NoUnnormalizedKeysRuleDefinition
|
|
721
|
+
*/
|
|
722
|
+
|
|
723
|
+
//-----------------------------------------------------------------------------
|
|
724
|
+
// Rule Definition
|
|
725
|
+
//-----------------------------------------------------------------------------
|
|
726
|
+
|
|
727
|
+
/** @type {NoUnnormalizedKeysRuleDefinition} */
|
|
728
|
+
const rule$3 = {
|
|
729
|
+
meta: {
|
|
730
|
+
type: "problem",
|
|
731
|
+
|
|
732
|
+
docs: {
|
|
733
|
+
recommended: true,
|
|
734
|
+
description: "Disallow JSON keys that are not normalized",
|
|
735
|
+
url: "https://github.com/eslint/json/tree/main/docs/rules/no-unnormalized-keys.md",
|
|
736
|
+
},
|
|
737
|
+
|
|
738
|
+
messages: {
|
|
739
|
+
unnormalizedKey: "Unnormalized key '{{key}}' found.",
|
|
740
|
+
},
|
|
741
|
+
|
|
742
|
+
schema: [
|
|
743
|
+
{
|
|
744
|
+
type: "object",
|
|
745
|
+
properties: {
|
|
746
|
+
form: {
|
|
747
|
+
enum: ["NFC", "NFD", "NFKC", "NFKD"],
|
|
748
|
+
},
|
|
749
|
+
},
|
|
750
|
+
additionalProperties: false,
|
|
751
|
+
},
|
|
752
|
+
],
|
|
753
|
+
},
|
|
754
|
+
|
|
755
|
+
create(context) {
|
|
756
|
+
const form = context.options.length
|
|
757
|
+
? context.options[0].form
|
|
758
|
+
: undefined;
|
|
759
|
+
|
|
760
|
+
return {
|
|
761
|
+
Member(node) {
|
|
762
|
+
const key =
|
|
763
|
+
node.name.type === "String"
|
|
764
|
+
? node.name.value
|
|
765
|
+
: node.name.name;
|
|
766
|
+
|
|
767
|
+
if (key.normalize(form) !== key) {
|
|
768
|
+
context.report({
|
|
769
|
+
loc: node.name.loc,
|
|
770
|
+
messageId: "unnormalizedKey",
|
|
771
|
+
data: {
|
|
772
|
+
key,
|
|
773
|
+
},
|
|
774
|
+
});
|
|
775
|
+
}
|
|
776
|
+
},
|
|
777
|
+
};
|
|
778
|
+
},
|
|
779
|
+
};
|
|
780
|
+
|
|
566
781
|
/**
|
|
567
782
|
* @fileoverview Rule to detect unsafe values in JSON.
|
|
568
783
|
* @author Bradley Meck Farias
|
|
@@ -572,8 +787,11 @@ const rule$4 = {
|
|
|
572
787
|
// Type Definitions
|
|
573
788
|
//-----------------------------------------------------------------------------
|
|
574
789
|
|
|
575
|
-
/**
|
|
576
|
-
|
|
790
|
+
/**
|
|
791
|
+
*
|
|
792
|
+
* @typedef {"unsafeNumber"|"unsafeInteger"|"unsafeZero"|"subnormal"|"loneSurrogate"} NoUnsafeValuesMessageIds
|
|
793
|
+
* @typedef {JSONRuleDefinition<{ MessageIds: NoUnsafeValuesMessageIds }>} NoUnsafeValuesRuleDefinition
|
|
794
|
+
*/
|
|
577
795
|
|
|
578
796
|
//-----------------------------------------------------------------------------
|
|
579
797
|
// Helpers
|
|
@@ -595,12 +813,14 @@ const NON_ZERO = /[1-9]/u;
|
|
|
595
813
|
//-----------------------------------------------------------------------------
|
|
596
814
|
|
|
597
815
|
/** @type {NoUnsafeValuesRuleDefinition} */
|
|
598
|
-
const rule$
|
|
816
|
+
const rule$2 = {
|
|
599
817
|
meta: {
|
|
600
818
|
type: "problem",
|
|
601
819
|
|
|
602
820
|
docs: {
|
|
821
|
+
recommended: true,
|
|
603
822
|
description: "Disallow JSON values that are unsafe for interchange",
|
|
823
|
+
url: "https://github.com/eslint/json/tree/main/docs/rules/no-unsafe-values.md",
|
|
604
824
|
},
|
|
605
825
|
|
|
606
826
|
messages: {
|
|
@@ -711,74 +931,6 @@ const rule$3 = {
|
|
|
711
931
|
},
|
|
712
932
|
};
|
|
713
933
|
|
|
714
|
-
/**
|
|
715
|
-
* @fileoverview Rule to detect unnormalized keys in JSON.
|
|
716
|
-
* @author Bradley Meck Farias
|
|
717
|
-
*/
|
|
718
|
-
|
|
719
|
-
//-----------------------------------------------------------------------------
|
|
720
|
-
// Type Definitions
|
|
721
|
-
//-----------------------------------------------------------------------------
|
|
722
|
-
|
|
723
|
-
/** @typedef {"unnormalizedKey"} NoUnnormalizedKeysMessageIds */
|
|
724
|
-
/** @typedef {import("./types.ts").JSONRuleDefinition<[{form:string}], NoUnnormalizedKeysMessageIds>} NoUnnormalizedKeysRuleDefinition */
|
|
725
|
-
|
|
726
|
-
//-----------------------------------------------------------------------------
|
|
727
|
-
// Rule Definition
|
|
728
|
-
//-----------------------------------------------------------------------------
|
|
729
|
-
|
|
730
|
-
/** @type {NoUnnormalizedKeysRuleDefinition} */
|
|
731
|
-
const rule$2 = {
|
|
732
|
-
meta: {
|
|
733
|
-
type: "problem",
|
|
734
|
-
|
|
735
|
-
docs: {
|
|
736
|
-
description: "Disallow JSON keys that are not normalized",
|
|
737
|
-
},
|
|
738
|
-
|
|
739
|
-
messages: {
|
|
740
|
-
unnormalizedKey: "Unnormalized key '{{key}}' found.",
|
|
741
|
-
},
|
|
742
|
-
|
|
743
|
-
schema: [
|
|
744
|
-
{
|
|
745
|
-
type: "object",
|
|
746
|
-
properties: {
|
|
747
|
-
form: {
|
|
748
|
-
enum: ["NFC", "NFD", "NFKC", "NFKD"],
|
|
749
|
-
},
|
|
750
|
-
},
|
|
751
|
-
additionalProperties: false,
|
|
752
|
-
},
|
|
753
|
-
],
|
|
754
|
-
},
|
|
755
|
-
|
|
756
|
-
create(context) {
|
|
757
|
-
const form = context.options.length
|
|
758
|
-
? context.options[0].form
|
|
759
|
-
: undefined;
|
|
760
|
-
|
|
761
|
-
return {
|
|
762
|
-
Member(node) {
|
|
763
|
-
const key =
|
|
764
|
-
node.name.type === "String"
|
|
765
|
-
? node.name.value
|
|
766
|
-
: node.name.name;
|
|
767
|
-
|
|
768
|
-
if (key.normalize(form) !== key) {
|
|
769
|
-
context.report({
|
|
770
|
-
loc: node.name.loc,
|
|
771
|
-
messageId: "unnormalizedKey",
|
|
772
|
-
data: {
|
|
773
|
-
key,
|
|
774
|
-
},
|
|
775
|
-
});
|
|
776
|
-
}
|
|
777
|
-
},
|
|
778
|
-
};
|
|
779
|
-
},
|
|
780
|
-
};
|
|
781
|
-
|
|
782
934
|
/**
|
|
783
935
|
* @fileoverview Rule to require JSON object keys to be sorted.
|
|
784
936
|
* Copied largely from https://github.com/eslint/eslint/blob/main/lib/rules/sort-keys.js
|
|
@@ -790,21 +942,21 @@ const rule$2 = {
|
|
|
790
942
|
// Type Definitions
|
|
791
943
|
//-----------------------------------------------------------------------------
|
|
792
944
|
|
|
793
|
-
/** @typedef {"sortKeys"} SortKeysMessageIds */
|
|
794
|
-
|
|
795
945
|
/**
|
|
946
|
+
*
|
|
796
947
|
* @typedef {Object} SortOptions
|
|
797
948
|
* @property {boolean} caseSensitive
|
|
798
949
|
* @property {boolean} natural
|
|
799
950
|
* @property {number} minKeys
|
|
800
951
|
* @property {boolean} allowLineSeparatedGroups
|
|
952
|
+
*
|
|
953
|
+
* @typedef {"sortKeys"} SortKeysMessageIds
|
|
954
|
+
* @typedef {"asc"|"desc"} SortDirection
|
|
955
|
+
* @typedef {[SortDirection, SortOptions]} SortKeysRuleOptions
|
|
956
|
+
* @typedef {JSONRuleDefinition<{ RuleOptions: SortKeysRuleOptions, MessageIds: SortKeysMessageIds }>} SortKeysRuleDefinition
|
|
957
|
+
* @typedef {(a:string,b:string) => boolean} Comparator
|
|
801
958
|
*/
|
|
802
959
|
|
|
803
|
-
/** @typedef {"asc"|"desc"} SortDirection */
|
|
804
|
-
/** @typedef {[SortDirection, SortOptions]} SortKeysRuleOptions */
|
|
805
|
-
/** @typedef {import("./types.ts").JSONRuleDefinition<SortKeysRuleOptions, SortKeysMessageIds>} SortKeysRuleDefinition */
|
|
806
|
-
/** @typedef {(a:string,b:string) => boolean} Comparator */
|
|
807
|
-
|
|
808
960
|
//-----------------------------------------------------------------------------
|
|
809
961
|
// Helpers
|
|
810
962
|
//-----------------------------------------------------------------------------
|
|
@@ -881,7 +1033,9 @@ const rule$1 = {
|
|
|
881
1033
|
],
|
|
882
1034
|
|
|
883
1035
|
docs: {
|
|
1036
|
+
recommended: false,
|
|
884
1037
|
description: `Require JSON object keys to be sorted`,
|
|
1038
|
+
url: "https://github.com/eslint/json/tree/main/docs/rules/sort-keys.md",
|
|
885
1039
|
},
|
|
886
1040
|
|
|
887
1041
|
messages: {
|
|
@@ -1010,7 +1164,7 @@ const rule$1 = {
|
|
|
1010
1164
|
};
|
|
1011
1165
|
|
|
1012
1166
|
/**
|
|
1013
|
-
* @fileoverview Rule to ensure top-level items are either an array or
|
|
1167
|
+
* @fileoverview Rule to ensure top-level items are either an array or object.
|
|
1014
1168
|
* @author Joe Hildebrand
|
|
1015
1169
|
*/
|
|
1016
1170
|
|
|
@@ -1018,8 +1172,11 @@ const rule$1 = {
|
|
|
1018
1172
|
// Type Definitions
|
|
1019
1173
|
//-----------------------------------------------------------------------------
|
|
1020
1174
|
|
|
1021
|
-
/**
|
|
1022
|
-
|
|
1175
|
+
/**
|
|
1176
|
+
*
|
|
1177
|
+
* @typedef {"topLevel"} TopLevelInteropMessageIds
|
|
1178
|
+
* @typedef {JSONRuleDefinition<{ MessageIds: TopLevelInteropMessageIds }>} TopLevelInteropRuleDefinition
|
|
1179
|
+
*/
|
|
1023
1180
|
|
|
1024
1181
|
//-----------------------------------------------------------------------------
|
|
1025
1182
|
// Rule Definition
|
|
@@ -1031,8 +1188,10 @@ const rule = {
|
|
|
1031
1188
|
type: "problem",
|
|
1032
1189
|
|
|
1033
1190
|
docs: {
|
|
1191
|
+
recommended: false,
|
|
1034
1192
|
description:
|
|
1035
1193
|
"Require the JSON top-level value to be an array or object",
|
|
1194
|
+
url: "https://github.com/eslint/json/tree/main/docs/rules/top-level-interop.md",
|
|
1036
1195
|
},
|
|
1037
1196
|
|
|
1038
1197
|
messages: {
|
|
@@ -1057,6 +1216,15 @@ const rule = {
|
|
|
1057
1216
|
},
|
|
1058
1217
|
};
|
|
1059
1218
|
|
|
1219
|
+
var rules = {
|
|
1220
|
+
"no-duplicate-keys": rule$5,
|
|
1221
|
+
"no-empty-keys": rule$4,
|
|
1222
|
+
"no-unnormalized-keys": rule$3,
|
|
1223
|
+
"no-unsafe-values": rule$2,
|
|
1224
|
+
"sort-keys": rule$1,
|
|
1225
|
+
"top-level-interop": rule,
|
|
1226
|
+
};
|
|
1227
|
+
|
|
1060
1228
|
/**
|
|
1061
1229
|
* @fileoverview JSON plugin.
|
|
1062
1230
|
* @author Nicholas C. Zakas
|
|
@@ -1070,30 +1238,18 @@ const rule = {
|
|
|
1070
1238
|
const plugin = {
|
|
1071
1239
|
meta: {
|
|
1072
1240
|
name: "@eslint/json",
|
|
1073
|
-
version: "0.
|
|
1241
|
+
version: "0.13.0", // x-release-please-version
|
|
1074
1242
|
},
|
|
1075
1243
|
languages: {
|
|
1076
1244
|
json: new JSONLanguage({ mode: "json" }),
|
|
1077
1245
|
jsonc: new JSONLanguage({ mode: "jsonc" }),
|
|
1078
1246
|
json5: new JSONLanguage({ mode: "json5" }),
|
|
1079
1247
|
},
|
|
1080
|
-
rules
|
|
1081
|
-
"no-duplicate-keys": rule$5,
|
|
1082
|
-
"no-empty-keys": rule$4,
|
|
1083
|
-
"no-unsafe-values": rule$3,
|
|
1084
|
-
"no-unnormalized-keys": rule$2,
|
|
1085
|
-
"sort-keys": rule$1,
|
|
1086
|
-
"top-level-interop": rule,
|
|
1087
|
-
},
|
|
1248
|
+
rules,
|
|
1088
1249
|
configs: {
|
|
1089
1250
|
recommended: {
|
|
1090
1251
|
plugins: {},
|
|
1091
|
-
rules:
|
|
1092
|
-
"json/no-duplicate-keys": "error",
|
|
1093
|
-
"json/no-empty-keys": "error",
|
|
1094
|
-
"json/no-unsafe-values": "error",
|
|
1095
|
-
"json/no-unnormalized-keys": "error",
|
|
1096
|
-
}),
|
|
1252
|
+
rules: rules$1,
|
|
1097
1253
|
},
|
|
1098
1254
|
},
|
|
1099
1255
|
};
|