diff --git a/.changeset/add-astro-framework-detection.md b/.changeset/add-astro-framework-detection.md new file mode 100644 index 000000000..75ca45b31 --- /dev/null +++ b/.changeset/add-astro-framework-detection.md @@ -0,0 +1,11 @@ +--- +"oxlint-plugin-react-doctor": patch +"@react-doctor/core": patch +"react-doctor": patch +--- + +feat: add Astro framework detection + +Astro projects are now correctly detected as `framework: "astro"` instead of `"unknown"`. Astro is checked before Vite in the detection order since Astro projects typically depend on both `astro` and `vite` packages, and the more specific framework should take precedence. + +This change also adds `.astro` file extension to the lintable source file pattern, though full rule support for Astro template syntax is not yet complete. diff --git a/packages/core/src/project-info/constants.ts b/packages/core/src/project-info/constants.ts index 515f9ad4a..1b7f79219 100644 --- a/packages/core/src/project-info/constants.ts +++ b/packages/core/src/project-info/constants.ts @@ -1,5 +1,5 @@ export const HTML_FILE_PATTERN = /\.html$/i; -export const SOURCE_FILE_PATTERN = /\.(?:tsx?|jsx?|mts|mjs|[hH][tT][mM][lL])$/; +export const SOURCE_FILE_PATTERN = /\.(?:tsx?|jsx?|mts|mjs|astro|[hH][tT][mM][lL])$/; // Bundler output — IIFE / UMD / global builds and explicitly-minified // drops (e.g. tsup/rollup emitting `widget.iife.js`, `sdk.umd.js`, diff --git a/packages/core/src/project-info/detectors.ts b/packages/core/src/project-info/detectors.ts index 3ec537b13..5658e4cb0 100644 --- a/packages/core/src/project-info/detectors.ts +++ b/packages/core/src/project-info/detectors.ts @@ -228,6 +228,7 @@ const FRAMEWORK_PACKAGES: Record = { "@tanstack/react-start": "tanstack-start", "@remix-run/react": "remix", gatsby: "gatsby", + astro: "astro", vite: "vite", "react-scripts": "cra", expo: "expo", @@ -241,6 +242,7 @@ const FRAMEWORK_DISPLAY_NAMES: Record = { cra: "Create React App", remix: "Remix", gatsby: "Gatsby", + astro: "Astro", expo: "Expo", "react-native": "React Native", preact: "Preact", diff --git a/packages/core/tests/discover-project.test.ts b/packages/core/tests/discover-project.test.ts index 43754a64d..77c165b98 100644 --- a/packages/core/tests/discover-project.test.ts +++ b/packages/core/tests/discover-project.test.ts @@ -12,7 +12,7 @@ import { } from "@react-doctor/core"; const FIXTURES_DIRECTORY = path.resolve(import.meta.dirname, "fixtures"); -const VALID_FRAMEWORKS = ["nextjs", "vite", "cra", "remix", "gatsby", "unknown"]; +const VALID_FRAMEWORKS = ["nextjs", "vite", "cra", "remix", "gatsby", "astro", "unknown"]; interface ReactCompilerDetectionCase { readonly name: string; @@ -2824,6 +2824,22 @@ describe("listWorkspacePackages", () => { expect(projectInfo.framework, "the framework package outranks its bundler").toBe("gatsby"); }); + it("classifies an Astro app that also lists Vite as `astro`, not `vite`", () => { + const projectDirectory = path.join(tempDirectory, "astro-with-vite"); + fs.mkdirSync(projectDirectory, { recursive: true }); + fs.writeFileSync( + path.join(projectDirectory, "package.json"), + JSON.stringify({ + name: "astro-with-vite", + dependencies: { astro: "^7.1.5", react: "^19.2.8" }, + devDependencies: { vite: "^6.0.0" }, + }), + ); + + const projectInfo = discoverProject(projectDirectory); + expect(projectInfo.framework, "the framework package outranks its bundler").toBe("astro"); + }); + it("flags a web-rooted monorepo with an Expo workspace as an Expo project", () => { const rootDirectory = path.join(tempDirectory, "expo-workspace-monorepo"); const mobileDirectory = path.join(rootDirectory, "apps", "mobile"); @@ -4451,6 +4467,7 @@ describe("formatFrameworkName", () => { expect(formatFrameworkName("cra")).toBe("Create React App"); expect(formatFrameworkName("remix")).toBe("Remix"); expect(formatFrameworkName("gatsby")).toBe("Gatsby"); + expect(formatFrameworkName("astro")).toBe("Astro"); }); it("formats unknown framework as React", () => { diff --git a/packages/oxlint-plugin-react-doctor/src/plugin/utils/capability.ts b/packages/oxlint-plugin-react-doctor/src/plugin/utils/capability.ts index 14e46dedc..30455efbc 100644 --- a/packages/oxlint-plugin-react-doctor/src/plugin/utils/capability.ts +++ b/packages/oxlint-plugin-react-doctor/src/plugin/utils/capability.ts @@ -14,6 +14,7 @@ export const FRAMEWORK_TOKENS = [ "cra", "remix", "gatsby", + "astro", "expo", "react-native", "tanstack-start",