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.
Files changed (35) hide show
  1. package/README.md +80 -0
  2. package/package.json +55 -0
  3. package/src/index.d.ts +198 -0
  4. package/src/index.js +60 -0
  5. package/src/index.js.map +1 -0
  6. package/src/lib/eslint-plugin-conventions.d.ts +1 -0
  7. package/src/lib/eslint-plugin-conventions.js +7 -0
  8. package/src/lib/eslint-plugin-conventions.js.map +1 -0
  9. package/src/rules/conventions/consistent-existence-index-check.d.ts +19 -0
  10. package/src/rules/conventions/consistent-existence-index-check.js +141 -0
  11. package/src/rules/conventions/consistent-existence-index-check.js.map +1 -0
  12. package/src/rules/conventions/expiring-todo-comments.d.ts +24 -0
  13. package/src/rules/conventions/expiring-todo-comments.js +307 -0
  14. package/src/rules/conventions/expiring-todo-comments.js.map +1 -0
  15. package/src/rules/conventions/filename-case.d.ts +32 -0
  16. package/src/rules/conventions/filename-case.js +264 -0
  17. package/src/rules/conventions/filename-case.js.map +1 -0
  18. package/src/rules/conventions/no-commented-code.d.ts +26 -0
  19. package/src/rules/conventions/no-commented-code.js +278 -0
  20. package/src/rules/conventions/no-commented-code.js.map +1 -0
  21. package/src/rules/conventions/no-console-spaces.d.ts +13 -0
  22. package/src/rules/conventions/no-console-spaces.js +128 -0
  23. package/src/rules/conventions/no-console-spaces.js.map +1 -0
  24. package/src/rules/conventions/prefer-code-point.d.ts +13 -0
  25. package/src/rules/conventions/prefer-code-point.js +95 -0
  26. package/src/rules/conventions/prefer-code-point.js.map +1 -0
  27. package/src/rules/conventions/prefer-dependency-version-strategy.d.ts +29 -0
  28. package/src/rules/conventions/prefer-dependency-version-strategy.js +226 -0
  29. package/src/rules/conventions/prefer-dependency-version-strategy.js.map +1 -0
  30. package/src/rules/conventions/prefer-dom-node-text-content.d.ts +13 -0
  31. package/src/rules/conventions/prefer-dom-node-text-content.js +147 -0
  32. package/src/rules/conventions/prefer-dom-node-text-content.js.map +1 -0
  33. package/src/rules/deprecation/no-deprecated-api.d.ts +30 -0
  34. package/src/rules/deprecation/no-deprecated-api.js +174 -0
  35. package/src/rules/deprecation/no-deprecated-api.js.map +1 -0
@@ -0,0 +1,307 @@
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.expiringTodoComments = void 0;
9
+ const eslint_devkit_1 = require("@interlace/eslint-devkit");
10
+ const eslint_devkit_2 = require("@interlace/eslint-devkit");
11
+ const eslint_devkit_3 = require("@interlace/eslint-devkit");
12
+ const eslint_devkit_4 = require("@interlace/eslint-devkit");
13
+ exports.expiringTodoComments = (0, eslint_devkit_1.createRule)({
14
+ name: 'expiring-todo-comments',
15
+ meta: {
16
+ type: 'problem',
17
+ docs: {
18
+ description: 'Add expiration conditions to TODO comments to prevent forgotten tasks',
19
+ },
20
+ hasSuggestions: false,
21
+ messages: {
22
+ expiringTodoComment: (0, eslint_devkit_2.formatLLMMessage)({
23
+ icon: eslint_devkit_2.MessageIcons.WARNING,
24
+ issueName: 'Expiring TODO Comment',
25
+ description: 'TODO comment has expired condition',
26
+ severity: 'HIGH',
27
+ fix: 'Address the TODO or update/remove the condition',
28
+ documentationLink: 'https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/expiring-todo-comments.md',
29
+ }),
30
+ invalidTodoCondition: (0, eslint_devkit_2.formatLLMMessage)({
31
+ icon: eslint_devkit_2.MessageIcons.WARNING,
32
+ issueName: 'Invalid TODO Condition',
33
+ description: '{{term}} TODO comment has invalid condition format',
34
+ severity: 'MEDIUM',
35
+ fix: 'Fix the condition format or remove the condition',
36
+ documentationLink: 'https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/expiring-todo-comments.md',
37
+ }),
38
+ multipleTodoConditions: (0, eslint_devkit_2.formatLLMMessage)({
39
+ icon: eslint_devkit_2.MessageIcons.WARNING,
40
+ issueName: 'Multiple TODO Conditions',
41
+ description: 'TODO comment has multiple conditions',
42
+ severity: 'MEDIUM',
43
+ fix: 'Use only one condition per TODO comment',
44
+ documentationLink: 'https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/expiring-todo-comments.md',
45
+ }),
46
+ },
47
+ schema: [
48
+ {
49
+ type: 'object',
50
+ properties: {
51
+ terms: {
52
+ type: 'array',
53
+ items: { type: 'string' },
54
+ default: ['TODO', 'FIXME', 'XXX'],
55
+ },
56
+ dateFormat: {
57
+ type: 'string',
58
+ default: 'YYYY-MM-DD',
59
+ },
60
+ },
61
+ additionalProperties: false,
62
+ },
63
+ ],
64
+ },
65
+ defaultOptions: [
66
+ { terms: ['TODO', 'FIXME', 'XXX'], dateFormat: 'YYYY-MM-DD' },
67
+ ],
68
+ create(context) {
69
+ const [options] = context.options;
70
+ const { terms = ['TODO', 'FIXME', 'XXX'] } = options || {};
71
+ // Cache package.json data
72
+ let packageJson = null;
73
+ function loadPackageJson() {
74
+ if (packageJson !== null) {
75
+ return packageJson;
76
+ }
77
+ const packageJsonPath = (0, eslint_devkit_4.resolvePath)(process.cwd(), 'package.json');
78
+ packageJson = (0, eslint_devkit_3.readJsonFileSync)(packageJsonPath);
79
+ return packageJson;
80
+ }
81
+ function parseSemver(version) {
82
+ const match = version.match(/^(\d+)\.(\d+)\.(\d+)/);
83
+ if (!match)
84
+ return null;
85
+ return {
86
+ major: parseInt(match[1], 10),
87
+ minor: parseInt(match[2], 10),
88
+ patch: parseInt(match[3], 10),
89
+ };
90
+ }
91
+ function compareVersions(version1, version2) {
92
+ const v1 = parseSemver(version1);
93
+ const v2 = parseSemver(version2);
94
+ if (!v1 || !v2)
95
+ return 0;
96
+ if (v1.major !== v2.major)
97
+ return v1.major - v2.major;
98
+ if (v1.minor !== v2.minor)
99
+ return v1.minor - v2.minor;
100
+ return v1.patch - v2.patch;
101
+ }
102
+ function checkDateCondition(dateStr) {
103
+ try {
104
+ const conditionDate = new Date(dateStr + 'T00:00:00Z'); // UTC
105
+ const now = new Date();
106
+ return now >= conditionDate;
107
+ }
108
+ catch {
109
+ return false;
110
+ }
111
+ }
112
+ function checkPackageVersionCondition(operator, targetVersion) {
113
+ const pkg = loadPackageJson();
114
+ if (!pkg?.version)
115
+ return false;
116
+ const currentVersion = pkg.version;
117
+ const comparison = compareVersions(currentVersion, targetVersion);
118
+ switch (operator) {
119
+ case '>':
120
+ return comparison > 0;
121
+ case '>=':
122
+ return comparison >= 0;
123
+ case '<':
124
+ return comparison < 0;
125
+ case '<=':
126
+ return comparison <= 0;
127
+ case '=':
128
+ case '==':
129
+ return comparison === 0;
130
+ default:
131
+ return false;
132
+ }
133
+ }
134
+ function checkEngineVersionCondition(engine, operator, targetVersion) {
135
+ if (engine !== 'node')
136
+ return false;
137
+ const pkg = loadPackageJson();
138
+ const nodeVersion = pkg?.engines?.node;
139
+ if (!nodeVersion)
140
+ return false;
141
+ // Simple version comparison for engines
142
+ const currentVersion = nodeVersion.replace(/^[\^~>=<]+/, '');
143
+ const comparison = compareVersions(currentVersion, targetVersion);
144
+ switch (operator) {
145
+ case '>':
146
+ return comparison > 0;
147
+ case '>=':
148
+ return comparison >= 0;
149
+ case '<':
150
+ return comparison < 0;
151
+ case '<=':
152
+ return comparison <= 0;
153
+ default:
154
+ return false;
155
+ }
156
+ }
157
+ function checkDependencyCondition(packageName, present) {
158
+ const pkg = loadPackageJson();
159
+ if (!pkg)
160
+ return false;
161
+ const allDeps = {
162
+ ...pkg.dependencies,
163
+ ...pkg.devDependencies,
164
+ ...pkg.peerDependencies,
165
+ };
166
+ const hasPackage = packageName in allDeps;
167
+ return present ? hasPackage : hasPackage;
168
+ }
169
+ function parseTodoCondition(commentValue, term) {
170
+ // Match patterns like: TODO [condition]: message
171
+ // or TODO (@author) [condition]: message
172
+ // Also handle block comments with * prefix: * TODO [condition]: message
173
+ const todoRegex = new RegExp(`\\*?\\s*${term}\\s*(?:\\([^)]+\\))?\\s*\\[([^\\]]+)\\]\\s*:\\s*(.+)$`, 'im');
174
+ const match = commentValue.match(todoRegex);
175
+ if (!match)
176
+ return null;
177
+ const conditionStr = match[1];
178
+ const rest = match[2];
179
+ // Split multiple conditions (shouldn't happen, but handle gracefully)
180
+ const conditions = conditionStr.split(/\s*,\s*/);
181
+ return { conditions, rest };
182
+ }
183
+ function validateCondition(condition) {
184
+ // Date condition: YYYY-MM-DD
185
+ if (/^\d{4}-\d{2}-\d{2}$/.test(condition)) {
186
+ return { type: 'date', value: condition };
187
+ }
188
+ // Package version condition: >=1.0.0, >2.0.0, etc.
189
+ const packageVersionMatch = condition.match(/^([><]=?|=|==)\s*([\d.]+)$/);
190
+ if (packageVersionMatch) {
191
+ return {
192
+ type: 'package-version',
193
+ operator: packageVersionMatch[1],
194
+ value: packageVersionMatch[2],
195
+ };
196
+ }
197
+ // Engine version condition: engine:node@>=8, engine:node@>20.0.0
198
+ const engineVersionMatch = condition.match(/^engine:(\w+)@([><]=?)\s*([\d.]+)$/);
199
+ if (engineVersionMatch) {
200
+ const engine = engineVersionMatch[1];
201
+ // Validate engine name
202
+ if (!['node', 'npm', 'yarn', 'pnpm'].includes(engine)) {
203
+ return null; // Invalid engine, let it be caught as invalid condition
204
+ }
205
+ return {
206
+ type: 'engine-version',
207
+ value: `${engine}@${engineVersionMatch[3]}`,
208
+ operator: engineVersionMatch[2],
209
+ };
210
+ }
211
+ // Dependency condition: +package-name or -package-name
212
+ const depMatch = condition.match(/^([+-])(.+)$/);
213
+ if (depMatch) {
214
+ return {
215
+ type: 'dependency',
216
+ value: depMatch[2],
217
+ operator: depMatch[1],
218
+ };
219
+ }
220
+ return null;
221
+ }
222
+ function checkCondition(condition) {
223
+ const parsed = validateCondition(condition);
224
+ if (!parsed)
225
+ return false;
226
+ switch (parsed.type) {
227
+ case 'date':
228
+ return checkDateCondition(parsed.value);
229
+ case 'package-version':
230
+ return parsed.operator
231
+ ? checkPackageVersionCondition(parsed.operator, parsed.value)
232
+ : false;
233
+ case 'engine-version': {
234
+ const [engine, version] = parsed.value.split('@');
235
+ return parsed.operator
236
+ ? checkEngineVersionCondition(engine, parsed.operator, version)
237
+ : false;
238
+ }
239
+ case 'dependency':
240
+ return checkDependencyCondition(parsed.value, parsed.operator === '+');
241
+ default:
242
+ return false;
243
+ }
244
+ }
245
+ function checkComment(comment) {
246
+ const commentValue = comment.value;
247
+ for (const term of terms) {
248
+ const parsed = parseTodoCondition(commentValue, term);
249
+ if (!parsed)
250
+ continue;
251
+ const { conditions, rest } = parsed;
252
+ // Check for multiple conditions
253
+ if (conditions.length > 1) {
254
+ context.report({
255
+ loc: comment.loc,
256
+ messageId: 'multipleTodoConditions',
257
+ data: {
258
+ term,
259
+ conditions: conditions.join(', '),
260
+ },
261
+ });
262
+ continue;
263
+ }
264
+ const condition = conditions[0];
265
+ // Validate condition format
266
+ const parsedCondition = validateCondition(condition);
267
+ if (!parsedCondition) {
268
+ context.report({
269
+ loc: comment.loc,
270
+ messageId: 'invalidTodoCondition',
271
+ data: {
272
+ condition,
273
+ term,
274
+ },
275
+ });
276
+ continue;
277
+ }
278
+ // Check if condition has expired
279
+ if (checkCondition(condition)) {
280
+ context.report({
281
+ loc: comment.loc,
282
+ messageId: 'expiringTodoComment',
283
+ data: {
284
+ term,
285
+ condition,
286
+ message: rest,
287
+ },
288
+ });
289
+ }
290
+ // Only process one term per comment
291
+ break;
292
+ }
293
+ }
294
+ return {
295
+ Program() {
296
+ const sourceCode = context.sourceCode;
297
+ const comments = sourceCode.getAllComments();
298
+ for (const comment of comments) {
299
+ if (comment.type === 'Line' || comment.type === 'Block') {
300
+ checkComment(comment);
301
+ }
302
+ }
303
+ },
304
+ };
305
+ },
306
+ });
307
+ //# sourceMappingURL=expiring-todo-comments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expiring-todo-comments.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-conventions/src/rules/conventions/expiring-todo-comments.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAOH,4DAAsD;AACtD,4DAA0E;AAC1E,4DAA4D;AAC5D,4DAAuD;AA4B1C,QAAA,oBAAoB,GAAG,IAAA,0BAAU,EAA0B;IACtE,IAAI,EAAE,wBAAwB;IAC9B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,IAAI,EAAE;YACJ,WAAW,EACT,uEAAuE;SAC1E;QACD,cAAc,EAAE,KAAK;QACrB,QAAQ,EAAE;YACR,mBAAmB,EAAE,IAAA,gCAAgB,EAAC;gBACpC,IAAI,EAAE,4BAAY,CAAC,OAAO;gBAC1B,SAAS,EAAE,uBAAuB;gBAClC,WAAW,EAAE,oCAAoC;gBACjD,QAAQ,EAAE,MAAM;gBAChB,GAAG,EAAE,iDAAiD;gBACtD,iBAAiB,EACf,sGAAsG;aACzG,CAAC;YACF,oBAAoB,EAAE,IAAA,gCAAgB,EAAC;gBACrC,IAAI,EAAE,4BAAY,CAAC,OAAO;gBAC1B,SAAS,EAAE,wBAAwB;gBACnC,WAAW,EAAE,oDAAoD;gBACjE,QAAQ,EAAE,QAAQ;gBAClB,GAAG,EAAE,kDAAkD;gBACvD,iBAAiB,EACf,sGAAsG;aACzG,CAAC;YACF,sBAAsB,EAAE,IAAA,gCAAgB,EAAC;gBACvC,IAAI,EAAE,4BAAY,CAAC,OAAO;gBAC1B,SAAS,EAAE,0BAA0B;gBACrC,WAAW,EAAE,sCAAsC;gBACnD,QAAQ,EAAE,QAAQ;gBAClB,GAAG,EAAE,yCAAyC;gBAC9C,iBAAiB,EACf,sGAAsG;aACzG,CAAC;SACH;QACD,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,QAAQ;gBACd,UAAU,EAAE;oBACV,KAAK,EAAE;wBACL,IAAI,EAAE,OAAO;wBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC;qBAClC;oBACD,UAAU,EAAE;wBACV,IAAI,EAAE,QAAQ;wBACd,OAAO,EAAE,YAAY;qBACtB;iBACF;gBACD,oBAAoB,EAAE,KAAK;aAC5B;SACF;KACF;IACD,cAAc,EAAE;QACd,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE;KAC9D;IAED,MAAM,CAAC,OAAsD;QAC3D,MAAM,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;QAClC,MAAM,EAAE,KAAK,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;QAE3D,0BAA0B;QAC1B,IAAI,WAAW,GAAuB,IAAI,CAAC;QAE3C,SAAS,eAAe;YACtB,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;gBACzB,OAAO,WAAW,CAAC;YACrB,CAAC;YAED,MAAM,eAAe,GAAG,IAAA,2BAAW,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,CAAC,CAAC;YACnE,WAAW,GAAG,IAAA,gCAAgB,EAAc,eAAe,CAAC,CAAC;YAC7D,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,SAAS,WAAW,CAClB,OAAe;YAEf,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;YACpD,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAC;YAExB,OAAO;gBACL,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC7B,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBAC7B,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;aAC9B,CAAC;QACJ,CAAC;QAED,SAAS,eAAe,CAAC,QAAgB,EAAE,QAAgB;YACzD,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;YACjC,MAAM,EAAE,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;YAEjC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE;gBAAE,OAAO,CAAC,CAAC;YAEzB,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK;gBAAE,OAAO,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC;YACtD,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,KAAK;gBAAE,OAAO,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC;YACtD,OAAO,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC;QAC7B,CAAC;QAED,SAAS,kBAAkB,CAAC,OAAe;YACzC,IAAI,CAAC;gBACH,MAAM,aAAa,GAAG,IAAI,IAAI,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM;gBAC9D,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,OAAO,GAAG,IAAI,aAAa,CAAC;YAC9B,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,SAAS,4BAA4B,CACnC,QAAgB,EAChB,aAAqB;YAErB,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,EAAE,OAAO;gBAAE,OAAO,KAAK,CAAC;YAEhC,MAAM,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC;YACnC,MAAM,UAAU,GAAG,eAAe,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;YAElE,QAAQ,QAAQ,EAAE,CAAC;gBACjB,KAAK,GAAG;oBACN,OAAO,UAAU,GAAG,CAAC,CAAC;gBACxB,KAAK,IAAI;oBACP,OAAO,UAAU,IAAI,CAAC,CAAC;gBACzB,KAAK,GAAG;oBACN,OAAO,UAAU,GAAG,CAAC,CAAC;gBACxB,KAAK,IAAI;oBACP,OAAO,UAAU,IAAI,CAAC,CAAC;gBACzB,KAAK,GAAG,CAAC;gBACT,KAAK,IAAI;oBACP,OAAO,UAAU,KAAK,CAAC,CAAC;gBAC1B;oBACE,OAAO,KAAK,CAAC;YACjB,CAAC;QACH,CAAC;QAED,SAAS,2BAA2B,CAClC,MAAc,EACd,QAAgB,EAChB,aAAqB;YAErB,IAAI,MAAM,KAAK,MAAM;gBAAE,OAAO,KAAK,CAAC;YAEpC,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;YAC9B,MAAM,WAAW,GAAG,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC;YACvC,IAAI,CAAC,WAAW;gBAAE,OAAO,KAAK,CAAC;YAE/B,wCAAwC;YACxC,MAAM,cAAc,GAAG,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;YAC7D,MAAM,UAAU,GAAG,eAAe,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;YAElE,QAAQ,QAAQ,EAAE,CAAC;gBACjB,KAAK,GAAG;oBACN,OAAO,UAAU,GAAG,CAAC,CAAC;gBACxB,KAAK,IAAI;oBACP,OAAO,UAAU,IAAI,CAAC,CAAC;gBACzB,KAAK,GAAG;oBACN,OAAO,UAAU,GAAG,CAAC,CAAC;gBACxB,KAAK,IAAI;oBACP,OAAO,UAAU,IAAI,CAAC,CAAC;gBACzB;oBACE,OAAO,KAAK,CAAC;YACjB,CAAC;QACH,CAAC;QAED,SAAS,wBAAwB,CAC/B,WAAmB,EACnB,OAAgB;YAEhB,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG;gBAAE,OAAO,KAAK,CAAC;YAEvB,MAAM,OAAO,GAAG;gBACd,GAAG,GAAG,CAAC,YAAY;gBACnB,GAAG,GAAG,CAAC,eAAe;gBACtB,GAAG,GAAG,CAAC,gBAAgB;aACxB,CAAC;YAEF,MAAM,UAAU,GAAG,WAAW,IAAI,OAAO,CAAC;YAC1C,OAAO,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;QAC3C,CAAC;QAED,SAAS,kBAAkB,CACzB,YAAoB,EACpB,IAAY;YAEZ,iDAAiD;YACjD,yCAAyC;YACzC,wEAAwE;YACxE,MAAM,SAAS,GAAG,IAAI,MAAM,CAC1B,WAAW,IAAI,uDAAuD,EACtE,IAAI,CACL,CAAC;YACF,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAE5C,IAAI,CAAC,KAAK;gBAAE,OAAO,IAAI,CAAC;YAExB,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAEtB,sEAAsE;YACtE,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAEjD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;QAC9B,CAAC;QAED,SAAS,iBAAiB,CACxB,SAAiB;YAEjB,6BAA6B;YAC7B,IAAI,qBAAqB,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;YAC5C,CAAC;YAED,mDAAmD;YACnD,MAAM,mBAAmB,GAAG,SAAS,CAAC,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAC1E,IAAI,mBAAmB,EAAE,CAAC;gBACxB,OAAO;oBACL,IAAI,EAAE,iBAAiB;oBACvB,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC;oBAChC,KAAK,EAAE,mBAAmB,CAAC,CAAC,CAAC;iBAC9B,CAAC;YACJ,CAAC;YAED,iEAAiE;YACjE,MAAM,kBAAkB,GAAG,SAAS,CAAC,KAAK,CACxC,oCAAoC,CACrC,CAAC;YACF,IAAI,kBAAkB,EAAE,CAAC;gBACvB,MAAM,MAAM,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAAC;gBACrC,uBAAuB;gBACvB,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;oBACtD,OAAO,IAAI,CAAC,CAAC,wDAAwD;gBACvE,CAAC;gBACD,OAAO;oBACL,IAAI,EAAE,gBAAgB;oBACtB,KAAK,EAAE,GAAG,MAAM,IAAI,kBAAkB,CAAC,CAAC,CAAC,EAAE;oBAC3C,QAAQ,EAAE,kBAAkB,CAAC,CAAC,CAAC;iBAChC,CAAC;YACJ,CAAC;YAED,uDAAuD;YACvD,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACjD,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO;oBACL,IAAI,EAAE,YAAY;oBAClB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;oBAClB,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;iBACtB,CAAC;YACJ,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAED,SAAS,cAAc,CAAC,SAAiB;YACvC,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;YAC5C,IAAI,CAAC,MAAM;gBAAE,OAAO,KAAK,CAAC;YAE1B,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;gBACpB,KAAK,MAAM;oBACT,OAAO,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC1C,KAAK,iBAAiB;oBACpB,OAAO,MAAM,CAAC,QAAQ;wBACpB,CAAC,CAAC,4BAA4B,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC;wBAC7D,CAAC,CAAC,KAAK,CAAC;gBACZ,KAAK,gBAAgB,CAAC,CAAC,CAAC;oBACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBAClD,OAAO,MAAM,CAAC,QAAQ;wBACpB,CAAC,CAAC,2BAA2B,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC;wBAC/D,CAAC,CAAC,KAAK,CAAC;gBACZ,CAAC;gBACD,KAAK,YAAY;oBACf,OAAO,wBAAwB,CAC7B,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,QAAQ,KAAK,GAAG,CACxB,CAAC;gBACJ;oBACE,OAAO,KAAK,CAAC;YACjB,CAAC;QACH,CAAC;QAED,SAAS,YAAY,CAAC,OAAyB;YAC7C,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC;YAEnC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;gBACtD,IAAI,CAAC,MAAM;oBAAE,SAAS;gBAEtB,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;gBAEpC,gCAAgC;gBAChC,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,OAAO,CAAC,MAAM,CAAC;wBACb,GAAG,EAAE,OAAO,CAAC,GAAG;wBAChB,SAAS,EAAE,wBAAwB;wBACnC,IAAI,EAAE;4BACJ,IAAI;4BACJ,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;yBAClC;qBACF,CAAC,CAAC;oBACH,SAAS;gBACX,CAAC;gBAED,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;gBAEhC,4BAA4B;gBAC5B,MAAM,eAAe,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;gBACrD,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,OAAO,CAAC,MAAM,CAAC;wBACb,GAAG,EAAE,OAAO,CAAC,GAAG;wBAChB,SAAS,EAAE,sBAAsB;wBACjC,IAAI,EAAE;4BACJ,SAAS;4BACT,IAAI;yBACL;qBACF,CAAC,CAAC;oBACH,SAAS;gBACX,CAAC;gBAED,iCAAiC;gBACjC,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC9B,OAAO,CAAC,MAAM,CAAC;wBACb,GAAG,EAAE,OAAO,CAAC,GAAG;wBAChB,SAAS,EAAE,qBAAqB;wBAChC,IAAI,EAAE;4BACJ,IAAI;4BACJ,SAAS;4BACT,OAAO,EAAE,IAAI;yBACd;qBACF,CAAC,CAAC;gBACL,CAAC;gBAED,oCAAoC;gBACpC,MAAM;YACR,CAAC;QACH,CAAC;QAED,OAAO;YACL,OAAO;gBACL,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;gBACtC,MAAM,QAAQ,GAAG,UAAU,CAAC,cAAc,EAAE,CAAC;gBAE7C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;wBACxD,YAAY,CAAC,OAAO,CAAC,CAAC;oBACxB,CAAC;gBACH,CAAC;YACH,CAAC;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,32 @@
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: filename-case
8
+ * Enforce filename case conventions
9
+ */
10
+ import type { TSESLint } from '@interlace/eslint-devkit';
11
+ export type CaseType = 'camelCase' | 'kebabCase' | 'pascalCase' | 'snakeCase';
12
+ export interface Options {
13
+ /** Case convention to enforce */
14
+ case?: CaseType;
15
+ /** List of patterns to ignore completely */
16
+ ignore?: (string | RegExp)[];
17
+ /** List of uppercase filenames to allow (without extension). Set to empty array to disable. */
18
+ allowedUppercaseFiles?: string[];
19
+ /** List of filenames allowed to use kebab-case regardless of the global case setting */
20
+ allowedKebabCase?: string[];
21
+ /** List of filenames allowed to use snake_case regardless of the global case setting */
22
+ allowedSnakeCase?: string[];
23
+ /** List of filenames allowed to use camelCase regardless of the global case setting */
24
+ allowedCamelCase?: string[];
25
+ /** List of filenames allowed to use PascalCase regardless of the global case setting */
26
+ allowedPascalCase?: string[];
27
+ }
28
+ type RuleOptions = [Options?];
29
+ export declare const filenameCase: TSESLint.RuleModule<"filenameCase", RuleOptions, unknown, TSESLint.RuleListener> & {
30
+ name: string;
31
+ };
32
+ export {};
@@ -0,0 +1,264 @@
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.filenameCase = void 0;
9
+ const eslint_devkit_1 = require("@interlace/eslint-devkit");
10
+ const eslint_devkit_2 = require("@interlace/eslint-devkit");
11
+ const eslint_devkit_3 = require("@interlace/eslint-devkit");
12
+ /**
13
+ * Default uppercase filenames that are conventionally valid across all case conventions
14
+ */
15
+ const DEFAULT_ALLOWED_UPPERCASE_FILES = [
16
+ 'README',
17
+ 'LICENSE',
18
+ 'CHANGELOG',
19
+ 'CONTRIBUTING',
20
+ 'AUTHORS',
21
+ 'COPYING',
22
+ 'SECURITY',
23
+ 'NOTICE',
24
+ 'PATENTS',
25
+ 'VERSION',
26
+ ];
27
+ exports.filenameCase = (0, eslint_devkit_1.createRule)({
28
+ name: 'filename-case',
29
+ meta: {
30
+ type: 'problem',
31
+ docs: {
32
+ description: 'Enforce filename case conventions for consistency',
33
+ },
34
+ hasSuggestions: true,
35
+ messages: {
36
+ filenameCase: (0, eslint_devkit_2.formatLLMMessage)({
37
+ icon: eslint_devkit_2.MessageIcons.WARNING,
38
+ issueName: 'Filename Case Convention',
39
+ description: 'Filename "{{current}}" violates {{case}} naming convention',
40
+ severity: 'MEDIUM',
41
+ fix: 'Rename file from "{{current}}" to "{{suggested}}" following {{case}} convention',
42
+ documentationLink: 'https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/filename-case.md',
43
+ }),
44
+ },
45
+ schema: [
46
+ {
47
+ type: 'object',
48
+ properties: {
49
+ case: {
50
+ type: 'string',
51
+ enum: ['camelCase', 'kebabCase', 'pascalCase', 'snakeCase'],
52
+ default: 'kebabCase',
53
+ },
54
+ ignore: {
55
+ type: 'array',
56
+ items: {
57
+ anyOf: [
58
+ { type: 'string' },
59
+ { type: 'object' },
60
+ ],
61
+ },
62
+ default: [],
63
+ },
64
+ allowedUppercaseFiles: {
65
+ type: 'array',
66
+ items: { type: 'string' },
67
+ description: 'List of uppercase filenames to allow (without extension). Defaults to common files like README, LICENSE, etc.',
68
+ },
69
+ allowedKebabCase: {
70
+ type: 'array',
71
+ items: { type: 'string' },
72
+ description: 'List of filenames allowed to use kebab-case regardless of the global case setting.',
73
+ default: [],
74
+ },
75
+ allowedSnakeCase: {
76
+ type: 'array',
77
+ items: { type: 'string' },
78
+ description: 'List of filenames allowed to use snake_case regardless of the global case setting.',
79
+ default: [],
80
+ },
81
+ allowedCamelCase: {
82
+ type: 'array',
83
+ items: { type: 'string' },
84
+ description: 'List of filenames allowed to use camelCase regardless of the global case setting.',
85
+ default: [],
86
+ },
87
+ allowedPascalCase: {
88
+ type: 'array',
89
+ items: { type: 'string' },
90
+ description: 'List of filenames allowed to use PascalCase regardless of the global case setting.',
91
+ default: [],
92
+ },
93
+ },
94
+ additionalProperties: false,
95
+ },
96
+ ],
97
+ },
98
+ defaultOptions: [{
99
+ case: 'kebabCase',
100
+ ignore: [],
101
+ allowedUppercaseFiles: DEFAULT_ALLOWED_UPPERCASE_FILES,
102
+ allowedKebabCase: [],
103
+ allowedSnakeCase: [],
104
+ allowedCamelCase: [],
105
+ allowedPascalCase: [],
106
+ }],
107
+ create(context) {
108
+ const [options] = context.options;
109
+ const { case: caseType = 'kebabCase', ignore = [], allowedUppercaseFiles = DEFAULT_ALLOWED_UPPERCASE_FILES, allowedKebabCase = [], allowedSnakeCase = [], allowedCamelCase = [], allowedPascalCase = [], } = options || {};
110
+ // Convert to different case formats
111
+ function toCamelCase(str) {
112
+ return str.replace(/[-_](.)/g, (_, letter) => letter.toUpperCase());
113
+ }
114
+ function toKebabCase(str) {
115
+ return str
116
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
117
+ .replace(/[\s_]+/g, '-')
118
+ .toLowerCase();
119
+ }
120
+ function toPascalCase(str) {
121
+ const camel = toCamelCase(str);
122
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
123
+ }
124
+ function toSnakeCase(str) {
125
+ return str
126
+ .replace(/([a-z])([A-Z])/g, '$1_$2')
127
+ .replace(/[\s-]+/g, '_')
128
+ .toLowerCase();
129
+ }
130
+ // Check if filename matches the expected case pattern
131
+ function isCamelCase(str) {
132
+ // camelCase: starts with lowercase, no separators, can have uppercase after first char
133
+ return /^[a-z][a-zA-Z0-9]*$/.test(str);
134
+ }
135
+ function isKebabCase(str) {
136
+ // kebab-case: all lowercase with hyphens as separators
137
+ return /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/.test(str);
138
+ }
139
+ function isPascalCase(str) {
140
+ // PascalCase: starts with uppercase, no separators
141
+ return /^[A-Z][a-zA-Z0-9]*$/.test(str);
142
+ }
143
+ function isSnakeCase(str) {
144
+ // snake_case: all lowercase with underscores as separators
145
+ return /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/.test(str);
146
+ }
147
+ function matchesCase(str, expectedCase) {
148
+ switch (expectedCase) {
149
+ case 'camelCase':
150
+ return isCamelCase(str);
151
+ case 'kebabCase':
152
+ return isKebabCase(str);
153
+ case 'pascalCase':
154
+ return isPascalCase(str);
155
+ case 'snakeCase':
156
+ return isSnakeCase(str);
157
+ default:
158
+ return true;
159
+ }
160
+ }
161
+ // Generate suggested filename
162
+ function getSuggestedName(basename, nameWithoutExt, targetCase) {
163
+ let transformed;
164
+ switch (targetCase) {
165
+ case 'camelCase':
166
+ transformed = toCamelCase(nameWithoutExt);
167
+ break;
168
+ case 'kebabCase':
169
+ transformed = toKebabCase(nameWithoutExt);
170
+ break;
171
+ case 'pascalCase':
172
+ transformed = toPascalCase(nameWithoutExt);
173
+ break;
174
+ case 'snakeCase':
175
+ transformed = toSnakeCase(nameWithoutExt);
176
+ break;
177
+ default:
178
+ transformed = nameWithoutExt;
179
+ }
180
+ // Add back the extension
181
+ const ext = basename.slice(nameWithoutExt.length);
182
+ return transformed + ext;
183
+ }
184
+ return {
185
+ Program(node) {
186
+ // Get filename from context
187
+ const filename = context.getFilename();
188
+ if (!filename) {
189
+ return;
190
+ }
191
+ // Get just the filename part (without directory)
192
+ const basename = (0, eslint_devkit_3.getBasename)(filename);
193
+ // Remove all extensions for checking (handles .spec.ts, .test.tsx, etc.)
194
+ const nameWithoutExt = basename.replace(/(\.(spec|test|stories|story|e2e|d))*\.[^.]+$/, '');
195
+ // Skip if no name part (e.g., just extension or dotfile)
196
+ if (!nameWithoutExt) {
197
+ return;
198
+ }
199
+ // Check if filename should be ignored
200
+ for (const ignorePattern of ignore) {
201
+ if (typeof ignorePattern === 'string') {
202
+ if (basename === ignorePattern) {
203
+ return;
204
+ }
205
+ }
206
+ else if (ignorePattern instanceof RegExp) {
207
+ if (ignorePattern.test(basename)) {
208
+ return;
209
+ }
210
+ }
211
+ }
212
+ // Skip allowed uppercase files (README, LICENSE, etc.) as they are conventionally valid
213
+ if (allowedUppercaseFiles.includes(nameWithoutExt)) {
214
+ return;
215
+ }
216
+ // Skip dotfiles (.eslintrc, .gitignore, etc.)
217
+ if (basename.startsWith('.')) {
218
+ return;
219
+ }
220
+ // Check if filename is allowed via case-specific overrides
221
+ // These allow specific files to use a different case than the global setting
222
+ if (allowedKebabCase.includes(nameWithoutExt) && matchesCase(nameWithoutExt, 'kebabCase')) {
223
+ return;
224
+ }
225
+ if (allowedSnakeCase.includes(nameWithoutExt) && matchesCase(nameWithoutExt, 'snakeCase')) {
226
+ return;
227
+ }
228
+ if (allowedCamelCase.includes(nameWithoutExt) && matchesCase(nameWithoutExt, 'camelCase')) {
229
+ return;
230
+ }
231
+ if (allowedPascalCase.includes(nameWithoutExt) && matchesCase(nameWithoutExt, 'pascalCase')) {
232
+ return;
233
+ }
234
+ // Check if filename matches the expected case
235
+ if (!matchesCase(nameWithoutExt, caseType)) {
236
+ const suggestedName = getSuggestedName(basename, nameWithoutExt, caseType);
237
+ context.report({
238
+ node, // Report on the Program node
239
+ messageId: 'filenameCase',
240
+ data: {
241
+ case: caseType,
242
+ current: basename,
243
+ suggested: suggestedName,
244
+ },
245
+ suggest: [
246
+ {
247
+ messageId: 'filenameCase',
248
+ data: {
249
+ suggestedName,
250
+ },
251
+ fix() {
252
+ // This is a file rename operation that can't be auto-fixed
253
+ // Just provide the suggestion
254
+ return null;
255
+ },
256
+ },
257
+ ],
258
+ });
259
+ }
260
+ },
261
+ };
262
+ },
263
+ });
264
+ //# sourceMappingURL=filename-case.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filename-case.js","sourceRoot":"","sources":["../../../../../../packages/eslint-plugin-conventions/src/rules/conventions/filename-case.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
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-commented-code
8
+ * Detects commented-out code blocks
9
+ *
10
+ * @see https://rules.sonarsource.com/javascript/RSPEC-125/
11
+ */
12
+ import type { TSESLint } from '@interlace/eslint-devkit';
13
+ type MessageIds = 'commentedCode' | 'removeCode' | 'useVersionControl';
14
+ export interface Options {
15
+ /** Ignore single-line comments. Default: false */
16
+ ignoreSingleLine?: boolean;
17
+ /** Ignore comments in test files. Default: true */
18
+ ignoreInTests?: boolean;
19
+ /** Minimum lines of commented code to trigger. Default: 1 */
20
+ minLines?: number;
21
+ }
22
+ type RuleOptions = [Options?];
23
+ export declare const noCommentedCode: TSESLint.RuleModule<MessageIds, RuleOptions, unknown, TSESLint.RuleListener> & {
24
+ name: string;
25
+ };
26
+ export {};