This commit is contained in:
gcch 2026-03-12 18:42:12 +01:00
commit 62ee424274
27 changed files with 1290 additions and 996 deletions

View file

@ -1,11 +0,0 @@
{
"categories": {
"correctness": "error",
"suspicious": "error",
"perf": "error"
},
"plugins": ["import", "oxc"],
"rules": {
"oxc/branches-sharing-code": "error"
}
}

938
bun.lock

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
{ {
"dictionaries": ["fr-fr", "en-gb"], "dictionaries": ["fr-fr", "en-gb"],
"words": ["Navigateur", "tsdown", "publint", "sonarjs"], "userWords": ["oxlint"],
"userWords": ["oxlint"] "words": ["Navigateur", "tsdown", "publint", "sonarjs"]
} }

3
dist/index.d.mts vendored
View file

@ -2,5 +2,6 @@ import { Linter } from "eslint";
//#region index.d.ts //#region index.d.ts
declare const configTypescriptNavigateur: ReadonlyArray<Linter.Config>; declare const configTypescriptNavigateur: ReadonlyArray<Linter.Config>;
declare const configAstro: ReadonlyArray<Linter.Config>;
//#endregion //#endregion
export { configTypescriptNavigateur }; export { configAstro, configTypescriptNavigateur };

391
dist/index.mjs vendored
View file

@ -1,188 +1,271 @@
import { Linter } from "eslint"; import { Linter } from "eslint";
import { defineConfig, globalIgnores } from "eslint/config"; import { defineConfig, globalIgnores } from "eslint/config";
import globals from "globals"; 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 javascript from "@eslint/js";
import jsdoc from "eslint-plugin-jsdoc"; import jsdoc from "eslint-plugin-jsdoc";
import oxlint from "eslint-plugin-oxlint";
import functional from "eslint-plugin-functional";
import typescriptEslint from "typescript-eslint";
import sonarJs from "eslint-plugin-sonarjs"; import sonarJs from "eslint-plugin-sonarjs";
import perfectionist from "eslint-plugin-perfectionist"; import perfectionist from "eslint-plugin-perfectionist";
import unicorn from "eslint-plugin-unicorn"; import unicorn from "eslint-plugin-unicorn";
//#region règles/javascript.ts //#region rules/astro.ts
const règlesJavaScript = { const getAstroPlugin = () => {
name: "JavaScript", const firstBaseConfig = astro.configs.base.at(0);
rules: { if (firstBaseConfig === void 0) throw new Error("Impossible de récupérer la configuration de base du plugin Astro.");
...javascript.configs.recommended.rules, const astroPlugin = firstBaseConfig.plugins?.["astro"];
"array-callback-return": ["error", { if (astroPlugin === void 0) throw new Error("Impossible de récupérer le plugin Astro.");
allowVoid: true, return astroPlugin;
checkForEach: true };
}], const astroRules = [
"no-nested-ternary": "off", {
"no-unassigned-vars": "error", files: ["**/*.astro"],
"no-unneeded-ternary": ["error", { defaultAssignment: false }], languageOptions: {
"no-unreachable-loop": "error", globals: { ...globals.astro },
"no-use-before-define": "off", parser: astroEsLintParser,
"no-useless-assignment": "error", parserOptions: {
yoda: ["error", "never"] extraFileExtensions: [".astro"],
} parser: typeScriptEsLint.parser,
project: true,
projectService: null,
tsconfigRootDir: null,
},
sourceType: "module",
},
name: "Astro",
plugins: { astro: getAstroPlugin() },
processor: "astro/client-side-ts",
rules: {
"astro/jsx-a11y/alt-text": "error",
"astro/jsx-a11y/anchor-ambiguous-text": "error",
"astro/jsx-a11y/anchor-has-content": "error",
"astro/jsx-a11y/anchor-is-valid": "error",
"astro/jsx-a11y/aria-activedescendant-has-tabindex": "error",
"astro/jsx-a11y/aria-props": "error",
"astro/jsx-a11y/aria-proptypes": "error",
"astro/jsx-a11y/aria-role": "error",
"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",
},
},
{
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 //#endregion
//#region règles/jsdoc.ts //#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 flatRecommended = jsdoc.configs["flat/recommended-typescript"];
const flatStylistic = jsdoc.configs["flat/stylistic-typescript"]; const flatStylistic = jsdoc.configs["flat/stylistic-typescript"];
const règlesJsDoc = { const jsDocRules = {
name: "JSDoc", name: "JSDoc",
plugins: flatRecommended.plugins ?? {}, plugins: flatRecommended.plugins ?? {},
rules: { rules: {
...flatRecommended.rules, ...flatRecommended.rules,
...flatStylistic.rules, ...flatStylistic.rules,
"jsdoc/check-indentation": "warn", "jsdoc/check-indentation": "warn",
"jsdoc/check-line-alignment": "warn", "jsdoc/check-line-alignment": "warn",
"jsdoc/check-tag-names": ["warn", { definedTags: ["link"] }], "jsdoc/check-tag-names": ["warn", { definedTags: ["link"] }],
"jsdoc/lines-before-block": "off", "jsdoc/lines-before-block": "off",
"jsdoc/no-blank-block-descriptions": "warn", "jsdoc/no-blank-block-descriptions": "warn",
"jsdoc/no-blank-blocks": "warn", "jsdoc/no-blank-blocks": "warn",
"jsdoc/require-hyphen-before-param-description": ["warn", "never"], "jsdoc/require-hyphen-before-param-description": ["warn", "never"],
"jsdoc/require-throws": "warn", "jsdoc/require-throws": "warn",
"jsdoc/sort-tags": "warn", "jsdoc/sort-tags": "warn",
"jsdoc/tag-lines": "off" "jsdoc/tag-lines": "off",
} },
}; };
//#endregion //#endregion
//#region règles/oxlint.ts //#region rules/sonarjs.ts
const règlesOxlint = { const sonarJsRules = {
name: "Oxlint", name: "SonarJS",
...oxlint.configs["flat/recommended"][0] 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 //#endregion
//#region règles/programmation-fonctionnelle.ts //#region rules/tri.ts
const règlesProgrammationFonctionnelle = { const sortRules = {
name: "Programmation fonctionnelle", name: "Tri",
plugins: { functional }, plugins: perfectionist.configs["recommended-natural"].plugins ?? {},
rules: { rules: perfectionist.configs["recommended-natural"].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 //#endregion
//#region règles/sonarjs.ts //#region rules/typescript.ts
const règlesSonarJs = { const findConfiguration = (configuration, nom) => configuration.find((v) => v.name === nom) ?? {};
name: "SonarJS", const base = findConfiguration(typeScriptEsLint.configs.strictTypeChecked, "typescript-eslint/base");
plugins: sonarJs.configs.recommended.plugins ?? {}, const desactivationsJavaScript = findConfiguration(
rules: { typeScriptEsLint.configs.strictTypeChecked,
...sonarJs.configs.recommended.rules, "typescript-eslint/eslint-recommended",
"sonarjs/arguments-usage": "error", );
"sonarjs/no-collapsible-if": "error", const strictTypeChecked = findConfiguration(
"sonarjs/no-duplicate-string": "error", typeScriptEsLint.configs.strictTypeChecked,
"sonarjs/no-inconsistent-returns": "error", "typescript-eslint/strict-type-checked",
"sonarjs/no-nested-switch": "error", );
"sonarjs/prefer-immediate-return": "error" 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",
"@typescript-eslint/only-throw-error": "off",
},
}; };
//#endregion //#endregion
//#region règles/tri.ts //#region rules/unicorn.ts
const règlesTri = { const unicornRules = {
name: "Tri", name: "Unicorn",
plugins: perfectionist.configs["recommended-natural"].plugins ?? {}, plugins: { unicorn },
rules: perfectionist.configs["recommended-natural"].rules ?? {} rules: {
}; ...unicorn.configs.unopinionated.rules,
"unicorn/catch-error-name": "error",
//#endregion "unicorn/consistent-empty-array-spread": "error",
//#region règles/typescript.ts "unicorn/custom-error-definition": "error",
const trouveConfiguration = (configuration, nom) => configuration.find((v) => v.name === nom) ?? {}; "unicorn/explicit-length-check": ["error", { "non-zero": "not-equal" }],
const base = trouveConfiguration(typescriptEslint.configs.strictTypeChecked, "typescript-eslint/base"); "unicorn/no-array-for-each": "off",
const desactivationsJavaScript = trouveConfiguration(typescriptEslint.configs.strictTypeChecked, "typescript-eslint/eslint-recommended"); "unicorn/no-array-reduce": "off",
const strictTypeChecked = trouveConfiguration(typescriptEslint.configs.strictTypeChecked, "typescript-eslint/strict-type-checked"); "unicorn/no-negated-condition": "error",
const stylisticTypeChecked = trouveConfiguration(typescriptEslint.configs.stylisticTypeChecked, "typescript-eslint/stylistic-type-checked"); "unicorn/no-nested-ternary": "error",
const règlesTypeScript = { "unicorn/no-null": "error",
languageOptions: base.languageOptions ?? {}, "unicorn/prefer-dom-node-dataset": "off",
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 règles/unicorn.ts
const règlesUnicorn = {
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 //#endregion
//#region index.ts //#region index.ts
const configTypescriptNavigateur = defineConfig([ const configTypescriptNavigateur = defineConfig([
globalIgnores(["dist/**/*"], "Ignore le dossier de compilation"), globalIgnores(["dist/**/*"], "Ignore le dossier de compilation"),
{ {
files: ["**/*.js", "**/*.ts"], files: ["**/*.js", "**/*.ts"],
name: "Fichiers à analyser" name: "Fichiers à analyser",
}, },
{ {
languageOptions: { languageOptions: {
ecmaVersion: "latest", ecmaVersion: "latest",
globals: { globals: {
...globals.browser, ...globals.browser,
...globals.builtin, ...globals.builtin,
...globals.es2026, ...globals.es2026,
...globals.node ...globals.node,
}, },
parserOptions: { parserOptions: {
ecmaVersion: "latest", ecmaVersion: "latest",
projectService: true, projectService: true,
sourceType: "module", sourceType: "module",
tsconfigRootDir: import.meta.dirname tsconfigRootDir: import.meta.dirname,
} },
}, },
name: "Configuration du projet" name: "Configuration du projet",
}, },
règlesJavaScript, javascriptRules,
règlesTypeScript, typeScriptRules,
règlesProgrammationFonctionnelle, functionalRules,
règlesUnicorn, unicornRules,
règlesSonarJs, sonarJsRules,
règlesJsDoc, jsDocRules,
règlesTri, sortRules,
règlesOxlint
]); ]);
const configAstro = defineConfig([...configTypescriptNavigateur, ...astroRules]);
//#endregion //#endregion
export { configTypescriptNavigateur }; export { configAstro, configTypescriptNavigateur };

View file

@ -1,3 +0,0 @@
{
"extends": "node_modules/@gcch/configuration-dprint/dprint.json"
}

View file

@ -1,5 +1,5 @@
import { defineConfig } from "eslint/config"; import { defineConfig } from "eslint/config";
import { configTypescriptNavigateur } from "."; import { configAstro } from "./dist/index.mjs";
export default defineConfig([...configTypescriptNavigateur]); export default defineConfig([...configAstro]);

View file

@ -2,14 +2,14 @@ import { Linter } from "eslint";
import { defineConfig, globalIgnores } from "eslint/config"; import { defineConfig, globalIgnores } from "eslint/config";
import globals from "globals"; import globals from "globals";
import { règlesJavaScript } from "./règles/javascript.ts"; import { astroRules } from "./rules/astro.ts";
import { règlesJsDoc } from "./règles/jsdoc.ts"; import { functionalRules } from "./rules/functional.ts";
import { règlesOxlint } from "./règles/oxlint.ts"; import { javascriptRules } from "./rules/javascript.ts";
import { règlesProgrammationFonctionnelle } from "./règles/programmation-fonctionnelle.ts"; import { jsDocRules } from "./rules/jsdoc.ts";
import { règlesSonarJs } from "./règles/sonarjs.ts"; import { sonarJsRules } from "./rules/sonarjs.ts";
import { règlesTri } from "./règles/tri.ts"; import { sortRules } from "./rules/tri.ts";
import { règlesTypeScript } from "./règles/typescript.ts"; import { typeScriptRules } from "./rules/typescript.ts";
import { règlesUnicorn } from "./règles/unicorn.ts"; import { unicornRules } from "./rules/unicorn.ts";
export const configTypescriptNavigateur: ReadonlyArray<Linter.Config> = defineConfig([ export const configTypescriptNavigateur: ReadonlyArray<Linter.Config> = defineConfig([
globalIgnores(["dist/**/*"], "Ignore le dossier de compilation"), globalIgnores(["dist/**/*"], "Ignore le dossier de compilation"),
@ -35,12 +35,13 @@ export const configTypescriptNavigateur: ReadonlyArray<Linter.Config> = defineCo
}, },
name: "Configuration du projet", name: "Configuration du projet",
}, },
règlesJavaScript, javascriptRules,
règlesTypeScript, typeScriptRules,
règlesProgrammationFonctionnelle, functionalRules,
règlesUnicorn, unicornRules,
règlesSonarJs, sonarJsRules,
règlesJsDoc, jsDocRules,
règlesTri, sortRules,
règlesOxlint,
]); ]);
export const configAstro: ReadonlyArray<Linter.Config> = defineConfig([...configTypescriptNavigateur, ...astroRules]);

View file

@ -1,31 +1,38 @@
set shell := ["/usr/bin/fish", "-c"] set shell := ["/usr/bin/fish", "-c"]
# Formate le code. # Formate le code.
formate: format:
bun prettier --cache --cache-location ".cache/prettiercache" --ignore-unknown --parallel-workers 8 --write . bun prettier --cache --cache-location ".cache/prettiercache" --ignore-unknown --parallel-workers 8 --write .
dprint fmt dprint fmt --config ~/.config/dprint/dprint.jsonc
# Met à jour les dépendances NPM. # Met à jour les dépendances NPM.
maj-dependances: update:
bun update bun update
# Analyse le code TypeScript avec ESLint. # Analyse le code TypeScript avec ESLint.
analyse-code: lint-js:
bun eslint bun eslint --cache --cache-location ".cache/eslintcache"
# Analyse le code mort et les dépendances inutilisées du projet. # Analyse le code mort et les dépendances inutilisées du projet.
analyse-code-mort: find-dead-code:
bun knip bun knip
bun knip --production bun knip --production
# Compile le projet. # Compile le projet.
compile: build:
bun tsdown --attw --publint bun tsdown --attw --publint
# Nettoie le dosiser de compilation. # Nettoie le dosiser de compilation.
nettoie: clean:
rm -rfv dist rm -rf .cache/
rm -rf bun.lock
rm -rf node_modules/
rm -rfv dist/
# Nettoie le dossier de cache.
clean-cache:
rm -rf .cache/
# Publie le paquet sur le registre local. # Publie le paquet sur le registre local.
publie: publish:
npm publish --registry http://localhost:4873 npm publish --registry http://localhost:4873

View file

@ -1,6 +1,6 @@
{ {
"name": "@gcch/configuration-eslint", "name": "@gcch/configuration-eslint",
"version": "0.0.10", "version": "0.0.11",
"type": "module", "type": "module",
"description": "Configuration eslint partageable pour gcch.", "description": "Configuration eslint partageable pour gcch.",
"main": "./dist/index.mjs", "main": "./dist/index.mjs",
@ -10,39 +10,33 @@
".": "./dist/index.mjs", ".": "./dist/index.mjs",
"./package.json": "./package.json" "./package.json": "./package.json"
}, },
"files": [ "files": ["dist"],
"dist"
],
"peerDependencies": { "peerDependencies": {
"eslint": "^9.36.0", "eslint": "^10.0.3",
"oxlint": "^1.28.0", "typescript": "^6.0.1-rc"
"typescript": "^6.0.0-dev.20251111"
}, },
"dependencies": { "dependencies": {
"@eslint/js": "^9.39.1", "@eslint/js": "^10.0.1",
"eslint": "^9.39.1", "astro-eslint-parser": "^1.3.0",
"eslint-plugin-functional": "^9.0.2", "eslint": "^10.0.3",
"eslint-plugin-jsdoc": "^61.1.12", "eslint-plugin-astro": "^1.6.0",
"eslint-plugin-oxlint": "^1.28.0", "eslint-plugin-functional": "^9.0.4",
"eslint-plugin-perfectionist": "^4.15.1", "eslint-plugin-jsdoc": "^62.8.0",
"eslint-plugin-sonarjs": "^3.0.5", "eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-unicorn": "^62.0.0", "eslint-plugin-perfectionist": "^5.6.0",
"globals": "^16.5.0", "eslint-plugin-sonarjs": "^4.0.2",
"typescript-eslint": "^8.46.4" "eslint-plugin-unicorn": "^63.0.0",
"globals": "^17.4.0",
"typescript-eslint": "^8.57.0"
}, },
"devDependencies": { "devDependencies": {
"@arethetypeswrong/core": "^0.18.2", "@arethetypeswrong/core": "^0.18.2",
"@gcch/configuration-dprint": "^0.0.2", "@gcch/configuration-prettier": "git+https://git.gcch.fr/gcch/configuration-prettier",
"@gcch/configuration-prettier": "^0.0.10", "knip": "^5.86.0",
"knip": "^5.69.0", "prettier": "^3.8.1",
"prettier": "^4.0.0-alpha.12", "publint": "^0.3.18",
"prettier-plugin-curly": "^0.4.0", "tsdown": "^0.21.2",
"prettier-plugin-jsdoc": "^1.5.0", "typescript": "^6.0.1-rc"
"prettier-plugin-sh": "^0.18.0",
"publint": "^0.3.15",
"tsdown": "^0.16.2"
}, },
"trustedDependencies": [ "trustedDependencies": ["oxc-resolver"]
"oxc-resolver"
]
} }

116
rules/astro.ts Normal file
View file

@ -0,0 +1,116 @@
/* eslint-disable unicorn/no-null -- Le null est nécessaire ici. */
/* eslint-disable functional/no-throw-statements -- L'exécution d'ESLint doit pouvoir s'arrêter en cas d'échec critique. */
import type { ESLint, Linter } from "eslint";
import * as astroEsLintParser from "astro-eslint-parser";
import astro from "eslint-plugin-astro";
import globals from "globals";
import typeScriptEsLint from "typescript-eslint";
const getAstroPlugin = (): ESLint.Plugin => {
const firstBaseConfig = astro.configs.base.at(0);
if (firstBaseConfig === undefined) {
throw new Error("Impossible de récupérer la configuration de base du plugin Astro.");
}
const astroPlugin = firstBaseConfig.plugins?.["astro"];
if (astroPlugin === undefined) {
throw new Error("Impossible de récupérer le plugin Astro.");
}
return astroPlugin;
};
export const astroRules: ReadonlyArray<Linter.Config> = [
{
files: ["**/*.astro"],
languageOptions: {
globals: {
...globals.astro,
},
parser: astroEsLintParser,
parserOptions: {
extraFileExtensions: [".astro"],
parser: typeScriptEsLint.parser,
/// Ces lignes sont nécessaires pour surcharger la configuration pour les fichiers TS.
project: true,
projectService: null,
tsconfigRootDir: null,
},
sourceType: "module",
},
name: "Astro",
plugins: {
astro: getAstroPlugin(),
},
processor: "astro/client-side-ts",
rules: {
//
// Enforce that all elements that require alternative text have meaningful information to relay back to the end user.
"astro/jsx-a11y/alt-text": "error",
// Enforces <a> values are not exact matches for the phrases “click here”, “here”, “link”, “a link”, or “learn more”.
"astro/jsx-a11y/anchor-ambiguous-text": "error",
// Enforce that anchors have content and that the content is accessible to screen readers. Accessible means that it is not hidden using the aria-hidden prop.
"astro/jsx-a11y/anchor-has-content": "error",
// Ennforces that <a> elements avec valid hyperlinks (and not buttons).
"astro/jsx-a11y/anchor-is-valid": "error",
// Enforces good aria-activedescendant handling.
"astro/jsx-a11y/aria-activedescendant-has-tabindex": "error",
// Elements cannot use an invalid ARIA attribute. This will fail if it finds an aria-* property that is not listed in WAI-ARIA States and Properties spec.
"astro/jsx-a11y/aria-props": "error",
// ARIA state and property values must be valid.
"astro/jsx-a11y/aria-proptypes": "error",
// Elements with ARIA roles must use a valid, non-abstract ARIA role. A reference to role definitions can be found at
"astro/jsx-a11y/aria-role": "error",
// This rule reports not setting a value for the client:only directive.
"astro/missing-client-only-directive-value": "error",
// This rule reports conflicting set:text, set:html, and child content.
"astro/no-conflict-set-directives": "error",
// This rule reports use of deprecated Astro.canonicalURL.
"astro/no-deprecated-astro-canonicalurl": "error",
// This rule reports use of deprecated Astro.fetchContent().
"astro/no-deprecated-astro-fetchcontent": "error",
// This rule reports use of deprecated Astro.resolve().
"astro/no-deprecated-astro-resolve": "error",
// This rule reports use of deprecated getEntryBySlug().
"astro/no-deprecated-getentrybyslug": "error",
// This rule reports value exports from Astro components. The use of typed exports are still allowed.
"astro/no-exports-from-components": "error",
// This rule reports all uses of set:html in order to reduce the risk of injecting potentially unsafe / unescaped html into the browser leading to Cross-Site Scripting (XSS) attacks.
"astro/no-set-html-directive": "error",
// This rule reports all uses of set:text directive.
"astro/no-set-text-directive": "error",
// This rule aims to remove unused CSS selectors.
"astro/no-unused-css-selector": "error",
// This rule is aimed at eliminating unused defined variables in define:vars={...} in style tag.
"astro/no-unused-define-vars-in-style": "error",
// This rule aims to replace the class attribute with expression with the class:list directive.
"astro/prefer-class-list-directive": "error",
// This rule aims to replace the class attribute with expression with the class:list directive.
"astro/prefer-object-class-list": "error",
// This rule aims to use split array elements than string concatenation in class:list.
"astro/prefer-split-class-list": ["error", { splitLiteral: false }],
// This rule ensures that attributes are sorted, making the structure of your elements more predictable and easier to manage.
"astro/sort-attributes": ["error", { ignoreCase: false, order: "asc", type: "alphabetical" }],
// This rule uses @astrojs/compiler to check the source code.
"astro/valid-compile": "error",
// TODO: Finir.
},
},
{
/// Cette configuration permet de vérfier les blocs TS dans les fichiers Astro.
files: ["**/*.astro/*.ts"],
languageOptions: {
globals: { ...globals.browser },
parser: typeScriptEsLint.parser,
parserOptions: {
project: null,
},
sourceType: "module",
},
name: "Astro/TypeScript",
},
];

View file

@ -3,7 +3,7 @@ import type { Linter } from "eslint";
import functional from "eslint-plugin-functional"; import functional from "eslint-plugin-functional";
import typescriptEslint from "typescript-eslint"; import typescriptEslint from "typescript-eslint";
export const règlesProgrammationFonctionnelle: Readonly<Linter.Config> = { export const functionalRules: Readonly<Linter.Config> = {
name: "Programmation fonctionnelle", name: "Programmation fonctionnelle",
plugins: { functional: functional as typeof typescriptEslint.plugin }, plugins: { functional: functional as typeof typescriptEslint.plugin },
rules: { rules: {

View file

@ -2,7 +2,7 @@ import type { Linter } from "eslint";
import javascript from "@eslint/js"; import javascript from "@eslint/js";
export const règlesJavaScript: Readonly<Linter.Config> = { export const javascriptRules: Readonly<Linter.Config> = {
name: "JavaScript", name: "JavaScript",
rules: { rules: {
...javascript.configs.recommended.rules, ...javascript.configs.recommended.rules,

View file

@ -5,7 +5,7 @@ import jsdoc from "eslint-plugin-jsdoc";
const flatRecommended = jsdoc.configs["flat/recommended-typescript"]; const flatRecommended = jsdoc.configs["flat/recommended-typescript"];
const flatStylistic = jsdoc.configs["flat/stylistic-typescript"]; const flatStylistic = jsdoc.configs["flat/stylistic-typescript"];
export const règlesJsDoc: Readonly<Linter.Config> = { export const jsDocRules: Readonly<Linter.Config> = {
name: "JSDoc", name: "JSDoc",
plugins: flatRecommended.plugins ?? {}, plugins: flatRecommended.plugins ?? {},
rules: { rules: {

View file

@ -2,7 +2,7 @@ import type { Linter } from "eslint";
import sonarJs from "eslint-plugin-sonarjs"; import sonarJs from "eslint-plugin-sonarjs";
export const règlesSonarJs: Readonly<Linter.Config> = { export const sonarJsRules: Readonly<Linter.Config> = {
name: "SonarJS", name: "SonarJS",
plugins: sonarJs.configs.recommended.plugins ?? {}, plugins: sonarJs.configs.recommended.plugins ?? {},
rules: { rules: {

View file

@ -2,7 +2,7 @@ import type { Linter } from "eslint";
import perfectionist from "eslint-plugin-perfectionist"; import perfectionist from "eslint-plugin-perfectionist";
export const règlesTri: Readonly<Linter.Config> = { export const sortRules: Readonly<Linter.Config> = {
name: "Tri", name: "Tri",
plugins: perfectionist.configs["recommended-natural"].plugins ?? {}, plugins: perfectionist.configs["recommended-natural"].plugins ?? {},
rules: perfectionist.configs["recommended-natural"].rules ?? {}, rules: perfectionist.configs["recommended-natural"].rules ?? {},

View file

@ -4,24 +4,24 @@ import typescriptEslint from "typescript-eslint";
type EsLintConfig = Readonly<Linter.Config>; type EsLintConfig = Readonly<Linter.Config>;
const trouveConfiguration = (configuration: ReadonlyArray<Linter.Config>, nom: string): EsLintConfig => const findConfiguration = (configuration: ReadonlyArray<Linter.Config>, nom: string): EsLintConfig =>
configuration.find((v: EsLintConfig) => v.name === nom) ?? {}; configuration.find((v: EsLintConfig) => v.name === nom) ?? {};
const base = trouveConfiguration(typescriptEslint.configs.strictTypeChecked, "typescript-eslint/base"); const base = findConfiguration(typescriptEslint.configs.strictTypeChecked, "typescript-eslint/base");
const desactivationsJavaScript = trouveConfiguration( const desactivationsJavaScript = findConfiguration(
typescriptEslint.configs.strictTypeChecked, typescriptEslint.configs.strictTypeChecked,
"typescript-eslint/eslint-recommended", "typescript-eslint/eslint-recommended",
); );
const strictTypeChecked = trouveConfiguration( const strictTypeChecked = findConfiguration(
typescriptEslint.configs.strictTypeChecked, typescriptEslint.configs.strictTypeChecked,
"typescript-eslint/strict-type-checked", "typescript-eslint/strict-type-checked",
); );
const stylisticTypeChecked = trouveConfiguration( const stylisticTypeChecked = findConfiguration(
typescriptEslint.configs.stylisticTypeChecked, typescriptEslint.configs.stylisticTypeChecked,
"typescript-eslint/stylistic-type-checked", "typescript-eslint/stylistic-type-checked",
); );
export const règlesTypeScript: Readonly<Linter.Config> = { export const typeScriptRules: Readonly<Linter.Config> = {
languageOptions: base.languageOptions ?? {}, languageOptions: base.languageOptions ?? {},
name: "TypeScript", name: "TypeScript",
plugins: base.plugins ?? {}, plugins: base.plugins ?? {},
@ -74,5 +74,11 @@ export const règlesTypeScript: Readonly<Linter.Config> = {
* @link [typescript-eslint](https://typescript-eslint.io/rules/no-unnecessary-type-parameters) * @link [typescript-eslint](https://typescript-eslint.io/rules/no-unnecessary-type-parameters)
*/ */
"@typescript-eslint/no-unnecessary-type-parameters": "off", "@typescript-eslint/no-unnecessary-type-parameters": "off",
/**
* Interdit de lever des exceptions avec des valeurs autres que `Error`. Semble déconner.
*
* @link [typescript-eslint](https://typescript-eslint.io/rules/only-throw-error/)
*/
"@typescript-eslint/only-throw-error": "off",
}, },
}; };

View file

@ -2,7 +2,7 @@ import type { Linter } from "eslint";
import unicorn from "eslint-plugin-unicorn"; import unicorn from "eslint-plugin-unicorn";
export const règlesUnicorn: Readonly<Linter.Config> = { export const unicornRules: Readonly<Linter.Config> = {
name: "Unicorn", name: "Unicorn",
plugins: { unicorn: unicorn }, plugins: { unicorn: unicorn },
rules: { rules: {

View file

@ -1,8 +0,0 @@
import type { Linter } from "eslint";
import oxlint from "eslint-plugin-oxlint";
export const règlesOxlint: Readonly<Linter.Config> = {
name: "Oxlint",
...oxlint.configs["flat/recommended"][0],
};

View file

@ -47,5 +47,5 @@
"verbatimModuleSyntax": true "verbatimModuleSyntax": true
}, },
"exclude": ["dist"], "exclude": ["dist"],
"include": ["**/*.js", "**/*.ts"] "include": ["**/*.js", "**/*.ts", "**/*.astro", "**/*.tsx"]
} }