From 7d4dd65acd8bf5d6df2b6e0aea272dcbd4c5247f Mon Sep 17 00:00:00 2001 From: shadcn Date: Thu, 26 Feb 2026 15:27:34 +0400 Subject: [PATCH] fix --- apps/v4/components/component-source.tsx | 2 +- apps/v4/lib/format-code.ts | 112 +++++++++++++++++++++++ apps/v4/lib/rehype.ts | 113 +----------------------- 3 files changed, 117 insertions(+), 110 deletions(-) create mode 100644 apps/v4/lib/format-code.ts diff --git a/apps/v4/components/component-source.tsx b/apps/v4/components/component-source.tsx index 0721ce23f3..d31d0097e7 100644 --- a/apps/v4/components/component-source.tsx +++ b/apps/v4/components/component-source.tsx @@ -2,9 +2,9 @@ import fs from "node:fs/promises" import path from "node:path" import * as React from "react" +import { formatCode } from "@/lib/format-code" import { highlightCode } from "@/lib/highlight-code" import { getDemoItem, getRegistryItem } from "@/lib/registry" -import { formatCode } from "@/lib/rehype" import { cn } from "@/lib/utils" import { CodeCollapsibleWrapper } from "@/components/code-collapsible-wrapper" import { CopyButton } from "@/components/copy-button" diff --git a/apps/v4/lib/format-code.ts b/apps/v4/lib/format-code.ts new file mode 100644 index 0000000000..c812169de2 --- /dev/null +++ b/apps/v4/lib/format-code.ts @@ -0,0 +1,112 @@ +import { promises as fsPromises } from "fs" +import path from "path" +import { + createStyleMap, + transformIcons, + transformMenu, + transformRender, + transformStyle, +} from "shadcn/utils" +import { Project, ScriptKind } from "ts-morph" + +import { BASES } from "@/registry/bases" + +function getStyleFromStyleName(styleName: string) { + const parts = styleName.split("-") + return parts.length > 1 ? parts.slice(1).join("-") : styleName +} + +function buildDisplayConfig(styleName: string) { + return { + $schema: "https://ui.shadcn.com/schema.json", + style: styleName, + rsc: true, + tsx: true, + tailwind: { + config: "", + css: "", + baseColor: "neutral", + cssVariables: true, + prefix: "", + }, + iconLibrary: "lucide", + aliases: { + components: "@/components", + utils: "@/lib/utils", + ui: "@/components/ui", + lib: "@/lib", + hooks: "@/hooks", + }, + resolvedPaths: { + cwd: "/", + tailwindConfig: "", + tailwindCss: "", + utils: "@/lib/utils", + components: "@/components", + lib: "@/lib", + hooks: "@/hooks", + ui: "@/components/ui", + }, + } +} + +const styleMapCache = new Map>() + +async function getStyleMap(styleName: string) { + const style = getStyleFromStyleName(styleName) + + if (styleMapCache.has(style)) { + return styleMapCache.get(style)! + } + + try { + const cssPath = path.join( + process.cwd(), + `registry/styles/style-${style}.css` + ) + const css = await fsPromises.readFile(cssPath, "utf-8") + const styleMap = createStyleMap(css) + styleMapCache.set(style, styleMap) + return styleMap + } catch { + return {} + } +} + +export async function formatCode(code: string, styleName: string) { + code = code.replaceAll(`@/registry/${styleName}/`, "@/components/") + + for (const base of BASES) { + code = code.replaceAll(`@/registry/bases/${base.name}/`, "@/components/") + code = code.replaceAll(`@/examples/${base.name}/ui/`, "@/components/ui/") + code = code.replaceAll(`@/examples/${base.name}/lib/`, "@/lib/") + code = code.replaceAll(`@/examples/${base.name}/hooks/`, "@/hooks/") + } + + code = code.replaceAll("export default", "export") + + try { + const styleMap = await getStyleMap(styleName) + const transformed = await transformStyle(code, { styleMap }) + const config = buildDisplayConfig(styleName) + const project = new Project({ compilerOptions: {} }) + const sourceFile = project.createSourceFile("component.tsx", transformed, { + scriptKind: ScriptKind.TSX, + }) + + const transformers = [transformIcons, transformMenu, transformRender] + for (const transformer of transformers) { + await transformer({ + filename: "component.tsx", + raw: transformed, + sourceFile, + config, + }) + } + + return sourceFile.getText() + } catch (error) { + console.error("Transform failed:", error) + return code + } +} diff --git a/apps/v4/lib/rehype.ts b/apps/v4/lib/rehype.ts index 6690e1dc44..2db86066f6 100644 --- a/apps/v4/lib/rehype.ts +++ b/apps/v4/lib/rehype.ts @@ -1,22 +1,17 @@ -import fs, { promises as fsPromises } from "fs" +import fs from "fs" import path from "path" import { ExamplesIndex } from "@/examples/__index__" -import { - createStyleMap, - transformIcons, - transformMenu, - transformRender, - transformStyle, -} from "shadcn/utils" -import { Project, ScriptKind } from "ts-morph" import { u } from "unist-builder" import { visit } from "unist-util-visit" +import { formatCode } from "@/lib/format-code" import { Index as StylesIndex } from "@/registry/__index__" import { getActiveStyle } from "@/registry/_legacy-styles" import { BASES } from "@/registry/bases" import { Index as BasesIndex } from "@/registry/bases/__index__" +export { formatCode } from "@/lib/format-code" + function getBaseForStyle(styleName: string) { for (const base of BASES) { if (styleName.startsWith(`${base.name}-`)) { @@ -44,106 +39,6 @@ function getIndexForStyle(styleName: string) { return { index: StylesIndex, key: styleName } } -function getStyleFromStyleName(styleName: string) { - const parts = styleName.split("-") - return parts.length > 1 ? parts.slice(1).join("-") : styleName -} - -function buildDisplayConfig(styleName: string) { - return { - $schema: "https://ui.shadcn.com/schema.json", - style: styleName, - rsc: true, - tsx: true, - tailwind: { - config: "", - css: "", - baseColor: "neutral", - cssVariables: true, - prefix: "", - }, - iconLibrary: "lucide", - aliases: { - components: "@/components", - utils: "@/lib/utils", - ui: "@/components/ui", - lib: "@/lib", - hooks: "@/hooks", - }, - resolvedPaths: { - cwd: "/", - tailwindConfig: "", - tailwindCss: "", - utils: "@/lib/utils", - components: "@/components", - lib: "@/lib", - hooks: "@/hooks", - ui: "@/components/ui", - }, - } -} - -const styleMapCache = new Map>() - -async function getStyleMap(styleName: string) { - const style = getStyleFromStyleName(styleName) - - if (styleMapCache.has(style)) { - return styleMapCache.get(style)! - } - - try { - const cssPath = path.join( - process.cwd(), - `registry/styles/style-${style}.css` - ) - const css = await fsPromises.readFile(cssPath, "utf-8") - const styleMap = createStyleMap(css) - styleMapCache.set(style, styleMap) - return styleMap - } catch { - return {} - } -} - -export async function formatCode(code: string, styleName: string) { - code = code.replaceAll(`@/registry/${styleName}/`, "@/components/") - - for (const base of BASES) { - code = code.replaceAll(`@/registry/bases/${base.name}/`, "@/components/") - code = code.replaceAll(`@/examples/${base.name}/ui/`, "@/components/ui/") - code = code.replaceAll(`@/examples/${base.name}/lib/`, "@/lib/") - code = code.replaceAll(`@/examples/${base.name}/hooks/`, "@/hooks/") - } - - code = code.replaceAll("export default", "export") - - try { - const styleMap = await getStyleMap(styleName) - const transformed = await transformStyle(code, { styleMap }) - const config = buildDisplayConfig(styleName) - const project = new Project({ compilerOptions: {} }) - const sourceFile = project.createSourceFile("component.tsx", transformed, { - scriptKind: ScriptKind.TSX, - }) - - const transformers = [transformIcons, transformMenu, transformRender] - for (const transformer of transformers) { - await transformer({ - filename: "component.tsx", - raw: transformed, - sourceFile, - config, - }) - } - - return sourceFile.getText() - } catch (error) { - console.error("Transform failed:", error) - return code - } -} - interface UnistNode { type: string name?: string