UNPKG

shadcn-nuxt

Version:
62 lines (59 loc) 2.19 kB
import { existsSync, readdirSync, readFileSync } from 'node:fs'; import { join } from 'node:path'; import { defineNuxtModule, createResolver, addComponent } from '@nuxt/kit'; import { parseSync } from 'oxc-parser'; const module = defineNuxtModule({ meta: { name: "shadcn", configKey: "shadcn" }, defaults: { prefix: "Ui", componentDir: "@/components/ui" }, async setup({ prefix, componentDir }, nuxt) { const COMPONENT_DIR_PATH = componentDir; const ROOT_DIR_PATH = nuxt.options.rootDir; const { resolve, resolvePath } = createResolver(ROOT_DIR_PATH); const componentsPath = await resolvePath(COMPONENT_DIR_PATH); if (!existsSync(componentsPath)) { console.warn(`Component directory does not exist: ${componentsPath}`); return; } nuxt.hook("components:dirs", (dirs) => { dirs.unshift({ path: componentsPath, extensions: [] }); }); try { readdirSync(componentsPath).forEach(async (dir) => { try { const filePath = await resolvePath(join(COMPONENT_DIR_PATH, dir, "index"), { extensions: [".ts", ".js"] }); const content = readFileSync(filePath, { encoding: "utf8" }); const ast = parseSync(filePath, content, { sourceType: "module" }); const exportedKeys = ast.program.body.filter((node) => node.type === "ExportNamedDeclaration").flatMap((node) => node.specifiers?.map((specifier) => specifier.exported?.name) || []).filter((key) => /^[A-Z]/.test(key)); exportedKeys.forEach((key) => { addComponent({ name: `${prefix}${key}`, // name of the component to be used in vue templates export: key, // (optional) if the component is a named (rather than default) export filePath: resolve(filePath), priority: 1 }); }); } catch (err) { if (err instanceof Error) console.warn("Module error: ", err.message); } }); } catch (err) { if (err instanceof Error) console.warn(err.message); } } }); export { module as default };