/
githubmirror
/
eslint-plugin
Обзор
Документация
Войти
/
githubmirror
/
eslint-plugin
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
lib/rules/noStaticStylesAssignment.ts
146 строк
6 KB
saberzero1
refactor: streamline meta.docs.url for static analysis
10 июн 2026, 16:14
10 июн 2026, 16:14
13385bc
Код
Авторство
О чём код?
import { TSESTree } from "@typescript-eslint/utils"; import { docsUrl, ruleCreator } from "../ruleCreator.js"; // This rule will flag: // // - element.style.color = 'red' // - element.style.setProperty('color', 'red') // - element.style.cssText = 'color: red;' // - element.setAttribute('style', 'color: red;') // // This rule will not flag: // // - element.style.width = myWidth; (assignment from a variable) // - element.style.transform = `translateX(${offset}px)`; (assignment from a template literal with expressions) // Checks if a node is a MemberExpression accessing the 'style' property. // e.g., `el.style` or `this.containerEl.style` function isStyleMemberExpression( node: TSESTree.Node, ): node is TSESTree.MemberExpression { return ( node.type === TSESTree.AST_NODE_TYPES.MemberExpression && !node.computed && node.property.type === TSESTree.AST_NODE_TYPES.Identifier && node.property.name === "style" ); } export default ruleCreator({ meta: { type: "suggestion" as const, docs: { description: "Disallow setting styles directly on DOM elements, favoring CSS classes instead.", url: docsUrl("no-static-styles-assignment"), }, schema: [], messages: { avoidStyleAssignment: "Avoid setting styles directly via `{{property}}`. Use CSS classes for better theming and maintainability. Use the `setCssProps` function if the CSS properties need to change dynamically.", }, }, defaultOptions: [], create(context) { return { // Catches `el.style.color = 'red'` and `el.style.cssText = '...'` AssignmentExpression(node: TSESTree.AssignmentExpression) { const left = node.left; // We only care about static assignments (literals) if (node.right.type !== TSESTree.AST_NODE_TYPES.Literal) { return; } if ( left.type === TSESTree.AST_NODE_TYPES.MemberExpression && isStyleMemberExpression(left.object) ) { context.report({ node, messageId: "avoidStyleAssignment", data: { property: `element.style.${(left.property as TSESTree.Identifier).name}`, }, }); } }, // Catches `el.style.setProperty(...)` and `el.setAttribute('style', ...)` CallExpression(node: TSESTree.CallExpression) { const callee = node.callee; if (callee.type !== TSESTree.AST_NODE_TYPES.MemberExpression) { return; } const propertyName = (callee.property as TSESTree.Identifier) .name; // Case 1: `el.style.setProperty('color', 'red')` if ( propertyName === "setProperty" && isStyleMemberExpression(callee.object) ) { // Check if the second argument is a literal if ( node.arguments.length > 1 && node.arguments[1].type === TSESTree.AST_NODE_TYPES.Literal ) { context.report({ node, messageId: "avoidStyleAssignment", data: { property: "element.style.setProperty" }, }); } } // Case 2: `el.setAttribute('style', '...')` if (propertyName === "setAttribute") { if ( node.arguments.length > 1 && node.arguments[0].type === TSESTree.AST_NODE_TYPES.Literal && node.arguments[0].value === "style" && node.arguments[1].type === TSESTree.AST_NODE_TYPES.Literal ) { context.report({ node, messageId: "avoidStyleAssignment", data: { property: "element.setAttribute" }, }); } } // Case 3: `el.style.setCssProps({ 'color': 'blue' })` if ( propertyName === "setCssProps" && node.arguments[0].type === TSESTree.AST_NODE_TYPES.ObjectExpression ) { for (const property of node.arguments[0].properties) { if (property.type === TSESTree.AST_NODE_TYPES.Property && property.key.type === TSESTree.AST_NODE_TYPES.Literal && typeof property.key.value === 'string' && !property.key.value.startsWith('--')) { context.report({ node, messageId: "avoidStyleAssignment", data: { property: "el.setCssProps" }, }); break; } } } // Case 4: `el.style.setCssStyles({ 'color': 'blue' })` if ( propertyName === "setCssStyles" && node.arguments[0].type === TSESTree.AST_NODE_TYPES.ObjectExpression ) { for (const property of node.arguments[0].properties) { if (property.type === TSESTree.AST_NODE_TYPES.Property && property.key.type === TSESTree.AST_NODE_TYPES.Literal && typeof property.key.value === 'string' && !property.key.value.startsWith('--')) { context.report({ node, messageId: "avoidStyleAssignment", data: { property: "el.setCssStyles" }, }); break; } } } }, }; }, });