diff --git a/README.md b/README.md index 296b396..4cb4eee 100644 --- a/README.md +++ b/README.md @@ -95,55 +95,54 @@ You can also override or add rules: πŸ’Ό Configurations enabled in.\ ⚠️ Configurations set to warn in.\ -🚫 Configurations disabled in.\ βœ… Set in the `recommended` configuration.\ πŸ‡¬πŸ‡§ Set in the `recommendedWithLocalesEn` configuration.\ πŸ”§ Automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/user-guide/command-line-interface#--fix).\ πŸ’‘ Manually fixable by [editor suggestions](https://eslint.org/docs/latest/use/core-concepts#rule-suggestions). -| NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  | Description | πŸ’Ό | ⚠️ | 🚫 | πŸ”§ | πŸ’‘ | -| :----------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- | :----- | :----- | :----- | :- | :- | -| [commands/no-command-in-command-id](docs/rules/commands/no-command-in-command-id.md) | Disallow using the word 'command' in a command ID. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [commands/no-command-in-command-name](docs/rules/commands/no-command-in-command-name.md) | Disallow using the word 'command' in a command name. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [commands/no-default-hotkeys](docs/rules/commands/no-default-hotkeys.md) | Discourage providing default hotkeys for commands. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [commands/no-plugin-id-in-command-id](docs/rules/commands/no-plugin-id-in-command-id.md) | Disallow including the plugin ID in a command ID. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [commands/no-plugin-name-in-command-name](docs/rules/commands/no-plugin-name-in-command-name.md) | Disallow including the plugin name in a command name. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [detach-leaves](docs/rules/detach-leaves.md) | Don't detach leaves in onunload. | βœ… πŸ‡¬πŸ‡§ | | | πŸ”§ | | -| [editor-drop-paste](docs/rules/editor-drop-paste.md) | Require checking `evt.defaultPrevented` and calling `evt.preventDefault()` in editor-drop/editor-paste handlers. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [hardcoded-config-path](docs/rules/hardcoded-config-path.md) | Disallow hardcoded `.obsidian` config paths. Use `Vault#configDir` instead. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [no-forbidden-elements](docs/rules/no-forbidden-elements.md) | Disallow attachment of forbidden elements to the DOM in Obsidian plugins. | βœ… πŸ‡¬πŸ‡§ | | | | | -| [no-global-this](docs/rules/no-global-this.md) | Disallow `global` and `globalThis`. Use `window` or `activeWindow` for popout window compatibility. | | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | | -| [no-nodejs-modules](docs/rules/no-nodejs-modules.md) | Disallow importing Node.js built-in modules unless guarded by Platform.isDesktop | | βœ… πŸ‡¬πŸ‡§ | | | | -| [no-plugin-as-component](docs/rules/no-plugin-as-component.md) | Disallow anti-patterns when passing a component to MarkdownRenderer.render to prevent memory leaks. | βœ… πŸ‡¬πŸ‡§ | | | | | -| [no-sample-code](docs/rules/no-sample-code.md) | Disallow sample code snippets from the Obsidian plugin template. | βœ… πŸ‡¬πŸ‡§ | | | πŸ”§ | | -| [no-static-styles-assignment](docs/rules/no-static-styles-assignment.md) | Disallow setting styles directly on DOM elements, favoring CSS classes instead. | βœ… πŸ‡¬πŸ‡§ | | | | | -| [no-tfile-tfolder-cast](docs/rules/no-tfile-tfolder-cast.md) | Disallow type casting to TFile or TFolder, suggesting instanceof checks instead. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [no-unsupported-api](docs/rules/no-unsupported-api.md) | Disallow usage of Obsidian APIs not available in the plugin's minimum app version | βœ… πŸ‡¬πŸ‡§ | | | | | -| [no-view-references-in-plugin](docs/rules/no-view-references-in-plugin.md) | Disallow storing references to custom views directly in the plugin, which can cause memory leaks. | βœ… πŸ‡¬πŸ‡§ | | | | | -| [object-assign](docs/rules/object-assign.md) | Discourage using `Object.assign` with two arguments | | βœ… πŸ‡¬πŸ‡§ | | | | -| [platform](docs/rules/platform.md) | Disallow use of navigator API for OS detection | βœ… πŸ‡¬πŸ‡§ | | | | | -| [prefer-abstract-input-suggest](docs/rules/prefer-abstract-input-suggest.md) | Disallow Liam's frequently copied `TextInputSuggest` implementation in favor of the built-in `AbstractInputSuggest`. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [prefer-active-doc](docs/rules/prefer-active-doc.md) | Prefer `activeDocument` over `document` for popout window compatibility. | | | βœ… πŸ‡¬πŸ‡§ | | | -| [prefer-create-el](docs/rules/prefer-create-el.md) | Prefer Obsidian DOM helpers (`createEl`, `createDiv`, `createSpan`, `createSvg`, `createFragment`) over native DOM methods. | | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | πŸ’‘ | -| [prefer-file-manager-trash-file](docs/rules/prefer-file-manager-trash-file.md) | Prefer FileManager.trashFile() over Vault.trash() or Vault.delete() to respect user settings. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [prefer-get-language](docs/rules/prefer-get-language.md) | Prefer Obsidian's `getLanguage()` over `localStorage.getItem('language')` and `i18next-browser-languagedetector` for detecting the user's language. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [prefer-instanceof](docs/rules/prefer-instanceof.md) | Prefer `.instanceOf(T)` over `instanceof T` for cross-window safe type checks on DOM Nodes and UIEvents. | | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | πŸ’‘ | -| [prefer-window-timers](docs/rules/prefer-window-timers.md) | Prefer `window.setTimeout()` and related timer functions over bare global calls for popout window compatibility. | | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | | -| [regex-lookbehind](docs/rules/regex-lookbehind.md) | Using lookbehinds in Regex is not supported in some iOS versions | βœ… πŸ‡¬πŸ‡§ | | | | | -| [rule-custom-message](docs/rules/rule-custom-message.md) | Allows redefining error messages from other ESLint rules that don't provide this functionality natively. | βœ… πŸ‡¬πŸ‡§ | | | | | -| [sample-names](docs/rules/sample-names.md) | Rename sample plugin class names | βœ… πŸ‡¬πŸ‡§ | | | | | -| [settings-tab/no-deprecated-display](docs/rules/settings-tab/no-deprecated-display.md) | Disallow a leftover display() method on PluginSettingTab subclasses once getSettingDefinitions() is implemented and minAppVersion is 1.13.0 or later. | | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | | -| [settings-tab/no-manual-html-headings](docs/rules/settings-tab/no-manual-html-headings.md) | Disallow using HTML heading elements for settings headings. | βœ… πŸ‡¬πŸ‡§ | | | πŸ”§ | | -| [settings-tab/no-problematic-settings-headings](docs/rules/settings-tab/no-problematic-settings-headings.md) | Discourage anti-patterns in settings headings. | βœ… πŸ‡¬πŸ‡§ | | | πŸ”§ | | -| [settings-tab/prefer-setting-definitions](docs/rules/settings-tab/prefer-setting-definitions.md) | Encourage PluginSettingTab subclasses to implement getSettingDefinitions() so settings appear in Obsidian 1.13+ settings search. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [settings-tab/prefer-update-over-display](docs/rules/settings-tab/prefer-update-over-display.md) | Prefer this.update() over this.display() to refresh a PluginSettingTab on Obsidian 1.13+. | | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | | -| [settings-tab/require-display](docs/rules/settings-tab/require-display.md) | Require a display() method on PluginSettingTab subclasses when minAppVersion is below 1.13.0. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [ui/sentence-case](docs/rules/ui/sentence-case.md) | Enforce sentence case for UI strings | | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | | -| [ui/sentence-case-json](docs/rules/ui/sentence-case-json.md) | Enforce sentence case for English JSON locale strings | | πŸ‡¬πŸ‡§ | | πŸ”§ | | -| [ui/sentence-case-locale-module](docs/rules/ui/sentence-case-locale-module.md) | Enforce sentence case for English TS/JS locale module strings | | πŸ‡¬πŸ‡§ | | πŸ”§ | | -| [validate-license](docs/rules/validate-license.md) | Validate the structure of copyright notices in LICENSE files for Obsidian plugins. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [validate-manifest](docs/rules/validate-manifest.md) | Validate the structure of manifest.json for Obsidian plugins. | | βœ… πŸ‡¬πŸ‡§ | | | | -| [vault/iterate](docs/rules/vault/iterate.md) | Avoid iterating all files to find a file by its path | | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | | +| NameΒ Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β Β  | Description | πŸ’Ό | ⚠️ | πŸ”§ | πŸ’‘ | +| :----------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------- | :----- | :----- | :- | :- | +| [commands/no-command-in-command-id](docs/rules/commands/no-command-in-command-id.md) | Disallow using the word 'command' in a command ID. | | βœ… πŸ‡¬πŸ‡§ | | | +| [commands/no-command-in-command-name](docs/rules/commands/no-command-in-command-name.md) | Disallow using the word 'command' in a command name. | | βœ… πŸ‡¬πŸ‡§ | | | +| [commands/no-default-hotkeys](docs/rules/commands/no-default-hotkeys.md) | Discourage providing default hotkeys for commands. | | βœ… πŸ‡¬πŸ‡§ | | | +| [commands/no-plugin-id-in-command-id](docs/rules/commands/no-plugin-id-in-command-id.md) | Disallow including the plugin ID in a command ID. | | βœ… πŸ‡¬πŸ‡§ | | | +| [commands/no-plugin-name-in-command-name](docs/rules/commands/no-plugin-name-in-command-name.md) | Disallow including the plugin name in a command name. | | βœ… πŸ‡¬πŸ‡§ | | | +| [detach-leaves](docs/rules/detach-leaves.md) | Don't detach leaves in onunload. | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | | +| [editor-drop-paste](docs/rules/editor-drop-paste.md) | Require checking `evt.defaultPrevented` and calling `evt.preventDefault()` in editor-drop/editor-paste handlers. | | βœ… πŸ‡¬πŸ‡§ | | | +| [hardcoded-config-path](docs/rules/hardcoded-config-path.md) | Disallow hardcoded `.obsidian` config paths. Use `Vault#configDir` instead. | | βœ… πŸ‡¬πŸ‡§ | | | +| [no-forbidden-elements](docs/rules/no-forbidden-elements.md) | Disallow attachment of forbidden elements to the DOM in Obsidian plugins. | βœ… πŸ‡¬πŸ‡§ | | | | +| [no-global-this](docs/rules/no-global-this.md) | Disallow `global` and `globalThis`. Use `window` or `activeWindow` for popout window compatibility. | | βœ… πŸ‡¬πŸ‡§ | πŸ”§ | | +| [no-nodejs-modules](docs/rules/no-nodejs-modules.md) | Disallow importing Node.js built-in modules unless guarded by Platform.isDesktop | | βœ… πŸ‡¬πŸ‡§ | | | +| [no-plugin-as-component](docs/rules/no-plugin-as-component.md) | Disallow anti-patterns when passing a component to MarkdownRenderer.render to prevent memory leaks. | βœ… πŸ‡¬πŸ‡§ | | | | +| [no-sample-code](docs/rules/no-sample-code.md) | Disallow sample code snippets from the Obsidian plugin template. | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | | +| [no-static-styles-assignment](docs/rules/no-static-styles-assignment.md) | Disallow setting styles directly on DOM elements, favoring CSS classes instead. | βœ… πŸ‡¬πŸ‡§ | | | | +| [no-tfile-tfolder-cast](docs/rules/no-tfile-tfolder-cast.md) | Disallow type casting to TFile or TFolder, suggesting instanceof checks instead. | | βœ… πŸ‡¬πŸ‡§ | | | +| [no-unsupported-api](docs/rules/no-unsupported-api.md) | Disallow usage of Obsidian APIs not available in the plugin's minimum app version | βœ… πŸ‡¬πŸ‡§ | | | | +| [no-view-references-in-plugin](docs/rules/no-view-references-in-plugin.md) | Disallow storing references to custom views directly in the plugin, which can cause memory leaks. | βœ… πŸ‡¬πŸ‡§ | | | | +| [object-assign](docs/rules/object-assign.md) | Discourage using `Object.assign` with two arguments | | βœ… πŸ‡¬πŸ‡§ | | | +| [platform](docs/rules/platform.md) | Disallow use of navigator API for OS detection | βœ… πŸ‡¬πŸ‡§ | | | | +| [prefer-abstract-input-suggest](docs/rules/prefer-abstract-input-suggest.md) | Disallow Liam's frequently copied `TextInputSuggest` implementation in favor of the built-in `AbstractInputSuggest`. | | βœ… πŸ‡¬πŸ‡§ | | | +| [prefer-active-doc](docs/rules/prefer-active-doc.md) | Prefer `activeDocument` over `document` for popout window compatibility. | | βœ… πŸ‡¬πŸ‡§ | | | +| [prefer-create-el](docs/rules/prefer-create-el.md) | Prefer Obsidian DOM helpers (`createEl`, `createDiv`, `createSpan`, `createSvg`, `createFragment`) over native DOM methods. | | βœ… πŸ‡¬πŸ‡§ | πŸ”§ | πŸ’‘ | +| [prefer-file-manager-trash-file](docs/rules/prefer-file-manager-trash-file.md) | Prefer FileManager.trashFile() over Vault.trash() or Vault.delete() to respect user settings. | | βœ… πŸ‡¬πŸ‡§ | | | +| [prefer-get-language](docs/rules/prefer-get-language.md) | Prefer Obsidian's `getLanguage()` over `localStorage.getItem('language')` and `i18next-browser-languagedetector` for detecting the user's language. | | βœ… πŸ‡¬πŸ‡§ | | | +| [prefer-instanceof](docs/rules/prefer-instanceof.md) | Prefer `.instanceOf(T)` over `instanceof T` for cross-window safe type checks on DOM Nodes and UIEvents. | | βœ… πŸ‡¬πŸ‡§ | πŸ”§ | πŸ’‘ | +| [prefer-window-timers](docs/rules/prefer-window-timers.md) | Prefer `window.setTimeout()` and related timer functions over bare global calls for popout window compatibility. | | βœ… πŸ‡¬πŸ‡§ | πŸ”§ | | +| [regex-lookbehind](docs/rules/regex-lookbehind.md) | Using lookbehinds in Regex is not supported in some iOS versions | βœ… πŸ‡¬πŸ‡§ | | | | +| [rule-custom-message](docs/rules/rule-custom-message.md) | Allows redefining error messages from other ESLint rules that don't provide this functionality natively. | βœ… πŸ‡¬πŸ‡§ | | | | +| [sample-names](docs/rules/sample-names.md) | Rename sample plugin class names | βœ… πŸ‡¬πŸ‡§ | | | | +| [settings-tab/no-deprecated-display](docs/rules/settings-tab/no-deprecated-display.md) | Disallow a leftover display() method on PluginSettingTab subclasses once getSettingDefinitions() is implemented and minAppVersion is 1.13.0 or later. | | βœ… πŸ‡¬πŸ‡§ | πŸ”§ | | +| [settings-tab/no-manual-html-headings](docs/rules/settings-tab/no-manual-html-headings.md) | Disallow using HTML heading elements for settings headings. | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | | +| [settings-tab/no-problematic-settings-headings](docs/rules/settings-tab/no-problematic-settings-headings.md) | Discourage anti-patterns in settings headings. | βœ… πŸ‡¬πŸ‡§ | | πŸ”§ | | +| [settings-tab/prefer-setting-definitions](docs/rules/settings-tab/prefer-setting-definitions.md) | Encourage PluginSettingTab subclasses to implement getSettingDefinitions() so settings appear in Obsidian 1.13+ settings search. | | βœ… πŸ‡¬πŸ‡§ | | | +| [settings-tab/prefer-update-over-display](docs/rules/settings-tab/prefer-update-over-display.md) | Prefer this.update() over this.display() to refresh a PluginSettingTab on Obsidian 1.13+. | | βœ… πŸ‡¬πŸ‡§ | πŸ”§ | | +| [settings-tab/require-display](docs/rules/settings-tab/require-display.md) | Require a display() method on PluginSettingTab subclasses when minAppVersion is below 1.13.0. | | βœ… πŸ‡¬πŸ‡§ | | | +| [ui/sentence-case](docs/rules/ui/sentence-case.md) | Enforce sentence case for UI strings | | βœ… πŸ‡¬πŸ‡§ | πŸ”§ | | +| [ui/sentence-case-json](docs/rules/ui/sentence-case-json.md) | Enforce sentence case for English JSON locale strings | | πŸ‡¬πŸ‡§ | πŸ”§ | | +| [ui/sentence-case-locale-module](docs/rules/ui/sentence-case-locale-module.md) | Enforce sentence case for English TS/JS locale module strings | | πŸ‡¬πŸ‡§ | πŸ”§ | | +| [validate-license](docs/rules/validate-license.md) | Validate the structure of copyright notices in LICENSE files for Obsidian plugins. | | βœ… πŸ‡¬πŸ‡§ | | | +| [validate-manifest](docs/rules/validate-manifest.md) | Validate the structure of manifest.json for Obsidian plugins. | | βœ… πŸ‡¬πŸ‡§ | | | +| [vault/iterate](docs/rules/vault/iterate.md) | Avoid iterating all files to find a file by its path | | βœ… πŸ‡¬πŸ‡§ | πŸ”§ | | diff --git a/docs/rules/prefer-active-doc.md b/docs/rules/prefer-active-doc.md index e145bd9..9704624 100644 --- a/docs/rules/prefer-active-doc.md +++ b/docs/rules/prefer-active-doc.md @@ -2,6 +2,6 @@ πŸ“ Prefer `activeDocument` over `document` for popout window compatibility. -🚫 This rule is _disabled_ in the following configs: βœ… `recommended`, πŸ‡¬πŸ‡§ `recommendedWithLocalesEn`. +⚠️ This rule _warns_ in the following configs: βœ… `recommended`, πŸ‡¬πŸ‡§ `recommendedWithLocalesEn`. diff --git a/lib/index.ts b/lib/index.ts index f543241..746b79c 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -163,7 +163,7 @@ const recommendedPluginRulesConfigBase: RulesConfig = { "obsidianmd/prefer-get-language": "warn", "obsidianmd/prefer-abstract-input-suggest": "warn", "obsidianmd/prefer-window-timers": "warn", - "obsidianmd/prefer-active-doc": "off", + "obsidianmd/prefer-active-doc": "warn", "obsidianmd/regex-lookbehind": "error", "obsidianmd/sample-names": "error", "obsidianmd/validate-manifest": "warn", diff --git a/lib/rules/preferActiveDoc.ts b/lib/rules/preferActiveDoc.ts index 170f3c5..e52d08f 100644 --- a/lib/rules/preferActiveDoc.ts +++ b/lib/rules/preferActiveDoc.ts @@ -41,6 +41,11 @@ export default ruleCreator({ return; } + // Skip identifiers in type-level constructs (interfaces, type aliases, type annotations, etc.) + if (isInTypeContext(node)) { + return; + } + // Skip if this is a property access (e.g., `obj.document`) if ( node.parent.type === TSESTree.AST_NODE_TYPES.MemberExpression && @@ -70,6 +75,34 @@ export default ruleCreator({ return; } + // Skip class property/method declarations (key position) + if ( + (node.parent.type === TSESTree.AST_NODE_TYPES.PropertyDefinition || + node.parent.type === TSESTree.AST_NODE_TYPES.MethodDefinition) && + node.parent.key === node + ) { + return; + } + + // Skip enum member names (but NOT initializers β€” enum initializers are runtime code) + if ( + node.parent.type === TSESTree.AST_NODE_TYPES.TSEnumMember && + node.parent.id === node + ) { + return; + } + + // Skip labeled statements and break/continue label references + if ( + (node.parent.type === TSESTree.AST_NODE_TYPES.LabeledStatement && + node.parent.label === node) || + ((node.parent.type === TSESTree.AST_NODE_TYPES.BreakStatement || + node.parent.type === TSESTree.AST_NODE_TYPES.ContinueStatement) && + node.parent.label === node) + ) { + return; + } + // Skip window.setTimeout/clearTimeout/setInterval/clearInterval β€” timer functions should use window, not activeWindow if ( node.name === "window" && @@ -110,5 +143,34 @@ export default ruleCreator({ } return null; } + + function isInTypeContext(node: TSESTree.Node): boolean { + let current: TSESTree.Node | undefined = node.parent; + while (current) { + switch (current.type) { + case TSESTree.AST_NODE_TYPES.TSTypeAnnotation: + case TSESTree.AST_NODE_TYPES.TSTypeQuery: + case TSESTree.AST_NODE_TYPES.TSQualifiedName: + case TSESTree.AST_NODE_TYPES.TSPropertySignature: + case TSESTree.AST_NODE_TYPES.TSMethodSignature: + case TSESTree.AST_NODE_TYPES.TSIndexSignature: + case TSESTree.AST_NODE_TYPES.TSTypeLiteral: + case TSESTree.AST_NODE_TYPES.TSInterfaceBody: + case TSESTree.AST_NODE_TYPES.TSInterfaceDeclaration: + case TSESTree.AST_NODE_TYPES.TSTypeAliasDeclaration: + case TSESTree.AST_NODE_TYPES.TSTypeReference: + case TSESTree.AST_NODE_TYPES.TSMappedType: + case TSESTree.AST_NODE_TYPES.TSConditionalType: + case TSESTree.AST_NODE_TYPES.TSTypeParameterDeclaration: + case TSESTree.AST_NODE_TYPES.TSTypeParameterInstantiation: + case TSESTree.AST_NODE_TYPES.TSModuleDeclaration: + return true; + default: + break; + } + current = current.parent; + } + return false; + } }, }); diff --git a/tests/preferActiveDoc.test.ts b/tests/preferActiveDoc.test.ts index 5a74a36..24c438e 100644 --- a/tests/preferActiveDoc.test.ts +++ b/tests/preferActiveDoc.test.ts @@ -77,6 +77,66 @@ ruleTester.run("prefer-active-doc", preferActiveDocRule, { name: "window.requestAnimationFrame is allowed", code: "window.requestAnimationFrame(() => {});", }, + { + name: "interface property named document is allowed", + code: "interface Foo { document: string; }", + }, + { + name: "typeof property access in type position is allowed", + code: "let html: ReturnType | null = null;", + }, + { + name: "type alias property named document is allowed", + code: "type Foo = { document: string; };", + }, + { + name: "interface method named document is allowed", + code: "interface Foo { document(): void; }", + }, + { + name: "class property named document is allowed", + code: "class Foo { document: string = ''; }", + }, + { + name: "class method named document is allowed", + code: "class Foo { document() { return ''; } }", + }, + { + name: "enum member named document is allowed", + code: "enum Foo { document = 'doc' }", + }, + { + name: "document in type annotation is allowed", + code: "const x: { document: string } = { document: '' };", + }, + { + name: "document in index signature is allowed", + code: "interface Foo { [document: string]: number; }", + }, + { + name: "function parameter named document is allowed", + code: "function foo(document: Document) { document.title; }", + }, + { + name: "destructured document is allowed", + code: "const { document } = someObj;", + }, + { + name: "for-of binding named document is allowed", + code: "for (const document of docs) { document.title; }", + }, + { + name: "label named document is allowed", + code: "document: while(true) { break document; }", + }, + { + name: "typeof in type position is allowed", + code: "type T = typeof document;", + }, + { + name: "document in declare module is allowed", + code: "declare module 'foo' { const document: string; }", + }, ], invalid: [ { @@ -99,5 +159,25 @@ ruleTester.run("prefer-active-doc", preferActiveDocRule, { code: "document.addEventListener('click', handler);", errors: [{ messageId: "preferActive" }], }, + { + name: "document in as-expression is still flagged", + code: "const el = (document as any).body;", + errors: [{ messageId: "preferActive", data: { original: "document", replacement: "activeDocument" } }], + }, + { + name: "document in satisfies-expression is still flagged", + code: "const el = (document satisfies Document).body;", + errors: [{ messageId: "preferActive", data: { original: "document", replacement: "activeDocument" } }], + }, + { + name: "document in non-null assertion is still flagged", + code: "const el = document!.body;", + errors: [{ messageId: "preferActive", data: { original: "document", replacement: "activeDocument" } }], + }, + { + name: "document in enum initializer is still flagged", + code: "enum Foo { bar = document.title }", + errors: [{ messageId: "preferActive", data: { original: "document", replacement: "activeDocument" } }], + }, ], });