create-velocity-astro 1.0.7 → 1.1.0
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/dist/index.js +210 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/i18n/src/components/landing/CTA.astro +1 -1
- package/templates/i18n/src/components/landing/Hero.astro +1 -1
- package/templates/i18n/src/components/landing/LandingFooter.astro +2 -2
- package/templates/i18n/src/components/landing/Navbar.astro +1 -1
- package/templates/i18n/src/i18n/translations/en.ts +184 -0
- package/templates/i18n/src/i18n/translations/es.ts +184 -0
- package/templates/i18n/src/i18n/translations/fr.ts +184 -0
- package/templates/i18n/src/pages/[lang]/components.astro +729 -0
- package/templates/i18n/src/pages/components.astro +717 -0
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import mri from "mri";
|
|
5
5
|
import { resolve as resolve2 } from "path";
|
|
6
|
-
import { existsSync as
|
|
6
|
+
import { existsSync as existsSync5 } from "fs";
|
|
7
7
|
import * as p3 from "@clack/prompts";
|
|
8
8
|
import pc2 from "picocolors";
|
|
9
9
|
|
|
@@ -63,6 +63,10 @@ function getInstallCommand(pm) {
|
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
// src/prompts.ts
|
|
66
|
+
function parsePageNames(input) {
|
|
67
|
+
if (!input.trim()) return [];
|
|
68
|
+
return input.split(",").map((name) => name.trim().toLowerCase()).filter((name) => name.length > 0).map((name) => name.replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "")).filter((name) => name.length > 0 && !["index", "blog", "404", "rss"].includes(name));
|
|
69
|
+
}
|
|
66
70
|
async function runPrompts(defaults = {}) {
|
|
67
71
|
const detectedPm = detectPackageManager();
|
|
68
72
|
const answers = await p.group(
|
|
@@ -125,6 +129,48 @@ async function runPrompts(defaults = {}) {
|
|
|
125
129
|
],
|
|
126
130
|
initialValue: false
|
|
127
131
|
}),
|
|
132
|
+
generatePages: defaults.pages !== void 0 ? () => Promise.resolve(defaults.pages) : () => p.select({
|
|
133
|
+
message: "Generate starter pages?",
|
|
134
|
+
options: [
|
|
135
|
+
{
|
|
136
|
+
value: false,
|
|
137
|
+
label: "No",
|
|
138
|
+
hint: "Create pages manually later"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
value: true,
|
|
142
|
+
label: "Yes",
|
|
143
|
+
hint: "Auto-generate page files with layout"
|
|
144
|
+
}
|
|
145
|
+
],
|
|
146
|
+
initialValue: false
|
|
147
|
+
}),
|
|
148
|
+
pageNames: ({ results }) => results.generatePages ? p.text({
|
|
149
|
+
message: "Enter page names (comma-separated):",
|
|
150
|
+
placeholder: "about, pricing, faq, contact",
|
|
151
|
+
validate: (value) => {
|
|
152
|
+
const pages = parsePageNames(value);
|
|
153
|
+
if (pages.length === 0) {
|
|
154
|
+
return "Please enter at least one valid page name";
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}) : Promise.resolve(""),
|
|
158
|
+
pageLayout: ({ results }) => results.generatePages ? p.select({
|
|
159
|
+
message: "Select layout for pages:",
|
|
160
|
+
options: [
|
|
161
|
+
{
|
|
162
|
+
value: "page",
|
|
163
|
+
label: "PageLayout",
|
|
164
|
+
hint: "Standard content pages (Header + Footer)"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
value: "landing",
|
|
168
|
+
label: "LandingLayout",
|
|
169
|
+
hint: "Marketing pages (Navbar + LandingFooter)"
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
initialValue: "page"
|
|
173
|
+
}) : Promise.resolve("page"),
|
|
128
174
|
packageManager: () => p.select({
|
|
129
175
|
message: "Which package manager?",
|
|
130
176
|
options: [
|
|
@@ -164,6 +210,8 @@ async function runPrompts(defaults = {}) {
|
|
|
164
210
|
demo: answers.demo,
|
|
165
211
|
components: answers.components,
|
|
166
212
|
i18n: answers.i18n,
|
|
213
|
+
pages: parsePageNames(answers.pageNames),
|
|
214
|
+
pageLayout: answers.pageLayout || "page",
|
|
167
215
|
packageManager: answers.packageManager
|
|
168
216
|
};
|
|
169
217
|
}
|
|
@@ -193,8 +241,8 @@ function showSuccess(message) {
|
|
|
193
241
|
}
|
|
194
242
|
|
|
195
243
|
// src/scaffold.ts
|
|
196
|
-
import { existsSync as
|
|
197
|
-
import { join } from "path";
|
|
244
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync, copyFileSync, readFileSync, writeFileSync as writeFileSync2, rmSync } from "fs";
|
|
245
|
+
import { join as join2 } from "path";
|
|
198
246
|
import * as p2 from "@clack/prompts";
|
|
199
247
|
import { execa as execa2 } from "execa";
|
|
200
248
|
import { downloadTemplate } from "giget";
|
|
@@ -234,6 +282,124 @@ async function initGit(targetDir) {
|
|
|
234
282
|
}
|
|
235
283
|
}
|
|
236
284
|
|
|
285
|
+
// src/features/pages.ts
|
|
286
|
+
import { existsSync as existsSync2, mkdirSync, writeFileSync } from "fs";
|
|
287
|
+
import { join } from "path";
|
|
288
|
+
function toTitle(slug) {
|
|
289
|
+
return slug.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
290
|
+
}
|
|
291
|
+
function generatePageTemplate(pageName, layout) {
|
|
292
|
+
const title = toTitle(pageName);
|
|
293
|
+
const layoutName = layout === "landing" ? "LandingLayout" : "PageLayout";
|
|
294
|
+
return `---
|
|
295
|
+
import ${layoutName} from '@/layouts/${layoutName}.astro';
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
<${layoutName}
|
|
299
|
+
title="${title}"
|
|
300
|
+
description="Add your description here"
|
|
301
|
+
>
|
|
302
|
+
<!-- Hero Section -->
|
|
303
|
+
<section class="py-20 bg-secondary">
|
|
304
|
+
<div class="container">
|
|
305
|
+
<h1 class="text-4xl font-bold text-foreground">${title}</h1>
|
|
306
|
+
<p class="mt-4 text-foreground-muted max-w-2xl">
|
|
307
|
+
Add your content here.
|
|
308
|
+
</p>
|
|
309
|
+
</div>
|
|
310
|
+
</section>
|
|
311
|
+
|
|
312
|
+
<!-- Content Section -->
|
|
313
|
+
<section class="py-16">
|
|
314
|
+
<div class="container">
|
|
315
|
+
<!-- Your content -->
|
|
316
|
+
</div>
|
|
317
|
+
</section>
|
|
318
|
+
</${layoutName}>
|
|
319
|
+
`;
|
|
320
|
+
}
|
|
321
|
+
function generateI18nPageTemplate(pageName, layout) {
|
|
322
|
+
const title = toTitle(pageName);
|
|
323
|
+
const layoutName = layout === "landing" ? "LandingLayout" : "PageLayout";
|
|
324
|
+
const titleKey = `${pageName.replace(/-/g, "_")}.title`;
|
|
325
|
+
const descKey = `${pageName.replace(/-/g, "_")}.description`;
|
|
326
|
+
return `---
|
|
327
|
+
import ${layoutName} from '@/layouts/${layoutName}.astro';
|
|
328
|
+
import { locales, isValidLocale, type Locale } from '@/i18n/config';
|
|
329
|
+
import { useTranslations } from '@/i18n/index';
|
|
330
|
+
|
|
331
|
+
export function getStaticPaths() {
|
|
332
|
+
return locales.map((lang) => ({
|
|
333
|
+
params: { lang },
|
|
334
|
+
}));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const { lang } = Astro.params;
|
|
338
|
+
|
|
339
|
+
if (!lang || !isValidLocale(lang)) {
|
|
340
|
+
return Astro.redirect('/');
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const locale = lang as Locale;
|
|
344
|
+
const t = useTranslations(locale);
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
<${layoutName}
|
|
348
|
+
title={t('${titleKey}') || '${title}'}
|
|
349
|
+
description={t('${descKey}') || 'Add your description here'}
|
|
350
|
+
lang={locale}
|
|
351
|
+
>
|
|
352
|
+
<!-- Hero Section -->
|
|
353
|
+
<section class="py-20 bg-secondary">
|
|
354
|
+
<div class="container">
|
|
355
|
+
<h1 class="text-4xl font-bold text-foreground">
|
|
356
|
+
{t('${titleKey}') || '${title}'}
|
|
357
|
+
</h1>
|
|
358
|
+
<p class="mt-4 text-foreground-muted max-w-2xl">
|
|
359
|
+
{t('${descKey}') || 'Add your content here.'}
|
|
360
|
+
</p>
|
|
361
|
+
</div>
|
|
362
|
+
</section>
|
|
363
|
+
|
|
364
|
+
<!-- Content Section -->
|
|
365
|
+
<section class="py-16">
|
|
366
|
+
<div class="container">
|
|
367
|
+
<!-- Your content -->
|
|
368
|
+
</div>
|
|
369
|
+
</section>
|
|
370
|
+
</${layoutName}>
|
|
371
|
+
`;
|
|
372
|
+
}
|
|
373
|
+
async function generatePages(targetDir, pages, layout, isI18n) {
|
|
374
|
+
const generatedFiles = [];
|
|
375
|
+
if (pages.length === 0) {
|
|
376
|
+
return generatedFiles;
|
|
377
|
+
}
|
|
378
|
+
const pagesDir = join(targetDir, "src", "pages");
|
|
379
|
+
if (!existsSync2(pagesDir)) {
|
|
380
|
+
mkdirSync(pagesDir, { recursive: true });
|
|
381
|
+
}
|
|
382
|
+
for (const pageName of pages) {
|
|
383
|
+
const filePath = join(pagesDir, `${pageName}.astro`);
|
|
384
|
+
const template = generatePageTemplate(pageName, layout);
|
|
385
|
+
writeFileSync(filePath, template);
|
|
386
|
+
generatedFiles.push(`src/pages/${pageName}.astro`);
|
|
387
|
+
}
|
|
388
|
+
if (isI18n) {
|
|
389
|
+
const langDir = join(pagesDir, "[lang]");
|
|
390
|
+
if (!existsSync2(langDir)) {
|
|
391
|
+
mkdirSync(langDir, { recursive: true });
|
|
392
|
+
}
|
|
393
|
+
for (const pageName of pages) {
|
|
394
|
+
const filePath = join(langDir, `${pageName}.astro`);
|
|
395
|
+
const template = generateI18nPageTemplate(pageName, layout);
|
|
396
|
+
writeFileSync(filePath, template);
|
|
397
|
+
generatedFiles.push(`src/pages/[lang]/${pageName}.astro`);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return generatedFiles;
|
|
401
|
+
}
|
|
402
|
+
|
|
237
403
|
// src/scaffold.ts
|
|
238
404
|
var TEMPLATE_REPO = "github:southwellmedia-dev/velocity";
|
|
239
405
|
var CLEANUP_ITEMS = [
|
|
@@ -258,13 +424,13 @@ var COMPONENTS_CONTENT = [
|
|
|
258
424
|
"src/pages/components.astro"
|
|
259
425
|
];
|
|
260
426
|
function copyTemplateFiles(src, dest) {
|
|
261
|
-
if (!
|
|
262
|
-
|
|
427
|
+
if (!existsSync3(dest)) {
|
|
428
|
+
mkdirSync2(dest, { recursive: true });
|
|
263
429
|
}
|
|
264
430
|
const entries = readdirSync(src, { withFileTypes: true });
|
|
265
431
|
for (const entry of entries) {
|
|
266
|
-
const srcPath =
|
|
267
|
-
const destPath =
|
|
432
|
+
const srcPath = join2(src, entry.name);
|
|
433
|
+
const destPath = join2(dest, entry.name);
|
|
268
434
|
if (entry.isDirectory()) {
|
|
269
435
|
copyTemplateFiles(srcPath, destPath);
|
|
270
436
|
} else {
|
|
@@ -274,8 +440,8 @@ function copyTemplateFiles(src, dest) {
|
|
|
274
440
|
}
|
|
275
441
|
function removeItems(targetDir, items) {
|
|
276
442
|
for (const item of items) {
|
|
277
|
-
const itemPath =
|
|
278
|
-
if (
|
|
443
|
+
const itemPath = join2(targetDir, item);
|
|
444
|
+
if (existsSync3(itemPath)) {
|
|
279
445
|
try {
|
|
280
446
|
rmSync(itemPath, { recursive: true, force: true });
|
|
281
447
|
} catch {
|
|
@@ -284,8 +450,8 @@ function removeItems(targetDir, items) {
|
|
|
284
450
|
}
|
|
285
451
|
}
|
|
286
452
|
function updatePackageJson(targetDir, projectName) {
|
|
287
|
-
const pkgPath =
|
|
288
|
-
if (!
|
|
453
|
+
const pkgPath = join2(targetDir, "package.json");
|
|
454
|
+
if (!existsSync3(pkgPath)) {
|
|
289
455
|
throw new Error("package.json not found in template");
|
|
290
456
|
}
|
|
291
457
|
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
@@ -294,11 +460,11 @@ function updatePackageJson(targetDir, projectName) {
|
|
|
294
460
|
delete pkg.repository;
|
|
295
461
|
delete pkg.bugs;
|
|
296
462
|
delete pkg.homepage;
|
|
297
|
-
|
|
463
|
+
writeFileSync2(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
298
464
|
}
|
|
299
465
|
function applyBaseTemplate(targetDir) {
|
|
300
466
|
const baseTemplate = getBaseTemplatePath();
|
|
301
|
-
if (
|
|
467
|
+
if (existsSync3(baseTemplate)) {
|
|
302
468
|
copyTemplateFiles(baseTemplate, targetDir);
|
|
303
469
|
}
|
|
304
470
|
}
|
|
@@ -311,15 +477,15 @@ function createContentDirectories(targetDir) {
|
|
|
311
477
|
"src/content/blog"
|
|
312
478
|
];
|
|
313
479
|
for (const dir of contentDirs) {
|
|
314
|
-
const dirPath =
|
|
315
|
-
if (!
|
|
316
|
-
|
|
317
|
-
|
|
480
|
+
const dirPath = join2(targetDir, dir);
|
|
481
|
+
if (!existsSync3(dirPath)) {
|
|
482
|
+
mkdirSync2(dirPath, { recursive: true });
|
|
483
|
+
writeFileSync2(join2(dirPath, ".gitkeep"), "");
|
|
318
484
|
}
|
|
319
485
|
}
|
|
320
486
|
}
|
|
321
487
|
async function scaffold(options) {
|
|
322
|
-
const { projectName, targetDir, demo, components, i18n, packageManager } = options;
|
|
488
|
+
const { projectName, targetDir, demo, components, i18n, pages, pageLayout, packageManager } = options;
|
|
323
489
|
const spinner2 = p2.spinner();
|
|
324
490
|
spinner2.start("Downloading template from GitHub...");
|
|
325
491
|
try {
|
|
@@ -358,6 +524,16 @@ ${error instanceof Error ? error.message : ""}`
|
|
|
358
524
|
throw error;
|
|
359
525
|
}
|
|
360
526
|
}
|
|
527
|
+
if (pages.length > 0) {
|
|
528
|
+
spinner2.start(`Generating ${pages.length} starter page${pages.length > 1 ? "s" : ""}...`);
|
|
529
|
+
try {
|
|
530
|
+
const generatedFiles = await generatePages(targetDir, pages, pageLayout, i18n);
|
|
531
|
+
spinner2.stop(`Generated ${generatedFiles.length} page file${generatedFiles.length > 1 ? "s" : ""}`);
|
|
532
|
+
} catch (error) {
|
|
533
|
+
spinner2.stop("Failed to generate pages");
|
|
534
|
+
throw error;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
361
537
|
spinner2.start("Configuring project...");
|
|
362
538
|
try {
|
|
363
539
|
updatePackageJson(targetDir, projectName);
|
|
@@ -387,10 +563,10 @@ ${error instanceof Error ? error.message : ""}`
|
|
|
387
563
|
}
|
|
388
564
|
|
|
389
565
|
// src/utils/fs.ts
|
|
390
|
-
import { existsSync as
|
|
391
|
-
import { join as
|
|
566
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync2, statSync, copyFileSync as copyFileSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
567
|
+
import { join as join3, dirname as dirname2 } from "path";
|
|
392
568
|
function isEmptyDir(path) {
|
|
393
|
-
if (!
|
|
569
|
+
if (!existsSync4(path)) return true;
|
|
394
570
|
const files = readdirSync2(path);
|
|
395
571
|
return files.length === 0 || files.length === 1 && files[0] === ".git";
|
|
396
572
|
}
|
|
@@ -409,6 +585,7 @@ ${pc2.bold("Options:")}
|
|
|
409
585
|
--demo Include demo landing page and sample content
|
|
410
586
|
--components Include UI component library
|
|
411
587
|
--i18n Add internationalization support
|
|
588
|
+
--pages Prompt for starter pages to generate
|
|
412
589
|
--yes, -y Skip prompts and use defaults
|
|
413
590
|
--help, -h Show this help message
|
|
414
591
|
--version, -v Show version number
|
|
@@ -416,13 +593,13 @@ ${pc2.bold("Options:")}
|
|
|
416
593
|
${pc2.bold("Examples:")}
|
|
417
594
|
npm create velocity-astro@latest my-site
|
|
418
595
|
npm create velocity-astro@latest my-site --demo --components
|
|
419
|
-
npm create velocity-astro@latest my-site --i18n
|
|
596
|
+
npm create velocity-astro@latest my-site --i18n --pages
|
|
420
597
|
pnpm create velocity-astro my-site -y
|
|
421
598
|
`;
|
|
422
|
-
var VERSION = "1.0
|
|
599
|
+
var VERSION = "1.1.0";
|
|
423
600
|
async function run(argv) {
|
|
424
601
|
const args = mri(argv, {
|
|
425
|
-
boolean: ["demo", "components", "i18n", "help", "version", "yes"],
|
|
602
|
+
boolean: ["demo", "components", "i18n", "pages", "help", "version", "yes"],
|
|
426
603
|
alias: {
|
|
427
604
|
h: "help",
|
|
428
605
|
v: "version",
|
|
@@ -442,7 +619,7 @@ async function run(argv) {
|
|
|
442
619
|
if (args.yes) {
|
|
443
620
|
const projectName2 = toValidProjectName(argProjectName || "my-velocity-site");
|
|
444
621
|
const targetDir2 = resolve2(process.cwd(), projectName2);
|
|
445
|
-
if (
|
|
622
|
+
if (existsSync5(targetDir2) && !isEmptyDir(targetDir2)) {
|
|
446
623
|
showError(`Directory "${projectName2}" already exists and is not empty.`);
|
|
447
624
|
process.exit(1);
|
|
448
625
|
}
|
|
@@ -453,6 +630,8 @@ async function run(argv) {
|
|
|
453
630
|
components: args.components !== false,
|
|
454
631
|
// Default to true
|
|
455
632
|
i18n: args.i18n || false,
|
|
633
|
+
pages: [],
|
|
634
|
+
pageLayout: "page",
|
|
456
635
|
packageManager: "pnpm"
|
|
457
636
|
});
|
|
458
637
|
showOutro(projectName2, "pnpm");
|
|
@@ -462,14 +641,15 @@ async function run(argv) {
|
|
|
462
641
|
projectName: argProjectName,
|
|
463
642
|
demo: args.demo,
|
|
464
643
|
components: args.components,
|
|
465
|
-
i18n: args.i18n
|
|
644
|
+
i18n: args.i18n,
|
|
645
|
+
pages: args.pages
|
|
466
646
|
});
|
|
467
647
|
if (typeof answers === "symbol") {
|
|
468
648
|
return;
|
|
469
649
|
}
|
|
470
|
-
const { projectName, demo, components, i18n, packageManager } = answers;
|
|
650
|
+
const { projectName, demo, components, i18n, pages, pageLayout, packageManager } = answers;
|
|
471
651
|
const targetDir = resolve2(process.cwd(), projectName);
|
|
472
|
-
if (
|
|
652
|
+
if (existsSync5(targetDir) && !isEmptyDir(targetDir)) {
|
|
473
653
|
const shouldOverwrite = await p3.confirm({
|
|
474
654
|
message: `Directory "${projectName}" already exists. Continue and overwrite?`,
|
|
475
655
|
initialValue: false
|
|
@@ -486,6 +666,8 @@ async function run(argv) {
|
|
|
486
666
|
demo,
|
|
487
667
|
components,
|
|
488
668
|
i18n,
|
|
669
|
+
pages,
|
|
670
|
+
pageLayout,
|
|
489
671
|
packageManager
|
|
490
672
|
});
|
|
491
673
|
showOutro(projectName, packageManager);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/prompts.ts","../src/utils/validate.ts","../src/utils/package-manager.ts","../src/scaffold.ts","../src/template.ts","../src/utils/git.ts","../src/utils/fs.ts","../src/index.ts"],"sourcesContent":["import mri from 'mri';\nimport { resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport type { CliOptions } from './types.js';\nimport { runPrompts, showIntro, showOutro, showError } from './prompts.js';\nimport { scaffold } from './scaffold.js';\nimport { isEmptyDir } from './utils/fs.js';\nimport { toValidProjectName } from './utils/validate.js';\n\nconst HELP_TEXT = `\n${pc.bold('create-velocity-astro')} - Create a new Velocity project\n\n${pc.bold('Usage:')}\n npm create velocity-astro@latest [project-name] [options]\n pnpm create velocity-astro [project-name] [options]\n yarn create velocity-astro [project-name] [options]\n bun create velocity-astro [project-name] [options]\n\n${pc.bold('Options:')}\n --demo Include demo landing page and sample content\n --components Include UI component library\n --i18n Add internationalization support\n --yes, -y Skip prompts and use defaults\n --help, -h Show this help message\n --version, -v Show version number\n\n${pc.bold('Examples:')}\n npm create velocity-astro@latest my-site\n npm create velocity-astro@latest my-site --demo --components\n npm create velocity-astro@latest my-site --i18n\n pnpm create velocity-astro my-site -y\n`;\n\nconst VERSION = '1.0.3';\n\nexport async function run(argv: string[]): Promise<void> {\n const args = mri<CliOptions>(argv, {\n boolean: ['demo', 'components', 'i18n', 'help', 'version', 'yes'],\n alias: {\n h: 'help',\n v: 'version',\n y: 'yes',\n },\n });\n\n // Handle help\n if (args.help) {\n console.log(HELP_TEXT);\n return;\n }\n\n // Handle version\n if (args.version) {\n console.log(VERSION);\n return;\n }\n\n showIntro();\n\n // Get project name from args or prompt\n const argProjectName = args._[0] as string | undefined;\n\n // Skip prompts mode\n if (args.yes) {\n const projectName = toValidProjectName(argProjectName || 'my-velocity-site');\n const targetDir = resolve(process.cwd(), projectName);\n\n if (existsSync(targetDir) && !isEmptyDir(targetDir)) {\n showError(`Directory \"${projectName}\" already exists and is not empty.`);\n process.exit(1);\n }\n\n await scaffold({\n projectName,\n targetDir,\n demo: args.demo || false,\n components: args.components !== false, // Default to true\n i18n: args.i18n || false,\n packageManager: 'pnpm',\n });\n\n showOutro(projectName, 'pnpm');\n return;\n }\n\n // Interactive mode\n const answers = await runPrompts({\n projectName: argProjectName,\n demo: args.demo,\n components: args.components,\n i18n: args.i18n,\n });\n\n // User cancelled\n if (typeof answers === 'symbol') {\n return;\n }\n\n const { projectName, demo, components, i18n, packageManager } = answers;\n const targetDir = resolve(process.cwd(), projectName);\n\n // Check if directory exists and is not empty\n if (existsSync(targetDir) && !isEmptyDir(targetDir)) {\n const shouldOverwrite = await p.confirm({\n message: `Directory \"${projectName}\" already exists. Continue and overwrite?`,\n initialValue: false,\n });\n\n if (!shouldOverwrite || p.isCancel(shouldOverwrite)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n }\n\n // Run scaffold\n try {\n await scaffold({\n projectName,\n targetDir,\n demo,\n components,\n i18n,\n packageManager,\n });\n\n showOutro(projectName, packageManager);\n } catch (error) {\n showError(error instanceof Error ? error.message : 'An unexpected error occurred');\n process.exit(1);\n }\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport type { PackageManager, PromptAnswers } from './types.js';\nimport { validateProjectName, toValidProjectName } from './utils/validate.js';\nimport { detectPackageManager } from './utils/package-manager.js';\n\ninterface PromptDefaults {\n projectName?: string;\n demo?: boolean;\n components?: boolean;\n i18n?: boolean;\n}\n\nexport async function runPrompts(defaults: PromptDefaults = {}): Promise<PromptAnswers | symbol> {\n const detectedPm = detectPackageManager();\n\n const answers = await p.group(\n {\n projectName: () =>\n p.text({\n message: 'What is your project name?',\n placeholder: defaults.projectName || 'my-velocity-site',\n defaultValue: defaults.projectName,\n validate: (value) => {\n const name = value || defaults.projectName || 'my-velocity-site';\n const result = validateProjectName(toValidProjectName(name));\n if (!result.valid) return result.message;\n },\n }),\n\n demo:\n defaults.demo !== undefined\n ? () => Promise.resolve(defaults.demo)\n : () =>\n p.select({\n message: 'Include demo landing page and sample content?',\n options: [\n {\n value: false,\n label: 'No',\n hint: 'Minimal starter with basic pages',\n },\n {\n value: true,\n label: 'Yes',\n hint: 'Full demo with landing page, blog posts',\n },\n ],\n initialValue: false,\n }),\n\n components:\n defaults.components !== undefined\n ? () => Promise.resolve(defaults.components)\n : () =>\n p.select({\n message: 'Include UI component library?',\n options: [\n {\n value: false,\n label: 'No',\n hint: 'Just the basics',\n },\n {\n value: true,\n label: 'Yes',\n hint: 'Buttons, forms, cards, dialogs, etc.',\n },\n ],\n initialValue: true,\n }),\n\n i18n:\n defaults.i18n !== undefined\n ? () => Promise.resolve(defaults.i18n)\n : () =>\n p.select({\n message: 'Add internationalization (i18n)?',\n options: [\n {\n value: false,\n label: 'No',\n hint: 'English only',\n },\n {\n value: true,\n label: 'Yes',\n hint: 'Locale routing, translations',\n },\n ],\n initialValue: false,\n }),\n\n packageManager: () =>\n p.select({\n message: 'Which package manager?',\n options: [\n {\n value: 'pnpm' as PackageManager,\n label: 'pnpm',\n hint: detectedPm === 'pnpm' ? 'detected' : 'recommended',\n },\n {\n value: 'npm' as PackageManager,\n label: 'npm',\n hint: detectedPm === 'npm' ? 'detected' : undefined,\n },\n {\n value: 'yarn' as PackageManager,\n label: 'yarn',\n hint: detectedPm === 'yarn' ? 'detected' : undefined,\n },\n {\n value: 'bun' as PackageManager,\n label: 'bun',\n hint: detectedPm === 'bun' ? 'detected' : undefined,\n },\n ],\n initialValue: detectedPm,\n }),\n },\n {\n onCancel: () => {\n p.cancel('Operation cancelled.');\n process.exit(0);\n },\n }\n );\n\n return {\n projectName: toValidProjectName(answers.projectName || defaults.projectName || 'my-velocity-site'),\n demo: answers.demo as boolean,\n components: answers.components as boolean,\n i18n: answers.i18n as boolean,\n packageManager: answers.packageManager as PackageManager,\n };\n}\n\nexport function showIntro(): void {\n console.log();\n p.intro(pc.bgCyan(pc.black(' Create Velocity ')));\n}\n\nexport function showOutro(projectName: string, packageManager: PackageManager): void {\n const runCmd = packageManager === 'npm' ? 'npm run' : packageManager;\n\n p.note(\n [\n `cd ${projectName}`,\n `${runCmd} dev`,\n ].join('\\n'),\n 'Next steps'\n );\n\n p.outro(pc.green('Happy building!'));\n}\n\nexport function showError(message: string): void {\n p.log.error(pc.red(message));\n}\n\nexport function showWarning(message: string): void {\n p.log.warn(pc.yellow(message));\n}\n\nexport function showSuccess(message: string): void {\n p.log.success(pc.green(message));\n}\n\nexport function showStep(message: string): void {\n p.log.step(message);\n}\n","/**\n * Validates a project name for npm package naming conventions\n */\nexport function validateProjectName(name: string): { valid: boolean; message?: string } {\n if (!name || name.trim() === '') {\n return { valid: false, message: 'Project name cannot be empty' };\n }\n\n // Must be lowercase\n if (name !== name.toLowerCase()) {\n return { valid: false, message: 'Project name must be lowercase' };\n }\n\n // Cannot start with . or _\n if (name.startsWith('.') || name.startsWith('_')) {\n return { valid: false, message: 'Project name cannot start with . or _' };\n }\n\n // Cannot contain spaces\n if (/\\s/.test(name)) {\n return { valid: false, message: 'Project name cannot contain spaces' };\n }\n\n // Cannot contain special characters except - and @/\n if (!/^(@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name)) {\n return {\n valid: false,\n message: 'Project name can only contain lowercase letters, numbers, hyphens, and underscores',\n };\n }\n\n // Length check\n if (name.length > 214) {\n return { valid: false, message: 'Project name must be 214 characters or fewer' };\n }\n\n return { valid: true };\n}\n\n/**\n * Sanitizes a string to be a valid project name\n */\nexport function toValidProjectName(name: string): string {\n return name\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-_~.]/g, '-')\n .replace(/^[-._]+/, '')\n .replace(/[-._]+$/, '')\n .replace(/-+/g, '-');\n}\n","import type { PackageManager } from '../types.js';\n\n/**\n * Detects the package manager used to run this command\n */\nexport function detectPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent || '';\n\n if (userAgent.startsWith('pnpm')) return 'pnpm';\n if (userAgent.startsWith('yarn')) return 'yarn';\n if (userAgent.startsWith('bun')) return 'bun';\n return 'npm';\n}\n\n/**\n * Gets the install command for a package manager\n */\nexport function getInstallCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return 'pnpm install';\n case 'yarn':\n return 'yarn';\n case 'bun':\n return 'bun install';\n case 'npm':\n default:\n return 'npm install';\n }\n}\n\n/**\n * Gets the run command for a package manager\n */\nexport function getRunCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return 'pnpm';\n case 'yarn':\n return 'yarn';\n case 'bun':\n return 'bun';\n case 'npm':\n default:\n return 'npm run';\n }\n}\n","import { existsSync, mkdirSync, readdirSync, copyFileSync, readFileSync, writeFileSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport * as p from '@clack/prompts';\nimport { execa } from 'execa';\nimport { downloadTemplate } from 'giget';\nimport type { ScaffoldOptions } from './types.js';\nimport { getI18nTemplatePath, getBaseTemplatePath } from './template.js';\nimport { getInstallCommand } from './utils/package-manager.js';\nimport { initGit } from './utils/git.js';\nimport { showSuccess, showWarning } from './prompts.js';\n\n// GitHub repository for the Velocity template\nconst TEMPLATE_REPO = 'github:southwellmedia-dev/velocity';\n\n// Files/directories to remove after download\nconst CLEANUP_ITEMS = [\n 'pnpm-lock.yaml',\n 'package-lock.json',\n 'yarn.lock',\n 'bun.lockb',\n '.git',\n];\n\n// Demo-specific content to remove when --demo is false\nconst DEMO_CONTENT = [\n 'src/components/landing',\n 'src/pages/about.astro',\n 'src/pages/contact.astro',\n 'src/content/blog',\n 'src/content/faqs',\n 'src/content/authors',\n 'src/content/pages',\n];\n\n// UI component library content to remove when --components is false\nconst COMPONENTS_CONTENT = [\n 'src/components/ui',\n 'src/components/patterns',\n 'src/pages/components.astro',\n];\n\n/**\n * Copies template files recursively\n */\nfunction copyTemplateFiles(src: string, dest: string): void {\n if (!existsSync(dest)) {\n mkdirSync(dest, { recursive: true });\n }\n\n const entries = readdirSync(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(src, entry.name);\n const destPath = join(dest, entry.name);\n\n if (entry.isDirectory()) {\n copyTemplateFiles(srcPath, destPath);\n } else {\n copyFileSync(srcPath, destPath);\n }\n }\n}\n\n/**\n * Removes files/directories from the target\n */\nfunction removeItems(targetDir: string, items: string[]): void {\n for (const item of items) {\n const itemPath = join(targetDir, item);\n if (existsSync(itemPath)) {\n try {\n rmSync(itemPath, { recursive: true, force: true });\n } catch {\n // Ignore errors - item may not exist or be locked\n }\n }\n }\n}\n\n/**\n * Updates the package.json with the new project name\n */\nfunction updatePackageJson(targetDir: string, projectName: string): void {\n const pkgPath = join(targetDir, 'package.json');\n\n if (!existsSync(pkgPath)) {\n throw new Error('package.json not found in template');\n }\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n pkg.name = projectName;\n pkg.version = '0.1.0';\n delete pkg.repository;\n delete pkg.bugs;\n delete pkg.homepage;\n\n writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\n}\n\n/**\n * Applies base template (minimal pages) when demo is not selected\n */\nfunction applyBaseTemplate(targetDir: string): void {\n const baseTemplate = getBaseTemplatePath();\n if (existsSync(baseTemplate)) {\n copyTemplateFiles(baseTemplate, targetDir);\n }\n}\n\n/**\n * Applies the i18n overlay to the project\n */\nfunction applyI18nOverlay(targetDir: string): void {\n const i18nTemplate = getI18nTemplatePath();\n copyTemplateFiles(i18nTemplate, targetDir);\n}\n\n/**\n * Creates empty content directories with .gitkeep files\n */\nfunction createContentDirectories(targetDir: string): void {\n const contentDirs = [\n 'src/content/blog',\n ];\n\n for (const dir of contentDirs) {\n const dirPath = join(targetDir, dir);\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n writeFileSync(join(dirPath, '.gitkeep'), '');\n }\n }\n}\n\n/**\n * Main scaffold function\n */\nexport async function scaffold(options: ScaffoldOptions): Promise<void> {\n const { projectName, targetDir, demo, components, i18n, packageManager } = options;\n const spinner = p.spinner();\n\n // Step 1: Download base template from GitHub\n spinner.start('Downloading template from GitHub...');\n\n try {\n await downloadTemplate(TEMPLATE_REPO, {\n dir: targetDir,\n force: true,\n });\n removeItems(targetDir, CLEANUP_ITEMS);\n spinner.stop('Template downloaded');\n } catch (error) {\n spinner.stop('Failed to download template');\n throw new Error(\n `Could not download template from GitHub. Please check your internet connection.\\n${error instanceof Error ? error.message : ''}`\n );\n }\n\n // Step 2: Remove demo content if not requested\n if (!demo) {\n spinner.start('Configuring minimal template...');\n removeItems(targetDir, DEMO_CONTENT);\n applyBaseTemplate(targetDir);\n createContentDirectories(targetDir);\n spinner.stop('Minimal template configured');\n }\n\n // Step 3: Remove UI components if not requested\n if (!components) {\n spinner.start('Removing UI component library...');\n removeItems(targetDir, COMPONENTS_CONTENT);\n spinner.stop('UI components removed');\n }\n\n // Step 4: Apply i18n overlay if requested\n if (i18n) {\n spinner.start('Adding i18n support...');\n try {\n applyI18nOverlay(targetDir);\n spinner.stop('i18n support added');\n } catch (error) {\n spinner.stop('Failed to add i18n support');\n throw error;\n }\n }\n\n // Step 5: Update package.json\n spinner.start('Configuring project...');\n try {\n updatePackageJson(targetDir, projectName);\n spinner.stop('Project configured');\n } catch (error) {\n spinner.stop('Failed to configure project');\n throw error;\n }\n\n // Step 6: Initialize git\n spinner.start('Initializing git repository...');\n const gitInitialized = await initGit(targetDir);\n if (gitInitialized) {\n spinner.stop('Git repository initialized');\n } else {\n spinner.stop('Git not available, skipping');\n }\n\n // Step 7: Install dependencies\n spinner.start(`Installing dependencies with ${packageManager}...`);\n try {\n const installCmd = getInstallCommand(packageManager);\n const [cmd, ...args] = installCmd.split(' ');\n await execa(cmd!, args, { cwd: targetDir });\n spinner.stop('Dependencies installed');\n } catch {\n spinner.stop('Failed to install dependencies');\n showWarning(`Run \"${getInstallCommand(packageManager)}\" manually to install dependencies`);\n }\n\n showSuccess(`Project \"${projectName}\" created successfully!`);\n}\n","import { existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Resolves the path to the base template (minimal pages)\n */\nexport function getBaseTemplatePath(): string {\n const templatePath = resolve(__dirname, '..', 'templates', 'base');\n\n if (existsSync(templatePath)) {\n return templatePath;\n }\n\n throw new Error('Could not find base template. Package may be corrupted.');\n}\n\n/**\n * Resolves the path to the i18n overlay template\n */\nexport function getI18nTemplatePath(): string {\n const templatePath = resolve(__dirname, '..', 'templates', 'i18n');\n\n if (existsSync(templatePath)) {\n return templatePath;\n }\n\n throw new Error('Could not find i18n template. Package may be corrupted.');\n}\n","import { execa } from 'execa';\n\n/**\n * Initializes a git repository in the target directory\n */\nexport async function initGit(targetDir: string): Promise<boolean> {\n try {\n await execa('git', ['init'], { cwd: targetDir });\n await execa('git', ['add', '-A'], { cwd: targetDir });\n await execa('git', ['commit', '-m', 'Initial commit from create-velocity'], {\n cwd: targetDir,\n });\n return true;\n } catch {\n // Git may not be installed or configured\n return false;\n }\n}\n\n/**\n * Checks if git is available\n */\nexport async function isGitInstalled(): Promise<boolean> {\n try {\n await execa('git', ['--version']);\n return true;\n } catch {\n return false;\n }\n}\n","import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\n\n/**\n * Recursively copies a directory\n */\nexport function copyDirectory(src: string, dest: string, overwrite = false): void {\n if (!existsSync(src)) {\n throw new Error(`Source directory does not exist: ${src}`);\n }\n\n if (!existsSync(dest)) {\n mkdirSync(dest, { recursive: true });\n }\n\n const entries = readdirSync(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(src, entry.name);\n const destPath = join(dest, entry.name);\n\n if (entry.isDirectory()) {\n copyDirectory(srcPath, destPath, overwrite);\n } else {\n if (overwrite || !existsSync(destPath)) {\n const destDir = dirname(destPath);\n if (!existsSync(destDir)) {\n mkdirSync(destDir, { recursive: true });\n }\n copyFileSync(srcPath, destPath);\n }\n }\n }\n}\n\n/**\n * Checks if a directory is empty\n */\nexport function isEmptyDir(path: string): boolean {\n if (!existsSync(path)) return true;\n const files = readdirSync(path);\n return files.length === 0 || (files.length === 1 && files[0] === '.git');\n}\n\n/**\n * Reads a JSON file and parses it\n */\nexport function readJson<T = Record<string, unknown>>(path: string): T {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content) as T;\n}\n\n/**\n * Writes an object as JSON to a file\n */\nexport function writeJson(path: string, data: unknown): void {\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n');\n}\n\n/**\n * Checks if path exists and is a directory\n */\nexport function isDirectory(path: string): boolean {\n return existsSync(path) && statSync(path).isDirectory();\n}\n","import { run } from './cli.js';\n\nrun(process.argv.slice(2)).catch((error) => {\n console.error(error);\n process.exit(1);\n});\n"],"mappings":";;;AAAA,OAAO,SAAS;AAChB,SAAS,WAAAA,gBAAe;AACxB,SAAS,cAAAC,mBAAkB;AAC3B,YAAYC,QAAO;AACnB,OAAOC,SAAQ;;;ACJf,YAAY,OAAO;AACnB,OAAO,QAAQ;;;ACER,SAAS,oBAAoB,MAAoD;AACtF,MAAI,CAAC,QAAQ,KAAK,KAAK,MAAM,IAAI;AAC/B,WAAO,EAAE,OAAO,OAAO,SAAS,+BAA+B;AAAA,EACjE;AAGA,MAAI,SAAS,KAAK,YAAY,GAAG;AAC/B,WAAO,EAAE,OAAO,OAAO,SAAS,iCAAiC;AAAA,EACnE;AAGA,MAAI,KAAK,WAAW,GAAG,KAAK,KAAK,WAAW,GAAG,GAAG;AAChD,WAAO,EAAE,OAAO,OAAO,SAAS,wCAAwC;AAAA,EAC1E;AAGA,MAAI,KAAK,KAAK,IAAI,GAAG;AACnB,WAAO,EAAE,OAAO,OAAO,SAAS,qCAAqC;AAAA,EACvE;AAGA,MAAI,CAAC,yDAAyD,KAAK,IAAI,GAAG;AACxE,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,EACF;AAGA,MAAI,KAAK,SAAS,KAAK;AACrB,WAAO,EAAE,OAAO,OAAO,SAAS,+CAA+C;AAAA,EACjF;AAEA,SAAO,EAAE,OAAO,KAAK;AACvB;AAKO,SAAS,mBAAmB,MAAsB;AACvD,SAAO,KACJ,KAAK,EACL,YAAY,EACZ,QAAQ,QAAQ,GAAG,EACnB,QAAQ,kBAAkB,GAAG,EAC7B,QAAQ,WAAW,EAAE,EACrB,QAAQ,WAAW,EAAE,EACrB,QAAQ,OAAO,GAAG;AACvB;;;AC9CO,SAAS,uBAAuC;AACrD,QAAM,YAAY,QAAQ,IAAI,yBAAyB;AAEvD,MAAI,UAAU,WAAW,MAAM,EAAG,QAAO;AACzC,MAAI,UAAU,WAAW,MAAM,EAAG,QAAO;AACzC,MAAI,UAAU,WAAW,KAAK,EAAG,QAAO;AACxC,SAAO;AACT;AAKO,SAAS,kBAAkB,IAA4B;AAC5D,UAAQ,IAAI;AAAA,IACV,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AAAA,IACL;AACE,aAAO;AAAA,EACX;AACF;;;AFhBA,eAAsB,WAAW,WAA2B,CAAC,GAAoC;AAC/F,QAAM,aAAa,qBAAqB;AAExC,QAAM,UAAU,MAAQ;AAAA,IACtB;AAAA,MACE,aAAa,MACT,OAAK;AAAA,QACL,SAAS;AAAA,QACT,aAAa,SAAS,eAAe;AAAA,QACrC,cAAc,SAAS;AAAA,QACvB,UAAU,CAAC,UAAU;AACnB,gBAAM,OAAO,SAAS,SAAS,eAAe;AAC9C,gBAAM,SAAS,oBAAoB,mBAAmB,IAAI,CAAC;AAC3D,cAAI,CAAC,OAAO,MAAO,QAAO,OAAO;AAAA,QACnC;AAAA,MACF,CAAC;AAAA,MAEH,MACE,SAAS,SAAS,SACd,MAAM,QAAQ,QAAQ,SAAS,IAAI,IACnC,MACI,SAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,UACP;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,QACF;AAAA,QACA,cAAc;AAAA,MAChB,CAAC;AAAA,MAET,YACE,SAAS,eAAe,SACpB,MAAM,QAAQ,QAAQ,SAAS,UAAU,IACzC,MACI,SAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,UACP;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,QACF;AAAA,QACA,cAAc;AAAA,MAChB,CAAC;AAAA,MAET,MACE,SAAS,SAAS,SACd,MAAM,QAAQ,QAAQ,SAAS,IAAI,IACnC,MACI,SAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,UACP;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM;AAAA,UACR;AAAA,QACF;AAAA,QACA,cAAc;AAAA,MAChB,CAAC;AAAA,MAET,gBAAgB,MACZ,SAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,UACP;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM,eAAe,SAAS,aAAa;AAAA,UAC7C;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM,eAAe,QAAQ,aAAa;AAAA,UAC5C;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM,eAAe,SAAS,aAAa;AAAA,UAC7C;AAAA,UACA;AAAA,YACE,OAAO;AAAA,YACP,OAAO;AAAA,YACP,MAAM,eAAe,QAAQ,aAAa;AAAA,UAC5C;AAAA,QACF;AAAA,QACA,cAAc;AAAA,MAChB,CAAC;AAAA,IACL;AAAA,IACA;AAAA,MACE,UAAU,MAAM;AACd,QAAE,SAAO,sBAAsB;AAC/B,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,aAAa,mBAAmB,QAAQ,eAAe,SAAS,eAAe,kBAAkB;AAAA,IACjG,MAAM,QAAQ;AAAA,IACd,YAAY,QAAQ;AAAA,IACpB,MAAM,QAAQ;AAAA,IACd,gBAAgB,QAAQ;AAAA,EAC1B;AACF;AAEO,SAAS,YAAkB;AAChC,UAAQ,IAAI;AACZ,EAAE,QAAM,GAAG,OAAO,GAAG,MAAM,mBAAmB,CAAC,CAAC;AAClD;AAEO,SAAS,UAAU,aAAqB,gBAAsC;AACnF,QAAM,SAAS,mBAAmB,QAAQ,YAAY;AAEtD,EAAE;AAAA,IACA;AAAA,MACE,MAAM,WAAW;AAAA,MACjB,GAAG,MAAM;AAAA,IACX,EAAE,KAAK,IAAI;AAAA,IACX;AAAA,EACF;AAEA,EAAE,QAAM,GAAG,MAAM,iBAAiB,CAAC;AACrC;AAEO,SAAS,UAAU,SAAuB;AAC/C,EAAE,MAAI,MAAM,GAAG,IAAI,OAAO,CAAC;AAC7B;AAEO,SAAS,YAAY,SAAuB;AACjD,EAAE,MAAI,KAAK,GAAG,OAAO,OAAO,CAAC;AAC/B;AAEO,SAAS,YAAY,SAAuB;AACjD,EAAE,MAAI,QAAQ,GAAG,MAAM,OAAO,CAAC;AACjC;;;AGvKA,SAAS,cAAAC,aAAY,WAAW,aAAa,cAAc,cAAc,eAAe,cAAc;AACtG,SAAS,YAAY;AACrB,YAAYC,QAAO;AACnB,SAAS,SAAAC,cAAa;AACtB,SAAS,wBAAwB;;;ACJjC,SAAS,kBAAkB;AAC3B,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAE9B,IAAMC,aAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAKjD,SAAS,sBAA8B;AAC5C,QAAM,eAAe,QAAQA,YAAW,MAAM,aAAa,MAAM;AAEjE,MAAI,WAAW,YAAY,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,IAAI,MAAM,yDAAyD;AAC3E;AAKO,SAAS,sBAA8B;AAC5C,QAAM,eAAe,QAAQA,YAAW,MAAM,aAAa,MAAM;AAEjE,MAAI,WAAW,YAAY,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,IAAI,MAAM,yDAAyD;AAC3E;;;AC9BA,SAAS,aAAa;AAKtB,eAAsB,QAAQ,WAAqC;AACjE,MAAI;AACF,UAAM,MAAM,OAAO,CAAC,MAAM,GAAG,EAAE,KAAK,UAAU,CAAC;AAC/C,UAAM,MAAM,OAAO,CAAC,OAAO,IAAI,GAAG,EAAE,KAAK,UAAU,CAAC;AACpD,UAAM,MAAM,OAAO,CAAC,UAAU,MAAM,qCAAqC,GAAG;AAAA,MAC1E,KAAK;AAAA,IACP,CAAC;AACD,WAAO;AAAA,EACT,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;;;AFLA,IAAM,gBAAgB;AAGtB,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,IAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AACF;AAKA,SAAS,kBAAkB,KAAa,MAAoB;AAC1D,MAAI,CAACC,YAAW,IAAI,GAAG;AACrB,cAAU,MAAM,EAAE,WAAW,KAAK,CAAC;AAAA,EACrC;AAEA,QAAM,UAAU,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAExD,aAAW,SAAS,SAAS;AAC3B,UAAM,UAAU,KAAK,KAAK,MAAM,IAAI;AACpC,UAAM,WAAW,KAAK,MAAM,MAAM,IAAI;AAEtC,QAAI,MAAM,YAAY,GAAG;AACvB,wBAAkB,SAAS,QAAQ;AAAA,IACrC,OAAO;AACL,mBAAa,SAAS,QAAQ;AAAA,IAChC;AAAA,EACF;AACF;AAKA,SAAS,YAAY,WAAmB,OAAuB;AAC7D,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,KAAK,WAAW,IAAI;AACrC,QAAIA,YAAW,QAAQ,GAAG;AACxB,UAAI;AACF,eAAO,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACnD,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,kBAAkB,WAAmB,aAA2B;AACvE,QAAM,UAAU,KAAK,WAAW,cAAc;AAE9C,MAAI,CAACA,YAAW,OAAO,GAAG;AACxB,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACtD;AAEA,QAAM,MAAM,KAAK,MAAM,aAAa,SAAS,OAAO,CAAC;AACrD,MAAI,OAAO;AACX,MAAI,UAAU;AACd,SAAO,IAAI;AACX,SAAO,IAAI;AACX,SAAO,IAAI;AAEX,gBAAc,SAAS,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AAC5D;AAKA,SAAS,kBAAkB,WAAyB;AAClD,QAAM,eAAe,oBAAoB;AACzC,MAAIA,YAAW,YAAY,GAAG;AAC5B,sBAAkB,cAAc,SAAS;AAAA,EAC3C;AACF;AAKA,SAAS,iBAAiB,WAAyB;AACjD,QAAM,eAAe,oBAAoB;AACzC,oBAAkB,cAAc,SAAS;AAC3C;AAKA,SAAS,yBAAyB,WAAyB;AACzD,QAAM,cAAc;AAAA,IAClB;AAAA,EACF;AAEA,aAAW,OAAO,aAAa;AAC7B,UAAM,UAAU,KAAK,WAAW,GAAG;AACnC,QAAI,CAACA,YAAW,OAAO,GAAG;AACxB,gBAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AACtC,oBAAc,KAAK,SAAS,UAAU,GAAG,EAAE;AAAA,IAC7C;AAAA,EACF;AACF;AAKA,eAAsB,SAAS,SAAyC;AACtE,QAAM,EAAE,aAAa,WAAW,MAAM,YAAY,MAAM,eAAe,IAAI;AAC3E,QAAMC,WAAY,WAAQ;AAG1B,EAAAA,SAAQ,MAAM,qCAAqC;AAEnD,MAAI;AACF,UAAM,iBAAiB,eAAe;AAAA,MACpC,KAAK;AAAA,MACL,OAAO;AAAA,IACT,CAAC;AACD,gBAAY,WAAW,aAAa;AACpC,IAAAA,SAAQ,KAAK,qBAAqB;AAAA,EACpC,SAAS,OAAO;AACd,IAAAA,SAAQ,KAAK,6BAA6B;AAC1C,UAAM,IAAI;AAAA,MACR;AAAA,EAAoF,iBAAiB,QAAQ,MAAM,UAAU,EAAE;AAAA,IACjI;AAAA,EACF;AAGA,MAAI,CAAC,MAAM;AACT,IAAAA,SAAQ,MAAM,iCAAiC;AAC/C,gBAAY,WAAW,YAAY;AACnC,sBAAkB,SAAS;AAC3B,6BAAyB,SAAS;AAClC,IAAAA,SAAQ,KAAK,6BAA6B;AAAA,EAC5C;AAGA,MAAI,CAAC,YAAY;AACf,IAAAA,SAAQ,MAAM,kCAAkC;AAChD,gBAAY,WAAW,kBAAkB;AACzC,IAAAA,SAAQ,KAAK,uBAAuB;AAAA,EACtC;AAGA,MAAI,MAAM;AACR,IAAAA,SAAQ,MAAM,wBAAwB;AACtC,QAAI;AACF,uBAAiB,SAAS;AAC1B,MAAAA,SAAQ,KAAK,oBAAoB;AAAA,IACnC,SAAS,OAAO;AACd,MAAAA,SAAQ,KAAK,4BAA4B;AACzC,YAAM;AAAA,IACR;AAAA,EACF;AAGA,EAAAA,SAAQ,MAAM,wBAAwB;AACtC,MAAI;AACF,sBAAkB,WAAW,WAAW;AACxC,IAAAA,SAAQ,KAAK,oBAAoB;AAAA,EACnC,SAAS,OAAO;AACd,IAAAA,SAAQ,KAAK,6BAA6B;AAC1C,UAAM;AAAA,EACR;AAGA,EAAAA,SAAQ,MAAM,gCAAgC;AAC9C,QAAM,iBAAiB,MAAM,QAAQ,SAAS;AAC9C,MAAI,gBAAgB;AAClB,IAAAA,SAAQ,KAAK,4BAA4B;AAAA,EAC3C,OAAO;AACL,IAAAA,SAAQ,KAAK,6BAA6B;AAAA,EAC5C;AAGA,EAAAA,SAAQ,MAAM,gCAAgC,cAAc,KAAK;AACjE,MAAI;AACF,UAAM,aAAa,kBAAkB,cAAc;AACnD,UAAM,CAAC,KAAK,GAAG,IAAI,IAAI,WAAW,MAAM,GAAG;AAC3C,UAAMC,OAAM,KAAM,MAAM,EAAE,KAAK,UAAU,CAAC;AAC1C,IAAAD,SAAQ,KAAK,wBAAwB;AAAA,EACvC,QAAQ;AACN,IAAAA,SAAQ,KAAK,gCAAgC;AAC7C,gBAAY,QAAQ,kBAAkB,cAAc,CAAC,oCAAoC;AAAA,EAC3F;AAEA,cAAY,YAAY,WAAW,yBAAyB;AAC9D;;;AG1NA,SAAS,cAAAE,aAAY,aAAAC,YAAW,eAAAC,cAAa,UAAU,gBAAAC,eAAc,gBAAAC,eAAc,iBAAAC,sBAAqB;AACxG,SAAS,QAAAC,OAAM,WAAAC,gBAAe;AAqCvB,SAAS,WAAW,MAAuB;AAChD,MAAI,CAACC,YAAW,IAAI,EAAG,QAAO;AAC9B,QAAM,QAAQC,aAAY,IAAI;AAC9B,SAAO,MAAM,WAAW,KAAM,MAAM,WAAW,KAAK,MAAM,CAAC,MAAM;AACnE;;;AP/BA,IAAM,YAAY;AAAA,EAChBC,IAAG,KAAK,uBAAuB,CAAC;AAAA;AAAA,EAEhCA,IAAG,KAAK,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjBA,IAAG,KAAK,UAAU,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQnBA,IAAG,KAAK,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAOtB,IAAM,UAAU;AAEhB,eAAsB,IAAI,MAA+B;AACvD,QAAM,OAAO,IAAgB,MAAM;AAAA,IACjC,SAAS,CAAC,QAAQ,cAAc,QAAQ,QAAQ,WAAW,KAAK;AAAA,IAChE,OAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF,CAAC;AAGD,MAAI,KAAK,MAAM;AACb,YAAQ,IAAI,SAAS;AACrB;AAAA,EACF;AAGA,MAAI,KAAK,SAAS;AAChB,YAAQ,IAAI,OAAO;AACnB;AAAA,EACF;AAEA,YAAU;AAGV,QAAM,iBAAiB,KAAK,EAAE,CAAC;AAG/B,MAAI,KAAK,KAAK;AACZ,UAAMC,eAAc,mBAAmB,kBAAkB,kBAAkB;AAC3E,UAAMC,aAAYC,SAAQ,QAAQ,IAAI,GAAGF,YAAW;AAEpD,QAAIG,YAAWF,UAAS,KAAK,CAAC,WAAWA,UAAS,GAAG;AACnD,gBAAU,cAAcD,YAAW,oCAAoC;AACvE,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,SAAS;AAAA,MACb,aAAAA;AAAA,MACA,WAAAC;AAAA,MACA,MAAM,KAAK,QAAQ;AAAA,MACnB,YAAY,KAAK,eAAe;AAAA;AAAA,MAChC,MAAM,KAAK,QAAQ;AAAA,MACnB,gBAAgB;AAAA,IAClB,CAAC;AAED,cAAUD,cAAa,MAAM;AAC7B;AAAA,EACF;AAGA,QAAM,UAAU,MAAM,WAAW;AAAA,IAC/B,aAAa;AAAA,IACb,MAAM,KAAK;AAAA,IACX,YAAY,KAAK;AAAA,IACjB,MAAM,KAAK;AAAA,EACb,CAAC;AAGD,MAAI,OAAO,YAAY,UAAU;AAC/B;AAAA,EACF;AAEA,QAAM,EAAE,aAAa,MAAM,YAAY,MAAM,eAAe,IAAI;AAChE,QAAM,YAAYE,SAAQ,QAAQ,IAAI,GAAG,WAAW;AAGpD,MAAIC,YAAW,SAAS,KAAK,CAAC,WAAW,SAAS,GAAG;AACnD,UAAM,kBAAkB,MAAQ,WAAQ;AAAA,MACtC,SAAS,cAAc,WAAW;AAAA,MAClC,cAAc;AAAA,IAChB,CAAC;AAED,QAAI,CAAC,mBAAqB,YAAS,eAAe,GAAG;AACnD,MAAE,UAAO,sBAAsB;AAC/B,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AAGA,MAAI;AACF,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAED,cAAU,aAAa,cAAc;AAAA,EACvC,SAAS,OAAO;AACd,cAAU,iBAAiB,QAAQ,MAAM,UAAU,8BAA8B;AACjF,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;;;AQlIA,IAAI,QAAQ,KAAK,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU;AAC1C,UAAQ,MAAM,KAAK;AACnB,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["resolve","existsSync","p","pc","existsSync","p","execa","__dirname","existsSync","spinner","execa","existsSync","mkdirSync","readdirSync","copyFileSync","readFileSync","writeFileSync","join","dirname","existsSync","readdirSync","pc","projectName","targetDir","resolve","existsSync"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/prompts.ts","../src/utils/validate.ts","../src/utils/package-manager.ts","../src/scaffold.ts","../src/template.ts","../src/utils/git.ts","../src/features/pages.ts","../src/utils/fs.ts","../src/index.ts"],"sourcesContent":["import mri from 'mri';\nimport { resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport type { CliOptions } from './types.js';\nimport { runPrompts, showIntro, showOutro, showError } from './prompts.js';\nimport { scaffold } from './scaffold.js';\nimport { isEmptyDir } from './utils/fs.js';\nimport { toValidProjectName } from './utils/validate.js';\n\nconst HELP_TEXT = `\n${pc.bold('create-velocity-astro')} - Create a new Velocity project\n\n${pc.bold('Usage:')}\n npm create velocity-astro@latest [project-name] [options]\n pnpm create velocity-astro [project-name] [options]\n yarn create velocity-astro [project-name] [options]\n bun create velocity-astro [project-name] [options]\n\n${pc.bold('Options:')}\n --demo Include demo landing page and sample content\n --components Include UI component library\n --i18n Add internationalization support\n --pages Prompt for starter pages to generate\n --yes, -y Skip prompts and use defaults\n --help, -h Show this help message\n --version, -v Show version number\n\n${pc.bold('Examples:')}\n npm create velocity-astro@latest my-site\n npm create velocity-astro@latest my-site --demo --components\n npm create velocity-astro@latest my-site --i18n --pages\n pnpm create velocity-astro my-site -y\n`;\n\nconst VERSION = '1.1.0';\n\nexport async function run(argv: string[]): Promise<void> {\n const args = mri<CliOptions>(argv, {\n boolean: ['demo', 'components', 'i18n', 'pages', 'help', 'version', 'yes'],\n alias: {\n h: 'help',\n v: 'version',\n y: 'yes',\n },\n });\n\n // Handle help\n if (args.help) {\n console.log(HELP_TEXT);\n return;\n }\n\n // Handle version\n if (args.version) {\n console.log(VERSION);\n return;\n }\n\n showIntro();\n\n // Get project name from args or prompt\n const argProjectName = args._[0] as string | undefined;\n\n // Skip prompts mode\n if (args.yes) {\n const projectName = toValidProjectName(argProjectName || 'my-velocity-site');\n const targetDir = resolve(process.cwd(), projectName);\n\n if (existsSync(targetDir) && !isEmptyDir(targetDir)) {\n showError(`Directory \"${projectName}\" already exists and is not empty.`);\n process.exit(1);\n }\n\n await scaffold({\n projectName,\n targetDir,\n demo: args.demo || false,\n components: args.components !== false, // Default to true\n i18n: args.i18n || false,\n pages: [],\n pageLayout: 'page',\n packageManager: 'pnpm',\n });\n\n showOutro(projectName, 'pnpm');\n return;\n }\n\n // Interactive mode\n const answers = await runPrompts({\n projectName: argProjectName,\n demo: args.demo,\n components: args.components,\n i18n: args.i18n,\n pages: args.pages,\n });\n\n // User cancelled\n if (typeof answers === 'symbol') {\n return;\n }\n\n const { projectName, demo, components, i18n, pages, pageLayout, packageManager } = answers;\n const targetDir = resolve(process.cwd(), projectName);\n\n // Check if directory exists and is not empty\n if (existsSync(targetDir) && !isEmptyDir(targetDir)) {\n const shouldOverwrite = await p.confirm({\n message: `Directory \"${projectName}\" already exists. Continue and overwrite?`,\n initialValue: false,\n });\n\n if (!shouldOverwrite || p.isCancel(shouldOverwrite)) {\n p.cancel('Operation cancelled.');\n process.exit(0);\n }\n }\n\n // Run scaffold\n try {\n await scaffold({\n projectName,\n targetDir,\n demo,\n components,\n i18n,\n pages,\n pageLayout,\n packageManager,\n });\n\n showOutro(projectName, packageManager);\n } catch (error) {\n showError(error instanceof Error ? error.message : 'An unexpected error occurred');\n process.exit(1);\n }\n}\n","import * as p from '@clack/prompts';\nimport pc from 'picocolors';\nimport type { PackageManager, PageLayout, PromptAnswers } from './types.js';\nimport { validateProjectName, toValidProjectName } from './utils/validate.js';\nimport { detectPackageManager } from './utils/package-manager.js';\n\ninterface PromptDefaults {\n projectName?: string;\n demo?: boolean;\n components?: boolean;\n i18n?: boolean;\n pages?: boolean;\n}\n\n/**\n * Parses comma-separated page names into an array of valid page slugs\n */\nfunction parsePageNames(input: string): string[] {\n if (!input.trim()) return [];\n\n return input\n .split(',')\n .map((name) => name.trim().toLowerCase())\n .filter((name) => name.length > 0)\n .map((name) => name.replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, ''))\n .filter((name) => name.length > 0 && !['index', 'blog', '404', 'rss'].includes(name));\n}\n\nexport async function runPrompts(defaults: PromptDefaults = {}): Promise<PromptAnswers | symbol> {\n const detectedPm = detectPackageManager();\n\n const answers = await p.group(\n {\n projectName: () =>\n p.text({\n message: 'What is your project name?',\n placeholder: defaults.projectName || 'my-velocity-site',\n defaultValue: defaults.projectName,\n validate: (value) => {\n const name = value || defaults.projectName || 'my-velocity-site';\n const result = validateProjectName(toValidProjectName(name));\n if (!result.valid) return result.message;\n },\n }),\n\n demo:\n defaults.demo !== undefined\n ? () => Promise.resolve(defaults.demo)\n : () =>\n p.select({\n message: 'Include demo landing page and sample content?',\n options: [\n {\n value: false,\n label: 'No',\n hint: 'Minimal starter with basic pages',\n },\n {\n value: true,\n label: 'Yes',\n hint: 'Full demo with landing page, blog posts',\n },\n ],\n initialValue: false,\n }),\n\n components:\n defaults.components !== undefined\n ? () => Promise.resolve(defaults.components)\n : () =>\n p.select({\n message: 'Include UI component library?',\n options: [\n {\n value: false,\n label: 'No',\n hint: 'Just the basics',\n },\n {\n value: true,\n label: 'Yes',\n hint: 'Buttons, forms, cards, dialogs, etc.',\n },\n ],\n initialValue: true,\n }),\n\n i18n:\n defaults.i18n !== undefined\n ? () => Promise.resolve(defaults.i18n)\n : () =>\n p.select({\n message: 'Add internationalization (i18n)?',\n options: [\n {\n value: false,\n label: 'No',\n hint: 'English only',\n },\n {\n value: true,\n label: 'Yes',\n hint: 'Locale routing, translations',\n },\n ],\n initialValue: false,\n }),\n\n generatePages:\n defaults.pages !== undefined\n ? () => Promise.resolve(defaults.pages)\n : () =>\n p.select({\n message: 'Generate starter pages?',\n options: [\n {\n value: false,\n label: 'No',\n hint: 'Create pages manually later',\n },\n {\n value: true,\n label: 'Yes',\n hint: 'Auto-generate page files with layout',\n },\n ],\n initialValue: false,\n }),\n\n pageNames: ({ results }) =>\n results.generatePages\n ? p.text({\n message: 'Enter page names (comma-separated):',\n placeholder: 'about, pricing, faq, contact',\n validate: (value) => {\n const pages = parsePageNames(value);\n if (pages.length === 0) {\n return 'Please enter at least one valid page name';\n }\n },\n })\n : Promise.resolve(''),\n\n pageLayout: ({ results }) =>\n results.generatePages\n ? p.select({\n message: 'Select layout for pages:',\n options: [\n {\n value: 'page' as PageLayout,\n label: 'PageLayout',\n hint: 'Standard content pages (Header + Footer)',\n },\n {\n value: 'landing' as PageLayout,\n label: 'LandingLayout',\n hint: 'Marketing pages (Navbar + LandingFooter)',\n },\n ],\n initialValue: 'page' as PageLayout,\n })\n : Promise.resolve('page' as PageLayout),\n\n packageManager: () =>\n p.select({\n message: 'Which package manager?',\n options: [\n {\n value: 'pnpm' as PackageManager,\n label: 'pnpm',\n hint: detectedPm === 'pnpm' ? 'detected' : 'recommended',\n },\n {\n value: 'npm' as PackageManager,\n label: 'npm',\n hint: detectedPm === 'npm' ? 'detected' : undefined,\n },\n {\n value: 'yarn' as PackageManager,\n label: 'yarn',\n hint: detectedPm === 'yarn' ? 'detected' : undefined,\n },\n {\n value: 'bun' as PackageManager,\n label: 'bun',\n hint: detectedPm === 'bun' ? 'detected' : undefined,\n },\n ],\n initialValue: detectedPm,\n }),\n },\n {\n onCancel: () => {\n p.cancel('Operation cancelled.');\n process.exit(0);\n },\n }\n );\n\n return {\n projectName: toValidProjectName(answers.projectName || defaults.projectName || 'my-velocity-site'),\n demo: answers.demo as boolean,\n components: answers.components as boolean,\n i18n: answers.i18n as boolean,\n pages: parsePageNames(answers.pageNames as string),\n pageLayout: (answers.pageLayout as PageLayout) || 'page',\n packageManager: answers.packageManager as PackageManager,\n };\n}\n\nexport function showIntro(): void {\n console.log();\n p.intro(pc.bgCyan(pc.black(' Create Velocity ')));\n}\n\nexport function showOutro(projectName: string, packageManager: PackageManager): void {\n const runCmd = packageManager === 'npm' ? 'npm run' : packageManager;\n\n p.note(\n [\n `cd ${projectName}`,\n `${runCmd} dev`,\n ].join('\\n'),\n 'Next steps'\n );\n\n p.outro(pc.green('Happy building!'));\n}\n\nexport function showError(message: string): void {\n p.log.error(pc.red(message));\n}\n\nexport function showWarning(message: string): void {\n p.log.warn(pc.yellow(message));\n}\n\nexport function showSuccess(message: string): void {\n p.log.success(pc.green(message));\n}\n\nexport function showStep(message: string): void {\n p.log.step(message);\n}\n","/**\n * Validates a project name for npm package naming conventions\n */\nexport function validateProjectName(name: string): { valid: boolean; message?: string } {\n if (!name || name.trim() === '') {\n return { valid: false, message: 'Project name cannot be empty' };\n }\n\n // Must be lowercase\n if (name !== name.toLowerCase()) {\n return { valid: false, message: 'Project name must be lowercase' };\n }\n\n // Cannot start with . or _\n if (name.startsWith('.') || name.startsWith('_')) {\n return { valid: false, message: 'Project name cannot start with . or _' };\n }\n\n // Cannot contain spaces\n if (/\\s/.test(name)) {\n return { valid: false, message: 'Project name cannot contain spaces' };\n }\n\n // Cannot contain special characters except - and @/\n if (!/^(@[a-z0-9-~][a-z0-9-._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(name)) {\n return {\n valid: false,\n message: 'Project name can only contain lowercase letters, numbers, hyphens, and underscores',\n };\n }\n\n // Length check\n if (name.length > 214) {\n return { valid: false, message: 'Project name must be 214 characters or fewer' };\n }\n\n return { valid: true };\n}\n\n/**\n * Sanitizes a string to be a valid project name\n */\nexport function toValidProjectName(name: string): string {\n return name\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, '-')\n .replace(/[^a-z0-9-_~.]/g, '-')\n .replace(/^[-._]+/, '')\n .replace(/[-._]+$/, '')\n .replace(/-+/g, '-');\n}\n","import type { PackageManager } from '../types.js';\n\n/**\n * Detects the package manager used to run this command\n */\nexport function detectPackageManager(): PackageManager {\n const userAgent = process.env.npm_config_user_agent || '';\n\n if (userAgent.startsWith('pnpm')) return 'pnpm';\n if (userAgent.startsWith('yarn')) return 'yarn';\n if (userAgent.startsWith('bun')) return 'bun';\n return 'npm';\n}\n\n/**\n * Gets the install command for a package manager\n */\nexport function getInstallCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return 'pnpm install';\n case 'yarn':\n return 'yarn';\n case 'bun':\n return 'bun install';\n case 'npm':\n default:\n return 'npm install';\n }\n}\n\n/**\n * Gets the run command for a package manager\n */\nexport function getRunCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return 'pnpm';\n case 'yarn':\n return 'yarn';\n case 'bun':\n return 'bun';\n case 'npm':\n default:\n return 'npm run';\n }\n}\n","import { existsSync, mkdirSync, readdirSync, copyFileSync, readFileSync, writeFileSync, rmSync } from 'node:fs';\nimport { join } from 'node:path';\nimport * as p from '@clack/prompts';\nimport { execa } from 'execa';\nimport { downloadTemplate } from 'giget';\nimport type { ScaffoldOptions } from './types.js';\nimport { getI18nTemplatePath, getBaseTemplatePath } from './template.js';\nimport { getInstallCommand } from './utils/package-manager.js';\nimport { initGit } from './utils/git.js';\nimport { showSuccess, showWarning } from './prompts.js';\nimport { generatePages } from './features/pages.js';\n\n// GitHub repository for the Velocity template\nconst TEMPLATE_REPO = 'github:southwellmedia-dev/velocity';\n\n// Files/directories to remove after download\nconst CLEANUP_ITEMS = [\n 'pnpm-lock.yaml',\n 'package-lock.json',\n 'yarn.lock',\n 'bun.lockb',\n '.git',\n];\n\n// Demo-specific content to remove when --demo is false\nconst DEMO_CONTENT = [\n 'src/components/landing',\n 'src/pages/about.astro',\n 'src/pages/contact.astro',\n 'src/content/blog',\n 'src/content/faqs',\n 'src/content/authors',\n 'src/content/pages',\n];\n\n// UI component library content to remove when --components is false\nconst COMPONENTS_CONTENT = [\n 'src/components/ui',\n 'src/components/patterns',\n 'src/pages/components.astro',\n];\n\n/**\n * Copies template files recursively\n */\nfunction copyTemplateFiles(src: string, dest: string): void {\n if (!existsSync(dest)) {\n mkdirSync(dest, { recursive: true });\n }\n\n const entries = readdirSync(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(src, entry.name);\n const destPath = join(dest, entry.name);\n\n if (entry.isDirectory()) {\n copyTemplateFiles(srcPath, destPath);\n } else {\n copyFileSync(srcPath, destPath);\n }\n }\n}\n\n/**\n * Removes files/directories from the target\n */\nfunction removeItems(targetDir: string, items: string[]): void {\n for (const item of items) {\n const itemPath = join(targetDir, item);\n if (existsSync(itemPath)) {\n try {\n rmSync(itemPath, { recursive: true, force: true });\n } catch {\n // Ignore errors - item may not exist or be locked\n }\n }\n }\n}\n\n/**\n * Updates the package.json with the new project name\n */\nfunction updatePackageJson(targetDir: string, projectName: string): void {\n const pkgPath = join(targetDir, 'package.json');\n\n if (!existsSync(pkgPath)) {\n throw new Error('package.json not found in template');\n }\n\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));\n pkg.name = projectName;\n pkg.version = '0.1.0';\n delete pkg.repository;\n delete pkg.bugs;\n delete pkg.homepage;\n\n writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\n}\n\n/**\n * Applies base template (minimal pages) when demo is not selected\n */\nfunction applyBaseTemplate(targetDir: string): void {\n const baseTemplate = getBaseTemplatePath();\n if (existsSync(baseTemplate)) {\n copyTemplateFiles(baseTemplate, targetDir);\n }\n}\n\n/**\n * Applies the i18n overlay to the project\n */\nfunction applyI18nOverlay(targetDir: string): void {\n const i18nTemplate = getI18nTemplatePath();\n copyTemplateFiles(i18nTemplate, targetDir);\n}\n\n/**\n * Creates empty content directories with .gitkeep files\n */\nfunction createContentDirectories(targetDir: string): void {\n const contentDirs = [\n 'src/content/blog',\n ];\n\n for (const dir of contentDirs) {\n const dirPath = join(targetDir, dir);\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n writeFileSync(join(dirPath, '.gitkeep'), '');\n }\n }\n}\n\n/**\n * Main scaffold function\n */\nexport async function scaffold(options: ScaffoldOptions): Promise<void> {\n const { projectName, targetDir, demo, components, i18n, pages, pageLayout, packageManager } = options;\n const spinner = p.spinner();\n\n // Step 1: Download base template from GitHub\n spinner.start('Downloading template from GitHub...');\n\n try {\n await downloadTemplate(TEMPLATE_REPO, {\n dir: targetDir,\n force: true,\n });\n removeItems(targetDir, CLEANUP_ITEMS);\n spinner.stop('Template downloaded');\n } catch (error) {\n spinner.stop('Failed to download template');\n throw new Error(\n `Could not download template from GitHub. Please check your internet connection.\\n${error instanceof Error ? error.message : ''}`\n );\n }\n\n // Step 2: Remove demo content if not requested\n if (!demo) {\n spinner.start('Configuring minimal template...');\n removeItems(targetDir, DEMO_CONTENT);\n applyBaseTemplate(targetDir);\n createContentDirectories(targetDir);\n spinner.stop('Minimal template configured');\n }\n\n // Step 3: Remove UI components if not requested\n if (!components) {\n spinner.start('Removing UI component library...');\n removeItems(targetDir, COMPONENTS_CONTENT);\n spinner.stop('UI components removed');\n }\n\n // Step 4: Apply i18n overlay if requested\n if (i18n) {\n spinner.start('Adding i18n support...');\n try {\n applyI18nOverlay(targetDir);\n spinner.stop('i18n support added');\n } catch (error) {\n spinner.stop('Failed to add i18n support');\n throw error;\n }\n }\n\n // Step 5: Generate starter pages if requested\n if (pages.length > 0) {\n spinner.start(`Generating ${pages.length} starter page${pages.length > 1 ? 's' : ''}...`);\n try {\n const generatedFiles = await generatePages(targetDir, pages, pageLayout, i18n);\n spinner.stop(`Generated ${generatedFiles.length} page file${generatedFiles.length > 1 ? 's' : ''}`);\n } catch (error) {\n spinner.stop('Failed to generate pages');\n throw error;\n }\n }\n\n // Step 6: Update package.json\n spinner.start('Configuring project...');\n try {\n updatePackageJson(targetDir, projectName);\n spinner.stop('Project configured');\n } catch (error) {\n spinner.stop('Failed to configure project');\n throw error;\n }\n\n // Step 7: Initialize git\n spinner.start('Initializing git repository...');\n const gitInitialized = await initGit(targetDir);\n if (gitInitialized) {\n spinner.stop('Git repository initialized');\n } else {\n spinner.stop('Git not available, skipping');\n }\n\n // Step 8: Install dependencies\n spinner.start(`Installing dependencies with ${packageManager}...`);\n try {\n const installCmd = getInstallCommand(packageManager);\n const [cmd, ...args] = installCmd.split(' ');\n await execa(cmd!, args, { cwd: targetDir });\n spinner.stop('Dependencies installed');\n } catch {\n spinner.stop('Failed to install dependencies');\n showWarning(`Run \"${getInstallCommand(packageManager)}\" manually to install dependencies`);\n }\n\n showSuccess(`Project \"${projectName}\" created successfully!`);\n}\n","import { existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\n/**\n * Resolves the path to the base template (minimal pages)\n */\nexport function getBaseTemplatePath(): string {\n const templatePath = resolve(__dirname, '..', 'templates', 'base');\n\n if (existsSync(templatePath)) {\n return templatePath;\n }\n\n throw new Error('Could not find base template. Package may be corrupted.');\n}\n\n/**\n * Resolves the path to the i18n overlay template\n */\nexport function getI18nTemplatePath(): string {\n const templatePath = resolve(__dirname, '..', 'templates', 'i18n');\n\n if (existsSync(templatePath)) {\n return templatePath;\n }\n\n throw new Error('Could not find i18n template. Package may be corrupted.');\n}\n","import { execa } from 'execa';\n\n/**\n * Initializes a git repository in the target directory\n */\nexport async function initGit(targetDir: string): Promise<boolean> {\n try {\n await execa('git', ['init'], { cwd: targetDir });\n await execa('git', ['add', '-A'], { cwd: targetDir });\n await execa('git', ['commit', '-m', 'Initial commit from create-velocity'], {\n cwd: targetDir,\n });\n return true;\n } catch {\n // Git may not be installed or configured\n return false;\n }\n}\n\n/**\n * Checks if git is available\n */\nexport async function isGitInstalled(): Promise<boolean> {\n try {\n await execa('git', ['--version']);\n return true;\n } catch {\n return false;\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { PageLayout } from '../types.js';\n\n/**\n * Converts a page slug to a display title\n * e.g., 'about-us' -> 'About Us'\n */\nfunction toTitle(slug: string): string {\n return slug\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n}\n\n/**\n * Generates the standard page template (non-i18n)\n */\nfunction generatePageTemplate(pageName: string, layout: PageLayout): string {\n const title = toTitle(pageName);\n const layoutName = layout === 'landing' ? 'LandingLayout' : 'PageLayout';\n\n return `---\nimport ${layoutName} from '@/layouts/${layoutName}.astro';\n---\n\n<${layoutName}\n title=\"${title}\"\n description=\"Add your description here\"\n>\n <!-- Hero Section -->\n <section class=\"py-20 bg-secondary\">\n <div class=\"container\">\n <h1 class=\"text-4xl font-bold text-foreground\">${title}</h1>\n <p class=\"mt-4 text-foreground-muted max-w-2xl\">\n Add your content here.\n </p>\n </div>\n </section>\n\n <!-- Content Section -->\n <section class=\"py-16\">\n <div class=\"container\">\n <!-- Your content -->\n </div>\n </section>\n</${layoutName}>\n`;\n}\n\n/**\n * Generates the i18n-aware page template\n */\nfunction generateI18nPageTemplate(pageName: string, layout: PageLayout): string {\n const title = toTitle(pageName);\n const layoutName = layout === 'landing' ? 'LandingLayout' : 'PageLayout';\n const titleKey = `${pageName.replace(/-/g, '_')}.title`;\n const descKey = `${pageName.replace(/-/g, '_')}.description`;\n\n return `---\nimport ${layoutName} from '@/layouts/${layoutName}.astro';\nimport { locales, isValidLocale, type Locale } from '@/i18n/config';\nimport { useTranslations } from '@/i18n/index';\n\nexport function getStaticPaths() {\n return locales.map((lang) => ({\n params: { lang },\n }));\n}\n\nconst { lang } = Astro.params;\n\nif (!lang || !isValidLocale(lang)) {\n return Astro.redirect('/');\n}\n\nconst locale = lang as Locale;\nconst t = useTranslations(locale);\n---\n\n<${layoutName}\n title={t('${titleKey}') || '${title}'}\n description={t('${descKey}') || 'Add your description here'}\n lang={locale}\n>\n <!-- Hero Section -->\n <section class=\"py-20 bg-secondary\">\n <div class=\"container\">\n <h1 class=\"text-4xl font-bold text-foreground\">\n {t('${titleKey}') || '${title}'}\n </h1>\n <p class=\"mt-4 text-foreground-muted max-w-2xl\">\n {t('${descKey}') || 'Add your content here.'}\n </p>\n </div>\n </section>\n\n <!-- Content Section -->\n <section class=\"py-16\">\n <div class=\"container\">\n <!-- Your content -->\n </div>\n </section>\n</${layoutName}>\n`;\n}\n\n/**\n * Generates pages in the target directory\n */\nexport async function generatePages(\n targetDir: string,\n pages: string[],\n layout: PageLayout,\n isI18n: boolean\n): Promise<string[]> {\n const generatedFiles: string[] = [];\n\n if (pages.length === 0) {\n return generatedFiles;\n }\n\n // Ensure pages directory exists\n const pagesDir = join(targetDir, 'src', 'pages');\n if (!existsSync(pagesDir)) {\n mkdirSync(pagesDir, { recursive: true });\n }\n\n // Generate standard pages\n for (const pageName of pages) {\n const filePath = join(pagesDir, `${pageName}.astro`);\n const template = generatePageTemplate(pageName, layout);\n writeFileSync(filePath, template);\n generatedFiles.push(`src/pages/${pageName}.astro`);\n }\n\n // Generate i18n pages if enabled\n if (isI18n) {\n const langDir = join(pagesDir, '[lang]');\n if (!existsSync(langDir)) {\n mkdirSync(langDir, { recursive: true });\n }\n\n for (const pageName of pages) {\n const filePath = join(langDir, `${pageName}.astro`);\n const template = generateI18nPageTemplate(pageName, layout);\n writeFileSync(filePath, template);\n generatedFiles.push(`src/pages/[lang]/${pageName}.astro`);\n }\n }\n\n return generatedFiles;\n}\n\n/**\n * List of page-related files that could be generated\n */\nexport const PAGES_FILES = [\n 'src/pages/{pageName}.astro',\n 'src/pages/[lang]/{pageName}.astro',\n];\n","import { existsSync, mkdirSync, readdirSync, statSync, copyFileSync, readFileSync, writeFileSync } from 'node:fs';\nimport { join, dirname } from 'node:path';\n\n/**\n * Recursively copies a directory\n */\nexport function copyDirectory(src: string, dest: string, overwrite = false): void {\n if (!existsSync(src)) {\n throw new Error(`Source directory does not exist: ${src}`);\n }\n\n if (!existsSync(dest)) {\n mkdirSync(dest, { recursive: true });\n }\n\n const entries = readdirSync(src, { withFileTypes: true });\n\n for (const entry of entries) {\n const srcPath = join(src, entry.name);\n const destPath = join(dest, entry.name);\n\n if (entry.isDirectory()) {\n copyDirectory(srcPath, destPath, overwrite);\n } else {\n if (overwrite || !existsSync(destPath)) {\n const destDir = dirname(destPath);\n if (!existsSync(destDir)) {\n mkdirSync(destDir, { recursive: true });\n }\n copyFileSync(srcPath, destPath);\n }\n }\n }\n}\n\n/**\n * Checks if a directory is empty\n */\nexport function isEmptyDir(path: string): boolean {\n if (!existsSync(path)) return true;\n const files = readdirSync(path);\n return files.length === 0 || (files.length === 1 && files[0] === '.git');\n}\n\n/**\n * Reads a JSON file and parses it\n */\nexport function readJson<T = Record<string, unknown>>(path: string): T {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content) as T;\n}\n\n/**\n * Writes an object as JSON to a file\n */\nexport function writeJson(path: string, data: unknown): void {\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n');\n}\n\n/**\n * Checks if path exists and is a directory\n */\nexport function isDirectory(path: string): boolean {\n return existsSync(path) && statSync(path).isDirectory();\n}\n","import { run } from './cli.js';\n\nrun(process.argv.slice(2)).catch((error) => {\n console.error(error);\n process.exit(1);\n});\n"],"mappings":"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","names":["resolve","existsSync","p","pc","existsSync","mkdirSync","writeFileSync","join","p","execa","__dirname","existsSync","existsSync","mkdirSync","join","writeFileSync","spinner","execa","existsSync","mkdirSync","readdirSync","copyFileSync","readFileSync","writeFileSync","join","dirname","existsSync","readdirSync","pc","projectName","targetDir","resolve","existsSync"]}
|
package/package.json
CHANGED
|
@@ -11,9 +11,9 @@ const t = useTranslations(locale);
|
|
|
11
11
|
|
|
12
12
|
const links = [
|
|
13
13
|
{ labelKey: 'footer.links.documentation' as const, href: localePath('/blog', locale) },
|
|
14
|
-
{ labelKey: 'footer.links.github' as const, href: 'https://github.com/
|
|
14
|
+
{ labelKey: 'footer.links.github' as const, href: 'https://github.com/southwellmedia-dev/velocity' },
|
|
15
15
|
{ labelKey: 'footer.links.twitter' as const, href: 'https://twitter.com/southwellmedia' },
|
|
16
|
-
{ labelKey: 'footer.links.license' as const, href: 'https://github.com/
|
|
16
|
+
{ labelKey: 'footer.links.license' as const, href: 'https://github.com/southwellmedia-dev/velocity/blob/main/LICENSE' },
|
|
17
17
|
];
|
|
18
18
|
|
|
19
19
|
const homeLink = locale === defaultLocale ? '/' : `/${locale}`;
|