This commit is contained in:
gcch 2026-04-27 22:20:50 +02:00
commit 888eb4aa54
8 changed files with 564 additions and 414 deletions

2
dist/index.d.mts vendored
View file

@ -4,4 +4,4 @@ import { Linter } from "eslint";
declare const configTypescriptNavigateur: ReadonlyArray<Linter.Config>;
declare const configAstro: ReadonlyArray<Linter.Config>;
//#endregion
export { configAstro, configTypescriptNavigateur };
export { configAstro, configTypescriptNavigateur };

594
dist/index.mjs vendored
View file

@ -13,121 +13,154 @@ import unicorn from "eslint-plugin-unicorn";
//#region ../rules/astro.ts
const getAstroPlugin = () => {
const firstBaseConfig = astro.configs.base.at(0);
if (firstBaseConfig === void 0) throw new Error("Impossible de récupérer la configuration de base du plugin Astro.");
const astroPlugin = firstBaseConfig.plugins?.["astro"];
if (astroPlugin === void 0) throw new Error("Impossible de récupérer le plugin Astro.");
return astroPlugin;
const firstBaseConfig = astro.configs.base.at(0);
if (firstBaseConfig === void 0) throw new Error("Impossible de récupérer la configuration de base du plugin Astro.");
const astroPlugin = firstBaseConfig.plugins?.["astro"];
if (astroPlugin === void 0) throw new Error("Impossible de récupérer le plugin Astro.");
return astroPlugin;
};
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: 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",
},
];
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: 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",
},
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"],
},
name: "JavaScript",
rules: {
...javascript.configs.recommended.rules,
/**
* Impose la présence de déclarations `return` dans les _callbacks_ des méthodes `Array`.
*
* Il est autorisé ici l'usage de valeurs de retour en `void` et la vérification de valeurs de retour superflues
* pour `forEach()`.
*
* @link [ESLint](https://eslint.org/docs/latest/rules/array-callback-return)
*/
"array-callback-return": ["error", {
allowVoid: true,
checkForEach: true
}],
/** Surchargé par une meilleur version présente dans le plugin _Unicorn_. */
"no-nested-ternary": "off",
/**
* Interdit l'usage de variables lues sans être préalablement assignées.
*
* @link [ESLint](https://eslint.org/docs/latest/rules/no-unassigned-vars)
*/
"no-unassigned-vars": "error",
/**
* Interdit l'usage d'opérateurs ternaires quand des opérations plus simples existent. Cela inclut ici l'usage de
* ternaires comme opération d'assignation par défaut d'une valeur.
*
* @link [ESLint](https://eslint.org/docs/latest/rules/no-unneeded-ternary)
*/
"no-unneeded-ternary": ["error", { defaultAssignment: false }],
/**
* Interdit l'usage de boucles ne permettant qu'une seule itération. Par la nature de l'analyse statique de code,
* certains cas peuvent ne pas être détectées.
*
* @link [ESLint](https://eslint.org/docs/latest/rules/no-unreachable-loop)
*/
"no-unreachable-loop": "error",
/**
* Interdit l'utilisation d'une variable avant sa définition.
*
* La règle est désactivée ici pour que l'ordre de déclaration au sein d'un module n'ait pas d'importance.
*
* @link [ESLint](https://eslint.org/docs/latest/rules/no-use-before-define)
*/
"no-use-before-define": "off",
/**
* Interdit l'assignation de variables non utilisées. Par la nature de l'analyse statique de code, certains cas
* peuvent ne pas être détectées.
*
* @link [ESLint](https://eslint.org/docs/latest/rules/no-useless-assignment)
*/
"no-useless-assignment": "error",
/**
* Interdit ici l'usage de conditions « [Yoda](https://en.wikipedia.org/wiki/Yoda_conditions) » pour des soucis de
* lisibilité du code.
*
* @link [ESLint](https://eslint.org/docs/latest/rules/yoda)
*/
yoda: ["error", "never"]
}
};
//#endregion
@ -135,137 +168,282 @@ const javascriptRules = {
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",
},
name: "JSDoc",
plugins: flatRecommended.plugins ?? {},
rules: {
...flatRecommended.rules,
...flatStylistic.rules,
/**
* Vérifie que l'indentation au sein des blocs _JSDoc_ est cohérente.
*
* @link [GitHub](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-indentation.md)
*/
"jsdoc/check-indentation": "warn",
/**
* TODO: Finir la description.
*
* @link [GitHub](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-line-alignment.md)
*/
"jsdoc/check-line-alignment": "warn",
/**
* TODO: Finir la description.
*
* @link [GitHub](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/check-tag-names.md)
*/
"jsdoc/check-tag-names": ["warn", { definedTags: ["link"] }],
/**
* TODO: Finir la description
*
* @link [GitHub](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/lines-before-block.md)
*/
"jsdoc/lines-before-block": "off",
/**
* TODO: Finir la description.
*
* @link [GitHub](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-blank-block-descriptions.md)
*/
"jsdoc/no-blank-block-descriptions": "warn",
/**
* TODO: Finir la description.
*
* @link [GitHub](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/no-blank-blocks.md)
*/
"jsdoc/no-blank-blocks": "warn",
/**
* TODO: Finir la description.
*
* @link [GitHub](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-hyphen-before-param-description.md)
*/
"jsdoc/require-hyphen-before-param-description": ["warn", "never"],
/**
* TODO: Finir la description.
*
* @link [GitHub](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/require-throws.md)
*/
"jsdoc/require-throws": "warn",
/**
* TODO: Finir la description.
*
* @link [GitHub](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/sort-tags.md)
*/
"jsdoc/sort-tags": "warn",
/**
* Impose la présence de lignes (ou non) entre les _tags_.
*
* Désactivé ici car elle rentre en conflit avec l'extension _Prettier_ pour _JSDoc_.
*
* @link [GitHub](https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/rules/tag-lines.md)
*/
"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",
},
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 ?? {},
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 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",
"@typescript-eslint/only-throw-error": "off",
},
languageOptions: base.languageOptions ?? {},
name: "TypeScript",
plugins: base.plugins ?? {},
rules: {
...desactivationsJavaScript.rules,
...strictTypeChecked.rules,
...stylisticTypeChecked.rules,
/**
* Impose un usage consistant entre interfaces et types. Ici préfère les déclarations de types.
*
* @link [typescript-eslint](https://typescript-eslint.io/rules/consistent-type-definitions)
*/
"@typescript-eslint/consistent-type-definitions": ["error", "type"],
/**
* Interdit la définition de fonctions avec plus de 3 paramètres.
*
* @link [typescript-eslint](https://eslint.org/docs/latest/rules/max-params)
*/
"@typescript-eslint/max-params": ["error", { max: 3 }],
/**
* Impose une syntaxe particulière pour les signatures de méthodes au sein d'interfaces et types. Ici utilise la
* syntaxe « propriété ».
*
* ```typescript
* interface Exemple {
* func: (arg: string) => number;
* }
* ```
*
* @link [typescript-eslint](https://typescript-eslint.io/rules/method-signature-style/)
*/
"@typescript-eslint/method-signature-style": ["off", "property"],
/**
* Interdit l'usage de nombres magiques. Cette règle étend
* [no-magic-numbers](https://eslint.org/docs/latest/rules/no-magic-numbers) de la configuration de base _ESLint_.
*
* @link [typescript-eslint](https://eslint.org/docs/latest/rules/no-magic-numbers)
*/
"@typescript-eslint/no-magic-numbers": "off",
/**
* Autorise ici la comparaison avec des littéraux booléens. La désactivation de cette règle permet des comparaisons
* plus claires qu'avec l'opérateur de négation `!`.
*
* @link [typescript-eslint](https://typescript-eslint.io/rules/no-unnecessary-boolean-literal-compare)
*/
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "off",
/**
* Interdit l'usage de paramètres de types non utilisés plusieurs fois. Désactivé ici à cause de faux positifs.
*
* @link [typescript-eslint](https://typescript-eslint.io/rules/no-unnecessary-type-parameters)
*/
"@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"
}
};
//#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",
},
name: "Unicorn",
plugins: { unicorn },
rules: {
...unicorn.configs.unopinionated.rules,
/**
* Impose un nom de paramètre spécifique dans les clauses de capture des Erreurs.
*
* @link [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/catch-error-name.md)
*/
"unicorn/catch-error-name": "error",
/**
* Préfère des types consistants lors de l'étalage d'un tableau de littéraux au sein d'une condition ternaire.
*
* @link [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/consistent-empty-array-spread.md)
*/
"unicorn/consistent-empty-array-spread": "error",
/**
* Impose l'unique manière valide d'étendre la classe `Error`.
*
* @link [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/custom-error-definition.md)
*/
"unicorn/custom-error-definition": "error",
/**
* Impose la comparaison explicite de propriétés `length` ou `size`. Cela inclut ici l'obligation de vérifier
* qu'elles ne correspondent pas à `0` avec `!==`.
*
* @link [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/explicit-length-check.md)
*/
"unicorn/explicit-length-check": ["error", { "non-zero": "not-equal" }],
/**
* Autorise ici l'usage de la méthode `forEach()` des tableaux.
*
* Je préfère cette méthode (ou celle de la librairie _Effect_) aux boucles.
*
* @link [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-for-each.md)
*/
"unicorn/no-array-for-each": "off",
/**
* Autorise ici l'usage de la méthode `reduce()` des tableaux.
*
* J'utilise occasionnellement cette méthode pour des opérations simples.
*
* @link [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-array-for-each.md)
*/
"unicorn/no-array-reduce": "off",
/**
* Interdit l'usage de conditions négatives pour la clarté du code.
*
* @link [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-negated-condition.md)
*/
"unicorn/no-negated-condition": "error",
/**
* Interdit l'usage d'opérateurs ternaires imbriqués. Cette règle remplace celle présente par défaut dans _ESLint_
* avec le même nom.
*
* @link [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-nested-ternary.md)
*/
"unicorn/no-nested-ternary": "error",
/**
* Interdit l'usage de `null`.
*
* @link [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/no-null.md)
*/
"unicorn/no-null": "error",
/**
* N'impose pas ici l'usage de `.dataset` pour l'interaction avec les attributs d'Éléments DOM.
*
* L'ergonomie est réduite comparée aux méthodes `{get,has,set,remove}Attribute()`.
*
* @link [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-dom-node-dataset.md)
*/
"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,
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 };
export { configAstro, configTypescriptNavigateur };