eslint-plugin-conventions 4.0.0
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/README.md +80 -0
- package/package.json +55 -0
- package/src/index.d.ts +198 -0
- package/src/index.js +60 -0
- package/src/index.js.map +1 -0
- package/src/lib/eslint-plugin-conventions.d.ts +1 -0
- package/src/lib/eslint-plugin-conventions.js +7 -0
- package/src/lib/eslint-plugin-conventions.js.map +1 -0
- package/src/rules/conventions/consistent-existence-index-check.d.ts +19 -0
- package/src/rules/conventions/consistent-existence-index-check.js +141 -0
- package/src/rules/conventions/consistent-existence-index-check.js.map +1 -0
- package/src/rules/conventions/expiring-todo-comments.d.ts +24 -0
- package/src/rules/conventions/expiring-todo-comments.js +307 -0
- package/src/rules/conventions/expiring-todo-comments.js.map +1 -0
- package/src/rules/conventions/filename-case.d.ts +32 -0
- package/src/rules/conventions/filename-case.js +264 -0
- package/src/rules/conventions/filename-case.js.map +1 -0
- package/src/rules/conventions/no-commented-code.d.ts +26 -0
- package/src/rules/conventions/no-commented-code.js +278 -0
- package/src/rules/conventions/no-commented-code.js.map +1 -0
- package/src/rules/conventions/no-console-spaces.d.ts +13 -0
- package/src/rules/conventions/no-console-spaces.js +128 -0
- package/src/rules/conventions/no-console-spaces.js.map +1 -0
- package/src/rules/conventions/prefer-code-point.d.ts +13 -0
- package/src/rules/conventions/prefer-code-point.js +95 -0
- package/src/rules/conventions/prefer-code-point.js.map +1 -0
- package/src/rules/conventions/prefer-dependency-version-strategy.d.ts +29 -0
- package/src/rules/conventions/prefer-dependency-version-strategy.js +226 -0
- package/src/rules/conventions/prefer-dependency-version-strategy.js.map +1 -0
- package/src/rules/conventions/prefer-dom-node-text-content.d.ts +13 -0
- package/src/rules/conventions/prefer-dom-node-text-content.js +147 -0
- package/src/rules/conventions/prefer-dom-node-text-content.js.map +1 -0
- package/src/rules/deprecation/no-deprecated-api.d.ts +30 -0
- package/src/rules/deprecation/no-deprecated-api.js +174 -0
- package/src/rules/deprecation/no-deprecated-api.js.map +1 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Ofri Peretz
|
|
4
|
+
* Licensed under the MIT License. Use of this source code is governed by the
|
|
5
|
+
* MIT license that can be found in the LICENSE file.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.noCommentedCode = void 0;
|
|
9
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
+
const eslint_devkit_2 = require("@interlace/eslint-devkit");
|
|
11
|
+
/**
|
|
12
|
+
* Check if a comment block contains code-like patterns
|
|
13
|
+
*/
|
|
14
|
+
function looksLikeCode(comment, isBlockComment) {
|
|
15
|
+
// Remove comment markers for pattern matching
|
|
16
|
+
let text = comment;
|
|
17
|
+
if (isBlockComment) {
|
|
18
|
+
// Remove /* and */ markers and any leading * on each line
|
|
19
|
+
text = text.replace(/^\s*\/\*+/, '').replace(/\*+\/\s*$/, '');
|
|
20
|
+
// Remove leading * from each line in block comments
|
|
21
|
+
text = text
|
|
22
|
+
.split('\n')
|
|
23
|
+
.map((line) => line.replace(/^\s*\*+\s*/, ''))
|
|
24
|
+
.join('\n');
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
// Remove // markers
|
|
28
|
+
text = text
|
|
29
|
+
.split('\n')
|
|
30
|
+
.map((line) => line.replace(/^\s*\/\/+\s*/, ''))
|
|
31
|
+
.join('\n');
|
|
32
|
+
}
|
|
33
|
+
// Split into lines and check each line
|
|
34
|
+
const lines = text
|
|
35
|
+
.split('\n')
|
|
36
|
+
.map((line) => line.trim())
|
|
37
|
+
.filter((line) => line.length > 0);
|
|
38
|
+
if (lines.length === 0) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const codePatterns = [
|
|
42
|
+
/^(const|let|var|function|class|if|for|while|return|import|export)\s+/,
|
|
43
|
+
/^[a-zA-Z_$][a-zA-Z0-9_$]*\s*[=:]\s*/,
|
|
44
|
+
/^[a-zA-Z_$][a-zA-Z0-9_$]*\s*\(/,
|
|
45
|
+
/^[{}[\]]/,
|
|
46
|
+
];
|
|
47
|
+
// Count how many lines look like code
|
|
48
|
+
let codeLikeLines = 0;
|
|
49
|
+
// Check if any line looks like code (but not a TODO comment)
|
|
50
|
+
for (const line of lines) {
|
|
51
|
+
// Skip TODO/FIXME comments
|
|
52
|
+
if (/^(TODO|FIXME|HACK|XXX)/i.test(line)) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
// Check if line matches code patterns
|
|
56
|
+
for (const pattern of codePatterns) {
|
|
57
|
+
if (pattern.test(line)) {
|
|
58
|
+
codeLikeLines++;
|
|
59
|
+
break; // Count each line only once
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Consider it code if at least one line looks like code
|
|
64
|
+
return codeLikeLines > 0;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Count lines in a comment
|
|
68
|
+
* For single-line comments, the value doesn't include newlines, so we count 1
|
|
69
|
+
* For multi-line comments, we count the newlines in the value + 1
|
|
70
|
+
*/
|
|
71
|
+
function countCommentLines(comment) {
|
|
72
|
+
if (!comment)
|
|
73
|
+
return 0;
|
|
74
|
+
const newlineCount = (comment.match(/\n/g) || []).length;
|
|
75
|
+
// If there are newlines, it's a multi-line comment (newlineCount + 1 lines)
|
|
76
|
+
// If no newlines, it's a single-line comment (1 line)
|
|
77
|
+
return newlineCount > 0 ? newlineCount + 1 : 1;
|
|
78
|
+
}
|
|
79
|
+
exports.noCommentedCode = (0, eslint_devkit_2.createRule)({
|
|
80
|
+
name: 'no-commented-code',
|
|
81
|
+
meta: {
|
|
82
|
+
type: 'suggestion',
|
|
83
|
+
docs: {
|
|
84
|
+
description: 'Detects commented-out code blocks',
|
|
85
|
+
},
|
|
86
|
+
hasSuggestions: true,
|
|
87
|
+
messages: {
|
|
88
|
+
commentedCode: (0, eslint_devkit_1.formatLLMMessage)({
|
|
89
|
+
icon: eslint_devkit_1.MessageIcons.WARNING,
|
|
90
|
+
issueName: 'Commented code',
|
|
91
|
+
description: 'Commented-out code detected ({{lines}} lines)',
|
|
92
|
+
severity: 'LOW',
|
|
93
|
+
fix: 'Remove commented code or use version control for history',
|
|
94
|
+
documentationLink: 'https://rules.sonarsource.com/javascript/RSPEC-125/',
|
|
95
|
+
}),
|
|
96
|
+
removeCode: (0, eslint_devkit_1.formatLLMMessage)({
|
|
97
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
98
|
+
issueName: 'Remove Code',
|
|
99
|
+
description: 'Remove commented code block',
|
|
100
|
+
severity: 'LOW',
|
|
101
|
+
fix: 'Delete the commented code block',
|
|
102
|
+
documentationLink: 'https://rules.sonarsource.com/javascript/RSPEC-125/',
|
|
103
|
+
}),
|
|
104
|
+
useVersionControl: (0, eslint_devkit_1.formatLLMMessage)({
|
|
105
|
+
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
106
|
+
issueName: 'Use Git',
|
|
107
|
+
description: 'Use version control for code history',
|
|
108
|
+
severity: 'LOW',
|
|
109
|
+
fix: 'Delete commented code and use git history instead',
|
|
110
|
+
documentationLink: 'https://git-scm.com/docs/git-log',
|
|
111
|
+
}),
|
|
112
|
+
},
|
|
113
|
+
schema: [
|
|
114
|
+
{
|
|
115
|
+
type: 'object',
|
|
116
|
+
properties: {
|
|
117
|
+
ignoreSingleLine: {
|
|
118
|
+
type: 'boolean',
|
|
119
|
+
default: false,
|
|
120
|
+
description: 'Ignore single-line comments',
|
|
121
|
+
},
|
|
122
|
+
ignoreInTests: {
|
|
123
|
+
type: 'boolean',
|
|
124
|
+
default: true,
|
|
125
|
+
description: 'Ignore comments in test files',
|
|
126
|
+
},
|
|
127
|
+
minLines: {
|
|
128
|
+
type: 'number',
|
|
129
|
+
default: 1,
|
|
130
|
+
minimum: 1,
|
|
131
|
+
description: 'Minimum lines of commented code to trigger',
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
additionalProperties: false,
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
defaultOptions: [
|
|
139
|
+
{
|
|
140
|
+
ignoreSingleLine: false,
|
|
141
|
+
ignoreInTests: true,
|
|
142
|
+
minLines: 1,
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
create(context, [options = {}]) {
|
|
146
|
+
const { ignoreSingleLine = false, ignoreInTests = true, minLines = 1, } = options || {};
|
|
147
|
+
const filename = context.getFilename();
|
|
148
|
+
const isTestFile = ignoreInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
|
|
149
|
+
if (isTestFile) {
|
|
150
|
+
return {};
|
|
151
|
+
}
|
|
152
|
+
const sourceCode = context.sourceCode || context.sourceCode;
|
|
153
|
+
/**
|
|
154
|
+
* Check comment nodes
|
|
155
|
+
*/
|
|
156
|
+
function checkComment(node) {
|
|
157
|
+
try {
|
|
158
|
+
const commentText = node.value || '';
|
|
159
|
+
const isBlockComment = node.type === 'Block';
|
|
160
|
+
const lines = countCommentLines(commentText);
|
|
161
|
+
// Skip single-line comments if configured
|
|
162
|
+
if (ignoreSingleLine && lines === 1 && !isBlockComment) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
// Skip if below minimum lines
|
|
166
|
+
if (lines < minLines) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
// Check if it looks like code
|
|
170
|
+
if (looksLikeCode(commentText, isBlockComment)) {
|
|
171
|
+
context.report({
|
|
172
|
+
node,
|
|
173
|
+
messageId: 'commentedCode',
|
|
174
|
+
data: {
|
|
175
|
+
lines: String(lines),
|
|
176
|
+
},
|
|
177
|
+
suggest: [
|
|
178
|
+
{
|
|
179
|
+
messageId: 'removeCode',
|
|
180
|
+
fix: (fixer) => {
|
|
181
|
+
try {
|
|
182
|
+
// Remove the entire comment
|
|
183
|
+
return fixer.remove(node);
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
messageId: 'useVersionControl',
|
|
192
|
+
fix: () => null,
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Silently skip if there's an error processing the comment
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
Program() {
|
|
205
|
+
const comments = sourceCode.getAllComments();
|
|
206
|
+
// Group consecutive comments that look like code
|
|
207
|
+
const groupedComments = [];
|
|
208
|
+
let currentGroup = [];
|
|
209
|
+
for (let i = 0; i < comments.length; i++) {
|
|
210
|
+
const comment = comments[i];
|
|
211
|
+
const commentText = comment.value || '';
|
|
212
|
+
const isBlockComment = comment.type === 'Block';
|
|
213
|
+
// Check if this comment looks like code
|
|
214
|
+
if (looksLikeCode(commentText, isBlockComment)) {
|
|
215
|
+
currentGroup.push(comment);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
// If current group has comments, add it to grouped comments
|
|
219
|
+
if (currentGroup.length > 0) {
|
|
220
|
+
groupedComments.push([...currentGroup]);
|
|
221
|
+
currentGroup = [];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
// Handle any remaining group
|
|
226
|
+
if (currentGroup.length > 0) {
|
|
227
|
+
groupedComments.push(currentGroup);
|
|
228
|
+
}
|
|
229
|
+
// Process each group
|
|
230
|
+
groupedComments.forEach((group) => {
|
|
231
|
+
if (group.length === 1) {
|
|
232
|
+
// Single comment - use the standard checkComment function
|
|
233
|
+
checkComment(group[0]);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
// Multiple consecutive comments - report as one error
|
|
237
|
+
const firstComment = group[0];
|
|
238
|
+
const totalLines = group.reduce((sum, comment) => {
|
|
239
|
+
const commentText = comment.value || '';
|
|
240
|
+
return sum + countCommentLines(commentText);
|
|
241
|
+
}, 0);
|
|
242
|
+
if (totalLines >= minLines) {
|
|
243
|
+
context.report({
|
|
244
|
+
node: firstComment,
|
|
245
|
+
messageId: 'commentedCode',
|
|
246
|
+
data: {
|
|
247
|
+
lines: String(totalLines),
|
|
248
|
+
},
|
|
249
|
+
suggest: [
|
|
250
|
+
{
|
|
251
|
+
messageId: 'removeCode',
|
|
252
|
+
fix: (fixer) => {
|
|
253
|
+
try {
|
|
254
|
+
// Remove the entire range of consecutive comments
|
|
255
|
+
return fixer.removeRange([
|
|
256
|
+
group[0].range[0],
|
|
257
|
+
group[group.length - 1].range[1],
|
|
258
|
+
]);
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
messageId: 'useVersionControl',
|
|
267
|
+
fix: () => null,
|
|
268
|
+
},
|
|
269
|
+
],
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
},
|
|
275
|
+
};
|
|
276
|
+
},
|
|
277
|
+
});
|
|
278
|
+
//# sourceMappingURL=no-commented-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-commented-code.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-conventions/src/rules/conventions/no-commented-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Ofri Peretz
|
|
3
|
+
* Licensed under the MIT License. Use of this source code is governed by the
|
|
4
|
+
* MIT license that can be found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* ESLint Rule: no-console-spaces
|
|
8
|
+
* Prevent leading/trailing space between console.log parameters
|
|
9
|
+
*/
|
|
10
|
+
import type { TSESLint } from '@interlace/eslint-devkit';
|
|
11
|
+
export declare const noConsoleSpaces: TSESLint.RuleModule<"noConsoleSpaces", [], unknown, TSESLint.RuleListener> & {
|
|
12
|
+
name: string;
|
|
13
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Ofri Peretz
|
|
4
|
+
* Licensed under the MIT License. Use of this source code is governed by the
|
|
5
|
+
* MIT license that can be found in the LICENSE file.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.noConsoleSpaces = void 0;
|
|
9
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
+
const eslint_devkit_2 = require("@interlace/eslint-devkit");
|
|
11
|
+
exports.noConsoleSpaces = (0, eslint_devkit_1.createRule)({
|
|
12
|
+
name: 'no-console-spaces',
|
|
13
|
+
meta: {
|
|
14
|
+
type: 'problem',
|
|
15
|
+
docs: {
|
|
16
|
+
description: 'Prevent leading/trailing space between console.log parameters',
|
|
17
|
+
},
|
|
18
|
+
fixable: 'code',
|
|
19
|
+
hasSuggestions: true,
|
|
20
|
+
messages: {
|
|
21
|
+
noConsoleSpaces: (0, eslint_devkit_2.formatLLMMessage)({
|
|
22
|
+
icon: eslint_devkit_2.MessageIcons.WARNING,
|
|
23
|
+
issueName: 'Console Spaces',
|
|
24
|
+
description: 'Remove leading/trailing spaces in console method parameters',
|
|
25
|
+
severity: 'MEDIUM',
|
|
26
|
+
fix: 'Remove spaces from console method arguments',
|
|
27
|
+
documentationLink: 'https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-console-spaces.md',
|
|
28
|
+
}),
|
|
29
|
+
},
|
|
30
|
+
schema: [],
|
|
31
|
+
},
|
|
32
|
+
defaultOptions: [],
|
|
33
|
+
create(context) {
|
|
34
|
+
// Console methods that join parameters with spaces
|
|
35
|
+
const consoleMethods = new Set([
|
|
36
|
+
'log',
|
|
37
|
+
'debug',
|
|
38
|
+
'info',
|
|
39
|
+
'warn',
|
|
40
|
+
'error',
|
|
41
|
+
'table',
|
|
42
|
+
'trace',
|
|
43
|
+
'group',
|
|
44
|
+
'groupCollapsed',
|
|
45
|
+
]);
|
|
46
|
+
function isInAllowedContext() {
|
|
47
|
+
// For simplicity, we'll skip the allow option for now
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
function isConsoleMethodCall(node) {
|
|
51
|
+
// Check if this is a call to a console method
|
|
52
|
+
if (node.callee.type === 'MemberExpression' &&
|
|
53
|
+
node.callee.object.type === 'Identifier' &&
|
|
54
|
+
node.callee.object.name === 'console' &&
|
|
55
|
+
node.callee.property.type === 'Identifier' &&
|
|
56
|
+
consoleMethods.has(node.callee.property.name)) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
function getConsoleMethodName(node) {
|
|
62
|
+
// Safe extraction of console method name
|
|
63
|
+
if (node.callee.type === 'MemberExpression' &&
|
|
64
|
+
node.callee.property.type === 'Identifier') {
|
|
65
|
+
return node.callee.property.name;
|
|
66
|
+
}
|
|
67
|
+
return 'console';
|
|
68
|
+
}
|
|
69
|
+
function hasLeadingOrTrailingSpaces(text) {
|
|
70
|
+
// Check if string starts or ends with whitespace, but not if it's only whitespace
|
|
71
|
+
// Only flag if there's actual content with leading/trailing spaces
|
|
72
|
+
const trimmed = text.trim();
|
|
73
|
+
return trimmed.length > 0 && /^\s|\s$/.test(text);
|
|
74
|
+
}
|
|
75
|
+
function hasLeadingOrTrailingSpacesInTemplate(text) {
|
|
76
|
+
// For template literals, even whitespace-only quasis should be flagged
|
|
77
|
+
return /^\s|\s$/.test(text);
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
CallExpression(node) {
|
|
81
|
+
if (isConsoleMethodCall(node) && !isInAllowedContext()) {
|
|
82
|
+
// Check each argument for leading/trailing spaces
|
|
83
|
+
for (const arg of node.arguments) {
|
|
84
|
+
if (arg.type === 'Literal' && typeof arg.value === 'string') {
|
|
85
|
+
if (hasLeadingOrTrailingSpaces(arg.value)) {
|
|
86
|
+
context.report({
|
|
87
|
+
node: arg,
|
|
88
|
+
messageId: 'noConsoleSpaces',
|
|
89
|
+
data: {
|
|
90
|
+
method: getConsoleMethodName(node),
|
|
91
|
+
arg: arg.value,
|
|
92
|
+
},
|
|
93
|
+
fix(fixer) {
|
|
94
|
+
const trimmed = arg.value.trim();
|
|
95
|
+
return fixer.replaceText(arg, `'${trimmed}'`);
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else if (arg.type === 'TemplateLiteral') {
|
|
101
|
+
// Check template literal quasi values for leading/trailing spaces
|
|
102
|
+
let hasSpacesInTemplate = false;
|
|
103
|
+
for (const quasi of arg.quasis) {
|
|
104
|
+
if (hasLeadingOrTrailingSpacesInTemplate(quasi.value.raw)) {
|
|
105
|
+
hasSpacesInTemplate = true;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (hasSpacesInTemplate) {
|
|
110
|
+
context.report({
|
|
111
|
+
node: arg,
|
|
112
|
+
messageId: 'noConsoleSpaces',
|
|
113
|
+
data: {
|
|
114
|
+
method: getConsoleMethodName(node),
|
|
115
|
+
arg: 'template literal with spaces',
|
|
116
|
+
},
|
|
117
|
+
// Template literals are harder to fix automatically
|
|
118
|
+
fix: null,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
//# sourceMappingURL=no-console-spaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-console-spaces.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-conventions/src/rules/conventions/no-console-spaces.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Ofri Peretz
|
|
3
|
+
* Licensed under the MIT License. Use of this source code is governed by the
|
|
4
|
+
* MIT license that can be found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* ESLint Rule: prefer-code-point
|
|
8
|
+
* Prefer codePointAt over charCodeAt for proper Unicode handling
|
|
9
|
+
*/
|
|
10
|
+
import type { TSESLint } from '@interlace/eslint-devkit';
|
|
11
|
+
export declare const preferCodePoint: TSESLint.RuleModule<"preferCodePoint", [], unknown, TSESLint.RuleListener> & {
|
|
12
|
+
name: string;
|
|
13
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) 2025 Ofri Peretz
|
|
4
|
+
* Licensed under the MIT License. Use of this source code is governed by the
|
|
5
|
+
* MIT license that can be found in the LICENSE file.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.preferCodePoint = void 0;
|
|
9
|
+
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
10
|
+
const eslint_devkit_2 = require("@interlace/eslint-devkit");
|
|
11
|
+
exports.preferCodePoint = (0, eslint_devkit_1.createRule)({
|
|
12
|
+
name: 'prefer-code-point',
|
|
13
|
+
meta: {
|
|
14
|
+
type: 'suggestion',
|
|
15
|
+
docs: {
|
|
16
|
+
description: 'Prefer codePointAt over charCodeAt for proper Unicode character handling',
|
|
17
|
+
},
|
|
18
|
+
messages: {
|
|
19
|
+
preferCodePoint: (0, eslint_devkit_2.formatLLMMessage)({
|
|
20
|
+
icon: eslint_devkit_2.MessageIcons.WARNING,
|
|
21
|
+
issueName: 'Prefer codePointAt',
|
|
22
|
+
description: 'Use codePointAt instead of charCodeAt for Unicode safety',
|
|
23
|
+
severity: 'MEDIUM',
|
|
24
|
+
fix: 'Replace charCodeAt() with codePointAt()',
|
|
25
|
+
documentationLink: 'https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-code-point.md',
|
|
26
|
+
}),
|
|
27
|
+
},
|
|
28
|
+
schema: [
|
|
29
|
+
{
|
|
30
|
+
type: 'object',
|
|
31
|
+
properties: {},
|
|
32
|
+
additionalProperties: false,
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
defaultOptions: [],
|
|
37
|
+
create(context) {
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
39
|
+
function isInAllowedContext(node) {
|
|
40
|
+
// For simplicity, we'll skip the allow option for now
|
|
41
|
+
// This would require more complex logic to check comments/code context
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
function shouldIgnoreCall(node) {
|
|
45
|
+
// The unicorn rule flags ALL charCodeAt calls, but allows some contexts
|
|
46
|
+
if (node.callee.type === 'MemberExpression') {
|
|
47
|
+
// Allow optional chaining
|
|
48
|
+
if (node.callee.optional) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
// Allow computed property access where the property is a variable (not literal)
|
|
52
|
+
// This means obj[method] is ignored, but obj['charCodeAt'] is still flagged
|
|
53
|
+
if (node.callee.computed &&
|
|
54
|
+
node.callee.property.type === 'Identifier') {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
function isCharCodeAtCall(node) {
|
|
61
|
+
// Check if this is a call to charCodeAt method
|
|
62
|
+
if (node.callee.type === 'MemberExpression') {
|
|
63
|
+
// Direct property access: obj.charCodeAt
|
|
64
|
+
if (node.callee.property.type === 'Identifier' &&
|
|
65
|
+
node.callee.property.name === 'charCodeAt') {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
// Computed property access: obj['charCodeAt']
|
|
69
|
+
if (node.callee.computed &&
|
|
70
|
+
node.callee.property.type === 'Literal' &&
|
|
71
|
+
node.callee.property.value === 'charCodeAt') {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
CallExpression(node) {
|
|
79
|
+
if (isCharCodeAtCall(node) &&
|
|
80
|
+
!isInAllowedContext(node) &&
|
|
81
|
+
!shouldIgnoreCall(node)) {
|
|
82
|
+
context.report({
|
|
83
|
+
node,
|
|
84
|
+
messageId: 'preferCodePoint',
|
|
85
|
+
data: {
|
|
86
|
+
current: 'charCodeAt()',
|
|
87
|
+
fix: 'codePointAt()',
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
//# sourceMappingURL=prefer-code-point.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prefer-code-point.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-conventions/src/rules/conventions/prefer-code-point.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAOH,4DAAsD;AACtD,4DAA0E;AAM7D,QAAA,eAAe,GAAG,IAAA,0BAAU,EAA0B;IACjE,IAAI,EAAE,mBAAmB;IACzB,IAAI,EAAE;QACJ,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE;YACJ,WAAW,EACT,0EAA0E;SAC7E;QACD,QAAQ,EAAE;YACR,eAAe,EAAE,IAAA,gCAAgB,EAAC;gBAChC,IAAI,EAAE,4BAAY,CAAC,OAAO;gBAC1B,SAAS,EAAE,oBAAoB;gBAC/B,WAAW,EAAE,0DAA0D;gBACvE,QAAQ,EAAE,QAAQ;gBAClB,GAAG,EAAE,yCAAyC;gBAC9C,iBAAiB,EACf,iGAAiG;aACpG,CAAC;SACH;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE,EAAE;gBACd,oBAAoB,EAAE,KAAK;aAC5B;SACF;KACF;IACD,cAAc,EAAE,EAAE;IAElB,MAAM,CAAC,OAAsD;QAC3D,6DAA6D;QAC7D,SAAS,kBAAkB,CAAC,IAA6B;YACvD,sDAAsD;YACtD,uEAAuE;YACvE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,SAAS,gBAAgB,CAAC,IAA6B;YACrD,wEAAwE;YAExE,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBAC5C,0BAA0B;gBAC1B,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;oBACzB,OAAO,IAAI,CAAC;gBACd,CAAC;gBAED,gFAAgF;gBAChF,4EAA4E;gBAC5E,IACE,IAAI,CAAC,MAAM,CAAC,QAAQ;oBACpB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,EAC1C,CAAC;oBACD,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC;QAED,SAAS,gBAAgB,CAAC,IAA6B;YACrD,+CAA+C;YAC/C,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBAC5C,yCAAyC;gBACzC,IACE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY;oBAC1C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,EAC1C,CAAC;oBACD,OAAO,IAAI,CAAC;gBACd,CAAC;gBAED,8CAA8C;gBAC9C,IACE,IAAI,CAAC,MAAM,CAAC,QAAQ;oBACpB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS;oBACvC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,KAAK,YAAY,EAC3C,CAAC;oBACD,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO;YACL,cAAc,CAAC,IAA6B;gBAC1C,IACE,gBAAgB,CAAC,IAAI,CAAC;oBACtB,CAAC,kBAAkB,CAAC,IAAI,CAAC;oBACzB,CAAC,gBAAgB,CAAC,IAAI,CAAC,EACvB,CAAC;oBACD,OAAO,CAAC,MAAM,CAAC;wBACb,IAAI;wBACJ,SAAS,EAAE,iBAAiB;wBAC5B,IAAI,EAAE;4BACJ,OAAO,EAAE,cAAc;4BACvB,GAAG,EAAE,eAAe;yBACrB;qBACF,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Ofri Peretz
|
|
3
|
+
* Licensed under the MIT License. Use of this source code is governed by the
|
|
4
|
+
* MIT license that can be found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* prefer-dependency-version-strategy
|
|
8
|
+
*
|
|
9
|
+
* Enforces a consistent version strategy (caret, tilde, exact, etc.) for package.json dependencies.
|
|
10
|
+
* Works alongside @nx/dependency-checks to ensure both version alignment and strategy consistency.
|
|
11
|
+
*
|
|
12
|
+
* This rule is designed to complement @nx/dependency-checks, which validates that dependencies
|
|
13
|
+
* match the lockfile. This rule ensures the version specifier format is consistent.
|
|
14
|
+
*/
|
|
15
|
+
import type { TSESLint } from '@interlace/eslint-devkit';
|
|
16
|
+
type VersionStrategy = 'caret' | 'tilde' | 'exact' | 'range' | 'any';
|
|
17
|
+
export interface Options {
|
|
18
|
+
strategy?: VersionStrategy;
|
|
19
|
+
allowWorkspace?: boolean;
|
|
20
|
+
allowFile?: boolean;
|
|
21
|
+
allowLink?: boolean;
|
|
22
|
+
overrides?: Record<string, VersionStrategy>;
|
|
23
|
+
}
|
|
24
|
+
type RuleOptions = [Options?];
|
|
25
|
+
type MessageIds = 'preferStrategy' | 'invalidStrategy';
|
|
26
|
+
export declare const preferDependencyVersionStrategy: TSESLint.RuleModule<MessageIds, RuleOptions, unknown, TSESLint.RuleListener> & {
|
|
27
|
+
name: string;
|
|
28
|
+
};
|
|
29
|
+
export {};
|