create-contentisland 0.0.2 → 0.0.4
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 +226 -221
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { cac as ae } from "cac";
|
|
2
|
-
import
|
|
2
|
+
import b from "prompts";
|
|
3
3
|
import { existsSync as w } from "node:fs";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import g from "node:fs/promises";
|
|
5
|
+
import d from "node:path";
|
|
6
6
|
import { createClient as oe } from "@content-island/api-client";
|
|
7
|
-
const
|
|
7
|
+
const E = ".content-island", G = "config.json", N = ".gitignore", M = {
|
|
8
8
|
aa: "Afaraf",
|
|
9
9
|
ab: "Аҧсуа",
|
|
10
10
|
ae: "Avesta",
|
|
@@ -189,7 +189,7 @@ const x = ".content-island", G = "config.json", N = ".gitignore", M = {
|
|
|
189
189
|
za: "Zhuang",
|
|
190
190
|
zh: "中文",
|
|
191
191
|
zu: "isiZulu"
|
|
192
|
-
},
|
|
192
|
+
}, m = {
|
|
193
193
|
reset: "\x1B[0m",
|
|
194
194
|
green: "\x1B[32m",
|
|
195
195
|
red: "\x1B[31m",
|
|
@@ -198,15 +198,15 @@ const x = ".content-island", G = "config.json", N = ".gitignore", M = {
|
|
|
198
198
|
cyan: "\x1B[36m",
|
|
199
199
|
magenta: "\x1B[35m"
|
|
200
200
|
}, C = (e) => {
|
|
201
|
-
let
|
|
202
|
-
return e?.bold && (
|
|
201
|
+
let t = "";
|
|
202
|
+
return e?.bold && (t += m.bold), t;
|
|
203
203
|
}, c = {
|
|
204
|
-
green: (e,
|
|
205
|
-
red: (e,
|
|
206
|
-
yellow: (e,
|
|
207
|
-
bold: (e) => `${
|
|
208
|
-
cyan: (e,
|
|
209
|
-
magenta: (e,
|
|
204
|
+
green: (e, t) => `${m.green}${C(t)}${e}${m.reset}`,
|
|
205
|
+
red: (e, t) => `${m.red}${C(t)}${e}${m.reset}`,
|
|
206
|
+
yellow: (e, t) => `${m.yellow}${C(t)}${e}${m.reset}`,
|
|
207
|
+
bold: (e) => `${m.bold}${e}${m.reset}`,
|
|
208
|
+
cyan: (e, t) => `${m.cyan}${C(t)}${e}${m.reset}`,
|
|
209
|
+
magenta: (e, t) => `${m.magenta}${C(t)}${e}${m.reset}`
|
|
210
210
|
}, o = {
|
|
211
211
|
info: (e) => console.log(c.cyan("ℹ️ " + e)),
|
|
212
212
|
success: (e) => console.log(c.green("✅ " + e)),
|
|
@@ -230,60 +230,60 @@ const x = ".content-island", G = "config.json", N = ".gitignore", M = {
|
|
|
230
230
|
fetching: (e) => console.log(c.cyan("📥 " + e)),
|
|
231
231
|
clearing: (e) => console.log(c.yellow("🧹 " + e)),
|
|
232
232
|
updating: (e) => console.log(c.green("🔄 " + e))
|
|
233
|
-
}, A = () =>
|
|
234
|
-
const e = process.cwd(),
|
|
233
|
+
}, A = () => d.join(process.cwd(), E), se = async () => {
|
|
234
|
+
const e = process.cwd(), t = d.join(e, N), n = `${E}/`;
|
|
235
235
|
let a = "";
|
|
236
|
-
w(
|
|
236
|
+
w(t) && (a = await g.readFile(t, "utf-8"), a.includes(n)) || (a = a + `${a.endsWith(`
|
|
237
237
|
`) ? "" : `
|
|
238
|
-
`}${
|
|
239
|
-
`, await
|
|
238
|
+
`}${n}
|
|
239
|
+
`, await g.writeFile(t, a, "utf-8"), o.saved(`Added ${n} to ${N}`));
|
|
240
240
|
}, K = async () => {
|
|
241
241
|
const e = A();
|
|
242
242
|
try {
|
|
243
|
-
w(e) || (await
|
|
244
|
-
} catch (
|
|
245
|
-
o.error(`Failed to create config directory: ${
|
|
243
|
+
w(e) || (await g.mkdir(e, { recursive: !0 }), o.created(`Created: ${E}/`)), await se();
|
|
244
|
+
} catch (t) {
|
|
245
|
+
o.error(`Failed to create config directory: ${t.message}`);
|
|
246
246
|
}
|
|
247
|
-
}, J = async () => (await K(),
|
|
247
|
+
}, J = async () => (await K(), d.join(A(), G)), j = async () => {
|
|
248
248
|
const e = await J();
|
|
249
249
|
if (!w(e))
|
|
250
250
|
return null;
|
|
251
251
|
try {
|
|
252
|
-
const
|
|
253
|
-
return JSON.parse(
|
|
254
|
-
} catch (
|
|
255
|
-
return o.warning(`Could not parse ${G}: ${
|
|
252
|
+
const t = await g.readFile(e, "utf-8");
|
|
253
|
+
return JSON.parse(t);
|
|
254
|
+
} catch (t) {
|
|
255
|
+
return o.warning(`Could not parse ${G}: ${t.message}`), null;
|
|
256
256
|
}
|
|
257
|
-
},
|
|
258
|
-
let
|
|
257
|
+
}, S = async (e) => {
|
|
258
|
+
let t = {
|
|
259
259
|
...e
|
|
260
260
|
};
|
|
261
|
-
const
|
|
262
|
-
if (w(
|
|
261
|
+
const n = await J();
|
|
262
|
+
if (w(n)) {
|
|
263
263
|
const a = await j();
|
|
264
|
-
a && (
|
|
264
|
+
a && (t = { ...a, ...e });
|
|
265
265
|
}
|
|
266
266
|
try {
|
|
267
|
-
const a = JSON.stringify(
|
|
268
|
-
await
|
|
267
|
+
const a = JSON.stringify(t, null, 2);
|
|
268
|
+
await g.writeFile(n, a, "utf-8"), o.saved(`Saved configuration to ${n}`);
|
|
269
269
|
} catch (a) {
|
|
270
270
|
o.error(`Failed to save configuration: ${a.message}`);
|
|
271
271
|
}
|
|
272
|
-
}, ie = (e,
|
|
273
|
-
let s = 0, i =
|
|
274
|
-
const y = ['"', "'", "`"].includes(
|
|
275
|
-
for (let p =
|
|
276
|
-
const
|
|
277
|
-
if (
|
|
278
|
-
|
|
272
|
+
}, ie = (e, t, n, a) => {
|
|
273
|
+
let s = 0, i = t, r = !1, u = "", l = !1;
|
|
274
|
+
const y = ['"', "'", "`"].includes(n);
|
|
275
|
+
for (let p = t; p < e.length; p++) {
|
|
276
|
+
const f = e[p];
|
|
277
|
+
if (l) {
|
|
278
|
+
l = !1;
|
|
279
279
|
continue;
|
|
280
280
|
}
|
|
281
|
-
if (
|
|
282
|
-
|
|
281
|
+
if (f === "\\" && r) {
|
|
282
|
+
l = !0;
|
|
283
283
|
continue;
|
|
284
284
|
}
|
|
285
285
|
if (y) {
|
|
286
|
-
if (
|
|
286
|
+
if (f === n && !r) {
|
|
287
287
|
if (s++, s === 1)
|
|
288
288
|
continue;
|
|
289
289
|
if (s === 2) {
|
|
@@ -291,51 +291,51 @@ const x = ".content-island", G = "config.json", N = ".gitignore", M = {
|
|
|
291
291
|
break;
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
|
-
} else if (!r && (
|
|
295
|
-
r = !0,
|
|
296
|
-
else if (r &&
|
|
294
|
+
} else if (!r && (f === '"' || f === "'" || f === "`"))
|
|
295
|
+
r = !0, u = f;
|
|
296
|
+
else if (r && f === u)
|
|
297
297
|
r = !1;
|
|
298
298
|
else if (!r) {
|
|
299
|
-
if (
|
|
299
|
+
if (f === n)
|
|
300
300
|
s++;
|
|
301
|
-
else if (
|
|
301
|
+
else if (f === a && (s--, s === 0)) {
|
|
302
302
|
i = p + 1;
|
|
303
303
|
break;
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
307
|
return i;
|
|
308
|
-
},
|
|
309
|
-
const { filePath:
|
|
308
|
+
}, x = async (e) => {
|
|
309
|
+
const { filePath: t, property: n, startSymbol: a, endSymbol: s } = e, i = await g.readFile(t, "utf-8");
|
|
310
310
|
let r = a;
|
|
311
311
|
a === "[" && (r = "\\["), a === "{" && (r = "\\{"), a === "(" && (r = "\\(");
|
|
312
|
-
const
|
|
313
|
-
if (!
|
|
312
|
+
const u = new RegExp(`${n}\\s*:\\s*(${r})`), l = i.match(u);
|
|
313
|
+
if (!l)
|
|
314
314
|
return null;
|
|
315
|
-
const y = i.indexOf(
|
|
315
|
+
const y = i.indexOf(l[0]) + l[0].length - 1, p = ie(i, y, a, s);
|
|
316
316
|
return i.substring(y, p);
|
|
317
317
|
}, re = (e) => JSON.parse(
|
|
318
318
|
e.replace(/'/g, '"').replace(/(\w+):/g, '"$1":').replace(/,\s*}/g, "}").replace(/,\s*]/g, "]")
|
|
319
|
-
), q = (e) => e.replace(/"/g, "'").replace(/'(\w+)':/g, "$1:"), ce = async (e,
|
|
320
|
-
let s = await
|
|
321
|
-
if (s || (s = await
|
|
319
|
+
), q = (e) => e.replace(/"/g, "'").replace(/'(\w+)':/g, "$1:"), ce = async (e, t, n, a) => {
|
|
320
|
+
let s = await x(n);
|
|
321
|
+
if (s || (s = await x(a)), !s)
|
|
322
322
|
throw new Error(
|
|
323
|
-
`Could not find property '${
|
|
323
|
+
`Could not find property '${n.property}' or fallback property '${a.property}' in file ${n.filePath}`
|
|
324
324
|
);
|
|
325
|
-
const i = q(JSON.stringify(
|
|
326
|
-
return (await
|
|
325
|
+
const i = q(JSON.stringify(t, null, 2));
|
|
326
|
+
return (await g.readFile(n.filePath, "utf-8")).replace(s, (u) => `${u},
|
|
327
327
|
${e}: ${i}`);
|
|
328
|
-
}, T = (e,
|
|
328
|
+
}, T = (e, t) => Array.isArray(e) ? e.map(t) : [], le = (e, t) => ({
|
|
329
329
|
id: e.id,
|
|
330
330
|
language: e.language,
|
|
331
331
|
name: e.name,
|
|
332
332
|
label: e.label,
|
|
333
|
-
pages: T(e.pages, (
|
|
334
|
-
}), ge = (e,
|
|
333
|
+
pages: T(e.pages, (n) => t.find((a) => a.id === n))
|
|
334
|
+
}), ge = (e, t) => ({
|
|
335
335
|
id: e.id,
|
|
336
336
|
language: e.language,
|
|
337
337
|
index: e.index,
|
|
338
|
-
folders: T(e.folders, (
|
|
338
|
+
folders: T(e.folders, (n) => le(n, t))
|
|
339
339
|
});
|
|
340
340
|
let v = null;
|
|
341
341
|
const de = (e) => {
|
|
@@ -345,14 +345,14 @@ const de = (e) => {
|
|
|
345
345
|
throw new Error("API client not initialized. Call initializeClient first.");
|
|
346
346
|
return v;
|
|
347
347
|
}, ue = async () => await F().getProject(), O = async (e) => {
|
|
348
|
-
const
|
|
348
|
+
const t = F(), n = await t.getContent({
|
|
349
349
|
contentType: "Root",
|
|
350
350
|
includeRelatedContent: !0,
|
|
351
351
|
language: e
|
|
352
352
|
});
|
|
353
|
-
if (!
|
|
353
|
+
if (!n)
|
|
354
354
|
throw new Error(`Root content not found for language: ${e}`);
|
|
355
|
-
const a =
|
|
355
|
+
const a = n.folders?.flatMap((i) => i.pages) || [], s = await t.getContentList({
|
|
356
356
|
contentType: "Page",
|
|
357
357
|
id: {
|
|
358
358
|
in: a
|
|
@@ -361,84 +361,89 @@ const de = (e) => {
|
|
|
361
361
|
});
|
|
362
362
|
if (!s)
|
|
363
363
|
throw new Error(`Pages not found for IDs: ${a.join(", ")}`);
|
|
364
|
-
return ge(
|
|
364
|
+
return ge(n, s);
|
|
365
365
|
}, fe = async () => {
|
|
366
366
|
try {
|
|
367
367
|
return await F().getContent({
|
|
368
368
|
contentType: "Meta"
|
|
369
369
|
});
|
|
370
|
-
} catch {
|
|
371
|
-
|
|
370
|
+
} catch (e) {
|
|
371
|
+
e.message.includes("401") ? o.error(
|
|
372
|
+
"The Content Island API token is missing or malformed. Verify that you've copied the complete token and that you have sufficient permissions."
|
|
373
|
+
) : o.error("The requested template is not of type StarLight, so the meta field could not be found."), process.exit(1);
|
|
372
374
|
}
|
|
373
|
-
}, U = "astro.config.mjs", P = () =>
|
|
374
|
-
const e = [],
|
|
375
|
-
w(
|
|
376
|
-
const
|
|
377
|
-
return w(
|
|
375
|
+
}, U = "astro.config.mjs", P = () => d.join(process.cwd(), "src", "content", "docs"), L = () => d.join(process.cwd(), U), me = () => {
|
|
376
|
+
const e = [], t = L();
|
|
377
|
+
w(t) || e.push(U);
|
|
378
|
+
const n = P();
|
|
379
|
+
return w(n) || e.push("src/content/docs directory"), {
|
|
378
380
|
valid: e.length === 0,
|
|
379
381
|
missingItems: e
|
|
380
382
|
};
|
|
381
383
|
}, pe = async () => {
|
|
382
384
|
const e = P();
|
|
383
385
|
if (!w(e)) {
|
|
384
|
-
o.info("Content docs directory not found, creating it..."), await
|
|
386
|
+
o.info("Content docs directory not found, creating it..."), await g.mkdir(e, { recursive: !0 });
|
|
385
387
|
return;
|
|
386
388
|
}
|
|
387
|
-
const
|
|
388
|
-
for (const
|
|
389
|
-
const a =
|
|
390
|
-
await
|
|
389
|
+
const t = await g.readdir(e);
|
|
390
|
+
for (const n of t) {
|
|
391
|
+
const a = d.join(e, n);
|
|
392
|
+
await g.rm(a, { recursive: !0, force: !0 });
|
|
391
393
|
}
|
|
392
394
|
}, h = {
|
|
393
395
|
sidebar: { start: "[", end: "]" },
|
|
394
396
|
locales: { start: "{", end: "}" },
|
|
395
397
|
title: { start: "'", end: "'" }
|
|
396
|
-
}, W = (e,
|
|
397
|
-
const
|
|
398
|
-
for (const
|
|
399
|
-
const
|
|
400
|
-
if (
|
|
401
|
-
const
|
|
402
|
-
|
|
403
|
-
...e[
|
|
404
|
-
...
|
|
405
|
-
items:
|
|
398
|
+
}, W = (e, t) => {
|
|
399
|
+
const n = [], a = [];
|
|
400
|
+
for (const s of t) {
|
|
401
|
+
const i = e.findIndex((r) => r.label === s.label);
|
|
402
|
+
if (i >= 0) {
|
|
403
|
+
const r = s.items && e[i].items ? W(e[i].items || [], s.items) : s.items;
|
|
404
|
+
n[i] = {
|
|
405
|
+
...e[i],
|
|
406
|
+
...s,
|
|
407
|
+
items: r
|
|
406
408
|
};
|
|
407
409
|
} else
|
|
408
|
-
|
|
410
|
+
a.push(s);
|
|
409
411
|
}
|
|
410
|
-
return
|
|
411
|
-
|
|
412
|
-
|
|
412
|
+
return n.push(...a), n.sort((s, i) => {
|
|
413
|
+
const r = t.findIndex((l) => l.label === s.label), u = t.findIndex((l) => l.label === i.label);
|
|
414
|
+
return r - u;
|
|
415
|
+
});
|
|
416
|
+
}, we = (e, t) => {
|
|
417
|
+
const n = {
|
|
413
418
|
root: { lang: e, label: M[e] }
|
|
414
419
|
};
|
|
415
|
-
return Array.isArray(
|
|
420
|
+
return Array.isArray(t) ? t.reduce(
|
|
416
421
|
(a, s) => ({
|
|
417
422
|
...a,
|
|
418
423
|
[s]: { lang: s, label: M[s] }
|
|
419
424
|
}),
|
|
420
|
-
|
|
421
|
-
) :
|
|
422
|
-
}, D = async (e,
|
|
423
|
-
const a = L(), s = await
|
|
425
|
+
n
|
|
426
|
+
) : n;
|
|
427
|
+
}, D = async (e, t, n) => {
|
|
428
|
+
const a = L(), s = await x({
|
|
424
429
|
filePath: a,
|
|
425
|
-
property:
|
|
426
|
-
startSymbol: h[
|
|
427
|
-
endSymbol: h[
|
|
430
|
+
property: t,
|
|
431
|
+
startSymbol: h[t]?.start,
|
|
432
|
+
endSymbol: h[t]?.end
|
|
428
433
|
});
|
|
429
434
|
let i;
|
|
430
435
|
if (s) {
|
|
431
436
|
const r = q(JSON.stringify(e, null, 2));
|
|
432
|
-
i = (await
|
|
437
|
+
i = (await g.readFile(a, "utf-8")).replace(s, r);
|
|
433
438
|
} else
|
|
434
439
|
i = await ce(
|
|
435
|
-
|
|
440
|
+
t,
|
|
436
441
|
e,
|
|
437
442
|
{
|
|
438
443
|
filePath: a,
|
|
439
|
-
property:
|
|
440
|
-
startSymbol: h[
|
|
441
|
-
endSymbol: h[
|
|
444
|
+
property: n,
|
|
445
|
+
startSymbol: h[n]?.start,
|
|
446
|
+
endSymbol: h[n]?.end
|
|
442
447
|
},
|
|
443
448
|
{
|
|
444
449
|
filePath: a,
|
|
@@ -447,10 +452,10 @@ const de = (e) => {
|
|
|
447
452
|
endSymbol: h.title.end
|
|
448
453
|
}
|
|
449
454
|
);
|
|
450
|
-
await
|
|
451
|
-
}, he = async (e,
|
|
455
|
+
await g.writeFile(a, i, "utf-8");
|
|
456
|
+
}, he = async (e, t, n) => {
|
|
452
457
|
try {
|
|
453
|
-
let a = await
|
|
458
|
+
let a = await x({
|
|
454
459
|
filePath: L(),
|
|
455
460
|
property: "sidebar",
|
|
456
461
|
startSymbol: h.sidebar.start,
|
|
@@ -464,53 +469,53 @@ const de = (e) => {
|
|
|
464
469
|
s || (o.warning("No existing sidebar found in astro.config.mjs. A new sidebar will be created."), s = []);
|
|
465
470
|
const i = W(s, e);
|
|
466
471
|
await D(i, "sidebar", "locales");
|
|
467
|
-
const r = we(
|
|
472
|
+
const r = we(t, n);
|
|
468
473
|
await D(r, "locales", "sidebar");
|
|
469
474
|
} catch (a) {
|
|
470
475
|
o.error(`Error reading astro.config.mjs: ${a.message}`), process.exit(1);
|
|
471
476
|
}
|
|
472
|
-
}, ye = (e) => /^---\s*\n([\s\S]*?)\n---\s*\n/.test(e), ke = (e) =>
|
|
473
|
-
function Ce(e,
|
|
477
|
+
}, ye = (e) => /^---\s*\n([\s\S]*?)\n---\s*\n/.test(e), ke = (e) => d.parse(e).name.replace(/[-_]/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").split(" ").filter((a) => a.length > 0).map((a) => a.charAt(0).toUpperCase() + a.slice(1).toLowerCase()).join(" ");
|
|
478
|
+
function Ce(e, t, n) {
|
|
474
479
|
if (ye(e))
|
|
475
480
|
return e;
|
|
476
|
-
const a = ke(
|
|
481
|
+
const a = ke(t), s = `---
|
|
477
482
|
title: "${a}"
|
|
478
483
|
---
|
|
479
484
|
|
|
480
485
|
`;
|
|
481
|
-
return o.warning(`Missing frontmatter in ${
|
|
486
|
+
return o.warning(`Missing frontmatter in ${n}`), o.info(`Added default title: "${a}"`), o.warning("Please update the content in Content Island 🏝️ to include proper frontmatter"), o.newLine(), s + e;
|
|
482
487
|
}
|
|
483
|
-
const
|
|
484
|
-
const
|
|
485
|
-
w(i) || await
|
|
486
|
-
},
|
|
488
|
+
const $ = async (e, t) => {
|
|
489
|
+
const n = P(), a = d.join(n, e), s = Ce(t, e, d.relative(process.cwd(), a)), i = d.dirname(a);
|
|
490
|
+
w(i) || await g.mkdir(i, { recursive: !0 }), await g.writeFile(a, s, "utf-8");
|
|
491
|
+
}, be = async (e, t) => {
|
|
487
492
|
try {
|
|
488
|
-
await
|
|
489
|
-
for (const
|
|
490
|
-
for (const a of
|
|
491
|
-
await
|
|
492
|
-
for (const
|
|
493
|
-
await
|
|
494
|
-
for (const a of
|
|
493
|
+
await $(e.index.filename, e.index.content);
|
|
494
|
+
for (const n of e.folders)
|
|
495
|
+
for (const a of n.pages)
|
|
496
|
+
await $(d.join(n.name, a.filename), a.content);
|
|
497
|
+
for (const n of t) {
|
|
498
|
+
await $(d.join(n.language, n.index.filename), n.index.content);
|
|
499
|
+
for (const a of n.folders)
|
|
495
500
|
for (const s of a.pages)
|
|
496
|
-
await
|
|
501
|
+
await $(d.join(n.language, a.name, s.filename), s.content);
|
|
497
502
|
}
|
|
498
|
-
} catch (
|
|
499
|
-
o.error(`Error updating docs content: ${
|
|
503
|
+
} catch (n) {
|
|
504
|
+
o.error(`Error updating docs content: ${n.message}`), process.exit(1);
|
|
500
505
|
}
|
|
501
|
-
},
|
|
506
|
+
}, Se = async (e, t) => {
|
|
502
507
|
if (e.length === 1) {
|
|
503
508
|
const s = e[0];
|
|
504
|
-
return o.success(`Single language found: ${s}. Continuing...`), await
|
|
509
|
+
return o.success(`Single language found: ${s}. Continuing...`), await S({ languageCode: s }), s;
|
|
505
510
|
}
|
|
506
|
-
const
|
|
507
|
-
if (
|
|
508
|
-
if (e.includes(
|
|
509
|
-
return o.info(`Using saved default language: ${
|
|
510
|
-
o.warning(`Saved language '${
|
|
511
|
+
const n = (await j())?.languageCode;
|
|
512
|
+
if (n && !t) {
|
|
513
|
+
if (e.includes(n))
|
|
514
|
+
return o.info(`Using saved default language: ${n}`), n;
|
|
515
|
+
o.warning(`Saved language '${n}' not found in project languages`), o.step("Will ask for new default language and save it");
|
|
511
516
|
}
|
|
512
517
|
o.step("Multiple languages found. Please select the default language:");
|
|
513
|
-
const a = await
|
|
518
|
+
const a = await b({
|
|
514
519
|
type: "select",
|
|
515
520
|
name: "language",
|
|
516
521
|
message: "Select the default language:",
|
|
@@ -520,8 +525,8 @@ const I = async (e, n) => {
|
|
|
520
525
|
})),
|
|
521
526
|
initial: 0
|
|
522
527
|
});
|
|
523
|
-
return a.language || (o.error("Language selection is required to continue."), process.exit(1)),
|
|
524
|
-
},
|
|
528
|
+
return a.language || (o.error("Language selection is required to continue."), process.exit(1)), n !== a.language && (await S({ languageCode: a.language }), o.config(`Saving default language '${a.language}' to config`)), a.language;
|
|
529
|
+
}, Ie = () => {
|
|
525
530
|
o.detected(`
|
|
526
531
|
⭐ ✨ STARLIGHT PROJECT DETECTED ✨ ⭐
|
|
527
532
|
|
|
@@ -533,173 +538,173 @@ const I = async (e, n) => {
|
|
|
533
538
|
✨ ⭐ ✨ ⭐ ✨
|
|
534
539
|
⭐ ✨ ⭐ ✨
|
|
535
540
|
`), o.success("All good! Starlight ⭐ project detected successfully."), o.loading("Launching process..."), o.newLine();
|
|
536
|
-
},
|
|
537
|
-
o.newLine(), o.error("Starlight ⭐ project not found!"), o.newLine(), o.error("Missing required items:"), e.forEach((
|
|
538
|
-
o.error(` • ${
|
|
541
|
+
}, $e = (e) => {
|
|
542
|
+
o.newLine(), o.error("Starlight ⭐ project not found!"), o.newLine(), o.error("Missing required items:"), e.forEach((t) => {
|
|
543
|
+
o.error(` • ${t}`);
|
|
539
544
|
}), o.newLine(), o.error("Please make sure you are in the root directory of a Starlight ⭐ project."), o.warning("A Starlight ⭐ project should have:"), o.warning(" • astro.config.mjs file"), o.warning(" • src/content/docs directory"), o.newLine();
|
|
540
|
-
},
|
|
541
|
-
const
|
|
542
|
-
(
|
|
545
|
+
}, V = (e) => {
|
|
546
|
+
const t = e.reduce(
|
|
547
|
+
(n, a) => ({ ...n, ...a }),
|
|
543
548
|
{}
|
|
544
549
|
);
|
|
545
|
-
return Object.keys(
|
|
546
|
-
},
|
|
547
|
-
const
|
|
548
|
-
return
|
|
549
|
-
}, Te = (e,
|
|
550
|
+
return Object.keys(t).length > 0 ? t : void 0;
|
|
551
|
+
}, Y = (e) => e.filename.replace(/\.(mdx?|md)$/, ""), _ = (e) => e.label ? e.label.trim() : Y(e), xe = (e, t) => {
|
|
552
|
+
const n = Y(e), a = t.trim().toLowerCase();
|
|
553
|
+
return n.toLocaleLowerCase() === "index" ? a : `${a}/${n}`;
|
|
554
|
+
}, Te = (e, t, n) => {
|
|
550
555
|
e.filename.replace(/\.(mdx?|md)$/, "");
|
|
551
|
-
const a =
|
|
556
|
+
const a = n.filter((s) => s.id === e.id).map((s) => ({ [s.language]: _(s) }));
|
|
552
557
|
return {
|
|
553
558
|
label: _(e),
|
|
554
|
-
slug:
|
|
555
|
-
translations:
|
|
559
|
+
slug: xe(e, t),
|
|
560
|
+
translations: V(a)
|
|
556
561
|
};
|
|
557
|
-
}, R = (e) => e.label ? e.label.trim() : e.name, ve = (e,
|
|
558
|
-
const
|
|
562
|
+
}, R = (e) => e.label ? e.label.trim() : e.name, ve = (e, t) => {
|
|
563
|
+
const n = t.flatMap((i) => i.folders ?? []).filter((i) => i.id === e.id), a = n.flatMap((i) => i.pages ?? []).filter((i) => e.pages.some((r) => r.id === i.id)), s = n.map((i) => ({ [i.language]: R(i) }));
|
|
559
564
|
return {
|
|
560
565
|
label: R(e),
|
|
561
|
-
translations:
|
|
566
|
+
translations: V(s),
|
|
562
567
|
items: T(e.pages, (i) => Te(i, e.name, a))
|
|
563
568
|
};
|
|
564
|
-
},
|
|
569
|
+
}, Ee = (e, t) => T(e.folders, (n) => ve(n, t)), Ae = () => ({
|
|
565
570
|
id: "starlight",
|
|
566
571
|
syncProject: async (e) => {
|
|
567
|
-
const { accessToken:
|
|
572
|
+
const { accessToken: t, askIfMultipleLanguages: n } = e;
|
|
568
573
|
o.step("Checking for Starlight ⭐ project...");
|
|
569
574
|
const { valid: a, missingItems: s } = me();
|
|
570
|
-
a || (
|
|
575
|
+
a || ($e(s), process.exit(1)), Ie(), o.connecting("Initializing Content Island 🏝️ client..."), de(t);
|
|
571
576
|
const i = await fe();
|
|
572
577
|
o.success(`Connected to project using template: ${i.template} (version: ${i.version})`), i.template !== "starlight" && (o.warning(
|
|
573
578
|
"The project you are trying to sync is not using the Starlight ⭐ template. Please make sure you are using the correct template."
|
|
574
|
-
), process.exit(1)), await
|
|
579
|
+
), process.exit(1)), await S({
|
|
575
580
|
version: i.version
|
|
576
581
|
}), o.fetching("Fetching project information from Content Island 🏝️ ...");
|
|
577
582
|
const r = await ue();
|
|
578
583
|
o.success(`Project fetched: ${r.name}`);
|
|
579
|
-
const
|
|
580
|
-
o.info(`Languages found (${
|
|
581
|
-
const
|
|
582
|
-
o.language(
|
|
583
|
-
const y =
|
|
584
|
-
let
|
|
584
|
+
const u = r.languages.map((k) => k);
|
|
585
|
+
o.info(`Languages found (${u.length}): ${u.join(", ")}`);
|
|
586
|
+
const l = await Se(u, n);
|
|
587
|
+
o.language(l);
|
|
588
|
+
const y = u.filter((k) => k !== l), p = await O(l);
|
|
589
|
+
let f = [];
|
|
585
590
|
for (const k of y) {
|
|
586
591
|
const ne = await O(k);
|
|
587
|
-
|
|
592
|
+
f.push(ne);
|
|
588
593
|
}
|
|
589
|
-
o.clearing("Clearing existing docs content..."), await pe(), o.docs("Existing docs content cleared"), o.updating("Updating docs content with fetched data..."), await
|
|
590
|
-
const te =
|
|
591
|
-
await he(te,
|
|
594
|
+
o.clearing("Clearing existing docs content..."), await pe(), o.docs("Existing docs content cleared"), o.updating("Updating docs content with fetched data..."), await be(p, f), o.docs("Docs content updated"), o.config("Generating sidebar configuration...");
|
|
595
|
+
const te = Ee(p, f);
|
|
596
|
+
await he(te, l, y), o.config("Sidebar configuration updated in astro.config.mjs");
|
|
592
597
|
}
|
|
593
|
-
}),
|
|
598
|
+
}), H = {
|
|
594
599
|
starlight: Ae
|
|
595
600
|
}, je = (e) => {
|
|
596
|
-
const
|
|
597
|
-
if (!
|
|
601
|
+
const t = H[e];
|
|
602
|
+
if (!t)
|
|
598
603
|
throw new Error(`Template "${e}" not found`);
|
|
599
|
-
return
|
|
600
|
-
}, Fe = () => Object.keys(
|
|
601
|
-
let
|
|
602
|
-
return
|
|
604
|
+
return t();
|
|
605
|
+
}, Fe = () => Object.keys(H), Pe = async (e, t) => {
|
|
606
|
+
let n;
|
|
607
|
+
return n || (n = (await j())?.templateID), n && t && (o.info(`Existing template found: ${n}`), (await b({
|
|
603
608
|
type: "confirm",
|
|
604
609
|
name: "useExisting",
|
|
605
|
-
message: `An existing template (${
|
|
610
|
+
message: `An existing template (${n}) was found. Do you want to use it?`,
|
|
606
611
|
initial: !0
|
|
607
|
-
}))?.useExisting ? o.success(`Using existing template: ${
|
|
612
|
+
}))?.useExisting ? o.success(`Using existing template: ${n}`) : (n = null, o.step("Selecting new template..."))), n || (o.step("Please select a template:"), n = (await b({
|
|
608
613
|
type: "select",
|
|
609
614
|
name: "templateID",
|
|
610
615
|
message: "Select a template:",
|
|
611
616
|
choices: e.map((s) => ({ title: s, value: s }))
|
|
612
|
-
}))?.templateID),
|
|
617
|
+
}))?.templateID), n || (o.error("Template is required to continue"), process.exit(1)), n;
|
|
613
618
|
}, Z = async (e) => {
|
|
614
619
|
try {
|
|
615
|
-
const { selectedTemplateId:
|
|
616
|
-
let s = a.find((i) => i ===
|
|
617
|
-
return s || (s = await Pe(a,
|
|
618
|
-
} catch (
|
|
619
|
-
o.error(`Error configuring template: ${
|
|
620
|
+
const { selectedTemplateId: t, askIfExists: n } = e, a = Fe();
|
|
621
|
+
let s = a.find((i) => i === t);
|
|
622
|
+
return s || (s = await Pe(a, n)), o.detected(`Template selected: ${s}`), je(s);
|
|
623
|
+
} catch (t) {
|
|
624
|
+
o.error(`Error configuring template: ${t.message}`), process.exit(1);
|
|
620
625
|
}
|
|
621
626
|
}, z = ".env", X = "CONTENT_ISLAND_ACCESS_TOKEN", Le = async (e) => {
|
|
622
627
|
switch (e) {
|
|
623
628
|
case "starlight":
|
|
624
|
-
return await K(),
|
|
629
|
+
return await K(), d.join(A(), z);
|
|
625
630
|
default:
|
|
626
|
-
return
|
|
631
|
+
return d.join(process.cwd(), z);
|
|
627
632
|
}
|
|
628
633
|
}, Ne = async (e) => {
|
|
629
634
|
if (!w(e))
|
|
630
635
|
return null;
|
|
631
636
|
try {
|
|
632
|
-
const
|
|
633
|
-
return
|
|
637
|
+
const n = (await g.readFile(e, "utf-8")).match(new RegExp(`${X}=(.+)`));
|
|
638
|
+
return n ? n[1].trim() : null;
|
|
634
639
|
} catch {
|
|
635
640
|
return null;
|
|
636
641
|
}
|
|
637
|
-
}, Q = async (e,
|
|
642
|
+
}, Q = async (e, t) => {
|
|
638
643
|
try {
|
|
639
|
-
const
|
|
644
|
+
const n = `${X}=${e}
|
|
640
645
|
`;
|
|
641
|
-
await
|
|
642
|
-
} catch (
|
|
643
|
-
o.error(`Failed to save the access token: ${
|
|
646
|
+
await g.writeFile(t, n, "utf-8"), o.token(`Access token saved to ${t}`);
|
|
647
|
+
} catch (n) {
|
|
648
|
+
o.error(`Failed to save the access token: ${n.message}`);
|
|
644
649
|
}
|
|
645
650
|
}, B = (e) => {
|
|
646
651
|
e || (o.error("Token is required to continue"), process.exit(1));
|
|
647
|
-
}, Me = async (e,
|
|
648
|
-
let
|
|
649
|
-
if (
|
|
652
|
+
}, Me = async (e, t) => {
|
|
653
|
+
let n = await Ne(e);
|
|
654
|
+
if (n && t && (o.info("Found existing Content Island 🏝️ token"), (await b({
|
|
650
655
|
type: "confirm",
|
|
651
656
|
name: "useExisting",
|
|
652
657
|
message: "An existing token was found. Do you want to use it?",
|
|
653
658
|
initial: !0
|
|
654
|
-
}))?.useExisting || (
|
|
659
|
+
}))?.useExisting || (n = null)), n)
|
|
655
660
|
o.success("Using existing Content Island 🏝️ token");
|
|
656
661
|
else {
|
|
657
|
-
|
|
658
|
-
const a = await
|
|
662
|
+
t || o.warning("No existing token found");
|
|
663
|
+
const a = await b({
|
|
659
664
|
type: "password",
|
|
660
665
|
name: "token",
|
|
661
666
|
message: "Enter your Content Island 🏝️ API token:",
|
|
662
667
|
validate: (s) => s.length > 0 ? !0 : "Token is required"
|
|
663
668
|
});
|
|
664
|
-
B(a?.token),
|
|
669
|
+
B(a?.token), n = a?.token, await Q(n, e);
|
|
665
670
|
}
|
|
666
|
-
return B(
|
|
671
|
+
return B(n), n;
|
|
667
672
|
}, ee = async (e) => {
|
|
668
|
-
const { accessToken:
|
|
669
|
-
let s =
|
|
670
|
-
const i = await Le(
|
|
673
|
+
const { accessToken: t, templateID: n, askIfExists: a } = e;
|
|
674
|
+
let s = t;
|
|
675
|
+
const i = await Le(n);
|
|
671
676
|
return s ? (o.success("Using provided Content Island 🏝️ token"), await Q(s, i)) : s = await Me(i, a), s;
|
|
672
677
|
}, Oe = async (e) => {
|
|
673
678
|
try {
|
|
674
679
|
o.title("Content Island Integration"), o.step("Configuring template...");
|
|
675
|
-
const
|
|
676
|
-
o.step("Saving configuration..."), await
|
|
677
|
-
const
|
|
680
|
+
const t = await Z({ selectedTemplateId: e.template, askIfExists: !0 });
|
|
681
|
+
o.step("Saving configuration..."), await S({ templateID: t.id }), o.config("Template configuration saved"), o.step("Configuring access token...");
|
|
682
|
+
const n = await ee({
|
|
678
683
|
accessToken: e.token,
|
|
679
|
-
templateID:
|
|
684
|
+
templateID: t.id,
|
|
680
685
|
askIfExists: !0
|
|
681
686
|
});
|
|
682
|
-
o.token("Access token configured successfully"), o.step("Synchronizing project..."), await
|
|
683
|
-
} catch (
|
|
684
|
-
o.newLine(), o.error("Error during Content Island integration:"), o.error(
|
|
687
|
+
o.token("Access token configured successfully"), o.step("Synchronizing project..."), await t.syncProject({ accessToken: n, askIfMultipleLanguages: !0 }), o.docs("Project synchronized with Content Island"), o.newLine(), o.complete("Content Island 🏝️ integration completed successfully!");
|
|
688
|
+
} catch (t) {
|
|
689
|
+
o.newLine(), o.error("Error during Content Island integration:"), o.error(t instanceof Error ? t.message : String(t)), process.exit(1);
|
|
685
690
|
}
|
|
686
691
|
}, De = async () => {
|
|
687
692
|
try {
|
|
688
693
|
o.title("Content Island Integration"), o.step("Configuring template...");
|
|
689
694
|
const e = await Z({ askIfExists: !1 });
|
|
690
|
-
o.step("Saving configuration..."), await
|
|
691
|
-
const
|
|
695
|
+
o.step("Saving configuration..."), await S({ templateID: e.id }), o.config("Template configuration saved"), o.step("Configuring access token...");
|
|
696
|
+
const t = await ee({
|
|
692
697
|
templateID: e.id,
|
|
693
698
|
askIfExists: !1
|
|
694
699
|
});
|
|
695
|
-
o.token("Access token configured successfully"), o.step("Synchronizing project..."), await e.syncProject({ accessToken:
|
|
700
|
+
o.token("Access token configured successfully"), o.step("Synchronizing project..."), await e.syncProject({ accessToken: t, askIfMultipleLanguages: !1 }), o.docs("Project synchronized with Content Island"), o.newLine(), o.complete("Content Island 🏝️ integration completed successfully!");
|
|
696
701
|
} catch (e) {
|
|
697
702
|
o.newLine(), o.error("Error during Content Island integration:"), o.error(e instanceof Error ? e.message : String(e)), process.exit(1);
|
|
698
703
|
}
|
|
699
|
-
}, _e = "0.0.
|
|
704
|
+
}, _e = "0.0.4", Re = {
|
|
700
705
|
version: _e
|
|
701
|
-
},
|
|
702
|
-
|
|
706
|
+
}, I = ae("create-contentisland");
|
|
707
|
+
I.command("", "Initialize and validate a project").example("npm create contentisland").example("npm create contentisland --token <token>").example("npm create contentisland --token <token> --template starlight").option(
|
|
703
708
|
"--token <token>",
|
|
704
709
|
"Your Content Island token (you can also set the CONTENT_ISLAND_ACCESS_TOKEN environment variable)",
|
|
705
710
|
{
|
|
@@ -708,9 +713,9 @@ $.command("", "Initialize and validate a project").example("npm create contentis
|
|
|
708
713
|
).option("--template <template>", "The template to use: starlight.").action(async (e) => {
|
|
709
714
|
await Oe(e);
|
|
710
715
|
});
|
|
711
|
-
|
|
716
|
+
I.command("update", "Update content from Content Island 🏝️ (preserves existing token)").example("npm create contentisland update").action(async () => {
|
|
712
717
|
await De();
|
|
713
718
|
});
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
719
|
+
I.help();
|
|
720
|
+
I.version(Re.version);
|
|
721
|
+
I.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-contentisland",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Content Island - Starlight CLI",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"test:watch": "vitest -c ./config/test/config.ts"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@content-island/api-client": "0.
|
|
30
|
+
"@content-island/api-client": "0.12.0",
|
|
31
31
|
"cac": "6.7.14",
|
|
32
32
|
"prompts": "2.4.2"
|
|
33
33
|
},
|