mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-07-01 08:34:12 +00:00
feat(cli): tree resolver
This commit is contained in:
@@ -68,6 +68,11 @@ export const add = new Command()
|
||||
|
||||
const registryIndex = await getRegistryIndex()
|
||||
|
||||
if (!registryIndex) {
|
||||
handleError(new Error("Failed to fetch registry index."))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
let selectedComponents = options.all
|
||||
? registryIndex.map((entry) => entry.name)
|
||||
: options.components
|
||||
@@ -98,7 +103,7 @@ export const add = new Command()
|
||||
const payload = await fetchTree(config.style, tree)
|
||||
const baseColor = await getRegistryBaseColor(config.tailwind.baseColor)
|
||||
|
||||
if (!payload.length) {
|
||||
if (!payload?.length) {
|
||||
logger.warn("Selected components not found. Exiting.")
|
||||
process.exit(0)
|
||||
}
|
||||
@@ -133,11 +138,11 @@ export const add = new Command()
|
||||
await fs.mkdir(targetDir, { recursive: true })
|
||||
}
|
||||
|
||||
const existingComponent = item.files.filter((file) =>
|
||||
existsSync(path.resolve(targetDir, file.name))
|
||||
const existingComponent = item.files?.filter((file) =>
|
||||
existsSync(path.resolve(targetDir, file.path))
|
||||
)
|
||||
|
||||
if (existingComponent.length && !options.overwrite) {
|
||||
if (existingComponent?.length && !options.overwrite) {
|
||||
if (selectedComponents.includes(item.name)) {
|
||||
spinner.stop()
|
||||
const { overwrite } = await prompts({
|
||||
@@ -162,12 +167,16 @@ export const add = new Command()
|
||||
}
|
||||
}
|
||||
|
||||
for (const file of item.files) {
|
||||
let filePath = path.resolve(targetDir, file.name)
|
||||
for (const file of item.files ?? []) {
|
||||
let filePath = path.resolve(targetDir, file.path)
|
||||
|
||||
// Run transformers.
|
||||
if (!file.content) {
|
||||
continue
|
||||
}
|
||||
|
||||
const content = await transform({
|
||||
filename: file.name,
|
||||
filename: file.path,
|
||||
raw: file.content,
|
||||
config,
|
||||
baseColor,
|
||||
|
||||
@@ -59,13 +59,18 @@ export const diff = new Command()
|
||||
|
||||
const registryIndex = await getRegistryIndex()
|
||||
|
||||
if (!registryIndex) {
|
||||
handleError(new Error("Failed to fetch registry index."))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!options.component) {
|
||||
const targetDir = config.resolvedPaths.components
|
||||
|
||||
// Find all components that exist in the project.
|
||||
const projectComponents = registryIndex.filter((item) => {
|
||||
for (const file of item.files) {
|
||||
const filePath = path.resolve(targetDir, file)
|
||||
for (const file of item.files ?? []) {
|
||||
const filePath = path.resolve(targetDir, file.path)
|
||||
if (existsSync(filePath)) {
|
||||
return true
|
||||
}
|
||||
@@ -139,6 +144,10 @@ async function diffComponent(
|
||||
const payload = await fetchTree(config.style, [component])
|
||||
const baseColor = await getRegistryBaseColor(config.tailwind.baseColor)
|
||||
|
||||
if (!payload) {
|
||||
return []
|
||||
}
|
||||
|
||||
const changes = []
|
||||
|
||||
for (const item of payload) {
|
||||
@@ -148,8 +157,8 @@ async function diffComponent(
|
||||
continue
|
||||
}
|
||||
|
||||
for (const file of item.files) {
|
||||
const filePath = path.resolve(targetDir, file.name)
|
||||
for (const file of item.files ?? []) {
|
||||
const filePath = path.resolve(targetDir, file.path)
|
||||
|
||||
if (!existsSync(filePath)) {
|
||||
continue
|
||||
@@ -157,8 +166,12 @@ async function diffComponent(
|
||||
|
||||
const fileContent = await fs.readFile(filePath, "utf8")
|
||||
|
||||
if (!file.content) {
|
||||
continue
|
||||
}
|
||||
|
||||
const registryContent = await transform({
|
||||
filename: file.name,
|
||||
filename: file.path,
|
||||
raw: file.content,
|
||||
config,
|
||||
baseColor,
|
||||
@@ -167,7 +180,6 @@ async function diffComponent(
|
||||
const patch = diffLines(registryContent as string, fileContent)
|
||||
if (patch.length > 1) {
|
||||
changes.push({
|
||||
file: file.name,
|
||||
filePath,
|
||||
patch,
|
||||
})
|
||||
|
||||
@@ -19,10 +19,11 @@ import {
|
||||
getRegistryBaseColors,
|
||||
getRegistryItem,
|
||||
getRegistryStyles,
|
||||
registryResolveItemsTree,
|
||||
} from "@/src/utils/registry"
|
||||
import { updateDependencies } from "@/src/utils/updaters/update-dependencies"
|
||||
import { updateDestinations } from "@/src/utils/updaters/update-destinations"
|
||||
import { updateFiles } from "@/src/utils/updaters/update-files"
|
||||
import { updateRegistryDependencies } from "@/src/utils/updaters/update-registry-dependencies"
|
||||
import {
|
||||
buildTailwindThemeColorsFromCssVars,
|
||||
updateTailwindConfig,
|
||||
@@ -97,10 +98,10 @@ export const init = new Command()
|
||||
if (!opts.force && !opts.defaults) {
|
||||
logger.info("")
|
||||
}
|
||||
const spinner = ora(`Writing components.json...`).start()
|
||||
const spinner = ora(`Writing components.json.`).start()
|
||||
const targetPath = path.resolve(cwd, "components.json")
|
||||
await fs.writeFile(targetPath, JSON.stringify(config, null, 2), "utf8")
|
||||
spinner.succeed(`Writing components.json.`)
|
||||
spinner.succeed()
|
||||
|
||||
const fullConfig = await resolveConfigPaths(cwd, config)
|
||||
|
||||
@@ -291,60 +292,25 @@ export async function promptForMinimalConfig(
|
||||
}
|
||||
|
||||
export async function runInit(config: Config) {
|
||||
const initializersSpinner = ora(`Initializing project...`)?.start()
|
||||
await updateDestinations(config)
|
||||
const [payload, baseColor] = await Promise.all([
|
||||
getRegistryItem(config.style, "index"),
|
||||
getRegistryBaseColor(config.tailwind.baseColor),
|
||||
])
|
||||
|
||||
if (!payload) {
|
||||
const initializersSpinner = ora(`Initializing project.`)?.start()
|
||||
const tree = await registryResolveItemsTree(["index"], config)
|
||||
|
||||
if (!tree) {
|
||||
initializersSpinner?.fail()
|
||||
logger.error(`Something went wrong during the initialization process.`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Inline the base color in the tailwind config.
|
||||
if (config.tailwind.cssVariables && baseColor) {
|
||||
payload.cssVars = {
|
||||
light: {
|
||||
...baseColor.cssVars.light,
|
||||
...payload.cssVars?.light,
|
||||
},
|
||||
dark: {
|
||||
...baseColor.cssVars.dark,
|
||||
...payload.cssVars?.dark,
|
||||
},
|
||||
}
|
||||
console.log(tree.tailwind?.config?.theme)
|
||||
|
||||
// Move the css vars to the tailwind config.
|
||||
if (payload.tailwind?.config && baseColor.cssVars?.light) {
|
||||
payload.tailwind.config = deepmerge(payload.tailwind.config, {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: buildTailwindThemeColorsFromCssVars(
|
||||
baseColor.cssVars.light
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
await updateTailwindConfig(tree.tailwind?.config, config)
|
||||
await updateTailwindCss(tree.cssVars, config)
|
||||
initializersSpinner?.succeed()
|
||||
|
||||
if (payload.tailwind?.config) {
|
||||
await updateTailwindConfig(payload.tailwind?.config, config)
|
||||
}
|
||||
|
||||
if (payload.cssVars) {
|
||||
await updateTailwindCss(payload.cssVars, config)
|
||||
}
|
||||
|
||||
await updateFiles(payload.files, config)
|
||||
initializersSpinner?.succeed(`Initializing project.`)
|
||||
|
||||
// Install dependencies.
|
||||
if (payload.dependencies) {
|
||||
const dependenciesSpinner = ora(`Installing dependencies...`)?.start()
|
||||
await updateDependencies(payload.dependencies, config)
|
||||
dependenciesSpinner?.succeed(`Installing dependencies.`)
|
||||
}
|
||||
const dependenciesSpinner = ora(`Installing dependencies.`)?.start()
|
||||
// await updateRegistryDependencies(tree.registryDependencies, config)
|
||||
await updateDependencies(tree.dependencies, config)
|
||||
dependenciesSpinner?.succeed()
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ export function handleError(error: unknown) {
|
||||
}
|
||||
|
||||
if (error instanceof z.ZodError) {
|
||||
console.log(error.issues)
|
||||
logger.error("Validation failed:")
|
||||
for (const [key, value] of Object.entries(error.flatten().fieldErrors)) {
|
||||
logger.error(`- ${cyan(key)}: ${value}`)
|
||||
|
||||
@@ -5,11 +5,14 @@ import { logger } from "@/src/utils/logger"
|
||||
import {
|
||||
registryBaseColorSchema,
|
||||
registryIndexSchema,
|
||||
registryItemFileSchema,
|
||||
registryItemSchema,
|
||||
registryItemWithContentSchema,
|
||||
registryWithContentSchema,
|
||||
registryItemTypeSchema,
|
||||
registryResolvedItemsTreeSchema,
|
||||
stylesSchema,
|
||||
} from "@/src/utils/registry/schema"
|
||||
import { buildTailwindThemeColorsFromCssVars } from "@/src/utils/updaters/update-tailwind-config"
|
||||
import deepmerge from "deepmerge"
|
||||
import { HttpsProxyAgent } from "https-proxy-agent"
|
||||
import { cyan } from "kleur/colors"
|
||||
import fetch from "node-fetch"
|
||||
@@ -28,7 +31,8 @@ export async function getRegistryIndex() {
|
||||
|
||||
return registryIndexSchema.parse(result)
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to fetch components from registry.`)
|
||||
logger.error("\n")
|
||||
handleError(error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +42,9 @@ export async function getRegistryStyles() {
|
||||
|
||||
return stylesSchema.parse(result)
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to fetch styles from registry.`)
|
||||
logger.error("\n")
|
||||
handleError(error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +54,7 @@ export async function getRegistryItem(style: string, name: string) {
|
||||
|
||||
return registryItemSchema.parse(result)
|
||||
} catch (error) {
|
||||
logger.error("\n")
|
||||
handleError(error)
|
||||
|
||||
return null
|
||||
@@ -123,16 +130,15 @@ export async function fetchTree(
|
||||
try {
|
||||
const paths = tree.map((item) => `styles/${style}/${item.name}.json`)
|
||||
const result = await fetchRegistry(paths)
|
||||
|
||||
return registryWithContentSchema.parse(result)
|
||||
return registryIndexSchema.parse(result)
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to fetch tree from registry.`)
|
||||
handleError(error)
|
||||
}
|
||||
}
|
||||
|
||||
export async function getItemTargetPath(
|
||||
config: Config,
|
||||
item: Pick<z.infer<typeof registryItemWithContentSchema>, "type">,
|
||||
item: z.infer<typeof registryItemSchema>,
|
||||
override?: string
|
||||
) {
|
||||
if (override) {
|
||||
@@ -183,3 +189,130 @@ async function fetchRegistry(paths: string[]) {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
export async function getRegistryItemFileTargetPath(
|
||||
file: z.infer<typeof registryItemFileSchema>,
|
||||
config: Config,
|
||||
override?: string
|
||||
) {
|
||||
if (override) {
|
||||
return override
|
||||
}
|
||||
|
||||
if (file.type === "registry:ui") {
|
||||
return config.resolvedPaths.ui
|
||||
}
|
||||
|
||||
if (file.type === "registry:lib") {
|
||||
return config.resolvedPaths.utils
|
||||
}
|
||||
|
||||
if (file.type === "registry:component") {
|
||||
return config.resolvedPaths.components
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export async function registryResolveItemsTree(
|
||||
names: z.infer<typeof registryItemSchema>["name"][],
|
||||
config: Config
|
||||
) {
|
||||
const index = await getRegistryIndex()
|
||||
if (!index) {
|
||||
return null
|
||||
}
|
||||
|
||||
let items = (
|
||||
await Promise.all(
|
||||
names.map(async (name) => {
|
||||
const item = await getRegistryItem(config.style, name)
|
||||
return item
|
||||
})
|
||||
)
|
||||
).filter((item): item is NonNullable<typeof item> => item !== null)
|
||||
|
||||
if (!items.length) {
|
||||
return null
|
||||
}
|
||||
|
||||
const registryDependencies: string[] = items
|
||||
.map((item) => item.registryDependencies ?? [])
|
||||
.flat()
|
||||
|
||||
const uniqueDependencies = Array.from(new Set(registryDependencies))
|
||||
const tree = await resolveTree(index, [...names, ...uniqueDependencies])
|
||||
let payload = await fetchTree(config.style, tree)
|
||||
|
||||
if (!payload) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (names.includes("index")) {
|
||||
const index = await getInitRegistryItem(config)
|
||||
if (index) {
|
||||
payload.unshift(index)
|
||||
}
|
||||
}
|
||||
|
||||
let tailwind = {}
|
||||
payload.forEach((item) => {
|
||||
console.log(item.tailwind?.config?.theme)
|
||||
tailwind = deepmerge(tailwind, item.tailwind ?? {})
|
||||
})
|
||||
|
||||
let cssVars = {}
|
||||
payload.forEach((item) => {
|
||||
cssVars = deepmerge(cssVars, item.cssVars ?? {})
|
||||
})
|
||||
|
||||
return registryResolvedItemsTreeSchema.parse({
|
||||
dependencies: deepmerge.all(payload.map((item) => item.dependencies ?? [])),
|
||||
devDependencies: deepmerge.all(
|
||||
payload.map((item) => item.devDependencies ?? [])
|
||||
),
|
||||
files: deepmerge.all(payload.map((item) => item.files ?? [])),
|
||||
tailwind,
|
||||
cssVars,
|
||||
})
|
||||
}
|
||||
|
||||
async function getInitRegistryItem(config: Config) {
|
||||
const [payload, baseColor] = await Promise.all([
|
||||
getRegistryItem(config.style, "index"),
|
||||
getRegistryBaseColor(config.tailwind.baseColor),
|
||||
])
|
||||
|
||||
if (!payload || !baseColor) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Inline the base color in the tailwind config.
|
||||
// TODO: Remove this when we have theme handling.
|
||||
if (config.tailwind.cssVariables && baseColor) {
|
||||
payload.cssVars = {
|
||||
light: {
|
||||
...baseColor.cssVars.light,
|
||||
...payload.cssVars?.light,
|
||||
},
|
||||
dark: {
|
||||
...baseColor.cssVars.dark,
|
||||
...payload.cssVars?.dark,
|
||||
},
|
||||
}
|
||||
|
||||
if (payload.tailwind?.config && baseColor.cssVars?.light) {
|
||||
payload.tailwind.config = deepmerge(payload.tailwind.config, {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: buildTailwindThemeColorsFromCssVars(
|
||||
baseColor.cssVars.light
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
|
||||
@@ -1,34 +1,59 @@
|
||||
import { z } from "zod"
|
||||
|
||||
// TODO: Extract this to a shared package.
|
||||
export const legacyRegistryItemSchema = z.object({
|
||||
name: z.string(),
|
||||
dependencies: z.array(z.string()).optional(),
|
||||
devDependencies: z.array(z.string()).optional(),
|
||||
registryDependencies: z.array(z.string()).optional(),
|
||||
files: z.array(z.string()),
|
||||
type: z
|
||||
.enum(["components:ui", "components:component", "components:example"])
|
||||
export const registryItemTypeSchema = z.enum([
|
||||
"components:ui",
|
||||
"components:component",
|
||||
"components:example",
|
||||
"components:block",
|
||||
"components:chart",
|
||||
"registry:style",
|
||||
"registry:lib",
|
||||
"registry:component",
|
||||
"registry:ui",
|
||||
"registry:hook",
|
||||
])
|
||||
|
||||
export const registryItemFileSchema = z.object({
|
||||
path: z.string(),
|
||||
content: z.string().optional(),
|
||||
type: registryItemTypeSchema,
|
||||
})
|
||||
|
||||
export const registryItemTailwindSchema = z.object({
|
||||
config: z
|
||||
.object({
|
||||
content: z.array(z.string()).optional(),
|
||||
theme: z.record(z.string(), z.any()).optional(),
|
||||
plugins: z.array(z.string()).optional(),
|
||||
})
|
||||
.optional(),
|
||||
})
|
||||
|
||||
export const registryIndexSchema = z.array(legacyRegistryItemSchema)
|
||||
|
||||
export const registryItemWithContentSchema = legacyRegistryItemSchema.extend({
|
||||
files: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
content: z.string(),
|
||||
type: z.enum([
|
||||
"components:ui",
|
||||
"components:component",
|
||||
"components:example",
|
||||
]),
|
||||
})
|
||||
),
|
||||
export const registryItemCssVarsSchema = z.object({
|
||||
light: z.record(z.string(), z.string()).optional(),
|
||||
dark: z.record(z.string(), z.string()).optional(),
|
||||
})
|
||||
|
||||
export const registryWithContentSchema = z.array(registryItemWithContentSchema)
|
||||
export const registryItemSchema = z.object({
|
||||
name: z.string(),
|
||||
type: registryItemTypeSchema,
|
||||
description: z.string().optional(),
|
||||
dependencies: z.array(z.string()).optional(),
|
||||
devDependencies: z.array(z.string()).optional(),
|
||||
registryDependencies: z.array(z.string()).optional(),
|
||||
files: z.array(registryItemFileSchema).optional(),
|
||||
tailwind: registryItemTailwindSchema.optional(),
|
||||
cssVars: registryItemCssVarsSchema.optional(),
|
||||
})
|
||||
|
||||
export type RegistryItem = z.infer<typeof registryItemSchema>
|
||||
|
||||
export const registryIndexSchema = z.array(
|
||||
registryItemSchema.extend({
|
||||
files: z.array(z.union([z.string(), registryItemFileSchema])).optional(),
|
||||
})
|
||||
)
|
||||
|
||||
export const stylesSchema = z.array(
|
||||
z.object({
|
||||
@@ -50,33 +75,10 @@ export const registryBaseColorSchema = z.object({
|
||||
cssVarsTemplate: z.string(),
|
||||
})
|
||||
|
||||
export const registryCssVarsSchema = z.object({
|
||||
light: z.record(z.string(), z.string()).optional(),
|
||||
dark: z.record(z.string(), z.string()).optional(),
|
||||
export const registryResolvedItemsTreeSchema = registryItemSchema.pick({
|
||||
dependencies: true,
|
||||
devDependencies: true,
|
||||
files: true,
|
||||
tailwind: true,
|
||||
cssVars: true,
|
||||
})
|
||||
|
||||
export const registryItemSchema = z.object({
|
||||
name: z.string(),
|
||||
dependencies: z.array(z.string()).optional(),
|
||||
devDependencies: z.array(z.string()).optional(),
|
||||
registryDependencies: z.array(z.string()).optional(),
|
||||
files: z.array(
|
||||
z.object({
|
||||
name: z.string(),
|
||||
content: z.string(),
|
||||
type: z.enum(["utils", "ui", "component"]),
|
||||
})
|
||||
),
|
||||
tailwind: z
|
||||
.object({
|
||||
config: z.object({
|
||||
content: z.array(z.string()).optional(),
|
||||
theme: z.record(z.string(), z.any()).optional(),
|
||||
plugins: z.array(z.string()).optional(),
|
||||
}),
|
||||
})
|
||||
.optional(),
|
||||
cssVars: registryCssVarsSchema.optional(),
|
||||
})
|
||||
|
||||
export type RegistryItem = z.infer<typeof registryItemSchema>
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
import { Config } from "@/src/utils/get-config"
|
||||
import { getPackageManager } from "@/src/utils/get-package-manager"
|
||||
import { RegistryItem } from "@/src/utils/registry/schema"
|
||||
import { execa } from "execa"
|
||||
|
||||
export async function updateDependencies(
|
||||
dependencies: string[],
|
||||
dependencies: RegistryItem["dependencies"],
|
||||
config: Config
|
||||
) {
|
||||
if (!dependencies) {
|
||||
return
|
||||
}
|
||||
|
||||
const packageManager = await getPackageManager(config.resolvedPaths.cwd)
|
||||
|
||||
await execa(
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { promises as fs } from "fs"
|
||||
import { Config } from "@/src/utils/get-config"
|
||||
import { RegistryItem } from "@/src/utils/registry/schema"
|
||||
import * as templates from "@/src/utils/templates"
|
||||
|
||||
export async function updateFiles(
|
||||
files: RegistryItem["files"],
|
||||
config: Config
|
||||
) {
|
||||
const extension = config.tsx ? "ts" : "js"
|
||||
await fs.writeFile(
|
||||
`${config.resolvedPaths.utils}.${extension}`,
|
||||
extension === "ts" ? templates.UTILS : templates.UTILS_JS,
|
||||
"utf8"
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Config } from "@/src/utils/get-config"
|
||||
import { fetchTree, getRegistryIndex, resolveTree } from "@/src/utils/registry"
|
||||
import { RegistryItem } from "@/src/utils/registry/schema"
|
||||
import { z } from "zod"
|
||||
|
||||
export async function updateRegistryDependencies(
|
||||
registryDependencies: RegistryItem["registryDependencies"],
|
||||
config: Config
|
||||
) {
|
||||
if (!registryDependencies?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
const registryIndex = await getRegistryIndex()
|
||||
if (!registryIndex) {
|
||||
return null
|
||||
}
|
||||
|
||||
const tree = await resolveTree(registryIndex, registryDependencies)
|
||||
const payload = await fetchTree(config.style, tree)
|
||||
|
||||
if (!payload?.length) {
|
||||
return
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
payload.map(async (dependency) => {
|
||||
console.log(dependency)
|
||||
// const targetPath = await getRegistryItemFileTargetPath(file, config)
|
||||
|
||||
// if (!targetPath) {
|
||||
// return
|
||||
// }
|
||||
|
||||
// console.log(targetPath)
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -2,6 +2,10 @@ import { promises as fs } from "fs"
|
||||
import { tmpdir } from "os"
|
||||
import path from "path"
|
||||
import { Config } from "@/src/utils/get-config"
|
||||
import {
|
||||
RegistryItem,
|
||||
registryItemTailwindSchema,
|
||||
} from "@/src/utils/registry/schema"
|
||||
import deepmerge from "deepmerge"
|
||||
import objectToString from "stringify-object"
|
||||
import { type Config as TailwindConfig } from "tailwindcss"
|
||||
@@ -14,6 +18,7 @@ import {
|
||||
SyntaxKind,
|
||||
VariableStatement,
|
||||
} from "ts-morph"
|
||||
import { z } from "zod"
|
||||
|
||||
export type UpdaterTailwindConfig = Omit<TailwindConfig, "plugins"> & {
|
||||
// We only want string plugins for now.
|
||||
@@ -21,9 +26,14 @@ export type UpdaterTailwindConfig = Omit<TailwindConfig, "plugins"> & {
|
||||
}
|
||||
|
||||
export async function updateTailwindConfig(
|
||||
tailwindConfig: UpdaterTailwindConfig,
|
||||
tailwindConfig:
|
||||
| z.infer<typeof registryItemTailwindSchema>["config"]
|
||||
| undefined,
|
||||
config: Config
|
||||
) {
|
||||
if (!tailwindConfig) {
|
||||
return
|
||||
}
|
||||
const raw = await fs.readFile(config.resolvedPaths.tailwindConfig, "utf8")
|
||||
const output = await transformTailwindConfig(raw, tailwindConfig, config)
|
||||
await fs.writeFile(config.resolvedPaths.tailwindConfig, output, "utf8")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { promises as fs } from "fs"
|
||||
import { Config } from "@/src/utils/get-config"
|
||||
import { registryCssVarsSchema } from "@/src/utils/registry/schema"
|
||||
import { registryItemCssVarsSchema } from "@/src/utils/registry/schema"
|
||||
import postcss from "postcss"
|
||||
import AtRule from "postcss/lib/at-rule"
|
||||
import Root from "postcss/lib/root"
|
||||
@@ -8,9 +8,13 @@ import Rule from "postcss/lib/rule"
|
||||
import { z } from "zod"
|
||||
|
||||
export async function updateTailwindCss(
|
||||
cssVars: z.infer<typeof registryCssVarsSchema>,
|
||||
cssVars: z.infer<typeof registryItemCssVarsSchema> | undefined,
|
||||
config: Config
|
||||
) {
|
||||
if (!cssVars) {
|
||||
return
|
||||
}
|
||||
|
||||
const raw = await fs.readFile(config.resolvedPaths.tailwindCss, "utf8")
|
||||
let output = await transformTailwindCss(raw, cssVars)
|
||||
|
||||
@@ -19,7 +23,7 @@ export async function updateTailwindCss(
|
||||
|
||||
export async function transformTailwindCss(
|
||||
input: string,
|
||||
cssVars: z.infer<typeof registryCssVarsSchema>
|
||||
cssVars: z.infer<typeof registryItemCssVarsSchema>
|
||||
) {
|
||||
const result = await postcss([
|
||||
updateCssVarsPlugin(cssVars),
|
||||
@@ -94,7 +98,9 @@ function updateBaseLayerPlugin() {
|
||||
}
|
||||
}
|
||||
|
||||
function updateCssVarsPlugin(cssVars: z.infer<typeof registryCssVarsSchema>) {
|
||||
function updateCssVarsPlugin(
|
||||
cssVars: z.infer<typeof registryItemCssVarsSchema>
|
||||
) {
|
||||
return {
|
||||
postcssPlugin: "update-css-vars",
|
||||
Once(root: Root) {
|
||||
@@ -140,7 +146,7 @@ function addOrUpdateVars(
|
||||
}
|
||||
|
||||
Object.entries(vars).forEach(([key, value]) => {
|
||||
const prop = `--${key}`
|
||||
const prop = `--${key.replace(/^--/, "")}`
|
||||
const newDecl = postcss.decl({
|
||||
prop,
|
||||
value,
|
||||
|
||||
Reference in New Issue
Block a user