basecampjs 0.0.10 → 0.0.12
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/index.js +61 -35
- package/package.json +2 -1
package/index.js
CHANGED
|
@@ -70,7 +70,7 @@ function showHelp() {
|
|
|
70
70
|
console.log(kolor.dim("Build and manage your static campsite.\n"));
|
|
71
71
|
|
|
72
72
|
console.log(kolor.bold("Usage:"));
|
|
73
|
-
console.log("
|
|
73
|
+
console.log(" camper <command> [arguments] [options]\n");
|
|
74
74
|
|
|
75
75
|
console.log(kolor.bold("Project Commands:"));
|
|
76
76
|
console.log(" " + kolor.cyan("init") + " Initialize a new Campsite project in current directory");
|
|
@@ -110,15 +110,15 @@ function showHelp() {
|
|
|
110
110
|
|
|
111
111
|
console.log(kolor.bold("Examples:"));
|
|
112
112
|
console.log(" " + kolor.dim("# Initialize a new project"));
|
|
113
|
-
console.log("
|
|
113
|
+
console.log(" camper init\n");
|
|
114
114
|
console.log(" " + kolor.dim("# Start development"));
|
|
115
|
-
console.log("
|
|
115
|
+
console.log(" camper dev\n");
|
|
116
116
|
console.log(" " + kolor.dim("# Create new content"));
|
|
117
|
-
console.log("
|
|
118
|
-
console.log("
|
|
119
|
-
console.log("
|
|
117
|
+
console.log(" camper make:page about");
|
|
118
|
+
console.log(" camper make:post \"My First Post\"");
|
|
119
|
+
console.log(" camper make:collection products\n");
|
|
120
120
|
console.log(" " + kolor.dim("# Build and preview"));
|
|
121
|
-
console.log("
|
|
121
|
+
console.log(" camper preview\n");
|
|
122
122
|
console.log(kolor.dim("For more information, visit: https://campsitejs.dev"));
|
|
123
123
|
console.log();
|
|
124
124
|
}
|
|
@@ -388,6 +388,26 @@ function createLiquidEnv(layoutsDir, pagesDir, srcDir, partialsDir) {
|
|
|
388
388
|
});
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
+
async function loadMustachePartials(partialsDir) {
|
|
392
|
+
const partials = {};
|
|
393
|
+
if (!existsSync(partialsDir)) return partials;
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
const files = await walkFiles(partialsDir);
|
|
397
|
+
await Promise.all(files.map(async (file) => {
|
|
398
|
+
if (extname(file).toLowerCase() === ".mustache") {
|
|
399
|
+
const content = await readFile(file, "utf8");
|
|
400
|
+
const partialName = basename(file, ".mustache");
|
|
401
|
+
partials[partialName] = content;
|
|
402
|
+
}
|
|
403
|
+
}));
|
|
404
|
+
} catch (err) {
|
|
405
|
+
console.error(kolor.yellow(`Warning: Failed to load Mustache partials: ${err.message}`));
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return partials;
|
|
409
|
+
}
|
|
410
|
+
|
|
391
411
|
function toUrlPath(outRel) {
|
|
392
412
|
const normalized = outRel.replace(/\\/g, "/");
|
|
393
413
|
let path = `/${normalized}`;
|
|
@@ -416,7 +436,7 @@ function shouldRenderMarkdown(frontmatter, config, defaultValue) {
|
|
|
416
436
|
return defaultValue;
|
|
417
437
|
}
|
|
418
438
|
|
|
419
|
-
async function renderWithLayout(layoutName, html, ctx, env, liquidEnv, layoutsDir) {
|
|
439
|
+
async function renderWithLayout(layoutName, html, ctx, env, liquidEnv, layoutsDir, partials = {}) {
|
|
420
440
|
if (!layoutName) return html;
|
|
421
441
|
const ext = extname(layoutName).toLowerCase();
|
|
422
442
|
const layoutCtx = {
|
|
@@ -438,7 +458,7 @@ async function renderWithLayout(layoutName, html, ctx, env, liquidEnv, layoutsDi
|
|
|
438
458
|
const layoutPath = join(layoutsDir, layoutName);
|
|
439
459
|
if (existsSync(layoutPath)) {
|
|
440
460
|
const layoutTemplate = await readFile(layoutPath, "utf8");
|
|
441
|
-
return Mustache.render(layoutTemplate, layoutCtx);
|
|
461
|
+
return Mustache.render(layoutTemplate, layoutCtx, partials);
|
|
442
462
|
}
|
|
443
463
|
}
|
|
444
464
|
|
|
@@ -446,20 +466,25 @@ async function renderWithLayout(layoutName, html, ctx, env, liquidEnv, layoutsDi
|
|
|
446
466
|
return html;
|
|
447
467
|
}
|
|
448
468
|
|
|
449
|
-
async function renderPage(filePath, { pagesDir, layoutsDir, outDir, env, liquidEnv, config, data }) {
|
|
469
|
+
async function renderPage(filePath, { pagesDir, layoutsDir, outDir, env, liquidEnv, config, data, partialsDir }) {
|
|
450
470
|
const rel = relative(pagesDir, filePath);
|
|
451
471
|
const ext = extname(filePath).toLowerCase();
|
|
452
472
|
const outRel = rel.replace(/\.liquid(\.html)?$/i, ".html").replace(ext, ".html");
|
|
453
473
|
const outPath = join(outDir, outRel);
|
|
454
474
|
const path = toUrlPath(outRel);
|
|
455
475
|
await ensureDir(dirname(outPath));
|
|
476
|
+
|
|
477
|
+
// Load Mustache partials if needed
|
|
478
|
+
const partials = (ext === ".mustache" || (await readFile(filePath, "utf8")).match(/layout:.*\.mustache/))
|
|
479
|
+
? await loadMustachePartials(partialsDir)
|
|
480
|
+
: {};
|
|
456
481
|
|
|
457
482
|
if (ext === ".md") {
|
|
458
483
|
const raw = await readFile(filePath, "utf8");
|
|
459
484
|
const parsed = matter(raw);
|
|
460
485
|
const html = md.render(parsed.content);
|
|
461
486
|
const ctx = pageContext(parsed.data, html, config, rel, data, path);
|
|
462
|
-
const rendered = await renderWithLayout(parsed.data.layout, html, ctx, env, liquidEnv, layoutsDir);
|
|
487
|
+
const rendered = await renderWithLayout(parsed.data.layout, html, ctx, env, liquidEnv, layoutsDir, partials);
|
|
463
488
|
await writeFile(outPath, rendered, "utf8");
|
|
464
489
|
return;
|
|
465
490
|
}
|
|
@@ -473,7 +498,7 @@ async function renderPage(filePath, { pagesDir, layoutsDir, outDir, env, liquidE
|
|
|
473
498
|
if (shouldRenderMarkdown(parsed.data, config, false)) {
|
|
474
499
|
pageHtml = md.render(pageHtml);
|
|
475
500
|
}
|
|
476
|
-
const rendered = await renderWithLayout(parsed.data.layout, pageHtml, ctx, env, liquidEnv, layoutsDir);
|
|
501
|
+
const rendered = await renderWithLayout(parsed.data.layout, pageHtml, ctx, env, liquidEnv, layoutsDir, partials);
|
|
477
502
|
await writeFile(outPath, rendered, "utf8");
|
|
478
503
|
return;
|
|
479
504
|
}
|
|
@@ -486,7 +511,7 @@ async function renderPage(filePath, { pagesDir, layoutsDir, outDir, env, liquidE
|
|
|
486
511
|
if (shouldRenderMarkdown(parsed.data, config, false)) {
|
|
487
512
|
pageHtml = md.render(pageHtml);
|
|
488
513
|
}
|
|
489
|
-
const rendered = await renderWithLayout(parsed.data.layout, pageHtml, ctx, env, liquidEnv, layoutsDir);
|
|
514
|
+
const rendered = await renderWithLayout(parsed.data.layout, pageHtml, ctx, env, liquidEnv, layoutsDir, partials);
|
|
490
515
|
await writeFile(outPath, rendered, "utf8");
|
|
491
516
|
return;
|
|
492
517
|
}
|
|
@@ -495,11 +520,11 @@ async function renderPage(filePath, { pagesDir, layoutsDir, outDir, env, liquidE
|
|
|
495
520
|
const raw = await readFile(filePath, "utf8");
|
|
496
521
|
const parsed = matter(raw);
|
|
497
522
|
const ctx = pageContext(parsed.data, parsed.content, config, rel, data, path);
|
|
498
|
-
let pageHtml = Mustache.render(parsed.content, ctx);
|
|
523
|
+
let pageHtml = Mustache.render(parsed.content, ctx, partials);
|
|
499
524
|
if (shouldRenderMarkdown(parsed.data, config, false)) {
|
|
500
525
|
pageHtml = md.render(pageHtml);
|
|
501
526
|
}
|
|
502
|
-
const rendered = await renderWithLayout(parsed.data.layout, pageHtml, ctx, env, liquidEnv, layoutsDir);
|
|
527
|
+
const rendered = await renderWithLayout(parsed.data.layout, pageHtml, ctx, env, liquidEnv, layoutsDir, partials);
|
|
503
528
|
await writeFile(outPath, rendered, "utf8");
|
|
504
529
|
return;
|
|
505
530
|
}
|
|
@@ -512,7 +537,7 @@ async function renderPage(filePath, { pagesDir, layoutsDir, outDir, env, liquidE
|
|
|
512
537
|
if (shouldRenderMarkdown(parsed.data, config, false)) {
|
|
513
538
|
pageHtml = md.render(pageHtml);
|
|
514
539
|
}
|
|
515
|
-
const rendered = await renderWithLayout(parsed.data.layout, pageHtml, ctx, env, liquidEnv, layoutsDir);
|
|
540
|
+
const rendered = await renderWithLayout(parsed.data.layout, pageHtml, ctx, env, liquidEnv, layoutsDir, partials);
|
|
516
541
|
await writeFile(outPath, rendered, "utf8");
|
|
517
542
|
return;
|
|
518
543
|
}
|
|
@@ -645,7 +670,7 @@ async function build(cwdArg = cwd) {
|
|
|
645
670
|
return;
|
|
646
671
|
}
|
|
647
672
|
|
|
648
|
-
await Promise.all(files.map((file) => renderPage(file, { pagesDir, layoutsDir, outDir, env, liquidEnv, config, data })));
|
|
673
|
+
await Promise.all(files.map((file) => renderPage(file, { pagesDir, layoutsDir, outDir, env, liquidEnv, config, data, partialsDir })));
|
|
649
674
|
|
|
650
675
|
if (config.minifyCSS) {
|
|
651
676
|
await minifyCSSFiles(outDir);
|
|
@@ -789,17 +814,17 @@ async function makeContent(type) {
|
|
|
789
814
|
|
|
790
815
|
if (args.length === 0) {
|
|
791
816
|
console.log(kolor.red("❌ Missing name argument"));
|
|
792
|
-
console.log(kolor.dim(`Usage:
|
|
817
|
+
console.log(kolor.dim(`Usage: camper make:${type} <name> [name2, name3, ...]`));
|
|
793
818
|
console.log(kolor.dim("\nExamples:"));
|
|
794
|
-
console.log(kolor.dim("
|
|
795
|
-
console.log(kolor.dim("
|
|
796
|
-
console.log(kolor.dim("
|
|
819
|
+
console.log(kolor.dim(" camper make:page about"));
|
|
820
|
+
console.log(kolor.dim(" camper make:page home, about, contact"));
|
|
821
|
+
console.log(kolor.dim(" camper make:collection products, categories\n"));
|
|
797
822
|
exit(1);
|
|
798
823
|
}
|
|
799
824
|
|
|
800
825
|
// Join all args and split by comma to support both formats:
|
|
801
|
-
//
|
|
802
|
-
//
|
|
826
|
+
// camper make:page home about contact
|
|
827
|
+
// camper make:page home, about, contact
|
|
803
828
|
const namesString = args.join(" ");
|
|
804
829
|
const names = namesString.split(",").map(n => n.trim()).filter(n => n.length > 0);
|
|
805
830
|
|
|
@@ -1024,7 +1049,7 @@ async function init() {
|
|
|
1024
1049
|
// Check if already initialized
|
|
1025
1050
|
if (existsSync(join(targetDir, "campsite.config.js"))) {
|
|
1026
1051
|
console.log(kolor.yellow("⚠️ This directory already has a campsite.config.js file."));
|
|
1027
|
-
console.log(kolor.dim("Run '
|
|
1052
|
+
console.log(kolor.dim("Run 'camper dev' to start developing.\n"));
|
|
1028
1053
|
return;
|
|
1029
1054
|
}
|
|
1030
1055
|
|
|
@@ -1087,7 +1112,7 @@ Your cozy static site is ready to build.
|
|
|
1087
1112
|
|
|
1088
1113
|
## Get Started
|
|
1089
1114
|
|
|
1090
|
-
- Run \`
|
|
1115
|
+
- Run \`camper dev\` to start developing
|
|
1091
1116
|
- Edit pages in \`src/pages/\`
|
|
1092
1117
|
- Customize layouts in \`src/layouts/\`
|
|
1093
1118
|
|
|
@@ -1128,10 +1153,10 @@ dist/
|
|
|
1128
1153
|
version: "0.0.1",
|
|
1129
1154
|
type: "module",
|
|
1130
1155
|
scripts: {
|
|
1131
|
-
dev: "
|
|
1132
|
-
build: "
|
|
1133
|
-
serve: "
|
|
1134
|
-
preview: "
|
|
1156
|
+
dev: "camper dev",
|
|
1157
|
+
build: "camper build",
|
|
1158
|
+
serve: "camper serve",
|
|
1159
|
+
preview: "camper preview"
|
|
1135
1160
|
},
|
|
1136
1161
|
dependencies: {
|
|
1137
1162
|
basecampjs: "^0.0.8"
|
|
@@ -1142,7 +1167,7 @@ dist/
|
|
|
1142
1167
|
console.log(kolor.green("✅ Campsite initialized successfully!\n"));
|
|
1143
1168
|
console.log(kolor.bold("Next steps:"));
|
|
1144
1169
|
console.log(kolor.dim(" 1. Install dependencies: npm install"));
|
|
1145
|
-
console.log(kolor.dim(" 2. Start developing:
|
|
1170
|
+
console.log(kolor.dim(" 2. Start developing: camper dev\n"));
|
|
1146
1171
|
}
|
|
1147
1172
|
|
|
1148
1173
|
async function clean() {
|
|
@@ -1167,7 +1192,7 @@ async function check() {
|
|
|
1167
1192
|
const configPath = join(cwd, "campsite.config.js");
|
|
1168
1193
|
if (!existsSync(configPath)) {
|
|
1169
1194
|
console.log(kolor.red("❌ campsite.config.js not found"));
|
|
1170
|
-
console.log(kolor.dim(" Run '
|
|
1195
|
+
console.log(kolor.dim(" Run 'camper init' to initialize a project\n"));
|
|
1171
1196
|
hasIssues = true;
|
|
1172
1197
|
} else {
|
|
1173
1198
|
console.log(kolor.green("✅ campsite.config.js found"));
|
|
@@ -1300,7 +1325,7 @@ async function upgrade() {
|
|
|
1300
1325
|
} catch {}
|
|
1301
1326
|
|
|
1302
1327
|
console.log();
|
|
1303
|
-
console.log(kolor.dim("🌲 Tip: Run '
|
|
1328
|
+
console.log(kolor.dim("🌲 Tip: Run 'camper dev' to start developing with the latest version\n"));
|
|
1304
1329
|
resolve();
|
|
1305
1330
|
} else {
|
|
1306
1331
|
console.log();
|
|
@@ -1403,7 +1428,7 @@ async function list() {
|
|
|
1403
1428
|
}
|
|
1404
1429
|
}
|
|
1405
1430
|
|
|
1406
|
-
console.log(kolor.dim("🌲 Tip: Use '
|
|
1431
|
+
console.log(kolor.dim("🌲 Tip: Use 'camper make:<type> <name>' to create new content\n"));
|
|
1407
1432
|
}
|
|
1408
1433
|
|
|
1409
1434
|
async function preview() {
|
|
@@ -1436,7 +1461,7 @@ async function main() {
|
|
|
1436
1461
|
const type = command.substring(5); // Remove 'make:' prefix
|
|
1437
1462
|
if (!type) {
|
|
1438
1463
|
console.log(kolor.red("❌ No type specified"));
|
|
1439
|
-
console.log(kolor.dim("Run '
|
|
1464
|
+
console.log(kolor.dim("Run 'camper --help' for available make commands.\n"));
|
|
1440
1465
|
exit(1);
|
|
1441
1466
|
}
|
|
1442
1467
|
await makeContent(type);
|
|
@@ -1466,6 +1491,7 @@ async function main() {
|
|
|
1466
1491
|
await preview();
|
|
1467
1492
|
break;
|
|
1468
1493
|
case "clean":
|
|
1494
|
+
case "cleanup":
|
|
1469
1495
|
await clean();
|
|
1470
1496
|
break;
|
|
1471
1497
|
case "check":
|
|
@@ -1479,7 +1505,7 @@ async function main() {
|
|
|
1479
1505
|
break;
|
|
1480
1506
|
default:
|
|
1481
1507
|
console.log(kolor.yellow(`Unknown command: ${command}`));
|
|
1482
|
-
console.log(kolor.dim("Run '
|
|
1508
|
+
console.log(kolor.dim("Run 'camper --help' for usage information."));
|
|
1483
1509
|
exit(1);
|
|
1484
1510
|
}
|
|
1485
1511
|
}
|
package/package.json
CHANGED