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.
Files changed (2) hide show
  1. package/index.js +61 -35
  2. 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(" campsite <command> [arguments] [options]\n");
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(" campsite init\n");
113
+ console.log(" camper init\n");
114
114
  console.log(" " + kolor.dim("# Start development"));
115
- console.log(" campsite dev\n");
115
+ console.log(" camper dev\n");
116
116
  console.log(" " + kolor.dim("# Create new content"));
117
- console.log(" campsite make:page about");
118
- console.log(" campsite make:post \"My First Post\"");
119
- console.log(" campsite make:collection products\n");
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(" campsite preview\n");
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: campsite make:${type} <name> [name2, name3, ...]`));
817
+ console.log(kolor.dim(`Usage: camper make:${type} <name> [name2, name3, ...]`));
793
818
  console.log(kolor.dim("\nExamples:"));
794
- console.log(kolor.dim(" campsite make:page about"));
795
- console.log(kolor.dim(" campsite make:page home, about, contact"));
796
- console.log(kolor.dim(" campsite make:collection products, categories\n"));
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
- // campsite make:page home about contact
802
- // campsite make:page home, about, contact
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 'campsite dev' to start developing.\n"));
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 \`campsite dev\` to start developing
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: "campsite dev",
1132
- build: "campsite build",
1133
- serve: "campsite serve",
1134
- preview: "campsite 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: campsite dev\n"));
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 'campsite init' to initialize a project\n"));
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 'campsite dev' to start developing with the latest version\n"));
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 'campsite make:<type> <name>' to create new content\n"));
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 'campsite --help' for available make commands.\n"));
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 'campsite --help' for usage information."));
1508
+ console.log(kolor.dim("Run 'camper --help' for usage information."));
1483
1509
  exit(1);
1484
1510
  }
1485
1511
  }
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "basecampjs",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "type": "module",
5
5
  "description": "BasecampJS engine for CampsiteJS static site generator.",
6
6
  "bin": {
7
+ "camper": "./index.js",
7
8
  "campsite": "./index.js"
8
9
  },
9
10
  "license": "MIT",