blume 1.4.0 → 1.4.1
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/CHANGELOG.md +22 -0
- package/dist/cli/index.js +322 -644
- package/dist/cli/index.js.map +34 -34
- package/package.json +22 -1
- package/src/ai/component-markdown.ts +7 -6
- package/src/astro/generate.ts +4 -13
- package/src/astro/islands.ts +4 -1
- package/src/astro/templates.ts +3 -4
- package/src/audit/checks/indexability.ts +3 -6
- package/src/audit/checks/robots.ts +18 -37
- package/src/audit/crawl.ts +49 -49
- package/src/audit/image-size.ts +13 -53
- package/src/audit/report.ts +22 -33
- package/src/audit/types.ts +6 -2
- package/src/cli/commands/dev.ts +9 -21
- package/src/cli/commands/doctor.ts +9 -22
- package/src/cli/env.ts +6 -52
- package/src/cli/init/scaffold.ts +15 -28
- package/src/cli/internal-error.ts +11 -11
- package/src/components/islands/ask-ai.tsx +25 -100
- package/src/components/islands/hooks.ts +10 -3
- package/src/components/layout/RootLayout.astro +37 -109
- package/src/components/layout/Search.astro +3 -5
- package/src/components/layout/search/types.ts +4 -16
- package/src/components/openapi/helpers.ts +21 -75
- package/src/core/component-overrides.ts +0 -7
- package/src/core/config.ts +3 -3
- package/src/core/diagnostics.ts +10 -20
- package/src/core/fs-atomic.ts +22 -0
- package/src/core/sources/github-releases.ts +29 -26
- package/src/core/sources/mdx-remote.ts +10 -57
- package/src/core/sources/notion.ts +17 -23
- package/src/core/tsconfig-aliases.ts +39 -172
- package/src/deploy/rss.ts +4 -1
- package/src/deploy/sitemap.ts +3 -1
- package/src/eval/report.ts +20 -28
- package/src/markdown/directives.ts +6 -18
- package/src/markdown/index.ts +1 -6
- package/src/markdown/package-commands.ts +0 -4
- package/src/openapi/parse.ts +11 -9
- package/src/search/popular-icon.ts +3 -3
- package/src/translate/ledger.ts +5 -11
- package/src/translate/report.ts +22 -28
- package/src/translate/run.ts +5 -24
- package/src/translate/work-list.ts +0 -0
- package/src/deploy/xml.ts +0 -8
package/dist/cli/index.js
CHANGED
|
@@ -281,6 +281,7 @@ import { consola } from "consola";
|
|
|
281
281
|
import { relative as relative3 } from "pathe";
|
|
282
282
|
|
|
283
283
|
// src/core/diagnostics.ts
|
|
284
|
+
import { colors } from "consola/utils";
|
|
284
285
|
import { relative as relative2 } from "pathe";
|
|
285
286
|
|
|
286
287
|
class BlumeError extends Error {
|
|
@@ -394,45 +395,35 @@ var diagnosticsFromZod = (error, options) => diagnosticsFromIssues(error.issues.
|
|
|
394
395
|
message: issue.message,
|
|
395
396
|
path: issue.path.filter((segment) => typeof segment !== "symbol")
|
|
396
397
|
})), options);
|
|
397
|
-
var ESC = String.fromCodePoint(27);
|
|
398
|
-
var COLORS = {
|
|
399
|
-
blue: `${ESC}[34m`,
|
|
400
|
-
bold: `${ESC}[1m`,
|
|
401
|
-
cyan: `${ESC}[36m`,
|
|
402
|
-
dim: `${ESC}[2m`,
|
|
403
|
-
red: `${ESC}[31m`,
|
|
404
|
-
reset: `${ESC}[0m`,
|
|
405
|
-
yellow: `${ESC}[33m`
|
|
406
|
-
};
|
|
407
398
|
var severityColor = (severity) => {
|
|
408
399
|
if (severity === "error") {
|
|
409
|
-
return
|
|
400
|
+
return colors.red;
|
|
410
401
|
}
|
|
411
402
|
if (severity === "warning") {
|
|
412
|
-
return
|
|
403
|
+
return colors.yellow;
|
|
413
404
|
}
|
|
414
|
-
return
|
|
405
|
+
return colors.blue;
|
|
415
406
|
};
|
|
416
407
|
var formatDiagnostic = (diagnostic, root) => {
|
|
417
408
|
const color = severityColor(diagnostic.severity);
|
|
418
409
|
const lines = [
|
|
419
|
-
`${color
|
|
410
|
+
`${color(colors.bold(diagnostic.code))} ${diagnostic.message}`
|
|
420
411
|
];
|
|
421
412
|
if (diagnostic.url) {
|
|
422
|
-
lines.push(` ${
|
|
413
|
+
lines.push(` ${colors.dim(`at ${diagnostic.url}`)}`);
|
|
423
414
|
}
|
|
424
415
|
if (diagnostic.file) {
|
|
425
416
|
const location = root ? relative2(root, diagnostic.file) : diagnostic.file;
|
|
426
417
|
const column = diagnostic.column === undefined ? "" : `:${diagnostic.column}`;
|
|
427
418
|
const position = diagnostic.line === undefined ? "" : `:${diagnostic.line}${column}`;
|
|
428
419
|
const label = diagnostic.url ? "in" : "at";
|
|
429
|
-
lines.push(` ${
|
|
420
|
+
lines.push(` ${colors.dim(`${label} ${location}${position}`)}`);
|
|
430
421
|
}
|
|
431
422
|
if (diagnostic.suggestion) {
|
|
432
|
-
lines.push(` ${
|
|
423
|
+
lines.push(` ${colors.cyan(`fix: ${diagnostic.suggestion}`)}`);
|
|
433
424
|
}
|
|
434
425
|
if (diagnostic.docsUrl) {
|
|
435
|
-
lines.push(` ${
|
|
426
|
+
lines.push(` ${colors.dim(`docs: ${diagnostic.docsUrl}`)}`);
|
|
436
427
|
}
|
|
437
428
|
return lines.join(`
|
|
438
429
|
`);
|
|
@@ -552,6 +543,7 @@ import { tmpdir } from "node:os";
|
|
|
552
543
|
import { join as join5 } from "pathe";
|
|
553
544
|
|
|
554
545
|
// src/audit/report.ts
|
|
546
|
+
import { colors as colors2 } from "consola/utils";
|
|
555
547
|
import { relative as relative4 } from "pathe";
|
|
556
548
|
|
|
557
549
|
// src/audit/catalog.ts
|
|
@@ -1295,20 +1287,10 @@ var finding = (id, site, detail, fix) => {
|
|
|
1295
1287
|
};
|
|
1296
1288
|
|
|
1297
1289
|
// src/audit/report.ts
|
|
1298
|
-
var ESC2 = String.fromCodePoint(27);
|
|
1299
|
-
var COLORS2 = {
|
|
1300
|
-
bold: `${ESC2}[1m`,
|
|
1301
|
-
cyan: `${ESC2}[36m`,
|
|
1302
|
-
dim: `${ESC2}[2m`,
|
|
1303
|
-
green: `${ESC2}[32m`,
|
|
1304
|
-
red: `${ESC2}[31m`,
|
|
1305
|
-
reset: `${ESC2}[0m`,
|
|
1306
|
-
yellow: `${ESC2}[33m`
|
|
1307
|
-
};
|
|
1308
1290
|
var SEVERITY_COLOR = {
|
|
1309
|
-
error:
|
|
1310
|
-
info:
|
|
1311
|
-
warning:
|
|
1291
|
+
error: colors2.red,
|
|
1292
|
+
info: colors2.blue,
|
|
1293
|
+
warning: colors2.yellow
|
|
1312
1294
|
};
|
|
1313
1295
|
var GLYPH = {
|
|
1314
1296
|
error: "✖",
|
|
@@ -1355,7 +1337,7 @@ var rollup = (diagnostics) => {
|
|
|
1355
1337
|
};
|
|
1356
1338
|
var skippedTiers = (tiers) => Object.keys(TIER_FLAG).filter((tier) => !tiers[tier]).map((tier) => {
|
|
1357
1339
|
const label = CHECKS.filter((check) => check.tier === tier).length;
|
|
1358
|
-
return ` ${
|
|
1340
|
+
return ` ${colors2.dim(`⊘ ${tier.padEnd(12)} skipped — pass ${TIER_FLAG[tier]} (${label} checks)`)}`;
|
|
1359
1341
|
});
|
|
1360
1342
|
var activeChecks = (tiers) => CHECKS.filter((check) => tiers[check.tier]).length;
|
|
1361
1343
|
var auditCount = (result) => activeChecks(result.tiers) * result.pages;
|
|
@@ -1367,7 +1349,7 @@ var summaryLine = (counts, audits) => [
|
|
|
1367
1349
|
].join(" · ");
|
|
1368
1350
|
var findingLine = (diagnostic, root) => {
|
|
1369
1351
|
const url = diagnostic.url ?? "";
|
|
1370
|
-
const source = diagnostic.file ?
|
|
1352
|
+
const source = diagnostic.file ? colors2.dim(`${relative4(root, diagnostic.file)}${diagnostic.line === undefined ? "" : `:${diagnostic.line}`}`) : "";
|
|
1371
1353
|
return ` ${url.padEnd(34)} ${source}`.trimEnd();
|
|
1372
1354
|
};
|
|
1373
1355
|
var formatReport = (result, root, options = {}) => {
|
|
@@ -1375,35 +1357,35 @@ var formatReport = (result, root, options = {}) => {
|
|
|
1375
1357
|
const groups = rollup(result.diagnostics);
|
|
1376
1358
|
const lines = [];
|
|
1377
1359
|
const where = result.origin ? `${relative4(root, result.staticDir) || "dist"} + ${result.origin}` : `${relative4(root, result.staticDir) || "dist"} · offline`;
|
|
1378
|
-
lines.push("", ` ${
|
|
1360
|
+
lines.push("", ` ${colors2.bold("blume audit")} ${colors2.dim(`${result.pages} pages · ${where}`)}`, ` ${summaryLine(counts, auditCount(result))}`, "");
|
|
1379
1361
|
if (groups.length === 0) {
|
|
1380
|
-
lines.push(` ${
|
|
1362
|
+
lines.push(` ${colors2.green("✔ No issues found.")}`, "");
|
|
1381
1363
|
}
|
|
1382
1364
|
let category = null;
|
|
1383
1365
|
for (const group of groups) {
|
|
1384
1366
|
const { category: next } = group;
|
|
1385
1367
|
if (next !== category) {
|
|
1386
1368
|
category = next;
|
|
1387
|
-
lines.push(` ${
|
|
1369
|
+
lines.push(` ${colors2.bold(category)}`, "");
|
|
1388
1370
|
}
|
|
1389
1371
|
const color = SEVERITY_COLOR[group.severity];
|
|
1390
1372
|
const pages = `${group.count} page${group.count === 1 ? "" : "s"}`;
|
|
1391
|
-
lines.push(` ${color
|
|
1373
|
+
lines.push(` ${color(`${GLYPH[group.severity]} ${group.title}`)} ${colors2.dim(pages)}`);
|
|
1392
1374
|
const shown = options.verbose ? group.findings : group.findings.slice(0, PREVIEW);
|
|
1393
1375
|
for (const diagnostic of shown) {
|
|
1394
1376
|
lines.push(findingLine(diagnostic, root));
|
|
1395
1377
|
if (options.verbose) {
|
|
1396
|
-
lines.push(` ${
|
|
1378
|
+
lines.push(` ${colors2.dim(diagnostic.message)}`);
|
|
1397
1379
|
}
|
|
1398
1380
|
}
|
|
1399
1381
|
const hidden = group.count - shown.length;
|
|
1400
1382
|
if (hidden > 0) {
|
|
1401
|
-
lines.push(` ${
|
|
1383
|
+
lines.push(` ${colors2.dim(`… and ${hidden} more (--verbose)`)}`);
|
|
1402
1384
|
}
|
|
1403
1385
|
const [first] = group.findings;
|
|
1404
1386
|
const fix = first?.suggestion;
|
|
1405
1387
|
if (fix) {
|
|
1406
|
-
lines.push(` ${
|
|
1388
|
+
lines.push(` ${colors2.cyan(`fix: ${fix}`)}`);
|
|
1407
1389
|
}
|
|
1408
1390
|
lines.push("");
|
|
1409
1391
|
}
|
|
@@ -1442,10 +1424,10 @@ var formatCatalog = () => {
|
|
|
1442
1424
|
const { category: next } = check;
|
|
1443
1425
|
if (next !== category) {
|
|
1444
1426
|
category = next;
|
|
1445
|
-
lines.push(` ${
|
|
1427
|
+
lines.push(` ${colors2.bold(category)}`);
|
|
1446
1428
|
}
|
|
1447
|
-
const tier = check.tier === "static" ? "" : ` ${
|
|
1448
|
-
lines.push(` ${SEVERITY_COLOR[check.severity]
|
|
1429
|
+
const tier = check.tier === "static" ? "" : ` ${colors2.dim(`[${check.tier}]`)}`;
|
|
1430
|
+
lines.push(` ${SEVERITY_COLOR[check.severity](GLYPH[check.severity])} ${check.id.replace("BLUME_AUDIT_", "").toLowerCase().padEnd(34)} ${colors2.dim(check.title)}${tier}`);
|
|
1449
1431
|
}
|
|
1450
1432
|
lines.push("", ` ${CHECKS.length} checks.`, "");
|
|
1451
1433
|
return lines.join(`
|
|
@@ -2167,12 +2149,9 @@ var applyDeploymentEnv = (config, env = process.env) => {
|
|
|
2167
2149
|
};
|
|
2168
2150
|
|
|
2169
2151
|
// src/audit/checks/indexability.ts
|
|
2170
|
-
var parseCanonical = (
|
|
2171
|
-
if (!page.canonical) {
|
|
2172
|
-
return null;
|
|
2173
|
-
}
|
|
2152
|
+
var parseCanonical = (canonical) => {
|
|
2174
2153
|
try {
|
|
2175
|
-
return new URL(
|
|
2154
|
+
return new URL(canonical);
|
|
2176
2155
|
} catch {
|
|
2177
2156
|
return null;
|
|
2178
2157
|
}
|
|
@@ -2188,7 +2167,7 @@ var canonicalChecks = (context, page) => {
|
|
|
2188
2167
|
finding("BLUME_AUDIT_CANONICAL_MISSING", pageSite(context, page), "Page has no canonical URL.")
|
|
2189
2168
|
] : [];
|
|
2190
2169
|
}
|
|
2191
|
-
const canonical = parseCanonical(page);
|
|
2170
|
+
const canonical = parseCanonical(page.canonical);
|
|
2192
2171
|
if (!canonical) {
|
|
2193
2172
|
return [
|
|
2194
2173
|
finding("BLUME_AUDIT_CANONICAL_BAD_TARGET", pageSite(context, page, ["seo", "canonical"]), `Canonical "${page.canonical}" is not a valid absolute URL.`)
|
|
@@ -2658,41 +2637,15 @@ import { readFile as readFile2 } from "node:fs/promises";
|
|
|
2658
2637
|
import { join as join7 } from "pathe";
|
|
2659
2638
|
|
|
2660
2639
|
// src/audit/image-size.ts
|
|
2661
|
-
|
|
2662
|
-
var
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
};
|
|
2668
|
-
var isSof = (marker) => marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204;
|
|
2669
|
-
var jpegSize = (bytes) => {
|
|
2670
|
-
if (bytes.length < 4 || bytes[0] !== 255 || bytes[1] !== 216) {
|
|
2671
|
-
return null;
|
|
2672
|
-
}
|
|
2673
|
-
let offset = 2;
|
|
2674
|
-
while (offset + 9 < bytes.length) {
|
|
2675
|
-
if (bytes[offset] !== 255) {
|
|
2676
|
-
return null;
|
|
2677
|
-
}
|
|
2678
|
-
const marker = bytes[offset + 1] ?? 0;
|
|
2679
|
-
if (isSof(marker)) {
|
|
2680
|
-
return {
|
|
2681
|
-
height: bytes.readUInt16BE(offset + 5),
|
|
2682
|
-
width: bytes.readUInt16BE(offset + 7)
|
|
2683
|
-
};
|
|
2684
|
-
}
|
|
2685
|
-
offset += 2 + bytes.readUInt16BE(offset + 2);
|
|
2686
|
-
}
|
|
2687
|
-
return null;
|
|
2688
|
-
};
|
|
2689
|
-
var gifSize = (bytes) => {
|
|
2690
|
-
if (bytes.length < 10 || bytes.subarray(0, 4).toString("latin1") !== "GIF8") {
|
|
2640
|
+
import { imageSize as measureImage } from "image-size";
|
|
2641
|
+
var imageSize = (bytes) => {
|
|
2642
|
+
try {
|
|
2643
|
+
const { width, height } = measureImage(bytes);
|
|
2644
|
+
return width > 0 && height > 0 ? { height, width } : null;
|
|
2645
|
+
} catch {
|
|
2691
2646
|
return null;
|
|
2692
2647
|
}
|
|
2693
|
-
return { height: bytes.readUInt16LE(8), width: bytes.readUInt16LE(6) };
|
|
2694
2648
|
};
|
|
2695
|
-
var imageSize = (bytes) => pngSize(bytes) ?? jpegSize(bytes) ?? gifSize(bytes);
|
|
2696
2649
|
|
|
2697
2650
|
// src/audit/checks/og-image.ts
|
|
2698
2651
|
var MIN_WIDTH = 600;
|
|
@@ -2785,28 +2738,8 @@ var redirectChecks = {
|
|
|
2785
2738
|
};
|
|
2786
2739
|
|
|
2787
2740
|
// src/audit/checks/robots.ts
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
const pattern = anchored ? rule.slice(0, -1) : rule;
|
|
2791
|
-
const parts = pattern.split("*");
|
|
2792
|
-
let cursor = 0;
|
|
2793
|
-
for (const [index, part] of parts.entries()) {
|
|
2794
|
-
if (part === "") {
|
|
2795
|
-
continue;
|
|
2796
|
-
}
|
|
2797
|
-
let at;
|
|
2798
|
-
if (index === 0) {
|
|
2799
|
-
at = path.startsWith(part) ? 0 : -1;
|
|
2800
|
-
} else {
|
|
2801
|
-
at = path.indexOf(part, cursor);
|
|
2802
|
-
}
|
|
2803
|
-
if (at === -1) {
|
|
2804
|
-
return false;
|
|
2805
|
-
}
|
|
2806
|
-
cursor = at + part.length;
|
|
2807
|
-
}
|
|
2808
|
-
return anchored && !pattern.endsWith("*") ? cursor === path.length : true;
|
|
2809
|
-
};
|
|
2741
|
+
import robotsParser from "robots-parser";
|
|
2742
|
+
var MATCH_ORIGIN = "https://robots-audit.invalid";
|
|
2810
2743
|
var robotsChecks = {
|
|
2811
2744
|
category: "robots",
|
|
2812
2745
|
run(context) {
|
|
@@ -2824,6 +2757,8 @@ var robotsChecks = {
|
|
|
2824
2757
|
if (site && robots.sitemaps.length === 0) {
|
|
2825
2758
|
found.push(finding("BLUME_AUDIT_ROBOTS_SITEMAP_MISSING", { file: robots.file, url: "/robots.txt" }, "robots.txt does not declare a Sitemap."));
|
|
2826
2759
|
}
|
|
2760
|
+
const parser = robotsParser(`${MATCH_ORIGIN}/robots.txt`, robots.raw);
|
|
2761
|
+
const lines = robots.raw.split(/\r?\n/u);
|
|
2827
2762
|
for (const loc of context.sitemap?.urls ?? []) {
|
|
2828
2763
|
let pathname;
|
|
2829
2764
|
try {
|
|
@@ -2832,9 +2767,11 @@ var robotsChecks = {
|
|
|
2832
2767
|
continue;
|
|
2833
2768
|
}
|
|
2834
2769
|
const path = normalizePath(pathname);
|
|
2835
|
-
const
|
|
2836
|
-
if (
|
|
2837
|
-
|
|
2770
|
+
const url = `${MATCH_ORIGIN}${pathname}`;
|
|
2771
|
+
if (parser.isDisallowed(url, "*")) {
|
|
2772
|
+
const line = parser.getMatchingLineNumber(url, "*");
|
|
2773
|
+
const rule = line > 0 ? lines[line - 1]?.trim() : undefined;
|
|
2774
|
+
found.push(finding("BLUME_AUDIT_ROBOTS_DISALLOWS_INDEXABLE", { file: robots.file, url: path }, `robots.txt "${rule ?? "Disallow"}" blocks ${path}, which sitemap.xml advertises.`));
|
|
2838
2775
|
}
|
|
2839
2776
|
}
|
|
2840
2777
|
return found;
|
|
@@ -3058,6 +2995,7 @@ var urlChecks = {
|
|
|
3058
2995
|
|
|
3059
2996
|
// src/audit/crawl.ts
|
|
3060
2997
|
import { readFile as readFile3, stat } from "node:fs/promises";
|
|
2998
|
+
import { XMLParser } from "fast-xml-parser";
|
|
3061
2999
|
import { join as join9, relative as relative6 } from "pathe";
|
|
3062
3000
|
import { glob } from "tinyglobby";
|
|
3063
3001
|
|
|
@@ -4225,7 +4163,8 @@ var hostedSearchOptions = (search) => {
|
|
|
4225
4163
|
var searchClientTemplate = (config) => {
|
|
4226
4164
|
const { search } = config;
|
|
4227
4165
|
if (search.provider === "orama" || search.provider === "flexsearch") {
|
|
4228
|
-
|
|
4166
|
+
const locale = search.provider === "orama" ? config.i18n?.defaultLocale : undefined;
|
|
4167
|
+
return staticSearchClient(search.provider, locale);
|
|
4229
4168
|
}
|
|
4230
4169
|
const hosted = hostedSearchOptions(search);
|
|
4231
4170
|
if (hosted) {
|
|
@@ -5464,35 +5403,39 @@ var routeIndex = (manifest, basePath) => {
|
|
|
5464
5403
|
}
|
|
5465
5404
|
return index;
|
|
5466
5405
|
};
|
|
5467
|
-
var
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5472
|
-
|
|
5473
|
-
">": ">",
|
|
5474
|
-
"<": "<",
|
|
5475
|
-
""": '"'
|
|
5476
|
-
};
|
|
5477
|
-
var unescapeXml = (value) => value.replaceAll(/&(?:amp|apos|gt|lt|quot);/gu, (entity) => XML_ENTITIES[entity] ?? entity);
|
|
5406
|
+
var sitemapParser = new XMLParser({
|
|
5407
|
+
htmlEntities: true,
|
|
5408
|
+
ignoreAttributes: true,
|
|
5409
|
+
parseTagValue: false,
|
|
5410
|
+
removeNSPrefix: true
|
|
5411
|
+
});
|
|
5478
5412
|
var parseSitemap = (file, xml, bytes) => {
|
|
5479
5413
|
const doc = { bytes, file, lastmod: new Map, urls: [] };
|
|
5480
|
-
|
|
5481
|
-
|
|
5414
|
+
let parsed;
|
|
5415
|
+
try {
|
|
5416
|
+
parsed = sitemapParser.parse(xml);
|
|
5417
|
+
} catch {
|
|
5418
|
+
doc.error = "no <urlset> element";
|
|
5482
5419
|
return doc;
|
|
5483
5420
|
}
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
doc.urls.push(loc);
|
|
5488
|
-
}
|
|
5421
|
+
if (!Object.hasOwn(parsed, "urlset")) {
|
|
5422
|
+
doc.error = Object.hasOwn(parsed, "sitemapindex") ? "sitemap is an index, not a urlset" : "no <urlset> element";
|
|
5423
|
+
return doc;
|
|
5489
5424
|
}
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5425
|
+
const urlset = parsed.urlset;
|
|
5426
|
+
const entries = typeof urlset === "object" && urlset !== null ? [urlset.url].flat() : [];
|
|
5427
|
+
for (const entry of entries) {
|
|
5428
|
+
if (typeof entry !== "object" || entry === null) {
|
|
5429
|
+
continue;
|
|
5430
|
+
}
|
|
5431
|
+
const { loc, lastmod } = entry;
|
|
5432
|
+
const locText = typeof loc === "string" ? loc.trim() : "";
|
|
5433
|
+
if (!locText) {
|
|
5434
|
+
continue;
|
|
5435
|
+
}
|
|
5436
|
+
doc.urls.push(locText);
|
|
5437
|
+
if (typeof lastmod === "string" && lastmod.trim() !== "") {
|
|
5438
|
+
doc.lastmod?.set(locText, lastmod.trim());
|
|
5496
5439
|
}
|
|
5497
5440
|
}
|
|
5498
5441
|
return doc;
|
|
@@ -5512,8 +5455,7 @@ var parseLlms = (file, text) => {
|
|
|
5512
5455
|
};
|
|
5513
5456
|
var ROBOTS_DIRECTIVE = /^(?<field>[a-z-]+)\s*:\s*(?<value>.*)$/iu;
|
|
5514
5457
|
var parseRobots = (file, text) => {
|
|
5515
|
-
const doc = {
|
|
5516
|
-
let appliesToAll = false;
|
|
5458
|
+
const doc = { file, invalid: [], raw: text, sitemaps: [] };
|
|
5517
5459
|
for (const [index, raw] of text.split(/\r?\n/u).entries()) {
|
|
5518
5460
|
const line = raw.trim();
|
|
5519
5461
|
if (line === "" || line.startsWith("#")) {
|
|
@@ -5526,11 +5468,7 @@ var parseRobots = (file, text) => {
|
|
|
5526
5468
|
}
|
|
5527
5469
|
const field = (match.groups?.field ?? "").toLowerCase();
|
|
5528
5470
|
const value = (match.groups?.value ?? "").trim();
|
|
5529
|
-
if (field === "
|
|
5530
|
-
appliesToAll = value === "*";
|
|
5531
|
-
} else if (field === "disallow" && appliesToAll && value) {
|
|
5532
|
-
doc.disallow.push(value);
|
|
5533
|
-
} else if (field === "sitemap" && value) {
|
|
5471
|
+
if (field === "sitemap" && value) {
|
|
5534
5472
|
doc.sitemaps.push(value);
|
|
5535
5473
|
}
|
|
5536
5474
|
}
|
|
@@ -10230,12 +10168,13 @@ var loadConfig = async (root, options = {}) => {
|
|
|
10230
10168
|
};
|
|
10231
10169
|
const moreIssues = rest.map((d) => ` - ${d.message}`).join(`
|
|
10232
10170
|
`);
|
|
10233
|
-
|
|
10171
|
+
const detail = rest.length > 0 ? {
|
|
10234
10172
|
...primary,
|
|
10235
10173
|
message: `${primary.message}
|
|
10236
10174
|
${rest.length} more config issue(s):
|
|
10237
10175
|
${moreIssues}`
|
|
10238
|
-
} : primary
|
|
10176
|
+
} : primary;
|
|
10177
|
+
throw new BlumeError(detail);
|
|
10239
10178
|
}
|
|
10240
10179
|
const config = applyDeploymentEnv(parsed.data);
|
|
10241
10180
|
const site = config.deployment.site ?? options.devServerUrl;
|
|
@@ -11894,10 +11833,12 @@ var fetchSpecText = async (spec) => {
|
|
|
11894
11833
|
if ("text" in last) {
|
|
11895
11834
|
return last.text;
|
|
11896
11835
|
}
|
|
11897
|
-
if (!last.retryable
|
|
11898
|
-
|
|
11836
|
+
if (!last.retryable) {
|
|
11837
|
+
break;
|
|
11838
|
+
}
|
|
11839
|
+
if (attempt < MAX_ATTEMPTS - 1) {
|
|
11840
|
+
await sleep(Math.min(last.retryAfter ?? BASE_BACKOFF_MS * 2 ** attempt, MAX_RETRY_WAIT_MS));
|
|
11899
11841
|
}
|
|
11900
|
-
await sleep(Math.min(last.retryAfter ?? BASE_BACKOFF_MS * 2 ** attempt, MAX_RETRY_WAIT_MS));
|
|
11901
11842
|
}
|
|
11902
11843
|
throw last.error;
|
|
11903
11844
|
};
|
|
@@ -12263,6 +12204,10 @@ var filesystemSource = (options) => {
|
|
|
12263
12204
|
};
|
|
12264
12205
|
|
|
12265
12206
|
// src/core/sources/github-releases.ts
|
|
12207
|
+
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
12208
|
+
import { gfmFromMarkdown } from "mdast-util-gfm";
|
|
12209
|
+
import { toString as mdastToString } from "mdast-util-to-string";
|
|
12210
|
+
import { gfm } from "micromark-extension-gfm";
|
|
12266
12211
|
var DEFAULT_BASE_URL = "https://api.github.com";
|
|
12267
12212
|
var DEFAULT_LIMIT = 100;
|
|
12268
12213
|
var PER_PAGE = 100;
|
|
@@ -12271,21 +12216,16 @@ var NON_SLUG3 = /[^a-z0-9]+/gu;
|
|
|
12271
12216
|
var EDGE_DASHES = /^-+|-+$/gu;
|
|
12272
12217
|
var DESCRIPTION_MAX = 160;
|
|
12273
12218
|
var DESCRIPTION_MIN = 110;
|
|
12274
|
-
var
|
|
12275
|
-
var HEADING_LINE = /^#{1,6}\s.*$/gmu;
|
|
12276
|
-
var LIST_MARK = /^\s*(?:[-*+]|\d+[.)])\s+/u;
|
|
12277
|
-
var CHANGESET_HASH = /^[0-9a-f]{7,40}:\s+/u;
|
|
12278
|
-
var IMAGE = /!\[[^\]]*\]\([^)]*\)/gu;
|
|
12279
|
-
var LINK = /\[(?<text>[^\]]*)\]\([^)]*\)/gu;
|
|
12280
|
-
var INLINE_CODE2 = /`(?<code>[^`]+)`/gu;
|
|
12281
|
-
var HTML_OR_JSX = /<\/?[a-zA-Z][^\n<>]*>|<\/?>/gu;
|
|
12282
|
-
var MARKDOWN_PUNCT = /[*_~>]+/gu;
|
|
12219
|
+
var CHANGESET_HASH = /^(?<mark>\s*(?:[-*+]|\d+[.)])\s+)[0-9a-f]{7,40}:\s+/gmu;
|
|
12283
12220
|
var WHITESPACE2 = /\s+/gu;
|
|
12284
12221
|
var TRAILING_FRAGMENT = /[\s,;:.—–-]+$/u;
|
|
12222
|
+
var NON_PROSE = new Set(["code", "heading", "html", "thematicBreak"]);
|
|
12285
12223
|
var releaseDescription = (body) => {
|
|
12286
|
-
const
|
|
12287
|
-
|
|
12288
|
-
|
|
12224
|
+
const tree = fromMarkdown(body.replaceAll(CHANGESET_HASH, "$<mark>"), {
|
|
12225
|
+
extensions: [gfm()],
|
|
12226
|
+
mdastExtensions: [gfmFromMarkdown()]
|
|
12227
|
+
});
|
|
12228
|
+
const text = tree.children.filter((node) => !NON_PROSE.has(node.type)).map((node) => mdastToString(node, { includeHtml: false, includeImageAlt: false })).join(" ").replaceAll(WHITESPACE2, " ").trim();
|
|
12289
12229
|
if (!text) {
|
|
12290
12230
|
return;
|
|
12291
12231
|
}
|
|
@@ -12406,42 +12346,7 @@ var githubReleasesSource = (options, ctx) => {
|
|
|
12406
12346
|
};
|
|
12407
12347
|
|
|
12408
12348
|
// src/core/sources/mdx-remote.ts
|
|
12409
|
-
|
|
12410
|
-
var escapeChar = (char) => REGEX_SPECIAL.test(char) ? `\\${char}` : char;
|
|
12411
|
-
var globToken = (pattern, i) => {
|
|
12412
|
-
const char = pattern[i] ?? "";
|
|
12413
|
-
if (char === "*") {
|
|
12414
|
-
if (pattern[i + 1] === "*") {
|
|
12415
|
-
if (pattern[i + 2] === "/") {
|
|
12416
|
-
return { next: i + 3, source: "(?:.*/)?" };
|
|
12417
|
-
}
|
|
12418
|
-
return { next: i + 2, source: ".*" };
|
|
12419
|
-
}
|
|
12420
|
-
return { next: i + 1, source: "[^/]*" };
|
|
12421
|
-
}
|
|
12422
|
-
if (char === "?") {
|
|
12423
|
-
return { next: i + 1, source: "[^/]" };
|
|
12424
|
-
}
|
|
12425
|
-
if (char === "{") {
|
|
12426
|
-
const end = pattern.indexOf("}", i);
|
|
12427
|
-
if (end !== -1) {
|
|
12428
|
-
const options = pattern.slice(i + 1, end).split(",").map((part) => [...part].map(escapeChar).join("")).join("|");
|
|
12429
|
-
return { next: end + 1, source: `(?:${options})` };
|
|
12430
|
-
}
|
|
12431
|
-
}
|
|
12432
|
-
return { next: i + 1, source: escapeChar(char) };
|
|
12433
|
-
};
|
|
12434
|
-
var globToRegExp = (pattern) => {
|
|
12435
|
-
let source = "";
|
|
12436
|
-
let i = 0;
|
|
12437
|
-
while (i < pattern.length) {
|
|
12438
|
-
const token = globToken(pattern, i);
|
|
12439
|
-
source += token.source;
|
|
12440
|
-
i = token.next;
|
|
12441
|
-
}
|
|
12442
|
-
return new RegExp(`^${source}$`, "u");
|
|
12443
|
-
};
|
|
12444
|
-
var matchesInclude = (ref, patterns) => patterns.some((pattern) => globToRegExp(pattern).test(ref));
|
|
12349
|
+
import picomatch from "picomatch";
|
|
12445
12350
|
var GITHUB_HOSTS = new Set(["api.github.com", "raw.githubusercontent.com"]);
|
|
12446
12351
|
var githubHeaders2 = (url) => {
|
|
12447
12352
|
const token = process.env.GITHUB_TOKEN;
|
|
@@ -12466,12 +12371,13 @@ var enumerateGithub = async (github, include, doFetch) => {
|
|
|
12466
12371
|
}
|
|
12467
12372
|
const body = await res.json();
|
|
12468
12373
|
const prefix = base ? `${base}/` : "";
|
|
12374
|
+
const included = picomatch(include);
|
|
12469
12375
|
const refs = (body.tree ?? []).flatMap((node) => {
|
|
12470
12376
|
if (!(node.type === "blob" && node.path.startsWith(prefix))) {
|
|
12471
12377
|
return [];
|
|
12472
12378
|
}
|
|
12473
12379
|
const rel = node.path.slice(prefix.length);
|
|
12474
|
-
if (!
|
|
12380
|
+
if (!included(rel)) {
|
|
12475
12381
|
return [];
|
|
12476
12382
|
}
|
|
12477
12383
|
return [
|
|
@@ -12503,7 +12409,8 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
12503
12409
|
return await enumerateGithub(options.github, options.include, doFetch);
|
|
12504
12410
|
}
|
|
12505
12411
|
const base = (options.url ?? "").replace(/\/$/u, "");
|
|
12506
|
-
const
|
|
12412
|
+
const included = picomatch(options.include);
|
|
12413
|
+
const refs = (options.files ?? []).flatMap((ref) => included(ref) ? [{ editUrl: `${base}/${ref}`, fetchUrl: `${base}/${ref}`, ref }] : []);
|
|
12507
12414
|
return { refs, truncated: false };
|
|
12508
12415
|
};
|
|
12509
12416
|
const fetchEntry = async (item) => {
|
|
@@ -12662,23 +12569,19 @@ var RATE_LIMITED = 429;
|
|
|
12662
12569
|
var MAX_RETRIES = 4;
|
|
12663
12570
|
var BASE_DELAY_MS = 500;
|
|
12664
12571
|
var SECOND_MS2 = 1000;
|
|
12665
|
-
var withNotionRetry = async (call) => {
|
|
12666
|
-
|
|
12667
|
-
|
|
12668
|
-
|
|
12669
|
-
|
|
12670
|
-
|
|
12671
|
-
|
|
12672
|
-
const { status } = error;
|
|
12673
|
-
if (status !== RATE_LIMITED || attempt === MAX_RETRIES) {
|
|
12674
|
-
throw error;
|
|
12675
|
-
}
|
|
12676
|
-
const retryAfter = Number(error.headers?.["retry-after"]);
|
|
12677
|
-
const wait = retryAfter > 0 ? retryAfter * SECOND_MS2 : BASE_DELAY_MS * 2 ** attempt;
|
|
12678
|
-
await sleep2(wait);
|
|
12572
|
+
var withNotionRetry = async (call, attempt = 0) => {
|
|
12573
|
+
try {
|
|
12574
|
+
return await call();
|
|
12575
|
+
} catch (error) {
|
|
12576
|
+
const { status } = error;
|
|
12577
|
+
if (status !== RATE_LIMITED || attempt === MAX_RETRIES) {
|
|
12578
|
+
throw error;
|
|
12679
12579
|
}
|
|
12580
|
+
const retryAfter = Number(error.headers?.["retry-after"]);
|
|
12581
|
+
const wait = retryAfter > 0 ? retryAfter * SECOND_MS2 : BASE_DELAY_MS * 2 ** attempt;
|
|
12582
|
+
await sleep2(wait);
|
|
12583
|
+
return withNotionRetry(call, attempt + 1);
|
|
12680
12584
|
}
|
|
12681
|
-
throw lastError instanceof Error ? lastError : new Error("Notion request failed after retries.");
|
|
12682
12585
|
};
|
|
12683
12586
|
var collectAll = async (page, cursor, acc = []) => {
|
|
12684
12587
|
const res = await page(cursor);
|
|
@@ -13401,11 +13304,7 @@ var scanProject = async (root, options = {}) => {
|
|
|
13401
13304
|
};
|
|
13402
13305
|
|
|
13403
13306
|
// src/cli/internal-error.ts
|
|
13404
|
-
|
|
13405
|
-
var DIM = `${ESC3}[2m`;
|
|
13406
|
-
var RED = `${ESC3}[31m`;
|
|
13407
|
-
var BOLD = `${ESC3}[1m`;
|
|
13408
|
-
var RESET = `${ESC3}[0m`;
|
|
13307
|
+
import { colors as colors3 } from "consola/utils";
|
|
13409
13308
|
var ISSUES_URL = "https://github.com/haydenbleasel/blume/issues";
|
|
13410
13309
|
var BLUME_FRAME = /(?<abs>(?:\/[^\s()]*\/|[A-Za-z]:\\[^\s()]*\\)\.blume[/\\][^\s()]*)/gu;
|
|
13411
13310
|
var BLUME_MARKER = /[/\\]\.blume[/\\]/u;
|
|
@@ -13416,16 +13315,21 @@ var remapBlumeStack = (stack) => stack.replaceAll(BLUME_FRAME, (match) => {
|
|
|
13416
13315
|
var reportInternalError = (error) => {
|
|
13417
13316
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
13418
13317
|
const lines = [
|
|
13419
|
-
`${
|
|
13318
|
+
`${colors3.red(colors3.bold("BLUME_INTERNAL"))} An unexpected error occurred.`,
|
|
13420
13319
|
` ${err.message}`
|
|
13421
13320
|
];
|
|
13422
13321
|
const stack = remapBlumeStack(err.stack ?? "").split(`
|
|
13423
13322
|
`).slice(1, 5).map((line) => line.trim()).filter(Boolean);
|
|
13424
13323
|
if (stack.length > 0) {
|
|
13425
|
-
lines.push("",
|
|
13426
|
-
`)
|
|
13324
|
+
lines.push("", colors3.dim(stack.join(`
|
|
13325
|
+
`)));
|
|
13427
13326
|
}
|
|
13428
|
-
lines.push("", "This is likely a bug in Blume. Please report it with the details below:",
|
|
13327
|
+
lines.push("", "This is likely a bug in Blume. Please report it with the details below:", colors3.dim([
|
|
13328
|
+
` Blume: ${getBlumeVersion()}`,
|
|
13329
|
+
` Node: ${process.version}`,
|
|
13330
|
+
` Platform: ${process.platform} ${process.arch}`
|
|
13331
|
+
].join(`
|
|
13332
|
+
`)), ` ${ISSUES_URL}`);
|
|
13429
13333
|
process.stderr.write(`${lines.join(`
|
|
13430
13334
|
`)}
|
|
13431
13335
|
`);
|
|
@@ -13581,15 +13485,13 @@ var auditCommand = defineCommand2({
|
|
|
13581
13485
|
|
|
13582
13486
|
// src/cli/commands/build.ts
|
|
13583
13487
|
import { existsSync as existsSync18 } from "node:fs";
|
|
13584
|
-
import { mkdir as
|
|
13488
|
+
import { mkdir as mkdir8, readdir as readdir2, readFile as readFile17, stat as stat3, writeFile as writeFile7 } from "node:fs/promises";
|
|
13585
13489
|
import { build } from "astro";
|
|
13586
13490
|
import { defineCommand as defineCommand3 } from "citty";
|
|
13587
|
-
import { dirname as
|
|
13588
|
-
|
|
13589
|
-
// src/deploy/xml.ts
|
|
13590
|
-
var escapeXml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
13491
|
+
import { dirname as dirname13, join as join30, resolve as resolve10 } from "pathe";
|
|
13591
13492
|
|
|
13592
13493
|
// src/deploy/rss.ts
|
|
13494
|
+
import { escape as escapeXml } from "html-escaper";
|
|
13593
13495
|
var capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);
|
|
13594
13496
|
var pageDate = (page) => {
|
|
13595
13497
|
const raw = page.meta.date ?? page.meta.changelog?.date;
|
|
@@ -13881,6 +13783,7 @@ var readEntryText = async (ctx, page) => {
|
|
|
13881
13783
|
};
|
|
13882
13784
|
|
|
13883
13785
|
// src/ai/component-markdown.ts
|
|
13786
|
+
import { markdownTable } from "markdown-table";
|
|
13884
13787
|
import { mdxToMdast } from "satteri";
|
|
13885
13788
|
|
|
13886
13789
|
// src/components/content/youtube.ts
|
|
@@ -13978,14 +13881,11 @@ var typeTable = ({ children, props }) => {
|
|
|
13978
13881
|
const typeCell = info.typeDescriptionLink ? `[${cellCode(info.type)}](${cellText(info.typeDescriptionLink)})` : cellCode(info.type);
|
|
13979
13882
|
const defaultCell = info.default === undefined ? "-" : cellCode(info.default);
|
|
13980
13883
|
const description = cellText([info.description, info.typeDescription].filter((part) => typeof part === "string" && part !== "").join(" "));
|
|
13981
|
-
return
|
|
13884
|
+
return [prop, typeCell, defaultCell, description];
|
|
13982
13885
|
});
|
|
13983
|
-
const table = rows.length > 0 ? [
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
...rows
|
|
13987
|
-
].join(`
|
|
13988
|
-
`) : "";
|
|
13886
|
+
const table = rows.length > 0 ? markdownTable([["Prop", "Type", "Default", "Description"], ...rows], {
|
|
13887
|
+
alignDelimiters: false
|
|
13888
|
+
}) : "";
|
|
13989
13889
|
return [table, children].filter(Boolean).join(`
|
|
13990
13890
|
|
|
13991
13891
|
`);
|
|
@@ -14944,6 +14844,9 @@ var buildRobots = (project) => {
|
|
|
14944
14844
|
`;
|
|
14945
14845
|
};
|
|
14946
14846
|
|
|
14847
|
+
// src/deploy/sitemap.ts
|
|
14848
|
+
import { escape as escapeXml2 } from "html-escaper";
|
|
14849
|
+
|
|
14947
14850
|
// src/astro/pages.ts
|
|
14948
14851
|
import { extname as extname6, relative as relative12 } from "pathe";
|
|
14949
14852
|
import { glob as glob4, globSync } from "tinyglobby";
|
|
@@ -15039,7 +14942,7 @@ var buildSitemap = (project) => {
|
|
|
15039
14942
|
const seen = new Set;
|
|
15040
14943
|
const urls = [];
|
|
15041
14944
|
const pushUrl = (route, lastModified) => {
|
|
15042
|
-
const loc =
|
|
14945
|
+
const loc = escapeXml2(encodeURI(`${base}${route}`));
|
|
15043
14946
|
if (seen.has(loc)) {
|
|
15044
14947
|
return;
|
|
15045
14948
|
}
|
|
@@ -15193,25 +15096,25 @@ var pageFacets = (page, config) => {
|
|
|
15193
15096
|
};
|
|
15194
15097
|
|
|
15195
15098
|
// src/search/documents.ts
|
|
15196
|
-
var
|
|
15197
|
-
var
|
|
15198
|
-
var
|
|
15199
|
-
var
|
|
15200
|
-
var
|
|
15099
|
+
var CODE_FENCE2 = /```[\s\S]*?```/gu;
|
|
15100
|
+
var INLINE_CODE2 = /`(?<code>[^`]+)`/gu;
|
|
15101
|
+
var HTML_OR_JSX = /<\/?[a-zA-Z][^\n<>]*>|<\/?>/gu;
|
|
15102
|
+
var IMAGE = /!\[[^\]]*\]\([^)]*\)/gu;
|
|
15103
|
+
var LINK = /\[(?<text>[^\]]*)\]\([^)]*\)/gu;
|
|
15201
15104
|
var HEADING_MARK = /^#{1,6}\s+/gmu;
|
|
15202
|
-
var
|
|
15105
|
+
var MARKDOWN_PUNCT = /[*_~>]+/gu;
|
|
15203
15106
|
var WHITESPACE3 = /\s+/gu;
|
|
15204
15107
|
var toPlainText = (markdown) => {
|
|
15205
|
-
const withoutBlocks = markdown.replaceAll(
|
|
15108
|
+
const withoutBlocks = markdown.replaceAll(CODE_FENCE2, " ").replaceAll(IMAGE, " ").replaceAll(LINK, "$<text>");
|
|
15206
15109
|
const pieces = [];
|
|
15207
15110
|
let cursor = 0;
|
|
15208
|
-
for (const match of withoutBlocks.matchAll(
|
|
15111
|
+
for (const match of withoutBlocks.matchAll(INLINE_CODE2)) {
|
|
15209
15112
|
const start = match.index ?? 0;
|
|
15210
|
-
pieces.push(withoutBlocks.slice(cursor, start).replaceAll(
|
|
15113
|
+
pieces.push(withoutBlocks.slice(cursor, start).replaceAll(HTML_OR_JSX, " "), match.groups?.code ?? "");
|
|
15211
15114
|
cursor = start + match[0].length;
|
|
15212
15115
|
}
|
|
15213
|
-
pieces.push(withoutBlocks.slice(cursor).replaceAll(
|
|
15214
|
-
return pieces.join("").replaceAll(HEADING_MARK, "").replaceAll(
|
|
15116
|
+
pieces.push(withoutBlocks.slice(cursor).replaceAll(HTML_OR_JSX, " "));
|
|
15117
|
+
return pieces.join("").replaceAll(HEADING_MARK, "").replaceAll(MARKDOWN_PUNCT, " ").replaceAll(WHITESPACE3, " ").trim();
|
|
15215
15118
|
};
|
|
15216
15119
|
var buildCrumbIndex = (sidebar) => {
|
|
15217
15120
|
const index = new Map;
|
|
@@ -15532,21 +15435,19 @@ var refuseIfDevRunning = (root, action, options = {}) => {
|
|
|
15532
15435
|
|
|
15533
15436
|
// src/astro/generate.ts
|
|
15534
15437
|
import { createHash as createHash3 } from "node:crypto";
|
|
15535
|
-
import { existsSync as existsSync16, readFileSync as
|
|
15438
|
+
import { existsSync as existsSync16, readFileSync as readFileSync8, realpathSync } from "node:fs";
|
|
15536
15439
|
import {
|
|
15537
15440
|
lstat,
|
|
15538
|
-
mkdir as
|
|
15441
|
+
mkdir as mkdir7,
|
|
15539
15442
|
readFile as readFile16,
|
|
15540
15443
|
readlink,
|
|
15541
15444
|
realpath,
|
|
15542
|
-
rename,
|
|
15543
15445
|
rm as rm2,
|
|
15544
|
-
symlink
|
|
15545
|
-
writeFile as writeFile7
|
|
15446
|
+
symlink
|
|
15546
15447
|
} from "node:fs/promises";
|
|
15547
|
-
import { createRequire as
|
|
15548
|
-
import { pathToFileURL as
|
|
15549
|
-
import { basename as basename3, dirname as
|
|
15448
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
15449
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
15450
|
+
import { basename as basename3, dirname as dirname11, join as join28, normalize as normalize3, relative as relative14, resolve as resolve8 } from "pathe";
|
|
15550
15451
|
import { glob as glob7 } from "tinyglobby";
|
|
15551
15452
|
|
|
15552
15453
|
// src/ai/ask-data.ts
|
|
@@ -15941,10 +15842,6 @@ var finalize = (key, group, descriptor, label, identifier, warnings) => {
|
|
|
15941
15842
|
if (client === "only" && source && !source.framework) {
|
|
15942
15843
|
warnings.push(`Override "${key}" uses client: "only" but its framework couldn't be inferred; reference a .tsx/.jsx/.vue/.svelte file.`);
|
|
15943
15844
|
}
|
|
15944
|
-
if (client && !source) {
|
|
15945
|
-
warnings.push(`Override "${key}" declares client: "${client}" but its component couldn't be resolved to a file, so it can't hydrate. Reference it by an imported component or a path string.`);
|
|
15946
|
-
return { identifier, key, source: null };
|
|
15947
|
-
}
|
|
15948
15845
|
if (!client && source?.framework) {
|
|
15949
15846
|
warnings.push(`Override "${key}" points to a ${FRAMEWORK_LABEL[source.framework]} component (${label}) but has no hydration mode, so it renders as static HTML with no interactivity. Add one, e.g. \`${key}: { component: ${JSON.stringify(label)}, client: "load" }\`.`);
|
|
15950
15847
|
}
|
|
@@ -16033,128 +15930,22 @@ var analyzeComponentOverrides = (source, filePath) => {
|
|
|
16033
15930
|
return result;
|
|
16034
15931
|
};
|
|
16035
15932
|
|
|
16036
|
-
// src/core/
|
|
16037
|
-
import {
|
|
16038
|
-
import {
|
|
16039
|
-
import
|
|
16040
|
-
|
|
16041
|
-
|
|
16042
|
-
|
|
16043
|
-
if (inString) {
|
|
16044
|
-
if (char === "\\") {
|
|
16045
|
-
return {
|
|
16046
|
-
append: char + (text2[index + 1] ?? ""),
|
|
16047
|
-
inString: true,
|
|
16048
|
-
next: index + 2
|
|
16049
|
-
};
|
|
16050
|
-
}
|
|
16051
|
-
return { append: char ?? "", inString: char !== '"', next: index + 1 };
|
|
16052
|
-
}
|
|
16053
|
-
if (char === '"') {
|
|
16054
|
-
return { append: char, inString: true, next: index + 1 };
|
|
16055
|
-
}
|
|
16056
|
-
if (char === "/" && text2[index + 1] === "/") {
|
|
16057
|
-
const newline = text2.indexOf(`
|
|
16058
|
-
`, index + 2);
|
|
16059
|
-
return {
|
|
16060
|
-
append: "",
|
|
16061
|
-
inString: false,
|
|
16062
|
-
next: newline === -1 ? text2.length : newline
|
|
16063
|
-
};
|
|
16064
|
-
}
|
|
16065
|
-
if (char === "/" && text2[index + 1] === "*") {
|
|
16066
|
-
const end = text2.indexOf("*/", index + 2);
|
|
16067
|
-
return {
|
|
16068
|
-
append: "",
|
|
16069
|
-
inString: false,
|
|
16070
|
-
next: end === -1 ? text2.length : end + 2
|
|
16071
|
-
};
|
|
16072
|
-
}
|
|
16073
|
-
return { append: char ?? "", inString: false, next: index + 1 };
|
|
16074
|
-
};
|
|
16075
|
-
var stripJsonComments = (text2) => {
|
|
16076
|
-
let out = "";
|
|
16077
|
-
let inString = false;
|
|
16078
|
-
let index = 0;
|
|
16079
|
-
while (index < text2.length) {
|
|
16080
|
-
const {
|
|
16081
|
-
append,
|
|
16082
|
-
inString: nextInString,
|
|
16083
|
-
next
|
|
16084
|
-
} = scanJsonChar(text2, index, inString);
|
|
16085
|
-
out += append;
|
|
16086
|
-
inString = nextInString;
|
|
16087
|
-
index = next;
|
|
16088
|
-
}
|
|
16089
|
-
return out;
|
|
16090
|
-
};
|
|
16091
|
-
var TRAILING_COMMA = /,(?<rest>\s*[}\]])/gu;
|
|
16092
|
-
var parseJsonc = (text2) => {
|
|
16093
|
-
try {
|
|
16094
|
-
const cleaned = stripJsonComments(text2).replaceAll(TRAILING_COMMA, "$<rest>");
|
|
16095
|
-
const value = JSON.parse(cleaned);
|
|
16096
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
16097
|
-
} catch {
|
|
16098
|
-
return null;
|
|
16099
|
-
}
|
|
15933
|
+
// src/core/fs-atomic.ts
|
|
15934
|
+
import { mkdir as mkdir6 } from "node:fs/promises";
|
|
15935
|
+
import { dirname as dirname9 } from "pathe";
|
|
15936
|
+
import writeFileAtomic from "write-file-atomic";
|
|
15937
|
+
var writeTextAtomic = async (path, text2) => {
|
|
15938
|
+
await mkdir6(dirname9(path), { recursive: true });
|
|
15939
|
+
await writeFileAtomic(path, text2, { encoding: "utf-8", fsync: false });
|
|
16100
15940
|
};
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
|
|
16105
|
-
|
|
16106
|
-
|
|
16107
|
-
|
|
16108
|
-
var
|
|
16109
|
-
if (spec.startsWith(".") || isAbsolute7(spec)) {
|
|
16110
|
-
const candidates = spec.endsWith(".json") ? [resolve7(fromDir, spec)] : [
|
|
16111
|
-
resolve7(fromDir, `${spec}.json`),
|
|
16112
|
-
resolve7(fromDir, spec, "tsconfig.json"),
|
|
16113
|
-
resolve7(fromDir, spec)
|
|
16114
|
-
];
|
|
16115
|
-
return candidates.find(isFile) ?? null;
|
|
16116
|
-
}
|
|
16117
|
-
try {
|
|
16118
|
-
const requireFromDir = createRequire3(pathToFileURL2(join22(fromDir, "_.js")).href);
|
|
16119
|
-
for (const sub of [`${spec}/tsconfig.json`, spec]) {
|
|
16120
|
-
try {
|
|
16121
|
-
return requireFromDir.resolve(sub);
|
|
16122
|
-
} catch {}
|
|
16123
|
-
}
|
|
16124
|
-
} catch {}
|
|
16125
|
-
return null;
|
|
16126
|
-
};
|
|
16127
|
-
var loadPaths = (file, seen) => {
|
|
16128
|
-
if (seen.has(file) || !existsSync13(file)) {
|
|
16129
|
-
return null;
|
|
16130
|
-
}
|
|
16131
|
-
seen.add(file);
|
|
16132
|
-
const json = parseJsonc(readFileSync6(file, "utf-8"));
|
|
16133
|
-
if (!json) {
|
|
16134
|
-
return null;
|
|
16135
|
-
}
|
|
16136
|
-
const options = json.compilerOptions ?? {};
|
|
16137
|
-
if (options.paths && typeof options.paths === "object") {
|
|
16138
|
-
const baseUrl = typeof options.baseUrl === "string" ? options.baseUrl : ".";
|
|
16139
|
-
return {
|
|
16140
|
-
baseDir: resolve7(dirname9(file), baseUrl),
|
|
16141
|
-
paths: options.paths
|
|
16142
|
-
};
|
|
16143
|
-
}
|
|
16144
|
-
const bases = Array.isArray(json.extends) ? json.extends : [json.extends].filter(Boolean);
|
|
16145
|
-
for (const base of bases) {
|
|
16146
|
-
if (typeof base !== "string") {
|
|
16147
|
-
continue;
|
|
16148
|
-
}
|
|
16149
|
-
const resolved = resolveExtends(base, dirname9(file));
|
|
16150
|
-
const found = resolved ? loadPaths(resolved, seen) : null;
|
|
16151
|
-
if (found) {
|
|
16152
|
-
return found;
|
|
16153
|
-
}
|
|
16154
|
-
}
|
|
16155
|
-
return null;
|
|
16156
|
-
};
|
|
16157
|
-
var toAlias = (key, value, baseDir) => {
|
|
15941
|
+
|
|
15942
|
+
// src/core/tsconfig-aliases.ts
|
|
15943
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
15944
|
+
import { parseTsconfig } from "get-tsconfig";
|
|
15945
|
+
import { dirname as dirname10, join as join22, resolve as resolve7 } from "pathe";
|
|
15946
|
+
var CONFIG_DIR_TEMPLATE = "${configDir}";
|
|
15947
|
+
var substituteConfigDir = (value, configDir) => value.startsWith(CONFIG_DIR_TEMPLATE) ? join22(configDir, value.slice(CONFIG_DIR_TEMPLATE.length)) : value;
|
|
15948
|
+
var toAlias = (key, value, baseDir, configDir) => {
|
|
16158
15949
|
const first = Array.isArray(value) ? value[0] : value;
|
|
16159
15950
|
if (typeof first !== "string") {
|
|
16160
15951
|
return null;
|
|
@@ -16164,20 +15955,31 @@ var toAlias = (key, value, baseDir) => {
|
|
|
16164
15955
|
if (find === "" || find === "*") {
|
|
16165
15956
|
return null;
|
|
16166
15957
|
}
|
|
16167
|
-
return {
|
|
15958
|
+
return {
|
|
15959
|
+
find,
|
|
15960
|
+
replacement: resolve7(baseDir, substituteConfigDir(target, configDir))
|
|
15961
|
+
};
|
|
16168
15962
|
};
|
|
16169
15963
|
var resolveTsconfigAliases = (root) => {
|
|
16170
15964
|
const entry = ["tsconfig.json", "jsconfig.json"].map((name) => join22(root, name)).find((file) => existsSync13(file));
|
|
16171
15965
|
if (!entry) {
|
|
16172
15966
|
return {};
|
|
16173
15967
|
}
|
|
16174
|
-
|
|
16175
|
-
|
|
15968
|
+
let options;
|
|
15969
|
+
try {
|
|
15970
|
+
options = parseTsconfig(entry).compilerOptions;
|
|
15971
|
+
} catch {
|
|
15972
|
+
return {};
|
|
15973
|
+
}
|
|
15974
|
+
const paths = options?.paths;
|
|
15975
|
+
if (!paths) {
|
|
16176
15976
|
return {};
|
|
16177
15977
|
}
|
|
15978
|
+
const configDir = dirname10(entry);
|
|
15979
|
+
const baseDir = resolve7(configDir, substituteConfigDir(options?.baseUrl ?? ".", configDir));
|
|
16178
15980
|
const aliases = {};
|
|
16179
|
-
for (const [key, value] of Object.entries(
|
|
16180
|
-
const alias = toAlias(key, value,
|
|
15981
|
+
for (const [key, value] of Object.entries(paths)) {
|
|
15982
|
+
const alias = toAlias(key, value, baseDir, configDir);
|
|
16181
15983
|
if (alias) {
|
|
16182
15984
|
aliases[alias.find] = alias.replacement;
|
|
16183
15985
|
}
|
|
@@ -16187,9 +15989,9 @@ var resolveTsconfigAliases = (root) => {
|
|
|
16187
15989
|
|
|
16188
15990
|
// src/og/derive.ts
|
|
16189
15991
|
import { existsSync as existsSync14 } from "node:fs";
|
|
16190
|
-
import { isAbsolute as
|
|
15992
|
+
import { isAbsolute as isAbsolute7, join as join23 } from "pathe";
|
|
16191
15993
|
var CARD_WEIGHTS = [400, 600];
|
|
16192
|
-
var absoluteSrc = (root, src) =>
|
|
15994
|
+
var absoluteSrc = (root, src) => isAbsolute7(src) ? src : join23(root, src);
|
|
16193
15995
|
var googleWeights = (weights) => {
|
|
16194
15996
|
const numbers = weights.filter((weight) => typeof weight === "number");
|
|
16195
15997
|
const used = numbers.filter((weight) => CARD_WEIGHTS.includes(weight));
|
|
@@ -16288,7 +16090,7 @@ var missingFontFiles = (options, root) => {
|
|
|
16288
16090
|
};
|
|
16289
16091
|
|
|
16290
16092
|
// src/og/logo.ts
|
|
16291
|
-
import { existsSync as existsSync15, readFileSync as
|
|
16093
|
+
import { existsSync as existsSync15, readFileSync as readFileSync6 } from "node:fs";
|
|
16292
16094
|
import { join as join24 } from "pathe";
|
|
16293
16095
|
var resolveOgLogo = (project, source) => {
|
|
16294
16096
|
if (!source?.toLowerCase().endsWith(".svg")) {
|
|
@@ -16299,12 +16101,12 @@ var resolveOgLogo = (project, source) => {
|
|
|
16299
16101
|
join24(project.context.root, "public", relative13),
|
|
16300
16102
|
join24(project.context.root, relative13)
|
|
16301
16103
|
].find((path) => existsSync15(path));
|
|
16302
|
-
return file ?
|
|
16104
|
+
return file ? readFileSync6(file, "utf-8") : undefined;
|
|
16303
16105
|
};
|
|
16304
16106
|
|
|
16305
16107
|
// src/openapi/scalar.ts
|
|
16306
16108
|
import { readFile as readFile13 } from "node:fs/promises";
|
|
16307
|
-
import { isAbsolute as
|
|
16109
|
+
import { isAbsolute as isAbsolute8, join as join25 } from "pathe";
|
|
16308
16110
|
|
|
16309
16111
|
// src/theme/palette.ts
|
|
16310
16112
|
var FALLBACK_ACCENT = "oklch(0.62 0.16 250)";
|
|
@@ -16410,7 +16212,7 @@ var specConfiguration = async (spec, root) => {
|
|
|
16410
16212
|
if (URL_SPEC2.test(spec)) {
|
|
16411
16213
|
return { config: { url: spec } };
|
|
16412
16214
|
}
|
|
16413
|
-
const absolute =
|
|
16215
|
+
const absolute = isAbsolute8(spec) ? spec : join25(root, spec);
|
|
16414
16216
|
try {
|
|
16415
16217
|
return { config: { content: await readFile13(absolute, "utf-8") } };
|
|
16416
16218
|
} catch {
|
|
@@ -17242,9 +17044,9 @@ ${options.userCss}
|
|
|
17242
17044
|
`;
|
|
17243
17045
|
|
|
17244
17046
|
// src/theme/twoslash.ts
|
|
17245
|
-
import { readFileSync as
|
|
17246
|
-
import { createRequire as
|
|
17247
|
-
var require2 =
|
|
17047
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
17048
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
17049
|
+
var require2 = createRequire3(import.meta.url);
|
|
17248
17050
|
var OVERRIDES = `
|
|
17249
17051
|
/* Twoslash: theme the rich renderer with Blume tokens. */
|
|
17250
17052
|
:root {
|
|
@@ -17319,7 +17121,7 @@ var OVERRIDES = `
|
|
|
17319
17121
|
`;
|
|
17320
17122
|
var twoslashCss = () => {
|
|
17321
17123
|
const file = require2.resolve("@shikijs/twoslash/style-rich.css");
|
|
17322
|
-
return `${
|
|
17124
|
+
return `${readFileSync7(file, "utf-8")}
|
|
17323
17125
|
${OVERRIDES}`;
|
|
17324
17126
|
};
|
|
17325
17127
|
|
|
@@ -17460,7 +17262,7 @@ var readClientMode = (source, file, warnings) => {
|
|
|
17460
17262
|
};
|
|
17461
17263
|
var discoverIslands = async (root) => {
|
|
17462
17264
|
const dir = join26(root, "islands");
|
|
17463
|
-
const matches2 = await glob5(["
|
|
17265
|
+
const matches2 = await glob5(["**/*"], {
|
|
17464
17266
|
absolute: true,
|
|
17465
17267
|
cwd: dir,
|
|
17466
17268
|
onlyFiles: true
|
|
@@ -17569,7 +17371,7 @@ var exampleMarkdownLookup = (examples) => Object.fromEntries(examples.map((examp
|
|
|
17569
17371
|
var BLUME_SRC = join28(packageRoot(), "src");
|
|
17570
17372
|
var canResolveFrom = (fromDir, spec) => {
|
|
17571
17373
|
try {
|
|
17572
|
-
|
|
17374
|
+
createRequire4(pathToFileURL2(join28(fromDir, "_.js")).href).resolve(spec);
|
|
17573
17375
|
return true;
|
|
17574
17376
|
} catch {
|
|
17575
17377
|
return false;
|
|
@@ -17580,7 +17382,7 @@ var resolveReactCompiler = (config, needsReact, pkgDir = packageRoot()) => {
|
|
|
17580
17382
|
return null;
|
|
17581
17383
|
}
|
|
17582
17384
|
try {
|
|
17583
|
-
return
|
|
17385
|
+
return createRequire4(pathToFileURL2(join28(pkgDir, "_.js")).href).resolve("babel-plugin-react-compiler");
|
|
17584
17386
|
} catch {
|
|
17585
17387
|
return null;
|
|
17586
17388
|
}
|
|
@@ -17603,7 +17405,7 @@ var resolvedAstroHit = (fromDir) => {
|
|
|
17603
17405
|
if (pkg) {
|
|
17604
17406
|
return { modulesDir, pkg };
|
|
17605
17407
|
}
|
|
17606
|
-
const parent =
|
|
17408
|
+
const parent = dirname11(dir);
|
|
17607
17409
|
if (parent === dir) {
|
|
17608
17410
|
return null;
|
|
17609
17411
|
}
|
|
@@ -17619,7 +17421,7 @@ var sameRealDir = (a, b) => {
|
|
|
17619
17421
|
};
|
|
17620
17422
|
var depsCandidates = (pkgDir) => [
|
|
17621
17423
|
join28(pkgDir, "node_modules"),
|
|
17622
|
-
|
|
17424
|
+
dirname11(pkgDir)
|
|
17623
17425
|
];
|
|
17624
17426
|
var candidateHolding = (pkgDir, ...segments) => depsCandidates(pkgDir).find((dir) => existsSync16(join28(dir, ...segments))) ?? null;
|
|
17625
17427
|
var linkDepsJunction = async (link, depsDir) => {
|
|
@@ -17634,13 +17436,13 @@ var linkDepsJunction = async (link, depsDir) => {
|
|
|
17634
17436
|
return;
|
|
17635
17437
|
}
|
|
17636
17438
|
try {
|
|
17637
|
-
if (resolve8(
|
|
17439
|
+
if (resolve8(dirname11(link), await readlink(link)) === resolve8(depsDir)) {
|
|
17638
17440
|
return;
|
|
17639
17441
|
}
|
|
17640
17442
|
} catch {}
|
|
17641
17443
|
await rm2(link, { force: true });
|
|
17642
17444
|
}
|
|
17643
|
-
await
|
|
17445
|
+
await mkdir7(dirname11(link), { recursive: true });
|
|
17644
17446
|
await symlink(depsDir, link, "junction");
|
|
17645
17447
|
};
|
|
17646
17448
|
var readPkgVersion = (pkgJsonPath) => {
|
|
@@ -17648,7 +17450,7 @@ var readPkgVersion = (pkgJsonPath) => {
|
|
|
17648
17450
|
return null;
|
|
17649
17451
|
}
|
|
17650
17452
|
try {
|
|
17651
|
-
return JSON.parse(
|
|
17453
|
+
return JSON.parse(readFileSync8(pkgJsonPath, "utf-8")).version ?? null;
|
|
17652
17454
|
} catch {
|
|
17653
17455
|
return null;
|
|
17654
17456
|
}
|
|
@@ -17797,15 +17599,7 @@ var writeIfChanged = async (path, content) => {
|
|
|
17797
17599
|
if (existing === content) {
|
|
17798
17600
|
return false;
|
|
17799
17601
|
}
|
|
17800
|
-
await
|
|
17801
|
-
const tmp = `${path}.${process.pid}.tmp`;
|
|
17802
|
-
await writeFile7(tmp, content, "utf-8");
|
|
17803
|
-
try {
|
|
17804
|
-
await rename(tmp, path);
|
|
17805
|
-
} catch (error) {
|
|
17806
|
-
await rm2(tmp, { force: true });
|
|
17807
|
-
throw error;
|
|
17808
|
-
}
|
|
17602
|
+
await writeTextAtomic(path, content);
|
|
17809
17603
|
return true;
|
|
17810
17604
|
};
|
|
17811
17605
|
var pruneOrphans = async (srcDir, written) => {
|
|
@@ -17874,7 +17668,7 @@ var readLogoSvg = (project, source) => {
|
|
|
17874
17668
|
join28(project.context.root, "public", rel),
|
|
17875
17669
|
join28(project.context.root, rel)
|
|
17876
17670
|
].find((path) => existsSync16(path));
|
|
17877
|
-
return file ?
|
|
17671
|
+
return file ? readFileSync8(file, "utf-8") : undefined;
|
|
17878
17672
|
};
|
|
17879
17673
|
var resolveLogo = (project) => {
|
|
17880
17674
|
const { logo } = project.config;
|
|
@@ -17917,7 +17711,7 @@ var faviconType = (name) => {
|
|
|
17917
17711
|
const ext = name.split(".").pop()?.toLowerCase();
|
|
17918
17712
|
return ext ? FAVICON_TYPES[ext] : undefined;
|
|
17919
17713
|
};
|
|
17920
|
-
var inlineDataUri = (file, type) => `data:${type};base64,${
|
|
17714
|
+
var inlineDataUri = (file, type) => `data:${type};base64,${readFileSync8(file).toString("base64")}`;
|
|
17921
17715
|
var defaultFavicon = () => ({
|
|
17922
17716
|
href: inlineDataUri(join28(BLUME_SRC, "assets", "icon.png"), "image/png"),
|
|
17923
17717
|
type: "image/png"
|
|
@@ -18441,44 +18235,9 @@ var generateRuntime = async (project) => {
|
|
|
18441
18235
|
};
|
|
18442
18236
|
|
|
18443
18237
|
// src/cli/env.ts
|
|
18444
|
-
import { existsSync as existsSync17, readFileSync as
|
|
18445
|
-
import {
|
|
18446
|
-
|
|
18447
|
-
var DOUBLE_QUOTED2 = /^"(?<body>[\s\S]*)"$/u;
|
|
18448
|
-
var SINGLE_QUOTED = /^'(?<body>[\s\S]*)'$/u;
|
|
18449
|
-
var ESCAPE = /\\(?<char>[\\nt"])/gu;
|
|
18450
|
-
var UNESCAPED = {
|
|
18451
|
-
'"': '"',
|
|
18452
|
-
"\\": "\\",
|
|
18453
|
-
n: `
|
|
18454
|
-
`,
|
|
18455
|
-
t: "\t"
|
|
18456
|
-
};
|
|
18457
|
-
var unquote = (raw) => {
|
|
18458
|
-
const double = raw.match(DOUBLE_QUOTED2)?.groups?.body;
|
|
18459
|
-
if (double !== undefined) {
|
|
18460
|
-
return double.replaceAll(ESCAPE, (match, char) => UNESCAPED[char] ?? match);
|
|
18461
|
-
}
|
|
18462
|
-
const single = raw.match(SINGLE_QUOTED)?.groups?.body;
|
|
18463
|
-
if (single !== undefined) {
|
|
18464
|
-
return single;
|
|
18465
|
-
}
|
|
18466
|
-
const hash = raw.indexOf("#");
|
|
18467
|
-
return (hash === -1 ? raw : raw.slice(0, hash)).trim();
|
|
18468
|
-
};
|
|
18469
|
-
var parseEnv = (content) => {
|
|
18470
|
-
const env = {};
|
|
18471
|
-
for (const line of content.split(/\r?\n/u)) {
|
|
18472
|
-
if (line.trim() === "" || line.trimStart().startsWith("#")) {
|
|
18473
|
-
continue;
|
|
18474
|
-
}
|
|
18475
|
-
const groups = line.match(ENV_LINE)?.groups;
|
|
18476
|
-
if (groups?.key !== undefined && groups.value !== undefined) {
|
|
18477
|
-
env[groups.key] = unquote(groups.value);
|
|
18478
|
-
}
|
|
18479
|
-
}
|
|
18480
|
-
return env;
|
|
18481
|
-
};
|
|
18238
|
+
import { existsSync as existsSync17, readFileSync as readFileSync9 } from "node:fs";
|
|
18239
|
+
import { parse as parse2 } from "dotenv";
|
|
18240
|
+
import { dirname as dirname12, join as join29, resolve as resolve9 } from "pathe";
|
|
18482
18241
|
var applyEnv = (parsed) => {
|
|
18483
18242
|
for (const [key, value] of Object.entries(parsed)) {
|
|
18484
18243
|
if (!(key in process.env)) {
|
|
@@ -18489,7 +18248,7 @@ var applyEnv = (parsed) => {
|
|
|
18489
18248
|
var loadFile = (path) => {
|
|
18490
18249
|
try {
|
|
18491
18250
|
if (existsSync17(path)) {
|
|
18492
|
-
applyEnv(
|
|
18251
|
+
applyEnv(parse2(readFileSync9(path, "utf-8")));
|
|
18493
18252
|
}
|
|
18494
18253
|
} catch {}
|
|
18495
18254
|
};
|
|
@@ -18499,7 +18258,7 @@ var loadEnvFiles = (startDir) => {
|
|
|
18499
18258
|
while (!done) {
|
|
18500
18259
|
loadFile(join29(dir, ".env.local"));
|
|
18501
18260
|
loadFile(join29(dir, ".env"));
|
|
18502
|
-
const parent =
|
|
18261
|
+
const parent = dirname12(dir);
|
|
18503
18262
|
done = existsSync17(join29(dir, ".git")) || parent === dir;
|
|
18504
18263
|
dir = parent;
|
|
18505
18264
|
}
|
|
@@ -18605,12 +18364,12 @@ var emitRedirectFiles = async (config, distDir) => {
|
|
|
18605
18364
|
if (redirects.length === 0 || config.deployment.output !== "static") {
|
|
18606
18365
|
return;
|
|
18607
18366
|
}
|
|
18608
|
-
await
|
|
18367
|
+
await writeFile7(join30(distDir, "blume-redirects.json"), buildRedirectManifest(redirects), "utf-8");
|
|
18609
18368
|
const platformFiles = [
|
|
18610
18369
|
{ content: buildNetlifyRedirects(redirects), name: "_redirects" },
|
|
18611
18370
|
{ content: buildVercelConfig(redirects), name: "vercel.json" }
|
|
18612
18371
|
];
|
|
18613
|
-
await Promise.all(platformFiles.map((file) => existsSync18(join30(distDir, file.name)) ? Promise.resolve() :
|
|
18372
|
+
await Promise.all(platformFiles.map((file) => existsSync18(join30(distDir, file.name)) ? Promise.resolve() : writeFile7(join30(distDir, file.name), file.content, "utf-8")));
|
|
18614
18373
|
logger.success(`Emitted redirect files for ${redirects.length} redirect(s)`);
|
|
18615
18374
|
};
|
|
18616
18375
|
var emitHeaderFiles = async (project, distDir) => {
|
|
@@ -18621,7 +18380,7 @@ var emitHeaderFiles = async (project, distDir) => {
|
|
|
18621
18380
|
const ours = buildNetlifyHeaders(config, buildHomeLinkHeader(config, markdownRoutePaths(project)));
|
|
18622
18381
|
const target = join30(distDir, "_headers");
|
|
18623
18382
|
const existing = existsSync18(target) ? await readFile17(target, "utf-8") : "";
|
|
18624
|
-
await
|
|
18383
|
+
await writeFile7(target, existing ? `${existing.trimEnd()}
|
|
18625
18384
|
${ours}` : ours, "utf-8");
|
|
18626
18385
|
logger.success("Emitted _headers (UTF-8 Content-Type + homepage Link header)");
|
|
18627
18386
|
};
|
|
@@ -18649,10 +18408,10 @@ var emitAgentSkills = async (project, distDir) => {
|
|
|
18649
18408
|
}
|
|
18650
18409
|
await Promise.all(skills.map(async (skill) => {
|
|
18651
18410
|
const target = join30(outDir, skill.path);
|
|
18652
|
-
await
|
|
18653
|
-
await
|
|
18411
|
+
await mkdir8(dirname13(target), { recursive: true });
|
|
18412
|
+
await writeFile7(target, skill.content);
|
|
18654
18413
|
}));
|
|
18655
|
-
await
|
|
18414
|
+
await writeFile7(join30(outDir, "index.json"), buildSkillsIndex(skills, project.config), "utf-8");
|
|
18656
18415
|
logger.success(`Published ${skills.length} agent skill(s) (.well-known/agent-skills/index.json)`);
|
|
18657
18416
|
};
|
|
18658
18417
|
var emitWellKnownFiles = async (config, distDir) => {
|
|
@@ -18673,8 +18432,8 @@ var emitWellKnownFiles = async (config, distDir) => {
|
|
|
18673
18432
|
if (!file.content || existsSync18(target)) {
|
|
18674
18433
|
continue;
|
|
18675
18434
|
}
|
|
18676
|
-
await
|
|
18677
|
-
await
|
|
18435
|
+
await mkdir8(join30(distDir, ".well-known"), { recursive: true });
|
|
18436
|
+
await writeFile7(target, file.content, "utf-8");
|
|
18678
18437
|
logger.success(`Generated ${file.path.slice(1)} (${file.label})`);
|
|
18679
18438
|
}
|
|
18680
18439
|
};
|
|
@@ -18695,7 +18454,7 @@ var emitVercelNegotiation = async (project, routePaths, root) => {
|
|
|
18695
18454
|
logger.warn("Could not wire Accept: text/markdown negotiation into .vercel/output/config.json — raw Markdown stays available at the .md URLs.");
|
|
18696
18455
|
return;
|
|
18697
18456
|
}
|
|
18698
|
-
await
|
|
18457
|
+
await writeFile7(configPath, injected, "utf-8");
|
|
18699
18458
|
logger.success("Wired Accept: text/markdown negotiation into the Vercel routing config");
|
|
18700
18459
|
};
|
|
18701
18460
|
var warnCloudflareNegotiationSkipped = () => logger.warn("Could not wire Accept: text/markdown negotiation into dist/server/wrangler.json — raw Markdown stays available at the .md URLs.");
|
|
@@ -18721,8 +18480,8 @@ var emitCloudflareNegotiation = async (project, routePaths) => {
|
|
|
18721
18480
|
warnCloudflareNegotiationSkipped();
|
|
18722
18481
|
return;
|
|
18723
18482
|
}
|
|
18724
|
-
await
|
|
18725
|
-
await
|
|
18483
|
+
await writeFile7(join30(serverDir, NEGOTIATION_WORKER_FILE), injected.worker, "utf-8");
|
|
18484
|
+
await writeFile7(wranglerPath, injected.wrangler, "utf-8");
|
|
18726
18485
|
logger.success("Wired Accept: text/markdown negotiation into the Cloudflare Worker");
|
|
18727
18486
|
};
|
|
18728
18487
|
var formatBytes2 = (bytes) => {
|
|
@@ -18819,10 +18578,10 @@ var publishLlmsFiles = async (project, distDir) => {
|
|
|
18819
18578
|
const { index, full } = await buildLlmsFiles(project);
|
|
18820
18579
|
const writes = [];
|
|
18821
18580
|
if (writeIndex) {
|
|
18822
|
-
writes.push(
|
|
18581
|
+
writes.push(writeFile7(indexPath, index, "utf-8"));
|
|
18823
18582
|
}
|
|
18824
18583
|
if (writeFull) {
|
|
18825
|
-
writes.push(
|
|
18584
|
+
writes.push(writeFile7(fullPath, full, "utf-8"));
|
|
18826
18585
|
}
|
|
18827
18586
|
await Promise.all(writes);
|
|
18828
18587
|
logger.success(`Generated ${[
|
|
@@ -18846,17 +18605,17 @@ var publishBuildArtifacts = async (project, distDir, args) => {
|
|
|
18846
18605
|
}
|
|
18847
18606
|
const sitemap = buildSitemap(project);
|
|
18848
18607
|
if (sitemap && !existsSync18(join30(distDir, "sitemap.xml"))) {
|
|
18849
|
-
await
|
|
18608
|
+
await writeFile7(join30(distDir, "sitemap.xml"), sitemap, "utf-8");
|
|
18850
18609
|
logger.success("Generated sitemap.xml");
|
|
18851
18610
|
}
|
|
18852
18611
|
const robots = buildRobots(project);
|
|
18853
18612
|
if (robots && !existsSync18(join30(distDir, "robots.txt"))) {
|
|
18854
|
-
await
|
|
18613
|
+
await writeFile7(join30(distDir, "robots.txt"), robots, "utf-8");
|
|
18855
18614
|
logger.success("Generated robots.txt");
|
|
18856
18615
|
}
|
|
18857
18616
|
const agentReadability = buildAgentReadability(project);
|
|
18858
18617
|
if (agentReadability && !existsSync18(join30(distDir, "agent-readability.json"))) {
|
|
18859
|
-
await
|
|
18618
|
+
await writeFile7(join30(distDir, "agent-readability.json"), `${JSON.stringify(agentReadability, null, 2)}
|
|
18860
18619
|
`, "utf-8");
|
|
18861
18620
|
logger.success("Generated agent-readability.json");
|
|
18862
18621
|
}
|
|
@@ -19046,10 +18805,9 @@ var checkCommand = defineCommand4({
|
|
|
19046
18805
|
});
|
|
19047
18806
|
|
|
19048
18807
|
// src/cli/commands/dev.ts
|
|
19049
|
-
import { watch } from "node:fs";
|
|
19050
18808
|
import { dev } from "astro";
|
|
18809
|
+
import { watch } from "chokidar";
|
|
19051
18810
|
import { defineCommand as defineCommand5 } from "citty";
|
|
19052
|
-
import { basename as basename4, dirname as dirname13 } from "pathe";
|
|
19053
18811
|
|
|
19054
18812
|
// src/astro/integration.ts
|
|
19055
18813
|
var overlayServer = null;
|
|
@@ -19234,21 +18992,12 @@ var devCommand = defineCommand5({
|
|
|
19234
18992
|
project.context.themeFile,
|
|
19235
18993
|
project.context.componentsFile
|
|
19236
18994
|
].filter((target) => target !== null);
|
|
18995
|
+
const projectWatcher = watch([...dirTargets, ...fileTargets], {
|
|
18996
|
+
ignoreInitial: true
|
|
18997
|
+
}).on("all", regenerate);
|
|
19237
18998
|
const disposers = [
|
|
19238
18999
|
...project.sources.map((source) => source.watch?.(regenerate)),
|
|
19239
|
-
|
|
19240
|
-
const watcher = watch(target, { recursive: true }, regenerate);
|
|
19241
|
-
return () => watcher.close();
|
|
19242
|
-
}),
|
|
19243
|
-
...fileTargets.map((target) => {
|
|
19244
|
-
const name = basename4(target);
|
|
19245
|
-
const watcher = watch(dirname13(target), (_event, filename) => {
|
|
19246
|
-
if (!filename || filename === name) {
|
|
19247
|
-
regenerate();
|
|
19248
|
-
}
|
|
19249
|
-
});
|
|
19250
|
-
return () => watcher.close();
|
|
19251
|
-
})
|
|
19000
|
+
() => void projectWatcher.close()
|
|
19252
19001
|
].filter((dispose) => dispose !== undefined);
|
|
19253
19002
|
const shutdown = async () => {
|
|
19254
19003
|
for (const dispose of disposers) {
|
|
@@ -19264,30 +19013,18 @@ var devCommand = defineCommand5({
|
|
|
19264
19013
|
});
|
|
19265
19014
|
|
|
19266
19015
|
// src/cli/commands/doctor.ts
|
|
19267
|
-
import { readFileSync as
|
|
19016
|
+
import { readFileSync as readFileSync10 } from "node:fs";
|
|
19268
19017
|
import { defineCommand as defineCommand6 } from "citty";
|
|
19269
19018
|
import { join as join32 } from "pathe";
|
|
19270
|
-
|
|
19271
|
-
var
|
|
19272
|
-
var
|
|
19019
|
+
import { satisfies } from "semver";
|
|
19020
|
+
var FALLBACK_NODE_RANGE = ">=22.12.0";
|
|
19021
|
+
var supportedNodeRange = () => {
|
|
19273
19022
|
try {
|
|
19274
|
-
const pkg = JSON.parse(
|
|
19275
|
-
|
|
19276
|
-
return range.replace(LEADING_RANGE, "") || FALLBACK_MIN_NODE;
|
|
19023
|
+
const pkg = JSON.parse(readFileSync10(join32(packageRoot(), "package.json"), "utf-8"));
|
|
19024
|
+
return pkg.engines?.node || FALLBACK_NODE_RANGE;
|
|
19277
19025
|
} catch {
|
|
19278
|
-
return
|
|
19279
|
-
}
|
|
19280
|
-
};
|
|
19281
|
-
var versionBelow = (current, minimum) => {
|
|
19282
|
-
const a = current.split(".").map((part) => Math.trunc(Number(part)));
|
|
19283
|
-
const b = minimum.split(".").map((part) => Math.trunc(Number(part)));
|
|
19284
|
-
for (let i = 0;i < 3; i += 1) {
|
|
19285
|
-
const delta = (a[i] ?? 0) - (b[i] ?? 0);
|
|
19286
|
-
if (delta !== 0) {
|
|
19287
|
-
return delta < 0;
|
|
19288
|
-
}
|
|
19026
|
+
return FALLBACK_NODE_RANGE;
|
|
19289
19027
|
}
|
|
19290
|
-
return false;
|
|
19291
19028
|
};
|
|
19292
19029
|
var doctorCommand = defineCommand6({
|
|
19293
19030
|
args: {
|
|
@@ -19303,11 +19040,11 @@ var doctorCommand = defineCommand6({
|
|
|
19303
19040
|
async run({ args }) {
|
|
19304
19041
|
const root = process.cwd();
|
|
19305
19042
|
const diagnostics = [];
|
|
19306
|
-
const
|
|
19307
|
-
if (
|
|
19043
|
+
const nodeRange = supportedNodeRange();
|
|
19044
|
+
if (!satisfies(process.versions.node, nodeRange)) {
|
|
19308
19045
|
diagnostics.push({
|
|
19309
19046
|
code: "BLUME_NODE_VERSION",
|
|
19310
|
-
message: `Node ${process.versions.node} is
|
|
19047
|
+
message: `Node ${process.versions.node} is outside the supported range (${nodeRange}).`,
|
|
19311
19048
|
severity: "warning"
|
|
19312
19049
|
});
|
|
19313
19050
|
}
|
|
@@ -19368,7 +19105,7 @@ import { relative as relative17 } from "pathe";
|
|
|
19368
19105
|
|
|
19369
19106
|
// src/registry/eject.ts
|
|
19370
19107
|
import { existsSync as existsSync20 } from "node:fs";
|
|
19371
|
-
import { cp as cp2, mkdir as
|
|
19108
|
+
import { cp as cp2, mkdir as mkdir9, readFile as readFile18, rm as rm3, writeFile as writeFile8 } from "node:fs/promises";
|
|
19372
19109
|
import { join as join33, relative as relative15 } from "pathe";
|
|
19373
19110
|
var toPosix = (path) => path.split("\\").join("/");
|
|
19374
19111
|
var LOCAL_BLUME_SOURCE = "../../node_modules/blume/src/**/*.{astro,ts,tsx}";
|
|
@@ -19715,8 +19452,8 @@ var eject = async (root) => {
|
|
|
19715
19452
|
}
|
|
19716
19453
|
const written = files.filter((file) => !(file.skipIfExists && existsSync20(file.path)));
|
|
19717
19454
|
await Promise.all(written.map(async (file) => {
|
|
19718
|
-
await
|
|
19719
|
-
await
|
|
19455
|
+
await mkdir9(join33(file.path, ".."), { recursive: true });
|
|
19456
|
+
await writeFile8(file.path, file.content, "utf-8");
|
|
19720
19457
|
}));
|
|
19721
19458
|
const assetsSrc = join33(context.outDir, "public", "blume-assets");
|
|
19722
19459
|
if (existsSync20(assetsSrc)) {
|
|
@@ -19729,7 +19466,7 @@ var eject = async (root) => {
|
|
|
19729
19466
|
};
|
|
19730
19467
|
|
|
19731
19468
|
// src/cli/eject-scripts.ts
|
|
19732
|
-
import { readFile as readFile19, writeFile as
|
|
19469
|
+
import { readFile as readFile19, writeFile as writeFile9 } from "node:fs/promises";
|
|
19733
19470
|
import { join as join34 } from "pathe";
|
|
19734
19471
|
var droppedArtifactNotices = (config) => {
|
|
19735
19472
|
const notices = [];
|
|
@@ -19771,14 +19508,14 @@ var updatePackageScripts = async (root) => {
|
|
|
19771
19508
|
dev: "astro dev",
|
|
19772
19509
|
preview: "astro preview"
|
|
19773
19510
|
};
|
|
19774
|
-
await
|
|
19511
|
+
await writeFile9(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
19775
19512
|
`, "utf-8");
|
|
19776
19513
|
};
|
|
19777
19514
|
|
|
19778
19515
|
// src/cli/init/scaffold.ts
|
|
19779
19516
|
import { existsSync as existsSync21 } from "node:fs";
|
|
19780
|
-
import { mkdir as
|
|
19781
|
-
import { basename as
|
|
19517
|
+
import { mkdir as mkdir10, writeFile as writeFile10 } from "node:fs/promises";
|
|
19518
|
+
import { basename as basename4, dirname as dirname14, isAbsolute as isAbsolute9, join as join35, relative as relative16 } from "pathe";
|
|
19782
19519
|
|
|
19783
19520
|
// src/core/package-json.ts
|
|
19784
19521
|
var toPackageName = (raw) => raw.toLowerCase().replaceAll(/[^a-z0-9._-]+/gu, "-").replaceAll(/^[-_.]+|[-_.]+$/gu, "") || "docs";
|
|
@@ -19906,34 +19643,35 @@ var detectPackageManager = (userAgent) => {
|
|
|
19906
19643
|
const name = userAgent?.split("/")[0];
|
|
19907
19644
|
return name !== undefined && PACKAGE_MANAGERS.includes(name) ? name : "npm";
|
|
19908
19645
|
};
|
|
19909
|
-
var validateContentDir = (root, dir) =>
|
|
19646
|
+
var validateContentDir = (root, dir) => isAbsolute9(dir) || relative16(root, join35(root, dir)).startsWith("..") ? "Must be a relative path inside the project." : undefined;
|
|
19910
19647
|
var titleize = (raw) => {
|
|
19911
19648
|
const words = raw.replaceAll(/[-_.]+/gu, " ").split(/\s+/u).filter(Boolean);
|
|
19912
19649
|
return words.length === 0 ? "My Docs" : words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
19913
19650
|
};
|
|
19914
19651
|
var hasRemoteSource = (sources) => sources.some((source) => source !== "filesystem");
|
|
19915
|
-
var
|
|
19916
|
-
|
|
19917
|
-
case "github-releases": {
|
|
19918
|
-
return ` // Changelog entries from GitHub Releases. Private repos read
|
|
19652
|
+
var SOURCE_SNIPPETS = {
|
|
19653
|
+
"github-releases": ` // Changelog entries from GitHub Releases. Private repos read
|
|
19919
19654
|
// GITHUB_TOKEN from the environment.
|
|
19920
19655
|
{
|
|
19921
19656
|
type: "github-releases",
|
|
19922
19657
|
owner: "your-org",
|
|
19923
19658
|
repo: "your-repo",
|
|
19924
19659
|
prefix: "changelog",
|
|
19925
|
-
}
|
|
19926
|
-
|
|
19927
|
-
|
|
19928
|
-
|
|
19660
|
+
},`,
|
|
19661
|
+
"mdx-remote": ` // MDX fetched from a GitHub repo. Private repos read GITHUB_TOKEN
|
|
19662
|
+
// from the environment.
|
|
19663
|
+
{
|
|
19664
|
+
type: "mdx-remote",
|
|
19665
|
+
github: { owner: "your-org", repo: "your-repo", path: "docs" },
|
|
19666
|
+
prefix: "remote",
|
|
19667
|
+
},`,
|
|
19668
|
+
notion: ` // Pages from a Notion database. Reads NOTION_TOKEN from the environment.
|
|
19929
19669
|
{
|
|
19930
19670
|
type: "notion",
|
|
19931
19671
|
database: "your-database-id",
|
|
19932
19672
|
prefix: "notion",
|
|
19933
|
-
}
|
|
19934
|
-
|
|
19935
|
-
case "sanity": {
|
|
19936
|
-
return ` // Documents from a Sanity dataset. Private datasets read SANITY_TOKEN
|
|
19673
|
+
},`,
|
|
19674
|
+
sanity: ` // Documents from a Sanity dataset. Private datasets read SANITY_TOKEN
|
|
19937
19675
|
// from the environment.
|
|
19938
19676
|
{
|
|
19939
19677
|
type: "sanity",
|
|
@@ -19941,21 +19679,7 @@ var sourceSnippetFor = (kind) => {
|
|
|
19941
19679
|
dataset: "production",
|
|
19942
19680
|
query: \`*[_type == "doc"]\`,
|
|
19943
19681
|
prefix: "sanity",
|
|
19944
|
-
}
|
|
19945
|
-
}
|
|
19946
|
-
case "mdx-remote": {
|
|
19947
|
-
return ` // MDX fetched from a GitHub repo. Private repos read GITHUB_TOKEN
|
|
19948
|
-
// from the environment.
|
|
19949
|
-
{
|
|
19950
|
-
type: "mdx-remote",
|
|
19951
|
-
github: { owner: "your-org", repo: "your-repo", path: "docs" },
|
|
19952
|
-
prefix: "remote",
|
|
19953
|
-
},`;
|
|
19954
|
-
}
|
|
19955
|
-
default: {
|
|
19956
|
-
return kind;
|
|
19957
|
-
}
|
|
19958
|
-
}
|
|
19682
|
+
},`
|
|
19959
19683
|
};
|
|
19960
19684
|
var contentBlockFor = (answers) => {
|
|
19961
19685
|
const sources = answers.sources.length === 0 ? ["filesystem"] : answers.sources;
|
|
@@ -19965,7 +19689,7 @@ var contentBlockFor = (answers) => {
|
|
|
19965
19689
|
root: ${JSON.stringify(answers.contentDir)},
|
|
19966
19690
|
},`;
|
|
19967
19691
|
}
|
|
19968
|
-
const entries = SOURCE_KINDS.filter((kind) => sources.includes(kind)).map((kind) => kind === "filesystem" ? ` { type: "filesystem", root: ${JSON.stringify(answers.contentDir)} },` :
|
|
19692
|
+
const entries = SOURCE_KINDS.filter((kind) => sources.includes(kind)).map((kind) => kind === "filesystem" ? ` { type: "filesystem", root: ${JSON.stringify(answers.contentDir)} },` : SOURCE_SNIPPETS[kind]);
|
|
19969
19693
|
return `
|
|
19970
19694
|
content: {
|
|
19971
19695
|
sources: [
|
|
@@ -19988,7 +19712,7 @@ var extraDepsFor = (sources) => ({
|
|
|
19988
19712
|
var buildPlan = (root, answers) => {
|
|
19989
19713
|
const files = [
|
|
19990
19714
|
{
|
|
19991
|
-
content: blumePackageJson(toPackageName(
|
|
19715
|
+
content: blumePackageJson(toPackageName(basename4(root)), extraDepsFor(answers.sources)),
|
|
19992
19716
|
path: join35(root, "package.json")
|
|
19993
19717
|
},
|
|
19994
19718
|
{ content: buildConfig(answers), path: join35(root, "blume.config.ts") }
|
|
@@ -20003,14 +19727,14 @@ var writeFileSafe = async (file, log) => {
|
|
|
20003
19727
|
log.info(`Skipped existing ${file.path}`);
|
|
20004
19728
|
return false;
|
|
20005
19729
|
}
|
|
20006
|
-
await
|
|
20007
|
-
await
|
|
19730
|
+
await mkdir10(dirname14(file.path), { recursive: true });
|
|
19731
|
+
await writeFile10(file.path, file.content, "utf-8");
|
|
20008
19732
|
log.success(`Created ${file.path}`);
|
|
20009
19733
|
return true;
|
|
20010
19734
|
};
|
|
20011
19735
|
var applyPlan = async (files, log) => {
|
|
20012
19736
|
const created = await Promise.all(files.map((file) => writeFileSafe(file, log)));
|
|
20013
|
-
const createdPackage = files.some((file, index) => created[index] &&
|
|
19737
|
+
const createdPackage = files.some((file, index) => created[index] && basename4(file.path) === "package.json");
|
|
20014
19738
|
return { createdPackage };
|
|
20015
19739
|
};
|
|
20016
19740
|
var envVarsFor = (sources) => [
|
|
@@ -20164,19 +19888,10 @@ Rules:
|
|
|
20164
19888
|
When you are done, print the file and suggest running \`blume eval\` to try it.`;
|
|
20165
19889
|
|
|
20166
19890
|
// src/eval/report.ts
|
|
20167
|
-
import { mkdtemp as mkdtemp2, writeFile as
|
|
19891
|
+
import { mkdtemp as mkdtemp2, writeFile as writeFile11 } from "node:fs/promises";
|
|
20168
19892
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
19893
|
+
import { colors as colors4 } from "consola/utils";
|
|
20169
19894
|
import { join as join36, relative as relative18 } from "pathe";
|
|
20170
|
-
var ESC4 = String.fromCodePoint(27);
|
|
20171
|
-
var COLORS3 = {
|
|
20172
|
-
bold: `${ESC4}[1m`,
|
|
20173
|
-
cyan: `${ESC4}[36m`,
|
|
20174
|
-
dim: `${ESC4}[2m`,
|
|
20175
|
-
green: `${ESC4}[32m`,
|
|
20176
|
-
red: `${ESC4}[31m`,
|
|
20177
|
-
reset: `${ESC4}[0m`,
|
|
20178
|
-
yellow: `${ESC4}[33m`
|
|
20179
|
-
};
|
|
20180
19895
|
var GLYPH2 = {
|
|
20181
19896
|
error: "!",
|
|
20182
19897
|
fail: "✖",
|
|
@@ -20184,10 +19899,10 @@ var GLYPH2 = {
|
|
|
20184
19899
|
skip: "⊘"
|
|
20185
19900
|
};
|
|
20186
19901
|
var STATUS_COLOR = {
|
|
20187
|
-
error:
|
|
20188
|
-
fail:
|
|
20189
|
-
pass:
|
|
20190
|
-
skip:
|
|
19902
|
+
error: colors4.yellow,
|
|
19903
|
+
fail: colors4.red,
|
|
19904
|
+
pass: colors4.green,
|
|
19905
|
+
skip: colors4.dim
|
|
20191
19906
|
};
|
|
20192
19907
|
var ID_PAD = 28;
|
|
20193
19908
|
var seconds = (ms) => `${(ms / 1000).toFixed(1)}s`;
|
|
@@ -20202,17 +19917,18 @@ var duration = (ms) => {
|
|
|
20202
19917
|
};
|
|
20203
19918
|
var questionLine = (result) => {
|
|
20204
19919
|
const color = STATUS_COLOR[result.status];
|
|
20205
|
-
const glyph =
|
|
19920
|
+
const glyph = color(GLYPH2[result.status]);
|
|
20206
19921
|
const id2 = result.id.padEnd(ID_PAD);
|
|
20207
19922
|
if (result.status === "skip") {
|
|
20208
|
-
return ` ${glyph} ${id2} ${
|
|
19923
|
+
return ` ${glyph} ${id2} ${colors4.dim("skipped")}`;
|
|
20209
19924
|
}
|
|
20210
19925
|
const score = result.score === undefined ? "" : result.score.toFixed(2);
|
|
19926
|
+
const cost = money(result.costUsd);
|
|
20211
19927
|
const cells = [
|
|
20212
|
-
|
|
19928
|
+
color(result.status),
|
|
20213
19929
|
score,
|
|
20214
|
-
|
|
20215
|
-
|
|
19930
|
+
colors4.dim(seconds(result.durationMs)),
|
|
19931
|
+
cost === "" ? "" : colors4.dim(cost)
|
|
20216
19932
|
].filter((cell) => cell !== "").join(" ");
|
|
20217
19933
|
return ` ${glyph} ${id2} ${cells}`;
|
|
20218
19934
|
};
|
|
@@ -20220,15 +19936,15 @@ var questionDetails = (result, verbose) => {
|
|
|
20220
19936
|
const lines = [];
|
|
20221
19937
|
if (result.status === "fail") {
|
|
20222
19938
|
for (const fact of result.missing) {
|
|
20223
|
-
lines.push(` ${
|
|
19939
|
+
lines.push(` ${colors4.dim(`missing: ${fact}`)}`);
|
|
20224
19940
|
}
|
|
20225
19941
|
}
|
|
20226
19942
|
if (result.status === "error" && result.detail) {
|
|
20227
|
-
lines.push(` ${
|
|
19943
|
+
lines.push(` ${colors4.dim(result.detail)}`);
|
|
20228
19944
|
}
|
|
20229
19945
|
if (verbose && result.answer && result.status !== "pass") {
|
|
20230
19946
|
lines.push(...result.answer.split(`
|
|
20231
|
-
`).map((line) => ` ${
|
|
19947
|
+
`).map((line) => ` ${colors4.dim(`> ${line}`)}`));
|
|
20232
19948
|
}
|
|
20233
19949
|
return lines;
|
|
20234
19950
|
};
|
|
@@ -20244,15 +19960,15 @@ var summaryLine2 = (result) => {
|
|
|
20244
19960
|
].filter((part) => part !== "");
|
|
20245
19961
|
return parts.join(" · ");
|
|
20246
19962
|
};
|
|
20247
|
-
var headerLine = (total, agent) => `${
|
|
20248
|
-
var startLine = (id2, index, total) => ` ${
|
|
19963
|
+
var headerLine = (total, agent) => `${colors4.bold("blume eval")} ${total} question(s) · ${AGENTS[agent].name}`;
|
|
19964
|
+
var startLine = (id2, index, total) => ` ${colors4.dim(`▸ ${id2} (${index + 1}/${total})`)}`;
|
|
20249
19965
|
var fixLines = (result, root) => result.diagnostics.filter((diagnostic) => diagnostic.code !== "BLUME_EVAL_ROUTE_UNKNOWN").map((finding2) => {
|
|
20250
19966
|
const site = finding2.file ? `${relative18(root, finding2.file)}${finding2.line ? `:${finding2.line}` : ""}` : "";
|
|
20251
|
-
return ` ${
|
|
19967
|
+
return ` ${colors4.cyan("fix:")} ${site} ${colors4.dim(finding2.message)}`;
|
|
20252
19968
|
});
|
|
20253
19969
|
var warningLines = (result, root) => result.diagnostics.filter((diagnostic) => diagnostic.code === "BLUME_EVAL_ROUTE_UNKNOWN").map((finding2) => {
|
|
20254
19970
|
const site = finding2.file ? ` ${relative18(root, finding2.file)}${finding2.line ? `:${finding2.line}` : ""}` : "";
|
|
20255
|
-
return ` ${
|
|
19971
|
+
return ` ${colors4.yellow("⚠")}${site} ${colors4.dim(finding2.message)}`;
|
|
20256
19972
|
});
|
|
20257
19973
|
var evalReportJson = (result, root, threshold) => {
|
|
20258
19974
|
const diagnostics = result.diagnostics.map((diagnostic) => diagnostic.file ? { ...diagnostic, file: relative18(root, diagnostic.file) } : diagnostic);
|
|
@@ -20273,18 +19989,18 @@ var evalReportJson = (result, root, threshold) => {
|
|
|
20273
19989
|
var writeEvalReport = async (result, root, threshold) => {
|
|
20274
19990
|
const dir = await mkdtemp2(join36(tmpdir2(), "blume-eval-"));
|
|
20275
19991
|
const path = join36(dir, "report.json");
|
|
20276
|
-
await
|
|
19992
|
+
await writeFile11(path, evalReportJson(result, root, threshold));
|
|
20277
19993
|
return path;
|
|
20278
19994
|
};
|
|
20279
19995
|
|
|
20280
19996
|
// src/eval/run.ts
|
|
20281
|
-
import { mkdir as
|
|
19997
|
+
import { mkdir as mkdir11, mkdtemp as mkdtemp3, writeFile as writeFile13 } from "node:fs/promises";
|
|
20282
19998
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
20283
19999
|
import { join as join38 } from "pathe";
|
|
20284
20000
|
|
|
20285
20001
|
// src/eval/agents.ts
|
|
20286
20002
|
import { spawn as spawn2 } from "node:child_process";
|
|
20287
|
-
import { readFile as readFile20, writeFile as
|
|
20003
|
+
import { readFile as readFile20, writeFile as writeFile12 } from "node:fs/promises";
|
|
20288
20004
|
import { join as join37 } from "pathe";
|
|
20289
20005
|
import { z as z3 } from "zod";
|
|
20290
20006
|
var KILL_GRACE_MS = 5000;
|
|
@@ -20357,7 +20073,7 @@ var writeMcpConfig = async (dir, snapshotPath, launcher) => {
|
|
|
20357
20073
|
[MCP_SERVER_NAME]: { args: resolved.args, command: resolved.command }
|
|
20358
20074
|
}
|
|
20359
20075
|
};
|
|
20360
|
-
await
|
|
20076
|
+
await writeFile12(configPath, JSON.stringify(config, null, 2));
|
|
20361
20077
|
return {
|
|
20362
20078
|
configPath,
|
|
20363
20079
|
serverArgs: resolved.args,
|
|
@@ -20632,7 +20348,7 @@ var runQuestion = async (question, index, context) => {
|
|
|
20632
20348
|
const started = performance.now();
|
|
20633
20349
|
const elapsed = () => Math.round(performance.now() - started);
|
|
20634
20350
|
const workDir = join38(context.dir, `work-${index}`);
|
|
20635
|
-
await
|
|
20351
|
+
await mkdir11(workDir, { recursive: true });
|
|
20636
20352
|
const answerPath = join38(workDir, "answer.txt");
|
|
20637
20353
|
const reader = await context.run(context.bin, agentArgs(context.kind, { lastMessagePath: answerPath, mcp: context.mcp }), {
|
|
20638
20354
|
cwd: workDir,
|
|
@@ -20690,7 +20406,7 @@ var runEval = async (options) => {
|
|
|
20690
20406
|
const anchor = { path: options.evalsPath, raw: options.rawEvals };
|
|
20691
20407
|
const dir = await mkdtemp3(join38(tmpdir3(), "blume-eval-"));
|
|
20692
20408
|
const snapshotPath = join38(dir, "mcp-data.json");
|
|
20693
|
-
await
|
|
20409
|
+
await writeFile13(snapshotPath, JSON.stringify(await buildMcpData(options.project)));
|
|
20694
20410
|
const mcp = await writeMcpConfig(dir, snapshotPath);
|
|
20695
20411
|
const context = {
|
|
20696
20412
|
bin: AGENTS[kind].bin,
|
|
@@ -20969,7 +20685,7 @@ import { defineCommand as defineCommand9 } from "citty";
|
|
|
20969
20685
|
import { resolve as resolve12 } from "pathe";
|
|
20970
20686
|
|
|
20971
20687
|
// src/cli/init/questions.ts
|
|
20972
|
-
import { basename as
|
|
20688
|
+
import { basename as basename5, resolve as resolve11 } from "pathe";
|
|
20973
20689
|
var cancelled = (value) => typeof value === "symbol";
|
|
20974
20690
|
var collectAnswers = async (prompter, flags, defaults) => {
|
|
20975
20691
|
const directory = flags.directory ?? await prompter.text({
|
|
@@ -20982,7 +20698,7 @@ var collectAnswers = async (prompter, flags, defaults) => {
|
|
|
20982
20698
|
}
|
|
20983
20699
|
const root = resolve11(defaults.cwd, directory);
|
|
20984
20700
|
const title = await prompter.text({
|
|
20985
|
-
initialValue: titleize(
|
|
20701
|
+
initialValue: titleize(basename5(root)),
|
|
20986
20702
|
message: "What's your docs site called?",
|
|
20987
20703
|
validate: (value) => value?.trim() ? undefined : "Give your docs site a name."
|
|
20988
20704
|
});
|
|
@@ -21606,8 +21322,8 @@ var translateAgentArgs = (kind, lastMessagePath) => kind === "claude" ? claudeAr
|
|
|
21606
21322
|
|
|
21607
21323
|
// src/translate/ledger.ts
|
|
21608
21324
|
import { createHash as createHash4 } from "node:crypto";
|
|
21609
|
-
import {
|
|
21610
|
-
import {
|
|
21325
|
+
import { readFile as readFile23 } from "node:fs/promises";
|
|
21326
|
+
import { join as join42 } from "pathe";
|
|
21611
21327
|
import { z as z5 } from "zod";
|
|
21612
21328
|
var LEDGER_FILE = "blume.translations.json";
|
|
21613
21329
|
var ledgerSchema = z5.object({
|
|
@@ -21656,15 +21372,7 @@ var writeLedger = async (root, ledger) => {
|
|
|
21656
21372
|
if (existing === content) {
|
|
21657
21373
|
return false;
|
|
21658
21374
|
}
|
|
21659
|
-
await
|
|
21660
|
-
const tmp = `${path}.${process.pid}.tmp`;
|
|
21661
|
-
await writeFile15(tmp, content, "utf-8");
|
|
21662
|
-
try {
|
|
21663
|
-
await rename2(tmp, path);
|
|
21664
|
-
} catch (error) {
|
|
21665
|
-
await rm5(tmp, { force: true });
|
|
21666
|
-
throw error;
|
|
21667
|
-
}
|
|
21375
|
+
await writeTextAtomic(path, content);
|
|
21668
21376
|
return true;
|
|
21669
21377
|
};
|
|
21670
21378
|
var stampLedger = (ledger, sourceRel, locale, hash) => {
|
|
@@ -21687,25 +21395,17 @@ var pruneLedger = (ledger, knownSources, knownLocales) => {
|
|
|
21687
21395
|
};
|
|
21688
21396
|
|
|
21689
21397
|
// src/translate/report.ts
|
|
21690
|
-
|
|
21691
|
-
var
|
|
21692
|
-
bold: `${ESC5}[1m`,
|
|
21693
|
-
cyan: `${ESC5}[36m`,
|
|
21694
|
-
dim: `${ESC5}[2m`,
|
|
21695
|
-
green: `${ESC5}[32m`,
|
|
21696
|
-
red: `${ESC5}[31m`,
|
|
21697
|
-
reset: `${ESC5}[0m`,
|
|
21698
|
-
yellow: `${ESC5}[33m`
|
|
21699
|
-
};
|
|
21398
|
+
import { colors as colors5 } from "consola/utils";
|
|
21399
|
+
var ESC = String.fromCodePoint(27);
|
|
21700
21400
|
var GLYPH3 = {
|
|
21701
21401
|
failed: "✖",
|
|
21702
21402
|
partial: "!",
|
|
21703
21403
|
translated: "✔"
|
|
21704
21404
|
};
|
|
21705
21405
|
var STATUS_COLOR2 = {
|
|
21706
|
-
failed:
|
|
21707
|
-
partial:
|
|
21708
|
-
translated:
|
|
21406
|
+
failed: colors5.red,
|
|
21407
|
+
partial: colors5.yellow,
|
|
21408
|
+
translated: colors5.green
|
|
21709
21409
|
};
|
|
21710
21410
|
var SPINNER_FRAMES = [
|
|
21711
21411
|
"⠋",
|
|
@@ -21720,7 +21420,7 @@ var SPINNER_FRAMES = [
|
|
|
21720
21420
|
"⠏"
|
|
21721
21421
|
];
|
|
21722
21422
|
var SPINNER_INTERVAL_MS = 80;
|
|
21723
|
-
var REWRITE = `\r${
|
|
21423
|
+
var REWRITE = `\r${ESC}[K`;
|
|
21724
21424
|
var seconds2 = (ms) => `${(ms / 1000).toFixed(1)}s`;
|
|
21725
21425
|
var money2 = (cost) => cost === undefined ? "" : `$${cost.toFixed(2)}`;
|
|
21726
21426
|
var duration2 = (ms) => {
|
|
@@ -21735,20 +21435,20 @@ var itemLabel = (item) => item.kind === "page" ? `${item.sourceRel} → ${item.l
|
|
|
21735
21435
|
var spinnerLine = (active, done, total, frame) => {
|
|
21736
21436
|
const first = active[0];
|
|
21737
21437
|
const more = active.length > 1 ? ` (+${active.length - 1} more)` : "";
|
|
21738
|
-
return ` ${
|
|
21438
|
+
return ` ${colors5.cyan(SPINNER_FRAMES[frame % SPINNER_FRAMES.length])} ${itemLabel(first)}${more} ${colors5.dim(`${done}/${total}`)}`;
|
|
21739
21439
|
};
|
|
21740
21440
|
var itemEndLine = (result) => {
|
|
21741
21441
|
const color = STATUS_COLOR2[result.status];
|
|
21742
|
-
const glyph =
|
|
21442
|
+
const glyph = color(GLYPH3[result.status]);
|
|
21743
21443
|
const label = itemLabel(result.item);
|
|
21744
21444
|
if (result.status === "translated") {
|
|
21745
21445
|
const cells = [seconds2(result.durationMs), money2(result.costUsd)].filter((cell) => cell !== "").join(" ");
|
|
21746
|
-
return ` ${glyph} ${label} ${
|
|
21446
|
+
return ` ${glyph} ${label} ${colors5.dim(cells)}`;
|
|
21747
21447
|
}
|
|
21748
21448
|
const word = result.status === "partial" ? "partial" : "failed";
|
|
21749
|
-
return ` ${glyph} ${label} ${color
|
|
21449
|
+
return ` ${glyph} ${label} ${color(word)}${result.detail ? colors5.dim(`: ${result.detail}`) : ""}`;
|
|
21750
21450
|
};
|
|
21751
|
-
var translateHeaderLine = (itemCount, localeCount, agent) => `${
|
|
21451
|
+
var translateHeaderLine = (itemCount, localeCount, agent) => `${colors5.bold("blume translate")} ${itemCount} item(s) · ${localeCount} locale(s) · ${AGENTS[agent].name}`;
|
|
21752
21452
|
var translateSummaryLine = (result, workList) => {
|
|
21753
21453
|
const { counts } = result;
|
|
21754
21454
|
const parts = [
|
|
@@ -21762,7 +21462,7 @@ var translateSummaryLine = (result, workList) => {
|
|
|
21762
21462
|
].filter((part) => part !== "");
|
|
21763
21463
|
return parts.join(" · ");
|
|
21764
21464
|
};
|
|
21765
|
-
var diagnosticLines = (diagnostics) => diagnostics.map((diagnostic) => ` ${
|
|
21465
|
+
var diagnosticLines = (diagnostics) => diagnostics.map((diagnostic) => ` ${colors5.yellow("⚠")} ${colors5.dim(diagnostic.message)}`);
|
|
21766
21466
|
var driftRows = (workList) => workList.items.flatMap((item) => item.kind === "page" ? [
|
|
21767
21467
|
{
|
|
21768
21468
|
locale: item.locale,
|
|
@@ -21775,8 +21475,8 @@ var driftRows = (workList) => workList.items.flatMap((item) => item.kind === "pa
|
|
|
21775
21475
|
status: entry.status
|
|
21776
21476
|
})));
|
|
21777
21477
|
var checkLines = (workList) => [
|
|
21778
|
-
...driftRows(workList).map((row) => ` ${
|
|
21779
|
-
...workList.untracked.map((entry) => ` ${
|
|
21478
|
+
...driftRows(workList).map((row) => ` ${colors5.red("✖")} ${row.sourceRel} → ${row.locale} ${colors5.dim(row.status)}`),
|
|
21479
|
+
...workList.untracked.map((entry) => ` ${colors5.dim(`⊘ ${entry.sourceRel} → ${entry.locale} untracked (adopted by the next translate run)`)}`)
|
|
21780
21480
|
];
|
|
21781
21481
|
var checkSummaryLine = (workList) => {
|
|
21782
21482
|
const rows = driftRows(workList);
|
|
@@ -21897,20 +21597,13 @@ var createProgressRenderer = (options) => {
|
|
|
21897
21597
|
|
|
21898
21598
|
// src/translate/run.ts
|
|
21899
21599
|
import { existsSync as existsSync24 } from "node:fs";
|
|
21900
|
-
import {
|
|
21901
|
-
mkdir as mkdir12,
|
|
21902
|
-
mkdtemp as mkdtemp4,
|
|
21903
|
-
readFile as readFile25,
|
|
21904
|
-
rename as rename3,
|
|
21905
|
-
rm as rm6,
|
|
21906
|
-
writeFile as writeFile16
|
|
21907
|
-
} from "node:fs/promises";
|
|
21600
|
+
import { mkdtemp as mkdtemp4, readFile as readFile25 } from "node:fs/promises";
|
|
21908
21601
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
21909
|
-
import {
|
|
21602
|
+
import { join as join44 } from "pathe";
|
|
21910
21603
|
|
|
21911
21604
|
// src/translate/meta.ts
|
|
21912
21605
|
import { readFile as readFile24 } from "node:fs/promises";
|
|
21913
|
-
import { dirname as
|
|
21606
|
+
import { dirname as dirname15, join as join43, relative as relative19 } from "pathe";
|
|
21914
21607
|
import { glob as glob8 } from "tinyglobby";
|
|
21915
21608
|
var META_FILES2 = ["**/meta.ts", "**/meta.js", "**/meta.mjs"];
|
|
21916
21609
|
var metaTargetPath = (meta, locale) => join43(meta.contentRoot, locale, meta.dir, "meta.ts");
|
|
@@ -21932,7 +21625,7 @@ var discoverTranslatableMeta = async (project) => {
|
|
|
21932
21625
|
onlyFiles: true
|
|
21933
21626
|
});
|
|
21934
21627
|
for (const file of files.toSorted()) {
|
|
21935
|
-
const dir = relative19(contentRoot2,
|
|
21628
|
+
const dir = relative19(contentRoot2, dirname15(file));
|
|
21936
21629
|
const first = dir.split("/")[0]?.toLowerCase();
|
|
21937
21630
|
if (first && localeDirs.has(first)) {
|
|
21938
21631
|
continue;
|
|
@@ -22127,17 +21820,6 @@ var parseMetaTitles = (agentText, expectedKeys) => {
|
|
|
22127
21820
|
|
|
22128
21821
|
// src/translate/run.ts
|
|
22129
21822
|
var metaDirKey = (dir) => dir === "" ? "." : dir;
|
|
22130
|
-
var writeFileAtomic = async (path, text3) => {
|
|
22131
|
-
await mkdir12(dirname17(path), { recursive: true });
|
|
22132
|
-
const tmp = `${path}.${process.pid}.tmp`;
|
|
22133
|
-
await writeFile16(tmp, text3, "utf-8");
|
|
22134
|
-
try {
|
|
22135
|
-
await rename3(tmp, path);
|
|
22136
|
-
} catch (error) {
|
|
22137
|
-
await rm6(tmp, { force: true });
|
|
22138
|
-
throw error;
|
|
22139
|
-
}
|
|
22140
|
-
};
|
|
22141
21823
|
var invokeAgent = async (context, prompt, index) => {
|
|
22142
21824
|
const messagePath = join44(context.dir, `message-${index}.txt`);
|
|
22143
21825
|
const result = await context.run(context.bin, translateAgentArgs(context.kind, messagePath), { cwd: context.dir, prompt, timeoutMs: context.timeoutMs });
|
|
@@ -22168,7 +21850,7 @@ var runPageItem = async (item, index, context, ledger) => {
|
|
|
22168
21850
|
if (!validated.ok) {
|
|
22169
21851
|
return done("failed", validated.reason, output.costUsd);
|
|
22170
21852
|
}
|
|
22171
|
-
await
|
|
21853
|
+
await writeTextAtomic(item.targetPath, validated.text);
|
|
22172
21854
|
stampLedger(ledger, item.sourceRel, item.locale, hashSource(sourceText));
|
|
22173
21855
|
return done("translated", undefined, output.costUsd);
|
|
22174
21856
|
};
|
|
@@ -22193,7 +21875,7 @@ var runMetaItem = async (item, index, context, ledger) => {
|
|
|
22193
21875
|
if (translated === undefined) {
|
|
22194
21876
|
continue;
|
|
22195
21877
|
}
|
|
22196
|
-
await
|
|
21878
|
+
await writeTextAtomic(entry.targetPath, generateMetaModule(entry.meta.data, translated));
|
|
22197
21879
|
stampLedger(ledger, entry.meta.sourceRel, item.locale, hashSource(entry.meta.raw));
|
|
22198
21880
|
}
|
|
22199
21881
|
if (parsed.missing.length === item.entries.length) {
|
|
@@ -22293,13 +21975,9 @@ var runTranslate = async (options) => {
|
|
|
22293
21975
|
// src/translate/work-list.ts
|
|
22294
21976
|
import { existsSync as existsSync25 } from "node:fs";
|
|
22295
21977
|
import { readFile as readFile26 } from "node:fs/promises";
|
|
22296
|
-
import { dirname as
|
|
21978
|
+
import { dirname as dirname16, extname as extname8, join as join45, relative as relative20 } from "pathe";
|
|
22297
21979
|
var PAGE_EXTENSIONS = new Set([".md", ".mdx"]);
|
|
22298
|
-
var translatablePages = (project) => {
|
|
22299
|
-
const { i18n } = project.config;
|
|
22300
|
-
if (!i18n) {
|
|
22301
|
-
return [];
|
|
22302
|
-
}
|
|
21980
|
+
var translatablePages = (project, i18n) => {
|
|
22303
21981
|
const rootsByName = new Map(project.sources.flatMap((source) => source.staged || !source.contentRoot ? [] : [[source.name, source.contentRoot]]));
|
|
22304
21982
|
const seen = new Set;
|
|
22305
21983
|
const universe = [];
|
|
@@ -22337,7 +22015,7 @@ var computeWorkList = async (project, ledger, options = {}) => {
|
|
|
22337
22015
|
const untracked = [];
|
|
22338
22016
|
const pageItems = [];
|
|
22339
22017
|
let upToDate = 0;
|
|
22340
|
-
for (const { page: page2, contentRoot: contentRoot2, ext, sourcePath } of translatablePages(project)) {
|
|
22018
|
+
for (const { page: page2, contentRoot: contentRoot2, ext, sourcePath } of translatablePages(project, i18n)) {
|
|
22341
22019
|
const sourceRel = relative20(root, sourcePath);
|
|
22342
22020
|
knownSources.add(sourceRel);
|
|
22343
22021
|
const hash = hashSource(await readFile26(sourcePath, "utf-8"));
|
|
@@ -22376,7 +22054,7 @@ var computeWorkList = async (project, ledger, options = {}) => {
|
|
|
22376
22054
|
const entries = [];
|
|
22377
22055
|
for (const source of meta.metas) {
|
|
22378
22056
|
knownSources.add(source.sourceRel);
|
|
22379
|
-
const targetDir =
|
|
22057
|
+
const targetDir = dirname16(metaTargetPath(source, locale));
|
|
22380
22058
|
const exists = ["meta.ts", "meta.js", "meta.mjs"].some((name) => existsSync25(join45(targetDir, name)));
|
|
22381
22059
|
const hash = hashSource(source.raw);
|
|
22382
22060
|
const stamp = ledger.files[source.sourceRel]?.[locale];
|
|
@@ -22615,7 +22293,7 @@ import { join as join47 } from "pathe";
|
|
|
22615
22293
|
|
|
22616
22294
|
// src/core/links.ts
|
|
22617
22295
|
import { existsSync as existsSync26 } from "node:fs";
|
|
22618
|
-
import { basename as
|
|
22296
|
+
import { basename as basename6, join as join46 } from "pathe";
|
|
22619
22297
|
var HTTP = /^https?:\/\//iu;
|
|
22620
22298
|
var PROTOCOL_RELATIVE = /^\/\//u;
|
|
22621
22299
|
var SCHEME = /^[a-z][a-z0-9+.-]*:/iu;
|
|
@@ -22630,7 +22308,7 @@ var DOC_EXT = /\.(?:md|mdx)$/iu;
|
|
|
22630
22308
|
var FILE_EXT = /\.[a-z0-9]+$/iu;
|
|
22631
22309
|
var assetIsPresent = (resolved, ctx) => ctx.publicDir !== null && existsSync26(join46(ctx.publicDir, resolved));
|
|
22632
22310
|
var NUMERIC_PREFIX3 = /^\d+[-_.]/u;
|
|
22633
|
-
var isIndexPage = (page2) => /^index\.(?:md|mdx)$/iu.test(
|
|
22311
|
+
var isIndexPage = (page2) => /^index\.(?:md|mdx)$/iu.test(basename6(page2.navPath).replace(NUMERIC_PREFIX3, ""));
|
|
22634
22312
|
var applyRelativePart = (segments, part) => {
|
|
22635
22313
|
if (part === "" || part === ".") {
|
|
22636
22314
|
return;
|
|
@@ -22909,5 +22587,5 @@ process.on("unhandledRejection", (error) => {
|
|
|
22909
22587
|
});
|
|
22910
22588
|
runMain(main);
|
|
22911
22589
|
|
|
22912
|
-
//# debugId=
|
|
22590
|
+
//# debugId=C86B4C53CC85579764756E2164756E21
|
|
22913
22591
|
//# sourceMappingURL=index.js.map
|