Skip to content

Commit

Permalink
feat(shadcn): add tailwind version detection
Browse files Browse the repository at this point in the history
  • Loading branch information
shadcn committed Jan 28, 2025
1 parent c8c4027 commit f30efb6
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 68 deletions.
11 changes: 10 additions & 1 deletion packages/shadcn/src/preflights/preflight-init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 4 additions & 3 deletions packages/shadcn/src/utils/get-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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),
Expand Down Expand Up @@ -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),
Expand Down
53 changes: 43 additions & 10 deletions packages/shadcn/src/utils/get-project-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type ProjectInfo = {
isTsx: boolean
tailwindConfigFile: string | null
tailwindCssFile: string | null
tailwindVersion: "v3" | "v4" | null
aliasPrefix: string | null
}

Expand All @@ -43,6 +44,7 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
isTsx,
tailwindConfigFile,
tailwindCssFile,
tailwindVersion,
aliasPrefix,
packageJson,
] = await Promise.all([
Expand 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),
])
Expand All @@ -70,6 +73,7 @@ export async function getProjectInfo(cwd: string): Promise<ProjectInfo | null> {
isTsx,
tailwindConfigFile,
tailwindCssFile,
tailwindVersion,
aliasPrefix,
}

Expand Down Expand Up @@ -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
}
}
Expand Down Expand Up @@ -237,8 +270,8 @@ export async function getProjectConfig(

if (
!projectInfo ||
!projectInfo.tailwindConfigFile ||
!projectInfo.tailwindCssFile
!projectInfo.tailwindCssFile ||
(projectInfo.tailwindVersion === "v3" && !projectInfo.tailwindConfigFile)
) {
return null
}
Expand All @@ -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,
Expand Down
14 changes: 14 additions & 0 deletions packages/shadcn/test/fixtures/frameworks/next-app-src/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"tailwindcss": "^3.0.0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"tailwindcss": "^4.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -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";
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"devDependencies": {
"tailwindcss": "4.1.2"
}
}
Original file line number Diff line number Diff line change
@@ -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";
9 changes: 9 additions & 0 deletions packages/shadcn/test/utils/get-project-info.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe("get project info", async () => {
isTsx: true,
tailwindConfigFile: "tailwind.config.ts",
tailwindCssFile: "app/globals.css",
tailwindVersion: "v3",
aliasPrefix: "@",
},
},
Expand All @@ -27,6 +28,7 @@ describe("get project info", async () => {
isTsx: true,
tailwindConfigFile: "tailwind.config.ts",
tailwindCssFile: "src/app/styles.css",
tailwindVersion: "v3",
aliasPrefix: "#",
},
},
Expand All @@ -39,6 +41,7 @@ describe("get project info", async () => {
isTsx: true,
tailwindConfigFile: "tailwind.config.ts",
tailwindCssFile: "styles/globals.css",
tailwindVersion: "v4",
aliasPrefix: "~",
},
},
Expand All @@ -51,6 +54,7 @@ describe("get project info", async () => {
isTsx: true,
tailwindConfigFile: "tailwind.config.ts",
tailwindCssFile: "src/styles/globals.css",
tailwindVersion: "v4",
aliasPrefix: "@",
},
},
Expand All @@ -63,6 +67,7 @@ describe("get project info", async () => {
isTsx: true,
tailwindConfigFile: "tailwind.config.ts",
tailwindCssFile: "src/styles/globals.css",
tailwindVersion: "v3",
aliasPrefix: "~",
},
},
Expand All @@ -75,6 +80,7 @@ describe("get project info", async () => {
isTsx: true,
tailwindConfigFile: "tailwind.config.ts",
tailwindCssFile: "src/styles/globals.css",
tailwindVersion: "v3",
aliasPrefix: "~",
},
},
Expand All @@ -87,6 +93,7 @@ describe("get project info", async () => {
isTsx: true,
tailwindConfigFile: "tailwind.config.ts",
tailwindCssFile: "app/tailwind.css",
tailwindVersion: "v3",
aliasPrefix: "~",
},
},
Expand All @@ -99,6 +106,7 @@ describe("get project info", async () => {
isTsx: true,
tailwindConfigFile: "tailwind.config.ts",
tailwindCssFile: "app/tailwind.css",
tailwindVersion: "v3",
aliasPrefix: "~",
},
},
Expand All @@ -111,6 +119,7 @@ describe("get project info", async () => {
isTsx: true,
tailwindConfigFile: "tailwind.config.js",
tailwindCssFile: "src/index.css",
tailwindVersion: "v3",
aliasPrefix: null,
},
},
Expand Down

0 comments on commit f30efb6

Please sign in to comment.