camelmind 0.2.3 → 0.2.5

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 CHANGED
@@ -153,6 +153,7 @@ var FRAMEWORK_FILES = [
153
153
  "eslint.config.mjs",
154
154
  "proxy.ts"
155
155
  ];
156
+ var DEFAULT_IGNORED_FILES = ["app/home/page.tsx"];
156
157
  async function walkFiles(dir) {
157
158
  if (!await fs2.pathExists(dir)) return [];
158
159
  const entries = await fs2.readdir(dir, { withFileTypes: true });
@@ -224,6 +225,19 @@ async function plannedTemplateFiles() {
224
225
  files.push(...FRAMEWORK_FILES);
225
226
  return files.sort();
226
227
  }
228
+ function normalizeUpdatePath(file) {
229
+ return file.replace(/\\/g, "/").replace(/^\.?\//, "");
230
+ }
231
+ function ignoredFilesFor(options) {
232
+ const ignored = /* @__PURE__ */ new Set();
233
+ if (!options.overwriteHome) {
234
+ for (const file of DEFAULT_IGNORED_FILES) ignored.add(file);
235
+ }
236
+ for (const file of options.ignoreFile ?? []) {
237
+ ignored.add(normalizeUpdatePath(file));
238
+ }
239
+ return ignored;
240
+ }
227
241
  async function update(targetDir, options) {
228
242
  const projectRoot = path2.resolve(process.cwd(), targetDir ?? ".");
229
243
  const packageJsonPath = path2.join(projectRoot, "package.json");
@@ -236,7 +250,10 @@ async function update(targetDir, options) {
236
250
  console.error(chalk2.red("Run this command from a CamelMind project root, or pass the project directory."));
237
251
  process.exit(1);
238
252
  }
239
- const files = await plannedTemplateFiles();
253
+ const ignoredFiles = ignoredFilesFor(options);
254
+ const allFiles = await plannedTemplateFiles();
255
+ const files = allFiles.filter((file) => !ignoredFiles.has(file));
256
+ const skippedFiles = allFiles.filter((file) => ignoredFiles.has(file));
240
257
  const backupRoot = path2.join(
241
258
  projectRoot,
242
259
  ".camelmind-update-backup",
@@ -247,12 +264,17 @@ async function update(targetDir, options) {
247
264
 
248
265
  Project: ${chalk2.cyan(projectRoot)}
249
266
  Files: ${chalk2.cyan(String(files.length))} framework files + package.json
267
+ Skipped: ${chalk2.cyan(String(skippedFiles.length))} preserved files
250
268
  Backup: ${chalk2.cyan(path2.relative(projectRoot, backupRoot))}
251
269
  `);
252
270
  if (options.dryRun) {
253
271
  console.log(chalk2.bold(" Dry run \u2014 files that would be refreshed:\n"));
254
272
  for (const file of files) console.log(` ${file}`);
255
273
  console.log(" package.json");
274
+ if (skippedFiles.length) {
275
+ console.log(chalk2.bold("\n Preserved files:\n"));
276
+ for (const file of skippedFiles) console.log(` ${file}`);
277
+ }
256
278
  console.log("");
257
279
  return;
258
280
  }
@@ -359,5 +381,5 @@ var program = new Command();
359
381
  program.name("camelmind").description("CamelMind CLI \u2014 scaffold and manage documentation sites").version(pkg.version);
360
382
  program.command("init [project-name]").description("Create a new CamelMind documentation site").option("--no-install", "Skip installing npm dependencies").action(init);
361
383
  program.command("version").description("Show installed version and check for updates").action(() => checkVersion(pkg.version));
362
- program.command("update [project-dir]").description("Update an existing CamelMind site to the latest platform files").option("--no-install", "Skip installing npm dependencies").option("--dry-run", "Show what would change without writing files").option("-y, --yes", "Skip the confirmation prompt").action(update);
384
+ program.command("update [project-dir]").description("Update an existing CamelMind site to the latest platform files").option("--no-install", "Skip installing npm dependencies").option("--dry-run", "Show what would change without writing files").option("--ignore-file <path...>", "Preserve additional project files during update").option("--overwrite-home", "Overwrite app/home/page.tsx with the latest template").option("-y, --yes", "Skip the confirmation prompt").action(update);
363
385
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camelmind",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Create and manage CamelMind documentation sites",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -36,14 +36,24 @@
36
36
  --cm-btn-primary-bg: var(--cm-oasis-teal);
37
37
  --cm-btn-primary-text: #FFFFFF;
38
38
 
39
- --cm-note-bg: #EAF7FA;
39
+ --cm-note-bg: #EDF8FA;
40
40
  --cm-note-border: #4BA8B7;
41
- --cm-tip-bg: #EEF7EC;
42
- --cm-tip-border: #5B9B62;
43
- --cm-warning-bg: #FFF6E2;
44
- --cm-warning-border: #D9A441;
45
- --cm-danger-bg: #FFF0EC;
46
- --cm-danger-border: #C76B56;
41
+ --cm-note-icon: #2E8391;
42
+ --cm-tip-bg: #F1F6EC;
43
+ --cm-tip-border: #7D9850;
44
+ --cm-tip-icon: #6A8741;
45
+ --cm-warning-bg: #FFF7E6;
46
+ --cm-warning-border: #D8A15B;
47
+ --cm-warning-icon: #B67D32;
48
+ --cm-important-bg: #F1EEF8;
49
+ --cm-important-border: #6B5B95;
50
+ --cm-important-icon: #56467C;
51
+ --cm-danger-bg: #FFF1ED;
52
+ --cm-danger-border: #BF6651;
53
+ --cm-danger-icon: #A54D39;
54
+ --cm-success-bg: #ECF7EF;
55
+ --cm-success-border: #5B9B62;
56
+ --cm-success-icon: #4D8453;
47
57
 
48
58
  --cm-radius-md: 10px;
49
59
  --cm-font-heading: var(--font-alegreya), Georgia, serif;
@@ -66,6 +76,25 @@
66
76
  --cm-link-hover: #7AD2DE;
67
77
  --cm-active: #63C1CF;
68
78
  --cm-active-border: #63C1CF;
79
+
80
+ --cm-note-bg: #1F3E49;
81
+ --cm-note-border: #63C1CF;
82
+ --cm-note-icon: #8BDDE8;
83
+ --cm-tip-bg: #344329;
84
+ --cm-tip-border: #A7BC72;
85
+ --cm-tip-icon: #B8CC84;
86
+ --cm-warning-bg: #4A3518;
87
+ --cm-warning-border: #E8B34E;
88
+ --cm-warning-icon: #F0C46F;
89
+ --cm-important-bg: #48351F;
90
+ --cm-important-border: #D8A15B;
91
+ --cm-important-icon: #E3BA7A;
92
+ --cm-danger-bg: #4A241F;
93
+ --cm-danger-border: #D9826C;
94
+ --cm-danger-icon: #E99B87;
95
+ --cm-success-bg: #24402C;
96
+ --cm-success-border: #73B97B;
97
+ --cm-success-icon: #8ACD91;
69
98
  }
70
99
 
71
100
  .cm-primary-button {
@@ -80,8 +109,8 @@
80
109
  margin-bottom: 1.25rem;
81
110
  border-radius: 8px;
82
111
  font-size: 1rem;
83
- background-color: #fdfdfd;
84
- border: 1.5px solid #bbbbbb;
112
+ background-color: var(--cm-bg-secondary);
113
+ border: 1.5px solid var(--cm-border);
85
114
  overflow: hidden;
86
115
  }
87
116
 
@@ -91,32 +120,38 @@
91
120
  font-size: 0.85rem;
92
121
  padding: 0.4rem 0.75rem;
93
122
  letter-spacing: 0.04em;
94
- color: #1f1f1f;
123
+ color: var(--cm-text-primary);
95
124
  }
96
125
 
97
126
  .callout-body {
98
127
  padding: 0.5rem 0.75rem 0.75rem;
99
128
  font-size: 0.95rem;
100
- color: #333;
129
+ color: var(--cm-text-primary);
101
130
  }
102
131
 
103
132
  .callout.note { border-color: var(--cm-note-border); }
104
133
  .callout.note .callout-header { background-color: var(--cm-note-bg); color: var(--cm-text-primary); }
134
+ .callout.note .callout-header svg { color: var(--cm-note-icon); }
105
135
 
106
136
  .callout.tip { border-color: var(--cm-tip-border); }
107
137
  .callout.tip .callout-header { background-color: var(--cm-tip-bg); color: var(--cm-text-primary); }
138
+ .callout.tip .callout-header svg { color: var(--cm-tip-icon); }
108
139
 
109
140
  .callout.warning { border-color: var(--cm-warning-border); }
110
141
  .callout.warning .callout-header { background-color: var(--cm-warning-bg); color: var(--cm-text-primary); }
142
+ .callout.warning .callout-header svg { color: var(--cm-warning-icon); }
111
143
 
112
- .callout.important { border-color: var(--cm-oasis-teal); }
113
- .callout.important .callout-header { background-color: var(--cm-note-bg); color: var(--cm-text-primary); }
144
+ .callout.important { border-color: var(--cm-important-border); }
145
+ .callout.important .callout-header { background-color: var(--cm-important-bg); color: var(--cm-text-primary); }
146
+ .callout.important .callout-header svg { color: var(--cm-important-icon); }
114
147
 
115
148
  .callout.danger { border-color: var(--cm-danger-border); }
116
149
  .callout.danger .callout-header { background-color: var(--cm-danger-bg); color: var(--cm-text-primary); }
150
+ .callout.danger .callout-header svg { color: var(--cm-danger-icon); }
117
151
 
118
- .callout.success { border-color: var(--cm-tip-border); }
119
- .callout.success .callout-header { background-color: var(--cm-tip-bg); color: var(--cm-text-primary); }
152
+ .callout.success { border-color: var(--cm-success-border); }
153
+ .callout.success .callout-header { background-color: var(--cm-success-bg); color: var(--cm-text-primary); }
154
+ .callout.success .callout-header svg { color: var(--cm-success-icon); }
120
155
 
121
156
  body {
122
157
  font-family: var(--cm-font-body);
@@ -318,35 +353,35 @@ body {
318
353
  /* ── Dark mode overrides ── */
319
354
 
320
355
  .dark .callout {
321
- background-color: #1e2027;
322
- border-color: #374151;
356
+ background-color: var(--cm-bg-secondary);
357
+ border-color: var(--cm-border);
323
358
  }
324
359
 
325
360
  .dark .callout-header {
326
- color: #f3f4f6;
361
+ color: var(--cm-text-primary);
327
362
  }
328
363
 
329
364
  .dark .callout-body {
330
- color: #d1d5db;
365
+ color: var(--cm-text-secondary);
331
366
  }
332
367
 
333
- .dark .callout.note { border-color: #3b5ea6; }
334
- .dark .callout.note .callout-header { background-color: #1e3a5f; }
368
+ .dark .callout.note { border-color: var(--cm-note-border); }
369
+ .dark .callout.note .callout-header { background-color: var(--cm-note-bg); }
335
370
 
336
- .dark .callout.tip { border-color: #3b4ea6; }
337
- .dark .callout.tip .callout-header { background-color: #1e2f6b; }
371
+ .dark .callout.tip { border-color: var(--cm-tip-border); }
372
+ .dark .callout.tip .callout-header { background-color: var(--cm-tip-bg); }
338
373
 
339
- .dark .callout.warning { border-color: #7c5a2a; }
340
- .dark .callout.warning .callout-header { background-color: #4a3010; }
374
+ .dark .callout.warning { border-color: var(--cm-warning-border); }
375
+ .dark .callout.warning .callout-header { background-color: var(--cm-warning-bg); }
341
376
 
342
- .dark .callout.important { border-color: #1a7a70; }
343
- .dark .callout.important .callout-header { background-color: #0d3d39; }
377
+ .dark .callout.important { border-color: var(--cm-important-border); }
378
+ .dark .callout.important .callout-header { background-color: var(--cm-important-bg); }
344
379
 
345
- .dark .callout.danger { border-color: #7c2a2a; }
346
- .dark .callout.danger .callout-header { background-color: #4a1010; }
380
+ .dark .callout.danger { border-color: var(--cm-danger-border); }
381
+ .dark .callout.danger .callout-header { background-color: var(--cm-danger-bg); }
347
382
 
348
- .dark .callout.success { border-color: #2a6b2a; }
349
- .dark .callout.success .callout-header { background-color: #103a10; }
383
+ .dark .callout.success { border-color: var(--cm-success-border); }
384
+ .dark .callout.success .callout-header { background-color: var(--cm-success-bg); }
350
385
 
351
386
  /* Dark prose — tables, code, headings */
352
387
  .dark .prose {
@@ -2,6 +2,18 @@ import fs from "fs"
2
2
  import path from "path"
3
3
  import { execSync } from "child_process"
4
4
  import matter from "gray-matter"
5
+ import yaml from "js-yaml"
6
+
7
+ // gray-matter's bundled YAML engine calls the js-yaml v3 API (safeLoad/safeDump),
8
+ // which js-yaml v4 removed — pass the current API explicitly.
9
+ const matterOptions = {
10
+ engines: {
11
+ yaml: {
12
+ parse: (s: string) => yaml.load(s) as object,
13
+ stringify: (o: object) => yaml.dump(o),
14
+ },
15
+ },
16
+ }
5
17
 
6
18
  export type FrontMatter = {
7
19
  title: string
@@ -53,14 +65,14 @@ export function processForLLM(source: string): string {
53
65
  export function loadFrontmatterOnly(filePath: string): FrontMatter {
54
66
  const fullPath = path.join(process.cwd(), filePath)
55
67
  const raw = fs.readFileSync(fullPath, "utf-8")
56
- const { data } = matter(raw)
68
+ const { data } = matter(raw, matterOptions)
57
69
  return data as FrontMatter
58
70
  }
59
71
 
60
72
  export function loadMdxFile(filePath: string): DocContent {
61
73
  const fullPath = path.join(process.cwd(), filePath)
62
74
  const raw = fs.readFileSync(fullPath, "utf-8")
63
- const { data, content } = matter(raw)
75
+ const { data, content } = matter(raw, matterOptions)
64
76
  const frontmatter = data as FrontMatter
65
77
 
66
78
  let lastUpdated: Date | null = null
@@ -1,6 +1,7 @@
1
1
  import type { NextConfig } from "next";
2
2
 
3
3
  const isOffline = process.env.OFFLINE_MODE === "true"
4
+ const isDev = process.env.NODE_ENV === "development"
4
5
 
5
6
  const securityHeaders = [
6
7
  { key: "X-Frame-Options", value: "DENY" },
@@ -11,7 +12,8 @@ const securityHeaders = [
11
12
  key: "Content-Security-Policy",
12
13
  value: [
13
14
  "default-src 'self'",
14
- "script-src 'self' 'unsafe-inline'",
15
+ // React dev mode (Fast Refresh, component stacks) needs eval()
16
+ `script-src 'self' 'unsafe-inline'${isDev ? " 'unsafe-eval'" : ""}`,
15
17
  "style-src 'self' 'unsafe-inline'",
16
18
  "img-src 'self' data:",
17
19
  "font-src 'self'",
@@ -76,7 +76,9 @@ async function main() {
76
76
  for (const entry of entries) {
77
77
  const filePath = path.join(ROOT, entry.file)
78
78
  if (!fs.existsSync(filePath)) continue
79
- const { data: frontmatter, content } = matter(fs.readFileSync(filePath, "utf-8"))
79
+ const { data: frontmatter, content } = matter(fs.readFileSync(filePath, "utf-8"), {
80
+ engines: { yaml: { parse: (s: string) => yaml.load(s) as object, stringify: (o: object) => yaml.dump(o) } },
81
+ })
80
82
 
81
83
  index.push({
82
84
  slug: entry.slug,