@eslint/json 0.6.0 → 0.8.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 +3 -1
- package/dist/cjs/index.cjs +136 -13
- package/dist/cjs/index.d.cts +53 -3
- package/dist/esm/index.d.ts +53 -3
- package/dist/esm/index.js +136 -13
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -154,6 +154,8 @@ export default [
|
|
|
154
154
|
|
|
155
155
|
- `no-duplicate-keys` - warns when there are two keys in an object with the same text.
|
|
156
156
|
- `no-empty-keys` - warns when there is a key in an object that is an empty string or contains only whitespace (note: `package-lock.json` uses empty keys intentionally)
|
|
157
|
+
- `no-unsafe-values` - warns on values that are unsafe for interchange, such as numbers outside safe range or lone surrogates.
|
|
158
|
+
- `no-unnormalized-keys` - warns on keys containing [unnormalized characters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize#description). You can optionally specify the normalization form via `{ form: "form_name" }`, where `form_name` can be any of `"NFC"`, `"NFD"`, `"NFKC"`, or `"NFKD"`.
|
|
157
159
|
|
|
158
160
|
## Configuration Comments
|
|
159
161
|
|
|
@@ -249,7 +251,7 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).
|
|
|
249
251
|
<p><a href="https://automattic.com"><img src="https://images.opencollective.com/automattic/d0ef3e1/logo.png" alt="Automattic" height="128"></a> <a href="https://www.airbnb.com/"><img src="https://images.opencollective.com/airbnb/d327d66/logo.png" alt="Airbnb" height="128"></a></p><h3>Gold Sponsors</h3>
|
|
250
252
|
<p><a href="https://trunk.io/"><img src="https://images.opencollective.com/trunkio/fb92d60/avatar.png" alt="trunk.io" height="96"></a></p><h3>Silver Sponsors</h3>
|
|
251
253
|
<p><a href="https://www.serptriumph.com/"><img src="https://images.opencollective.com/serp-triumph5/fea3074/logo.png" alt="SERP Triumph" height="64"></a> <a href="https://www.jetbrains.com/"><img src="https://images.opencollective.com/jetbrains/fe76f99/logo.png" alt="JetBrains" height="64"></a> <a href="https://liftoff.io/"><img src="https://images.opencollective.com/liftoff/5c4fa84/logo.png" alt="Liftoff" height="64"></a> <a href="https://americanexpress.io"><img src="https://avatars.githubusercontent.com/u/3853301?v=4" alt="American Express" height="64"></a> <a href="https://www.workleap.com"><img src="https://avatars.githubusercontent.com/u/53535748?u=d1e55d7661d724bf2281c1bfd33cb8f99fe2465f&v=4" alt="Workleap" height="64"></a></p><h3>Bronze Sponsors</h3>
|
|
252
|
-
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://www.wordhint.net/"><img src="https://images.opencollective.com/wordhint/be86813/avatar.png" alt="WordHint" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340?v=4" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104?v=4" alt="Nx" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a></p>
|
|
254
|
+
<p><a href="https://cybozu.co.jp/"><img src="https://images.opencollective.com/cybozu/933e46d/logo.png" alt="Cybozu" height="32"></a> <a href="https://syntax.fm"><img src="https://github.com/syntaxfm.png" alt="Syntax" height="32"></a> <a href="https://www.wordhint.net/"><img src="https://images.opencollective.com/wordhint/be86813/avatar.png" alt="WordHint" height="32"></a> <a href="https://www.crosswordsolver.org/anagram-solver/"><img src="https://images.opencollective.com/anagram-solver/2666271/logo.png" alt="Anagram Solver" height="32"></a> <a href="https://icons8.com/"><img src="https://images.opencollective.com/icons8/7fa1641/logo.png" alt="Icons8" height="32"></a> <a href="https://discord.com"><img src="https://images.opencollective.com/discordapp/f9645d9/logo.png" alt="Discord" height="32"></a> <a href="https://www.gitbook.com"><img src="https://avatars.githubusercontent.com/u/7111340?v=4" alt="GitBook" height="32"></a> <a href="https://nx.dev"><img src="https://avatars.githubusercontent.com/u/23692104?v=4" alt="Nx" height="32"></a> <a href="https://herocoders.com"><img src="https://avatars.githubusercontent.com/u/37549774?v=4" alt="HeroCoders" height="32"></a></p>
|
|
253
255
|
<h3>Technology Sponsors</h3>
|
|
254
256
|
Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.
|
|
255
257
|
<p><a href="https://netlify.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/netlify-icon.svg" alt="Netlify" height="32"></a> <a href="https://algolia.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/algolia-icon.svg" alt="Algolia" height="32"></a> <a href="https://1password.com"><img src="https://raw.githubusercontent.com/eslint/eslint.org/main/src/assets/images/techsponsors/1password-icon.svg" alt="1Password" height="32"></a></p>
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -455,7 +455,7 @@ class JSONLanguage {
|
|
|
455
455
|
|
|
456
456
|
var noDuplicateKeys = {
|
|
457
457
|
meta: {
|
|
458
|
-
type: "problem",
|
|
458
|
+
type: /** @type {const} */ ("problem"),
|
|
459
459
|
|
|
460
460
|
docs: {
|
|
461
461
|
description: "Disallow duplicate keys in JSON objects",
|
|
@@ -508,7 +508,7 @@ var noDuplicateKeys = {
|
|
|
508
508
|
|
|
509
509
|
var noEmptyKeys = {
|
|
510
510
|
meta: {
|
|
511
|
-
type: "problem",
|
|
511
|
+
type: /** @type {const} */ ("problem"),
|
|
512
512
|
|
|
513
513
|
docs: {
|
|
514
514
|
description: "Disallow empty keys in JSON objects",
|
|
@@ -538,6 +538,122 @@ var noEmptyKeys = {
|
|
|
538
538
|
},
|
|
539
539
|
};
|
|
540
540
|
|
|
541
|
+
/**
|
|
542
|
+
* @fileoverview Rule to detect unsafe values in JSON.
|
|
543
|
+
* @author Bradley Meck Farias
|
|
544
|
+
*/
|
|
545
|
+
|
|
546
|
+
var noUnsafeValues = {
|
|
547
|
+
meta: {
|
|
548
|
+
type: /** @type {const} */ ("problem"),
|
|
549
|
+
|
|
550
|
+
docs: {
|
|
551
|
+
description: "Disallow JSON values that are unsafe for interchange",
|
|
552
|
+
},
|
|
553
|
+
|
|
554
|
+
messages: {
|
|
555
|
+
unsafeNumber: "Number outside safe range found.",
|
|
556
|
+
loneSurrogate: "Lone surrogate '{{ surrogate }}' found.",
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
|
|
560
|
+
create(context) {
|
|
561
|
+
return {
|
|
562
|
+
Number(node) {
|
|
563
|
+
if (Number.isFinite(node.value) !== true) {
|
|
564
|
+
context.report({
|
|
565
|
+
loc: node.loc,
|
|
566
|
+
messageId: "unsafeNumber",
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
String(node) {
|
|
571
|
+
if (node.value.isWellFormed) {
|
|
572
|
+
if (node.value.isWellFormed()) {
|
|
573
|
+
return;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
// match any high surrogate and, if it exists, a paired low surrogate
|
|
577
|
+
// match any low surrogate not already matched
|
|
578
|
+
const surrogatePattern =
|
|
579
|
+
/[\uD800-\uDBFF][\uDC00-\uDFFF]?|[\uDC00-\uDFFF]/gu;
|
|
580
|
+
let match = surrogatePattern.exec(node.value);
|
|
581
|
+
while (match) {
|
|
582
|
+
// only need to report non-paired surrogates
|
|
583
|
+
if (match[0].length < 2) {
|
|
584
|
+
context.report({
|
|
585
|
+
loc: node.loc,
|
|
586
|
+
messageId: "loneSurrogate",
|
|
587
|
+
data: {
|
|
588
|
+
surrogate: JSON.stringify(match[0]).slice(
|
|
589
|
+
1,
|
|
590
|
+
-1,
|
|
591
|
+
),
|
|
592
|
+
},
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
match = surrogatePattern.exec(node.value);
|
|
596
|
+
}
|
|
597
|
+
},
|
|
598
|
+
};
|
|
599
|
+
},
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* @fileoverview Rule to detect unnormalized keys in JSON.
|
|
604
|
+
* @author Bradley Meck Farias
|
|
605
|
+
*/
|
|
606
|
+
|
|
607
|
+
var noUnnormalizedKeys = {
|
|
608
|
+
meta: {
|
|
609
|
+
type: /** @type {const} */ ("problem"),
|
|
610
|
+
|
|
611
|
+
docs: {
|
|
612
|
+
description: "Disallow JSON keys that are not normalized",
|
|
613
|
+
},
|
|
614
|
+
|
|
615
|
+
messages: {
|
|
616
|
+
unnormalizedKey: "Unnormalized key '{{key}}' found.",
|
|
617
|
+
},
|
|
618
|
+
|
|
619
|
+
schema: [
|
|
620
|
+
{
|
|
621
|
+
type: "object",
|
|
622
|
+
properties: {
|
|
623
|
+
form: {
|
|
624
|
+
enum: ["NFC", "NFD", "NFKC", "NFKD"],
|
|
625
|
+
},
|
|
626
|
+
},
|
|
627
|
+
additionalProperties: false,
|
|
628
|
+
},
|
|
629
|
+
],
|
|
630
|
+
},
|
|
631
|
+
|
|
632
|
+
create(context) {
|
|
633
|
+
const normalization = context.options.length
|
|
634
|
+
? text => text.normalize(context.options[0].form)
|
|
635
|
+
: text => text.normalize();
|
|
636
|
+
return {
|
|
637
|
+
Member(node) {
|
|
638
|
+
const key =
|
|
639
|
+
node.name.type === "String"
|
|
640
|
+
? node.name.value
|
|
641
|
+
: node.name.name;
|
|
642
|
+
|
|
643
|
+
if (normalization(key) !== key) {
|
|
644
|
+
context.report({
|
|
645
|
+
loc: node.name.loc,
|
|
646
|
+
messageId: "unnormalizedKey",
|
|
647
|
+
data: {
|
|
648
|
+
key,
|
|
649
|
+
},
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
};
|
|
654
|
+
},
|
|
655
|
+
};
|
|
656
|
+
|
|
541
657
|
/**
|
|
542
658
|
* @fileoverview JSON plugin.
|
|
543
659
|
* @author Nicholas C. Zakas
|
|
@@ -551,7 +667,7 @@ var noEmptyKeys = {
|
|
|
551
667
|
const plugin = {
|
|
552
668
|
meta: {
|
|
553
669
|
name: "@eslint/json",
|
|
554
|
-
version: "0.
|
|
670
|
+
version: "0.8.0", // x-release-please-version
|
|
555
671
|
},
|
|
556
672
|
languages: {
|
|
557
673
|
json: new JSONLanguage({ mode: "json" }),
|
|
@@ -561,19 +677,26 @@ const plugin = {
|
|
|
561
677
|
rules: {
|
|
562
678
|
"no-duplicate-keys": noDuplicateKeys,
|
|
563
679
|
"no-empty-keys": noEmptyKeys,
|
|
680
|
+
"no-unsafe-values": noUnsafeValues,
|
|
681
|
+
"no-unnormalized-keys": noUnnormalizedKeys,
|
|
564
682
|
},
|
|
565
|
-
configs: {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
683
|
+
configs: {
|
|
684
|
+
recommended: {
|
|
685
|
+
plugins: {},
|
|
686
|
+
rules: /** @type {const} */ ({
|
|
687
|
+
"json/no-duplicate-keys": "error",
|
|
688
|
+
"json/no-empty-keys": "error",
|
|
689
|
+
"json/no-unsafe-values": "error",
|
|
690
|
+
"json/no-unnormalized-keys": "error",
|
|
691
|
+
}),
|
|
574
692
|
},
|
|
575
693
|
},
|
|
576
|
-
}
|
|
694
|
+
};
|
|
695
|
+
|
|
696
|
+
// eslint-disable-next-line no-lone-blocks -- The block syntax { ... } ensures that TypeScript does not get confused about the type of `plugin`.
|
|
697
|
+
{
|
|
698
|
+
plugin.configs.recommended.plugins.json = plugin;
|
|
699
|
+
}
|
|
577
700
|
|
|
578
701
|
exports.JSONLanguage = JSONLanguage;
|
|
579
702
|
exports.JSONSourceCode = JSONSourceCode;
|
package/dist/cjs/index.d.cts
CHANGED
|
@@ -174,7 +174,7 @@ declare namespace plugin {
|
|
|
174
174
|
let rules: {
|
|
175
175
|
"no-duplicate-keys": {
|
|
176
176
|
meta: {
|
|
177
|
-
type:
|
|
177
|
+
type: "problem";
|
|
178
178
|
docs: {
|
|
179
179
|
description: string;
|
|
180
180
|
};
|
|
@@ -190,7 +190,7 @@ declare namespace plugin {
|
|
|
190
190
|
};
|
|
191
191
|
"no-empty-keys": {
|
|
192
192
|
meta: {
|
|
193
|
-
type:
|
|
193
|
+
type: "problem";
|
|
194
194
|
docs: {
|
|
195
195
|
description: string;
|
|
196
196
|
};
|
|
@@ -202,8 +202,58 @@ declare namespace plugin {
|
|
|
202
202
|
Member(node: any): void;
|
|
203
203
|
};
|
|
204
204
|
};
|
|
205
|
+
"no-unsafe-values": {
|
|
206
|
+
meta: {
|
|
207
|
+
type: "problem";
|
|
208
|
+
docs: {
|
|
209
|
+
description: string;
|
|
210
|
+
};
|
|
211
|
+
messages: {
|
|
212
|
+
unsafeNumber: string;
|
|
213
|
+
loneSurrogate: string;
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
create(context: any): {
|
|
217
|
+
Number(node: any): void;
|
|
218
|
+
String(node: any): void;
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
"no-unnormalized-keys": {
|
|
222
|
+
meta: {
|
|
223
|
+
type: "problem";
|
|
224
|
+
docs: {
|
|
225
|
+
description: string;
|
|
226
|
+
};
|
|
227
|
+
messages: {
|
|
228
|
+
unnormalizedKey: string;
|
|
229
|
+
};
|
|
230
|
+
schema: {
|
|
231
|
+
type: string;
|
|
232
|
+
properties: {
|
|
233
|
+
form: {
|
|
234
|
+
enum: string[];
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
additionalProperties: boolean;
|
|
238
|
+
}[];
|
|
239
|
+
};
|
|
240
|
+
create(context: any): {
|
|
241
|
+
Member(node: any): void;
|
|
242
|
+
};
|
|
243
|
+
};
|
|
205
244
|
};
|
|
206
|
-
|
|
245
|
+
namespace configs {
|
|
246
|
+
namespace recommended {
|
|
247
|
+
export let plugins: {};
|
|
248
|
+
let rules_1: {
|
|
249
|
+
readonly "json/no-duplicate-keys": "error";
|
|
250
|
+
readonly "json/no-empty-keys": "error";
|
|
251
|
+
readonly "json/no-unsafe-values": "error";
|
|
252
|
+
readonly "json/no-unnormalized-keys": "error";
|
|
253
|
+
};
|
|
254
|
+
export { rules_1 as rules };
|
|
255
|
+
}
|
|
256
|
+
}
|
|
207
257
|
}
|
|
208
258
|
import { TextSourceCodeBase } from '@eslint/plugin-kit';
|
|
209
259
|
import { Directive } from '@eslint/plugin-kit';
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -174,7 +174,7 @@ declare namespace plugin {
|
|
|
174
174
|
let rules: {
|
|
175
175
|
"no-duplicate-keys": {
|
|
176
176
|
meta: {
|
|
177
|
-
type:
|
|
177
|
+
type: "problem";
|
|
178
178
|
docs: {
|
|
179
179
|
description: string;
|
|
180
180
|
};
|
|
@@ -190,7 +190,7 @@ declare namespace plugin {
|
|
|
190
190
|
};
|
|
191
191
|
"no-empty-keys": {
|
|
192
192
|
meta: {
|
|
193
|
-
type:
|
|
193
|
+
type: "problem";
|
|
194
194
|
docs: {
|
|
195
195
|
description: string;
|
|
196
196
|
};
|
|
@@ -202,8 +202,58 @@ declare namespace plugin {
|
|
|
202
202
|
Member(node: any): void;
|
|
203
203
|
};
|
|
204
204
|
};
|
|
205
|
+
"no-unsafe-values": {
|
|
206
|
+
meta: {
|
|
207
|
+
type: "problem";
|
|
208
|
+
docs: {
|
|
209
|
+
description: string;
|
|
210
|
+
};
|
|
211
|
+
messages: {
|
|
212
|
+
unsafeNumber: string;
|
|
213
|
+
loneSurrogate: string;
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
create(context: any): {
|
|
217
|
+
Number(node: any): void;
|
|
218
|
+
String(node: any): void;
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
"no-unnormalized-keys": {
|
|
222
|
+
meta: {
|
|
223
|
+
type: "problem";
|
|
224
|
+
docs: {
|
|
225
|
+
description: string;
|
|
226
|
+
};
|
|
227
|
+
messages: {
|
|
228
|
+
unnormalizedKey: string;
|
|
229
|
+
};
|
|
230
|
+
schema: {
|
|
231
|
+
type: string;
|
|
232
|
+
properties: {
|
|
233
|
+
form: {
|
|
234
|
+
enum: string[];
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
additionalProperties: boolean;
|
|
238
|
+
}[];
|
|
239
|
+
};
|
|
240
|
+
create(context: any): {
|
|
241
|
+
Member(node: any): void;
|
|
242
|
+
};
|
|
243
|
+
};
|
|
205
244
|
};
|
|
206
|
-
|
|
245
|
+
namespace configs {
|
|
246
|
+
namespace recommended {
|
|
247
|
+
export let plugins: {};
|
|
248
|
+
let rules_1: {
|
|
249
|
+
readonly "json/no-duplicate-keys": "error";
|
|
250
|
+
readonly "json/no-empty-keys": "error";
|
|
251
|
+
readonly "json/no-unsafe-values": "error";
|
|
252
|
+
readonly "json/no-unnormalized-keys": "error";
|
|
253
|
+
};
|
|
254
|
+
export { rules_1 as rules };
|
|
255
|
+
}
|
|
256
|
+
}
|
|
207
257
|
}
|
|
208
258
|
import { TextSourceCodeBase } from '@eslint/plugin-kit';
|
|
209
259
|
import { Directive } from '@eslint/plugin-kit';
|
package/dist/esm/index.js
CHANGED
|
@@ -452,7 +452,7 @@ class JSONLanguage {
|
|
|
452
452
|
|
|
453
453
|
var noDuplicateKeys = {
|
|
454
454
|
meta: {
|
|
455
|
-
type: "problem",
|
|
455
|
+
type: /** @type {const} */ ("problem"),
|
|
456
456
|
|
|
457
457
|
docs: {
|
|
458
458
|
description: "Disallow duplicate keys in JSON objects",
|
|
@@ -505,7 +505,7 @@ var noDuplicateKeys = {
|
|
|
505
505
|
|
|
506
506
|
var noEmptyKeys = {
|
|
507
507
|
meta: {
|
|
508
|
-
type: "problem",
|
|
508
|
+
type: /** @type {const} */ ("problem"),
|
|
509
509
|
|
|
510
510
|
docs: {
|
|
511
511
|
description: "Disallow empty keys in JSON objects",
|
|
@@ -535,6 +535,122 @@ var noEmptyKeys = {
|
|
|
535
535
|
},
|
|
536
536
|
};
|
|
537
537
|
|
|
538
|
+
/**
|
|
539
|
+
* @fileoverview Rule to detect unsafe values in JSON.
|
|
540
|
+
* @author Bradley Meck Farias
|
|
541
|
+
*/
|
|
542
|
+
|
|
543
|
+
var noUnsafeValues = {
|
|
544
|
+
meta: {
|
|
545
|
+
type: /** @type {const} */ ("problem"),
|
|
546
|
+
|
|
547
|
+
docs: {
|
|
548
|
+
description: "Disallow JSON values that are unsafe for interchange",
|
|
549
|
+
},
|
|
550
|
+
|
|
551
|
+
messages: {
|
|
552
|
+
unsafeNumber: "Number outside safe range found.",
|
|
553
|
+
loneSurrogate: "Lone surrogate '{{ surrogate }}' found.",
|
|
554
|
+
},
|
|
555
|
+
},
|
|
556
|
+
|
|
557
|
+
create(context) {
|
|
558
|
+
return {
|
|
559
|
+
Number(node) {
|
|
560
|
+
if (Number.isFinite(node.value) !== true) {
|
|
561
|
+
context.report({
|
|
562
|
+
loc: node.loc,
|
|
563
|
+
messageId: "unsafeNumber",
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
},
|
|
567
|
+
String(node) {
|
|
568
|
+
if (node.value.isWellFormed) {
|
|
569
|
+
if (node.value.isWellFormed()) {
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
// match any high surrogate and, if it exists, a paired low surrogate
|
|
574
|
+
// match any low surrogate not already matched
|
|
575
|
+
const surrogatePattern =
|
|
576
|
+
/[\uD800-\uDBFF][\uDC00-\uDFFF]?|[\uDC00-\uDFFF]/gu;
|
|
577
|
+
let match = surrogatePattern.exec(node.value);
|
|
578
|
+
while (match) {
|
|
579
|
+
// only need to report non-paired surrogates
|
|
580
|
+
if (match[0].length < 2) {
|
|
581
|
+
context.report({
|
|
582
|
+
loc: node.loc,
|
|
583
|
+
messageId: "loneSurrogate",
|
|
584
|
+
data: {
|
|
585
|
+
surrogate: JSON.stringify(match[0]).slice(
|
|
586
|
+
1,
|
|
587
|
+
-1,
|
|
588
|
+
),
|
|
589
|
+
},
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
match = surrogatePattern.exec(node.value);
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
};
|
|
596
|
+
},
|
|
597
|
+
};
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* @fileoverview Rule to detect unnormalized keys in JSON.
|
|
601
|
+
* @author Bradley Meck Farias
|
|
602
|
+
*/
|
|
603
|
+
|
|
604
|
+
var noUnnormalizedKeys = {
|
|
605
|
+
meta: {
|
|
606
|
+
type: /** @type {const} */ ("problem"),
|
|
607
|
+
|
|
608
|
+
docs: {
|
|
609
|
+
description: "Disallow JSON keys that are not normalized",
|
|
610
|
+
},
|
|
611
|
+
|
|
612
|
+
messages: {
|
|
613
|
+
unnormalizedKey: "Unnormalized key '{{key}}' found.",
|
|
614
|
+
},
|
|
615
|
+
|
|
616
|
+
schema: [
|
|
617
|
+
{
|
|
618
|
+
type: "object",
|
|
619
|
+
properties: {
|
|
620
|
+
form: {
|
|
621
|
+
enum: ["NFC", "NFD", "NFKC", "NFKD"],
|
|
622
|
+
},
|
|
623
|
+
},
|
|
624
|
+
additionalProperties: false,
|
|
625
|
+
},
|
|
626
|
+
],
|
|
627
|
+
},
|
|
628
|
+
|
|
629
|
+
create(context) {
|
|
630
|
+
const normalization = context.options.length
|
|
631
|
+
? text => text.normalize(context.options[0].form)
|
|
632
|
+
: text => text.normalize();
|
|
633
|
+
return {
|
|
634
|
+
Member(node) {
|
|
635
|
+
const key =
|
|
636
|
+
node.name.type === "String"
|
|
637
|
+
? node.name.value
|
|
638
|
+
: node.name.name;
|
|
639
|
+
|
|
640
|
+
if (normalization(key) !== key) {
|
|
641
|
+
context.report({
|
|
642
|
+
loc: node.name.loc,
|
|
643
|
+
messageId: "unnormalizedKey",
|
|
644
|
+
data: {
|
|
645
|
+
key,
|
|
646
|
+
},
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
},
|
|
650
|
+
};
|
|
651
|
+
},
|
|
652
|
+
};
|
|
653
|
+
|
|
538
654
|
/**
|
|
539
655
|
* @fileoverview JSON plugin.
|
|
540
656
|
* @author Nicholas C. Zakas
|
|
@@ -548,7 +664,7 @@ var noEmptyKeys = {
|
|
|
548
664
|
const plugin = {
|
|
549
665
|
meta: {
|
|
550
666
|
name: "@eslint/json",
|
|
551
|
-
version: "0.
|
|
667
|
+
version: "0.8.0", // x-release-please-version
|
|
552
668
|
},
|
|
553
669
|
languages: {
|
|
554
670
|
json: new JSONLanguage({ mode: "json" }),
|
|
@@ -558,18 +674,25 @@ const plugin = {
|
|
|
558
674
|
rules: {
|
|
559
675
|
"no-duplicate-keys": noDuplicateKeys,
|
|
560
676
|
"no-empty-keys": noEmptyKeys,
|
|
677
|
+
"no-unsafe-values": noUnsafeValues,
|
|
678
|
+
"no-unnormalized-keys": noUnnormalizedKeys,
|
|
561
679
|
},
|
|
562
|
-
configs: {
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
680
|
+
configs: {
|
|
681
|
+
recommended: {
|
|
682
|
+
plugins: {},
|
|
683
|
+
rules: /** @type {const} */ ({
|
|
684
|
+
"json/no-duplicate-keys": "error",
|
|
685
|
+
"json/no-empty-keys": "error",
|
|
686
|
+
"json/no-unsafe-values": "error",
|
|
687
|
+
"json/no-unnormalized-keys": "error",
|
|
688
|
+
}),
|
|
571
689
|
},
|
|
572
690
|
},
|
|
573
|
-
}
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
// eslint-disable-next-line no-lone-blocks -- The block syntax { ... } ensures that TypeScript does not get confused about the type of `plugin`.
|
|
694
|
+
{
|
|
695
|
+
plugin.configs.recommended.plugins.json = plugin;
|
|
696
|
+
}
|
|
574
697
|
|
|
575
698
|
export { JSONLanguage, JSONSourceCode, plugin as default };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eslint/json",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "JSON linting plugin for ESLint",
|
|
5
5
|
"author": "Nicholas C. Zakas",
|
|
6
6
|
"type": "module",
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
"fmt": "prettier --write .",
|
|
52
52
|
"fmt:check": "prettier --check .",
|
|
53
53
|
"test": "mocha tests/**/*.js",
|
|
54
|
-
"test:coverage": "c8 npm test"
|
|
54
|
+
"test:coverage": "c8 npm test",
|
|
55
|
+
"test:types": "tsc -p tests/types/tsconfig.json"
|
|
55
56
|
},
|
|
56
57
|
"keywords": [
|
|
57
58
|
"eslint",
|
|
@@ -62,8 +63,8 @@
|
|
|
62
63
|
],
|
|
63
64
|
"license": "Apache-2.0",
|
|
64
65
|
"dependencies": {
|
|
65
|
-
"@eslint/plugin-kit": "^0.2.
|
|
66
|
-
"@humanwhocodes/momoa": "^3.3.
|
|
66
|
+
"@eslint/plugin-kit": "^0.2.3",
|
|
67
|
+
"@humanwhocodes/momoa": "^3.3.3"
|
|
67
68
|
},
|
|
68
69
|
"devDependencies": {
|
|
69
70
|
"@eslint/core": "^0.6.0",
|
|
@@ -72,6 +73,7 @@
|
|
|
72
73
|
"dedent": "^1.5.3",
|
|
73
74
|
"eslint": "^9.11.1",
|
|
74
75
|
"eslint-config-eslint": "^11.0.0",
|
|
76
|
+
"eslint-plugin-eslint-plugin": "^6.3.2",
|
|
75
77
|
"got": "^14.4.2",
|
|
76
78
|
"lint-staged": "^15.2.7",
|
|
77
79
|
"mocha": "^10.4.0",
|