@agilebot/eslint-plugin 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # @agilebot/eslint-plugin
2
-
3
- ### Usage
4
-
5
- ```bash
6
- npm install --save-dev eslint @agilebot/eslint-plugin
7
- ```
8
-
9
- ### Documentation
10
-
11
- See `docs` folder.
1
+ # @agilebot/eslint-plugin
2
+
3
+ ### Usage
4
+
5
+ ```bash
6
+ npm install --save-dev eslint @agilebot/eslint-plugin
7
+ ```
8
+
9
+ ### Documentation
10
+
11
+ See `docs` folder.
package/lib/index.js CHANGED
@@ -1,58 +1,43 @@
1
- // @ts-check
2
- const path = require('node:path');
3
- const { globSync } = require('fast-glob');
4
-
5
- // List all rules in rules folder
6
- const rulesPath = path.join(__dirname, 'rules');
7
- const ruleFiles = globSync('**/*.js', {
8
- cwd: rulesPath
9
- });
10
-
11
- /**
12
- * @type {import('eslint').Linter.RulesRecord}
13
- */
14
- const rules = {};
15
- ruleFiles.forEach(file => {
16
- const { dir, name } = path.parse(file);
17
- const ruleName = `${dir}/${name}`;
18
- rules[ruleName] = require(path.join(rulesPath, file));
19
- });
20
-
21
- module.exports.rules = rules;
22
-
23
- module.exports.configs = {
24
- recommended: {
25
- plugins: ['@agilebot'],
26
- rules: {
27
- 'react-hooks/exhaustive-deps': 'off',
28
- '@agilebot/react/better-exhaustive-deps': [
29
- 'warn',
30
- {
31
- checkMemoizedVariableIsStatic: true,
32
- staticHooks: {
33
- 'useIpc.*': {
34
- value: true,
35
- regexp: true
36
- },
37
- useDialog: true,
38
- useSnackbar: true,
39
- useForm: true,
40
- 'use.*Store': {
41
- value: true,
42
- regexp: true
43
- }
44
- }
45
- }
46
- ],
47
- '@agilebot/react/prefer-named-property-access': 'error',
48
- '@agilebot/react/hook-use-ref': 'warn',
49
- '@agilebot/react/no-inline-styles': 'error',
50
- '@agilebot/tss/unused-classes': 'warn',
51
- '@agilebot/tss/no-color-value': 'error',
52
- '@agilebot/tss/class-naming': 'error',
53
- '@agilebot/import/enforce-icon-alias': 'error',
54
- '@agilebot/import/monorepo': 'error',
55
- '@agilebot/others/no-unnecessary-template-literals': 'error'
56
- }
57
- }
58
- };
1
+ // @ts-check
2
+ const path = require('node:path');
3
+ const { globSync } = require('fast-glob');
4
+
5
+ // List all rules in rules folder
6
+ const rulesPath = path.join(__dirname, 'rules');
7
+ const ruleFiles = globSync('**/*.js', {
8
+ cwd: rulesPath
9
+ });
10
+
11
+ /**
12
+ * @type {import('eslint').Linter.RulesRecord}
13
+ */
14
+ const rules = {};
15
+ ruleFiles.forEach(file => {
16
+ const { dir, name } = path.parse(file);
17
+ const ruleName = `${dir}/${name}`;
18
+ rules[ruleName] = require(path.join(rulesPath, file));
19
+ });
20
+
21
+ module.exports.rules = rules;
22
+
23
+ module.exports.configs = {
24
+ recommended: {
25
+ plugins: ['@agilebot'],
26
+ rules: {
27
+ '@agilebot/react/prefer-named-property-access': 'error',
28
+ '@agilebot/react/hook-use-ref': 'warn',
29
+ '@agilebot/react/no-inline-styles': 'error',
30
+ '@agilebot/tss/unused-classes': 'warn',
31
+ '@agilebot/tss/no-color-value': 'error',
32
+ '@agilebot/tss/class-naming': 'error',
33
+ '@agilebot/import/enforce-icon-alias': 'error',
34
+ '@agilebot/import/monorepo': 'error',
35
+ '@agilebot/others/no-unnecessary-template-literals': 'error'
36
+ },
37
+ settings: {
38
+ react: {
39
+ version: '18.0.0'
40
+ }
41
+ }
42
+ }
43
+ };
@@ -1,42 +1,42 @@
1
- module.exports = {
2
- meta: {
3
- type: 'problem', // `problem`, `suggestion`, or `layout`
4
- docs: {
5
- description: 'Enforce alias for @mui/icons-material imports',
6
- recommended: true
7
- },
8
- fixable: 'code', // Or `code` or `whitespace`
9
- schema: [] // Add a schema if the rule has options
10
- },
11
-
12
- create(context) {
13
- return {
14
- ImportDeclaration(node) {
15
- if (
16
- node.source.value !== '@mui/icons-material' &&
17
- node.source.value !== 'mdi-material-ui'
18
- ) {
19
- return;
20
- }
21
-
22
- for (const specifier of node.specifiers) {
23
- if (specifier.type !== 'ImportSpecifier') {
24
- return;
25
- }
26
-
27
- if (specifier.imported.name === specifier.local.name) {
28
- context.report({
29
- node,
30
- message: `Import for ${node.source.value} should be aliased.`,
31
- fix: fixer =>
32
- fixer.replaceText(
33
- specifier,
34
- `${specifier.imported.name} as ${specifier.imported.name}Icon`
35
- )
36
- });
37
- }
38
- }
39
- }
40
- };
41
- }
42
- };
1
+ module.exports = {
2
+ meta: {
3
+ type: 'problem', // `problem`, `suggestion`, or `layout`
4
+ docs: {
5
+ description: 'Enforce alias for @mui/icons-material imports',
6
+ recommended: true
7
+ },
8
+ fixable: 'code', // Or `code` or `whitespace`
9
+ schema: [] // Add a schema if the rule has options
10
+ },
11
+
12
+ create(context) {
13
+ return {
14
+ ImportDeclaration(node) {
15
+ if (
16
+ node.source.value !== '@mui/icons-material' &&
17
+ node.source.value !== 'mdi-material-ui'
18
+ ) {
19
+ return;
20
+ }
21
+
22
+ for (const specifier of node.specifiers) {
23
+ if (specifier.type !== 'ImportSpecifier') {
24
+ return;
25
+ }
26
+
27
+ if (specifier.imported.name === specifier.local.name) {
28
+ context.report({
29
+ node,
30
+ message: `Import for ${node.source.value} should be aliased.`,
31
+ fix: fixer =>
32
+ fixer.replaceText(
33
+ specifier,
34
+ `${specifier.imported.name} as ${specifier.imported.name}Icon`
35
+ )
36
+ });
37
+ }
38
+ }
39
+ }
40
+ };
41
+ }
42
+ };
@@ -1,49 +1,49 @@
1
- const { getSetting } = require('../../util/settings');
2
-
3
- let warnedForMissingPrefix = false;
4
-
5
- module.exports = {
6
- meta: {
7
- type: 'problem', // `problem`, `suggestion`, or `layout`
8
- docs: {
9
- description: 'Enforce import styles for monorepo',
10
- recommended: true
11
- },
12
- fixable: 'code', // Or `code` or `whitespace`
13
- schema: [] // Add a schema if the rule has options
14
- },
15
-
16
- create(context) {
17
- return {
18
- ImportDeclaration(node) {
19
- const prefix = getSetting(context, 'monorepo-prefix');
20
- if (!prefix) {
21
- if (!warnedForMissingPrefix) {
22
- // eslint-disable-next-line no-console -- this is a CLI tool
23
- console.error('Warning: agilebot/monorepo-prefix is not set.');
24
- warnedForMissingPrefix = true;
25
- }
26
- return;
27
- }
28
-
29
- if (!node.source.value.startsWith(prefix)) {
30
- return;
31
- }
32
- const values = node.source.value.split('/');
33
-
34
- if (values[2] === 'src') {
35
- context.report({
36
- node,
37
- message: `Import for ${node.source.value} should not contains src folder.`,
38
- fix: fixer => {
39
- const correctedPath = values
40
- .filter((_, index) => index !== 2)
41
- .join('/');
42
- return fixer.replaceText(node.source, `'${correctedPath}'`);
43
- }
44
- });
45
- }
46
- }
47
- };
48
- }
49
- };
1
+ const { getSetting } = require('../../util/settings');
2
+
3
+ let warnedForMissingPrefix = false;
4
+
5
+ module.exports = {
6
+ meta: {
7
+ type: 'problem', // `problem`, `suggestion`, or `layout`
8
+ docs: {
9
+ description: 'Enforce import styles for monorepo',
10
+ recommended: true
11
+ },
12
+ fixable: 'code', // Or `code` or `whitespace`
13
+ schema: [] // Add a schema if the rule has options
14
+ },
15
+
16
+ create(context) {
17
+ return {
18
+ ImportDeclaration(node) {
19
+ const prefix = getSetting(context, 'monorepo-prefix');
20
+ if (!prefix) {
21
+ if (!warnedForMissingPrefix) {
22
+ // eslint-disable-next-line no-console -- this is a CLI tool
23
+ console.error('Warning: agilebot/monorepo-prefix is not set.');
24
+ warnedForMissingPrefix = true;
25
+ }
26
+ return;
27
+ }
28
+
29
+ if (!node.source.value.startsWith(prefix)) {
30
+ return;
31
+ }
32
+ const values = node.source.value.split('/');
33
+
34
+ if (values[2] === 'src') {
35
+ context.report({
36
+ node,
37
+ message: `Import for ${node.source.value} should not contains src folder.`,
38
+ fix: fixer => {
39
+ const correctedPath = values
40
+ .filter((_, index) => index !== 2)
41
+ .join('/');
42
+ return fixer.replaceText(node.source, `'${correctedPath}'`);
43
+ }
44
+ });
45
+ }
46
+ }
47
+ };
48
+ }
49
+ };
@@ -1,111 +1,111 @@
1
- const {
2
- sortedTemplateElements,
3
- templateLiteralDisplayStr,
4
- findFormatMessageAttrNode,
5
- findFormattedMessageAttrNode,
6
- findAttrNodeInDefineMessages,
7
- findAttrNodeInDefineMessage
8
- } = require('../../util/intl');
9
- const { getIntlIds } = require('../../util/translations');
10
-
11
- // ------------------------------------------------------------------------------
12
- // Rule Definition
13
- // ------------------------------------------------------------------------------
14
-
15
- module.exports = {
16
- meta: {
17
- docs: {
18
- description: 'Validates intl message ids are in locale file',
19
- category: 'Intl',
20
- recommended: true
21
- },
22
- fixable: null,
23
- schema: []
24
- },
25
-
26
- create: function (context) {
27
- const translatedIds = getIntlIds(context);
28
- const translatedIdSet = new Set(translatedIds);
29
-
30
- // ----------------------------------------------------------------------
31
- // Helpers
32
- // ----------------------------------------------------------------------
33
-
34
- function isLiteralTranslated(id) {
35
- return translatedIdSet.has(id);
36
- }
37
-
38
- function isTemplateTranslated(re) {
39
- return translatedIds.some(k => re.test(k));
40
- }
41
-
42
- function processLiteral(node) {
43
- if (!isLiteralTranslated(node.value)) {
44
- context.report({
45
- node: node,
46
- message: 'Missing id: ' + node.value
47
- });
48
- }
49
- }
50
-
51
- function processTemplateLiteral(node) {
52
- const exStr = sortedTemplateElements(node)
53
- .map(e => (!e.value ? '.*' : e.value.raw))
54
- .join('');
55
- const re = new RegExp(exStr);
56
-
57
- if (!isTemplateTranslated(re)) {
58
- context.report({
59
- node: node,
60
- message: 'Missing id pattern: ' + templateLiteralDisplayStr(node)
61
- });
62
- }
63
- }
64
-
65
- function processAttrNode(node) {
66
- if (node.value.type === 'Literal') {
67
- return processLiteral(node.value);
68
- }
69
- if (
70
- node.value.type === 'JSXExpressionContainer' &&
71
- node.value.expression.type === 'TemplateLiteral'
72
- ) {
73
- return processTemplateLiteral(node.value.expression);
74
- }
75
- if (node.value.type === 'TemplateLiteral') {
76
- return processTemplateLiteral(node.value);
77
- }
78
- context.report({
79
- node: node,
80
- message: 'Do not invoke intl by ' + node.value.type
81
- });
82
- }
83
-
84
- // ----------------------------------------------------------------------
85
- // Public
86
- // ----------------------------------------------------------------------
87
-
88
- return {
89
- JSXIdentifier: function (node) {
90
- const attrNode = findFormattedMessageAttrNode(node, 'id');
91
- if (attrNode) {
92
- return processAttrNode(attrNode);
93
- }
94
- },
95
- CallExpression: function (node) {
96
- const attrNode = findFormatMessageAttrNode(node, 'id');
97
- if (attrNode) {
98
- return processAttrNode(attrNode);
99
- }
100
- },
101
- Property: function (node) {
102
- const attrNode =
103
- findAttrNodeInDefineMessages(node, 'id') ||
104
- findAttrNodeInDefineMessage(node, 'id');
105
- if (attrNode) {
106
- return processAttrNode(attrNode);
107
- }
108
- }
109
- };
110
- }
111
- };
1
+ const {
2
+ sortedTemplateElements,
3
+ templateLiteralDisplayStr,
4
+ findFormatMessageAttrNode,
5
+ findFormattedMessageAttrNode,
6
+ findAttrNodeInDefineMessages,
7
+ findAttrNodeInDefineMessage
8
+ } = require('../../util/intl');
9
+ const { getIntlIds } = require('../../util/translations');
10
+
11
+ // ------------------------------------------------------------------------------
12
+ // Rule Definition
13
+ // ------------------------------------------------------------------------------
14
+
15
+ module.exports = {
16
+ meta: {
17
+ docs: {
18
+ description: 'Validates intl message ids are in locale file',
19
+ category: 'Intl',
20
+ recommended: true
21
+ },
22
+ fixable: null,
23
+ schema: []
24
+ },
25
+
26
+ create: function (context) {
27
+ const translatedIds = getIntlIds(context);
28
+ const translatedIdSet = new Set(translatedIds);
29
+
30
+ // ----------------------------------------------------------------------
31
+ // Helpers
32
+ // ----------------------------------------------------------------------
33
+
34
+ function isLiteralTranslated(id) {
35
+ return translatedIdSet.has(id);
36
+ }
37
+
38
+ function isTemplateTranslated(re) {
39
+ return translatedIds.some(k => re.test(k));
40
+ }
41
+
42
+ function processLiteral(node) {
43
+ if (!isLiteralTranslated(node.value)) {
44
+ context.report({
45
+ node: node,
46
+ message: 'Missing id: ' + node.value
47
+ });
48
+ }
49
+ }
50
+
51
+ function processTemplateLiteral(node) {
52
+ const exStr = sortedTemplateElements(node)
53
+ .map(e => (!e.value ? '.*' : e.value.raw))
54
+ .join('');
55
+ const re = new RegExp(exStr);
56
+
57
+ if (!isTemplateTranslated(re)) {
58
+ context.report({
59
+ node: node,
60
+ message: 'Missing id pattern: ' + templateLiteralDisplayStr(node)
61
+ });
62
+ }
63
+ }
64
+
65
+ function processAttrNode(node) {
66
+ if (node.value.type === 'Literal') {
67
+ return processLiteral(node.value);
68
+ }
69
+ if (
70
+ node.value.type === 'JSXExpressionContainer' &&
71
+ node.value.expression.type === 'TemplateLiteral'
72
+ ) {
73
+ return processTemplateLiteral(node.value.expression);
74
+ }
75
+ if (node.value.type === 'TemplateLiteral') {
76
+ return processTemplateLiteral(node.value);
77
+ }
78
+ context.report({
79
+ node: node,
80
+ message: 'Do not invoke intl by ' + node.value.type
81
+ });
82
+ }
83
+
84
+ // ----------------------------------------------------------------------
85
+ // Public
86
+ // ----------------------------------------------------------------------
87
+
88
+ return {
89
+ JSXIdentifier: function (node) {
90
+ const attrNode = findFormattedMessageAttrNode(node, 'id');
91
+ if (attrNode) {
92
+ return processAttrNode(attrNode);
93
+ }
94
+ },
95
+ CallExpression: function (node) {
96
+ const attrNode = findFormatMessageAttrNode(node, 'id');
97
+ if (attrNode) {
98
+ return processAttrNode(attrNode);
99
+ }
100
+ },
101
+ Property: function (node) {
102
+ const attrNode =
103
+ findAttrNodeInDefineMessages(node, 'id') ||
104
+ findAttrNodeInDefineMessage(node, 'id');
105
+ if (attrNode) {
106
+ return processAttrNode(attrNode);
107
+ }
108
+ }
109
+ };
110
+ }
111
+ };