reborn-ui 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -0
- package/dist/index.js +871 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
- package/registry/.gitkeep +2 -0
- package/registry/components/animate-grid.json +18 -0
- package/registry/components/animated-beam.json +16 -0
- package/registry/components/animated-circular-progressbar.json +16 -0
- package/registry/components/animated-list.json +22 -0
- package/registry/components/animated-testimonials.json +18 -0
- package/registry/components/animated-tooltip.json +18 -0
- package/registry/components/apple-card-carousel.json +35 -0
- package/registry/components/aurora-background.json +16 -0
- package/registry/components/balance-slider.json +16 -0
- package/registry/components/bending-gallery.json +18 -0
- package/registry/components/bento-grid.json +24 -0
- package/registry/components/bg-black-hole.json +14 -0
- package/registry/components/bg-bubbles.json +18 -0
- package/registry/components/bg-falling-stars.json +16 -0
- package/registry/components/bg-neural.json +14 -0
- package/registry/components/bg-particle-whirlpool.json +18 -0
- package/registry/components/bg-silk.json +16 -0
- package/registry/components/bg-stars.json +18 -0
- package/registry/components/bg-stractium.json +16 -0
- package/registry/components/blur-reveal.json +18 -0
- package/registry/components/book.json +28 -0
- package/registry/components/border-beam.json +16 -0
- package/registry/components/box-reveal.json +18 -0
- package/registry/components/card-3d.json +24 -0
- package/registry/components/card-spotlight.json +16 -0
- package/registry/components/carousel-3d.json +15 -0
- package/registry/components/color-picker.json +26 -0
- package/registry/components/colourful-text.json +18 -0
- package/registry/components/compare.json +22 -0
- package/registry/components/confetti.json +22 -0
- package/registry/components/container-scroll.json +26 -0
- package/registry/components/container-text-flip.json +19 -0
- package/registry/components/cosmic-portal.json +18 -0
- package/registry/components/direction-aware-hover.json +16 -0
- package/registry/components/dock.json +32 -0
- package/registry/components/expandable-gallery.json +16 -0
- package/registry/components/file-tree.json +28 -0
- package/registry/components/file-upload.json +22 -0
- package/registry/components/flickering-grid.json +16 -0
- package/registry/components/flip-card.json +16 -0
- package/registry/components/flip-words.json +16 -0
- package/registry/components/fluid-cursor.json +16 -0
- package/registry/components/focus.json +16 -0
- package/registry/components/github-globe.json +23 -0
- package/registry/components/glare-card.json +18 -0
- package/registry/components/globe.json +19 -0
- package/registry/components/glow-border.json +16 -0
- package/registry/components/glowing-effect.json +18 -0
- package/registry/components/gradient-button.json +16 -0
- package/registry/components/halo-search.json +16 -0
- package/registry/components/hyper-text.json +19 -0
- package/registry/components/icon-cloud.json +16 -0
- package/registry/components/image-trail-cursor.json +22 -0
- package/registry/components/images-slider.json +18 -0
- package/registry/components/infinite-grid.json +47 -0
- package/registry/components/input.json +18 -0
- package/registry/components/interactive-grid-pattern.json +16 -0
- package/registry/components/interactive-hover-button.json +16 -0
- package/registry/components/iphone-mockup.json +16 -0
- package/registry/components/lamp-effect.json +16 -0
- package/registry/components/lens.json +18 -0
- package/registry/components/letter-pullup.json +18 -0
- package/registry/components/light-speed.json +31 -0
- package/registry/components/line-shadow-text.json +16 -0
- package/registry/components/link-preview.json +16 -0
- package/registry/components/liquid-background.json +18 -0
- package/registry/components/liquid-glass.json +16 -0
- package/registry/components/liquid-logo.json +24 -0
- package/registry/components/logo-cloud.json +24 -0
- package/registry/components/logo-origami.json +22 -0
- package/registry/components/marquee.json +20 -0
- package/registry/components/meteors.json +16 -0
- package/registry/components/morphing-tabs.json +16 -0
- package/registry/components/morphing-text.json +16 -0
- package/registry/components/multi-step-loader.json +16 -0
- package/registry/components/neon-border.json +16 -0
- package/registry/components/number-ticker.json +18 -0
- package/registry/components/orbit.json +16 -0
- package/registry/components/particle-image.json +24 -0
- package/registry/components/particles-bg.json +18 -0
- package/registry/components/pattern-background.json +18 -0
- package/registry/components/photo-gallery.json +16 -0
- package/registry/components/radiant-text.json +16 -0
- package/registry/components/rainbow-button.json +16 -0
- package/registry/components/ripple-button.json +16 -0
- package/registry/components/ripple.json +24 -0
- package/registry/components/safari-mockup.json +16 -0
- package/registry/components/scratch-to-reveal.json +18 -0
- package/registry/components/scroll-island.json +20 -0
- package/registry/components/shader-toy.json +22 -0
- package/registry/components/shimmer-button.json +16 -0
- package/registry/components/sleek-line-cursor.json +12 -0
- package/registry/components/smooth-cursor.json +23 -0
- package/registry/components/snowfall-bg.json +18 -0
- package/registry/components/sparkles-text.json +18 -0
- package/registry/components/sparkles.json +18 -0
- package/registry/components/spinning-text.json +18 -0
- package/registry/components/spline.json +23 -0
- package/registry/components/spring-calendar.json +22 -0
- package/registry/components/svg-mask.json +16 -0
- package/registry/components/tailed-cursor.json +14 -0
- package/registry/components/testimonial-slider.json +16 -0
- package/registry/components/tetris.json +19 -0
- package/registry/components/text-3d.json +16 -0
- package/registry/components/text-generate-effect.json +16 -0
- package/registry/components/text-glitch.json +12 -0
- package/registry/components/text-highlight.json +16 -0
- package/registry/components/text-hover-effect.json +16 -0
- package/registry/components/text-reveal-card.json +20 -0
- package/registry/components/text-reveal.json +18 -0
- package/registry/components/text-scroll-reveal.json +20 -0
- package/registry/components/timeline.json +18 -0
- package/registry/components/tracing-beam.json +19 -0
- package/registry/components/vanishing-input.json +18 -0
- package/registry/components/video-text.json +16 -0
- package/registry/components/vortex.json +19 -0
- package/registry/components/warp-background.json +22 -0
- package/registry/components/wavy-background.json +19 -0
- package/registry/components/world-map.json +19 -0
- package/registry/registry.json +2007 -0
- package/templates/composables/useMouseState.ts +21 -0
- package/templates/lib/utils.ts +13 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,871 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { Command as Command4 } from "commander";
|
|
5
|
+
|
|
6
|
+
// src/commands/add.ts
|
|
7
|
+
import path4 from "path";
|
|
8
|
+
import { Command } from "commander";
|
|
9
|
+
import prompts from "prompts";
|
|
10
|
+
|
|
11
|
+
// src/utils/fs.ts
|
|
12
|
+
import { createHash } from "crypto";
|
|
13
|
+
import fs from "fs/promises";
|
|
14
|
+
import path from "path";
|
|
15
|
+
async function pathExists(p) {
|
|
16
|
+
try {
|
|
17
|
+
await fs.access(p);
|
|
18
|
+
return true;
|
|
19
|
+
} catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function ensureDir(dirPath) {
|
|
24
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
25
|
+
}
|
|
26
|
+
async function readJsonFile(filePath) {
|
|
27
|
+
const raw = await fs.readFile(filePath, "utf8");
|
|
28
|
+
return JSON.parse(raw);
|
|
29
|
+
}
|
|
30
|
+
async function writeJsonFile(filePath, data) {
|
|
31
|
+
await ensureDir(path.dirname(filePath));
|
|
32
|
+
await fs.writeFile(filePath, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
33
|
+
}
|
|
34
|
+
async function writeTextFile(filePath, content) {
|
|
35
|
+
await ensureDir(path.dirname(filePath));
|
|
36
|
+
await fs.writeFile(filePath, content, "utf8");
|
|
37
|
+
}
|
|
38
|
+
async function listFilesRecursive(dirPath, opts) {
|
|
39
|
+
const ignoreDirNames = opts?.ignoreDirNames ?? /* @__PURE__ */ new Set(["node_modules", ".git", ".nuxt", "dist", ".output"]);
|
|
40
|
+
const out = [];
|
|
41
|
+
async function walk(current) {
|
|
42
|
+
const entries = await fs.readdir(current, { withFileTypes: true });
|
|
43
|
+
for (const entry of entries) {
|
|
44
|
+
const p = path.join(current, entry.name);
|
|
45
|
+
if (entry.isDirectory()) {
|
|
46
|
+
if (ignoreDirNames.has(entry.name)) continue;
|
|
47
|
+
await walk(p);
|
|
48
|
+
} else if (entry.isFile()) {
|
|
49
|
+
out.push(p);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
await walk(dirPath);
|
|
54
|
+
return out;
|
|
55
|
+
}
|
|
56
|
+
async function copyDirRecursive(params) {
|
|
57
|
+
const { fromDir, toDir, overwrite } = params;
|
|
58
|
+
const ignoreFileNames = params.ignoreFileNames ?? /* @__PURE__ */ new Set([".DS_Store"]);
|
|
59
|
+
const entries = await fs.readdir(fromDir, { withFileTypes: true });
|
|
60
|
+
await ensureDir(toDir);
|
|
61
|
+
for (const entry of entries) {
|
|
62
|
+
if (ignoreFileNames.has(entry.name)) continue;
|
|
63
|
+
const from = path.join(fromDir, entry.name);
|
|
64
|
+
const to = path.join(toDir, entry.name);
|
|
65
|
+
if (entry.isDirectory()) {
|
|
66
|
+
await copyDirRecursive({ fromDir: from, toDir: to, overwrite, ignoreFileNames });
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (!entry.isFile()) continue;
|
|
70
|
+
if (!overwrite) {
|
|
71
|
+
try {
|
|
72
|
+
await fs.access(to);
|
|
73
|
+
continue;
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
await ensureDir(path.dirname(to));
|
|
78
|
+
await fs.copyFile(from, to);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function sha1(text) {
|
|
82
|
+
return createHash("sha1").update(text).digest("hex");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/utils/pm.ts
|
|
86
|
+
import fs2 from "fs/promises";
|
|
87
|
+
import path2 from "path";
|
|
88
|
+
import { execa } from "execa";
|
|
89
|
+
async function detectPackageManager(cwd) {
|
|
90
|
+
if (await pathExists(path2.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
91
|
+
if (await pathExists(path2.join(cwd, "yarn.lock"))) return "yarn";
|
|
92
|
+
if (await pathExists(path2.join(cwd, "package-lock.json"))) return "npm";
|
|
93
|
+
if (await pathExists(path2.join(cwd, "bun.lockb"))) return "bun";
|
|
94
|
+
return "pnpm";
|
|
95
|
+
}
|
|
96
|
+
async function readPackageJson(cwd) {
|
|
97
|
+
return await readJsonFile(path2.join(cwd, "package.json"));
|
|
98
|
+
}
|
|
99
|
+
function getMissingDeps(pkg, deps) {
|
|
100
|
+
const existing = /* @__PURE__ */ new Set([
|
|
101
|
+
...Object.keys(pkg.dependencies ?? {}),
|
|
102
|
+
...Object.keys(pkg.devDependencies ?? {})
|
|
103
|
+
]);
|
|
104
|
+
return deps.filter((d) => !existing.has(d));
|
|
105
|
+
}
|
|
106
|
+
async function installDeps(params) {
|
|
107
|
+
const { cwd, pm, deps, dev } = params;
|
|
108
|
+
if (!deps.length) return;
|
|
109
|
+
const args = [];
|
|
110
|
+
if (pm === "pnpm") args.push("add");
|
|
111
|
+
else if (pm === "npm") args.push("install");
|
|
112
|
+
else if (pm === "yarn") args.push("add");
|
|
113
|
+
else if (pm === "bun") args.push("add");
|
|
114
|
+
if (dev) {
|
|
115
|
+
if (pm === "npm") args.push("--save-dev");
|
|
116
|
+
else args.push("-D");
|
|
117
|
+
}
|
|
118
|
+
args.push(...deps);
|
|
119
|
+
await execa(pm, args, { cwd, stdio: "inherit" });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/utils/registry.ts
|
|
123
|
+
import path3 from "path";
|
|
124
|
+
import fs3 from "fs";
|
|
125
|
+
import { createRequire } from "module";
|
|
126
|
+
import { fileURLToPath } from "url";
|
|
127
|
+
var DEFAULT_CONFIG_PATH = "components.json";
|
|
128
|
+
function findNearestPackageRoot(from) {
|
|
129
|
+
let dir = path3.dirname(fileURLToPath(from));
|
|
130
|
+
while (true) {
|
|
131
|
+
if (fs3.existsSync(path3.join(dir, "package.json"))) return dir;
|
|
132
|
+
const parent = path3.dirname(dir);
|
|
133
|
+
if (parent === dir) return dir;
|
|
134
|
+
dir = parent;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
function defaultConfig() {
|
|
138
|
+
return {
|
|
139
|
+
schemaVersion: 1,
|
|
140
|
+
componentsDir: "components",
|
|
141
|
+
libDir: "lib",
|
|
142
|
+
composablesDir: "composables",
|
|
143
|
+
// 默认使用 CLI 包内置的 registry(随 reborn-ui 一起发布)
|
|
144
|
+
registry: "builtin",
|
|
145
|
+
// 项目根目录映射别名符号(默认 @)
|
|
146
|
+
aliasSymbol: "@"
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
async function loadConfig(cwd, configPath = DEFAULT_CONFIG_PATH) {
|
|
150
|
+
const abs = path3.isAbsolute(configPath) ? configPath : path3.join(cwd, configPath);
|
|
151
|
+
if (!await pathExists(abs)) return null;
|
|
152
|
+
return await readJsonFile(abs);
|
|
153
|
+
}
|
|
154
|
+
function resolveRegistryJsonPath(params) {
|
|
155
|
+
const { cwd, registry } = params;
|
|
156
|
+
if (!registry || registry === "builtin") {
|
|
157
|
+
const pkgRoot = findNearestPackageRoot(import.meta.url);
|
|
158
|
+
return path3.join(pkgRoot, "registry", "registry.json");
|
|
159
|
+
}
|
|
160
|
+
const looksLikePath = registry.includes("/") || registry.includes("\\") || registry.endsWith(".json");
|
|
161
|
+
if (looksLikePath) {
|
|
162
|
+
const abs = path3.isAbsolute(registry) ? registry : path3.join(cwd, registry);
|
|
163
|
+
return abs;
|
|
164
|
+
}
|
|
165
|
+
const require2 = createRequire(import.meta.url);
|
|
166
|
+
return require2.resolve(`${registry}/registry/registry.json`);
|
|
167
|
+
}
|
|
168
|
+
async function loadRegistry(params) {
|
|
169
|
+
const jsonPath = resolveRegistryJsonPath(params);
|
|
170
|
+
return await readJsonFile(jsonPath);
|
|
171
|
+
}
|
|
172
|
+
async function loadConfigCompat(cwd, configPath) {
|
|
173
|
+
if (configPath) return await loadConfig(cwd, configPath);
|
|
174
|
+
const primary = await loadConfig(cwd, DEFAULT_CONFIG_PATH);
|
|
175
|
+
if (primary) return primary;
|
|
176
|
+
return await loadConfig(cwd, "shadcn-docs.json");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// src/commands/add.ts
|
|
180
|
+
function rewriteImports(params) {
|
|
181
|
+
const { content, aliasSymbol } = params;
|
|
182
|
+
if (!aliasSymbol || aliasSymbol === "@") return content;
|
|
183
|
+
return content.replaceAll("@/", `${aliasSymbol}/`);
|
|
184
|
+
}
|
|
185
|
+
async function writeComponentFiles(params) {
|
|
186
|
+
const { cwd, componentsDir, aliasSymbol, component, overwrite } = params;
|
|
187
|
+
const baseDir = path4.join(cwd, componentsDir, component.name);
|
|
188
|
+
await ensureDir(baseDir);
|
|
189
|
+
for (const f of component.files) {
|
|
190
|
+
const target = path4.join(baseDir, ...f.path.split("/"));
|
|
191
|
+
if (!overwrite && await pathExists(target)) continue;
|
|
192
|
+
const nextContent = rewriteImports({ content: f.content, aliasSymbol });
|
|
193
|
+
await writeTextFile(target, nextContent);
|
|
194
|
+
}
|
|
195
|
+
return baseDir;
|
|
196
|
+
}
|
|
197
|
+
function addCommand() {
|
|
198
|
+
const cmd = new Command("add").description("\u5411\u9879\u76EE\u4E2D\u6DFB\u52A0\u7EC4\u4EF6\u4E0E\u76F8\u5173\u4F9D\u8D56").argument("[components...]", "\u7EC4\u4EF6\u540D\uFF08\u53EF\u591A\u4E2A\uFF09").option("--cwd <path>", "\u76EE\u6807\u9879\u76EE\u76EE\u5F55", process.cwd()).option("--pm <pm>", "\u5305\u7BA1\u7406\u5668\uFF1Apnpm|npm|yarn|bun").option("--yes", "\u8DF3\u8FC7\u4EA4\u4E92", false).option("--overwrite", "\u8986\u76D6\u5DF2\u5B58\u5728\u6587\u4EF6", false).option("--config <path>", "\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u76F8\u5BF9 cwd\uFF09", "components.json").option("--registry <pkgOrPath>", "\u8986\u76D6\u914D\u7F6E\u91CC\u7684 registry").option("--components-dir <path>", "\u8986\u76D6\u914D\u7F6E\u91CC\u7684 componentsDir").option("--lib-dir <path>", "\u8986\u76D6\u914D\u7F6E\u91CC\u7684 libDir").option("--alias-symbol <symbol>", "\u8986\u76D6\u914D\u7F6E\u91CC\u7684 aliasSymbol\uFF08\u9ED8\u8BA4 @\uFF09").action(async (components, opts) => {
|
|
199
|
+
const cwd = path4.resolve(opts.cwd);
|
|
200
|
+
const pm = opts.pm ?? await detectPackageManager(cwd);
|
|
201
|
+
const cfg = await loadConfigCompat(cwd, opts.config) ?? defaultConfig();
|
|
202
|
+
if (opts.registry) cfg.registry = opts.registry;
|
|
203
|
+
if (opts.componentsDir) cfg.componentsDir = opts.componentsDir;
|
|
204
|
+
if (opts.libDir) cfg.libDir = opts.libDir;
|
|
205
|
+
if (opts.aliasSymbol) cfg.aliasSymbol = opts.aliasSymbol;
|
|
206
|
+
const registry = await loadRegistry({ cwd, registry: cfg.registry });
|
|
207
|
+
let targets = components ?? [];
|
|
208
|
+
if (!targets.length) {
|
|
209
|
+
if (opts.yes) {
|
|
210
|
+
throw new Error("\u672A\u6307\u5B9A\u7EC4\u4EF6\u540D\uFF1B\u8BF7\u4F20\u5165\u7EC4\u4EF6\u53C2\u6570\u6216\u53BB\u6389 --yes \u4EE5\u4EA4\u4E92\u9009\u62E9\u3002");
|
|
211
|
+
}
|
|
212
|
+
const choices = registry.components.map((c) => ({
|
|
213
|
+
title: c.name,
|
|
214
|
+
value: c.name
|
|
215
|
+
}));
|
|
216
|
+
const res = await prompts(
|
|
217
|
+
[
|
|
218
|
+
{
|
|
219
|
+
type: "multiselect",
|
|
220
|
+
name: "selected",
|
|
221
|
+
message: "\u9009\u62E9\u8981\u6DFB\u52A0\u7684\u7EC4\u4EF6",
|
|
222
|
+
choices,
|
|
223
|
+
min: 1
|
|
224
|
+
}
|
|
225
|
+
],
|
|
226
|
+
{
|
|
227
|
+
onCancel: () => {
|
|
228
|
+
throw new Error("\u5DF2\u53D6\u6D88");
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
targets = res.selected ?? [];
|
|
233
|
+
}
|
|
234
|
+
const pkg = await readPackageJson(cwd);
|
|
235
|
+
const allDeps = /* @__PURE__ */ new Set();
|
|
236
|
+
for (const name of targets) {
|
|
237
|
+
const c = registry.components.find((x) => x.name === name);
|
|
238
|
+
if (!c) throw new Error(`registry \u4E2D\u4E0D\u5B58\u5728\u8BE5\u7EC4\u4EF6\uFF1A${name}`);
|
|
239
|
+
const outDir = await writeComponentFiles({
|
|
240
|
+
cwd,
|
|
241
|
+
componentsDir: cfg.componentsDir,
|
|
242
|
+
aliasSymbol: cfg.aliasSymbol ?? "@",
|
|
243
|
+
component: c,
|
|
244
|
+
overwrite: opts.overwrite
|
|
245
|
+
});
|
|
246
|
+
console.log(`\u5DF2\u5199\u5165\u7EC4\u4EF6\uFF1A${name} -> ${path4.relative(cwd, outDir)}`);
|
|
247
|
+
for (const dep of c.dependencies) allDeps.add(dep);
|
|
248
|
+
}
|
|
249
|
+
const missing = getMissingDeps(pkg, [...allDeps]);
|
|
250
|
+
await installDeps({ cwd, pm, deps: missing });
|
|
251
|
+
console.log(
|
|
252
|
+
`\u5B8C\u6210\uFF1A\u6DFB\u52A0 ${targets.length} \u4E2A\u7EC4\u4EF6\uFF1B\u8865\u88C5\u4F9D\u8D56 ${missing.length} \u4E2A\uFF08pm=${pm}\uFF09`
|
|
253
|
+
);
|
|
254
|
+
});
|
|
255
|
+
return cmd;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// src/commands/build.ts
|
|
259
|
+
import path5 from "path";
|
|
260
|
+
import fs4 from "fs/promises";
|
|
261
|
+
import fssync from "fs";
|
|
262
|
+
import { Command as Command2 } from "commander";
|
|
263
|
+
|
|
264
|
+
// src/utils/imports.ts
|
|
265
|
+
var IMPORT_RE = /\bfrom\s+["']([^"']+)["']|\bimport\(\s*["']([^"']+)["']\s*\)|\brequire\(\s*["']([^"']+)["']\s*\)/g;
|
|
266
|
+
function normalizePackageName(specifier) {
|
|
267
|
+
if (specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("@/") || specifier.startsWith("~/") || specifier.startsWith("#") || specifier.startsWith("virtual:")) {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
if (specifier.startsWith("@")) {
|
|
271
|
+
const parts = specifier.split("/");
|
|
272
|
+
if (parts.length >= 2) return `${parts[0]}/${parts[1]}`;
|
|
273
|
+
return specifier;
|
|
274
|
+
}
|
|
275
|
+
return specifier.split("/")[0] ?? null;
|
|
276
|
+
}
|
|
277
|
+
function extractNpmDependenciesFromText(text) {
|
|
278
|
+
const out = /* @__PURE__ */ new Set();
|
|
279
|
+
for (const match of text.matchAll(IMPORT_RE)) {
|
|
280
|
+
const spec = match[1] ?? match[2] ?? match[3];
|
|
281
|
+
if (!spec) continue;
|
|
282
|
+
const pkg = normalizePackageName(spec);
|
|
283
|
+
if (!pkg) continue;
|
|
284
|
+
out.add(pkg);
|
|
285
|
+
}
|
|
286
|
+
out.delete("nuxt");
|
|
287
|
+
out.delete("vue");
|
|
288
|
+
return [...out].sort();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// src/commands/build.ts
|
|
292
|
+
function isAllowedFile(filePath) {
|
|
293
|
+
const ext = path5.extname(filePath).toLowerCase();
|
|
294
|
+
return [
|
|
295
|
+
".vue",
|
|
296
|
+
".ts",
|
|
297
|
+
".js",
|
|
298
|
+
".json",
|
|
299
|
+
".css",
|
|
300
|
+
".md",
|
|
301
|
+
".svg"
|
|
302
|
+
].includes(ext);
|
|
303
|
+
}
|
|
304
|
+
function findWorkspaceRoot(startDir) {
|
|
305
|
+
let current = path5.resolve(startDir);
|
|
306
|
+
for (; ; ) {
|
|
307
|
+
const marker = path5.join(current, "pnpm-workspace.yaml");
|
|
308
|
+
if (fssync.existsSync(marker)) return current;
|
|
309
|
+
const parent = path5.dirname(current);
|
|
310
|
+
if (parent === current) return startDir;
|
|
311
|
+
current = parent;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function buildCommand() {
|
|
315
|
+
const cmd = new Command2("build").description("\uFF08\u5185\u90E8\uFF09\u626B\u63CF\u7EC4\u4EF6\u6E90\u7801\u5E76\u751F\u6210 registry JSON").option("--root <path>", "\u4ED3\u5E93\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4\u81EA\u52A8\u5411\u4E0A\u67E5\u627E pnpm-workspace.yaml\uFF09").option(
|
|
316
|
+
"--source <path>",
|
|
317
|
+
"\u7EC4\u4EF6\u6E90\u7801\u76EE\u5F55\uFF08\u76F8\u5BF9 root\uFF09",
|
|
318
|
+
"components/content/reborn"
|
|
319
|
+
).option(
|
|
320
|
+
"--out <path>",
|
|
321
|
+
"\u8F93\u51FA registry.json \u8DEF\u5F84\uFF08\u76F8\u5BF9 root\uFF09",
|
|
322
|
+
"packages/cli/registry/registry.json"
|
|
323
|
+
).option(
|
|
324
|
+
"--also-out <path>",
|
|
325
|
+
"\u989D\u5916\u518D\u8F93\u51FA\u4E00\u4EFD registry.json\uFF08\u53EF\u91CD\u590D\u4F20\u53C2\uFF09",
|
|
326
|
+
(val, acc) => {
|
|
327
|
+
acc.push(val);
|
|
328
|
+
return acc;
|
|
329
|
+
},
|
|
330
|
+
[]
|
|
331
|
+
).action(async (opts) => {
|
|
332
|
+
const rootDir = opts.root ? path5.resolve(opts.root) : findWorkspaceRoot(process.cwd());
|
|
333
|
+
const sourceDir = path5.join(rootDir, opts.source);
|
|
334
|
+
const outPath = path5.join(rootDir, opts.out);
|
|
335
|
+
const alsoOutPaths = (opts.alsoOut ?? []).map(
|
|
336
|
+
(p) => path5.join(rootDir, p)
|
|
337
|
+
);
|
|
338
|
+
const dirents = await fs4.readdir(sourceDir, { withFileTypes: true });
|
|
339
|
+
const componentDirs = dirents.filter((d) => d.isDirectory()).map((d) => path5.join(sourceDir, d.name)).sort((a, b) => a.localeCompare(b));
|
|
340
|
+
const components = [];
|
|
341
|
+
for (const absComponentDir of componentDirs) {
|
|
342
|
+
const name = path5.basename(absComponentDir);
|
|
343
|
+
const absFiles = (await listFilesRecursive(absComponentDir)).filter(
|
|
344
|
+
isAllowedFile
|
|
345
|
+
);
|
|
346
|
+
const files = [];
|
|
347
|
+
const depSet = /* @__PURE__ */ new Set();
|
|
348
|
+
for (const absFile of absFiles) {
|
|
349
|
+
const rel = path5.relative(absComponentDir, absFile).split(path5.sep).join("/");
|
|
350
|
+
const content = await fs4.readFile(absFile, "utf8");
|
|
351
|
+
files.push({ path: rel, content });
|
|
352
|
+
const ext = path5.extname(absFile).toLowerCase();
|
|
353
|
+
if (ext === ".ts" || ext === ".js" || ext === ".vue") {
|
|
354
|
+
for (const dep of extractNpmDependenciesFromText(content)) {
|
|
355
|
+
depSet.add(dep);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
components.push({
|
|
360
|
+
name,
|
|
361
|
+
dependencies: [...depSet].sort(),
|
|
362
|
+
files
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
const registry = {
|
|
366
|
+
schemaVersion: 1,
|
|
367
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
368
|
+
source: {
|
|
369
|
+
rootDir: rootDir.split(path5.sep).join("/"),
|
|
370
|
+
componentsDir: opts.source
|
|
371
|
+
},
|
|
372
|
+
components
|
|
373
|
+
};
|
|
374
|
+
async function writeOut(targetRegistryPath) {
|
|
375
|
+
const outComponentsDir = path5.join(
|
|
376
|
+
path5.dirname(targetRegistryPath),
|
|
377
|
+
"components"
|
|
378
|
+
);
|
|
379
|
+
await writeJsonFile(targetRegistryPath, registry);
|
|
380
|
+
await fs4.mkdir(outComponentsDir, { recursive: true });
|
|
381
|
+
for (const c of components) {
|
|
382
|
+
await writeJsonFile(
|
|
383
|
+
path5.join(outComponentsDir, `${c.name}.json`),
|
|
384
|
+
{
|
|
385
|
+
...c,
|
|
386
|
+
fileCount: c.files.length,
|
|
387
|
+
contentHash: sha1(JSON.stringify(c.files.map((f) => f.content)))
|
|
388
|
+
}
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
await writeOut(outPath);
|
|
393
|
+
for (const p of alsoOutPaths) await writeOut(p);
|
|
394
|
+
console.log(
|
|
395
|
+
`registry \u5DF2\u751F\u6210\uFF1A${path5.relative(process.cwd(), outPath)}\uFF08${components.length} \u4E2A\u7EC4\u4EF6\uFF09`
|
|
396
|
+
);
|
|
397
|
+
});
|
|
398
|
+
return cmd;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// src/commands/init.ts
|
|
402
|
+
import path7 from "path";
|
|
403
|
+
import fs6 from "fs/promises";
|
|
404
|
+
import { Command as Command3 } from "commander";
|
|
405
|
+
import prompts2 from "prompts";
|
|
406
|
+
|
|
407
|
+
// src/utils/templates.ts
|
|
408
|
+
import path6 from "path";
|
|
409
|
+
import fs5 from "fs";
|
|
410
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
411
|
+
function findNearestPackageRoot2(from) {
|
|
412
|
+
let dir = path6.dirname(fileURLToPath2(from));
|
|
413
|
+
while (true) {
|
|
414
|
+
if (fs5.existsSync(path6.join(dir, "package.json"))) return dir;
|
|
415
|
+
const parent = path6.dirname(dir);
|
|
416
|
+
if (parent === dir) return dir;
|
|
417
|
+
dir = parent;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function getTemplatesRootDir() {
|
|
421
|
+
const pkgRoot = findNearestPackageRoot2(import.meta.url);
|
|
422
|
+
return path6.join(pkgRoot, "templates");
|
|
423
|
+
}
|
|
424
|
+
async function copyTemplateSubdir(params) {
|
|
425
|
+
const templatesRoot = getTemplatesRootDir();
|
|
426
|
+
const fromDir = path6.join(templatesRoot, params.subdir);
|
|
427
|
+
if (!await pathExists(fromDir)) return false;
|
|
428
|
+
const toDir = path6.join(params.cwd, params.targetDir);
|
|
429
|
+
await copyDirRecursive({ fromDir, toDir, overwrite: params.overwrite });
|
|
430
|
+
return true;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// src/commands/init.ts
|
|
434
|
+
function looksLikeNuxtProject(cwd) {
|
|
435
|
+
return Promise.all([
|
|
436
|
+
pathExists(path7.join(cwd, "nuxt.config.ts")),
|
|
437
|
+
pathExists(path7.join(cwd, "nuxt.config.js")),
|
|
438
|
+
pathExists(path7.join(cwd, "nuxt.config.mjs"))
|
|
439
|
+
]).then((arr) => arr.some(Boolean));
|
|
440
|
+
}
|
|
441
|
+
function isTailwindConfig(content) {
|
|
442
|
+
return content.includes("tailwind") || content.includes("content:");
|
|
443
|
+
}
|
|
444
|
+
function makeDefaultTailwindConfig(params) {
|
|
445
|
+
const { contentGlobs } = params;
|
|
446
|
+
const globs = contentGlobs.map((g) => ` "${g}",`).join("\n");
|
|
447
|
+
return `/** @type {import('tailwindcss').Config} */
|
|
448
|
+
export default {
|
|
449
|
+
darkMode: ['class'],
|
|
450
|
+
content: [
|
|
451
|
+
${globs}
|
|
452
|
+
],
|
|
453
|
+
theme: {
|
|
454
|
+
extend: {
|
|
455
|
+
colors: {
|
|
456
|
+
border: 'hsl(var(--border))',
|
|
457
|
+
input: 'hsl(var(--input))',
|
|
458
|
+
ring: 'hsl(var(--ring))',
|
|
459
|
+
background: 'hsl(var(--background))',
|
|
460
|
+
foreground: 'hsl(var(--foreground))',
|
|
461
|
+
primary: {
|
|
462
|
+
DEFAULT: 'hsl(var(--primary))',
|
|
463
|
+
foreground: 'hsl(var(--primary-foreground))',
|
|
464
|
+
},
|
|
465
|
+
secondary: {
|
|
466
|
+
DEFAULT: 'hsl(var(--secondary))',
|
|
467
|
+
foreground: 'hsl(var(--secondary-foreground))',
|
|
468
|
+
},
|
|
469
|
+
destructive: {
|
|
470
|
+
DEFAULT: 'hsl(var(--destructive))',
|
|
471
|
+
foreground: 'hsl(var(--destructive-foreground))',
|
|
472
|
+
},
|
|
473
|
+
muted: {
|
|
474
|
+
DEFAULT: 'hsl(var(--muted))',
|
|
475
|
+
foreground: 'hsl(var(--muted-foreground))',
|
|
476
|
+
},
|
|
477
|
+
accent: {
|
|
478
|
+
DEFAULT: 'hsl(var(--accent))',
|
|
479
|
+
foreground: 'hsl(var(--accent-foreground))',
|
|
480
|
+
},
|
|
481
|
+
popover: {
|
|
482
|
+
DEFAULT: 'hsl(var(--popover))',
|
|
483
|
+
foreground: 'hsl(var(--popover-foreground))',
|
|
484
|
+
},
|
|
485
|
+
card: {
|
|
486
|
+
DEFAULT: 'hsl(var(--card))',
|
|
487
|
+
foreground: 'hsl(var(--card-foreground))',
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
borderRadius: {
|
|
491
|
+
xl: 'calc(var(--radius) + 4px)',
|
|
492
|
+
lg: 'var(--radius)',
|
|
493
|
+
md: 'calc(var(--radius) - 2px)',
|
|
494
|
+
sm: 'calc(var(--radius) - 4px)',
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
},
|
|
498
|
+
plugins: [],
|
|
499
|
+
};
|
|
500
|
+
`;
|
|
501
|
+
}
|
|
502
|
+
function patchTailwindContentArray(existing, wantedGlobs) {
|
|
503
|
+
const m = existing.match(/content\s*:\s*\[([\s\S]*?)\]/m);
|
|
504
|
+
if (!m) return null;
|
|
505
|
+
const inner = m[1] ?? "";
|
|
506
|
+
const missing = wantedGlobs.filter((g) => !inner.includes(g));
|
|
507
|
+
if (!missing.length) return existing;
|
|
508
|
+
const insertion = missing.map((g) => ` "${g}",`).join("\n");
|
|
509
|
+
const replaced = existing.replace(
|
|
510
|
+
/content\s*:\s*\[([\s\S]*?)\]/m,
|
|
511
|
+
(full) => {
|
|
512
|
+
return full.replace(/\]\s*$/, `${insertion}
|
|
513
|
+
]`);
|
|
514
|
+
}
|
|
515
|
+
);
|
|
516
|
+
return replaced;
|
|
517
|
+
}
|
|
518
|
+
function defaultCssVariables() {
|
|
519
|
+
return `@tailwind base;
|
|
520
|
+
@tailwind components;
|
|
521
|
+
@tailwind utilities;
|
|
522
|
+
|
|
523
|
+
@layer base {
|
|
524
|
+
:root {
|
|
525
|
+
--background: 0 0% 100%;
|
|
526
|
+
--foreground: 222.2 84% 4.9%;
|
|
527
|
+
|
|
528
|
+
--card: 0 0% 100%;
|
|
529
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
530
|
+
|
|
531
|
+
--popover: 0 0% 100%;
|
|
532
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
533
|
+
|
|
534
|
+
--primary: 222.2 47.4% 11.2%;
|
|
535
|
+
--primary-foreground: 210 40% 98%;
|
|
536
|
+
|
|
537
|
+
--secondary: 210 40% 96.1%;
|
|
538
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
539
|
+
|
|
540
|
+
--muted: 210 40% 96.1%;
|
|
541
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
542
|
+
|
|
543
|
+
--accent: 210 40% 96.1%;
|
|
544
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
545
|
+
|
|
546
|
+
--destructive: 0 84.2% 60.2%;
|
|
547
|
+
--destructive-foreground: 210 40% 98%;
|
|
548
|
+
|
|
549
|
+
--border: 214.3 31.8% 91.4%;
|
|
550
|
+
--input: 214.3 31.8% 91.4%;
|
|
551
|
+
--ring: 222.2 84% 4.9%;
|
|
552
|
+
|
|
553
|
+
--radius: 0.5rem;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
.dark {
|
|
557
|
+
--background: 222.2 84% 4.9%;
|
|
558
|
+
--foreground: 210 40% 98%;
|
|
559
|
+
|
|
560
|
+
--card: 222.2 84% 4.9%;
|
|
561
|
+
--card-foreground: 210 40% 98%;
|
|
562
|
+
|
|
563
|
+
--popover: 222.2 84% 4.9%;
|
|
564
|
+
--popover-foreground: 210 40% 98%;
|
|
565
|
+
|
|
566
|
+
--primary: 210 40% 98%;
|
|
567
|
+
--primary-foreground: 222.2 47.4% 11.2%;
|
|
568
|
+
|
|
569
|
+
--secondary: 217.2 32.6% 17.5%;
|
|
570
|
+
--secondary-foreground: 210 40% 98%;
|
|
571
|
+
|
|
572
|
+
--muted: 217.2 32.6% 17.5%;
|
|
573
|
+
--muted-foreground: 215 20.2% 65.1%;
|
|
574
|
+
|
|
575
|
+
--accent: 217.2 32.6% 17.5%;
|
|
576
|
+
--accent-foreground: 210 40% 98%;
|
|
577
|
+
|
|
578
|
+
--destructive: 0 62.8% 30.6%;
|
|
579
|
+
--destructive-foreground: 210 40% 98%;
|
|
580
|
+
|
|
581
|
+
--border: 217.2 32.6% 17.5%;
|
|
582
|
+
--input: 217.2 32.6% 17.5%;
|
|
583
|
+
--ring: 212.7 26.8% 83.9%;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
`;
|
|
587
|
+
}
|
|
588
|
+
function cnUtilsTs(params) {
|
|
589
|
+
void params;
|
|
590
|
+
return `import { type ClassValue, clsx } from "clsx";
|
|
591
|
+
import { twMerge } from "tailwind-merge";
|
|
592
|
+
|
|
593
|
+
export function cn(...inputs: ClassValue[]) {
|
|
594
|
+
return twMerge(clsx(inputs));
|
|
595
|
+
}
|
|
596
|
+
`;
|
|
597
|
+
}
|
|
598
|
+
async function patchNuxtConfigAddCss(params) {
|
|
599
|
+
const { cwd, cssPath } = params;
|
|
600
|
+
const nuxtConfigPath = path7.join(cwd, "nuxt.config.ts");
|
|
601
|
+
if (!await pathExists(nuxtConfigPath)) return false;
|
|
602
|
+
const raw = await fs6.readFile(nuxtConfigPath, "utf8");
|
|
603
|
+
if (raw.includes(cssPath)) return true;
|
|
604
|
+
if (raw.match(/\bcss\s*:\s*\[/)) {
|
|
605
|
+
const patched2 = raw.replace(/\bcss\s*:\s*\[/, `css: ["${cssPath}", `);
|
|
606
|
+
await fs6.writeFile(nuxtConfigPath, patched2, "utf8");
|
|
607
|
+
return true;
|
|
608
|
+
}
|
|
609
|
+
const m = raw.match(/defineNuxtConfig\(\s*\{\s*/);
|
|
610
|
+
if (!m) return false;
|
|
611
|
+
const patched = raw.replace(
|
|
612
|
+
/defineNuxtConfig\(\s*\{\s*/,
|
|
613
|
+
(s) => `${s}
|
|
614
|
+
css: ["${cssPath}"],
|
|
615
|
+
`
|
|
616
|
+
);
|
|
617
|
+
await fs6.writeFile(nuxtConfigPath, patched, "utf8");
|
|
618
|
+
return true;
|
|
619
|
+
}
|
|
620
|
+
async function rewriteAliasInDir(params) {
|
|
621
|
+
const { cwd, targetDir, aliasSymbol } = params;
|
|
622
|
+
if (!aliasSymbol || aliasSymbol === "@") return;
|
|
623
|
+
const absDir = path7.join(cwd, targetDir);
|
|
624
|
+
if (!await pathExists(absDir)) return;
|
|
625
|
+
const files = await listFilesRecursive(absDir);
|
|
626
|
+
for (const f of files) {
|
|
627
|
+
const ext = path7.extname(f).toLowerCase();
|
|
628
|
+
if (![".ts", ".tsx", ".js", ".jsx", ".vue", ".mjs", ".cjs"].includes(ext)) continue;
|
|
629
|
+
const raw = await fs6.readFile(f, "utf8");
|
|
630
|
+
const next = raw.replaceAll("@/", `${aliasSymbol}/`);
|
|
631
|
+
if (next !== raw) await fs6.writeFile(f, next, "utf8");
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
function initCommand() {
|
|
635
|
+
const cmd = new Command3("init").description("\u521D\u59CB\u5316\u65B0\u9879\u76EE\uFF1A\u5B89\u88C5\u4F9D\u8D56\u3001\u751F\u6210 cn/utils\u3001\u914D\u7F6E tailwind \u4E0E CSS \u53D8\u91CF\uFF0C\u5E76\u5199\u5165 components.json").option("--cwd <path>", "\u76EE\u6807\u9879\u76EE\u76EE\u5F55", process.cwd()).option("--pm <pm>", "\u5305\u7BA1\u7406\u5668\uFF1Apnpm|npm|yarn|bun").option("--yes", "\u8DF3\u8FC7\u4EA4\u4E92\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u503C", false).option("--overwrite", "\u8986\u76D6\u5DF2\u5B58\u5728\u7684\u6A21\u677F\u6587\u4EF6\uFF08lib/composables\uFF09", false).option(
|
|
636
|
+
"--config <path>",
|
|
637
|
+
"\u914D\u7F6E\u6587\u4EF6\u8DEF\u5F84\uFF08\u76F8\u5BF9 cwd\uFF09",
|
|
638
|
+
DEFAULT_CONFIG_PATH
|
|
639
|
+
).option(
|
|
640
|
+
"--components-dir <path>",
|
|
641
|
+
"\u7EC4\u4EF6\u5199\u5165\u76EE\u5F55",
|
|
642
|
+
defaultConfig().componentsDir
|
|
643
|
+
).option(
|
|
644
|
+
"--lib-dir <path>",
|
|
645
|
+
"lib \u76EE\u5F55\uFF08cn/utils\uFF09",
|
|
646
|
+
defaultConfig().libDir
|
|
647
|
+
).option(
|
|
648
|
+
"--composables-dir <path>",
|
|
649
|
+
"composables \u76EE\u5F55",
|
|
650
|
+
defaultConfig().composablesDir
|
|
651
|
+
).option(
|
|
652
|
+
"--alias-symbol <symbol>",
|
|
653
|
+
"\u9879\u76EE\u6839\u76EE\u5F55\u6620\u5C04\u522B\u540D\u7B26\u53F7\uFF08\u9ED8\u8BA4 @\uFF09",
|
|
654
|
+
defaultConfig().aliasSymbol
|
|
655
|
+
).option("--registry <pkgOrPath>", "registry \u6765\u6E90\uFF08\u9ED8\u8BA4 builtin\uFF09", defaultConfig().registry).action(async (opts) => {
|
|
656
|
+
const cwd = path7.resolve(opts.cwd);
|
|
657
|
+
console.log(
|
|
658
|
+
"\u63D0\u793A\uFF1A\u9879\u76EE\u4E2D\u6709\u90E8\u5206\u4F9D\u8D56\u9700\u8981\u4F7F\u7528@/ \u8DEF\u5F84\u8FDB\u884C\u914D\u7F6E\uFF0C\u8BF7\u60A8\u5B89\u88C5\u5230\u9879\u76EE\u4E2D\u914D\u7F6E\u597D\u7684\u8DEF\u5F84\u4E0B\uFF0C\u8BF7\u614E\u91CD\u9009\u62E9\u6587\u4EF6\u4F4D\u7F6E"
|
|
659
|
+
);
|
|
660
|
+
const pkgPath = path7.join(cwd, "package.json");
|
|
661
|
+
if (!await pathExists(pkgPath)) {
|
|
662
|
+
throw new Error(`\u672A\u627E\u5230 package.json\uFF1A${pkgPath}`);
|
|
663
|
+
}
|
|
664
|
+
const pm = opts.pm ?? await detectPackageManager(cwd);
|
|
665
|
+
const cfg = {
|
|
666
|
+
schemaVersion: 1,
|
|
667
|
+
componentsDir: opts.componentsDir,
|
|
668
|
+
libDir: opts.libDir,
|
|
669
|
+
composablesDir: opts.composablesDir,
|
|
670
|
+
aliasSymbol: opts.aliasSymbol,
|
|
671
|
+
registry: opts.registry
|
|
672
|
+
};
|
|
673
|
+
const existing = await loadConfigCompat(cwd);
|
|
674
|
+
if (existing) {
|
|
675
|
+
cfg.componentsDir = opts.componentsDir ?? existing.componentsDir ?? cfg.componentsDir;
|
|
676
|
+
cfg.libDir = opts.libDir ?? existing.libDir ?? cfg.libDir;
|
|
677
|
+
cfg.composablesDir = opts.composablesDir ?? existing.composablesDir ?? cfg.composablesDir;
|
|
678
|
+
cfg.aliasSymbol = opts.aliasSymbol ?? existing.aliasSymbol ?? cfg.aliasSymbol;
|
|
679
|
+
cfg.registry = opts.registry ?? existing.registry ?? cfg.registry;
|
|
680
|
+
}
|
|
681
|
+
if (!opts.yes) {
|
|
682
|
+
const nuxt = await looksLikeNuxtProject(cwd);
|
|
683
|
+
const res = await prompts2(
|
|
684
|
+
[
|
|
685
|
+
{
|
|
686
|
+
type: "text",
|
|
687
|
+
name: "componentsDir",
|
|
688
|
+
message: "\u7EC4\u4EF6\u76EE\u5F55\uFF08componentsDir\uFF09",
|
|
689
|
+
initial: cfg.componentsDir
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
type: "text",
|
|
693
|
+
name: "libDir",
|
|
694
|
+
message: "lib \u76EE\u5F55\uFF08libDir\uFF0C\u7528\u4E8E cn/utils\uFF09",
|
|
695
|
+
initial: cfg.libDir
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
type: "text",
|
|
699
|
+
name: "composablesDir",
|
|
700
|
+
message: "composables \u76EE\u5F55\uFF08composablesDir\uFF09",
|
|
701
|
+
initial: cfg.composablesDir
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
type: "text",
|
|
705
|
+
name: "aliasSymbol",
|
|
706
|
+
message: "\u57FA\u4E8E\u9879\u76EE\u6839\u76EE\u5F55\u7684\u201C\u6620\u5C04\u201D\u7684\u7B26\u53F7\u662F\uFF1F\uFF08aliasSymbol\uFF09",
|
|
707
|
+
initial: cfg.aliasSymbol ?? "@"
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
type: "text",
|
|
711
|
+
name: "registry",
|
|
712
|
+
message: "registry\uFF08\u5305\u540D\u6216\u8DEF\u5F84\uFF09",
|
|
713
|
+
initial: cfg.registry
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
type: "confirm",
|
|
717
|
+
name: "installBaseDeps",
|
|
718
|
+
message: `\u5B89\u88C5\u57FA\u7840\u4F9D\u8D56\uFF08clsx\u3001tailwind-merge\u3001tailwindcss \u7B49\uFF09\uFF1F`,
|
|
719
|
+
initial: true
|
|
720
|
+
},
|
|
721
|
+
{
|
|
722
|
+
type: nuxt ? "confirm" : null,
|
|
723
|
+
name: "installDocs",
|
|
724
|
+
message: `\u68C0\u6D4B\u5230 Nuxt\uFF1A\u82E5\u7F3A\u5931\u5219\u5B89\u88C5 shadcn-docs-nuxt\uFF1F`,
|
|
725
|
+
initial: true
|
|
726
|
+
}
|
|
727
|
+
],
|
|
728
|
+
{
|
|
729
|
+
onCancel: () => {
|
|
730
|
+
throw new Error("\u5DF2\u53D6\u6D88");
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
);
|
|
734
|
+
cfg.componentsDir = res.componentsDir ?? cfg.componentsDir;
|
|
735
|
+
cfg.libDir = res.libDir ?? cfg.libDir;
|
|
736
|
+
cfg.composablesDir = res.composablesDir ?? cfg.composablesDir;
|
|
737
|
+
cfg.aliasSymbol = res.aliasSymbol ?? cfg.aliasSymbol;
|
|
738
|
+
cfg.registry = res.registry ?? cfg.registry;
|
|
739
|
+
const cfgPath2 = path7.join(cwd, opts.config);
|
|
740
|
+
await writeJsonFile(cfgPath2, cfg);
|
|
741
|
+
const pkg2 = await readPackageJson(cwd);
|
|
742
|
+
const wantDeps2 = [];
|
|
743
|
+
if (res.installBaseDeps)
|
|
744
|
+
wantDeps2.push("clsx", "tailwind-merge", "tailwindcss", "postcss", "autoprefixer");
|
|
745
|
+
if (res.installDocs) wantDeps2.push("shadcn-docs-nuxt");
|
|
746
|
+
const missing2 = getMissingDeps(pkg2, wantDeps2);
|
|
747
|
+
await installDeps({ cwd, pm, deps: missing2 });
|
|
748
|
+
await copyTemplateSubdir({
|
|
749
|
+
subdir: "lib",
|
|
750
|
+
cwd,
|
|
751
|
+
targetDir: cfg.libDir,
|
|
752
|
+
overwrite: opts.overwrite
|
|
753
|
+
});
|
|
754
|
+
await copyTemplateSubdir({
|
|
755
|
+
subdir: "composables",
|
|
756
|
+
cwd,
|
|
757
|
+
targetDir: cfg.composablesDir,
|
|
758
|
+
overwrite: opts.overwrite
|
|
759
|
+
});
|
|
760
|
+
await rewriteAliasInDir({ cwd, targetDir: cfg.libDir, aliasSymbol: cfg.aliasSymbol ?? "@" });
|
|
761
|
+
await rewriteAliasInDir({
|
|
762
|
+
cwd,
|
|
763
|
+
targetDir: cfg.composablesDir,
|
|
764
|
+
aliasSymbol: cfg.aliasSymbol ?? "@"
|
|
765
|
+
});
|
|
766
|
+
const libUtilsPath2 = path7.join(cwd, cfg.libDir, "utils.ts");
|
|
767
|
+
if (!await pathExists(libUtilsPath2)) await writeTextFile(libUtilsPath2, cnUtilsTs({}));
|
|
768
|
+
const cssRel2 = "assets/css/reborn-ui.css";
|
|
769
|
+
const cssAbs2 = path7.join(cwd, cssRel2);
|
|
770
|
+
if (!await pathExists(cssAbs2)) {
|
|
771
|
+
await writeTextFile(cssAbs2, defaultCssVariables());
|
|
772
|
+
}
|
|
773
|
+
const contentGlobs2 = [
|
|
774
|
+
"./components/**/*.{vue,js,ts}",
|
|
775
|
+
"./layouts/**/*.{vue,js,ts}",
|
|
776
|
+
"./pages/**/*.{vue,js,ts}",
|
|
777
|
+
"./plugins/**/*.{js,ts}",
|
|
778
|
+
"./app.vue",
|
|
779
|
+
"./error.vue",
|
|
780
|
+
"./content/**/*.{md,yml,yaml,json}",
|
|
781
|
+
`./${cfg.componentsDir}/**/*.{vue,js,ts}`,
|
|
782
|
+
`./${cfg.composablesDir}/**/*.{js,ts}`
|
|
783
|
+
];
|
|
784
|
+
const twPath2 = path7.join(cwd, "tailwind.config.js");
|
|
785
|
+
if (await pathExists(twPath2)) {
|
|
786
|
+
const rawTw = await fs6.readFile(twPath2, "utf8");
|
|
787
|
+
if (isTailwindConfig(rawTw)) {
|
|
788
|
+
const patched = patchTailwindContentArray(rawTw, contentGlobs2);
|
|
789
|
+
if (patched && patched !== rawTw) {
|
|
790
|
+
await fs6.writeFile(twPath2, patched, "utf8");
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
} else {
|
|
794
|
+
await writeTextFile(
|
|
795
|
+
twPath2,
|
|
796
|
+
makeDefaultTailwindConfig({ contentGlobs: contentGlobs2 })
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
await patchNuxtConfigAddCss({ cwd, cssPath: `~/${cssRel2}` });
|
|
800
|
+
console.log(
|
|
801
|
+
`\u5DF2\u5199\u5165\u914D\u7F6E\uFF1A${path7.relative(process.cwd(), cfgPath2)}\uFF1B\u5E76\u751F\u6210 cn/utils\u3001tailwind \u914D\u7F6E\u4E0E CSS \u53D8\u91CF\uFF08pm=${pm}\uFF09`
|
|
802
|
+
);
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
const cfgPath = path7.join(cwd, opts.config);
|
|
806
|
+
await ensureDir(path7.dirname(cfgPath));
|
|
807
|
+
await fs6.writeFile(cfgPath, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
808
|
+
const pkg = await readPackageJson(cwd);
|
|
809
|
+
const wantDeps = ["clsx", "tailwind-merge", "tailwindcss", "postcss", "autoprefixer"];
|
|
810
|
+
if (await looksLikeNuxtProject(cwd)) wantDeps.push("shadcn-docs-nuxt");
|
|
811
|
+
const missing = getMissingDeps(pkg, wantDeps);
|
|
812
|
+
await installDeps({ cwd, pm, deps: missing });
|
|
813
|
+
await copyTemplateSubdir({
|
|
814
|
+
subdir: "lib",
|
|
815
|
+
cwd,
|
|
816
|
+
targetDir: cfg.libDir,
|
|
817
|
+
overwrite: opts.overwrite
|
|
818
|
+
});
|
|
819
|
+
await copyTemplateSubdir({
|
|
820
|
+
subdir: "composables",
|
|
821
|
+
cwd,
|
|
822
|
+
targetDir: cfg.composablesDir,
|
|
823
|
+
overwrite: opts.overwrite
|
|
824
|
+
});
|
|
825
|
+
await rewriteAliasInDir({ cwd, targetDir: cfg.libDir, aliasSymbol: cfg.aliasSymbol ?? "@" });
|
|
826
|
+
await rewriteAliasInDir({
|
|
827
|
+
cwd,
|
|
828
|
+
targetDir: cfg.composablesDir,
|
|
829
|
+
aliasSymbol: cfg.aliasSymbol ?? "@"
|
|
830
|
+
});
|
|
831
|
+
const libUtilsPath = path7.join(cwd, cfg.libDir, "utils.ts");
|
|
832
|
+
if (!await pathExists(libUtilsPath)) await writeTextFile(libUtilsPath, cnUtilsTs({}));
|
|
833
|
+
const cssRel = "assets/css/reborn-ui.css";
|
|
834
|
+
const cssAbs = path7.join(cwd, cssRel);
|
|
835
|
+
if (!await pathExists(cssAbs)) {
|
|
836
|
+
await writeTextFile(cssAbs, defaultCssVariables());
|
|
837
|
+
}
|
|
838
|
+
const contentGlobs = [
|
|
839
|
+
"./components/**/*.{vue,js,ts}",
|
|
840
|
+
"./layouts/**/*.{vue,js,ts}",
|
|
841
|
+
"./pages/**/*.{vue,js,ts}",
|
|
842
|
+
"./plugins/**/*.{js,ts}",
|
|
843
|
+
"./app.vue",
|
|
844
|
+
"./error.vue",
|
|
845
|
+
"./content/**/*.{md,yml,yaml,json}",
|
|
846
|
+
`./${cfg.componentsDir}/**/*.{vue,js,ts}`,
|
|
847
|
+
`./${cfg.composablesDir}/**/*.{js,ts}`
|
|
848
|
+
];
|
|
849
|
+
const twPath = path7.join(cwd, "tailwind.config.js");
|
|
850
|
+
if (await pathExists(twPath)) {
|
|
851
|
+
const rawTw = await fs6.readFile(twPath, "utf8");
|
|
852
|
+
const patched = patchTailwindContentArray(rawTw, contentGlobs);
|
|
853
|
+
if (patched && patched !== rawTw) await fs6.writeFile(twPath, patched, "utf8");
|
|
854
|
+
} else {
|
|
855
|
+
await writeTextFile(twPath, makeDefaultTailwindConfig({ contentGlobs }));
|
|
856
|
+
}
|
|
857
|
+
await patchNuxtConfigAddCss({ cwd, cssPath: `~/${cssRel}` });
|
|
858
|
+
console.log(
|
|
859
|
+
`\u5DF2\u521D\u59CB\u5316\uFF1A${path7.relative(process.cwd(), cfgPath)}\uFF1B\u5E76\u751F\u6210 cn/utils\u3001tailwind \u914D\u7F6E\u4E0E CSS \u53D8\u91CF\uFF08pm=${pm}\uFF09`
|
|
860
|
+
);
|
|
861
|
+
});
|
|
862
|
+
return cmd;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// src/index.ts
|
|
866
|
+
var program = new Command4().name("reborn-ui").description("Reborn UI - \u7EC4\u4EF6\u5B89\u88C5\u4E0E registry \u8F85\u52A9 CLI").version("0.1.0");
|
|
867
|
+
program.addCommand(initCommand());
|
|
868
|
+
program.addCommand(addCommand());
|
|
869
|
+
program.addCommand(buildCommand());
|
|
870
|
+
await program.parseAsync(process.argv);
|
|
871
|
+
//# sourceMappingURL=index.js.map
|