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 +24 -2
- package/package.json +1 -1
- package/template/app/globals.css +66 -31
- package/template/lib/mdx.ts +14 -2
- package/template/next.config.ts +3 -1
- package/template/scripts/build-search-index.ts +3 -1
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
|
|
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
package/template/app/globals.css
CHANGED
|
@@ -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: #
|
|
39
|
+
--cm-note-bg: #EDF8FA;
|
|
40
40
|
--cm-note-border: #4BA8B7;
|
|
41
|
-
--cm-
|
|
42
|
-
--cm-tip-
|
|
43
|
-
--cm-
|
|
44
|
-
--cm-
|
|
45
|
-
--cm-
|
|
46
|
-
--cm-
|
|
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:
|
|
84
|
-
border: 1.5px solid
|
|
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:
|
|
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:
|
|
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-
|
|
113
|
-
.callout.important .callout-header { background-color: var(--cm-
|
|
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-
|
|
119
|
-
.callout.success .callout-header { background-color: var(--cm-
|
|
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:
|
|
322
|
-
border-color:
|
|
356
|
+
background-color: var(--cm-bg-secondary);
|
|
357
|
+
border-color: var(--cm-border);
|
|
323
358
|
}
|
|
324
359
|
|
|
325
360
|
.dark .callout-header {
|
|
326
|
-
color:
|
|
361
|
+
color: var(--cm-text-primary);
|
|
327
362
|
}
|
|
328
363
|
|
|
329
364
|
.dark .callout-body {
|
|
330
|
-
color:
|
|
365
|
+
color: var(--cm-text-secondary);
|
|
331
366
|
}
|
|
332
367
|
|
|
333
|
-
.dark .callout.note { border-color:
|
|
334
|
-
.dark .callout.note .callout-header { background-color:
|
|
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:
|
|
337
|
-
.dark .callout.tip .callout-header { background-color:
|
|
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:
|
|
340
|
-
.dark .callout.warning .callout-header { background-color:
|
|
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:
|
|
343
|
-
.dark .callout.important .callout-header { background-color:
|
|
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:
|
|
346
|
-
.dark .callout.danger .callout-header { background-color:
|
|
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:
|
|
349
|
-
.dark .callout.success .callout-header { background-color:
|
|
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 {
|
package/template/lib/mdx.ts
CHANGED
|
@@ -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
|
package/template/next.config.ts
CHANGED
|
@@ -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
|
-
|
|
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,
|