@addon24/eslint-config
Version:
ESLint configuration rules for WorldOfTextcraft projects - Centralized configuration for all project types
136 lines (120 loc) • 5.29 kB
JavaScript
/**
* ESLint-Regel, die die Verwendung von MUI-Button statt unserer eigenen Button-Komponente prüft
*/
const noMuiButtonRule = {
meta: {
type: "suggestion",
docs: {
description: "Verbietet die direkte Verwendung von MUI-Button",
category: "Best Practices",
recommended: true,
},
fixable: "code",
messages: {
noMuiButton: "Bitte verwende die eigene Button-Komponente aus '@/components/UI/Button' statt der MUI-Button-Komponente.",
noMuiButtonImport: "Bitte verwende die eigene Button-Komponente aus '@/components/UI/Button' statt der MUI-Button-Komponente.",
},
},
create(context) {
// Speichert Material-UI Button Importe
const muiButtonImports = new Set();
return {
// Prüft alle Import-Deklarationen
ImportDeclaration(node) {
// Überprüft, ob aus @mui/material importiert wird
if (node.source.value === "@mui/material" || node.source.value === "@material-ui/core") {
// Überprüft alle Importe aus diesem Modul
node.specifiers.forEach((specifier) => {
// Wenn Button importiert wird
if (
(specifier.type === "ImportSpecifier" && specifier.imported && specifier.imported.name === "Button") ||
(specifier.type === "ImportDefaultSpecifier" && specifier.local.name === "Button")
) {
// Speichert den lokalen Namen des importierten Buttons
muiButtonImports.add(specifier.local.name);
context.report({
node,
messageId: "noMuiButtonImport",
fix(fixer) {
// Entfernt Button aus dem Import
// Behandelt verschiedene Fälle, je nachdem wie der Import aussieht
// Fall 1: Einziger Import aus @mui/material
if (node.specifiers.length === 1) {
return fixer.remove(node);
}
// Fall 2: Benannter Import in geschweiften Klammern
if (specifier.type === "ImportSpecifier") {
const importText = context.getSourceCode().getText(node);
const buttonPattern = specifier.local.name === "Button"
? "Button" // Direkter Import: import { Button } from "@mui/material"
: `Button as ${specifier.local.name}`; // Alias Import: import { Button as MuiButton } from "@mui/material"
// Entfernt nur Button aus der Import-Liste
if (importText.includes(`, ${buttonPattern}`)) {
return fixer.replaceText(node, importText.replace(`, ${buttonPattern}`, ""));
} else if (importText.includes(`${buttonPattern}, `)) {
return fixer.replaceText(node, importText.replace(`${buttonPattern}, `, ""));
} else if (importText.includes(`{ ${buttonPattern} }`)) {
return fixer.remove(node);
}
}
return null;
}
});
}
});
}
},
// Prüft alle JSX-Elemente
JSXOpeningElement(node) {
// Wenn ein Element mit dem Namen "Button" gefunden wird
if (node.name.type === "JSXIdentifier" && node.name.name === "Button") {
// Prüfe anhand des Scopes, ob dieser Button aus @mui/material stammt
const scope = context.getScope();
let currentScope = scope;
// Durchsuche alle Scopes nach dem Button-Variablennamen
while (currentScope) {
const buttonVar = currentScope.variables.find(v => v.name === "Button");
if (buttonVar) {
// Prüfe jede Definition der Button-Variable
for (const def of buttonVar.defs) {
// Wenn es sich um einen Import handelt
if (def.type === "ImportBinding" && def.parent && def.parent.source) {
const importSource = def.parent.source.value;
// Wenn der Import von @mui/material oder @material-ui/core stammt
if (importSource === "@mui/material" || importSource === "@material-ui/core") {
context.report({
node,
messageId: "noMuiButton",
});
return;
}
}
}
// Wenn wir eine Definition gefunden haben, aber sie ist nicht von MUI,
// dann brechen wir die Suche ab (überschreibende Variable gefunden)
break;
}
// Zum übergeordneten Scope wechseln
currentScope = currentScope.upper;
}
// Außerdem prüfen wir anhand unserer Liste von MUI-Button-Importen
if (muiButtonImports.has("Button")) {
context.report({
node,
messageId: "noMuiButton",
});
}
}
},
// Am Ende der Datei werden die gesammelten Informationen zurückgesetzt
"Program:exit": function() {
muiButtonImports.clear();
}
};
}
};
export default {
rules: {
"no-mui-button": noMuiButtonRule
}
};