@blumintinc/eslint-plugin-blumint 1.7.1 → 1.7.2

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/lib/index.js CHANGED
@@ -69,10 +69,11 @@ const enforce_centralized_mock_firestore_1 = require("./rules/enforce-centralize
69
69
  const require_hooks_default_params_1 = require("./rules/require-hooks-default-params");
70
70
  const prefer_destructuring_no_class_1 = require("./rules/prefer-destructuring-no-class");
71
71
  const enforce_render_hits_memoization_1 = require("./rules/enforce-render-hits-memoization");
72
+ const prefer_fragment_component_1 = require("./rules/prefer-fragment-component");
72
73
  module.exports = {
73
74
  meta: {
74
75
  name: '@blumintinc/eslint-plugin-blumint',
75
- version: '1.7.1',
76
+ version: '1.7.2',
76
77
  },
77
78
  parseOptions: {
78
79
  ecmaVersion: 2020,
@@ -104,7 +105,7 @@ module.exports = {
104
105
  '@blumintinc/blumint/no-unpinned-dependencies': 'error',
105
106
  '@blumintinc/blumint/no-unused-props': 'error',
106
107
  //'@blumintinc/blumint/no-useless-fragment': 'error',
107
- '@blumintinc/blumint/prefer-fragment-shorthand': 'error',
108
+ //'@blumintinc/blumint/prefer-fragment-shorthand': 'error',
108
109
  '@blumintinc/blumint/prefer-type-over-interface': 'error',
109
110
  '@blumintinc/blumint/require-memo': 'error',
110
111
  '@blumintinc/blumint/require-dynamic-firebase-imports': 'error',
@@ -147,6 +148,7 @@ module.exports = {
147
148
  '@blumintinc/blumint/require-hooks-default-params': 'error',
148
149
  '@blumintinc/blumint/prefer-destructuring-no-class': 'error',
149
150
  '@blumintinc/blumint/enforce-render-hits-memoization': 'error',
151
+ '@blumintinc/blumint/prefer-fragment-component': 'error',
150
152
  },
151
153
  },
152
154
  },
@@ -217,6 +219,7 @@ module.exports = {
217
219
  'require-hooks-default-params': require_hooks_default_params_1.requireHooksDefaultParams,
218
220
  'prefer-destructuring-no-class': prefer_destructuring_no_class_1.preferDestructuringNoClass,
219
221
  'enforce-render-hits-memoization': enforce_render_hits_memoization_1.enforceRenderHitsMemoization,
222
+ 'prefer-fragment-component': prefer_fragment_component_1.preferFragmentComponent,
220
223
  },
221
224
  };
222
225
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,4 @@
1
+ import { TSESLint } from '@typescript-eslint/utils';
2
+ type MessageIds = 'preferFragment' | 'addFragmentImport';
3
+ export declare const preferFragmentComponent: TSESLint.RuleModule<MessageIds, [], TSESLint.RuleListener>;
4
+ export {};
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.preferFragmentComponent = void 0;
4
+ const utils_1 = require("@typescript-eslint/utils");
5
+ const createRule_1 = require("../utils/createRule");
6
+ exports.preferFragmentComponent = (0, createRule_1.createRule)({
7
+ name: 'prefer-fragment-component',
8
+ meta: {
9
+ type: 'suggestion',
10
+ docs: {
11
+ description: 'Enforce using Fragment imported from react over shorthand fragments and React.Fragment',
12
+ recommended: 'error',
13
+ },
14
+ fixable: 'code',
15
+ schema: [],
16
+ messages: {
17
+ preferFragment: 'Use Fragment imported from react instead of {{type}}',
18
+ addFragmentImport: 'Add Fragment import from react',
19
+ },
20
+ },
21
+ defaultOptions: [],
22
+ create(context) {
23
+ const sourceCode = context.getSourceCode();
24
+ let hasFragmentImport = false;
25
+ let reactImportNode = null;
26
+ function getReactImportNode() {
27
+ const program = sourceCode.ast;
28
+ for (const node of program.body) {
29
+ if (node.type === utils_1.AST_NODE_TYPES.ImportDeclaration &&
30
+ node.source.value === 'react') {
31
+ return node;
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+ function checkFragmentImport(node) {
37
+ if (node.source.value === 'react') {
38
+ reactImportNode = node;
39
+ for (const specifier of node.specifiers) {
40
+ if (specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
41
+ specifier.imported.name === 'Fragment') {
42
+ hasFragmentImport = true;
43
+ break;
44
+ }
45
+ }
46
+ }
47
+ }
48
+ function addFragmentImport(fixer) {
49
+ if (reactImportNode) {
50
+ // Add Fragment to existing react import
51
+ const lastSpecifier = reactImportNode.specifiers[reactImportNode.specifiers.length - 1];
52
+ return fixer.insertTextAfter(lastSpecifier, ', Fragment');
53
+ }
54
+ // Add new react import with Fragment
55
+ return fixer.insertTextBefore(sourceCode.ast.body[0], 'import { Fragment } from \'react\';\n');
56
+ }
57
+ return {
58
+ ImportDeclaration: checkFragmentImport,
59
+ JSXFragment(node) {
60
+ context.report({
61
+ node,
62
+ messageId: 'preferFragment',
63
+ data: { type: 'shorthand fragment (<>)' },
64
+ *fix(fixer) {
65
+ if (!hasFragmentImport) {
66
+ yield addFragmentImport(fixer);
67
+ }
68
+ yield fixer.replaceText(node.openingFragment, '<Fragment>');
69
+ yield fixer.replaceText(node.closingFragment, '</Fragment>');
70
+ },
71
+ });
72
+ },
73
+ JSXIdentifier(node) {
74
+ if (node.name === 'Fragment' &&
75
+ node.parent?.type === utils_1.AST_NODE_TYPES.JSXMemberExpression &&
76
+ node.parent.object.type === utils_1.AST_NODE_TYPES.JSXIdentifier &&
77
+ node.parent.object.name === 'React') {
78
+ const memberExpr = node.parent;
79
+ context.report({
80
+ node: memberExpr,
81
+ messageId: 'preferFragment',
82
+ data: { type: 'React.Fragment' },
83
+ *fix(fixer) {
84
+ if (!hasFragmentImport) {
85
+ yield addFragmentImport(fixer);
86
+ }
87
+ yield fixer.replaceText(memberExpr, 'Fragment');
88
+ },
89
+ });
90
+ }
91
+ },
92
+ 'Program:exit'() {
93
+ // If we found any violations but no Fragment import, we need to add it
94
+ if (!hasFragmentImport && !reactImportNode) {
95
+ reactImportNode = getReactImportNode();
96
+ }
97
+ },
98
+ };
99
+ },
100
+ });
101
+ //# sourceMappingURL=prefer-fragment-component.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blumintinc/eslint-plugin-blumint",
3
- "version": "1.7.1",
3
+ "version": "1.7.2",
4
4
  "description": "Custom eslint rules for use within BluMint",
5
5
  "author": {
6
6
  "name": "Brodie McGuire",