@agilebot/eslint-plugin 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/dist/index.d.ts +5 -20
- package/dist/index.js +366 -285
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
@@ -1,20 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
export default plugin;
|
2
|
+
declare namespace plugin {
|
3
|
+
let rules: import('eslint').Linter.RulesRecord;
|
4
|
+
namespace configs {
|
4
5
|
namespace recommended {
|
5
6
|
export let plugins: string[];
|
6
|
-
let rules_1:
|
7
|
-
'@agilebot/no-unnecessary-template-literals': string;
|
8
|
-
'@agilebot/no-async-array-methods': string;
|
9
|
-
'@agilebot/react-prefer-named-property-access': string;
|
10
|
-
'@agilebot/react-hook-use-ref': string;
|
11
|
-
'@agilebot/react-prefer-sx-prop': string;
|
12
|
-
'@agilebot/tss-unused-classes': string;
|
13
|
-
'@agilebot/tss-no-color-value': string;
|
14
|
-
'@agilebot/tss-class-naming': string;
|
15
|
-
'@agilebot/import-enforce-icon-alias': string;
|
16
|
-
'@agilebot/import-monorepo': string;
|
17
|
-
};
|
7
|
+
let rules_1: import('eslint').Linter.RulesRecord;
|
18
8
|
export { rules_1 as rules };
|
19
9
|
export namespace settings {
|
20
10
|
namespace react {
|
@@ -24,8 +14,3 @@ declare namespace _default {
|
|
24
14
|
}
|
25
15
|
}
|
26
16
|
}
|
27
|
-
export default _default;
|
28
|
-
/**
|
29
|
-
* @type {import('eslint').Linter.RulesRecord}
|
30
|
-
*/
|
31
|
-
declare const rules: import('eslint').Linter.RulesRecord;
|
package/dist/index.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
/**
|
2
|
-
* @license @agilebot/eslint-plugin v0.3.
|
2
|
+
* @license @agilebot/eslint-plugin v0.3.4
|
3
3
|
*
|
4
4
|
* Copyright (c) Agilebot, Inc. and its affiliates.
|
5
5
|
*
|
@@ -41,7 +41,10 @@ var enforceIconAlias = {
|
|
41
41
|
recommended: true
|
42
42
|
},
|
43
43
|
fixable: 'code',
|
44
|
-
schema: []
|
44
|
+
schema: [],
|
45
|
+
messages: {
|
46
|
+
iconAlias: 'Import for {{ name }} should be aliased.'
|
47
|
+
}
|
45
48
|
},
|
46
49
|
create(context) {
|
47
50
|
return {
|
@@ -59,7 +62,10 @@ var enforceIconAlias = {
|
|
59
62
|
if (specifier.imported.name === specifier.local.name) {
|
60
63
|
context.report({
|
61
64
|
node,
|
62
|
-
|
65
|
+
messageId: 'iconAlias',
|
66
|
+
data: {
|
67
|
+
name: node.source.value
|
68
|
+
},
|
63
69
|
fix: fixer =>
|
64
70
|
fixer.replaceText(
|
65
71
|
specifier,
|
@@ -86,7 +92,10 @@ var monorepo = {
|
|
86
92
|
recommended: true
|
87
93
|
},
|
88
94
|
fixable: 'code',
|
89
|
-
schema: []
|
95
|
+
schema: [],
|
96
|
+
messages: {
|
97
|
+
monorepoImport: 'Import for {{ module }} should not contains src folder.'
|
98
|
+
}
|
90
99
|
},
|
91
100
|
create(context) {
|
92
101
|
return {
|
@@ -110,7 +119,10 @@ var monorepo = {
|
|
110
119
|
if (values[2] === 'src') {
|
111
120
|
context.report({
|
112
121
|
node,
|
113
|
-
|
122
|
+
messageId: 'monorepoImport',
|
123
|
+
data: {
|
124
|
+
module: node.source.value
|
125
|
+
},
|
114
126
|
fix: fixer => {
|
115
127
|
const correctedPath = values
|
116
128
|
.filter((_, index) => index !== 2)
|
@@ -240,8 +252,7 @@ var idMissing = {
|
|
240
252
|
meta: {
|
241
253
|
docs: {
|
242
254
|
description: 'Validates intl message ids are in locale file',
|
243
|
-
category: 'Intl'
|
244
|
-
recommended: true
|
255
|
+
category: 'Intl'
|
245
256
|
},
|
246
257
|
fixable: undefined,
|
247
258
|
schema: []
|
@@ -322,8 +333,7 @@ var idPrefix = {
|
|
322
333
|
meta: {
|
323
334
|
docs: {
|
324
335
|
description: 'Validates intl message ids has correct prefixes',
|
325
|
-
category: 'Intl'
|
326
|
-
recommended: true
|
336
|
+
category: 'Intl'
|
327
337
|
},
|
328
338
|
fixable: undefined,
|
329
339
|
schema: [
|
@@ -400,8 +410,7 @@ var idUnused = {
|
|
400
410
|
meta: {
|
401
411
|
docs: {
|
402
412
|
description: 'Finds unused intl message ids in locale file',
|
403
|
-
category: 'Intl'
|
404
|
-
recommended: true
|
413
|
+
category: 'Intl'
|
405
414
|
},
|
406
415
|
fixable: undefined,
|
407
416
|
schema: []
|
@@ -483,8 +492,7 @@ var noDefault = {
|
|
483
492
|
meta: {
|
484
493
|
docs: {
|
485
494
|
description: 'Validates defaultMessage is not used with react-intl',
|
486
|
-
category: 'Intl'
|
487
|
-
recommended: true
|
495
|
+
category: 'Intl'
|
488
496
|
},
|
489
497
|
fixable: undefined,
|
490
498
|
schema: []
|
@@ -521,258 +529,12 @@ var noDefault = {
|
|
521
529
|
}
|
522
530
|
};
|
523
531
|
|
524
|
-
function getBasicIdentifier(node) {
|
525
|
-
if (node.type === 'Identifier') {
|
526
|
-
return node.name;
|
527
|
-
}
|
528
|
-
if (node.type === 'Literal') {
|
529
|
-
return node.value;
|
530
|
-
}
|
531
|
-
if (node.type === 'TemplateLiteral') {
|
532
|
-
if (node.expressions.length > 0) {
|
533
|
-
return null;
|
534
|
-
}
|
535
|
-
return node.quasis[0].value.raw;
|
536
|
-
}
|
537
|
-
return null;
|
538
|
-
}
|
539
|
-
function getBaseIdentifier(node) {
|
540
|
-
switch (node.type) {
|
541
|
-
case 'Identifier': {
|
542
|
-
return node;
|
543
|
-
}
|
544
|
-
case 'CallExpression': {
|
545
|
-
return getBaseIdentifier(node.callee);
|
546
|
-
}
|
547
|
-
case 'MemberExpression': {
|
548
|
-
return getBaseIdentifier(node.object);
|
549
|
-
}
|
550
|
-
}
|
551
|
-
return null;
|
552
|
-
}
|
553
|
-
function getStyesObj(node) {
|
554
|
-
const isMakeStyles = node.callee.name === 'makeStyles';
|
555
|
-
const isModernApi =
|
556
|
-
node.callee.type === 'MemberExpression' &&
|
557
|
-
node.callee.property.name === 'create' &&
|
558
|
-
getBaseIdentifier(node.callee.object) &&
|
559
|
-
getBaseIdentifier(node.callee.object).name === 'tss';
|
560
|
-
if (!isMakeStyles && !isModernApi) {
|
561
|
-
return;
|
562
|
-
}
|
563
|
-
const styles = (() => {
|
564
|
-
if (isMakeStyles) {
|
565
|
-
return node.parent.arguments[0];
|
566
|
-
}
|
567
|
-
if (isModernApi) {
|
568
|
-
return node.callee.parent.arguments[0];
|
569
|
-
}
|
570
|
-
})();
|
571
|
-
if (!styles) {
|
572
|
-
return;
|
573
|
-
}
|
574
|
-
switch (styles.type) {
|
575
|
-
case 'ObjectExpression':
|
576
|
-
return styles;
|
577
|
-
case 'ArrowFunctionExpression':
|
578
|
-
{
|
579
|
-
const { body } = styles;
|
580
|
-
switch (body.type) {
|
581
|
-
case 'ObjectExpression':
|
582
|
-
return body;
|
583
|
-
case 'BlockStatement': {
|
584
|
-
let stylesObj;
|
585
|
-
body.body.forEach(bodyNode => {
|
586
|
-
if (
|
587
|
-
bodyNode.type === 'ReturnStatement' &&
|
588
|
-
bodyNode.argument.type === 'ObjectExpression'
|
589
|
-
) {
|
590
|
-
stylesObj = bodyNode.argument;
|
591
|
-
}
|
592
|
-
});
|
593
|
-
return stylesObj;
|
594
|
-
}
|
595
|
-
}
|
596
|
-
}
|
597
|
-
break;
|
598
|
-
}
|
599
|
-
}
|
600
|
-
|
601
|
-
var classNaming = {
|
602
|
-
meta: {
|
603
|
-
type: 'problem'
|
604
|
-
},
|
605
|
-
create: function rule(context) {
|
606
|
-
return {
|
607
|
-
CallExpression(node) {
|
608
|
-
const stylesObj = getStyesObj(node);
|
609
|
-
if (stylesObj === undefined) {
|
610
|
-
return;
|
611
|
-
}
|
612
|
-
stylesObj.properties.forEach(property => {
|
613
|
-
if (property.computed) {
|
614
|
-
return;
|
615
|
-
}
|
616
|
-
if (
|
617
|
-
property.type === 'ExperimentalSpreadProperty' ||
|
618
|
-
property.type === 'SpreadElement'
|
619
|
-
) {
|
620
|
-
return;
|
621
|
-
}
|
622
|
-
const className = property.key.value || property.key.name;
|
623
|
-
if (!eslintUtils.isCamelCase(className)) {
|
624
|
-
context.report({
|
625
|
-
node: property,
|
626
|
-
message: `Class \`${className}\` must be camelCase in TSS.`
|
627
|
-
});
|
628
|
-
}
|
629
|
-
});
|
630
|
-
}
|
631
|
-
};
|
632
|
-
}
|
633
|
-
};
|
634
|
-
|
635
|
-
var noColorValue = {
|
636
|
-
meta: {
|
637
|
-
type: 'problem',
|
638
|
-
docs: {
|
639
|
-
description:
|
640
|
-
'Enforce the use of color variables instead of color codes within TSS'
|
641
|
-
}
|
642
|
-
},
|
643
|
-
create: function (context) {
|
644
|
-
const parserOptions = context.parserOptions;
|
645
|
-
if (!parserOptions || !parserOptions.project) {
|
646
|
-
return {};
|
647
|
-
}
|
648
|
-
return {
|
649
|
-
CallExpression(node) {
|
650
|
-
const stylesObj = getStyesObj(node);
|
651
|
-
if (!stylesObj) {
|
652
|
-
return;
|
653
|
-
}
|
654
|
-
function checkColorLiteral(value) {
|
655
|
-
if (value.type === 'Literal' && typeof value.value === 'string') {
|
656
|
-
const colorCodePattern =
|
657
|
-
/#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgb\?\(\s*(\d{1,3}\s*,\s*){2}\d{1,3}(?:\s*,\s*\d*(?:\.\d+)?)?\s*\)/g;
|
658
|
-
const isColorCode = colorCodePattern.test(value.value);
|
659
|
-
if (isColorCode) {
|
660
|
-
context.report({
|
661
|
-
node: value,
|
662
|
-
message: 'Use color variables instead of color codes in TSS.'
|
663
|
-
});
|
664
|
-
}
|
665
|
-
}
|
666
|
-
}
|
667
|
-
function loopStylesObj(obj) {
|
668
|
-
if (obj && obj.type === 'ObjectExpression') {
|
669
|
-
obj.properties.forEach(property => {
|
670
|
-
if (property.type === 'Property' && property.value) {
|
671
|
-
if (property.value.type === 'ObjectExpression') {
|
672
|
-
loopStylesObj(property.value);
|
673
|
-
} else {
|
674
|
-
checkColorLiteral(property.value);
|
675
|
-
}
|
676
|
-
}
|
677
|
-
});
|
678
|
-
}
|
679
|
-
}
|
680
|
-
loopStylesObj(stylesObj);
|
681
|
-
}
|
682
|
-
};
|
683
|
-
}
|
684
|
-
};
|
685
|
-
|
686
|
-
var unusedClasses = {
|
687
|
-
meta: {
|
688
|
-
type: 'problem'
|
689
|
-
},
|
690
|
-
create: function rule(context) {
|
691
|
-
const usedClasses = {};
|
692
|
-
const definedClasses = {};
|
693
|
-
return {
|
694
|
-
CallExpression(node) {
|
695
|
-
const stylesObj = getStyesObj(node);
|
696
|
-
if (stylesObj === undefined) {
|
697
|
-
return;
|
698
|
-
}
|
699
|
-
stylesObj.properties.forEach(property => {
|
700
|
-
if (property.computed) {
|
701
|
-
return;
|
702
|
-
}
|
703
|
-
if (
|
704
|
-
property.type === 'ExperimentalSpreadProperty' ||
|
705
|
-
property.type === 'SpreadElement'
|
706
|
-
) {
|
707
|
-
return;
|
708
|
-
}
|
709
|
-
definedClasses[property.key.value || property.key.name] = property;
|
710
|
-
});
|
711
|
-
},
|
712
|
-
MemberExpression(node) {
|
713
|
-
if (
|
714
|
-
node.object.type === 'Identifier' &&
|
715
|
-
node.object.name === 'classes'
|
716
|
-
) {
|
717
|
-
const whichClass = getBasicIdentifier(node.property);
|
718
|
-
if (whichClass) {
|
719
|
-
usedClasses[whichClass] = true;
|
720
|
-
}
|
721
|
-
return;
|
722
|
-
}
|
723
|
-
const classIdentifier = getBasicIdentifier(node.property);
|
724
|
-
if (!classIdentifier) {
|
725
|
-
return;
|
726
|
-
}
|
727
|
-
if (classIdentifier !== 'classes') {
|
728
|
-
return;
|
729
|
-
}
|
730
|
-
const { parent } = node;
|
731
|
-
if (parent.type !== 'MemberExpression') {
|
732
|
-
return;
|
733
|
-
}
|
734
|
-
if (
|
735
|
-
node.object.object &&
|
736
|
-
node.object.object.type !== 'ThisExpression'
|
737
|
-
) {
|
738
|
-
return;
|
739
|
-
}
|
740
|
-
const propsIdentifier = getBasicIdentifier(parent.object);
|
741
|
-
if (propsIdentifier && propsIdentifier !== 'props') {
|
742
|
-
return;
|
743
|
-
}
|
744
|
-
if (!propsIdentifier && parent.object.type !== 'MemberExpression') {
|
745
|
-
return;
|
746
|
-
}
|
747
|
-
if (parent.parent.type === 'MemberExpression') {
|
748
|
-
return;
|
749
|
-
}
|
750
|
-
const parentClassIdentifier = getBasicIdentifier(parent.property);
|
751
|
-
if (parentClassIdentifier) {
|
752
|
-
usedClasses[parentClassIdentifier] = true;
|
753
|
-
}
|
754
|
-
},
|
755
|
-
'Program:exit': () => {
|
756
|
-
Object.keys(definedClasses).forEach(definedClassKey => {
|
757
|
-
if (!usedClasses[definedClassKey]) {
|
758
|
-
context.report({
|
759
|
-
node: definedClasses[definedClassKey],
|
760
|
-
message: `Class \`${definedClassKey}\` is unused`
|
761
|
-
});
|
762
|
-
}
|
763
|
-
});
|
764
|
-
}
|
765
|
-
};
|
766
|
-
}
|
767
|
-
};
|
768
|
-
|
769
532
|
var betterExhaustiveDeps = {
|
770
533
|
meta: {
|
771
534
|
type: 'suggestion',
|
772
535
|
docs: {
|
773
536
|
description:
|
774
537
|
'verifies the list of dependencies for Hooks like useEffect and similar',
|
775
|
-
recommended: true,
|
776
538
|
url: 'https://github.com/facebook/react/issues/14920'
|
777
539
|
},
|
778
540
|
fixable: 'code',
|
@@ -2309,7 +2071,7 @@ var hookUseRef = {
|
|
2309
2071
|
meta: {
|
2310
2072
|
docs: {
|
2311
2073
|
description: 'Ensure naming of useRef hook value.',
|
2312
|
-
recommended:
|
2074
|
+
recommended: true
|
2313
2075
|
},
|
2314
2076
|
schema: [],
|
2315
2077
|
type: 'suggestion',
|
@@ -2370,7 +2132,8 @@ var preferNamedPropertyAccess = utils.ESLintUtils.RuleCreator.withoutDocs({
|
|
2370
2132
|
fixable: 'code',
|
2371
2133
|
docs: {
|
2372
2134
|
description:
|
2373
|
-
'Enforce importing each member of React namespace separately instead of accessing them through React namespace'
|
2135
|
+
'Enforce importing each member of React namespace separately instead of accessing them through React namespace',
|
2136
|
+
recommended: 'recommended'
|
2374
2137
|
},
|
2375
2138
|
messages: {
|
2376
2139
|
illegalReactPropertyAccess:
|
@@ -2424,7 +2187,7 @@ var preferSxProp = {
|
|
2424
2187
|
docs: {
|
2425
2188
|
description: 'Prefer using sx prop instead of inline styles',
|
2426
2189
|
category: 'Best Practices',
|
2427
|
-
recommended:
|
2190
|
+
recommended: true
|
2428
2191
|
},
|
2429
2192
|
messages: {
|
2430
2193
|
preferSxProp:
|
@@ -2497,6 +2260,262 @@ var preferSxProp = {
|
|
2497
2260
|
}
|
2498
2261
|
};
|
2499
2262
|
|
2263
|
+
function getBasicIdentifier(node) {
|
2264
|
+
if (node.type === 'Identifier') {
|
2265
|
+
return node.name;
|
2266
|
+
}
|
2267
|
+
if (node.type === 'Literal') {
|
2268
|
+
return node.value;
|
2269
|
+
}
|
2270
|
+
if (node.type === 'TemplateLiteral') {
|
2271
|
+
if (node.expressions.length > 0) {
|
2272
|
+
return null;
|
2273
|
+
}
|
2274
|
+
return node.quasis[0].value.raw;
|
2275
|
+
}
|
2276
|
+
return null;
|
2277
|
+
}
|
2278
|
+
function getBaseIdentifier(node) {
|
2279
|
+
switch (node.type) {
|
2280
|
+
case 'Identifier': {
|
2281
|
+
return node;
|
2282
|
+
}
|
2283
|
+
case 'CallExpression': {
|
2284
|
+
return getBaseIdentifier(node.callee);
|
2285
|
+
}
|
2286
|
+
case 'MemberExpression': {
|
2287
|
+
return getBaseIdentifier(node.object);
|
2288
|
+
}
|
2289
|
+
}
|
2290
|
+
return null;
|
2291
|
+
}
|
2292
|
+
function getStyesObj(node) {
|
2293
|
+
const isMakeStyles = node.callee.name === 'makeStyles';
|
2294
|
+
const isModernApi =
|
2295
|
+
node.callee.type === 'MemberExpression' &&
|
2296
|
+
node.callee.property.name === 'create' &&
|
2297
|
+
getBaseIdentifier(node.callee.object) &&
|
2298
|
+
getBaseIdentifier(node.callee.object).name === 'tss';
|
2299
|
+
if (!isMakeStyles && !isModernApi) {
|
2300
|
+
return;
|
2301
|
+
}
|
2302
|
+
const styles = (() => {
|
2303
|
+
if (isMakeStyles) {
|
2304
|
+
return node.parent.arguments[0];
|
2305
|
+
}
|
2306
|
+
if (isModernApi) {
|
2307
|
+
return node.callee.parent.arguments[0];
|
2308
|
+
}
|
2309
|
+
})();
|
2310
|
+
if (!styles) {
|
2311
|
+
return;
|
2312
|
+
}
|
2313
|
+
switch (styles.type) {
|
2314
|
+
case 'ObjectExpression':
|
2315
|
+
return styles;
|
2316
|
+
case 'ArrowFunctionExpression':
|
2317
|
+
{
|
2318
|
+
const { body } = styles;
|
2319
|
+
switch (body.type) {
|
2320
|
+
case 'ObjectExpression':
|
2321
|
+
return body;
|
2322
|
+
case 'BlockStatement': {
|
2323
|
+
let stylesObj;
|
2324
|
+
body.body.forEach(bodyNode => {
|
2325
|
+
if (
|
2326
|
+
bodyNode.type === 'ReturnStatement' &&
|
2327
|
+
bodyNode.argument.type === 'ObjectExpression'
|
2328
|
+
) {
|
2329
|
+
stylesObj = bodyNode.argument;
|
2330
|
+
}
|
2331
|
+
});
|
2332
|
+
return stylesObj;
|
2333
|
+
}
|
2334
|
+
}
|
2335
|
+
}
|
2336
|
+
break;
|
2337
|
+
}
|
2338
|
+
}
|
2339
|
+
|
2340
|
+
var classNaming = {
|
2341
|
+
meta: {
|
2342
|
+
type: 'problem',
|
2343
|
+
docs: {
|
2344
|
+
description: 'Enforce camelCase class names in TSS',
|
2345
|
+
category: 'Best Practices',
|
2346
|
+
recommended: true
|
2347
|
+
}
|
2348
|
+
},
|
2349
|
+
create: function rule(context) {
|
2350
|
+
return {
|
2351
|
+
CallExpression(node) {
|
2352
|
+
const stylesObj = getStyesObj(node);
|
2353
|
+
if (stylesObj === undefined) {
|
2354
|
+
return;
|
2355
|
+
}
|
2356
|
+
stylesObj.properties.forEach(property => {
|
2357
|
+
if (property.computed) {
|
2358
|
+
return;
|
2359
|
+
}
|
2360
|
+
if (
|
2361
|
+
property.type === 'ExperimentalSpreadProperty' ||
|
2362
|
+
property.type === 'SpreadElement'
|
2363
|
+
) {
|
2364
|
+
return;
|
2365
|
+
}
|
2366
|
+
const className = property.key.value || property.key.name;
|
2367
|
+
if (!eslintUtils.isCamelCase(className)) {
|
2368
|
+
context.report({
|
2369
|
+
node: property,
|
2370
|
+
message: `Class \`${className}\` must be camelCase in TSS.`
|
2371
|
+
});
|
2372
|
+
}
|
2373
|
+
});
|
2374
|
+
}
|
2375
|
+
};
|
2376
|
+
}
|
2377
|
+
};
|
2378
|
+
|
2379
|
+
var noColorValue = {
|
2380
|
+
meta: {
|
2381
|
+
type: 'problem',
|
2382
|
+
docs: {
|
2383
|
+
description:
|
2384
|
+
'Enforce the use of color variables instead of color codes within TSS',
|
2385
|
+
recommended: true
|
2386
|
+
}
|
2387
|
+
},
|
2388
|
+
create: function (context) {
|
2389
|
+
const parserOptions = context.parserOptions;
|
2390
|
+
if (!parserOptions || !parserOptions.project) {
|
2391
|
+
return {};
|
2392
|
+
}
|
2393
|
+
return {
|
2394
|
+
CallExpression(node) {
|
2395
|
+
const stylesObj = getStyesObj(node);
|
2396
|
+
if (!stylesObj) {
|
2397
|
+
return;
|
2398
|
+
}
|
2399
|
+
function checkColorLiteral(value) {
|
2400
|
+
if (value.type === 'Literal' && typeof value.value === 'string') {
|
2401
|
+
const colorCodePattern =
|
2402
|
+
/#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})|rgb\?\(\s*(\d{1,3}\s*,\s*){2}\d{1,3}(?:\s*,\s*\d*(?:\.\d+)?)?\s*\)/g;
|
2403
|
+
const isColorCode = colorCodePattern.test(value.value);
|
2404
|
+
if (isColorCode) {
|
2405
|
+
context.report({
|
2406
|
+
node: value,
|
2407
|
+
message: 'Use color variables instead of color codes in TSS.'
|
2408
|
+
});
|
2409
|
+
}
|
2410
|
+
}
|
2411
|
+
}
|
2412
|
+
function loopStylesObj(obj) {
|
2413
|
+
if (obj && obj.type === 'ObjectExpression') {
|
2414
|
+
obj.properties.forEach(property => {
|
2415
|
+
if (property.type === 'Property' && property.value) {
|
2416
|
+
if (property.value.type === 'ObjectExpression') {
|
2417
|
+
loopStylesObj(property.value);
|
2418
|
+
} else {
|
2419
|
+
checkColorLiteral(property.value);
|
2420
|
+
}
|
2421
|
+
}
|
2422
|
+
});
|
2423
|
+
}
|
2424
|
+
}
|
2425
|
+
loopStylesObj(stylesObj);
|
2426
|
+
}
|
2427
|
+
};
|
2428
|
+
}
|
2429
|
+
};
|
2430
|
+
|
2431
|
+
var unusedClasses = {
|
2432
|
+
meta: {
|
2433
|
+
type: 'suggestion',
|
2434
|
+
docs: {
|
2435
|
+
description: 'Disallow unused classes in tss',
|
2436
|
+
category: 'Best Practices',
|
2437
|
+
recommended: true
|
2438
|
+
}
|
2439
|
+
},
|
2440
|
+
create: function rule(context) {
|
2441
|
+
const usedClasses = {};
|
2442
|
+
const definedClasses = {};
|
2443
|
+
return {
|
2444
|
+
CallExpression(node) {
|
2445
|
+
const stylesObj = getStyesObj(node);
|
2446
|
+
if (stylesObj === undefined) {
|
2447
|
+
return;
|
2448
|
+
}
|
2449
|
+
stylesObj.properties.forEach(property => {
|
2450
|
+
if (property.computed) {
|
2451
|
+
return;
|
2452
|
+
}
|
2453
|
+
if (
|
2454
|
+
property.type === 'ExperimentalSpreadProperty' ||
|
2455
|
+
property.type === 'SpreadElement'
|
2456
|
+
) {
|
2457
|
+
return;
|
2458
|
+
}
|
2459
|
+
definedClasses[property.key.value || property.key.name] = property;
|
2460
|
+
});
|
2461
|
+
},
|
2462
|
+
MemberExpression(node) {
|
2463
|
+
if (
|
2464
|
+
node.object.type === 'Identifier' &&
|
2465
|
+
node.object.name === 'classes'
|
2466
|
+
) {
|
2467
|
+
const whichClass = getBasicIdentifier(node.property);
|
2468
|
+
if (whichClass) {
|
2469
|
+
usedClasses[whichClass] = true;
|
2470
|
+
}
|
2471
|
+
return;
|
2472
|
+
}
|
2473
|
+
const classIdentifier = getBasicIdentifier(node.property);
|
2474
|
+
if (!classIdentifier) {
|
2475
|
+
return;
|
2476
|
+
}
|
2477
|
+
if (classIdentifier !== 'classes') {
|
2478
|
+
return;
|
2479
|
+
}
|
2480
|
+
const { parent } = node;
|
2481
|
+
if (parent.type !== 'MemberExpression') {
|
2482
|
+
return;
|
2483
|
+
}
|
2484
|
+
if (
|
2485
|
+
node.object.object &&
|
2486
|
+
node.object.object.type !== 'ThisExpression'
|
2487
|
+
) {
|
2488
|
+
return;
|
2489
|
+
}
|
2490
|
+
const propsIdentifier = getBasicIdentifier(parent.object);
|
2491
|
+
if (propsIdentifier && propsIdentifier !== 'props') {
|
2492
|
+
return;
|
2493
|
+
}
|
2494
|
+
if (!propsIdentifier && parent.object.type !== 'MemberExpression') {
|
2495
|
+
return;
|
2496
|
+
}
|
2497
|
+
if (parent.parent.type === 'MemberExpression') {
|
2498
|
+
return;
|
2499
|
+
}
|
2500
|
+
const parentClassIdentifier = getBasicIdentifier(parent.property);
|
2501
|
+
if (parentClassIdentifier) {
|
2502
|
+
usedClasses[parentClassIdentifier] = true;
|
2503
|
+
}
|
2504
|
+
},
|
2505
|
+
'Program:exit': () => {
|
2506
|
+
Object.keys(definedClasses).forEach(definedClassKey => {
|
2507
|
+
if (!usedClasses[definedClassKey]) {
|
2508
|
+
context.report({
|
2509
|
+
node: definedClasses[definedClassKey],
|
2510
|
+
message: `Class \`${definedClassKey}\` is unused`
|
2511
|
+
});
|
2512
|
+
}
|
2513
|
+
});
|
2514
|
+
}
|
2515
|
+
};
|
2516
|
+
}
|
2517
|
+
};
|
2518
|
+
|
2500
2519
|
var noAsyncArrayMethods = {
|
2501
2520
|
meta: {
|
2502
2521
|
docs: {
|
@@ -2547,6 +2566,70 @@ var noAsyncArrayMethods = {
|
|
2547
2566
|
}
|
2548
2567
|
};
|
2549
2568
|
|
2569
|
+
var noThenCatchFinally = {
|
2570
|
+
meta: {
|
2571
|
+
type: 'suggestion',
|
2572
|
+
docs: {
|
2573
|
+
description:
|
2574
|
+
'Disallow the use of then()/catch()/finally() when invoking specific functions.'
|
2575
|
+
},
|
2576
|
+
schema: [
|
2577
|
+
{
|
2578
|
+
type: 'object',
|
2579
|
+
properties: {
|
2580
|
+
restrictedFunctions: {
|
2581
|
+
type: 'array',
|
2582
|
+
uniqueItems: true,
|
2583
|
+
items: { type: 'string' }
|
2584
|
+
}
|
2585
|
+
}
|
2586
|
+
}
|
2587
|
+
],
|
2588
|
+
messages: {
|
2589
|
+
forbiddenThenCatchFinally: `then()/catch()/finally() is forbidden when invoke {{ name }}().`
|
2590
|
+
}
|
2591
|
+
},
|
2592
|
+
create(context) {
|
2593
|
+
const configuration = context.options[0] || {};
|
2594
|
+
const restrictedFunctions = configuration.restrictedFunctions || [];
|
2595
|
+
function isTopLevelScoped() {
|
2596
|
+
return context.getScope().block.type === 'Program';
|
2597
|
+
}
|
2598
|
+
function isThenCatchFinally(node) {
|
2599
|
+
return (
|
2600
|
+
node.property &&
|
2601
|
+
(node.property.name === 'then' ||
|
2602
|
+
node.property.name === 'catch' ||
|
2603
|
+
node.property.name === 'finally')
|
2604
|
+
);
|
2605
|
+
}
|
2606
|
+
return {
|
2607
|
+
'CallExpression > MemberExpression.callee'(node) {
|
2608
|
+
if (isTopLevelScoped()) {
|
2609
|
+
return;
|
2610
|
+
}
|
2611
|
+
if (!isThenCatchFinally(node)) {
|
2612
|
+
return;
|
2613
|
+
}
|
2614
|
+
const callExpression = node.object;
|
2615
|
+
if (
|
2616
|
+
callExpression.type === 'CallExpression' &&
|
2617
|
+
callExpression.callee.type === 'Identifier' &&
|
2618
|
+
restrictedFunctions.includes(callExpression.callee.name)
|
2619
|
+
) {
|
2620
|
+
context.report({
|
2621
|
+
node: node.property,
|
2622
|
+
messageId: 'forbiddenThenCatchFinally',
|
2623
|
+
data: {
|
2624
|
+
name: callExpression.callee.name
|
2625
|
+
}
|
2626
|
+
});
|
2627
|
+
}
|
2628
|
+
}
|
2629
|
+
};
|
2630
|
+
}
|
2631
|
+
};
|
2632
|
+
|
2550
2633
|
var noUnnecessaryTemplateLiterals = {
|
2551
2634
|
meta: {
|
2552
2635
|
type: 'problem',
|
@@ -2555,7 +2638,11 @@ var noUnnecessaryTemplateLiterals = {
|
|
2555
2638
|
recommended: true
|
2556
2639
|
},
|
2557
2640
|
fixable: 'code',
|
2558
|
-
schema: []
|
2641
|
+
schema: [],
|
2642
|
+
messages: {
|
2643
|
+
unnecessaryTemplateString:
|
2644
|
+
'Unnecessary template string with only one ${}.'
|
2645
|
+
}
|
2559
2646
|
},
|
2560
2647
|
create(context) {
|
2561
2648
|
return {
|
@@ -2568,7 +2655,7 @@ var noUnnecessaryTemplateLiterals = {
|
|
2568
2655
|
) {
|
2569
2656
|
context.report({
|
2570
2657
|
node,
|
2571
|
-
|
2658
|
+
messageId: 'unnecessaryTemplateString',
|
2572
2659
|
fix(fixer) {
|
2573
2660
|
return fixer.replaceText(
|
2574
2661
|
node,
|
@@ -2598,32 +2685,16 @@ var ruleFiles = /*#__PURE__*/Object.freeze({
|
|
2598
2685
|
rules_tss_no_color_value: noColorValue,
|
2599
2686
|
rules_tss_unused_classes: unusedClasses,
|
2600
2687
|
rules_unprefixed_no_async_array_methods: noAsyncArrayMethods,
|
2688
|
+
rules_unprefixed_no_then_catch_finally: noThenCatchFinally,
|
2601
2689
|
rules_unprefixed_no_unnecessary_template_literals: noUnnecessaryTemplateLiterals
|
2602
2690
|
});
|
2603
2691
|
|
2604
|
-
const
|
2605
|
-
|
2606
|
-
const ruleKey = key.replace(/^rules_/, '').replace(/^unprefixed_/, '');
|
2607
|
-
const finalKey = ruleKey.replace(/_/g, '-');
|
2608
|
-
rules[finalKey] = ruleFiles[key];
|
2609
|
-
});
|
2610
|
-
var index = {
|
2611
|
-
rules,
|
2692
|
+
const plugin = {
|
2693
|
+
rules: {},
|
2612
2694
|
configs: {
|
2613
2695
|
recommended: {
|
2614
2696
|
plugins: ['@agilebot'],
|
2615
|
-
rules: {
|
2616
|
-
'@agilebot/no-unnecessary-template-literals': 'error',
|
2617
|
-
'@agilebot/no-async-array-methods': 'error',
|
2618
|
-
'@agilebot/react-prefer-named-property-access': 'error',
|
2619
|
-
'@agilebot/react-hook-use-ref': 'warn',
|
2620
|
-
'@agilebot/react-prefer-sx-prop': 'error',
|
2621
|
-
'@agilebot/tss-unused-classes': 'warn',
|
2622
|
-
'@agilebot/tss-no-color-value': 'error',
|
2623
|
-
'@agilebot/tss-class-naming': 'error',
|
2624
|
-
'@agilebot/import-enforce-icon-alias': 'error',
|
2625
|
-
'@agilebot/import-monorepo': 'error'
|
2626
|
-
},
|
2697
|
+
rules: {},
|
2627
2698
|
settings: {
|
2628
2699
|
react: {
|
2629
2700
|
version: '18.0.0'
|
@@ -2632,5 +2703,15 @@ var index = {
|
|
2632
2703
|
}
|
2633
2704
|
}
|
2634
2705
|
};
|
2706
|
+
Object.keys(ruleFiles).forEach(key => {
|
2707
|
+
const ruleKey = key.replace(/^rules_/, '').replace(/^unprefixed_/, '');
|
2708
|
+
const finalKey = ruleKey.replace(/_/g, '-');
|
2709
|
+
const rule = ruleFiles[key];
|
2710
|
+
plugin.rules[finalKey] = rule;
|
2711
|
+
if (rule.meta && rule.meta.docs && rule.meta.docs.recommended) {
|
2712
|
+
plugin.configs.recommended.rules[`@agilebot/${finalKey}`] =
|
2713
|
+
rule.meta.type === 'suggestion' ? 'warn' : 'error';
|
2714
|
+
}
|
2715
|
+
});
|
2635
2716
|
|
2636
|
-
module.exports =
|
2717
|
+
module.exports = plugin;
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@agilebot/eslint-plugin",
|
3
|
-
"version": "0.3.
|
3
|
+
"version": "0.3.4",
|
4
4
|
"description": "Agilebot's ESLint plugin",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"types": "dist/index.d.ts",
|
@@ -20,7 +20,7 @@
|
|
20
20
|
"dependencies": {
|
21
21
|
"@typescript-eslint/utils": "~7.7.0",
|
22
22
|
"eslint-plugin-react": "^7.34.1",
|
23
|
-
"@agilebot/eslint-utils": "0.3.
|
23
|
+
"@agilebot/eslint-utils": "0.3.4"
|
24
24
|
},
|
25
25
|
"peerDependencies": {
|
26
26
|
"eslint": "^7.0.0 || ^8.0.0"
|
@@ -29,7 +29,8 @@
|
|
29
29
|
"dist"
|
30
30
|
],
|
31
31
|
"devDependencies": {
|
32
|
-
"@types/estree": "^1.0.5"
|
32
|
+
"@types/estree": "^1.0.5",
|
33
|
+
"eslint-vitest-rule-tester": "^0.3.2"
|
33
34
|
},
|
34
35
|
"scripts": {
|
35
36
|
"build": "rollup -c rollup.config.mjs && nr dts",
|