/
githubmirror
/
eslint-plugin
Обзор
Документация
Войти
/
githubmirror
/
eslint-plugin
Код
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
lib/rules/preferActiveDoc.ts
114 строк
4 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"; const REPLACEMENTS: Record<string, string> = { document: "activeDocument", }; const WINDOW_TIMER_METHODS = new Set([ "clearInterval", "clearTimeout", "requestAnimationFrame", "setInterval", "setTimeout", ]); export default ruleCreator({ meta: { type: "suggestion" as const, docs: { description: "Prefer `activeDocument` over `document` for popout window compatibility.", url: docsUrl("prefer-active-doc"), }, schema: [], fixable: undefined, messages: { preferActive: "Use '{{replacement}}' instead of '{{original}}' for popout window compatibility.", }, }, defaultOptions: [], create(context) { return { Identifier(node: TSESTree.Identifier) { if (!Object.hasOwn(REPLACEMENTS, node.name)) { return; } const replacement = REPLACEMENTS[node.name]; if (!replacement) { return; } // Skip if this is a property access (e.g., `obj.document`) if ( node.parent.type === TSESTree.AST_NODE_TYPES.MemberExpression && node.parent.property === node ) { return; } // Skip if this is a property key in an object literal if ( node.parent.type === TSESTree.AST_NODE_TYPES.Property && node.parent.key === node ) { return; } // Skip if this is a declaration (variable, function param, etc.) if ( node.parent.type === TSESTree.AST_NODE_TYPES.VariableDeclarator && node.parent.id === node ) { return; } // Skip typeof expressions (typeof window === 'undefined') if (node.parent.type === TSESTree.AST_NODE_TYPES.UnaryExpression && node.parent.operator === "typeof") { return; } // Skip window.setTimeout/clearTimeout/setInterval/clearInterval — timer functions should use window, not activeWindow if ( node.name === "window" && node.parent.type === TSESTree.AST_NODE_TYPES.MemberExpression && node.parent.object === node && node.parent.property.type === TSESTree.AST_NODE_TYPES.Identifier && WINDOW_TIMER_METHODS.has(node.parent.property.name) ) { return; } // Check scope: only flag global references, not local variables named document/window const scope = context.sourceCode.getScope(node); const variable = findVariable(scope, node.name); if (variable && variable.defs.length > 0) { return; } context.report({ node, messageId: "preferActive", data: { original: node.name, replacement, }, }); }, }; function findVariable(scope: ReturnType<typeof context.sourceCode.getScope>, name: string): { defs: unknown[] } | null { let current: typeof scope | null = scope; while (current) { const variable = current.variables.find((v) => v.name === name); if (variable) { return variable; } current = current.upper; } return null; } }, });