@siberiacancode/eslint 2.16.4 → 2.16.6

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.
@@ -36,10 +36,6 @@ let eslint_plugin_jsx_a11y = require("eslint-plugin-jsx-a11y");
36
36
  eslint_plugin_jsx_a11y = __toESM(eslint_plugin_jsx_a11y);
37
37
  let eslint_plugin_playwright = require("eslint-plugin-playwright");
38
38
  eslint_plugin_playwright = __toESM(eslint_plugin_playwright);
39
- let node_fs = require("node:fs");
40
- node_fs = __toESM(node_fs);
41
- let node_path = require("node:path");
42
- node_path = __toESM(node_path);
43
39
 
44
40
  //#region src/plugin/rules/function-component-definition.ts
45
41
  const NAMED_TEMPLATES = {
@@ -252,131 +248,6 @@ const functionComponentDefinition = {
252
248
  }
253
249
  };
254
250
 
255
- //#endregion
256
- //#region src/plugin/rules/no-unused-class.ts
257
- const STYLE_IMPORT_REGEXP = /\.(?:css|scss|less)$/u;
258
- const toCamelCase = (value) => value.replace(/-([a-z])/gu, (_substring, letter) => letter.toUpperCase());
259
- const extractClassNames = (source) => {
260
- const classNames = /* @__PURE__ */ new Set();
261
- const classNameRegExp = /\.([_a-zA-Z][\w-]*)/gu;
262
- let match = classNameRegExp.exec(source);
263
- while (match !== null) {
264
- const className = match[1];
265
- if (className !== void 0 && className !== "") classNames.add(className);
266
- match = classNameRegExp.exec(source);
267
- }
268
- return [...classNames];
269
- };
270
- const buildClassesMap = (classNames, camelCaseOption) => {
271
- const onlyCamelCase = camelCaseOption === "only" || camelCaseOption === "dashes-only";
272
- const withCamelCase = camelCaseOption === true || camelCaseOption === "dashes" || onlyCamelCase;
273
- const classesMap = {};
274
- classNames.forEach((className) => {
275
- if (!onlyCamelCase) classesMap[className] = className;
276
- if (withCamelCase) classesMap[toCamelCase(className)] = className;
277
- });
278
- return classesMap;
279
- };
280
- const getStyleImportData = (node) => {
281
- if (node.source.type !== "Literal" || typeof node.source.value !== "string") return void 0;
282
- const source = node.source.value;
283
- if (!STYLE_IMPORT_REGEXP.test(source)) return void 0;
284
- const importSpecifier = node.specifiers.find((specifier) => specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportNamespaceSpecifier");
285
- if (importSpecifier === void 0) return void 0;
286
- return {
287
- importName: importSpecifier.local.name,
288
- importNode: importSpecifier,
289
- styleFilePath: source
290
- };
291
- };
292
- const getPropertyName = (node, camelCaseOption) => {
293
- if (node.computed === false && node.property.type === "Identifier") return node.property.name;
294
- if (node.computed === true && node.property.type === "Literal") {
295
- if (typeof node.property.value !== "string" || node.property.value === "") return void 0;
296
- return camelCaseOption === "only" ? toCamelCase(node.property.value) : node.property.value;
297
- }
298
- if (node.computed === true && node.property.type === "TemplateLiteral" && node.property.expressions.length === 0) {
299
- const value = node.property.quasis[0]?.value.cooked;
300
- if (typeof value !== "string" || value === "") return void 0;
301
- return camelCaseOption === "only" ? toCamelCase(value) : value;
302
- }
303
- };
304
- const getAbsoluteStylePath = (context, styleFilePath) => {
305
- const filename = context.filename;
306
- if (filename === "<input>") return void 0;
307
- return node_path.default.resolve(node_path.default.dirname(filename), styleFilePath);
308
- };
309
- const noUnusedClass = {
310
- meta: {
311
- type: "problem",
312
- docs: { description: "Checks that all CSS/SCSS/LESS classes imported as modules are used" },
313
- schema: [{
314
- type: "object",
315
- properties: {
316
- camelCase: { enum: [
317
- true,
318
- "dashes",
319
- "only",
320
- "dashes-only"
321
- ] },
322
- markAsUsed: {
323
- type: "array",
324
- items: { type: "string" }
325
- }
326
- },
327
- additionalProperties: false
328
- }]
329
- },
330
- create(context) {
331
- const options = context.options[0] ?? {};
332
- const camelCaseOption = options.camelCase;
333
- const markAsUsed = options.markAsUsed ?? [];
334
- const importMap = {};
335
- return {
336
- ImportDeclaration(node) {
337
- const styleImportData = getStyleImportData(node);
338
- if (styleImportData === void 0) return;
339
- const absoluteStylePath = getAbsoluteStylePath(context, styleImportData.styleFilePath);
340
- if (absoluteStylePath === void 0 || !node_fs.default.existsSync(absoluteStylePath)) return;
341
- const classNames = extractClassNames(node_fs.default.readFileSync(absoluteStylePath, "utf8"));
342
- const classes = {};
343
- classNames.forEach((className) => {
344
- classes[className] = false;
345
- });
346
- importMap[styleImportData.importName] = {
347
- classes,
348
- classesMap: buildClassesMap(classNames, camelCaseOption),
349
- filePath: styleImportData.styleFilePath,
350
- node: styleImportData.importNode
351
- };
352
- },
353
- MemberExpression(node) {
354
- const typedNode = node;
355
- if (typedNode.object.type !== "Identifier") return;
356
- const entry = importMap[typedNode.object.name];
357
- if (entry === void 0) return;
358
- const propertyName = getPropertyName(typedNode, camelCaseOption);
359
- if (propertyName === void 0 || propertyName === "") return;
360
- const className = entry.classesMap[propertyName];
361
- if (className === void 0 || className === "") return;
362
- entry.classes[className] = true;
363
- },
364
- "Program:exit": () => {
365
- Object.values(importMap).forEach((entry) => {
366
- markAsUsed.forEach((usedClass) => {
367
- if (usedClass !== "") entry.classes[usedClass] = true;
368
- });
369
- const unusedClasses = Object.entries(entry.classes).filter(([, used]) => used === false).map(([className]) => className);
370
- if (unusedClasses.length > 0) context.report({
371
- node: entry.node,
372
- message: `Unused classes found in ${node_path.default.basename(entry.filePath)}: ${unusedClasses.join(", ")}`
373
- });
374
- });
375
- }
376
- };
377
- }
378
- };
379
-
380
251
  //#endregion
381
252
  //#region src/plugin/index.ts
382
253
  const version = "1.0.0";
@@ -385,10 +256,7 @@ const siberiacancodePlugin = {
385
256
  name: "@siberiacancode/eslint-plugin",
386
257
  version
387
258
  },
388
- rules: {
389
- "function-component-definition": functionComponentDefinition,
390
- "no-unused-class": noUnusedClass
391
- }
259
+ rules: { "function-component-definition": functionComponentDefinition }
392
260
  };
393
261
 
394
262
  //#endregion
@@ -401,12 +269,13 @@ const eslint = (inputOptions = {}, ...configs) => {
401
269
  files: ["**/*.?([cm])ts", "**/*.?([cm])tsx"],
402
270
  languageOptions: { parserOptions: { projectService: true } },
403
271
  rules: {
272
+ ...options.react && { "react/no-leaked-conditional-rendering": "error" },
404
273
  "ts/promise-function-async": "off",
405
274
  "ts/strict-boolean-expressions": "off",
406
275
  "ts/no-unnecessary-condition": "error",
407
276
  "ts/no-namespace": "off",
408
277
  "ts/no-floating-promises": "off",
409
- "ts/no-misused-promises": "off",
278
+ "ts/no-misused-promises": ["error", { checksVoidReturn: false }],
410
279
  "ts/no-empty-object-type": "warn"
411
280
  }
412
281
  });
@@ -492,15 +361,12 @@ const eslint = (inputOptions = {}, ...configs) => {
492
361
  configs.unshift({
493
362
  name: "siberiacancode",
494
363
  plugins: { siberiacancode: siberiacancodePlugin },
495
- rules: {
496
- "siberiacancode/function-component-definition": ["error", { namedComponents: ["arrow-function"] }],
497
- "siberiacancode/no-unused-class": "error"
498
- }
364
+ rules: { "siberiacancode/function-component-definition": ["error", { namedComponents: ["arrow-function"] }] }
499
365
  });
500
366
  return (0, _antfu_eslint_config.default)({
501
367
  ...options,
502
368
  stylistic,
503
- ...typescript === "engine" ? { typescript: { tsconfigPath: "./tsconfig.json" } } : typescript
369
+ ...typescript === "engine" ? { typescript: { tsconfigPath: "./tsconfig.json" } } : { typescript }
504
370
  }, {
505
371
  name: "siberiacancode/rewrite",
506
372
  rules: {
@@ -1,4 +1,4 @@
1
- import { Awaitable, ConfigNames, OptionsConfig, TypedFlatConfigItem } from "@antfu/eslint-config";
1
+ import { Awaitable, ConfigNames, OptionsConfig, OptionsTypescript, TypedFlatConfigItem } from "@antfu/eslint-config";
2
2
  import { Linter } from "eslint";
3
3
  import { FlatConfigComposer } from "eslint-flat-config-utils";
4
4
 
@@ -7,7 +7,7 @@ type EslintOptions = OptionsConfig & TypedFlatConfigItem & {
7
7
  jsxA11y?: boolean;
8
8
  playwright?: boolean;
9
9
  tailwind?: boolean;
10
- typescript?: 'engine';
10
+ typescript?: boolean | 'engine' | OptionsTypescript;
11
11
  };
12
12
  type Eslint = (options?: EslintOptions, ...userConfigs: Awaitable<FlatConfigComposer<any, any> | Linter.Config[] | TypedFlatConfigItem | TypedFlatConfigItem[]>[]) => FlatConfigComposer<TypedFlatConfigItem, ConfigNames>;
13
13
  declare const eslint: Eslint;
@@ -1,4 +1,4 @@
1
- import { Awaitable, ConfigNames, OptionsConfig, TypedFlatConfigItem } from "@antfu/eslint-config";
1
+ import { Awaitable, ConfigNames, OptionsConfig, OptionsTypescript, TypedFlatConfigItem } from "@antfu/eslint-config";
2
2
  import { Linter } from "eslint";
3
3
  import { FlatConfigComposer } from "eslint-flat-config-utils";
4
4
 
@@ -7,7 +7,7 @@ type EslintOptions = OptionsConfig & TypedFlatConfigItem & {
7
7
  jsxA11y?: boolean;
8
8
  playwright?: boolean;
9
9
  tailwind?: boolean;
10
- typescript?: 'engine';
10
+ typescript?: boolean | 'engine' | OptionsTypescript;
11
11
  };
12
12
  type Eslint = (options?: EslintOptions, ...userConfigs: Awaitable<FlatConfigComposer<any, any> | Linter.Config[] | TypedFlatConfigItem | TypedFlatConfigItem[]>[]) => FlatConfigComposer<TypedFlatConfigItem, ConfigNames>;
13
13
  declare const eslint: Eslint;
@@ -3,8 +3,6 @@ import pluginCss from "@eslint/css";
3
3
  import pluginBetterTailwindcss from "eslint-plugin-better-tailwindcss";
4
4
  import pluginJsxA11y from "eslint-plugin-jsx-a11y";
5
5
  import pluginPlaywright from "eslint-plugin-playwright";
6
- import fs from "node:fs";
7
- import path from "node:path";
8
6
 
9
7
  //#region src/plugin/rules/function-component-definition.ts
10
8
  const NAMED_TEMPLATES = {
@@ -217,131 +215,6 @@ const functionComponentDefinition = {
217
215
  }
218
216
  };
219
217
 
220
- //#endregion
221
- //#region src/plugin/rules/no-unused-class.ts
222
- const STYLE_IMPORT_REGEXP = /\.(?:css|scss|less)$/u;
223
- const toCamelCase = (value) => value.replace(/-([a-z])/gu, (_substring, letter) => letter.toUpperCase());
224
- const extractClassNames = (source) => {
225
- const classNames = /* @__PURE__ */ new Set();
226
- const classNameRegExp = /\.([_a-zA-Z][\w-]*)/gu;
227
- let match = classNameRegExp.exec(source);
228
- while (match !== null) {
229
- const className = match[1];
230
- if (className !== void 0 && className !== "") classNames.add(className);
231
- match = classNameRegExp.exec(source);
232
- }
233
- return [...classNames];
234
- };
235
- const buildClassesMap = (classNames, camelCaseOption) => {
236
- const onlyCamelCase = camelCaseOption === "only" || camelCaseOption === "dashes-only";
237
- const withCamelCase = camelCaseOption === true || camelCaseOption === "dashes" || onlyCamelCase;
238
- const classesMap = {};
239
- classNames.forEach((className) => {
240
- if (!onlyCamelCase) classesMap[className] = className;
241
- if (withCamelCase) classesMap[toCamelCase(className)] = className;
242
- });
243
- return classesMap;
244
- };
245
- const getStyleImportData = (node) => {
246
- if (node.source.type !== "Literal" || typeof node.source.value !== "string") return void 0;
247
- const source = node.source.value;
248
- if (!STYLE_IMPORT_REGEXP.test(source)) return void 0;
249
- const importSpecifier = node.specifiers.find((specifier) => specifier.type === "ImportDefaultSpecifier" || specifier.type === "ImportNamespaceSpecifier");
250
- if (importSpecifier === void 0) return void 0;
251
- return {
252
- importName: importSpecifier.local.name,
253
- importNode: importSpecifier,
254
- styleFilePath: source
255
- };
256
- };
257
- const getPropertyName = (node, camelCaseOption) => {
258
- if (node.computed === false && node.property.type === "Identifier") return node.property.name;
259
- if (node.computed === true && node.property.type === "Literal") {
260
- if (typeof node.property.value !== "string" || node.property.value === "") return void 0;
261
- return camelCaseOption === "only" ? toCamelCase(node.property.value) : node.property.value;
262
- }
263
- if (node.computed === true && node.property.type === "TemplateLiteral" && node.property.expressions.length === 0) {
264
- const value = node.property.quasis[0]?.value.cooked;
265
- if (typeof value !== "string" || value === "") return void 0;
266
- return camelCaseOption === "only" ? toCamelCase(value) : value;
267
- }
268
- };
269
- const getAbsoluteStylePath = (context, styleFilePath) => {
270
- const filename = context.filename;
271
- if (filename === "<input>") return void 0;
272
- return path.resolve(path.dirname(filename), styleFilePath);
273
- };
274
- const noUnusedClass = {
275
- meta: {
276
- type: "problem",
277
- docs: { description: "Checks that all CSS/SCSS/LESS classes imported as modules are used" },
278
- schema: [{
279
- type: "object",
280
- properties: {
281
- camelCase: { enum: [
282
- true,
283
- "dashes",
284
- "only",
285
- "dashes-only"
286
- ] },
287
- markAsUsed: {
288
- type: "array",
289
- items: { type: "string" }
290
- }
291
- },
292
- additionalProperties: false
293
- }]
294
- },
295
- create(context) {
296
- const options = context.options[0] ?? {};
297
- const camelCaseOption = options.camelCase;
298
- const markAsUsed = options.markAsUsed ?? [];
299
- const importMap = {};
300
- return {
301
- ImportDeclaration(node) {
302
- const styleImportData = getStyleImportData(node);
303
- if (styleImportData === void 0) return;
304
- const absoluteStylePath = getAbsoluteStylePath(context, styleImportData.styleFilePath);
305
- if (absoluteStylePath === void 0 || !fs.existsSync(absoluteStylePath)) return;
306
- const classNames = extractClassNames(fs.readFileSync(absoluteStylePath, "utf8"));
307
- const classes = {};
308
- classNames.forEach((className) => {
309
- classes[className] = false;
310
- });
311
- importMap[styleImportData.importName] = {
312
- classes,
313
- classesMap: buildClassesMap(classNames, camelCaseOption),
314
- filePath: styleImportData.styleFilePath,
315
- node: styleImportData.importNode
316
- };
317
- },
318
- MemberExpression(node) {
319
- const typedNode = node;
320
- if (typedNode.object.type !== "Identifier") return;
321
- const entry = importMap[typedNode.object.name];
322
- if (entry === void 0) return;
323
- const propertyName = getPropertyName(typedNode, camelCaseOption);
324
- if (propertyName === void 0 || propertyName === "") return;
325
- const className = entry.classesMap[propertyName];
326
- if (className === void 0 || className === "") return;
327
- entry.classes[className] = true;
328
- },
329
- "Program:exit": () => {
330
- Object.values(importMap).forEach((entry) => {
331
- markAsUsed.forEach((usedClass) => {
332
- if (usedClass !== "") entry.classes[usedClass] = true;
333
- });
334
- const unusedClasses = Object.entries(entry.classes).filter(([, used]) => used === false).map(([className]) => className);
335
- if (unusedClasses.length > 0) context.report({
336
- node: entry.node,
337
- message: `Unused classes found in ${path.basename(entry.filePath)}: ${unusedClasses.join(", ")}`
338
- });
339
- });
340
- }
341
- };
342
- }
343
- };
344
-
345
218
  //#endregion
346
219
  //#region src/plugin/index.ts
347
220
  const version = "1.0.0";
@@ -350,10 +223,7 @@ const siberiacancodePlugin = {
350
223
  name: "@siberiacancode/eslint-plugin",
351
224
  version
352
225
  },
353
- rules: {
354
- "function-component-definition": functionComponentDefinition,
355
- "no-unused-class": noUnusedClass
356
- }
226
+ rules: { "function-component-definition": functionComponentDefinition }
357
227
  };
358
228
 
359
229
  //#endregion
@@ -366,12 +236,13 @@ const eslint = (inputOptions = {}, ...configs) => {
366
236
  files: ["**/*.?([cm])ts", "**/*.?([cm])tsx"],
367
237
  languageOptions: { parserOptions: { projectService: true } },
368
238
  rules: {
239
+ ...options.react && { "react/no-leaked-conditional-rendering": "error" },
369
240
  "ts/promise-function-async": "off",
370
241
  "ts/strict-boolean-expressions": "off",
371
242
  "ts/no-unnecessary-condition": "error",
372
243
  "ts/no-namespace": "off",
373
244
  "ts/no-floating-promises": "off",
374
- "ts/no-misused-promises": "off",
245
+ "ts/no-misused-promises": ["error", { checksVoidReturn: false }],
375
246
  "ts/no-empty-object-type": "warn"
376
247
  }
377
248
  });
@@ -457,15 +328,12 @@ const eslint = (inputOptions = {}, ...configs) => {
457
328
  configs.unshift({
458
329
  name: "siberiacancode",
459
330
  plugins: { siberiacancode: siberiacancodePlugin },
460
- rules: {
461
- "siberiacancode/function-component-definition": ["error", { namedComponents: ["arrow-function"] }],
462
- "siberiacancode/no-unused-class": "error"
463
- }
331
+ rules: { "siberiacancode/function-component-definition": ["error", { namedComponents: ["arrow-function"] }] }
464
332
  });
465
333
  return antfu({
466
334
  ...options,
467
335
  stylistic,
468
- ...typescript === "engine" ? { typescript: { tsconfigPath: "./tsconfig.json" } } : typescript
336
+ ...typescript === "engine" ? { typescript: { tsconfigPath: "./tsconfig.json" } } : { typescript }
469
337
  }, {
470
338
  name: "siberiacancode/rewrite",
471
339
  rules: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@siberiacancode/eslint",
3
3
  "type": "module",
4
- "version": "2.16.4",
4
+ "version": "2.16.6",
5
5
  "description": "eslint configs",
6
6
  "author": {
7
7
  "name": "SIBERIA CAN CODE 🧊",
@@ -45,13 +45,13 @@
45
45
  "dist"
46
46
  ],
47
47
  "scripts": {
48
- "prepublishOnly": "yarn type && yarn build",
48
+ "prepublishOnly": "pnpm type && pnpm build",
49
49
  "build": "tsdown",
50
50
  "lint": "eslint . --fix",
51
51
  "lint-inspector": "npx @eslint/config-inspector",
52
52
  "type": "tsc --noEmit",
53
53
  "format": "prettier --write .",
54
- "pretty": "yarn type && yarn lint && yarn format"
54
+ "pretty": "pnpm type && pnpm lint && pnpm format"
55
55
  },
56
56
  "dependencies": {
57
57
  "@antfu/eslint-config": "7.4.3",