shadcn-nuxt
Version:
Add shadcn-vue module to Nuxt
62 lines (59 loc) • 2.19 kB
JavaScript
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 };