import { Linter } from "eslint"; import { defineConfig, globalIgnores } from "eslint/config"; import globals from "globals"; import * as astroEsLintParser from "astro-eslint-parser"; import astro from "eslint-plugin-astro"; import typeScriptEsLint from "typescript-eslint"; import functional from "eslint-plugin-functional"; import javascript from "@eslint/js"; import jsdoc from "eslint-plugin-jsdoc"; import sonarJs from "eslint-plugin-sonarjs"; import perfectionist from "eslint-plugin-perfectionist"; import unicorn from "eslint-plugin-unicorn"; //#region rules/astro.ts const astroRules = [ { files: ["**/*.astro"], languageOptions: { globals: { ...globals.astro }, parser: astroEsLintParser, parserOptions: { extraFileExtensions: [".astro"], parser: typeScriptEsLint.parser, project: true, projectService: null, tsconfigRootDir: null, }, sourceType: "module", }, name: "Astro", plugins: { astro: astro.configs.base[0]?.plugins.astro ?? {} }, processor: "astro/client-side-ts", rules: { "astro/missing-client-only-directive-value": "error", "astro/no-conflict-set-directives": "error", "astro/no-deprecated-astro-canonicalurl": "error", "astro/no-deprecated-astro-fetchcontent": "error", "astro/no-deprecated-astro-resolve": "error", "astro/no-deprecated-getentrybyslug": "error", "astro/no-exports-from-components": "error", "astro/no-set-html-directive": "error", "astro/no-set-text-directive": "error", "astro/no-unused-css-selector": "error", "astro/no-unused-define-vars-in-style": "error", "astro/prefer-class-list-directive": "error", "astro/prefer-object-class-list": "error", "astro/prefer-split-class-list": ["error", { splitLiteral: false }], "astro/sort-attributes": [ "error", { ignoreCase: false, order: "asc", type: "alphabetical", }, ], "astro/valid-compile": "error", ...astro.configs["jsx-a11y-strict"][4]?.rules, }, }, { files: ["**/*.astro/*.ts"], languageOptions: { globals: { ...globals.browser }, parser: typeScriptEsLint.parser, parserOptions: { project: null }, sourceType: "module", }, name: "Astro/TypeScript", }, ]; //#endregion //#region rules/functional.ts const functionalRules = { name: "Programmation fonctionnelle", plugins: { functional }, rules: { ...functional.configs.noExceptions.rules, ...functional.configs.noMutations.rules, ...functional.configs.externalTypeScriptRecommended.rules, ...functional.configs.stylistic.rules, "@typescript-eslint/array-type": [ "error", { default: "generic", readonly: "generic", }, ], "functional/prefer-immutable-types": "off", "functional/prefer-tacit": "off", "functional/readonly-type": ["error", "generic"], "functional/type-declaration-immutability": "off", }, }; //#endregion //#region rules/javascript.ts const javascriptRules = { name: "JavaScript", rules: { ...javascript.configs.recommended.rules, "array-callback-return": [ "error", { allowVoid: true, checkForEach: true, }, ], "no-nested-ternary": "off", "no-unassigned-vars": "error", "no-unneeded-ternary": ["error", { defaultAssignment: false }], "no-unreachable-loop": "error", "no-use-before-define": "off", "no-useless-assignment": "error", yoda: ["error", "never"], }, }; //#endregion //#region rules/jsdoc.ts const flatRecommended = jsdoc.configs["flat/recommended-typescript"]; const flatStylistic = jsdoc.configs["flat/stylistic-typescript"]; const jsDocRules = { name: "JSDoc", plugins: flatRecommended.plugins ?? {}, rules: { ...flatRecommended.rules, ...flatStylistic.rules, "jsdoc/check-indentation": "warn", "jsdoc/check-line-alignment": "warn", "jsdoc/check-tag-names": ["warn", { definedTags: ["link"] }], "jsdoc/lines-before-block": "off", "jsdoc/no-blank-block-descriptions": "warn", "jsdoc/no-blank-blocks": "warn", "jsdoc/require-hyphen-before-param-description": ["warn", "never"], "jsdoc/require-throws": "warn", "jsdoc/sort-tags": "warn", "jsdoc/tag-lines": "off", }, }; //#endregion //#region rules/sonarjs.ts const sonarJsRules = { name: "SonarJS", plugins: sonarJs.configs.recommended.plugins ?? {}, rules: { ...sonarJs.configs.recommended.rules, "sonarjs/arguments-usage": "error", "sonarjs/no-collapsible-if": "error", "sonarjs/no-duplicate-string": "error", "sonarjs/no-inconsistent-returns": "error", "sonarjs/no-nested-switch": "error", "sonarjs/prefer-immediate-return": "error", }, }; //#endregion //#region rules/tri.ts const sortRules = { name: "Tri", plugins: perfectionist.configs["recommended-natural"].plugins ?? {}, rules: perfectionist.configs["recommended-natural"].rules ?? {}, }; //#endregion //#region rules/typescript.ts const findConfiguration = (configuration, nom) => configuration.find((v) => v.name === nom) ?? {}; const base = findConfiguration(typeScriptEsLint.configs.strictTypeChecked, "typescript-eslint/base"); const desactivationsJavaScript = findConfiguration( typeScriptEsLint.configs.strictTypeChecked, "typescript-eslint/eslint-recommended", ); const strictTypeChecked = findConfiguration( typeScriptEsLint.configs.strictTypeChecked, "typescript-eslint/strict-type-checked", ); const stylisticTypeChecked = findConfiguration( typeScriptEsLint.configs.stylisticTypeChecked, "typescript-eslint/stylistic-type-checked", ); const typeScriptRules = { languageOptions: base.languageOptions ?? {}, name: "TypeScript", plugins: base.plugins ?? {}, rules: { ...desactivationsJavaScript.rules, ...strictTypeChecked.rules, ...stylisticTypeChecked.rules, "@typescript-eslint/consistent-type-definitions": ["error", "type"], "@typescript-eslint/max-params": ["error", { max: 3 }], "@typescript-eslint/method-signature-style": ["off", "property"], "@typescript-eslint/no-magic-numbers": "off", "@typescript-eslint/no-unnecessary-boolean-literal-compare": "off", "@typescript-eslint/no-unnecessary-type-parameters": "off", }, }; //#endregion //#region rules/unicorn.ts const unicornRules = { name: "Unicorn", plugins: { unicorn }, rules: { ...unicorn.configs.unopinionated.rules, "unicorn/catch-error-name": "error", "unicorn/consistent-empty-array-spread": "error", "unicorn/custom-error-definition": "error", "unicorn/explicit-length-check": ["error", { "non-zero": "not-equal" }], "unicorn/no-array-for-each": "off", "unicorn/no-array-reduce": "off", "unicorn/no-negated-condition": "error", "unicorn/no-nested-ternary": "error", "unicorn/no-null": "error", "unicorn/prefer-dom-node-dataset": "off", }, }; //#endregion //#region index.ts const configTypescriptNavigateur = defineConfig([ globalIgnores(["dist/**/*"], "Ignore le dossier de compilation"), { files: ["**/*.js", "**/*.ts"], name: "Fichiers à analyser", }, { languageOptions: { ecmaVersion: "latest", globals: { ...globals.browser, ...globals.builtin, ...globals.es2026, ...globals.node, }, parserOptions: { ecmaVersion: "latest", projectService: true, sourceType: "module", tsconfigRootDir: import.meta.dirname, }, }, name: "Configuration du projet", }, javascriptRules, typeScriptRules, functionalRules, unicornRules, sonarJsRules, jsDocRules, sortRules, ]); const configAstro = defineConfig([...configTypescriptNavigateur, ...astroRules]); //#endregion export { configAstro, configTypescriptNavigateur };