@eslint/json 0.9.1 → 0.11.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 +4 -3
- package/dist/cjs/index.cjs +334 -30
- package/dist/cjs/index.d.cts +39 -99
- package/dist/cjs/types.cts +138 -0
- package/dist/esm/index.d.ts +39 -99
- package/dist/esm/index.js +334 -30
- package/dist/esm/types.d.ts +91 -0
- package/dist/esm/types.ts +138 -0
- package/package.json +22 -12
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @ts-self-types="./index.d.ts"
|
|
2
2
|
import { iterator, visitorKeys, parse } from '@humanwhocodes/momoa';
|
|
3
3
|
import { ConfigCommentParser, TextSourceCodeBase, Directive, VisitNodeStep } from '@eslint/plugin-kit';
|
|
4
|
+
import naturalCompare from 'natural-compare';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @fileoverview The JSONSourceCode class.
|
|
@@ -19,11 +20,12 @@ import { ConfigCommentParser, TextSourceCodeBase, Directive, VisitNodeStep } fro
|
|
|
19
20
|
/** @typedef {import("@eslint/core").SourceLocation} SourceLocation */
|
|
20
21
|
/** @typedef {import("@eslint/core").File} File */
|
|
21
22
|
/** @typedef {import("@eslint/core").TraversalStep} TraversalStep */
|
|
22
|
-
/** @typedef {import("@eslint/core").TextSourceCode} TextSourceCode */
|
|
23
23
|
/** @typedef {import("@eslint/core").VisitTraversalStep} VisitTraversalStep */
|
|
24
24
|
/** @typedef {import("@eslint/core").FileProblem} FileProblem */
|
|
25
25
|
/** @typedef {import("@eslint/core").DirectiveType} DirectiveType */
|
|
26
26
|
/** @typedef {import("@eslint/core").RulesConfig} RulesConfig */
|
|
27
|
+
/** @typedef {import("./types.ts").IJSONSourceCode} IJSONSourceCode */
|
|
28
|
+
/** @typedef {import("./types.ts").JSONSyntaxElement} JSONSyntaxElement */
|
|
27
29
|
|
|
28
30
|
//-----------------------------------------------------------------------------
|
|
29
31
|
// Helpers
|
|
@@ -64,6 +66,7 @@ class JSONTraversalStep extends VisitNodeStep {
|
|
|
64
66
|
|
|
65
67
|
/**
|
|
66
68
|
* JSON Source Code Object
|
|
69
|
+
* @implements {IJSONSourceCode}
|
|
67
70
|
*/
|
|
68
71
|
class JSONSourceCode extends TextSourceCodeBase {
|
|
69
72
|
/**
|
|
@@ -140,7 +143,7 @@ class JSONSourceCode extends TextSourceCodeBase {
|
|
|
140
143
|
);
|
|
141
144
|
}
|
|
142
145
|
|
|
143
|
-
return this.#inlineConfigComments;
|
|
146
|
+
return this.#inlineConfigComments ?? [];
|
|
144
147
|
}
|
|
145
148
|
|
|
146
149
|
/**
|
|
@@ -293,10 +296,8 @@ class JSONSourceCode extends TextSourceCodeBase {
|
|
|
293
296
|
/** @typedef {import("@eslint/core").Language} Language */
|
|
294
297
|
/** @typedef {import("@eslint/core").OkParseResult<DocumentNode>} OkParseResult */
|
|
295
298
|
/** @typedef {import("@eslint/core").ParseResult<DocumentNode>} ParseResult */
|
|
296
|
-
/**
|
|
297
|
-
|
|
298
|
-
* @property {boolean} [allowTrailingCommas] Whether to allow trailing commas.
|
|
299
|
-
*/
|
|
299
|
+
/** @typedef {import("./types.ts").IJSONLanguage} IJSONLanguage */
|
|
300
|
+
/** @typedef {import("./types.ts").JSONLanguageOptions} JSONLanguageOptions */
|
|
300
301
|
|
|
301
302
|
//-----------------------------------------------------------------------------
|
|
302
303
|
// Exports
|
|
@@ -304,7 +305,7 @@ class JSONSourceCode extends TextSourceCodeBase {
|
|
|
304
305
|
|
|
305
306
|
/**
|
|
306
307
|
* JSON Language Object
|
|
307
|
-
* @implements {
|
|
308
|
+
* @implements {IJSONLanguage}
|
|
308
309
|
*/
|
|
309
310
|
class JSONLanguage {
|
|
310
311
|
/**
|
|
@@ -446,13 +447,22 @@ class JSONLanguage {
|
|
|
446
447
|
* @author Nicholas C. Zakas
|
|
447
448
|
*/
|
|
448
449
|
|
|
450
|
+
//-----------------------------------------------------------------------------
|
|
451
|
+
// Type Definitions
|
|
452
|
+
//-----------------------------------------------------------------------------
|
|
453
|
+
|
|
454
|
+
/** @typedef {"duplicateKey"} NoDuplicateKeysMessageIds */
|
|
455
|
+
/** @typedef {import("./types.ts").JSONRuleDefinition<[], NoDuplicateKeysMessageIds>} NoDuplicateKeysRuleDefinition */
|
|
456
|
+
/** @typedef {import("@humanwhocodes/momoa").MemberNode} MemberNode */
|
|
457
|
+
|
|
449
458
|
//-----------------------------------------------------------------------------
|
|
450
459
|
// Rule Definition
|
|
451
460
|
//-----------------------------------------------------------------------------
|
|
452
461
|
|
|
453
|
-
|
|
462
|
+
/** @type {NoDuplicateKeysRuleDefinition} */
|
|
463
|
+
const rule$5 = {
|
|
454
464
|
meta: {
|
|
455
|
-
type:
|
|
465
|
+
type: "problem",
|
|
456
466
|
|
|
457
467
|
docs: {
|
|
458
468
|
description: "Disallow duplicate keys in JSON objects",
|
|
@@ -464,7 +474,10 @@ var noDuplicateKeys = {
|
|
|
464
474
|
},
|
|
465
475
|
|
|
466
476
|
create(context) {
|
|
477
|
+
/** @type {Array<Map<string, MemberNode>|undefined>} */
|
|
467
478
|
const objectKeys = [];
|
|
479
|
+
|
|
480
|
+
/** @type {Map<string, MemberNode>|undefined} */
|
|
468
481
|
let keys;
|
|
469
482
|
|
|
470
483
|
return {
|
|
@@ -503,9 +516,21 @@ var noDuplicateKeys = {
|
|
|
503
516
|
* @author Nicholas C. Zakas
|
|
504
517
|
*/
|
|
505
518
|
|
|
506
|
-
|
|
519
|
+
//-----------------------------------------------------------------------------
|
|
520
|
+
// Type Definitions
|
|
521
|
+
//-----------------------------------------------------------------------------
|
|
522
|
+
|
|
523
|
+
/** @typedef {"emptyKey"} NoEmptyKeysMessageIds */
|
|
524
|
+
/** @typedef {import("./types.ts").JSONRuleDefinition<[], NoEmptyKeysMessageIds>} NoEmptyKeysRuleDefinition */
|
|
525
|
+
|
|
526
|
+
//-----------------------------------------------------------------------------
|
|
527
|
+
// Rule Definition
|
|
528
|
+
//-----------------------------------------------------------------------------
|
|
529
|
+
|
|
530
|
+
/** @type {NoEmptyKeysRuleDefinition} */
|
|
531
|
+
const rule$4 = {
|
|
507
532
|
meta: {
|
|
508
|
-
type:
|
|
533
|
+
type: "problem",
|
|
509
534
|
|
|
510
535
|
docs: {
|
|
511
536
|
description: "Disallow empty keys in JSON objects",
|
|
@@ -540,15 +565,36 @@ var noEmptyKeys = {
|
|
|
540
565
|
* @author Bradley Meck Farias
|
|
541
566
|
*/
|
|
542
567
|
|
|
543
|
-
|
|
544
|
-
//
|
|
568
|
+
//-----------------------------------------------------------------------------
|
|
569
|
+
// Type Definitions
|
|
570
|
+
//-----------------------------------------------------------------------------
|
|
571
|
+
|
|
572
|
+
/** @typedef {"unsafeNumber"|"unsafeInteger"|"unsafeZero"|"subnormal"|"loneSurrogate"} NoUnsafeValuesMessageIds */
|
|
573
|
+
/** @typedef {import("./types.ts").JSONRuleDefinition<[], NoUnsafeValuesMessageIds>} NoUnsafeValuesRuleDefinition */
|
|
574
|
+
|
|
575
|
+
//-----------------------------------------------------------------------------
|
|
576
|
+
// Helpers
|
|
577
|
+
//-----------------------------------------------------------------------------
|
|
578
|
+
|
|
579
|
+
/*
|
|
580
|
+
* This rule is based on the JSON grammar from RFC 8259, section 6.
|
|
581
|
+
* https://tools.ietf.org/html/rfc8259#section-6
|
|
582
|
+
*
|
|
583
|
+
* We separately capture the integer and fractional parts of a number, so that
|
|
584
|
+
* we can check for unsafe numbers that will evaluate to Infinity.
|
|
585
|
+
*/
|
|
545
586
|
const NUMBER =
|
|
546
587
|
/^-?(?<int>0|([1-9][0-9]*))(?:\.(?<frac>[0-9]+))?(?:[eE][+-]?[0-9]+)?$/u;
|
|
547
588
|
const NON_ZERO = /[1-9]/u;
|
|
548
589
|
|
|
549
|
-
|
|
590
|
+
//-----------------------------------------------------------------------------
|
|
591
|
+
// Rule Definition
|
|
592
|
+
//-----------------------------------------------------------------------------
|
|
593
|
+
|
|
594
|
+
/** @type {NoUnsafeValuesRuleDefinition} */
|
|
595
|
+
const rule$3 = {
|
|
550
596
|
meta: {
|
|
551
|
-
type:
|
|
597
|
+
type: "problem",
|
|
552
598
|
|
|
553
599
|
docs: {
|
|
554
600
|
description: "Disallow JSON values that are unsafe for interchange",
|
|
@@ -622,7 +668,9 @@ var noUnsafeValues = {
|
|
|
622
668
|
loc: node.loc,
|
|
623
669
|
messageId: "subnormal",
|
|
624
670
|
// Value included so that it's seen in scientific notation
|
|
625
|
-
data:
|
|
671
|
+
data: {
|
|
672
|
+
value,
|
|
673
|
+
},
|
|
626
674
|
});
|
|
627
675
|
}
|
|
628
676
|
}
|
|
@@ -665,9 +713,21 @@ var noUnsafeValues = {
|
|
|
665
713
|
* @author Bradley Meck Farias
|
|
666
714
|
*/
|
|
667
715
|
|
|
668
|
-
|
|
716
|
+
//-----------------------------------------------------------------------------
|
|
717
|
+
// Type Definitions
|
|
718
|
+
//-----------------------------------------------------------------------------
|
|
719
|
+
|
|
720
|
+
/** @typedef {"unnormalizedKey"} NoUnnormalizedKeysMessageIds */
|
|
721
|
+
/** @typedef {import("./types.ts").JSONRuleDefinition<[{form:string}], NoUnnormalizedKeysMessageIds>} NoUnnormalizedKeysRuleDefinition */
|
|
722
|
+
|
|
723
|
+
//-----------------------------------------------------------------------------
|
|
724
|
+
// Rule Definition
|
|
725
|
+
//-----------------------------------------------------------------------------
|
|
726
|
+
|
|
727
|
+
/** @type {NoUnnormalizedKeysRuleDefinition} */
|
|
728
|
+
const rule$2 = {
|
|
669
729
|
meta: {
|
|
670
|
-
type:
|
|
730
|
+
type: "problem",
|
|
671
731
|
|
|
672
732
|
docs: {
|
|
673
733
|
description: "Disallow JSON keys that are not normalized",
|
|
@@ -691,9 +751,10 @@ var noUnnormalizedKeys = {
|
|
|
691
751
|
},
|
|
692
752
|
|
|
693
753
|
create(context) {
|
|
694
|
-
const
|
|
695
|
-
?
|
|
696
|
-
:
|
|
754
|
+
const form = context.options.length
|
|
755
|
+
? context.options[0].form
|
|
756
|
+
: undefined;
|
|
757
|
+
|
|
697
758
|
return {
|
|
698
759
|
Member(node) {
|
|
699
760
|
const key =
|
|
@@ -701,7 +762,7 @@ var noUnnormalizedKeys = {
|
|
|
701
762
|
? node.name.value
|
|
702
763
|
: node.name.name;
|
|
703
764
|
|
|
704
|
-
if (
|
|
765
|
+
if (key.normalize(form) !== key) {
|
|
705
766
|
context.report({
|
|
706
767
|
loc: node.name.loc,
|
|
707
768
|
messageId: "unnormalizedKey",
|
|
@@ -715,14 +776,256 @@ var noUnnormalizedKeys = {
|
|
|
715
776
|
},
|
|
716
777
|
};
|
|
717
778
|
|
|
779
|
+
/**
|
|
780
|
+
* @fileoverview Rule to require JSON object keys to be sorted.
|
|
781
|
+
* Copied largely from https://github.com/eslint/eslint/blob/main/lib/rules/sort-keys.js
|
|
782
|
+
* @author Robin Thomas
|
|
783
|
+
*/
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
//-----------------------------------------------------------------------------
|
|
787
|
+
// Type Definitions
|
|
788
|
+
//-----------------------------------------------------------------------------
|
|
789
|
+
|
|
790
|
+
/** @typedef {"sortKeys"} SortKeysMessageIds */
|
|
791
|
+
|
|
792
|
+
/**
|
|
793
|
+
* @typedef {Object} SortOptions
|
|
794
|
+
* @property {boolean} caseSensitive
|
|
795
|
+
* @property {boolean} natural
|
|
796
|
+
* @property {number} minKeys
|
|
797
|
+
* @property {boolean} allowLineSeparatedGroups
|
|
798
|
+
*/
|
|
799
|
+
|
|
800
|
+
/** @typedef {"asc"|"desc"} SortDirection */
|
|
801
|
+
/** @typedef {[SortDirection, SortOptions]} SortKeysRuleOptions */
|
|
802
|
+
/** @typedef {import("./types.ts").JSONRuleDefinition<SortKeysRuleOptions, SortKeysMessageIds>} SortKeysRuleDefinition */
|
|
803
|
+
/** @typedef {(a:string,b:string) => boolean} Comparator */
|
|
804
|
+
|
|
805
|
+
//-----------------------------------------------------------------------------
|
|
806
|
+
// Helpers
|
|
807
|
+
//-----------------------------------------------------------------------------
|
|
808
|
+
|
|
809
|
+
const hasNonWhitespace = /\S/u;
|
|
810
|
+
|
|
811
|
+
const comparators = {
|
|
812
|
+
ascending: {
|
|
813
|
+
alphanumeric: {
|
|
814
|
+
/** @type {Comparator} */
|
|
815
|
+
sensitive: (a, b) => a <= b,
|
|
816
|
+
|
|
817
|
+
/** @type {Comparator} */
|
|
818
|
+
insensitive: (a, b) => a.toLowerCase() <= b.toLowerCase(),
|
|
819
|
+
},
|
|
820
|
+
natural: {
|
|
821
|
+
/** @type {Comparator} */
|
|
822
|
+
sensitive: (a, b) => naturalCompare(a, b) <= 0,
|
|
823
|
+
|
|
824
|
+
/** @type {Comparator} */
|
|
825
|
+
insensitive: (a, b) =>
|
|
826
|
+
naturalCompare(a.toLowerCase(), b.toLowerCase()) <= 0,
|
|
827
|
+
},
|
|
828
|
+
},
|
|
829
|
+
descending: {
|
|
830
|
+
alphanumeric: {
|
|
831
|
+
/** @type {Comparator} */
|
|
832
|
+
sensitive: (a, b) =>
|
|
833
|
+
comparators.ascending.alphanumeric.sensitive(b, a),
|
|
834
|
+
|
|
835
|
+
/** @type {Comparator} */
|
|
836
|
+
insensitive: (a, b) =>
|
|
837
|
+
comparators.ascending.alphanumeric.insensitive(b, a),
|
|
838
|
+
},
|
|
839
|
+
natural: {
|
|
840
|
+
/** @type {Comparator} */
|
|
841
|
+
sensitive: (a, b) => comparators.ascending.natural.sensitive(b, a),
|
|
842
|
+
|
|
843
|
+
/** @type {Comparator} */
|
|
844
|
+
insensitive: (a, b) =>
|
|
845
|
+
comparators.ascending.natural.insensitive(b, a),
|
|
846
|
+
},
|
|
847
|
+
},
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* Gets the MemberNode's string key value.
|
|
852
|
+
* @param {MemberNode} member
|
|
853
|
+
* @return {string}
|
|
854
|
+
*/
|
|
855
|
+
function getKey(member) {
|
|
856
|
+
return member.name.type === "Identifier"
|
|
857
|
+
? member.name.name
|
|
858
|
+
: member.name.value;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
//-----------------------------------------------------------------------------
|
|
862
|
+
// Rule Definition
|
|
863
|
+
//-----------------------------------------------------------------------------
|
|
864
|
+
|
|
865
|
+
/** @type {SortKeysRuleDefinition} */
|
|
866
|
+
const rule$1 = {
|
|
867
|
+
meta: {
|
|
868
|
+
type: "suggestion",
|
|
869
|
+
|
|
870
|
+
defaultOptions: [
|
|
871
|
+
"asc",
|
|
872
|
+
{
|
|
873
|
+
allowLineSeparatedGroups: false,
|
|
874
|
+
caseSensitive: true,
|
|
875
|
+
minKeys: 2,
|
|
876
|
+
natural: false,
|
|
877
|
+
},
|
|
878
|
+
],
|
|
879
|
+
|
|
880
|
+
docs: {
|
|
881
|
+
description: `Require JSON object keys to be sorted`,
|
|
882
|
+
},
|
|
883
|
+
|
|
884
|
+
messages: {
|
|
885
|
+
sortKeys:
|
|
886
|
+
"Expected object keys to be in {{sortName}} case-{{sensitivity}} {{direction}} order. '{{thisName}}' should be before '{{prevName}}'.",
|
|
887
|
+
},
|
|
888
|
+
|
|
889
|
+
schema: [
|
|
890
|
+
{
|
|
891
|
+
enum: ["asc", "desc"],
|
|
892
|
+
},
|
|
893
|
+
{
|
|
894
|
+
type: "object",
|
|
895
|
+
properties: {
|
|
896
|
+
caseSensitive: {
|
|
897
|
+
type: "boolean",
|
|
898
|
+
},
|
|
899
|
+
natural: {
|
|
900
|
+
type: "boolean",
|
|
901
|
+
},
|
|
902
|
+
minKeys: {
|
|
903
|
+
type: "integer",
|
|
904
|
+
minimum: 2,
|
|
905
|
+
},
|
|
906
|
+
allowLineSeparatedGroups: {
|
|
907
|
+
type: "boolean",
|
|
908
|
+
},
|
|
909
|
+
},
|
|
910
|
+
additionalProperties: false,
|
|
911
|
+
},
|
|
912
|
+
],
|
|
913
|
+
},
|
|
914
|
+
|
|
915
|
+
create(context) {
|
|
916
|
+
const [
|
|
917
|
+
directionShort,
|
|
918
|
+
{ allowLineSeparatedGroups, caseSensitive, natural, minKeys },
|
|
919
|
+
] = context.options;
|
|
920
|
+
|
|
921
|
+
const direction = directionShort === "asc" ? "ascending" : "descending";
|
|
922
|
+
const sortName = natural ? "natural" : "alphanumeric";
|
|
923
|
+
const sensitivity = caseSensitive ? "sensitive" : "insensitive";
|
|
924
|
+
const isValidOrder = comparators[direction][sortName][sensitivity];
|
|
925
|
+
|
|
926
|
+
// Note that @humanwhocodes/momoa doesn't include comments in the object.members tree, so we can't just see if a member is preceded by a comment
|
|
927
|
+
const commentLineNums = new Set();
|
|
928
|
+
for (const comment of context.sourceCode.comments) {
|
|
929
|
+
for (
|
|
930
|
+
let lineNum = comment.loc.start.line;
|
|
931
|
+
lineNum <= comment.loc.end.line;
|
|
932
|
+
lineNum += 1
|
|
933
|
+
) {
|
|
934
|
+
commentLineNums.add(lineNum);
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/**
|
|
939
|
+
* Checks if two members are line-separated.
|
|
940
|
+
* @param {MemberNode} prevMember The previous member.
|
|
941
|
+
* @param {MemberNode} member The current member.
|
|
942
|
+
* @return {boolean}
|
|
943
|
+
*/
|
|
944
|
+
function isLineSeparated(prevMember, member) {
|
|
945
|
+
// Note that there can be comments *inside* members, e.g. `{"foo: /* comment *\/ "bar"}`, but these are ignored when calculating line-separated groups
|
|
946
|
+
const prevMemberEndLine = prevMember.loc.end.line;
|
|
947
|
+
const thisStartLine = member.loc.start.line;
|
|
948
|
+
if (thisStartLine - prevMemberEndLine < 2) {
|
|
949
|
+
return false;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
for (
|
|
953
|
+
let lineNum = prevMemberEndLine + 1;
|
|
954
|
+
lineNum < thisStartLine;
|
|
955
|
+
lineNum += 1
|
|
956
|
+
) {
|
|
957
|
+
if (
|
|
958
|
+
!commentLineNums.has(lineNum) &&
|
|
959
|
+
!hasNonWhitespace.test(
|
|
960
|
+
context.sourceCode.lines[lineNum - 1],
|
|
961
|
+
)
|
|
962
|
+
) {
|
|
963
|
+
return true;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
return false;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
return {
|
|
971
|
+
Object(node) {
|
|
972
|
+
let prevMember;
|
|
973
|
+
let prevName;
|
|
974
|
+
|
|
975
|
+
if (node.members.length < minKeys) {
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
for (const member of node.members) {
|
|
980
|
+
const thisName = getKey(member);
|
|
981
|
+
|
|
982
|
+
if (
|
|
983
|
+
prevMember &&
|
|
984
|
+
!isValidOrder(prevName, thisName) &&
|
|
985
|
+
(!allowLineSeparatedGroups ||
|
|
986
|
+
!isLineSeparated(prevMember, member))
|
|
987
|
+
) {
|
|
988
|
+
context.report({
|
|
989
|
+
loc: member.name.loc,
|
|
990
|
+
messageId: "sortKeys",
|
|
991
|
+
data: {
|
|
992
|
+
thisName,
|
|
993
|
+
prevName,
|
|
994
|
+
direction,
|
|
995
|
+
sensitivity,
|
|
996
|
+
sortName,
|
|
997
|
+
},
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
prevMember = member;
|
|
1002
|
+
prevName = thisName;
|
|
1003
|
+
}
|
|
1004
|
+
},
|
|
1005
|
+
};
|
|
1006
|
+
},
|
|
1007
|
+
};
|
|
1008
|
+
|
|
718
1009
|
/**
|
|
719
1010
|
* @fileoverview Rule to ensure top-level items are either an array or ojbect.
|
|
720
1011
|
* @author Joe Hildebrand
|
|
721
1012
|
*/
|
|
722
1013
|
|
|
723
|
-
|
|
1014
|
+
//-----------------------------------------------------------------------------
|
|
1015
|
+
// Type Definitions
|
|
1016
|
+
//-----------------------------------------------------------------------------
|
|
1017
|
+
|
|
1018
|
+
/** @typedef {"topLevel"} TopLevelInteropMessageIds */
|
|
1019
|
+
/** @typedef {import("./types.ts").JSONRuleDefinition<[], TopLevelInteropMessageIds>} TopLevelInteropRuleDefinition */
|
|
1020
|
+
|
|
1021
|
+
//-----------------------------------------------------------------------------
|
|
1022
|
+
// Rule Definition
|
|
1023
|
+
//-----------------------------------------------------------------------------
|
|
1024
|
+
|
|
1025
|
+
/** @type {TopLevelInteropRuleDefinition} */
|
|
1026
|
+
const rule = {
|
|
724
1027
|
meta: {
|
|
725
|
-
type:
|
|
1028
|
+
type: "problem",
|
|
726
1029
|
|
|
727
1030
|
docs: {
|
|
728
1031
|
description:
|
|
@@ -764,7 +1067,7 @@ var topLevelInterop = {
|
|
|
764
1067
|
const plugin = {
|
|
765
1068
|
meta: {
|
|
766
1069
|
name: "@eslint/json",
|
|
767
|
-
version: "0.
|
|
1070
|
+
version: "0.11.0", // x-release-please-version
|
|
768
1071
|
},
|
|
769
1072
|
languages: {
|
|
770
1073
|
json: new JSONLanguage({ mode: "json" }),
|
|
@@ -772,11 +1075,12 @@ const plugin = {
|
|
|
772
1075
|
json5: new JSONLanguage({ mode: "json5" }),
|
|
773
1076
|
},
|
|
774
1077
|
rules: {
|
|
775
|
-
"no-duplicate-keys":
|
|
776
|
-
"no-empty-keys":
|
|
777
|
-
"no-unsafe-values":
|
|
778
|
-
"no-unnormalized-keys":
|
|
779
|
-
"
|
|
1078
|
+
"no-duplicate-keys": rule$5,
|
|
1079
|
+
"no-empty-keys": rule$4,
|
|
1080
|
+
"no-unsafe-values": rule$3,
|
|
1081
|
+
"no-unnormalized-keys": rule$2,
|
|
1082
|
+
"sort-keys": rule$1,
|
|
1083
|
+
"top-level-interop": rule,
|
|
780
1084
|
},
|
|
781
1085
|
configs: {
|
|
782
1086
|
recommended: {
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Additional types for this package.
|
|
3
|
+
* @author Nicholas C. Zakas
|
|
4
|
+
*/
|
|
5
|
+
import type { RuleVisitor, TextSourceCode, Language, LanguageOptions, RuleDefinition } from "@eslint/core";
|
|
6
|
+
import { DocumentNode, MemberNode, ElementNode, ObjectNode, ArrayNode, StringNode, NullNode, NumberNode, BooleanNode, NaNNode, InfinityNode, IdentifierNode, AnyNode, Token } from "@humanwhocodes/momoa";
|
|
7
|
+
type ValueNodeParent = DocumentNode | MemberNode | ElementNode;
|
|
8
|
+
/**
|
|
9
|
+
* A JSON syntax element, including nodes and tokens.
|
|
10
|
+
*/
|
|
11
|
+
export type JSONSyntaxElement = Token | AnyNode;
|
|
12
|
+
/**
|
|
13
|
+
* Language options provided for JSON files.
|
|
14
|
+
*/
|
|
15
|
+
export interface JSONLanguageOptions extends LanguageOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Whether to allow trailing commas. Only valid in JSONC.
|
|
18
|
+
*/
|
|
19
|
+
allowTrailingCommas?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The visitor format returned from rules in this package.
|
|
23
|
+
*/
|
|
24
|
+
export interface JSONRuleVisitor extends RuleVisitor {
|
|
25
|
+
Document?(node: DocumentNode): void;
|
|
26
|
+
Member?(node: MemberNode, parent?: ObjectNode): void;
|
|
27
|
+
Element?(node: ElementNode, parent?: ArrayNode): void;
|
|
28
|
+
Object?(node: ObjectNode, parent?: ValueNodeParent): void;
|
|
29
|
+
Array?(node: ArrayNode, parent?: ValueNodeParent): void;
|
|
30
|
+
String?(node: StringNode, parent?: ValueNodeParent): void;
|
|
31
|
+
Null?(node: NullNode, parent?: ValueNodeParent): void;
|
|
32
|
+
Number?(node: NumberNode, parent?: ValueNodeParent): void;
|
|
33
|
+
Boolean?(node: BooleanNode, parent?: ValueNodeParent): void;
|
|
34
|
+
NaN?(node: NaNNode, parent?: ValueNodeParent): void;
|
|
35
|
+
Infinity?(node: InfinityNode, parent?: ValueNodeParent): void;
|
|
36
|
+
Identifier?(node: IdentifierNode, parent?: ValueNodeParent): void;
|
|
37
|
+
"Document:exit"?(node: DocumentNode): void;
|
|
38
|
+
"Member:exit"?(node: MemberNode, parent?: ObjectNode): void;
|
|
39
|
+
"Element:exit"?(node: ElementNode, parent?: ArrayNode): void;
|
|
40
|
+
"Object:exit"?(node: ObjectNode, parent?: ValueNodeParent): void;
|
|
41
|
+
"Array:exit"?(node: ArrayNode, parent?: ValueNodeParent): void;
|
|
42
|
+
"String:exit"?(node: StringNode, parent?: ValueNodeParent): void;
|
|
43
|
+
"Null:exit"?(node: NullNode, parent?: ValueNodeParent): void;
|
|
44
|
+
"Number:exit"?(node: NumberNode, parent?: ValueNodeParent): void;
|
|
45
|
+
"Boolean:exit"?(node: BooleanNode, parent?: ValueNodeParent): void;
|
|
46
|
+
"NaN:exit"?(node: NaNNode, parent?: ValueNodeParent): void;
|
|
47
|
+
"Infinity:exit"?(node: InfinityNode, parent?: ValueNodeParent): void;
|
|
48
|
+
"Identifier:exit"?(node: IdentifierNode, parent?: ValueNodeParent): void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The `SourceCode` implementation for JSON files.
|
|
52
|
+
*/
|
|
53
|
+
export interface IJSONSourceCode extends TextSourceCode<{
|
|
54
|
+
LangOptions: JSONLanguageOptions;
|
|
55
|
+
RootNode: DocumentNode;
|
|
56
|
+
SyntaxElementWithLoc: JSONSyntaxElement;
|
|
57
|
+
ConfigNode: Token;
|
|
58
|
+
}> {
|
|
59
|
+
/**
|
|
60
|
+
* Get the text of a syntax element.
|
|
61
|
+
* @param syntaxElement The syntax element to get the text of.
|
|
62
|
+
* @param beforeCount The number of characters to include before the syntax element.
|
|
63
|
+
* @param afterCount The number of characters to include after the syntax element.
|
|
64
|
+
* @returns The text of the syntax element.
|
|
65
|
+
*/
|
|
66
|
+
getText(syntaxElement: JSONSyntaxElement, beforeCount?: number, afterCount?: number): string;
|
|
67
|
+
/**
|
|
68
|
+
* Any comments found in a JSONC or JSON5 file.
|
|
69
|
+
*/
|
|
70
|
+
comments: Array<Token> | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* The lines of text found in the file.
|
|
73
|
+
*/
|
|
74
|
+
lines: Array<string>;
|
|
75
|
+
}
|
|
76
|
+
export type IJSONLanguage = Language<{
|
|
77
|
+
LangOptions: JSONLanguageOptions;
|
|
78
|
+
Code: IJSONSourceCode;
|
|
79
|
+
RootNode: DocumentNode;
|
|
80
|
+
Node: AnyNode;
|
|
81
|
+
}>;
|
|
82
|
+
export type JSONRuleDefinition<JSONRuleOptions extends unknown[], JSONRuleMessageIds extends string = ""> = RuleDefinition<{
|
|
83
|
+
LangOptions: JSONLanguageOptions;
|
|
84
|
+
Code: IJSONSourceCode;
|
|
85
|
+
RuleOptions: JSONRuleOptions;
|
|
86
|
+
Visitor: JSONRuleVisitor;
|
|
87
|
+
Node: AnyNode;
|
|
88
|
+
MessageIds: JSONRuleMessageIds;
|
|
89
|
+
ExtRuleDocs: {};
|
|
90
|
+
}>;
|
|
91
|
+
export {};
|