blume 1.4.0 → 1.4.2
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 +32 -0
- package/dist/cli/index.js +328 -644
- package/dist/cli/index.js.map +35 -35
- package/dist/types/core/data.d.ts +10 -0
- package/docs/configuration/ai.mdx +15 -1
- package/package.json +28 -7
- package/src/ai/component-markdown.ts +7 -6
- package/src/ai/link-headers.ts +7 -2
- package/src/astro/generate.ts +8 -13
- package/src/astro/islands.ts +4 -1
- package/src/astro/templates.ts +5 -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 +78 -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/data.ts +7 -0
- 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) {
|
|
@@ -4799,6 +4738,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
4799
4738
|
exportPdf={${options.exportPdf}}
|
|
4800
4739
|
exportEpub={${options.exportEpub}}
|
|
4801
4740
|
feeds={data.feeds}
|
|
4741
|
+
discovery={data.config.discovery}
|
|
4802
4742
|
siteUrl={data.config.site}
|
|
4803
4743
|
pageType={frontmatter.type}
|
|
4804
4744
|
published={frontmatter.date ?? frontmatter.changelog?.date ?? null}
|
|
@@ -5001,6 +4941,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
5001
4941
|
exportPdf={${options.exportPdf}}
|
|
5002
4942
|
exportEpub={${options.exportEpub}}
|
|
5003
4943
|
feeds={data.feeds}
|
|
4944
|
+
discovery={data.config.discovery}
|
|
5004
4945
|
siteUrl={data.config.site}
|
|
5005
4946
|
noindex={false}
|
|
5006
4947
|
structuredDataEnabled={data.config.structuredData}
|
|
@@ -5464,35 +5405,39 @@ var routeIndex = (manifest, basePath) => {
|
|
|
5464
5405
|
}
|
|
5465
5406
|
return index;
|
|
5466
5407
|
};
|
|
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);
|
|
5408
|
+
var sitemapParser = new XMLParser({
|
|
5409
|
+
htmlEntities: true,
|
|
5410
|
+
ignoreAttributes: true,
|
|
5411
|
+
parseTagValue: false,
|
|
5412
|
+
removeNSPrefix: true
|
|
5413
|
+
});
|
|
5478
5414
|
var parseSitemap = (file, xml, bytes) => {
|
|
5479
5415
|
const doc = { bytes, file, lastmod: new Map, urls: [] };
|
|
5480
|
-
|
|
5481
|
-
|
|
5416
|
+
let parsed;
|
|
5417
|
+
try {
|
|
5418
|
+
parsed = sitemapParser.parse(xml);
|
|
5419
|
+
} catch {
|
|
5420
|
+
doc.error = "no <urlset> element";
|
|
5482
5421
|
return doc;
|
|
5483
5422
|
}
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
doc.urls.push(loc);
|
|
5488
|
-
}
|
|
5423
|
+
if (!Object.hasOwn(parsed, "urlset")) {
|
|
5424
|
+
doc.error = Object.hasOwn(parsed, "sitemapindex") ? "sitemap is an index, not a urlset" : "no <urlset> element";
|
|
5425
|
+
return doc;
|
|
5489
5426
|
}
|
|
5490
|
-
|
|
5491
|
-
|
|
5492
|
-
|
|
5493
|
-
|
|
5494
|
-
|
|
5495
|
-
|
|
5427
|
+
const urlset = parsed.urlset;
|
|
5428
|
+
const entries = typeof urlset === "object" && urlset !== null ? [urlset.url].flat() : [];
|
|
5429
|
+
for (const entry of entries) {
|
|
5430
|
+
if (typeof entry !== "object" || entry === null) {
|
|
5431
|
+
continue;
|
|
5432
|
+
}
|
|
5433
|
+
const { loc, lastmod } = entry;
|
|
5434
|
+
const locText = typeof loc === "string" ? loc.trim() : "";
|
|
5435
|
+
if (!locText) {
|
|
5436
|
+
continue;
|
|
5437
|
+
}
|
|
5438
|
+
doc.urls.push(locText);
|
|
5439
|
+
if (typeof lastmod === "string" && lastmod.trim() !== "") {
|
|
5440
|
+
doc.lastmod?.set(locText, lastmod.trim());
|
|
5496
5441
|
}
|
|
5497
5442
|
}
|
|
5498
5443
|
return doc;
|
|
@@ -5512,8 +5457,7 @@ var parseLlms = (file, text) => {
|
|
|
5512
5457
|
};
|
|
5513
5458
|
var ROBOTS_DIRECTIVE = /^(?<field>[a-z-]+)\s*:\s*(?<value>.*)$/iu;
|
|
5514
5459
|
var parseRobots = (file, text) => {
|
|
5515
|
-
const doc = {
|
|
5516
|
-
let appliesToAll = false;
|
|
5460
|
+
const doc = { file, invalid: [], raw: text, sitemaps: [] };
|
|
5517
5461
|
for (const [index, raw] of text.split(/\r?\n/u).entries()) {
|
|
5518
5462
|
const line = raw.trim();
|
|
5519
5463
|
if (line === "" || line.startsWith("#")) {
|
|
@@ -5526,11 +5470,7 @@ var parseRobots = (file, text) => {
|
|
|
5526
5470
|
}
|
|
5527
5471
|
const field = (match.groups?.field ?? "").toLowerCase();
|
|
5528
5472
|
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) {
|
|
5473
|
+
if (field === "sitemap" && value) {
|
|
5534
5474
|
doc.sitemaps.push(value);
|
|
5535
5475
|
}
|
|
5536
5476
|
}
|
|
@@ -10230,12 +10170,13 @@ var loadConfig = async (root, options = {}) => {
|
|
|
10230
10170
|
};
|
|
10231
10171
|
const moreIssues = rest.map((d) => ` - ${d.message}`).join(`
|
|
10232
10172
|
`);
|
|
10233
|
-
|
|
10173
|
+
const detail = rest.length > 0 ? {
|
|
10234
10174
|
...primary,
|
|
10235
10175
|
message: `${primary.message}
|
|
10236
10176
|
${rest.length} more config issue(s):
|
|
10237
10177
|
${moreIssues}`
|
|
10238
|
-
} : primary
|
|
10178
|
+
} : primary;
|
|
10179
|
+
throw new BlumeError(detail);
|
|
10239
10180
|
}
|
|
10240
10181
|
const config = applyDeploymentEnv(parsed.data);
|
|
10241
10182
|
const site = config.deployment.site ?? options.devServerUrl;
|
|
@@ -11894,10 +11835,12 @@ var fetchSpecText = async (spec) => {
|
|
|
11894
11835
|
if ("text" in last) {
|
|
11895
11836
|
return last.text;
|
|
11896
11837
|
}
|
|
11897
|
-
if (!last.retryable
|
|
11898
|
-
|
|
11838
|
+
if (!last.retryable) {
|
|
11839
|
+
break;
|
|
11840
|
+
}
|
|
11841
|
+
if (attempt < MAX_ATTEMPTS - 1) {
|
|
11842
|
+
await sleep(Math.min(last.retryAfter ?? BASE_BACKOFF_MS * 2 ** attempt, MAX_RETRY_WAIT_MS));
|
|
11899
11843
|
}
|
|
11900
|
-
await sleep(Math.min(last.retryAfter ?? BASE_BACKOFF_MS * 2 ** attempt, MAX_RETRY_WAIT_MS));
|
|
11901
11844
|
}
|
|
11902
11845
|
throw last.error;
|
|
11903
11846
|
};
|
|
@@ -12263,6 +12206,10 @@ var filesystemSource = (options) => {
|
|
|
12263
12206
|
};
|
|
12264
12207
|
|
|
12265
12208
|
// src/core/sources/github-releases.ts
|
|
12209
|
+
import { fromMarkdown } from "mdast-util-from-markdown";
|
|
12210
|
+
import { gfmFromMarkdown } from "mdast-util-gfm";
|
|
12211
|
+
import { toString as mdastToString } from "mdast-util-to-string";
|
|
12212
|
+
import { gfm } from "micromark-extension-gfm";
|
|
12266
12213
|
var DEFAULT_BASE_URL = "https://api.github.com";
|
|
12267
12214
|
var DEFAULT_LIMIT = 100;
|
|
12268
12215
|
var PER_PAGE = 100;
|
|
@@ -12271,21 +12218,16 @@ var NON_SLUG3 = /[^a-z0-9]+/gu;
|
|
|
12271
12218
|
var EDGE_DASHES = /^-+|-+$/gu;
|
|
12272
12219
|
var DESCRIPTION_MAX = 160;
|
|
12273
12220
|
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;
|
|
12221
|
+
var CHANGESET_HASH = /^(?<mark>\s*(?:[-*+]|\d+[.)])\s+)[0-9a-f]{7,40}:\s+/gmu;
|
|
12283
12222
|
var WHITESPACE2 = /\s+/gu;
|
|
12284
12223
|
var TRAILING_FRAGMENT = /[\s,;:.—–-]+$/u;
|
|
12224
|
+
var NON_PROSE = new Set(["code", "heading", "html", "thematicBreak"]);
|
|
12285
12225
|
var releaseDescription = (body) => {
|
|
12286
|
-
const
|
|
12287
|
-
|
|
12288
|
-
|
|
12226
|
+
const tree = fromMarkdown(body.replaceAll(CHANGESET_HASH, "$<mark>"), {
|
|
12227
|
+
extensions: [gfm()],
|
|
12228
|
+
mdastExtensions: [gfmFromMarkdown()]
|
|
12229
|
+
});
|
|
12230
|
+
const text = tree.children.filter((node) => !NON_PROSE.has(node.type)).map((node) => mdastToString(node, { includeHtml: false, includeImageAlt: false })).join(" ").replaceAll(WHITESPACE2, " ").trim();
|
|
12289
12231
|
if (!text) {
|
|
12290
12232
|
return;
|
|
12291
12233
|
}
|
|
@@ -12406,42 +12348,7 @@ var githubReleasesSource = (options, ctx) => {
|
|
|
12406
12348
|
};
|
|
12407
12349
|
|
|
12408
12350
|
// 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));
|
|
12351
|
+
import picomatch from "picomatch";
|
|
12445
12352
|
var GITHUB_HOSTS = new Set(["api.github.com", "raw.githubusercontent.com"]);
|
|
12446
12353
|
var githubHeaders2 = (url) => {
|
|
12447
12354
|
const token = process.env.GITHUB_TOKEN;
|
|
@@ -12466,12 +12373,13 @@ var enumerateGithub = async (github, include, doFetch) => {
|
|
|
12466
12373
|
}
|
|
12467
12374
|
const body = await res.json();
|
|
12468
12375
|
const prefix = base ? `${base}/` : "";
|
|
12376
|
+
const included = picomatch(include);
|
|
12469
12377
|
const refs = (body.tree ?? []).flatMap((node) => {
|
|
12470
12378
|
if (!(node.type === "blob" && node.path.startsWith(prefix))) {
|
|
12471
12379
|
return [];
|
|
12472
12380
|
}
|
|
12473
12381
|
const rel = node.path.slice(prefix.length);
|
|
12474
|
-
if (!
|
|
12382
|
+
if (!included(rel)) {
|
|
12475
12383
|
return [];
|
|
12476
12384
|
}
|
|
12477
12385
|
return [
|
|
@@ -12503,7 +12411,8 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
12503
12411
|
return await enumerateGithub(options.github, options.include, doFetch);
|
|
12504
12412
|
}
|
|
12505
12413
|
const base = (options.url ?? "").replace(/\/$/u, "");
|
|
12506
|
-
const
|
|
12414
|
+
const included = picomatch(options.include);
|
|
12415
|
+
const refs = (options.files ?? []).flatMap((ref) => included(ref) ? [{ editUrl: `${base}/${ref}`, fetchUrl: `${base}/${ref}`, ref }] : []);
|
|
12507
12416
|
return { refs, truncated: false };
|
|
12508
12417
|
};
|
|
12509
12418
|
const fetchEntry = async (item) => {
|
|
@@ -12662,23 +12571,19 @@ var RATE_LIMITED = 429;
|
|
|
12662
12571
|
var MAX_RETRIES = 4;
|
|
12663
12572
|
var BASE_DELAY_MS = 500;
|
|
12664
12573
|
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);
|
|
12574
|
+
var withNotionRetry = async (call, attempt = 0) => {
|
|
12575
|
+
try {
|
|
12576
|
+
return await call();
|
|
12577
|
+
} catch (error) {
|
|
12578
|
+
const { status } = error;
|
|
12579
|
+
if (status !== RATE_LIMITED || attempt === MAX_RETRIES) {
|
|
12580
|
+
throw error;
|
|
12679
12581
|
}
|
|
12582
|
+
const retryAfter = Number(error.headers?.["retry-after"]);
|
|
12583
|
+
const wait = retryAfter > 0 ? retryAfter * SECOND_MS2 : BASE_DELAY_MS * 2 ** attempt;
|
|
12584
|
+
await sleep2(wait);
|
|
12585
|
+
return withNotionRetry(call, attempt + 1);
|
|
12680
12586
|
}
|
|
12681
|
-
throw lastError instanceof Error ? lastError : new Error("Notion request failed after retries.");
|
|
12682
12587
|
};
|
|
12683
12588
|
var collectAll = async (page, cursor, acc = []) => {
|
|
12684
12589
|
const res = await page(cursor);
|
|
@@ -13401,11 +13306,7 @@ var scanProject = async (root, options = {}) => {
|
|
|
13401
13306
|
};
|
|
13402
13307
|
|
|
13403
13308
|
// 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`;
|
|
13309
|
+
import { colors as colors3 } from "consola/utils";
|
|
13409
13310
|
var ISSUES_URL = "https://github.com/haydenbleasel/blume/issues";
|
|
13410
13311
|
var BLUME_FRAME = /(?<abs>(?:\/[^\s()]*\/|[A-Za-z]:\\[^\s()]*\\)\.blume[/\\][^\s()]*)/gu;
|
|
13411
13312
|
var BLUME_MARKER = /[/\\]\.blume[/\\]/u;
|
|
@@ -13416,16 +13317,21 @@ var remapBlumeStack = (stack) => stack.replaceAll(BLUME_FRAME, (match) => {
|
|
|
13416
13317
|
var reportInternalError = (error) => {
|
|
13417
13318
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
13418
13319
|
const lines = [
|
|
13419
|
-
`${
|
|
13320
|
+
`${colors3.red(colors3.bold("BLUME_INTERNAL"))} An unexpected error occurred.`,
|
|
13420
13321
|
` ${err.message}`
|
|
13421
13322
|
];
|
|
13422
13323
|
const stack = remapBlumeStack(err.stack ?? "").split(`
|
|
13423
13324
|
`).slice(1, 5).map((line) => line.trim()).filter(Boolean);
|
|
13424
13325
|
if (stack.length > 0) {
|
|
13425
|
-
lines.push("",
|
|
13426
|
-
`)
|
|
13326
|
+
lines.push("", colors3.dim(stack.join(`
|
|
13327
|
+
`)));
|
|
13427
13328
|
}
|
|
13428
|
-
lines.push("", "This is likely a bug in Blume. Please report it with the details below:",
|
|
13329
|
+
lines.push("", "This is likely a bug in Blume. Please report it with the details below:", colors3.dim([
|
|
13330
|
+
` Blume: ${getBlumeVersion()}`,
|
|
13331
|
+
` Node: ${process.version}`,
|
|
13332
|
+
` Platform: ${process.platform} ${process.arch}`
|
|
13333
|
+
].join(`
|
|
13334
|
+
`)), ` ${ISSUES_URL}`);
|
|
13429
13335
|
process.stderr.write(`${lines.join(`
|
|
13430
13336
|
`)}
|
|
13431
13337
|
`);
|
|
@@ -13581,15 +13487,13 @@ var auditCommand = defineCommand2({
|
|
|
13581
13487
|
|
|
13582
13488
|
// src/cli/commands/build.ts
|
|
13583
13489
|
import { existsSync as existsSync18 } from "node:fs";
|
|
13584
|
-
import { mkdir as
|
|
13490
|
+
import { mkdir as mkdir8, readdir as readdir2, readFile as readFile17, stat as stat3, writeFile as writeFile7 } from "node:fs/promises";
|
|
13585
13491
|
import { build } from "astro";
|
|
13586
13492
|
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("'", "'");
|
|
13493
|
+
import { dirname as dirname13, join as join30, resolve as resolve10 } from "pathe";
|
|
13591
13494
|
|
|
13592
13495
|
// src/deploy/rss.ts
|
|
13496
|
+
import { escape as escapeXml } from "html-escaper";
|
|
13593
13497
|
var capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);
|
|
13594
13498
|
var pageDate = (page) => {
|
|
13595
13499
|
const raw = page.meta.date ?? page.meta.changelog?.date;
|
|
@@ -13881,6 +13785,7 @@ var readEntryText = async (ctx, page) => {
|
|
|
13881
13785
|
};
|
|
13882
13786
|
|
|
13883
13787
|
// src/ai/component-markdown.ts
|
|
13788
|
+
import { markdownTable } from "markdown-table";
|
|
13884
13789
|
import { mdxToMdast } from "satteri";
|
|
13885
13790
|
|
|
13886
13791
|
// src/components/content/youtube.ts
|
|
@@ -13978,14 +13883,11 @@ var typeTable = ({ children, props }) => {
|
|
|
13978
13883
|
const typeCell = info.typeDescriptionLink ? `[${cellCode(info.type)}](${cellText(info.typeDescriptionLink)})` : cellCode(info.type);
|
|
13979
13884
|
const defaultCell = info.default === undefined ? "-" : cellCode(info.default);
|
|
13980
13885
|
const description = cellText([info.description, info.typeDescription].filter((part) => typeof part === "string" && part !== "").join(" "));
|
|
13981
|
-
return
|
|
13886
|
+
return [prop, typeCell, defaultCell, description];
|
|
13982
13887
|
});
|
|
13983
|
-
const table = rows.length > 0 ? [
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
...rows
|
|
13987
|
-
].join(`
|
|
13988
|
-
`) : "";
|
|
13888
|
+
const table = rows.length > 0 ? markdownTable([["Prop", "Type", "Default", "Description"], ...rows], {
|
|
13889
|
+
alignDelimiters: false
|
|
13890
|
+
}) : "";
|
|
13989
13891
|
return [table, children].filter(Boolean).join(`
|
|
13990
13892
|
|
|
13991
13893
|
`);
|
|
@@ -14944,6 +14846,9 @@ var buildRobots = (project) => {
|
|
|
14944
14846
|
`;
|
|
14945
14847
|
};
|
|
14946
14848
|
|
|
14849
|
+
// src/deploy/sitemap.ts
|
|
14850
|
+
import { escape as escapeXml2 } from "html-escaper";
|
|
14851
|
+
|
|
14947
14852
|
// src/astro/pages.ts
|
|
14948
14853
|
import { extname as extname6, relative as relative12 } from "pathe";
|
|
14949
14854
|
import { glob as glob4, globSync } from "tinyglobby";
|
|
@@ -15039,7 +14944,7 @@ var buildSitemap = (project) => {
|
|
|
15039
14944
|
const seen = new Set;
|
|
15040
14945
|
const urls = [];
|
|
15041
14946
|
const pushUrl = (route, lastModified) => {
|
|
15042
|
-
const loc =
|
|
14947
|
+
const loc = escapeXml2(encodeURI(`${base}${route}`));
|
|
15043
14948
|
if (seen.has(loc)) {
|
|
15044
14949
|
return;
|
|
15045
14950
|
}
|
|
@@ -15193,25 +15098,25 @@ var pageFacets = (page, config) => {
|
|
|
15193
15098
|
};
|
|
15194
15099
|
|
|
15195
15100
|
// src/search/documents.ts
|
|
15196
|
-
var
|
|
15197
|
-
var
|
|
15198
|
-
var
|
|
15199
|
-
var
|
|
15200
|
-
var
|
|
15101
|
+
var CODE_FENCE2 = /```[\s\S]*?```/gu;
|
|
15102
|
+
var INLINE_CODE2 = /`(?<code>[^`]+)`/gu;
|
|
15103
|
+
var HTML_OR_JSX = /<\/?[a-zA-Z][^\n<>]*>|<\/?>/gu;
|
|
15104
|
+
var IMAGE = /!\[[^\]]*\]\([^)]*\)/gu;
|
|
15105
|
+
var LINK = /\[(?<text>[^\]]*)\]\([^)]*\)/gu;
|
|
15201
15106
|
var HEADING_MARK = /^#{1,6}\s+/gmu;
|
|
15202
|
-
var
|
|
15107
|
+
var MARKDOWN_PUNCT = /[*_~>]+/gu;
|
|
15203
15108
|
var WHITESPACE3 = /\s+/gu;
|
|
15204
15109
|
var toPlainText = (markdown) => {
|
|
15205
|
-
const withoutBlocks = markdown.replaceAll(
|
|
15110
|
+
const withoutBlocks = markdown.replaceAll(CODE_FENCE2, " ").replaceAll(IMAGE, " ").replaceAll(LINK, "$<text>");
|
|
15206
15111
|
const pieces = [];
|
|
15207
15112
|
let cursor = 0;
|
|
15208
|
-
for (const match of withoutBlocks.matchAll(
|
|
15113
|
+
for (const match of withoutBlocks.matchAll(INLINE_CODE2)) {
|
|
15209
15114
|
const start = match.index ?? 0;
|
|
15210
|
-
pieces.push(withoutBlocks.slice(cursor, start).replaceAll(
|
|
15115
|
+
pieces.push(withoutBlocks.slice(cursor, start).replaceAll(HTML_OR_JSX, " "), match.groups?.code ?? "");
|
|
15211
15116
|
cursor = start + match[0].length;
|
|
15212
15117
|
}
|
|
15213
|
-
pieces.push(withoutBlocks.slice(cursor).replaceAll(
|
|
15214
|
-
return pieces.join("").replaceAll(HEADING_MARK, "").replaceAll(
|
|
15118
|
+
pieces.push(withoutBlocks.slice(cursor).replaceAll(HTML_OR_JSX, " "));
|
|
15119
|
+
return pieces.join("").replaceAll(HEADING_MARK, "").replaceAll(MARKDOWN_PUNCT, " ").replaceAll(WHITESPACE3, " ").trim();
|
|
15215
15120
|
};
|
|
15216
15121
|
var buildCrumbIndex = (sidebar) => {
|
|
15217
15122
|
const index = new Map;
|
|
@@ -15532,21 +15437,19 @@ var refuseIfDevRunning = (root, action, options = {}) => {
|
|
|
15532
15437
|
|
|
15533
15438
|
// src/astro/generate.ts
|
|
15534
15439
|
import { createHash as createHash3 } from "node:crypto";
|
|
15535
|
-
import { existsSync as existsSync16, readFileSync as
|
|
15440
|
+
import { existsSync as existsSync16, readFileSync as readFileSync8, realpathSync } from "node:fs";
|
|
15536
15441
|
import {
|
|
15537
15442
|
lstat,
|
|
15538
|
-
mkdir as
|
|
15443
|
+
mkdir as mkdir7,
|
|
15539
15444
|
readFile as readFile16,
|
|
15540
15445
|
readlink,
|
|
15541
15446
|
realpath,
|
|
15542
|
-
rename,
|
|
15543
15447
|
rm as rm2,
|
|
15544
|
-
symlink
|
|
15545
|
-
writeFile as writeFile7
|
|
15448
|
+
symlink
|
|
15546
15449
|
} from "node:fs/promises";
|
|
15547
|
-
import { createRequire as
|
|
15548
|
-
import { pathToFileURL as
|
|
15549
|
-
import { basename as basename3, dirname as
|
|
15450
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
15451
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
15452
|
+
import { basename as basename3, dirname as dirname11, join as join28, normalize as normalize3, relative as relative14, resolve as resolve8 } from "pathe";
|
|
15550
15453
|
import { glob as glob7 } from "tinyglobby";
|
|
15551
15454
|
|
|
15552
15455
|
// src/ai/ask-data.ts
|
|
@@ -15941,10 +15844,6 @@ var finalize = (key, group, descriptor, label, identifier, warnings) => {
|
|
|
15941
15844
|
if (client === "only" && source && !source.framework) {
|
|
15942
15845
|
warnings.push(`Override "${key}" uses client: "only" but its framework couldn't be inferred; reference a .tsx/.jsx/.vue/.svelte file.`);
|
|
15943
15846
|
}
|
|
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
15847
|
if (!client && source?.framework) {
|
|
15949
15848
|
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
15849
|
}
|
|
@@ -16033,128 +15932,22 @@ var analyzeComponentOverrides = (source, filePath) => {
|
|
|
16033
15932
|
return result;
|
|
16034
15933
|
};
|
|
16035
15934
|
|
|
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
|
-
}
|
|
15935
|
+
// src/core/fs-atomic.ts
|
|
15936
|
+
import { mkdir as mkdir6 } from "node:fs/promises";
|
|
15937
|
+
import { dirname as dirname9 } from "pathe";
|
|
15938
|
+
import writeFileAtomic from "write-file-atomic";
|
|
15939
|
+
var writeTextAtomic = async (path, text2) => {
|
|
15940
|
+
await mkdir6(dirname9(path), { recursive: true });
|
|
15941
|
+
await writeFileAtomic(path, text2, { encoding: "utf-8", fsync: false });
|
|
16100
15942
|
};
|
|
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) => {
|
|
15943
|
+
|
|
15944
|
+
// src/core/tsconfig-aliases.ts
|
|
15945
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
15946
|
+
import { parseTsconfig } from "get-tsconfig";
|
|
15947
|
+
import { dirname as dirname10, join as join22, resolve as resolve7 } from "pathe";
|
|
15948
|
+
var CONFIG_DIR_TEMPLATE = "${configDir}";
|
|
15949
|
+
var substituteConfigDir = (value, configDir) => value.startsWith(CONFIG_DIR_TEMPLATE) ? join22(configDir, value.slice(CONFIG_DIR_TEMPLATE.length)) : value;
|
|
15950
|
+
var toAlias = (key, value, baseDir, configDir) => {
|
|
16158
15951
|
const first = Array.isArray(value) ? value[0] : value;
|
|
16159
15952
|
if (typeof first !== "string") {
|
|
16160
15953
|
return null;
|
|
@@ -16164,20 +15957,31 @@ var toAlias = (key, value, baseDir) => {
|
|
|
16164
15957
|
if (find === "" || find === "*") {
|
|
16165
15958
|
return null;
|
|
16166
15959
|
}
|
|
16167
|
-
return {
|
|
15960
|
+
return {
|
|
15961
|
+
find,
|
|
15962
|
+
replacement: resolve7(baseDir, substituteConfigDir(target, configDir))
|
|
15963
|
+
};
|
|
16168
15964
|
};
|
|
16169
15965
|
var resolveTsconfigAliases = (root) => {
|
|
16170
15966
|
const entry = ["tsconfig.json", "jsconfig.json"].map((name) => join22(root, name)).find((file) => existsSync13(file));
|
|
16171
15967
|
if (!entry) {
|
|
16172
15968
|
return {};
|
|
16173
15969
|
}
|
|
16174
|
-
|
|
16175
|
-
|
|
15970
|
+
let options;
|
|
15971
|
+
try {
|
|
15972
|
+
options = parseTsconfig(entry).compilerOptions;
|
|
15973
|
+
} catch {
|
|
15974
|
+
return {};
|
|
15975
|
+
}
|
|
15976
|
+
const paths = options?.paths;
|
|
15977
|
+
if (!paths) {
|
|
16176
15978
|
return {};
|
|
16177
15979
|
}
|
|
15980
|
+
const configDir = dirname10(entry);
|
|
15981
|
+
const baseDir = resolve7(configDir, substituteConfigDir(options?.baseUrl ?? ".", configDir));
|
|
16178
15982
|
const aliases = {};
|
|
16179
|
-
for (const [key, value] of Object.entries(
|
|
16180
|
-
const alias = toAlias(key, value,
|
|
15983
|
+
for (const [key, value] of Object.entries(paths)) {
|
|
15984
|
+
const alias = toAlias(key, value, baseDir, configDir);
|
|
16181
15985
|
if (alias) {
|
|
16182
15986
|
aliases[alias.find] = alias.replacement;
|
|
16183
15987
|
}
|
|
@@ -16187,9 +15991,9 @@ var resolveTsconfigAliases = (root) => {
|
|
|
16187
15991
|
|
|
16188
15992
|
// src/og/derive.ts
|
|
16189
15993
|
import { existsSync as existsSync14 } from "node:fs";
|
|
16190
|
-
import { isAbsolute as
|
|
15994
|
+
import { isAbsolute as isAbsolute7, join as join23 } from "pathe";
|
|
16191
15995
|
var CARD_WEIGHTS = [400, 600];
|
|
16192
|
-
var absoluteSrc = (root, src) =>
|
|
15996
|
+
var absoluteSrc = (root, src) => isAbsolute7(src) ? src : join23(root, src);
|
|
16193
15997
|
var googleWeights = (weights) => {
|
|
16194
15998
|
const numbers = weights.filter((weight) => typeof weight === "number");
|
|
16195
15999
|
const used = numbers.filter((weight) => CARD_WEIGHTS.includes(weight));
|
|
@@ -16288,7 +16092,7 @@ var missingFontFiles = (options, root) => {
|
|
|
16288
16092
|
};
|
|
16289
16093
|
|
|
16290
16094
|
// src/og/logo.ts
|
|
16291
|
-
import { existsSync as existsSync15, readFileSync as
|
|
16095
|
+
import { existsSync as existsSync15, readFileSync as readFileSync6 } from "node:fs";
|
|
16292
16096
|
import { join as join24 } from "pathe";
|
|
16293
16097
|
var resolveOgLogo = (project, source) => {
|
|
16294
16098
|
if (!source?.toLowerCase().endsWith(".svg")) {
|
|
@@ -16299,12 +16103,12 @@ var resolveOgLogo = (project, source) => {
|
|
|
16299
16103
|
join24(project.context.root, "public", relative13),
|
|
16300
16104
|
join24(project.context.root, relative13)
|
|
16301
16105
|
].find((path) => existsSync15(path));
|
|
16302
|
-
return file ?
|
|
16106
|
+
return file ? readFileSync6(file, "utf-8") : undefined;
|
|
16303
16107
|
};
|
|
16304
16108
|
|
|
16305
16109
|
// src/openapi/scalar.ts
|
|
16306
16110
|
import { readFile as readFile13 } from "node:fs/promises";
|
|
16307
|
-
import { isAbsolute as
|
|
16111
|
+
import { isAbsolute as isAbsolute8, join as join25 } from "pathe";
|
|
16308
16112
|
|
|
16309
16113
|
// src/theme/palette.ts
|
|
16310
16114
|
var FALLBACK_ACCENT = "oklch(0.62 0.16 250)";
|
|
@@ -16410,7 +16214,7 @@ var specConfiguration = async (spec, root) => {
|
|
|
16410
16214
|
if (URL_SPEC2.test(spec)) {
|
|
16411
16215
|
return { config: { url: spec } };
|
|
16412
16216
|
}
|
|
16413
|
-
const absolute =
|
|
16217
|
+
const absolute = isAbsolute8(spec) ? spec : join25(root, spec);
|
|
16414
16218
|
try {
|
|
16415
16219
|
return { config: { content: await readFile13(absolute, "utf-8") } };
|
|
16416
16220
|
} catch {
|
|
@@ -17242,9 +17046,9 @@ ${options.userCss}
|
|
|
17242
17046
|
`;
|
|
17243
17047
|
|
|
17244
17048
|
// src/theme/twoslash.ts
|
|
17245
|
-
import { readFileSync as
|
|
17246
|
-
import { createRequire as
|
|
17247
|
-
var require2 =
|
|
17049
|
+
import { readFileSync as readFileSync7 } from "node:fs";
|
|
17050
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
17051
|
+
var require2 = createRequire3(import.meta.url);
|
|
17248
17052
|
var OVERRIDES = `
|
|
17249
17053
|
/* Twoslash: theme the rich renderer with Blume tokens. */
|
|
17250
17054
|
:root {
|
|
@@ -17319,7 +17123,7 @@ var OVERRIDES = `
|
|
|
17319
17123
|
`;
|
|
17320
17124
|
var twoslashCss = () => {
|
|
17321
17125
|
const file = require2.resolve("@shikijs/twoslash/style-rich.css");
|
|
17322
|
-
return `${
|
|
17126
|
+
return `${readFileSync7(file, "utf-8")}
|
|
17323
17127
|
${OVERRIDES}`;
|
|
17324
17128
|
};
|
|
17325
17129
|
|
|
@@ -17460,7 +17264,7 @@ var readClientMode = (source, file, warnings) => {
|
|
|
17460
17264
|
};
|
|
17461
17265
|
var discoverIslands = async (root) => {
|
|
17462
17266
|
const dir = join26(root, "islands");
|
|
17463
|
-
const matches2 = await glob5(["
|
|
17267
|
+
const matches2 = await glob5(["**/*"], {
|
|
17464
17268
|
absolute: true,
|
|
17465
17269
|
cwd: dir,
|
|
17466
17270
|
onlyFiles: true
|
|
@@ -17569,7 +17373,7 @@ var exampleMarkdownLookup = (examples) => Object.fromEntries(examples.map((examp
|
|
|
17569
17373
|
var BLUME_SRC = join28(packageRoot(), "src");
|
|
17570
17374
|
var canResolveFrom = (fromDir, spec) => {
|
|
17571
17375
|
try {
|
|
17572
|
-
|
|
17376
|
+
createRequire4(pathToFileURL2(join28(fromDir, "_.js")).href).resolve(spec);
|
|
17573
17377
|
return true;
|
|
17574
17378
|
} catch {
|
|
17575
17379
|
return false;
|
|
@@ -17580,7 +17384,7 @@ var resolveReactCompiler = (config, needsReact, pkgDir = packageRoot()) => {
|
|
|
17580
17384
|
return null;
|
|
17581
17385
|
}
|
|
17582
17386
|
try {
|
|
17583
|
-
return
|
|
17387
|
+
return createRequire4(pathToFileURL2(join28(pkgDir, "_.js")).href).resolve("babel-plugin-react-compiler");
|
|
17584
17388
|
} catch {
|
|
17585
17389
|
return null;
|
|
17586
17390
|
}
|
|
@@ -17603,7 +17407,7 @@ var resolvedAstroHit = (fromDir) => {
|
|
|
17603
17407
|
if (pkg) {
|
|
17604
17408
|
return { modulesDir, pkg };
|
|
17605
17409
|
}
|
|
17606
|
-
const parent =
|
|
17410
|
+
const parent = dirname11(dir);
|
|
17607
17411
|
if (parent === dir) {
|
|
17608
17412
|
return null;
|
|
17609
17413
|
}
|
|
@@ -17619,7 +17423,7 @@ var sameRealDir = (a, b) => {
|
|
|
17619
17423
|
};
|
|
17620
17424
|
var depsCandidates = (pkgDir) => [
|
|
17621
17425
|
join28(pkgDir, "node_modules"),
|
|
17622
|
-
|
|
17426
|
+
dirname11(pkgDir)
|
|
17623
17427
|
];
|
|
17624
17428
|
var candidateHolding = (pkgDir, ...segments) => depsCandidates(pkgDir).find((dir) => existsSync16(join28(dir, ...segments))) ?? null;
|
|
17625
17429
|
var linkDepsJunction = async (link, depsDir) => {
|
|
@@ -17634,13 +17438,13 @@ var linkDepsJunction = async (link, depsDir) => {
|
|
|
17634
17438
|
return;
|
|
17635
17439
|
}
|
|
17636
17440
|
try {
|
|
17637
|
-
if (resolve8(
|
|
17441
|
+
if (resolve8(dirname11(link), await readlink(link)) === resolve8(depsDir)) {
|
|
17638
17442
|
return;
|
|
17639
17443
|
}
|
|
17640
17444
|
} catch {}
|
|
17641
17445
|
await rm2(link, { force: true });
|
|
17642
17446
|
}
|
|
17643
|
-
await
|
|
17447
|
+
await mkdir7(dirname11(link), { recursive: true });
|
|
17644
17448
|
await symlink(depsDir, link, "junction");
|
|
17645
17449
|
};
|
|
17646
17450
|
var readPkgVersion = (pkgJsonPath) => {
|
|
@@ -17648,7 +17452,7 @@ var readPkgVersion = (pkgJsonPath) => {
|
|
|
17648
17452
|
return null;
|
|
17649
17453
|
}
|
|
17650
17454
|
try {
|
|
17651
|
-
return JSON.parse(
|
|
17455
|
+
return JSON.parse(readFileSync8(pkgJsonPath, "utf-8")).version ?? null;
|
|
17652
17456
|
} catch {
|
|
17653
17457
|
return null;
|
|
17654
17458
|
}
|
|
@@ -17797,15 +17601,7 @@ var writeIfChanged = async (path, content) => {
|
|
|
17797
17601
|
if (existing === content) {
|
|
17798
17602
|
return false;
|
|
17799
17603
|
}
|
|
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
|
-
}
|
|
17604
|
+
await writeTextAtomic(path, content);
|
|
17809
17605
|
return true;
|
|
17810
17606
|
};
|
|
17811
17607
|
var pruneOrphans = async (srcDir, written) => {
|
|
@@ -17874,7 +17670,7 @@ var readLogoSvg = (project, source) => {
|
|
|
17874
17670
|
join28(project.context.root, "public", rel),
|
|
17875
17671
|
join28(project.context.root, rel)
|
|
17876
17672
|
].find((path) => existsSync16(path));
|
|
17877
|
-
return file ?
|
|
17673
|
+
return file ? readFileSync8(file, "utf-8") : undefined;
|
|
17878
17674
|
};
|
|
17879
17675
|
var resolveLogo = (project) => {
|
|
17880
17676
|
const { logo } = project.config;
|
|
@@ -17917,7 +17713,7 @@ var faviconType = (name) => {
|
|
|
17917
17713
|
const ext = name.split(".").pop()?.toLowerCase();
|
|
17918
17714
|
return ext ? FAVICON_TYPES[ext] : undefined;
|
|
17919
17715
|
};
|
|
17920
|
-
var inlineDataUri = (file, type) => `data:${type};base64,${
|
|
17716
|
+
var inlineDataUri = (file, type) => `data:${type};base64,${readFileSync8(file).toString("base64")}`;
|
|
17921
17717
|
var defaultFavicon = () => ({
|
|
17922
17718
|
href: inlineDataUri(join28(BLUME_SRC, "assets", "icon.png"), "image/png"),
|
|
17923
17719
|
type: "image/png"
|
|
@@ -18042,6 +17838,10 @@ var buildRuntimeData = (project) => {
|
|
|
18042
17838
|
codeWrap: config.markdown.code.wrap,
|
|
18043
17839
|
dateFormat: config.dateFormat,
|
|
18044
17840
|
description: config.description,
|
|
17841
|
+
discovery: {
|
|
17842
|
+
agentReadability: config.seo.agentReadability,
|
|
17843
|
+
llmsTxt: config.ai.llmsTxt.enabled
|
|
17844
|
+
},
|
|
18045
17845
|
favicon: resolveFavicon(project),
|
|
18046
17846
|
feedback: config.feedback,
|
|
18047
17847
|
i18n: i18n ? {
|
|
@@ -18441,44 +18241,9 @@ var generateRuntime = async (project) => {
|
|
|
18441
18241
|
};
|
|
18442
18242
|
|
|
18443
18243
|
// 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
|
-
};
|
|
18244
|
+
import { existsSync as existsSync17, readFileSync as readFileSync9 } from "node:fs";
|
|
18245
|
+
import { parse as parse2 } from "dotenv";
|
|
18246
|
+
import { dirname as dirname12, join as join29, resolve as resolve9 } from "pathe";
|
|
18482
18247
|
var applyEnv = (parsed) => {
|
|
18483
18248
|
for (const [key, value] of Object.entries(parsed)) {
|
|
18484
18249
|
if (!(key in process.env)) {
|
|
@@ -18489,7 +18254,7 @@ var applyEnv = (parsed) => {
|
|
|
18489
18254
|
var loadFile = (path) => {
|
|
18490
18255
|
try {
|
|
18491
18256
|
if (existsSync17(path)) {
|
|
18492
|
-
applyEnv(
|
|
18257
|
+
applyEnv(parse2(readFileSync9(path, "utf-8")));
|
|
18493
18258
|
}
|
|
18494
18259
|
} catch {}
|
|
18495
18260
|
};
|
|
@@ -18499,7 +18264,7 @@ var loadEnvFiles = (startDir) => {
|
|
|
18499
18264
|
while (!done) {
|
|
18500
18265
|
loadFile(join29(dir, ".env.local"));
|
|
18501
18266
|
loadFile(join29(dir, ".env"));
|
|
18502
|
-
const parent =
|
|
18267
|
+
const parent = dirname12(dir);
|
|
18503
18268
|
done = existsSync17(join29(dir, ".git")) || parent === dir;
|
|
18504
18269
|
dir = parent;
|
|
18505
18270
|
}
|
|
@@ -18605,12 +18370,12 @@ var emitRedirectFiles = async (config, distDir) => {
|
|
|
18605
18370
|
if (redirects.length === 0 || config.deployment.output !== "static") {
|
|
18606
18371
|
return;
|
|
18607
18372
|
}
|
|
18608
|
-
await
|
|
18373
|
+
await writeFile7(join30(distDir, "blume-redirects.json"), buildRedirectManifest(redirects), "utf-8");
|
|
18609
18374
|
const platformFiles = [
|
|
18610
18375
|
{ content: buildNetlifyRedirects(redirects), name: "_redirects" },
|
|
18611
18376
|
{ content: buildVercelConfig(redirects), name: "vercel.json" }
|
|
18612
18377
|
];
|
|
18613
|
-
await Promise.all(platformFiles.map((file) => existsSync18(join30(distDir, file.name)) ? Promise.resolve() :
|
|
18378
|
+
await Promise.all(platformFiles.map((file) => existsSync18(join30(distDir, file.name)) ? Promise.resolve() : writeFile7(join30(distDir, file.name), file.content, "utf-8")));
|
|
18614
18379
|
logger.success(`Emitted redirect files for ${redirects.length} redirect(s)`);
|
|
18615
18380
|
};
|
|
18616
18381
|
var emitHeaderFiles = async (project, distDir) => {
|
|
@@ -18621,7 +18386,7 @@ var emitHeaderFiles = async (project, distDir) => {
|
|
|
18621
18386
|
const ours = buildNetlifyHeaders(config, buildHomeLinkHeader(config, markdownRoutePaths(project)));
|
|
18622
18387
|
const target = join30(distDir, "_headers");
|
|
18623
18388
|
const existing = existsSync18(target) ? await readFile17(target, "utf-8") : "";
|
|
18624
|
-
await
|
|
18389
|
+
await writeFile7(target, existing ? `${existing.trimEnd()}
|
|
18625
18390
|
${ours}` : ours, "utf-8");
|
|
18626
18391
|
logger.success("Emitted _headers (UTF-8 Content-Type + homepage Link header)");
|
|
18627
18392
|
};
|
|
@@ -18649,10 +18414,10 @@ var emitAgentSkills = async (project, distDir) => {
|
|
|
18649
18414
|
}
|
|
18650
18415
|
await Promise.all(skills.map(async (skill) => {
|
|
18651
18416
|
const target = join30(outDir, skill.path);
|
|
18652
|
-
await
|
|
18653
|
-
await
|
|
18417
|
+
await mkdir8(dirname13(target), { recursive: true });
|
|
18418
|
+
await writeFile7(target, skill.content);
|
|
18654
18419
|
}));
|
|
18655
|
-
await
|
|
18420
|
+
await writeFile7(join30(outDir, "index.json"), buildSkillsIndex(skills, project.config), "utf-8");
|
|
18656
18421
|
logger.success(`Published ${skills.length} agent skill(s) (.well-known/agent-skills/index.json)`);
|
|
18657
18422
|
};
|
|
18658
18423
|
var emitWellKnownFiles = async (config, distDir) => {
|
|
@@ -18673,8 +18438,8 @@ var emitWellKnownFiles = async (config, distDir) => {
|
|
|
18673
18438
|
if (!file.content || existsSync18(target)) {
|
|
18674
18439
|
continue;
|
|
18675
18440
|
}
|
|
18676
|
-
await
|
|
18677
|
-
await
|
|
18441
|
+
await mkdir8(join30(distDir, ".well-known"), { recursive: true });
|
|
18442
|
+
await writeFile7(target, file.content, "utf-8");
|
|
18678
18443
|
logger.success(`Generated ${file.path.slice(1)} (${file.label})`);
|
|
18679
18444
|
}
|
|
18680
18445
|
};
|
|
@@ -18695,7 +18460,7 @@ var emitVercelNegotiation = async (project, routePaths, root) => {
|
|
|
18695
18460
|
logger.warn("Could not wire Accept: text/markdown negotiation into .vercel/output/config.json — raw Markdown stays available at the .md URLs.");
|
|
18696
18461
|
return;
|
|
18697
18462
|
}
|
|
18698
|
-
await
|
|
18463
|
+
await writeFile7(configPath, injected, "utf-8");
|
|
18699
18464
|
logger.success("Wired Accept: text/markdown negotiation into the Vercel routing config");
|
|
18700
18465
|
};
|
|
18701
18466
|
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 +18486,8 @@ var emitCloudflareNegotiation = async (project, routePaths) => {
|
|
|
18721
18486
|
warnCloudflareNegotiationSkipped();
|
|
18722
18487
|
return;
|
|
18723
18488
|
}
|
|
18724
|
-
await
|
|
18725
|
-
await
|
|
18489
|
+
await writeFile7(join30(serverDir, NEGOTIATION_WORKER_FILE), injected.worker, "utf-8");
|
|
18490
|
+
await writeFile7(wranglerPath, injected.wrangler, "utf-8");
|
|
18726
18491
|
logger.success("Wired Accept: text/markdown negotiation into the Cloudflare Worker");
|
|
18727
18492
|
};
|
|
18728
18493
|
var formatBytes2 = (bytes) => {
|
|
@@ -18819,10 +18584,10 @@ var publishLlmsFiles = async (project, distDir) => {
|
|
|
18819
18584
|
const { index, full } = await buildLlmsFiles(project);
|
|
18820
18585
|
const writes = [];
|
|
18821
18586
|
if (writeIndex) {
|
|
18822
|
-
writes.push(
|
|
18587
|
+
writes.push(writeFile7(indexPath, index, "utf-8"));
|
|
18823
18588
|
}
|
|
18824
18589
|
if (writeFull) {
|
|
18825
|
-
writes.push(
|
|
18590
|
+
writes.push(writeFile7(fullPath, full, "utf-8"));
|
|
18826
18591
|
}
|
|
18827
18592
|
await Promise.all(writes);
|
|
18828
18593
|
logger.success(`Generated ${[
|
|
@@ -18846,17 +18611,17 @@ var publishBuildArtifacts = async (project, distDir, args) => {
|
|
|
18846
18611
|
}
|
|
18847
18612
|
const sitemap = buildSitemap(project);
|
|
18848
18613
|
if (sitemap && !existsSync18(join30(distDir, "sitemap.xml"))) {
|
|
18849
|
-
await
|
|
18614
|
+
await writeFile7(join30(distDir, "sitemap.xml"), sitemap, "utf-8");
|
|
18850
18615
|
logger.success("Generated sitemap.xml");
|
|
18851
18616
|
}
|
|
18852
18617
|
const robots = buildRobots(project);
|
|
18853
18618
|
if (robots && !existsSync18(join30(distDir, "robots.txt"))) {
|
|
18854
|
-
await
|
|
18619
|
+
await writeFile7(join30(distDir, "robots.txt"), robots, "utf-8");
|
|
18855
18620
|
logger.success("Generated robots.txt");
|
|
18856
18621
|
}
|
|
18857
18622
|
const agentReadability = buildAgentReadability(project);
|
|
18858
18623
|
if (agentReadability && !existsSync18(join30(distDir, "agent-readability.json"))) {
|
|
18859
|
-
await
|
|
18624
|
+
await writeFile7(join30(distDir, "agent-readability.json"), `${JSON.stringify(agentReadability, null, 2)}
|
|
18860
18625
|
`, "utf-8");
|
|
18861
18626
|
logger.success("Generated agent-readability.json");
|
|
18862
18627
|
}
|
|
@@ -19046,10 +18811,9 @@ var checkCommand = defineCommand4({
|
|
|
19046
18811
|
});
|
|
19047
18812
|
|
|
19048
18813
|
// src/cli/commands/dev.ts
|
|
19049
|
-
import { watch } from "node:fs";
|
|
19050
18814
|
import { dev } from "astro";
|
|
18815
|
+
import { watch } from "chokidar";
|
|
19051
18816
|
import { defineCommand as defineCommand5 } from "citty";
|
|
19052
|
-
import { basename as basename4, dirname as dirname13 } from "pathe";
|
|
19053
18817
|
|
|
19054
18818
|
// src/astro/integration.ts
|
|
19055
18819
|
var overlayServer = null;
|
|
@@ -19234,21 +18998,12 @@ var devCommand = defineCommand5({
|
|
|
19234
18998
|
project.context.themeFile,
|
|
19235
18999
|
project.context.componentsFile
|
|
19236
19000
|
].filter((target) => target !== null);
|
|
19001
|
+
const projectWatcher = watch([...dirTargets, ...fileTargets], {
|
|
19002
|
+
ignoreInitial: true
|
|
19003
|
+
}).on("all", regenerate);
|
|
19237
19004
|
const disposers = [
|
|
19238
19005
|
...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
|
-
})
|
|
19006
|
+
() => void projectWatcher.close()
|
|
19252
19007
|
].filter((dispose) => dispose !== undefined);
|
|
19253
19008
|
const shutdown = async () => {
|
|
19254
19009
|
for (const dispose of disposers) {
|
|
@@ -19264,30 +19019,18 @@ var devCommand = defineCommand5({
|
|
|
19264
19019
|
});
|
|
19265
19020
|
|
|
19266
19021
|
// src/cli/commands/doctor.ts
|
|
19267
|
-
import { readFileSync as
|
|
19022
|
+
import { readFileSync as readFileSync10 } from "node:fs";
|
|
19268
19023
|
import { defineCommand as defineCommand6 } from "citty";
|
|
19269
19024
|
import { join as join32 } from "pathe";
|
|
19270
|
-
|
|
19271
|
-
var
|
|
19272
|
-
var
|
|
19025
|
+
import { satisfies } from "semver";
|
|
19026
|
+
var FALLBACK_NODE_RANGE = ">=22.12.0";
|
|
19027
|
+
var supportedNodeRange = () => {
|
|
19273
19028
|
try {
|
|
19274
|
-
const pkg = JSON.parse(
|
|
19275
|
-
|
|
19276
|
-
return range.replace(LEADING_RANGE, "") || FALLBACK_MIN_NODE;
|
|
19029
|
+
const pkg = JSON.parse(readFileSync10(join32(packageRoot(), "package.json"), "utf-8"));
|
|
19030
|
+
return pkg.engines?.node || FALLBACK_NODE_RANGE;
|
|
19277
19031
|
} 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
|
-
}
|
|
19032
|
+
return FALLBACK_NODE_RANGE;
|
|
19289
19033
|
}
|
|
19290
|
-
return false;
|
|
19291
19034
|
};
|
|
19292
19035
|
var doctorCommand = defineCommand6({
|
|
19293
19036
|
args: {
|
|
@@ -19303,11 +19046,11 @@ var doctorCommand = defineCommand6({
|
|
|
19303
19046
|
async run({ args }) {
|
|
19304
19047
|
const root = process.cwd();
|
|
19305
19048
|
const diagnostics = [];
|
|
19306
|
-
const
|
|
19307
|
-
if (
|
|
19049
|
+
const nodeRange = supportedNodeRange();
|
|
19050
|
+
if (!satisfies(process.versions.node, nodeRange)) {
|
|
19308
19051
|
diagnostics.push({
|
|
19309
19052
|
code: "BLUME_NODE_VERSION",
|
|
19310
|
-
message: `Node ${process.versions.node} is
|
|
19053
|
+
message: `Node ${process.versions.node} is outside the supported range (${nodeRange}).`,
|
|
19311
19054
|
severity: "warning"
|
|
19312
19055
|
});
|
|
19313
19056
|
}
|
|
@@ -19368,7 +19111,7 @@ import { relative as relative17 } from "pathe";
|
|
|
19368
19111
|
|
|
19369
19112
|
// src/registry/eject.ts
|
|
19370
19113
|
import { existsSync as existsSync20 } from "node:fs";
|
|
19371
|
-
import { cp as cp2, mkdir as
|
|
19114
|
+
import { cp as cp2, mkdir as mkdir9, readFile as readFile18, rm as rm3, writeFile as writeFile8 } from "node:fs/promises";
|
|
19372
19115
|
import { join as join33, relative as relative15 } from "pathe";
|
|
19373
19116
|
var toPosix = (path) => path.split("\\").join("/");
|
|
19374
19117
|
var LOCAL_BLUME_SOURCE = "../../node_modules/blume/src/**/*.{astro,ts,tsx}";
|
|
@@ -19715,8 +19458,8 @@ var eject = async (root) => {
|
|
|
19715
19458
|
}
|
|
19716
19459
|
const written = files.filter((file) => !(file.skipIfExists && existsSync20(file.path)));
|
|
19717
19460
|
await Promise.all(written.map(async (file) => {
|
|
19718
|
-
await
|
|
19719
|
-
await
|
|
19461
|
+
await mkdir9(join33(file.path, ".."), { recursive: true });
|
|
19462
|
+
await writeFile8(file.path, file.content, "utf-8");
|
|
19720
19463
|
}));
|
|
19721
19464
|
const assetsSrc = join33(context.outDir, "public", "blume-assets");
|
|
19722
19465
|
if (existsSync20(assetsSrc)) {
|
|
@@ -19729,7 +19472,7 @@ var eject = async (root) => {
|
|
|
19729
19472
|
};
|
|
19730
19473
|
|
|
19731
19474
|
// src/cli/eject-scripts.ts
|
|
19732
|
-
import { readFile as readFile19, writeFile as
|
|
19475
|
+
import { readFile as readFile19, writeFile as writeFile9 } from "node:fs/promises";
|
|
19733
19476
|
import { join as join34 } from "pathe";
|
|
19734
19477
|
var droppedArtifactNotices = (config) => {
|
|
19735
19478
|
const notices = [];
|
|
@@ -19771,14 +19514,14 @@ var updatePackageScripts = async (root) => {
|
|
|
19771
19514
|
dev: "astro dev",
|
|
19772
19515
|
preview: "astro preview"
|
|
19773
19516
|
};
|
|
19774
|
-
await
|
|
19517
|
+
await writeFile9(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
19775
19518
|
`, "utf-8");
|
|
19776
19519
|
};
|
|
19777
19520
|
|
|
19778
19521
|
// src/cli/init/scaffold.ts
|
|
19779
19522
|
import { existsSync as existsSync21 } from "node:fs";
|
|
19780
|
-
import { mkdir as
|
|
19781
|
-
import { basename as
|
|
19523
|
+
import { mkdir as mkdir10, writeFile as writeFile10 } from "node:fs/promises";
|
|
19524
|
+
import { basename as basename4, dirname as dirname14, isAbsolute as isAbsolute9, join as join35, relative as relative16 } from "pathe";
|
|
19782
19525
|
|
|
19783
19526
|
// src/core/package-json.ts
|
|
19784
19527
|
var toPackageName = (raw) => raw.toLowerCase().replaceAll(/[^a-z0-9._-]+/gu, "-").replaceAll(/^[-_.]+|[-_.]+$/gu, "") || "docs";
|
|
@@ -19906,34 +19649,35 @@ var detectPackageManager = (userAgent) => {
|
|
|
19906
19649
|
const name = userAgent?.split("/")[0];
|
|
19907
19650
|
return name !== undefined && PACKAGE_MANAGERS.includes(name) ? name : "npm";
|
|
19908
19651
|
};
|
|
19909
|
-
var validateContentDir = (root, dir) =>
|
|
19652
|
+
var validateContentDir = (root, dir) => isAbsolute9(dir) || relative16(root, join35(root, dir)).startsWith("..") ? "Must be a relative path inside the project." : undefined;
|
|
19910
19653
|
var titleize = (raw) => {
|
|
19911
19654
|
const words = raw.replaceAll(/[-_.]+/gu, " ").split(/\s+/u).filter(Boolean);
|
|
19912
19655
|
return words.length === 0 ? "My Docs" : words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
19913
19656
|
};
|
|
19914
19657
|
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
|
|
19658
|
+
var SOURCE_SNIPPETS = {
|
|
19659
|
+
"github-releases": ` // Changelog entries from GitHub Releases. Private repos read
|
|
19919
19660
|
// GITHUB_TOKEN from the environment.
|
|
19920
19661
|
{
|
|
19921
19662
|
type: "github-releases",
|
|
19922
19663
|
owner: "your-org",
|
|
19923
19664
|
repo: "your-repo",
|
|
19924
19665
|
prefix: "changelog",
|
|
19925
|
-
}
|
|
19926
|
-
|
|
19927
|
-
|
|
19928
|
-
|
|
19666
|
+
},`,
|
|
19667
|
+
"mdx-remote": ` // MDX fetched from a GitHub repo. Private repos read GITHUB_TOKEN
|
|
19668
|
+
// from the environment.
|
|
19669
|
+
{
|
|
19670
|
+
type: "mdx-remote",
|
|
19671
|
+
github: { owner: "your-org", repo: "your-repo", path: "docs" },
|
|
19672
|
+
prefix: "remote",
|
|
19673
|
+
},`,
|
|
19674
|
+
notion: ` // Pages from a Notion database. Reads NOTION_TOKEN from the environment.
|
|
19929
19675
|
{
|
|
19930
19676
|
type: "notion",
|
|
19931
19677
|
database: "your-database-id",
|
|
19932
19678
|
prefix: "notion",
|
|
19933
|
-
}
|
|
19934
|
-
|
|
19935
|
-
case "sanity": {
|
|
19936
|
-
return ` // Documents from a Sanity dataset. Private datasets read SANITY_TOKEN
|
|
19679
|
+
},`,
|
|
19680
|
+
sanity: ` // Documents from a Sanity dataset. Private datasets read SANITY_TOKEN
|
|
19937
19681
|
// from the environment.
|
|
19938
19682
|
{
|
|
19939
19683
|
type: "sanity",
|
|
@@ -19941,21 +19685,7 @@ var sourceSnippetFor = (kind) => {
|
|
|
19941
19685
|
dataset: "production",
|
|
19942
19686
|
query: \`*[_type == "doc"]\`,
|
|
19943
19687
|
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
|
-
}
|
|
19688
|
+
},`
|
|
19959
19689
|
};
|
|
19960
19690
|
var contentBlockFor = (answers) => {
|
|
19961
19691
|
const sources = answers.sources.length === 0 ? ["filesystem"] : answers.sources;
|
|
@@ -19965,7 +19695,7 @@ var contentBlockFor = (answers) => {
|
|
|
19965
19695
|
root: ${JSON.stringify(answers.contentDir)},
|
|
19966
19696
|
},`;
|
|
19967
19697
|
}
|
|
19968
|
-
const entries = SOURCE_KINDS.filter((kind) => sources.includes(kind)).map((kind) => kind === "filesystem" ? ` { type: "filesystem", root: ${JSON.stringify(answers.contentDir)} },` :
|
|
19698
|
+
const entries = SOURCE_KINDS.filter((kind) => sources.includes(kind)).map((kind) => kind === "filesystem" ? ` { type: "filesystem", root: ${JSON.stringify(answers.contentDir)} },` : SOURCE_SNIPPETS[kind]);
|
|
19969
19699
|
return `
|
|
19970
19700
|
content: {
|
|
19971
19701
|
sources: [
|
|
@@ -19988,7 +19718,7 @@ var extraDepsFor = (sources) => ({
|
|
|
19988
19718
|
var buildPlan = (root, answers) => {
|
|
19989
19719
|
const files = [
|
|
19990
19720
|
{
|
|
19991
|
-
content: blumePackageJson(toPackageName(
|
|
19721
|
+
content: blumePackageJson(toPackageName(basename4(root)), extraDepsFor(answers.sources)),
|
|
19992
19722
|
path: join35(root, "package.json")
|
|
19993
19723
|
},
|
|
19994
19724
|
{ content: buildConfig(answers), path: join35(root, "blume.config.ts") }
|
|
@@ -20003,14 +19733,14 @@ var writeFileSafe = async (file, log) => {
|
|
|
20003
19733
|
log.info(`Skipped existing ${file.path}`);
|
|
20004
19734
|
return false;
|
|
20005
19735
|
}
|
|
20006
|
-
await
|
|
20007
|
-
await
|
|
19736
|
+
await mkdir10(dirname14(file.path), { recursive: true });
|
|
19737
|
+
await writeFile10(file.path, file.content, "utf-8");
|
|
20008
19738
|
log.success(`Created ${file.path}`);
|
|
20009
19739
|
return true;
|
|
20010
19740
|
};
|
|
20011
19741
|
var applyPlan = async (files, log) => {
|
|
20012
19742
|
const created = await Promise.all(files.map((file) => writeFileSafe(file, log)));
|
|
20013
|
-
const createdPackage = files.some((file, index) => created[index] &&
|
|
19743
|
+
const createdPackage = files.some((file, index) => created[index] && basename4(file.path) === "package.json");
|
|
20014
19744
|
return { createdPackage };
|
|
20015
19745
|
};
|
|
20016
19746
|
var envVarsFor = (sources) => [
|
|
@@ -20164,19 +19894,10 @@ Rules:
|
|
|
20164
19894
|
When you are done, print the file and suggest running \`blume eval\` to try it.`;
|
|
20165
19895
|
|
|
20166
19896
|
// src/eval/report.ts
|
|
20167
|
-
import { mkdtemp as mkdtemp2, writeFile as
|
|
19897
|
+
import { mkdtemp as mkdtemp2, writeFile as writeFile11 } from "node:fs/promises";
|
|
20168
19898
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
19899
|
+
import { colors as colors4 } from "consola/utils";
|
|
20169
19900
|
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
19901
|
var GLYPH2 = {
|
|
20181
19902
|
error: "!",
|
|
20182
19903
|
fail: "✖",
|
|
@@ -20184,10 +19905,10 @@ var GLYPH2 = {
|
|
|
20184
19905
|
skip: "⊘"
|
|
20185
19906
|
};
|
|
20186
19907
|
var STATUS_COLOR = {
|
|
20187
|
-
error:
|
|
20188
|
-
fail:
|
|
20189
|
-
pass:
|
|
20190
|
-
skip:
|
|
19908
|
+
error: colors4.yellow,
|
|
19909
|
+
fail: colors4.red,
|
|
19910
|
+
pass: colors4.green,
|
|
19911
|
+
skip: colors4.dim
|
|
20191
19912
|
};
|
|
20192
19913
|
var ID_PAD = 28;
|
|
20193
19914
|
var seconds = (ms) => `${(ms / 1000).toFixed(1)}s`;
|
|
@@ -20202,17 +19923,18 @@ var duration = (ms) => {
|
|
|
20202
19923
|
};
|
|
20203
19924
|
var questionLine = (result) => {
|
|
20204
19925
|
const color = STATUS_COLOR[result.status];
|
|
20205
|
-
const glyph =
|
|
19926
|
+
const glyph = color(GLYPH2[result.status]);
|
|
20206
19927
|
const id2 = result.id.padEnd(ID_PAD);
|
|
20207
19928
|
if (result.status === "skip") {
|
|
20208
|
-
return ` ${glyph} ${id2} ${
|
|
19929
|
+
return ` ${glyph} ${id2} ${colors4.dim("skipped")}`;
|
|
20209
19930
|
}
|
|
20210
19931
|
const score = result.score === undefined ? "" : result.score.toFixed(2);
|
|
19932
|
+
const cost = money(result.costUsd);
|
|
20211
19933
|
const cells = [
|
|
20212
|
-
|
|
19934
|
+
color(result.status),
|
|
20213
19935
|
score,
|
|
20214
|
-
|
|
20215
|
-
|
|
19936
|
+
colors4.dim(seconds(result.durationMs)),
|
|
19937
|
+
cost === "" ? "" : colors4.dim(cost)
|
|
20216
19938
|
].filter((cell) => cell !== "").join(" ");
|
|
20217
19939
|
return ` ${glyph} ${id2} ${cells}`;
|
|
20218
19940
|
};
|
|
@@ -20220,15 +19942,15 @@ var questionDetails = (result, verbose) => {
|
|
|
20220
19942
|
const lines = [];
|
|
20221
19943
|
if (result.status === "fail") {
|
|
20222
19944
|
for (const fact of result.missing) {
|
|
20223
|
-
lines.push(` ${
|
|
19945
|
+
lines.push(` ${colors4.dim(`missing: ${fact}`)}`);
|
|
20224
19946
|
}
|
|
20225
19947
|
}
|
|
20226
19948
|
if (result.status === "error" && result.detail) {
|
|
20227
|
-
lines.push(` ${
|
|
19949
|
+
lines.push(` ${colors4.dim(result.detail)}`);
|
|
20228
19950
|
}
|
|
20229
19951
|
if (verbose && result.answer && result.status !== "pass") {
|
|
20230
19952
|
lines.push(...result.answer.split(`
|
|
20231
|
-
`).map((line) => ` ${
|
|
19953
|
+
`).map((line) => ` ${colors4.dim(`> ${line}`)}`));
|
|
20232
19954
|
}
|
|
20233
19955
|
return lines;
|
|
20234
19956
|
};
|
|
@@ -20244,15 +19966,15 @@ var summaryLine2 = (result) => {
|
|
|
20244
19966
|
].filter((part) => part !== "");
|
|
20245
19967
|
return parts.join(" · ");
|
|
20246
19968
|
};
|
|
20247
|
-
var headerLine = (total, agent) => `${
|
|
20248
|
-
var startLine = (id2, index, total) => ` ${
|
|
19969
|
+
var headerLine = (total, agent) => `${colors4.bold("blume eval")} ${total} question(s) · ${AGENTS[agent].name}`;
|
|
19970
|
+
var startLine = (id2, index, total) => ` ${colors4.dim(`▸ ${id2} (${index + 1}/${total})`)}`;
|
|
20249
19971
|
var fixLines = (result, root) => result.diagnostics.filter((diagnostic) => diagnostic.code !== "BLUME_EVAL_ROUTE_UNKNOWN").map((finding2) => {
|
|
20250
19972
|
const site = finding2.file ? `${relative18(root, finding2.file)}${finding2.line ? `:${finding2.line}` : ""}` : "";
|
|
20251
|
-
return ` ${
|
|
19973
|
+
return ` ${colors4.cyan("fix:")} ${site} ${colors4.dim(finding2.message)}`;
|
|
20252
19974
|
});
|
|
20253
19975
|
var warningLines = (result, root) => result.diagnostics.filter((diagnostic) => diagnostic.code === "BLUME_EVAL_ROUTE_UNKNOWN").map((finding2) => {
|
|
20254
19976
|
const site = finding2.file ? ` ${relative18(root, finding2.file)}${finding2.line ? `:${finding2.line}` : ""}` : "";
|
|
20255
|
-
return ` ${
|
|
19977
|
+
return ` ${colors4.yellow("⚠")}${site} ${colors4.dim(finding2.message)}`;
|
|
20256
19978
|
});
|
|
20257
19979
|
var evalReportJson = (result, root, threshold) => {
|
|
20258
19980
|
const diagnostics = result.diagnostics.map((diagnostic) => diagnostic.file ? { ...diagnostic, file: relative18(root, diagnostic.file) } : diagnostic);
|
|
@@ -20273,18 +19995,18 @@ var evalReportJson = (result, root, threshold) => {
|
|
|
20273
19995
|
var writeEvalReport = async (result, root, threshold) => {
|
|
20274
19996
|
const dir = await mkdtemp2(join36(tmpdir2(), "blume-eval-"));
|
|
20275
19997
|
const path = join36(dir, "report.json");
|
|
20276
|
-
await
|
|
19998
|
+
await writeFile11(path, evalReportJson(result, root, threshold));
|
|
20277
19999
|
return path;
|
|
20278
20000
|
};
|
|
20279
20001
|
|
|
20280
20002
|
// src/eval/run.ts
|
|
20281
|
-
import { mkdir as
|
|
20003
|
+
import { mkdir as mkdir11, mkdtemp as mkdtemp3, writeFile as writeFile13 } from "node:fs/promises";
|
|
20282
20004
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
20283
20005
|
import { join as join38 } from "pathe";
|
|
20284
20006
|
|
|
20285
20007
|
// src/eval/agents.ts
|
|
20286
20008
|
import { spawn as spawn2 } from "node:child_process";
|
|
20287
|
-
import { readFile as readFile20, writeFile as
|
|
20009
|
+
import { readFile as readFile20, writeFile as writeFile12 } from "node:fs/promises";
|
|
20288
20010
|
import { join as join37 } from "pathe";
|
|
20289
20011
|
import { z as z3 } from "zod";
|
|
20290
20012
|
var KILL_GRACE_MS = 5000;
|
|
@@ -20357,7 +20079,7 @@ var writeMcpConfig = async (dir, snapshotPath, launcher) => {
|
|
|
20357
20079
|
[MCP_SERVER_NAME]: { args: resolved.args, command: resolved.command }
|
|
20358
20080
|
}
|
|
20359
20081
|
};
|
|
20360
|
-
await
|
|
20082
|
+
await writeFile12(configPath, JSON.stringify(config, null, 2));
|
|
20361
20083
|
return {
|
|
20362
20084
|
configPath,
|
|
20363
20085
|
serverArgs: resolved.args,
|
|
@@ -20632,7 +20354,7 @@ var runQuestion = async (question, index, context) => {
|
|
|
20632
20354
|
const started = performance.now();
|
|
20633
20355
|
const elapsed = () => Math.round(performance.now() - started);
|
|
20634
20356
|
const workDir = join38(context.dir, `work-${index}`);
|
|
20635
|
-
await
|
|
20357
|
+
await mkdir11(workDir, { recursive: true });
|
|
20636
20358
|
const answerPath = join38(workDir, "answer.txt");
|
|
20637
20359
|
const reader = await context.run(context.bin, agentArgs(context.kind, { lastMessagePath: answerPath, mcp: context.mcp }), {
|
|
20638
20360
|
cwd: workDir,
|
|
@@ -20690,7 +20412,7 @@ var runEval = async (options) => {
|
|
|
20690
20412
|
const anchor = { path: options.evalsPath, raw: options.rawEvals };
|
|
20691
20413
|
const dir = await mkdtemp3(join38(tmpdir3(), "blume-eval-"));
|
|
20692
20414
|
const snapshotPath = join38(dir, "mcp-data.json");
|
|
20693
|
-
await
|
|
20415
|
+
await writeFile13(snapshotPath, JSON.stringify(await buildMcpData(options.project)));
|
|
20694
20416
|
const mcp = await writeMcpConfig(dir, snapshotPath);
|
|
20695
20417
|
const context = {
|
|
20696
20418
|
bin: AGENTS[kind].bin,
|
|
@@ -20969,7 +20691,7 @@ import { defineCommand as defineCommand9 } from "citty";
|
|
|
20969
20691
|
import { resolve as resolve12 } from "pathe";
|
|
20970
20692
|
|
|
20971
20693
|
// src/cli/init/questions.ts
|
|
20972
|
-
import { basename as
|
|
20694
|
+
import { basename as basename5, resolve as resolve11 } from "pathe";
|
|
20973
20695
|
var cancelled = (value) => typeof value === "symbol";
|
|
20974
20696
|
var collectAnswers = async (prompter, flags, defaults) => {
|
|
20975
20697
|
const directory = flags.directory ?? await prompter.text({
|
|
@@ -20982,7 +20704,7 @@ var collectAnswers = async (prompter, flags, defaults) => {
|
|
|
20982
20704
|
}
|
|
20983
20705
|
const root = resolve11(defaults.cwd, directory);
|
|
20984
20706
|
const title = await prompter.text({
|
|
20985
|
-
initialValue: titleize(
|
|
20707
|
+
initialValue: titleize(basename5(root)),
|
|
20986
20708
|
message: "What's your docs site called?",
|
|
20987
20709
|
validate: (value) => value?.trim() ? undefined : "Give your docs site a name."
|
|
20988
20710
|
});
|
|
@@ -21606,8 +21328,8 @@ var translateAgentArgs = (kind, lastMessagePath) => kind === "claude" ? claudeAr
|
|
|
21606
21328
|
|
|
21607
21329
|
// src/translate/ledger.ts
|
|
21608
21330
|
import { createHash as createHash4 } from "node:crypto";
|
|
21609
|
-
import {
|
|
21610
|
-
import {
|
|
21331
|
+
import { readFile as readFile23 } from "node:fs/promises";
|
|
21332
|
+
import { join as join42 } from "pathe";
|
|
21611
21333
|
import { z as z5 } from "zod";
|
|
21612
21334
|
var LEDGER_FILE = "blume.translations.json";
|
|
21613
21335
|
var ledgerSchema = z5.object({
|
|
@@ -21656,15 +21378,7 @@ var writeLedger = async (root, ledger) => {
|
|
|
21656
21378
|
if (existing === content) {
|
|
21657
21379
|
return false;
|
|
21658
21380
|
}
|
|
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
|
-
}
|
|
21381
|
+
await writeTextAtomic(path, content);
|
|
21668
21382
|
return true;
|
|
21669
21383
|
};
|
|
21670
21384
|
var stampLedger = (ledger, sourceRel, locale, hash) => {
|
|
@@ -21687,25 +21401,17 @@ var pruneLedger = (ledger, knownSources, knownLocales) => {
|
|
|
21687
21401
|
};
|
|
21688
21402
|
|
|
21689
21403
|
// 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
|
-
};
|
|
21404
|
+
import { colors as colors5 } from "consola/utils";
|
|
21405
|
+
var ESC = String.fromCodePoint(27);
|
|
21700
21406
|
var GLYPH3 = {
|
|
21701
21407
|
failed: "✖",
|
|
21702
21408
|
partial: "!",
|
|
21703
21409
|
translated: "✔"
|
|
21704
21410
|
};
|
|
21705
21411
|
var STATUS_COLOR2 = {
|
|
21706
|
-
failed:
|
|
21707
|
-
partial:
|
|
21708
|
-
translated:
|
|
21412
|
+
failed: colors5.red,
|
|
21413
|
+
partial: colors5.yellow,
|
|
21414
|
+
translated: colors5.green
|
|
21709
21415
|
};
|
|
21710
21416
|
var SPINNER_FRAMES = [
|
|
21711
21417
|
"⠋",
|
|
@@ -21720,7 +21426,7 @@ var SPINNER_FRAMES = [
|
|
|
21720
21426
|
"⠏"
|
|
21721
21427
|
];
|
|
21722
21428
|
var SPINNER_INTERVAL_MS = 80;
|
|
21723
|
-
var REWRITE = `\r${
|
|
21429
|
+
var REWRITE = `\r${ESC}[K`;
|
|
21724
21430
|
var seconds2 = (ms) => `${(ms / 1000).toFixed(1)}s`;
|
|
21725
21431
|
var money2 = (cost) => cost === undefined ? "" : `$${cost.toFixed(2)}`;
|
|
21726
21432
|
var duration2 = (ms) => {
|
|
@@ -21735,20 +21441,20 @@ var itemLabel = (item) => item.kind === "page" ? `${item.sourceRel} → ${item.l
|
|
|
21735
21441
|
var spinnerLine = (active, done, total, frame) => {
|
|
21736
21442
|
const first = active[0];
|
|
21737
21443
|
const more = active.length > 1 ? ` (+${active.length - 1} more)` : "";
|
|
21738
|
-
return ` ${
|
|
21444
|
+
return ` ${colors5.cyan(SPINNER_FRAMES[frame % SPINNER_FRAMES.length])} ${itemLabel(first)}${more} ${colors5.dim(`${done}/${total}`)}`;
|
|
21739
21445
|
};
|
|
21740
21446
|
var itemEndLine = (result) => {
|
|
21741
21447
|
const color = STATUS_COLOR2[result.status];
|
|
21742
|
-
const glyph =
|
|
21448
|
+
const glyph = color(GLYPH3[result.status]);
|
|
21743
21449
|
const label = itemLabel(result.item);
|
|
21744
21450
|
if (result.status === "translated") {
|
|
21745
21451
|
const cells = [seconds2(result.durationMs), money2(result.costUsd)].filter((cell) => cell !== "").join(" ");
|
|
21746
|
-
return ` ${glyph} ${label} ${
|
|
21452
|
+
return ` ${glyph} ${label} ${colors5.dim(cells)}`;
|
|
21747
21453
|
}
|
|
21748
21454
|
const word = result.status === "partial" ? "partial" : "failed";
|
|
21749
|
-
return ` ${glyph} ${label} ${color
|
|
21455
|
+
return ` ${glyph} ${label} ${color(word)}${result.detail ? colors5.dim(`: ${result.detail}`) : ""}`;
|
|
21750
21456
|
};
|
|
21751
|
-
var translateHeaderLine = (itemCount, localeCount, agent) => `${
|
|
21457
|
+
var translateHeaderLine = (itemCount, localeCount, agent) => `${colors5.bold("blume translate")} ${itemCount} item(s) · ${localeCount} locale(s) · ${AGENTS[agent].name}`;
|
|
21752
21458
|
var translateSummaryLine = (result, workList) => {
|
|
21753
21459
|
const { counts } = result;
|
|
21754
21460
|
const parts = [
|
|
@@ -21762,7 +21468,7 @@ var translateSummaryLine = (result, workList) => {
|
|
|
21762
21468
|
].filter((part) => part !== "");
|
|
21763
21469
|
return parts.join(" · ");
|
|
21764
21470
|
};
|
|
21765
|
-
var diagnosticLines = (diagnostics) => diagnostics.map((diagnostic) => ` ${
|
|
21471
|
+
var diagnosticLines = (diagnostics) => diagnostics.map((diagnostic) => ` ${colors5.yellow("⚠")} ${colors5.dim(diagnostic.message)}`);
|
|
21766
21472
|
var driftRows = (workList) => workList.items.flatMap((item) => item.kind === "page" ? [
|
|
21767
21473
|
{
|
|
21768
21474
|
locale: item.locale,
|
|
@@ -21775,8 +21481,8 @@ var driftRows = (workList) => workList.items.flatMap((item) => item.kind === "pa
|
|
|
21775
21481
|
status: entry.status
|
|
21776
21482
|
})));
|
|
21777
21483
|
var checkLines = (workList) => [
|
|
21778
|
-
...driftRows(workList).map((row) => ` ${
|
|
21779
|
-
...workList.untracked.map((entry) => ` ${
|
|
21484
|
+
...driftRows(workList).map((row) => ` ${colors5.red("✖")} ${row.sourceRel} → ${row.locale} ${colors5.dim(row.status)}`),
|
|
21485
|
+
...workList.untracked.map((entry) => ` ${colors5.dim(`⊘ ${entry.sourceRel} → ${entry.locale} untracked (adopted by the next translate run)`)}`)
|
|
21780
21486
|
];
|
|
21781
21487
|
var checkSummaryLine = (workList) => {
|
|
21782
21488
|
const rows = driftRows(workList);
|
|
@@ -21897,20 +21603,13 @@ var createProgressRenderer = (options) => {
|
|
|
21897
21603
|
|
|
21898
21604
|
// src/translate/run.ts
|
|
21899
21605
|
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";
|
|
21606
|
+
import { mkdtemp as mkdtemp4, readFile as readFile25 } from "node:fs/promises";
|
|
21908
21607
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
21909
|
-
import {
|
|
21608
|
+
import { join as join44 } from "pathe";
|
|
21910
21609
|
|
|
21911
21610
|
// src/translate/meta.ts
|
|
21912
21611
|
import { readFile as readFile24 } from "node:fs/promises";
|
|
21913
|
-
import { dirname as
|
|
21612
|
+
import { dirname as dirname15, join as join43, relative as relative19 } from "pathe";
|
|
21914
21613
|
import { glob as glob8 } from "tinyglobby";
|
|
21915
21614
|
var META_FILES2 = ["**/meta.ts", "**/meta.js", "**/meta.mjs"];
|
|
21916
21615
|
var metaTargetPath = (meta, locale) => join43(meta.contentRoot, locale, meta.dir, "meta.ts");
|
|
@@ -21932,7 +21631,7 @@ var discoverTranslatableMeta = async (project) => {
|
|
|
21932
21631
|
onlyFiles: true
|
|
21933
21632
|
});
|
|
21934
21633
|
for (const file of files.toSorted()) {
|
|
21935
|
-
const dir = relative19(contentRoot2,
|
|
21634
|
+
const dir = relative19(contentRoot2, dirname15(file));
|
|
21936
21635
|
const first = dir.split("/")[0]?.toLowerCase();
|
|
21937
21636
|
if (first && localeDirs.has(first)) {
|
|
21938
21637
|
continue;
|
|
@@ -22127,17 +21826,6 @@ var parseMetaTitles = (agentText, expectedKeys) => {
|
|
|
22127
21826
|
|
|
22128
21827
|
// src/translate/run.ts
|
|
22129
21828
|
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
21829
|
var invokeAgent = async (context, prompt, index) => {
|
|
22142
21830
|
const messagePath = join44(context.dir, `message-${index}.txt`);
|
|
22143
21831
|
const result = await context.run(context.bin, translateAgentArgs(context.kind, messagePath), { cwd: context.dir, prompt, timeoutMs: context.timeoutMs });
|
|
@@ -22168,7 +21856,7 @@ var runPageItem = async (item, index, context, ledger) => {
|
|
|
22168
21856
|
if (!validated.ok) {
|
|
22169
21857
|
return done("failed", validated.reason, output.costUsd);
|
|
22170
21858
|
}
|
|
22171
|
-
await
|
|
21859
|
+
await writeTextAtomic(item.targetPath, validated.text);
|
|
22172
21860
|
stampLedger(ledger, item.sourceRel, item.locale, hashSource(sourceText));
|
|
22173
21861
|
return done("translated", undefined, output.costUsd);
|
|
22174
21862
|
};
|
|
@@ -22193,7 +21881,7 @@ var runMetaItem = async (item, index, context, ledger) => {
|
|
|
22193
21881
|
if (translated === undefined) {
|
|
22194
21882
|
continue;
|
|
22195
21883
|
}
|
|
22196
|
-
await
|
|
21884
|
+
await writeTextAtomic(entry.targetPath, generateMetaModule(entry.meta.data, translated));
|
|
22197
21885
|
stampLedger(ledger, entry.meta.sourceRel, item.locale, hashSource(entry.meta.raw));
|
|
22198
21886
|
}
|
|
22199
21887
|
if (parsed.missing.length === item.entries.length) {
|
|
@@ -22293,13 +21981,9 @@ var runTranslate = async (options) => {
|
|
|
22293
21981
|
// src/translate/work-list.ts
|
|
22294
21982
|
import { existsSync as existsSync25 } from "node:fs";
|
|
22295
21983
|
import { readFile as readFile26 } from "node:fs/promises";
|
|
22296
|
-
import { dirname as
|
|
21984
|
+
import { dirname as dirname16, extname as extname8, join as join45, relative as relative20 } from "pathe";
|
|
22297
21985
|
var PAGE_EXTENSIONS = new Set([".md", ".mdx"]);
|
|
22298
|
-
var translatablePages = (project) => {
|
|
22299
|
-
const { i18n } = project.config;
|
|
22300
|
-
if (!i18n) {
|
|
22301
|
-
return [];
|
|
22302
|
-
}
|
|
21986
|
+
var translatablePages = (project, i18n) => {
|
|
22303
21987
|
const rootsByName = new Map(project.sources.flatMap((source) => source.staged || !source.contentRoot ? [] : [[source.name, source.contentRoot]]));
|
|
22304
21988
|
const seen = new Set;
|
|
22305
21989
|
const universe = [];
|
|
@@ -22337,7 +22021,7 @@ var computeWorkList = async (project, ledger, options = {}) => {
|
|
|
22337
22021
|
const untracked = [];
|
|
22338
22022
|
const pageItems = [];
|
|
22339
22023
|
let upToDate = 0;
|
|
22340
|
-
for (const { page: page2, contentRoot: contentRoot2, ext, sourcePath } of translatablePages(project)) {
|
|
22024
|
+
for (const { page: page2, contentRoot: contentRoot2, ext, sourcePath } of translatablePages(project, i18n)) {
|
|
22341
22025
|
const sourceRel = relative20(root, sourcePath);
|
|
22342
22026
|
knownSources.add(sourceRel);
|
|
22343
22027
|
const hash = hashSource(await readFile26(sourcePath, "utf-8"));
|
|
@@ -22376,7 +22060,7 @@ var computeWorkList = async (project, ledger, options = {}) => {
|
|
|
22376
22060
|
const entries = [];
|
|
22377
22061
|
for (const source of meta.metas) {
|
|
22378
22062
|
knownSources.add(source.sourceRel);
|
|
22379
|
-
const targetDir =
|
|
22063
|
+
const targetDir = dirname16(metaTargetPath(source, locale));
|
|
22380
22064
|
const exists = ["meta.ts", "meta.js", "meta.mjs"].some((name) => existsSync25(join45(targetDir, name)));
|
|
22381
22065
|
const hash = hashSource(source.raw);
|
|
22382
22066
|
const stamp = ledger.files[source.sourceRel]?.[locale];
|
|
@@ -22615,7 +22299,7 @@ import { join as join47 } from "pathe";
|
|
|
22615
22299
|
|
|
22616
22300
|
// src/core/links.ts
|
|
22617
22301
|
import { existsSync as existsSync26 } from "node:fs";
|
|
22618
|
-
import { basename as
|
|
22302
|
+
import { basename as basename6, join as join46 } from "pathe";
|
|
22619
22303
|
var HTTP = /^https?:\/\//iu;
|
|
22620
22304
|
var PROTOCOL_RELATIVE = /^\/\//u;
|
|
22621
22305
|
var SCHEME = /^[a-z][a-z0-9+.-]*:/iu;
|
|
@@ -22630,7 +22314,7 @@ var DOC_EXT = /\.(?:md|mdx)$/iu;
|
|
|
22630
22314
|
var FILE_EXT = /\.[a-z0-9]+$/iu;
|
|
22631
22315
|
var assetIsPresent = (resolved, ctx) => ctx.publicDir !== null && existsSync26(join46(ctx.publicDir, resolved));
|
|
22632
22316
|
var NUMERIC_PREFIX3 = /^\d+[-_.]/u;
|
|
22633
|
-
var isIndexPage = (page2) => /^index\.(?:md|mdx)$/iu.test(
|
|
22317
|
+
var isIndexPage = (page2) => /^index\.(?:md|mdx)$/iu.test(basename6(page2.navPath).replace(NUMERIC_PREFIX3, ""));
|
|
22634
22318
|
var applyRelativePart = (segments, part) => {
|
|
22635
22319
|
if (part === "" || part === ".") {
|
|
22636
22320
|
return;
|
|
@@ -22909,5 +22593,5 @@ process.on("unhandledRejection", (error) => {
|
|
|
22909
22593
|
});
|
|
22910
22594
|
runMain(main);
|
|
22911
22595
|
|
|
22912
|
-
//# debugId=
|
|
22596
|
+
//# debugId=84600BB45DA0E5EB64756E2164756E21
|
|
22913
22597
|
//# sourceMappingURL=index.js.map
|