@agilebot/eslint-plugin 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,37 +1,35 @@
1
- const Components = require('eslint-plugin-react/lib/util/Components');
2
-
3
- module.exports = {
4
- meta: {
5
- docs: {
6
- description: 'Ensure naming of useRef hook value.',
7
- recommended: false
8
- },
9
- schema: [],
10
- type: 'suggestion',
11
- hasSuggestions: true
12
- },
13
-
14
- create: Components.detect((context, component, util) => {
15
- return {
16
- CallExpression(node) {
17
- const isImmediateReturn =
18
- node.parent && node.parent.type === 'ReturnStatement';
19
-
20
- if (isImmediateReturn || !util.isReactHookCall(node, ['useRef'])) {
21
- return;
22
- }
23
- if (node.parent.id.type !== 'Identifier') {
24
- return;
25
- }
26
- const variable = node.parent.id.name;
27
-
28
- if (!variable.endsWith('Ref')) {
29
- context.report({
30
- node: node,
31
- message: 'useRef call is not end with "Ref"'
32
- });
33
- }
34
- }
35
- };
36
- })
37
- };
1
+ const Components = require('eslint-plugin-react/lib/util/Components');
2
+
3
+ module.exports = {
4
+ meta: {
5
+ docs: {
6
+ description: 'Ensure naming of useRef hook value.',
7
+ recommended: false
8
+ },
9
+ schema: [],
10
+ type: 'suggestion',
11
+ hasSuggestions: true
12
+ },
13
+
14
+ create: Components.detect((context, component, util) => ({
15
+ CallExpression(node) {
16
+ const isImmediateReturn =
17
+ node.parent && node.parent.type === 'ReturnStatement';
18
+
19
+ if (isImmediateReturn || !util.isReactHookCall(node, ['useRef'])) {
20
+ return;
21
+ }
22
+ if (node.parent.id.type !== 'Identifier') {
23
+ return;
24
+ }
25
+ const variable = node.parent.id.name;
26
+
27
+ if (!variable.endsWith('Ref')) {
28
+ context.report({
29
+ node: node,
30
+ message: 'useRef call is not end with "Ref"'
31
+ });
32
+ }
33
+ }
34
+ }))
35
+ };
@@ -1,87 +1,87 @@
1
- module.exports = {
2
- meta: {
3
- docs: {
4
- description: 'Disallow style props on components and DOM Nodes',
5
- category: 'Best Practices',
6
- recommended: false
7
- },
8
- messages: {
9
- disallowInlineStyles:
10
- 'Avoid using inline styles, use sx prop or tss-react or styled-component instead'
11
- },
12
- schema: [
13
- {
14
- type: 'object',
15
- properties: {
16
- allowedFor: {
17
- type: 'array',
18
- uniqueItems: true,
19
- items: { type: 'string' }
20
- }
21
- }
22
- }
23
- ]
24
- },
25
-
26
- create(context) {
27
- const configuration = context.options[0] || {};
28
- const allowedFor = configuration.allowedFor || [];
29
-
30
- function checkComponent(node) {
31
- const parentName = node.parent.name;
32
- // Extract a component name when using a "namespace", e.g. `<AntdLayout.Content />`.
33
- const tag =
34
- parentName.name ||
35
- `${parentName.object.name}.${parentName.property.name}`;
36
- const componentName = parentName.name || parentName.property.name;
37
- if (
38
- componentName &&
39
- typeof componentName[0] === 'string' &&
40
- componentName[0] !== componentName[0].toUpperCase()
41
- ) {
42
- // This is a DOM node, not a Component, so exit.
43
- return;
44
- }
45
-
46
- if (allowedFor.includes(tag)) {
47
- return;
48
- }
49
- const prop = node.name.name;
50
-
51
- if (prop === 'style') {
52
- context.report({
53
- node,
54
- messageId: 'disallowInlineStyles'
55
- });
56
- }
57
- }
58
-
59
- function checkDOMNodes(node) {
60
- const tag = node.parent.name.name;
61
- if (
62
- !(tag && typeof tag === 'string' && tag[0] !== tag[0].toUpperCase())
63
- ) {
64
- // This is a Component, not a DOM node, so exit.
65
- return;
66
- }
67
- if (allowedFor.includes(tag)) {
68
- return;
69
- }
70
- const prop = node.name.name;
71
-
72
- if (prop === 'style') {
73
- context.report({
74
- node,
75
- messageId: 'disallowInlineStyles'
76
- });
77
- }
78
- }
79
-
80
- return {
81
- JSXAttribute(node) {
82
- checkComponent(node);
83
- checkDOMNodes(node);
84
- }
85
- };
86
- }
87
- };
1
+ module.exports = {
2
+ meta: {
3
+ docs: {
4
+ description: 'Disallow style props on components and DOM Nodes',
5
+ category: 'Best Practices',
6
+ recommended: false
7
+ },
8
+ messages: {
9
+ disallowInlineStyles:
10
+ 'Avoid using inline styles, use sx prop or tss-react or styled-component instead'
11
+ },
12
+ schema: [
13
+ {
14
+ type: 'object',
15
+ properties: {
16
+ allowedFor: {
17
+ type: 'array',
18
+ uniqueItems: true,
19
+ items: { type: 'string' }
20
+ }
21
+ }
22
+ }
23
+ ]
24
+ },
25
+
26
+ create(context) {
27
+ const configuration = context.options[0] || {};
28
+ const allowedFor = configuration.allowedFor || [];
29
+
30
+ function checkComponent(node) {
31
+ const parentName = node.parent.name;
32
+ // Extract a component name when using a "namespace", e.g. `<AntdLayout.Content />`.
33
+ const tag =
34
+ parentName.name ||
35
+ `${parentName.object.name}.${parentName.property.name}`;
36
+ const componentName = parentName.name || parentName.property.name;
37
+ if (
38
+ componentName &&
39
+ typeof componentName[0] === 'string' &&
40
+ componentName[0] !== componentName[0].toUpperCase()
41
+ ) {
42
+ // This is a DOM node, not a Component, so exit.
43
+ return;
44
+ }
45
+
46
+ if (allowedFor.includes(tag)) {
47
+ return;
48
+ }
49
+ const prop = node.name.name;
50
+
51
+ if (prop === 'style') {
52
+ context.report({
53
+ node,
54
+ messageId: 'disallowInlineStyles'
55
+ });
56
+ }
57
+ }
58
+
59
+ function checkDOMNodes(node) {
60
+ const tag = node.parent.name.name;
61
+ if (
62
+ !(tag && typeof tag === 'string' && tag[0] !== tag[0].toUpperCase())
63
+ ) {
64
+ // This is a Component, not a DOM node, so exit.
65
+ return;
66
+ }
67
+ if (allowedFor.includes(tag)) {
68
+ return;
69
+ }
70
+ const prop = node.name.name;
71
+
72
+ if (prop === 'style') {
73
+ context.report({
74
+ node,
75
+ messageId: 'disallowInlineStyles'
76
+ });
77
+ }
78
+ }
79
+
80
+ return {
81
+ JSXAttribute(node) {
82
+ checkComponent(node);
83
+ checkDOMNodes(node);
84
+ }
85
+ };
86
+ }
87
+ };
@@ -1,105 +1,105 @@
1
- const { ESLintUtils } = require('@typescript-eslint/utils');
2
-
3
- /**
4
- * Auto-fix util.
5
- * Ensures that passed key is imported from 'react' package.
6
- */
7
- function* updateImportStatement(context, fixer, key) {
8
- const sourceCode = context.getSourceCode();
9
- const importNode = sourceCode.ast.body.find(
10
- node => node.type === 'ImportDeclaration' && node.source.value === 'react'
11
- );
12
-
13
- // No import from 'react' - create import statement
14
- if (!importNode) {
15
- yield fixer.insertTextBefore(
16
- sourceCode.ast.body[0],
17
- `import { ${key} } from 'react';\n`
18
- );
19
-
20
- return;
21
- }
22
-
23
- // Only default import from 'react' - add named imports section
24
- if (
25
- importNode.specifiers.length === 1 &&
26
- importNode.specifiers[0].type === 'ImportDefaultSpecifier'
27
- ) {
28
- yield fixer.insertTextAfter(importNode.specifiers[0], `, { ${key} }`);
29
-
30
- return;
31
- }
32
-
33
- const alreadyImportedKeys = importNode.specifiers
34
- .filter(specifier => specifier.type === 'ImportSpecifier')
35
- .map(specifier => specifier.imported.name);
36
-
37
- // Named imports section is present and current key is already imported - do nothing
38
- if (alreadyImportedKeys.includes(key)) {
39
- return;
40
- }
41
-
42
- // Named imports section is present and current key is not imported yet - add it to named imports section
43
- yield fixer.insertTextAfter([...importNode.specifiers].pop(), `, ${key}`);
44
- }
45
-
46
- /** @type {import('eslint').Rule.RuleModule} */
47
- module.exports = ESLintUtils.RuleCreator.withoutDocs({
48
- defaultOptions: [],
49
- meta: {
50
- type: 'layout',
51
- fixable: 'code',
52
- docs: {
53
- description:
54
- 'Enforce importing each member of React namespace separately instead of accessing them through React namespace',
55
- category: 'Layout & Formatting'
56
- },
57
- messages: {
58
- illegalReactPropertyAccess:
59
- 'Illegal React property access: {{name}}. Use named import instead.'
60
- }
61
- },
62
-
63
- create(context) {
64
- return {
65
- // Analyze TS types declarations
66
- TSQualifiedName(node) {
67
- // Do nothing to types that are ending with 'Event' as they will overlap with global event types otherwise
68
- if (node.left.name !== 'React' || node.right.name.endsWith('Event')) {
69
- return;
70
- }
71
-
72
- context.report({
73
- node,
74
- messageId: 'illegalReactPropertyAccess',
75
- data: {
76
- name: node.right.name
77
- },
78
- *fix(fixer) {
79
- yield fixer.replaceText(node, node.right.name);
80
- yield* updateImportStatement(context, fixer, node.right.name);
81
- }
82
- });
83
- },
84
-
85
- // Analyze expressions for React.* access
86
- MemberExpression(node) {
87
- if (node.object.name !== 'React') {
88
- return;
89
- }
90
-
91
- context.report({
92
- node,
93
- messageId: 'illegalReactPropertyAccess',
94
- data: {
95
- name: node.property.name
96
- },
97
- *fix(fixer) {
98
- yield fixer.replaceText(node, node.property.name);
99
- yield* updateImportStatement(context, fixer, node.property.name);
100
- }
101
- });
102
- }
103
- };
104
- }
105
- });
1
+ const { ESLintUtils } = require('@typescript-eslint/utils');
2
+
3
+ /**
4
+ * Auto-fix util.
5
+ * Ensures that passed key is imported from 'react' package.
6
+ */
7
+ function* updateImportStatement(context, fixer, key) {
8
+ const sourceCode = context.getSourceCode();
9
+ const importNode = sourceCode.ast.body.find(
10
+ node => node.type === 'ImportDeclaration' && node.source.value === 'react'
11
+ );
12
+
13
+ // No import from 'react' - create import statement
14
+ if (!importNode) {
15
+ yield fixer.insertTextBefore(
16
+ sourceCode.ast.body[0],
17
+ `import { ${key} } from 'react';\n`
18
+ );
19
+
20
+ return;
21
+ }
22
+
23
+ // Only default import from 'react' - add named imports section
24
+ if (
25
+ importNode.specifiers.length === 1 &&
26
+ importNode.specifiers[0].type === 'ImportDefaultSpecifier'
27
+ ) {
28
+ yield fixer.insertTextAfter(importNode.specifiers[0], `, { ${key} }`);
29
+
30
+ return;
31
+ }
32
+
33
+ const alreadyImportedKeys = importNode.specifiers
34
+ .filter(specifier => specifier.type === 'ImportSpecifier')
35
+ .map(specifier => specifier.imported.name);
36
+
37
+ // Named imports section is present and current key is already imported - do nothing
38
+ if (alreadyImportedKeys.includes(key)) {
39
+ return;
40
+ }
41
+
42
+ // Named imports section is present and current key is not imported yet - add it to named imports section
43
+ yield fixer.insertTextAfter([...importNode.specifiers].pop(), `, ${key}`);
44
+ }
45
+
46
+ /** @type {import('eslint').Rule.RuleModule} */
47
+ module.exports = ESLintUtils.RuleCreator.withoutDocs({
48
+ defaultOptions: [],
49
+ meta: {
50
+ type: 'layout',
51
+ fixable: 'code',
52
+ docs: {
53
+ description:
54
+ 'Enforce importing each member of React namespace separately instead of accessing them through React namespace',
55
+ category: 'Layout & Formatting'
56
+ },
57
+ messages: {
58
+ illegalReactPropertyAccess:
59
+ 'Illegal React property access: {{name}}. Use named import instead.'
60
+ }
61
+ },
62
+
63
+ create(context) {
64
+ return {
65
+ // Analyze TS types declarations
66
+ TSQualifiedName(node) {
67
+ // Do nothing to types that are ending with 'Event' as they will overlap with global event types otherwise
68
+ if (node.left.name !== 'React' || node.right.name.endsWith('Event')) {
69
+ return;
70
+ }
71
+
72
+ context.report({
73
+ node,
74
+ messageId: 'illegalReactPropertyAccess',
75
+ data: {
76
+ name: node.right.name
77
+ },
78
+ *fix(fixer) {
79
+ yield fixer.replaceText(node, node.right.name);
80
+ yield* updateImportStatement(context, fixer, node.right.name);
81
+ }
82
+ });
83
+ },
84
+
85
+ // Analyze expressions for React.* access
86
+ MemberExpression(node) {
87
+ if (node.object.name !== 'React') {
88
+ return;
89
+ }
90
+
91
+ context.report({
92
+ node,
93
+ messageId: 'illegalReactPropertyAccess',
94
+ data: {
95
+ name: node.property.name
96
+ },
97
+ *fix(fixer) {
98
+ yield fixer.replaceText(node, node.property.name);
99
+ yield* updateImportStatement(context, fixer, node.property.name);
100
+ }
101
+ });
102
+ }
103
+ };
104
+ }
105
+ });
@@ -1,43 +1,43 @@
1
- const { getStyesObj, isCamelCase } = require('../../util/tss');
2
-
3
- module.exports = {
4
- meta: {
5
- type: 'problem'
6
- },
7
- create: function rule(context) {
8
- return {
9
- CallExpression(node) {
10
- const stylesObj = getStyesObj(node);
11
-
12
- if (stylesObj === undefined) {
13
- return;
14
- }
15
-
16
- stylesObj.properties.forEach(property => {
17
- if (property.computed) {
18
- // Skip over computed properties for now.
19
- // e.g. `{ [foo]: { ... } }`
20
- return;
21
- }
22
-
23
- if (
24
- property.type === 'ExperimentalSpreadProperty' ||
25
- property.type === 'SpreadElement'
26
- ) {
27
- // Skip over object spread for now.
28
- // e.g. `{ ...foo }`
29
- return;
30
- }
31
-
32
- const className = property.key.value || property.key.name;
33
- if (!isCamelCase(className)) {
34
- context.report(
35
- property,
36
- `Class \`${className}\` must be camelCase in makeStyles.`
37
- );
38
- }
39
- });
40
- }
41
- };
42
- }
43
- };
1
+ const { getStyesObj, isCamelCase } = require('../../util/tss');
2
+
3
+ module.exports = {
4
+ meta: {
5
+ type: 'problem'
6
+ },
7
+ create: function rule(context) {
8
+ return {
9
+ CallExpression(node) {
10
+ const stylesObj = getStyesObj(node);
11
+
12
+ if (stylesObj === undefined) {
13
+ return;
14
+ }
15
+
16
+ stylesObj.properties.forEach(property => {
17
+ if (property.computed) {
18
+ // Skip over computed properties for now.
19
+ // e.g. `{ [foo]: { ... } }`
20
+ return;
21
+ }
22
+
23
+ if (
24
+ property.type === 'ExperimentalSpreadProperty' ||
25
+ property.type === 'SpreadElement'
26
+ ) {
27
+ // Skip over object spread for now.
28
+ // e.g. `{ ...foo }`
29
+ return;
30
+ }
31
+
32
+ const className = property.key.value || property.key.name;
33
+ if (!isCamelCase(className)) {
34
+ context.report(
35
+ property,
36
+ `Class \`${className}\` must be camelCase in makeStyles.`
37
+ );
38
+ }
39
+ });
40
+ }
41
+ };
42
+ }
43
+ };
@@ -1,58 +1,58 @@
1
- const { getStyesObj } = require('../../util/tss');
2
-
3
- module.exports = {
4
- meta: {
5
- type: 'problem',
6
- docs: {
7
- description:
8
- 'Enforce the use of color variables instead of color codes within makeStyles'
9
- }
10
- },
11
- create: function (context) {
12
- const parserOptions = context.parserOptions;
13
- if (!parserOptions || !parserOptions.project) {
14
- return {};
15
- }
16
-
17
- return {
18
- CallExpression(node) {
19
- const stylesObj = getStyesObj(node);
20
- if (!stylesObj) {
21
- return;
22
- }
23
-
24
- // Check for color codes inside the stylesObj
25
- function checkColorLiteral(value) {
26
- if (value.type === 'Literal' && typeof value.value === 'string') {
27
- const colorCodePattern =
28
- /#(?:[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;
29
- const isColorCode = colorCodePattern.test(value.value);
30
- if (isColorCode) {
31
- context.report({
32
- node: value,
33
- message:
34
- 'Use color variables instead of color codes in makeStyles.'
35
- });
36
- }
37
- }
38
- }
39
-
40
- function loopStylesObj(obj) {
41
- if (obj && obj.type === 'ObjectExpression') {
42
- obj.properties.forEach(property => {
43
- if (property.type === 'Property' && property.value) {
44
- if (property.value.type === 'ObjectExpression') {
45
- loopStylesObj(property.value);
46
- } else {
47
- checkColorLiteral(property.value);
48
- }
49
- }
50
- });
51
- }
52
- }
53
-
54
- loopStylesObj(stylesObj);
55
- }
56
- };
57
- }
58
- };
1
+ const { getStyesObj } = require('../../util/tss');
2
+
3
+ module.exports = {
4
+ meta: {
5
+ type: 'problem',
6
+ docs: {
7
+ description:
8
+ 'Enforce the use of color variables instead of color codes within makeStyles'
9
+ }
10
+ },
11
+ create: function (context) {
12
+ const parserOptions = context.parserOptions;
13
+ if (!parserOptions || !parserOptions.project) {
14
+ return {};
15
+ }
16
+
17
+ return {
18
+ CallExpression(node) {
19
+ const stylesObj = getStyesObj(node);
20
+ if (!stylesObj) {
21
+ return;
22
+ }
23
+
24
+ // Check for color codes inside the stylesObj
25
+ function checkColorLiteral(value) {
26
+ if (value.type === 'Literal' && typeof value.value === 'string') {
27
+ const colorCodePattern =
28
+ /#(?:[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;
29
+ const isColorCode = colorCodePattern.test(value.value);
30
+ if (isColorCode) {
31
+ context.report({
32
+ node: value,
33
+ message:
34
+ 'Use color variables instead of color codes in makeStyles.'
35
+ });
36
+ }
37
+ }
38
+ }
39
+
40
+ function loopStylesObj(obj) {
41
+ if (obj && obj.type === 'ObjectExpression') {
42
+ obj.properties.forEach(property => {
43
+ if (property.type === 'Property' && property.value) {
44
+ if (property.value.type === 'ObjectExpression') {
45
+ loopStylesObj(property.value);
46
+ } else {
47
+ checkColorLiteral(property.value);
48
+ }
49
+ }
50
+ });
51
+ }
52
+ }
53
+
54
+ loopStylesObj(stylesObj);
55
+ }
56
+ };
57
+ }
58
+ };