mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-25 13:46:07 +00:00
(1/n) shadcn: add tailwind version detection (#6478)
* feat(shadcn): add tailwind version detection * chore: changeset
This commit is contained in:
5
.changeset/five-hounds-tell.md
Normal file
5
.changeset/five-hounds-tell.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"shadcn": minor
|
||||
---
|
||||
|
||||
add tailwind version detection
|
||||
@@ -81,7 +81,16 @@ export async function preFlightInit(
|
||||
const tailwindSpinner = spinner(`Validating Tailwind CSS.`, {
|
||||
silent: options.silent,
|
||||
}).start()
|
||||
if (!projectInfo?.tailwindConfigFile || !projectInfo?.tailwindCssFile) {
|
||||
if (
|
||||
projectInfo.tailwindVersion === "v3" &&
|
||||
(!projectInfo?.tailwindConfigFile || !projectInfo?.tailwindCssFile)
|
||||
) {
|
||||
errors[ERRORS.TAILWIND_NOT_CONFIGURED] = true
|
||||
tailwindSpinner?.fail()
|
||||
} else if (
|
||||
projectInfo.tailwindVersion === "v4" &&
|
||||
!projectInfo?.tailwindCssFile
|
||||
) {
|
||||
errors[ERRORS.TAILWIND_NOT_CONFIGURED] = true
|
||||
tailwindSpinner?.fail()
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,6 @@ import { highlighter } from "@/src/utils/highlighter"
|
||||
import { resolveImport } from "@/src/utils/resolve-import"
|
||||
import { cosmiconfig } from "cosmiconfig"
|
||||
import fg from "fast-glob"
|
||||
import fs from "fs-extra"
|
||||
import { loadConfig } from "tsconfig-paths"
|
||||
import { z } from "zod"
|
||||
|
||||
@@ -27,7 +26,7 @@ export const rawConfigSchema = z
|
||||
rsc: z.coerce.boolean().default(false),
|
||||
tsx: z.coerce.boolean().default(true),
|
||||
tailwind: z.object({
|
||||
config: z.string(),
|
||||
config: z.string().optional(),
|
||||
css: z.string(),
|
||||
baseColor: z.string(),
|
||||
cssVariables: z.boolean().default(true),
|
||||
@@ -96,7 +95,9 @@ export async function resolveConfigPaths(cwd: string, config: RawConfig) {
|
||||
...config,
|
||||
resolvedPaths: {
|
||||
cwd,
|
||||
tailwindConfig: path.resolve(cwd, config.tailwind.config),
|
||||
tailwindConfig: config.tailwind.config
|
||||
? path.resolve(cwd, config.tailwind.config)
|
||||
: "",
|
||||
tailwindCss: path.resolve(cwd, config.tailwind.css),
|
||||
utils: await resolveImport(config.aliases["utils"], tsConfig),
|
||||
components: await resolveImport(config.aliases["components"], tsConfig),
|
||||
|
||||
@@ -19,6 +19,7 @@ type ProjectInfo = {
|
||||
isTsx: boolean
|
||||
tailwindConfigFile: string | null
|
||||
tailwindCssFile: string | null
|
||||
tailwindVersion: "v3" | "v4" | null
|
||||
aliasPrefix: string | null
|
||||
}
|
||||
|
||||
@@ -43,6 +44,7 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
|
||||
isTsx,
|
||||
tailwindConfigFile,
|
||||
tailwindCssFile,
|
||||
tailwindVersion,
|
||||
aliasPrefix,
|
||||
packageJson,
|
||||
] = await Promise.all([
|
||||
@@ -55,6 +57,7 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
|
||||
isTypeScriptProject(cwd),
|
||||
getTailwindConfigFile(cwd),
|
||||
getTailwindCssFile(cwd),
|
||||
getTailwindVersion(cwd),
|
||||
getTsConfigAliasPrefix(cwd),
|
||||
getPackageInfo(cwd, false),
|
||||
])
|
||||
@@ -70,6 +73,7 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
|
||||
isTsx,
|
||||
tailwindConfigFile,
|
||||
tailwindCssFile,
|
||||
tailwindVersion,
|
||||
aliasPrefix,
|
||||
}
|
||||
|
||||
@@ -121,21 +125,50 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
|
||||
return type
|
||||
}
|
||||
|
||||
export async function getTailwindVersion(
|
||||
cwd: string
|
||||
): Promise<ProjectInfo["tailwindVersion"]> {
|
||||
const packageInfo = getPackageInfo(cwd)
|
||||
|
||||
if (
|
||||
!packageInfo?.dependencies?.tailwindcss &&
|
||||
!packageInfo?.devDependencies?.tailwindcss
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (
|
||||
/^(?:\^|~)?3(?:\.\d+)*(?:-.*)?$/.test(
|
||||
packageInfo?.dependencies?.tailwindcss ||
|
||||
packageInfo?.devDependencies?.tailwindcss ||
|
||||
""
|
||||
)
|
||||
) {
|
||||
return "v3"
|
||||
}
|
||||
|
||||
return "v4"
|
||||
}
|
||||
|
||||
export async function getTailwindCssFile(cwd: string) {
|
||||
const files = await fg.glob(["**/*.css", "**/*.scss"], {
|
||||
cwd,
|
||||
deep: 5,
|
||||
ignore: PROJECT_SHARED_IGNORE,
|
||||
})
|
||||
const [files, tailwindVersion] = await Promise.all([
|
||||
fg.glob(["**/*.css", "**/*.scss"], {
|
||||
cwd,
|
||||
deep: 5,
|
||||
ignore: PROJECT_SHARED_IGNORE,
|
||||
}),
|
||||
getTailwindVersion(cwd),
|
||||
])
|
||||
|
||||
if (!files.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
const needle =
|
||||
tailwindVersion === "v4" ? `@import "tailwindcss"` : "@tailwind base"
|
||||
for (const file of files) {
|
||||
const contents = await fs.readFile(path.resolve(cwd, file), "utf8")
|
||||
// Assume that if the file contains `@tailwind base` it's the main css file.
|
||||
if (contents.includes("@tailwind base")) {
|
||||
if (contents.includes(needle)) {
|
||||
return file
|
||||
}
|
||||
}
|
||||
@@ -237,8 +270,8 @@ export async function getProjectConfig(
|
||||
|
||||
if (
|
||||
!projectInfo ||
|
||||
!projectInfo.tailwindConfigFile ||
|
||||
!projectInfo.tailwindCssFile
|
||||
!projectInfo.tailwindCssFile ||
|
||||
(projectInfo.tailwindVersion === "v3" && !projectInfo.tailwindConfigFile)
|
||||
) {
|
||||
return null
|
||||
}
|
||||
@@ -249,7 +282,7 @@ export async function getProjectConfig(
|
||||
tsx: projectInfo.isTsx,
|
||||
style: "new-york",
|
||||
tailwind: {
|
||||
config: projectInfo.tailwindConfigFile,
|
||||
config: projectInfo.tailwindConfigFile ?? "",
|
||||
baseColor: "zinc",
|
||||
css: projectInfo.tailwindCssFile,
|
||||
cssVariables: true,
|
||||
|
||||
14
packages/shadcn/test/fixtures/frameworks/next-app-src/package.json
vendored
Normal file
14
packages/shadcn/test/fixtures/frameworks/next-app-src/package.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "next-app-src",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"tailwindcss": "3.1.2"
|
||||
}
|
||||
}
|
||||
@@ -7,5 +7,8 @@
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"tailwindcss": "^3.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,5 +7,8 @@
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"tailwindcss": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--foreground-rgb: 0, 0, 0;
|
||||
--background-start-rgb: 214, 219, 220;
|
||||
--background-end-rgb: 255, 255, 255;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--foreground-rgb: 255, 255, 255;
|
||||
--background-start-rgb: 0, 0, 0;
|
||||
--background-end-rgb: 0, 0, 0;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
color: rgb(var(--foreground-rgb));
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
rgb(var(--background-end-rgb))
|
||||
)
|
||||
rgb(var(--background-start-rgb));
|
||||
}
|
||||
@import "tailwindcss";
|
||||
|
||||
@@ -7,5 +7,8 @@
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tailwindcss": "4.1.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--foreground-rgb: 0, 0, 0;
|
||||
--background-start-rgb: 214, 219, 220;
|
||||
--background-end-rgb: 255, 255, 255;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--foreground-rgb: 255, 255, 255;
|
||||
--background-start-rgb: 0, 0, 0;
|
||||
--background-end-rgb: 0, 0, 0;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
color: rgb(var(--foreground-rgb));
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
transparent,
|
||||
rgb(var(--background-end-rgb))
|
||||
)
|
||||
rgb(var(--background-start-rgb));
|
||||
}
|
||||
@import "tailwindcss";
|
||||
|
||||
@@ -15,6 +15,7 @@ describe("get project info", async () => {
|
||||
isTsx: true,
|
||||
tailwindConfigFile: "tailwind.config.ts",
|
||||
tailwindCssFile: "app/globals.css",
|
||||
tailwindVersion: "v3",
|
||||
aliasPrefix: "@",
|
||||
},
|
||||
},
|
||||
@@ -27,6 +28,7 @@ describe("get project info", async () => {
|
||||
isTsx: true,
|
||||
tailwindConfigFile: "tailwind.config.ts",
|
||||
tailwindCssFile: "src/app/styles.css",
|
||||
tailwindVersion: "v3",
|
||||
aliasPrefix: "#",
|
||||
},
|
||||
},
|
||||
@@ -39,6 +41,7 @@ describe("get project info", async () => {
|
||||
isTsx: true,
|
||||
tailwindConfigFile: "tailwind.config.ts",
|
||||
tailwindCssFile: "styles/globals.css",
|
||||
tailwindVersion: "v4",
|
||||
aliasPrefix: "~",
|
||||
},
|
||||
},
|
||||
@@ -51,6 +54,7 @@ describe("get project info", async () => {
|
||||
isTsx: true,
|
||||
tailwindConfigFile: "tailwind.config.ts",
|
||||
tailwindCssFile: "src/styles/globals.css",
|
||||
tailwindVersion: "v4",
|
||||
aliasPrefix: "@",
|
||||
},
|
||||
},
|
||||
@@ -63,6 +67,7 @@ describe("get project info", async () => {
|
||||
isTsx: true,
|
||||
tailwindConfigFile: "tailwind.config.ts",
|
||||
tailwindCssFile: "src/styles/globals.css",
|
||||
tailwindVersion: "v3",
|
||||
aliasPrefix: "~",
|
||||
},
|
||||
},
|
||||
@@ -75,6 +80,7 @@ describe("get project info", async () => {
|
||||
isTsx: true,
|
||||
tailwindConfigFile: "tailwind.config.ts",
|
||||
tailwindCssFile: "src/styles/globals.css",
|
||||
tailwindVersion: "v3",
|
||||
aliasPrefix: "~",
|
||||
},
|
||||
},
|
||||
@@ -87,6 +93,7 @@ describe("get project info", async () => {
|
||||
isTsx: true,
|
||||
tailwindConfigFile: "tailwind.config.ts",
|
||||
tailwindCssFile: "app/tailwind.css",
|
||||
tailwindVersion: "v3",
|
||||
aliasPrefix: "~",
|
||||
},
|
||||
},
|
||||
@@ -99,6 +106,7 @@ describe("get project info", async () => {
|
||||
isTsx: true,
|
||||
tailwindConfigFile: "tailwind.config.ts",
|
||||
tailwindCssFile: "app/tailwind.css",
|
||||
tailwindVersion: "v3",
|
||||
aliasPrefix: "~",
|
||||
},
|
||||
},
|
||||
@@ -111,6 +119,7 @@ describe("get project info", async () => {
|
||||
isTsx: true,
|
||||
tailwindConfigFile: "tailwind.config.js",
|
||||
tailwindCssFile: "src/index.css",
|
||||
tailwindVersion: "v3",
|
||||
aliasPrefix: null,
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user