diff --git a/.changeset/sharp-beans-design.md b/.changeset/sharp-beans-design.md new file mode 100644 index 000000000..70ef2688f --- /dev/null +++ b/.changeset/sharp-beans-design.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-svelte": minor +--- + +fix: improved loading of external modules diff --git a/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte b/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte index 769a53662..32588fdc9 100644 --- a/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte +++ b/docs-svelte-kit/src/lib/components/ESLintCodeBlock.svelte @@ -7,7 +7,7 @@ postprocess, } from "../eslint/scripts/linter.js" import { loadTsParser } from "../eslint/scripts/ts-parser.js" - import { loadModulesForBrowser } from "../../../../src/shared/svelte-compile-warns/transform/load-module" + import { loadModulesForBrowser } from "../../../../src/utils/load-module" const modulesForBrowser = loadModulesForBrowser() const loadLinter = createLinter() diff --git a/docs-svelte-kit/src/lib/components/ESLintPlayground.svelte b/docs-svelte-kit/src/lib/components/ESLintPlayground.svelte index e5635ca3a..bca993358 100644 --- a/docs-svelte-kit/src/lib/components/ESLintPlayground.svelte +++ b/docs-svelte-kit/src/lib/components/ESLintPlayground.svelte @@ -10,7 +10,7 @@ postprocess, } from "../eslint/scripts/linter.js" import { loadTsParser } from "../eslint/scripts/ts-parser.js" - import { loadModulesForBrowser } from "../../../../src/shared/svelte-compile-warns/transform/load-module" + import { loadModulesForBrowser } from "../../../../src/utils/load-module" let tsParser = null const linter = loadModulesForBrowser() .then(async () => { diff --git a/src/shared/svelte-compile-warns/transform/babel.ts b/src/shared/svelte-compile-warns/transform/babel.ts index 7d211a040..626e965ba 100644 --- a/src/shared/svelte-compile-warns/transform/babel.ts +++ b/src/shared/svelte-compile-warns/transform/babel.ts @@ -2,7 +2,7 @@ import type { AST } from "svelte-eslint-parser" import type babelCore from "@babel/core" import type { RuleContext } from "../../../types" import type { TransformResult } from "./types" -import { loadModule } from "./load-module" +import { loadModule } from "../../../utils/load-module" type BabelCore = typeof babelCore /** diff --git a/src/shared/svelte-compile-warns/transform/less.ts b/src/shared/svelte-compile-warns/transform/less.ts index fae8fb16e..5f1e458ec 100644 --- a/src/shared/svelte-compile-warns/transform/less.ts +++ b/src/shared/svelte-compile-warns/transform/less.ts @@ -2,7 +2,7 @@ import type { AST } from "svelte-eslint-parser" import type less from "less" import type { RuleContext } from "../../../types" import type { TransformResult } from "./types" -import { loadModule } from "./load-module" +import { loadModule } from "../../../utils/load-module" type Less = typeof less /** diff --git a/src/shared/svelte-compile-warns/transform/sass.ts b/src/shared/svelte-compile-warns/transform/sass.ts index 4666e509a..927cfa924 100644 --- a/src/shared/svelte-compile-warns/transform/sass.ts +++ b/src/shared/svelte-compile-warns/transform/sass.ts @@ -2,7 +2,7 @@ import type { AST } from "svelte-eslint-parser" import type sass from "sass" import type { RuleContext } from "../../../types" import type { TransformResult } from "./types" -import { loadModule } from "./load-module" +import { loadModule } from "../../../utils/load-module" type Sass = typeof sass /** diff --git a/src/shared/svelte-compile-warns/transform/stylus.ts b/src/shared/svelte-compile-warns/transform/stylus.ts index 06a871405..4783d745b 100644 --- a/src/shared/svelte-compile-warns/transform/stylus.ts +++ b/src/shared/svelte-compile-warns/transform/stylus.ts @@ -3,7 +3,7 @@ import type stylus from "stylus" import type { RawSourceMap } from "source-map-js" import type { RuleContext } from "../../../types" import type { TransformResult } from "./types" -import { loadModule } from "./load-module" +import { loadModule } from "../../../utils/load-module" type Stylus = typeof stylus /** diff --git a/src/shared/svelte-compile-warns/transform/typescript.ts b/src/shared/svelte-compile-warns/transform/typescript.ts index 432b90c52..6f3618961 100644 --- a/src/shared/svelte-compile-warns/transform/typescript.ts +++ b/src/shared/svelte-compile-warns/transform/typescript.ts @@ -2,7 +2,7 @@ import type { AST } from "svelte-eslint-parser" import type typescript from "typescript" import type { RuleContext } from "../../../types" import type { TransformResult } from "./types" -import { loadModule } from "./load-module" +import { loadModule } from "../../../utils/load-module" type TS = typeof typescript /** diff --git a/src/types.ts b/src/types.ts index d16daa8d8..accfd1514 100644 --- a/src/types.ts +++ b/src/types.ts @@ -154,6 +154,8 @@ export type RuleContext = { // eslint@6 does not have this method. getCwd?: () => string + // eslint@<7.11.0 does not have this method. + getPhysicalFilename?: () => string } export type NodeOrToken = { diff --git a/src/shared/svelte-compile-warns/transform/load-module.ts b/src/utils/load-module.ts similarity index 65% rename from src/shared/svelte-compile-warns/transform/load-module.ts rename to src/utils/load-module.ts index e14d6329d..853d66d90 100644 --- a/src/shared/svelte-compile-warns/transform/load-module.ts +++ b/src/utils/load-module.ts @@ -1,7 +1,7 @@ import type { AST } from "svelte-eslint-parser" import Module from "module" import path from "path" -import type { RuleContext } from "../../../types" +import type { RuleContext } from "../types" const cache = new WeakMap>() const cache4b = new Map() /** @@ -17,12 +17,30 @@ export function loadModule(context: RuleContext, name: string): R | null { const mod = modules[name] || cache4b.get(name) if (mod) return mod as R try { + // load from cwd const cwd = context.getCwd?.() ?? process.cwd() const relativeTo = path.join(cwd, "__placeholder__.js") return (modules[name] = Module.createRequire(relativeTo)(name) as R) } catch { - return null + // ignore } + for (const relativeTo of [ + // load from lint file name + context.getFilename(), + // load from lint file name (physical) + context.getPhysicalFilename?.(), + // load from this plugin module + typeof __filename !== "undefined" ? __filename : "", + ]) { + if (relativeTo) { + try { + return (modules[name] = Module.createRequire(relativeTo)(name) as R) + } catch { + // ignore + } + } + } + return null } /** Load modules for browser */ diff --git a/src/utils/ts-utils/index.ts b/src/utils/ts-utils/index.ts index e49ece5ac..a0ee0812d 100644 --- a/src/utils/ts-utils/index.ts +++ b/src/utils/ts-utils/index.ts @@ -1,7 +1,6 @@ import type { RuleContext, ASTNode } from "../../types" import type * as TS from "typescript" -import Module from "module" -import path from "path" +import { loadModule } from "../load-module" export type TypeScript = typeof TS export type { TS } @@ -47,21 +46,15 @@ export function getTypeScriptTools(context: RuleContext): TSTools | null { } } -let cacheTypeScript: TypeScript | undefined +let cacheTypeScript: TypeScript | null = null /** * Get TypeScript tools */ -export function getTypeScript(context: RuleContext): TypeScript | undefined { +export function getTypeScript(context: RuleContext): TypeScript | null { if (cacheTypeScript) { return cacheTypeScript } - try { - const cwd = context.getCwd?.() ?? process.cwd() - const relativeTo = path.join(cwd, "__placeholder__.js") - cacheTypeScript = Module.createRequire(relativeTo)("typescript") - } catch { - // ignore - } + cacheTypeScript = loadModule(context, "typescript") if (cacheTypeScript) { return cacheTypeScript }