@blumintinc/eslint-plugin-blumint 1.21.2 → 1.21.3
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 +1 -1
- package/lib/rules/enforce-boolean-naming-prefixes.js +28 -5
- package/lib/rules/enforce-centralized-mock-firestore.d.ts +2 -1
- package/lib/rules/enforce-centralized-mock-firestore.js +173 -38
- package/lib/rules/enforce-fieldpath-syntax-in-docsetter.js +78 -13
- package/lib/rules/enforce-firestore-set-merge.js +155 -4
- package/lib/rules/enforce-object-literal-as-const.js +85 -4
- package/lib/rules/enforce-positive-naming.js +17 -13
- package/lib/rules/enforce-snapshot-state-narrowing.d.ts +1 -1
- package/lib/rules/enforce-snapshot-state-narrowing.js +39 -19
- package/lib/rules/memo-nested-react-components.js +12 -0
- package/lib/rules/no-entire-object-hook-deps.js +26 -3
- package/lib/rules/no-hungarian.js +14 -0
- package/lib/rules/no-inline-component-prop.js +83 -14
- package/lib/rules/no-restricted-properties-fix.js +53 -3
- package/lib/rules/no-useless-usememo-primitives.js +43 -11
- package/lib/rules/prefer-destructuring-no-class.js +65 -11
- package/lib/rules/prefer-document-flattening.js +71 -35
- package/lib/rules/require-memoize-jsx-returners.js +18 -4
- package/lib/rules/use-custom-memo.js +4 -6
- package/lib/utils/memoModule.d.ts +26 -0
- package/lib/utils/memoModule.js +54 -0
- package/package.json +1 -1
- package/release-manifest.json +134 -0
|
@@ -3,9 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.useCustomMemo = void 0;
|
|
4
4
|
const utils_1 = require("@typescript-eslint/utils");
|
|
5
5
|
const createRule_1 = require("../utils/createRule");
|
|
6
|
-
const
|
|
7
|
-
/** `MEMO_MODULE` carries the quotes the fixer emits; a path never does. */
|
|
8
|
-
const MEMO_MODULE_PATH = MEMO_MODULE.slice(1, -1);
|
|
6
|
+
const memoModule_1 = require("../utils/memoModule");
|
|
9
7
|
const SOURCE_EXTENSION = /\.(?:ts|tsx|js|jsx)$/;
|
|
10
8
|
/**
|
|
11
9
|
* The module the fixer points every `memo` import at is the one module that must
|
|
@@ -20,10 +18,10 @@ const SOURCE_EXTENSION = /\.(?:ts|tsx|js|jsx)$/;
|
|
|
20
18
|
*/
|
|
21
19
|
const isMemoModule = (filename) => {
|
|
22
20
|
const normalized = filename.replace(/\\/g, '/').replace(SOURCE_EXTENSION, '');
|
|
23
|
-
if (!normalized.endsWith(
|
|
21
|
+
if (!normalized.endsWith(memoModule_1.CUSTOM_MEMO_MODULE_PATH)) {
|
|
24
22
|
return false;
|
|
25
23
|
}
|
|
26
|
-
const suffixStart = normalized.length -
|
|
24
|
+
const suffixStart = normalized.length - memoModule_1.CUSTOM_MEMO_MODULE_PATH.length;
|
|
27
25
|
return suffixStart === 0 || normalized[suffixStart - 1] === '/';
|
|
28
26
|
};
|
|
29
27
|
const isComment = (token) => token.type === utils_1.AST_TOKEN_TYPES.Line || token.type === utils_1.AST_TOKEN_TYPES.Block;
|
|
@@ -206,7 +204,7 @@ exports.useCustomMemo = (0, createRule_1.createRule)({
|
|
|
206
204
|
messageId: 'useCustomMemo',
|
|
207
205
|
fix(fixer) {
|
|
208
206
|
const sourceCode = context.getSourceCode();
|
|
209
|
-
const memoImport = buildImport(memoSpecifiers,
|
|
207
|
+
const memoImport = buildImport(memoSpecifiers, memoModule_1.CUSTOM_MEMO_MODULE_SOURCE, node.importKind, sourceCode);
|
|
210
208
|
const survivingSpecifiers = node.specifiers.filter((specifier) => !isMemoSpecifier(specifier));
|
|
211
209
|
const comments = sourceCode
|
|
212
210
|
.getCommentsInside(node)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The project's memo wrapper: the module `use-custom-memo`'s fixer points every
|
|
3
|
+
* `import { memo } from 'react'` at. It re-exports React's `memo`, so a rule
|
|
4
|
+
* that recognises a `memo(...)` call has to accept this module's binding as
|
|
5
|
+
* React's — keying recognition on the `'react'` spelling alone lets that fixer
|
|
6
|
+
* switch the recogniser off on the very convention this plugin enforces.
|
|
7
|
+
*
|
|
8
|
+
* The quotes live inside the value because the fixer splices the specifier into
|
|
9
|
+
* emitted import text verbatim, beside `sourceCode.getText(node.source)`, which
|
|
10
|
+
* carries its own quotes.
|
|
11
|
+
*/
|
|
12
|
+
export declare const CUSTOM_MEMO_MODULE_SOURCE = "'src/util/memo'";
|
|
13
|
+
/** `CUSTOM_MEMO_MODULE_SOURCE` carries the quotes the fixer emits; a path never does. */
|
|
14
|
+
export declare const CUSTOM_MEMO_MODULE_PATH: string;
|
|
15
|
+
/** Whether an import specifier, read alone, names the memo wrapper module. */
|
|
16
|
+
export declare const isCustomMemoModuleSource: (source: string) => boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether `source`, imported from `filename`, names the memo wrapper module.
|
|
19
|
+
*
|
|
20
|
+
* A relative specifier is resolved against the importing file before matching,
|
|
21
|
+
* because a file that sits inside the wrapper's own directory spells the same
|
|
22
|
+
* module `../memo` — a specifier naming no `util` segment of its own. Only
|
|
23
|
+
* relative specifiers resolve: a bare specifier is a package or an alias whose
|
|
24
|
+
* target the linter cannot know without a resolver.
|
|
25
|
+
*/
|
|
26
|
+
export declare const isCustomMemoModuleImport: (source: string, filename?: string) => boolean;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isCustomMemoModuleImport = exports.isCustomMemoModuleSource = exports.CUSTOM_MEMO_MODULE_PATH = exports.CUSTOM_MEMO_MODULE_SOURCE = void 0;
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
8
|
+
/**
|
|
9
|
+
* The project's memo wrapper: the module `use-custom-memo`'s fixer points every
|
|
10
|
+
* `import { memo } from 'react'` at. It re-exports React's `memo`, so a rule
|
|
11
|
+
* that recognises a `memo(...)` call has to accept this module's binding as
|
|
12
|
+
* React's — keying recognition on the `'react'` spelling alone lets that fixer
|
|
13
|
+
* switch the recogniser off on the very convention this plugin enforces.
|
|
14
|
+
*
|
|
15
|
+
* The quotes live inside the value because the fixer splices the specifier into
|
|
16
|
+
* emitted import text verbatim, beside `sourceCode.getText(node.source)`, which
|
|
17
|
+
* carries its own quotes.
|
|
18
|
+
*/
|
|
19
|
+
exports.CUSTOM_MEMO_MODULE_SOURCE = `'src/util/memo'`;
|
|
20
|
+
/** `CUSTOM_MEMO_MODULE_SOURCE` carries the quotes the fixer emits; a path never does. */
|
|
21
|
+
exports.CUSTOM_MEMO_MODULE_PATH = exports.CUSTOM_MEMO_MODULE_SOURCE.slice(1, -1);
|
|
22
|
+
/**
|
|
23
|
+
* The trailing segments that identify the wrapper module however it is spelled.
|
|
24
|
+
* Only the leading segments vary between spellings of the same module — the
|
|
25
|
+
* `src/` alias the fixer emits, a `@/` alias, or any depth of `../` — so the
|
|
26
|
+
* tail is what a specifier has to carry. It has to land on a segment boundary,
|
|
27
|
+
* so `./memo`, `lodash-memo` and `react-memo` name other modules and stay out.
|
|
28
|
+
*/
|
|
29
|
+
const MODULE_TAIL = exports.CUSTOM_MEMO_MODULE_PATH.split('/').slice(-2).join('/');
|
|
30
|
+
const MODULE_TAIL_PATTERN = new RegExp(`(?:^|/)${MODULE_TAIL}$`);
|
|
31
|
+
/** Whether an import specifier, read alone, names the memo wrapper module. */
|
|
32
|
+
const isCustomMemoModuleSource = (source) => MODULE_TAIL_PATTERN.test(source);
|
|
33
|
+
exports.isCustomMemoModuleSource = isCustomMemoModuleSource;
|
|
34
|
+
/**
|
|
35
|
+
* Whether `source`, imported from `filename`, names the memo wrapper module.
|
|
36
|
+
*
|
|
37
|
+
* A relative specifier is resolved against the importing file before matching,
|
|
38
|
+
* because a file that sits inside the wrapper's own directory spells the same
|
|
39
|
+
* module `../memo` — a specifier naming no `util` segment of its own. Only
|
|
40
|
+
* relative specifiers resolve: a bare specifier is a package or an alias whose
|
|
41
|
+
* target the linter cannot know without a resolver.
|
|
42
|
+
*/
|
|
43
|
+
const isCustomMemoModuleImport = (source, filename) => {
|
|
44
|
+
if ((0, exports.isCustomMemoModuleSource)(source)) {
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
if (!filename || !source.startsWith('.')) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const importerDirectory = path_1.default.posix.dirname(filename.replace(/\\/g, '/'));
|
|
51
|
+
return (0, exports.isCustomMemoModuleSource)(path_1.default.posix.normalize(path_1.default.posix.join(importerDirectory, source)));
|
|
52
|
+
};
|
|
53
|
+
exports.isCustomMemoModuleImport = isCustomMemoModuleImport;
|
|
54
|
+
//# sourceMappingURL=memoModule.js.map
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -1,4 +1,138 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.21.3",
|
|
4
|
+
"date": "2026-09-03T23:34:34.310Z",
|
|
5
|
+
"rules": [
|
|
6
|
+
{
|
|
7
|
+
"name": "enforce-boolean-naming-prefixes",
|
|
8
|
+
"changeType": "fix",
|
|
9
|
+
"issues": [
|
|
10
|
+
2308
|
|
11
|
+
],
|
|
12
|
+
"summary": "accept `??` as a boolean fallback operator (closes #2308)"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "enforce-centralized-mock-firestore",
|
|
16
|
+
"changeType": "fix",
|
|
17
|
+
"issues": [
|
|
18
|
+
2307
|
|
19
|
+
],
|
|
20
|
+
"summary": "match the local mock by normalized name so a MOCK_FIRESTORE constant is flagged (closes #2307)"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "enforce-fieldpath-syntax-in-docsetter",
|
|
24
|
+
"changeType": "fix",
|
|
25
|
+
"issues": [
|
|
26
|
+
2303
|
|
27
|
+
],
|
|
28
|
+
"summary": "decline the fix when a flattened key collides (closes #2303)"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "enforce-firestore-set-merge",
|
|
32
|
+
"changeType": "fix",
|
|
33
|
+
"issues": [
|
|
34
|
+
2311
|
|
35
|
+
],
|
|
36
|
+
"summary": "decline the merge rewrite on update's varargs and precondition forms (closes #2311)"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"name": "enforce-object-literal-as-const",
|
|
40
|
+
"changeType": "fix",
|
|
41
|
+
"issues": [
|
|
42
|
+
2319
|
|
43
|
+
],
|
|
44
|
+
"summary": "fall back to the sole return's own assertion for the declared type (closes #2319)"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"name": "enforce-positive-naming",
|
|
48
|
+
"changeType": "fix",
|
|
49
|
+
"issues": [
|
|
50
|
+
2306
|
|
51
|
+
],
|
|
52
|
+
"summary": "make the boolean-like gate spelling-independent (closes #2306)"
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"name": "enforce-snapshot-state-narrowing",
|
|
56
|
+
"changeType": "fix",
|
|
57
|
+
"issues": [
|
|
58
|
+
2315
|
|
59
|
+
],
|
|
60
|
+
"summary": "accept ?? alongside || in the logical guard (closes #2315)"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"name": "memo-nested-react-components",
|
|
64
|
+
"changeType": "fix",
|
|
65
|
+
"issues": [
|
|
66
|
+
2313
|
|
67
|
+
],
|
|
68
|
+
"summary": "admit useLatestCallback as a callback hook (closes #2313)"
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "no-entire-object-hook-deps",
|
|
72
|
+
"changeType": "fix",
|
|
73
|
+
"issues": [
|
|
74
|
+
2309
|
|
75
|
+
],
|
|
76
|
+
"summary": "govern the deep-compare hooks, which the useMemo rename walked out of view (closes #2309)"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"name": "no-hungarian",
|
|
80
|
+
"changeType": "fix",
|
|
81
|
+
"issues": [
|
|
82
|
+
2317
|
|
83
|
+
],
|
|
84
|
+
"summary": "read a leading single-letter segment as a prefix in SCREAMING_SNAKE_CASE (closes #2317)"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"name": "no-inline-component-prop",
|
|
88
|
+
"changeType": "fix",
|
|
89
|
+
"issues": [
|
|
90
|
+
2314
|
|
91
|
+
],
|
|
92
|
+
"summary": "resolve a memo(namedReference) argument to its declaration (closes #2314)"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"name": "no-restricted-properties-fix",
|
|
96
|
+
"changeType": "fix",
|
|
97
|
+
"issues": [
|
|
98
|
+
2318
|
|
99
|
+
],
|
|
100
|
+
"summary": "match a configured object through global-const-style's rename (closes #2318)"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"name": "no-useless-usememo-primitives",
|
|
104
|
+
"changeType": "fix",
|
|
105
|
+
"issues": [
|
|
106
|
+
2312
|
|
107
|
+
],
|
|
108
|
+
"summary": "recognise the deep-compare memo spelling so a renamed callee still reports (closes #2312)"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "prefer-destructuring-no-class",
|
|
112
|
+
"changeType": "fix",
|
|
113
|
+
"issues": [
|
|
114
|
+
2316
|
|
115
|
+
],
|
|
116
|
+
"summary": "match a binding to its property ignoring case and underscores (closes #2316)"
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"name": "prefer-document-flattening",
|
|
120
|
+
"changeType": "fix",
|
|
121
|
+
"issues": [
|
|
122
|
+
2304
|
|
123
|
+
],
|
|
124
|
+
"summary": "rewrite an existing shouldFlatten in place rather than appending a duplicate key (closes #2304)"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"name": "require-memoize-jsx-returners",
|
|
128
|
+
"changeType": "fix",
|
|
129
|
+
"issues": [
|
|
130
|
+
2305
|
|
131
|
+
],
|
|
132
|
+
"summary": "re-cut the degenerate-identifier duplicate ceiling for the wrapper-memo fixtures (closes #2305); recognise memo imported from the project memo wrapper (closes #2305)"
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
},
|
|
2
136
|
{
|
|
3
137
|
"version": "1.21.2",
|
|
4
138
|
"date": "2026-09-03T01:55:23.074Z",
|