From 2574c1e8b670dc99fe8a7a0699d8ef68dc5d4440 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 30 Jul 2026 04:36:56 +0000 Subject: [PATCH 1/2] feat: add Astro framework detection and .astro file support - Add 'astro' to FRAMEWORK_PACKAGES mapping (before 'vite' for precedence) - Add 'astro' to FRAMEWORK_TOKENS and display names - Add .astro extension to SOURCE_FILE_PATTERN for lint pipeline inclusion - Add tests for Astro framework detection and formatting Astro projects use Vite internally, so 'astro' must be checked before 'vite' in the framework detection order (similar to Next.js and Gatsby). The .astro file extension is now recognized by the lint pipeline. Oxlint's Astro frontend (already used for HTML files) can parse Astro templates. Refs: #1517 Co-authored-by: Skosh --- packages/core/src/project-info/constants.ts | 2 +- packages/core/src/project-info/detectors.ts | 2 ++ packages/core/tests/discover-project.test.ts | 19 ++++++++++++++++++- .../src/plugin/utils/capability.ts | 1 + 4 files changed, 22 insertions(+), 2 deletions(-) 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", From 21e022b84bff3962db4df25661e1ba1eaa492efd Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 30 Jul 2026 04:41:58 +0000 Subject: [PATCH 2/2] chore: add changeset for Astro framework detection Co-authored-by: Skosh --- .changeset/add-astro-framework-detection.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .changeset/add-astro-framework-detection.md 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.