diff --git a/packages/eslint-config/src/globs.ts b/packages/eslint-config/src/globs.ts index a265183..13303d5 100644 --- a/packages/eslint-config/src/globs.ts +++ b/packages/eslint-config/src/globs.ts @@ -44,5 +44,5 @@ export function globAsFormat(glob: string) { * Apply custom rules to snippets in markdown files. */ export function globMarkdownSnippetFromGlob(glob: string) { - return `**/*.md/*.${glob.split("/").pop()}`; + return `**/*.md/*.${glob.split("/").pop() ?? ""}`; } diff --git a/packages/eslint-config/src/index.ts b/packages/eslint-config/src/index.ts index a07ede3..a3f099b 100644 --- a/packages/eslint-config/src/index.ts +++ b/packages/eslint-config/src/index.ts @@ -1,8 +1,9 @@ import { FlatConfig } from "@typescript-eslint/utils/ts-eslint"; import { globUse } from "./globs.js"; +import { javascript } from "./javascript.js"; import { markdownConfig } from "./markdown.js"; import { prettierConfig, PrettierConfig } from "./prettier.js"; -import { typescript, TypescriptConfig } from "./typescript.js"; +import { typescript, TypescriptConfig, typescriptResolveConfig } from "./typescript.js"; interface Opts { prettier?: PrettierConfig; @@ -23,6 +24,8 @@ export function defineConfig(opts: Opts, ...userConfigs: FlatConfig.Config[]) { } } + opts.typescript = typescriptResolveConfig(opts.typescript); + return [ // Global options { @@ -38,6 +41,7 @@ export function defineConfig(opts: Opts, ...userConfigs: FlatConfig.Config[]) { // Language specifics ...markdownConfig(), + ...javascript(!!opts.typescript), ...typescript(opts.typescript), // Ecosystem specific diff --git a/packages/eslint-config/src/javascript.ts b/packages/eslint-config/src/javascript.ts new file mode 100644 index 0000000..179fb1c --- /dev/null +++ b/packages/eslint-config/src/javascript.ts @@ -0,0 +1,18 @@ +import { FlatConfig } from "@typescript-eslint/utils/ts-eslint"; +import eslintConfigs from "@eslint/js"; +import { GLOBS, globUse } from "./globs.js"; + +export function javascript(hasTypescriptEnabled: boolean) { + if (hasTypescriptEnabled) { + return []; + } + + return [ + { + files: globUse([GLOBS.javascript]), + rules: { + ...eslintConfigs.configs.recommended.rules, + }, + }, + ] satisfies FlatConfig.Config[]; +} diff --git a/packages/eslint-config/src/typescript.ts b/packages/eslint-config/src/typescript.ts index c978139..5f0f380 100644 --- a/packages/eslint-config/src/typescript.ts +++ b/packages/eslint-config/src/typescript.ts @@ -6,25 +6,47 @@ import { GLOBS, globUse } from "./globs.js"; export type TypescriptConfig = | boolean | { - project?: string; + project?: boolean | string; }; -export function typescript(config?: TypescriptConfig) { +export function typescriptResolveConfig(config?: TypescriptConfig): TypescriptConfig { + if (config === false) { + return false; + } + + if (config === true) { + config = { + project: true, + }; + } + if (config === undefined) { if (existsSync("./tsconfig.eslint.json")) { config = { project: "./tsconfig.eslint.json", }; + } else if (existsSync("./tsconfig.json")) { + config = { + project: "./tsconfig.json", + }; } else { - config = existsSync("./tsconfig.json"); + config = false; } } + return config; +} + +export function typescript(config: TypescriptConfig) { if (config === false) { return []; } - const project = typeof config === "boolean" ? config : config.project; + if (typeof config === "boolean") { + config = { + project: true, + }; + } return [ { @@ -35,7 +57,7 @@ export function typescript(config?: TypescriptConfig) { languageOptions: { parser: typescriptEslint.parser, parserOptions: { - project, + project: config.project, warnOnUnsupportedTypeScriptVersion: false, }, }, diff --git a/packages/eslint-config/test/index.ts b/packages/eslint-config/test/index.ts index 20d38a7..8ac1d56 100644 --- a/packages/eslint-config/test/index.ts +++ b/packages/eslint-config/test/index.ts @@ -232,5 +232,17 @@ const foo = 'bar'; ); assert.match(stdoutLinesForFile(stdout, "index.ts"), /\(format\/prettier\)/); }); + + void it("enables js file linting without tsconfig.json", async () => { + const { stdout } = await testOnStdout({}, [ + { + path: "index.js", + contents: `let foo= 2`, + }, + ]); + + assert.match(stdoutLinesForFile(stdout, "index.js"), /\(no-unused-vars\)/); + assert.match(stdoutLinesForFile(stdout, "index.js"), /\(format\/prettier\)/); + }); }, );