blume 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1162 -455
- package/dist/cli/index.js.map +32 -28
- package/dist/types/core/bridge.d.ts +24 -0
- package/dist/types/core/config.d.ts +35 -0
- package/dist/types/core/data.d.ts +129 -0
- package/dist/types/core/define-components.d.ts +27 -0
- package/dist/types/core/define-meta.d.ts +16 -0
- package/dist/types/core/deployment-env.d.ts +9 -0
- package/dist/types/core/diagnostics.d.ts +17 -0
- package/dist/types/core/i18n-ui.d.ts +500 -0
- package/dist/types/core/load-module.d.ts +7 -0
- package/dist/types/core/package-root.d.ts +17 -0
- package/dist/types/core/project.d.ts +9 -0
- package/dist/types/core/schema.d.ts +3451 -0
- package/dist/types/core/sources/types.d.ts +107 -0
- package/dist/types/core/types.d.ts +245 -0
- package/dist/types/core/ui-packs/ar.d.ts +3 -0
- package/dist/types/core/ui-packs/bg.d.ts +3 -0
- package/dist/types/core/ui-packs/bn.d.ts +3 -0
- package/dist/types/core/ui-packs/ca.d.ts +3 -0
- package/dist/types/core/ui-packs/cs.d.ts +3 -0
- package/dist/types/core/ui-packs/da.d.ts +3 -0
- package/dist/types/core/ui-packs/de.d.ts +3 -0
- package/dist/types/core/ui-packs/el.d.ts +3 -0
- package/dist/types/core/ui-packs/es.d.ts +3 -0
- package/dist/types/core/ui-packs/fa.d.ts +3 -0
- package/dist/types/core/ui-packs/fi.d.ts +3 -0
- package/dist/types/core/ui-packs/fr.d.ts +3 -0
- package/dist/types/core/ui-packs/he.d.ts +3 -0
- package/dist/types/core/ui-packs/hi.d.ts +3 -0
- package/dist/types/core/ui-packs/hr.d.ts +3 -0
- package/dist/types/core/ui-packs/hu.d.ts +3 -0
- package/dist/types/core/ui-packs/id.d.ts +3 -0
- package/dist/types/core/ui-packs/index.d.ts +13 -0
- package/dist/types/core/ui-packs/it.d.ts +3 -0
- package/dist/types/core/ui-packs/ja.d.ts +3 -0
- package/dist/types/core/ui-packs/ko.d.ts +3 -0
- package/dist/types/core/ui-packs/nl.d.ts +3 -0
- package/dist/types/core/ui-packs/no.d.ts +3 -0
- package/dist/types/core/ui-packs/pl.d.ts +3 -0
- package/dist/types/core/ui-packs/pt-br.d.ts +3 -0
- package/dist/types/core/ui-packs/pt.d.ts +3 -0
- package/dist/types/core/ui-packs/ro.d.ts +3 -0
- package/dist/types/core/ui-packs/ru.d.ts +3 -0
- package/dist/types/core/ui-packs/sk.d.ts +3 -0
- package/dist/types/core/ui-packs/sr.d.ts +3 -0
- package/dist/types/core/ui-packs/sv.d.ts +3 -0
- package/dist/types/core/ui-packs/th.d.ts +3 -0
- package/dist/types/core/ui-packs/tr.d.ts +3 -0
- package/dist/types/core/ui-packs/uk.d.ts +3 -0
- package/dist/types/core/ui-packs/vi.d.ts +3 -0
- package/dist/types/core/ui-packs/zh-tw.d.ts +3 -0
- package/dist/types/core/ui-packs/zh.d.ts +3 -0
- package/dist/types/core/version.d.ts +8 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/migrate/mintlify/config.d.ts +2 -0
- package/dist/types/migrate/mintlify/i18n.d.ts +7 -0
- package/dist/types/theme/fonts.d.ts +163 -0
- package/docs/advanced/custom-pages.mdx +91 -10
- package/docs/configuration/index.mdx +19 -0
- package/docs/content/components.mdx +87 -1
- package/package.json +13 -3
- package/src/ai/llms.ts +1 -2
- package/src/astro/examples.ts +104 -0
- package/src/astro/generate.ts +197 -69
- package/src/astro/islands.ts +1 -1
- package/src/astro/pages.ts +59 -0
- package/src/astro/templates.ts +136 -9
- package/src/cli/commands/validate.ts +1 -0
- package/src/components/content/CodeBlock.astro +28 -0
- package/src/components/content/Component.astro +65 -0
- package/src/components/content/Diff.astro +44 -0
- package/src/components/content/Tab.astro +8 -2
- package/src/components/content/diff.ts +95 -0
- package/src/components/layout/Favicon.astro +11 -4
- package/src/components/layout/PageLayout.astro +173 -0
- package/src/components/layout/ReferenceLayout.astro +6 -1
- package/src/components/layout/RootLayout.astro +9 -5
- package/src/components/layout/head-scripts.ts +19 -0
- package/src/core/data.ts +128 -0
- package/src/core/frontmatter.ts +43 -0
- package/src/core/links.ts +26 -10
- package/src/core/sources/filesystem.ts +1 -1
- package/src/core/sources/mdx-remote.ts +1 -2
- package/src/core/sources/mintlify.ts +1 -1
- package/src/core/sources/normalize.ts +19 -3
- package/src/core/sources/notion.ts +1 -1
- package/src/core/sources/sanity.ts +1 -1
- package/src/core/tsconfig-aliases.ts +201 -0
- package/src/index.ts +12 -0
- package/src/markdown/index.ts +69 -0
- package/src/migrate/fumadocs/config.ts +53 -4
- package/src/migrate/fumadocs/content.ts +1 -1
- package/src/migrate/fumadocs/groups.ts +230 -0
- package/src/migrate/fumadocs/index.ts +104 -19
- package/src/migrate/fumadocs/meta.ts +140 -10
- package/src/migrate/mintlify/snippets.ts +2 -1
- package/src/migrate/mintlify/transform.ts +1 -2
- package/src/migrate/nextra/index.ts +1 -1
- package/src/migrate/shared.ts +98 -1
- package/src/migrate/starlight/index.ts +1 -1
- package/src/registry/eject.ts +57 -10
- package/src/search/documents.ts +1 -2
- package/src/theme/entry.ts +29 -0
package/dist/cli/index.js
CHANGED
|
@@ -279,14 +279,30 @@ Next steps:
|
|
|
279
279
|
});
|
|
280
280
|
|
|
281
281
|
// src/cli/commands/build.ts
|
|
282
|
-
import { existsSync as
|
|
282
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
283
283
|
import { writeFile as writeFile6 } from "node:fs/promises";
|
|
284
284
|
import { build } from "astro";
|
|
285
285
|
import { defineCommand as defineCommand2 } from "citty";
|
|
286
|
-
import { join as
|
|
286
|
+
import { join as join23 } from "pathe";
|
|
287
287
|
|
|
288
|
-
// src/
|
|
289
|
-
import
|
|
288
|
+
// src/core/frontmatter.ts
|
|
289
|
+
import baseMatter from "gray-matter";
|
|
290
|
+
import { dump, load } from "js-yaml";
|
|
291
|
+
var yamlEngine = {
|
|
292
|
+
parse: (input) => load(input) ?? {},
|
|
293
|
+
stringify: (data) => dump(data)
|
|
294
|
+
};
|
|
295
|
+
var withYamlEngine = (options) => ({
|
|
296
|
+
...options,
|
|
297
|
+
engines: {
|
|
298
|
+
yaml: yamlEngine,
|
|
299
|
+
...options?.engines
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
var matter = Object.assign((input, options) => baseMatter(input, withYamlEngine(options)), baseMatter, {
|
|
303
|
+
stringify: (file, data, options) => baseMatter.stringify(file, data, withYamlEngine(options))
|
|
304
|
+
});
|
|
305
|
+
var frontmatter_default = matter;
|
|
290
306
|
|
|
291
307
|
// src/core/sources/read.ts
|
|
292
308
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
@@ -335,7 +351,7 @@ var buildFull = async (project) => {
|
|
|
335
351
|
const pages = orderedPages(project);
|
|
336
352
|
const sections = await Promise.all(pages.map(async (page) => {
|
|
337
353
|
const raw = await readEntryText(project, page);
|
|
338
|
-
const body =
|
|
354
|
+
const body = frontmatter_default(raw).content.trim();
|
|
339
355
|
const url = pageUrl(page.route, config.deployment.site);
|
|
340
356
|
return [`# ${page.title}`, `Source: ${url}`, "", body].join(`
|
|
341
357
|
`);
|
|
@@ -473,9 +489,6 @@ var buildSearchIndex = async (outDir) => {
|
|
|
473
489
|
return result.page_count;
|
|
474
490
|
};
|
|
475
491
|
|
|
476
|
-
// src/search/documents.ts
|
|
477
|
-
import matter2 from "gray-matter";
|
|
478
|
-
|
|
479
492
|
// src/core/ui-packs/ar.ts
|
|
480
493
|
var ar = {
|
|
481
494
|
actions: {
|
|
@@ -2365,7 +2378,7 @@ var buildSearchDocuments = async (project, options) => {
|
|
|
2365
2378
|
return await Promise.all(indexable.map(async (route) => {
|
|
2366
2379
|
const page = pageById.get(route.id);
|
|
2367
2380
|
const raw = page ? await readEntryText(project, page) : "";
|
|
2368
|
-
const body = raw ? toPlainText(
|
|
2381
|
+
const body = raw ? toPlainText(frontmatter_default(raw).content) : "";
|
|
2369
2382
|
const tags = page?.meta?.search?.tags;
|
|
2370
2383
|
const crumb = crumbs.get(route.path);
|
|
2371
2384
|
return {
|
|
@@ -2501,19 +2514,20 @@ var syncSearchProvider = async (project, reporter) => {
|
|
|
2501
2514
|
};
|
|
2502
2515
|
|
|
2503
2516
|
// src/astro/generate.ts
|
|
2504
|
-
import { existsSync as
|
|
2517
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, realpathSync } from "node:fs";
|
|
2505
2518
|
import {
|
|
2519
|
+
lstat,
|
|
2506
2520
|
mkdir as mkdir2,
|
|
2507
|
-
readFile as
|
|
2521
|
+
readFile as readFile7,
|
|
2508
2522
|
rename,
|
|
2509
2523
|
rm,
|
|
2510
2524
|
symlink,
|
|
2511
2525
|
writeFile as writeFile2
|
|
2512
2526
|
} from "node:fs/promises";
|
|
2513
|
-
import { createRequire as
|
|
2514
|
-
import { pathToFileURL } from "node:url";
|
|
2515
|
-
import { dirname as
|
|
2516
|
-
import { glob as
|
|
2527
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
2528
|
+
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
2529
|
+
import { dirname as dirname6, join as join11, normalize, relative as relative5 } from "pathe";
|
|
2530
|
+
import { glob as glob4 } from "tinyglobby";
|
|
2517
2531
|
|
|
2518
2532
|
// src/ai/ask.ts
|
|
2519
2533
|
var ASK_PRESETS = {
|
|
@@ -2754,6 +2768,143 @@ var resolveUIStrings = (locale, options) => {
|
|
|
2754
2768
|
return dict;
|
|
2755
2769
|
};
|
|
2756
2770
|
|
|
2771
|
+
// src/core/tsconfig-aliases.ts
|
|
2772
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, statSync } from "node:fs";
|
|
2773
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
2774
|
+
import { pathToFileURL } from "node:url";
|
|
2775
|
+
import { dirname as dirname4, isAbsolute, join as join6, resolve as resolve2 } from "pathe";
|
|
2776
|
+
var stripJsonComments = (text) => {
|
|
2777
|
+
let out = "";
|
|
2778
|
+
let inString = false;
|
|
2779
|
+
for (let index = 0;index < text.length; index += 1) {
|
|
2780
|
+
const char = text[index];
|
|
2781
|
+
if (inString) {
|
|
2782
|
+
out += char;
|
|
2783
|
+
if (char === "\\") {
|
|
2784
|
+
out += text[index + 1] ?? "";
|
|
2785
|
+
index += 1;
|
|
2786
|
+
} else if (char === '"') {
|
|
2787
|
+
inString = false;
|
|
2788
|
+
}
|
|
2789
|
+
continue;
|
|
2790
|
+
}
|
|
2791
|
+
if (char === '"') {
|
|
2792
|
+
inString = true;
|
|
2793
|
+
out += char;
|
|
2794
|
+
continue;
|
|
2795
|
+
}
|
|
2796
|
+
if (char === "/" && text[index + 1] === "/") {
|
|
2797
|
+
const newline = text.indexOf(`
|
|
2798
|
+
`, index + 2);
|
|
2799
|
+
index = newline === -1 ? text.length : newline - 1;
|
|
2800
|
+
continue;
|
|
2801
|
+
}
|
|
2802
|
+
if (char === "/" && text[index + 1] === "*") {
|
|
2803
|
+
const end = text.indexOf("*/", index + 2);
|
|
2804
|
+
index = end === -1 ? text.length : end + 1;
|
|
2805
|
+
continue;
|
|
2806
|
+
}
|
|
2807
|
+
out += char;
|
|
2808
|
+
}
|
|
2809
|
+
return out;
|
|
2810
|
+
};
|
|
2811
|
+
var TRAILING_COMMA = /,(?<rest>\s*[}\]])/gu;
|
|
2812
|
+
var parseJsonc = (text) => {
|
|
2813
|
+
try {
|
|
2814
|
+
const cleaned = stripJsonComments(text).replaceAll(TRAILING_COMMA, "$<rest>");
|
|
2815
|
+
const value = JSON.parse(cleaned);
|
|
2816
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
2817
|
+
} catch {
|
|
2818
|
+
return null;
|
|
2819
|
+
}
|
|
2820
|
+
};
|
|
2821
|
+
var isFile = (path) => {
|
|
2822
|
+
try {
|
|
2823
|
+
return statSync(path).isFile();
|
|
2824
|
+
} catch {
|
|
2825
|
+
return false;
|
|
2826
|
+
}
|
|
2827
|
+
};
|
|
2828
|
+
var resolveExtends = (spec, fromDir) => {
|
|
2829
|
+
if (spec.startsWith(".") || isAbsolute(spec)) {
|
|
2830
|
+
const candidates = spec.endsWith(".json") ? [resolve2(fromDir, spec)] : [
|
|
2831
|
+
resolve2(fromDir, `${spec}.json`),
|
|
2832
|
+
resolve2(fromDir, spec, "tsconfig.json"),
|
|
2833
|
+
resolve2(fromDir, spec)
|
|
2834
|
+
];
|
|
2835
|
+
return candidates.find(isFile) ?? null;
|
|
2836
|
+
}
|
|
2837
|
+
try {
|
|
2838
|
+
const require_ = createRequire2(pathToFileURL(join6(fromDir, "_.js")).href);
|
|
2839
|
+
for (const sub of [`${spec}/tsconfig.json`, spec]) {
|
|
2840
|
+
try {
|
|
2841
|
+
return require_.resolve(sub);
|
|
2842
|
+
} catch {}
|
|
2843
|
+
}
|
|
2844
|
+
} catch {}
|
|
2845
|
+
return null;
|
|
2846
|
+
};
|
|
2847
|
+
var loadPaths = (file, seen) => {
|
|
2848
|
+
if (seen.has(file) || !existsSync3(file)) {
|
|
2849
|
+
return null;
|
|
2850
|
+
}
|
|
2851
|
+
seen.add(file);
|
|
2852
|
+
const json = parseJsonc(readFileSync2(file, "utf-8"));
|
|
2853
|
+
if (!json) {
|
|
2854
|
+
return null;
|
|
2855
|
+
}
|
|
2856
|
+
const options = json.compilerOptions ?? {};
|
|
2857
|
+
if (options.paths && typeof options.paths === "object") {
|
|
2858
|
+
const baseUrl = typeof options.baseUrl === "string" ? options.baseUrl : ".";
|
|
2859
|
+
return {
|
|
2860
|
+
baseDir: resolve2(dirname4(file), baseUrl),
|
|
2861
|
+
paths: options.paths
|
|
2862
|
+
};
|
|
2863
|
+
}
|
|
2864
|
+
const bases = Array.isArray(json.extends) ? json.extends : [json.extends].filter(Boolean);
|
|
2865
|
+
for (const base of bases) {
|
|
2866
|
+
if (typeof base !== "string") {
|
|
2867
|
+
continue;
|
|
2868
|
+
}
|
|
2869
|
+
const resolved = resolveExtends(base, dirname4(file));
|
|
2870
|
+
const found = resolved ? loadPaths(resolved, seen) : null;
|
|
2871
|
+
if (found) {
|
|
2872
|
+
return found;
|
|
2873
|
+
}
|
|
2874
|
+
}
|
|
2875
|
+
return null;
|
|
2876
|
+
};
|
|
2877
|
+
var toAlias = (key, value, baseDir) => {
|
|
2878
|
+
const first = Array.isArray(value) ? value[0] : value;
|
|
2879
|
+
if (typeof first !== "string") {
|
|
2880
|
+
return null;
|
|
2881
|
+
}
|
|
2882
|
+
const find = key.endsWith("/*") ? key.slice(0, -2) : key;
|
|
2883
|
+
const target = first.endsWith("/*") ? first.slice(0, -2) : first;
|
|
2884
|
+
if (find === "" || find === "*") {
|
|
2885
|
+
return null;
|
|
2886
|
+
}
|
|
2887
|
+
return { find, replacement: resolve2(baseDir, target) };
|
|
2888
|
+
};
|
|
2889
|
+
var resolveTsconfigAliases = (root) => {
|
|
2890
|
+
const entry = ["tsconfig.json", "jsconfig.json"].map((name) => join6(root, name)).find((file) => existsSync3(file));
|
|
2891
|
+
if (!entry) {
|
|
2892
|
+
return {};
|
|
2893
|
+
}
|
|
2894
|
+
const loaded = loadPaths(entry, new Set);
|
|
2895
|
+
if (!loaded) {
|
|
2896
|
+
return {};
|
|
2897
|
+
}
|
|
2898
|
+
const aliases = {};
|
|
2899
|
+
for (const [key, value] of Object.entries(loaded.paths)) {
|
|
2900
|
+
const alias = toAlias(key, value, loaded.baseDir);
|
|
2901
|
+
if (alias) {
|
|
2902
|
+
aliases[alias.find] = alias.replacement;
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
return aliases;
|
|
2906
|
+
};
|
|
2907
|
+
|
|
2757
2908
|
// src/deploy/rss.ts
|
|
2758
2909
|
var capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);
|
|
2759
2910
|
var pageDate = (page) => {
|
|
@@ -2835,11 +2986,11 @@ ${items}
|
|
|
2835
2986
|
|
|
2836
2987
|
// src/openapi/scalar.ts
|
|
2837
2988
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
2838
|
-
import { isAbsolute, join as
|
|
2989
|
+
import { isAbsolute as isAbsolute2, join as join8 } from "pathe";
|
|
2839
2990
|
|
|
2840
2991
|
// src/astro/templates.ts
|
|
2841
|
-
import { existsSync as
|
|
2842
|
-
import { dirname as
|
|
2992
|
+
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "node:fs";
|
|
2993
|
+
import { dirname as dirname5, join as join7 } from "pathe";
|
|
2843
2994
|
|
|
2844
2995
|
// src/theme/fonts.ts
|
|
2845
2996
|
var FALLBACKS = {
|
|
@@ -2997,24 +3148,24 @@ var WORKSPACE_MARKERS = [
|
|
|
2997
3148
|
"yarn.lock"
|
|
2998
3149
|
];
|
|
2999
3150
|
var hasWorkspacesField = (pkgPath) => {
|
|
3000
|
-
if (!
|
|
3151
|
+
if (!existsSync4(pkgPath)) {
|
|
3001
3152
|
return false;
|
|
3002
3153
|
}
|
|
3003
3154
|
try {
|
|
3004
|
-
const pkg = JSON.parse(
|
|
3155
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
3005
3156
|
return pkg.workspaces !== undefined;
|
|
3006
3157
|
} catch {
|
|
3007
3158
|
return false;
|
|
3008
3159
|
}
|
|
3009
3160
|
};
|
|
3010
|
-
var hasWorkspaceMarker = (dir) => hasWorkspacesField(
|
|
3161
|
+
var hasWorkspaceMarker = (dir) => hasWorkspacesField(join7(dir, "package.json")) || WORKSPACE_MARKERS.some((marker) => existsSync4(join7(dir, marker)));
|
|
3011
3162
|
var findWorkspaceRoot = (start) => {
|
|
3012
3163
|
let dir = start;
|
|
3013
3164
|
for (;; ) {
|
|
3014
3165
|
if (hasWorkspaceMarker(dir)) {
|
|
3015
3166
|
return dir;
|
|
3016
3167
|
}
|
|
3017
|
-
const parent =
|
|
3168
|
+
const parent = dirname5(dir);
|
|
3018
3169
|
if (parent === dir) {
|
|
3019
3170
|
return start;
|
|
3020
3171
|
}
|
|
@@ -3061,10 +3212,19 @@ var runtimeDependencies = (options) => {
|
|
|
3061
3212
|
}
|
|
3062
3213
|
return deps;
|
|
3063
3214
|
};
|
|
3215
|
+
var renderUserAliases = (aliases) => Object.entries(aliases ?? {}).toSorted(([a], [b]) => b.length - a.length).map(([find, replacement]) => `
|
|
3216
|
+
${JSON.stringify(find)}: ${JSON.stringify(replacement)},`).join("");
|
|
3064
3217
|
var astroConfigTemplate = (options) => {
|
|
3065
3218
|
const { context, config, needsReact, pages, dataPath, themePath } = options;
|
|
3066
|
-
const {
|
|
3219
|
+
const {
|
|
3220
|
+
contentRoutes,
|
|
3221
|
+
examplesPath,
|
|
3222
|
+
needsSvelte,
|
|
3223
|
+
needsVue,
|
|
3224
|
+
searchClientPath
|
|
3225
|
+
} = options;
|
|
3067
3226
|
const { deployment } = config;
|
|
3227
|
+
const userAliasLines = renderUserAliases(options.aliases);
|
|
3068
3228
|
const server = deployment.output === "server";
|
|
3069
3229
|
const fsAllow = [...new Set([findWorkspaceRoot(context.root), context.root])];
|
|
3070
3230
|
const adapterImport = server && deployment.adapter ? `import adapter from "${ADAPTER_IMPORTS[deployment.adapter]}";
|
|
@@ -3167,8 +3327,9 @@ export default defineConfig({
|
|
|
3167
3327
|
resolve: {
|
|
3168
3328
|
alias: {
|
|
3169
3329
|
"blume:data": ${JSON.stringify(dataPath)},
|
|
3330
|
+
"blume:examples": ${JSON.stringify(examplesPath)},
|
|
3170
3331
|
"blume:search-client": ${JSON.stringify(searchClientPath)},
|
|
3171
|
-
"blume:theme": ${JSON.stringify(themePath)}
|
|
3332
|
+
"blume:theme": ${JSON.stringify(themePath)},${userAliasLines}
|
|
3172
3333
|
},
|
|
3173
3334
|
},
|
|
3174
3335
|
server: {
|
|
@@ -3180,7 +3341,7 @@ export default defineConfig({
|
|
|
3180
3341
|
});
|
|
3181
3342
|
`;
|
|
3182
3343
|
};
|
|
3183
|
-
var stagedContentDir = (outDir) =>
|
|
3344
|
+
var stagedContentDir = (outDir) => join7(outDir, "content");
|
|
3184
3345
|
var contentConfigTemplate = (options) => {
|
|
3185
3346
|
const { context, config } = options;
|
|
3186
3347
|
const stagedBase = options.stagedBase ?? stagedContentDir(context.outDir);
|
|
@@ -3426,24 +3587,44 @@ export function GET({ props }) {
|
|
|
3426
3587
|
});
|
|
3427
3588
|
}
|
|
3428
3589
|
`;
|
|
3429
|
-
var ogEndpointTemplate = () => `// Generated by Blume. Do not edit.
|
|
3590
|
+
var ogEndpointTemplate = (customRoutes = []) => `// Generated by Blume. Do not edit.
|
|
3430
3591
|
import { renderOgImage } from "blume/og";
|
|
3431
3592
|
import data from "../../generated/data.json";
|
|
3432
3593
|
|
|
3433
3594
|
export const prerender = true;
|
|
3434
3595
|
|
|
3596
|
+
// Custom (non-content) pages opted into a generated card, baked in at build.
|
|
3597
|
+
const customRoutes = ${JSON.stringify(customRoutes)};
|
|
3598
|
+
|
|
3435
3599
|
export function getStaticPaths() {
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3600
|
+
const seen = new Set();
|
|
3601
|
+
const paths = [];
|
|
3602
|
+
const add = (slug, title, eyebrow) => {
|
|
3603
|
+
if (seen.has(slug)) {
|
|
3604
|
+
return;
|
|
3605
|
+
}
|
|
3606
|
+
seen.add(slug);
|
|
3607
|
+
paths.push({ params: { slug }, props: { eyebrow, title } });
|
|
3608
|
+
};
|
|
3609
|
+
// A custom page wins over a content route sharing its path, so add it first.
|
|
3610
|
+
for (const route of customRoutes) {
|
|
3611
|
+
add(route.slug, route.title, route.eyebrow);
|
|
3612
|
+
}
|
|
3613
|
+
for (const route of data.routes) {
|
|
3614
|
+
add(
|
|
3615
|
+
route.path === "/" ? "index" : route.path.slice(1),
|
|
3616
|
+
route.title,
|
|
3617
|
+
data.config.title
|
|
3618
|
+
);
|
|
3619
|
+
}
|
|
3620
|
+
return paths;
|
|
3440
3621
|
}
|
|
3441
3622
|
|
|
3442
3623
|
export async function GET({ props }) {
|
|
3443
3624
|
const png = await renderOgImage({
|
|
3444
|
-
title: props.title,
|
|
3445
|
-
eyebrow: data.config.title,
|
|
3446
3625
|
accent: data.config.theme.accent,
|
|
3626
|
+
eyebrow: props.eyebrow,
|
|
3627
|
+
title: props.title,
|
|
3447
3628
|
});
|
|
3448
3629
|
return new Response(png, {
|
|
3449
3630
|
headers: {
|
|
@@ -3470,6 +3651,7 @@ const configuration = ${JSON.stringify(options.configuration, null, 2)};
|
|
|
3470
3651
|
fontCssVars={data.fontCssVars}
|
|
3471
3652
|
logo={data.config.logo}
|
|
3472
3653
|
favicon={data.config.favicon}
|
|
3654
|
+
appleIcon={data.config.appleIcon}
|
|
3473
3655
|
navigation={data.navigation}
|
|
3474
3656
|
pageTitle={${JSON.stringify(options.title)}}
|
|
3475
3657
|
route={${JSON.stringify(options.route)}}
|
|
@@ -3501,12 +3683,15 @@ import Badge from "blume/components/content/Badge.astro";
|
|
|
3501
3683
|
import Callout from "blume/components/content/Callout.astro";
|
|
3502
3684
|
import Card from "blume/components/content/Card.astro";
|
|
3503
3685
|
import CardGroup from "blume/components/content/CardGroup.astro";
|
|
3686
|
+
import CodeBlock from "blume/components/content/CodeBlock.astro";
|
|
3504
3687
|
import CodeGroup from "blume/components/content/CodeGroup.astro";
|
|
3505
3688
|
import ColorRoot from "blume/components/content/Color.astro";
|
|
3506
3689
|
import ColorItem from "blume/components/content/ColorItem.astro";
|
|
3507
3690
|
import ColorRow from "blume/components/content/ColorRow.astro";
|
|
3508
3691
|
import Column from "blume/components/content/Column.astro";
|
|
3509
3692
|
import Columns from "blume/components/content/Columns.astro";
|
|
3693
|
+
import Component from "blume/components/content/Component.astro";
|
|
3694
|
+
import Diff from "blume/components/content/Diff.astro";
|
|
3510
3695
|
import Expandable from "blume/components/content/Expandable.astro";
|
|
3511
3696
|
import FileTree from "blume/components/content/FileTree.astro";
|
|
3512
3697
|
import Frame from "blume/components/content/Frame.astro";
|
|
@@ -3546,10 +3731,13 @@ const components = {
|
|
|
3546
3731
|
Callout,
|
|
3547
3732
|
Card,
|
|
3548
3733
|
CardGroup,
|
|
3734
|
+
CodeBlock,
|
|
3549
3735
|
CodeGroup,
|
|
3550
3736
|
Color,
|
|
3551
3737
|
Column,
|
|
3552
3738
|
Columns,
|
|
3739
|
+
Component,
|
|
3740
|
+
Diff,
|
|
3553
3741
|
Expandable,
|
|
3554
3742
|
FileTree,
|
|
3555
3743
|
Frame,
|
|
@@ -3670,6 +3858,7 @@ const localeSwitch = i18n
|
|
|
3670
3858
|
logo={data.config.logo}
|
|
3671
3859
|
mcp={data.config.mcp}
|
|
3672
3860
|
favicon={data.config.favicon}
|
|
3861
|
+
appleIcon={data.config.appleIcon}
|
|
3673
3862
|
banner={data.config.banner}
|
|
3674
3863
|
analytics={data.config.analytics}
|
|
3675
3864
|
imageZoom={data.config.imageZoom}
|
|
@@ -3796,6 +3985,7 @@ const canonical = base ? base + "/changelog" : null;
|
|
|
3796
3985
|
logo={data.config.logo}
|
|
3797
3986
|
mcp={data.config.mcp}
|
|
3798
3987
|
favicon={data.config.favicon}
|
|
3988
|
+
appleIcon={data.config.appleIcon}
|
|
3799
3989
|
banner={data.config.banner}
|
|
3800
3990
|
analytics={data.config.analytics}
|
|
3801
3991
|
imageZoom={data.config.imageZoom}
|
|
@@ -3875,8 +4065,43 @@ ${entries}
|
|
|
3875
4065
|
};
|
|
3876
4066
|
`;
|
|
3877
4067
|
};
|
|
4068
|
+
var exampleDirective = (spec) => {
|
|
4069
|
+
if (spec.framework === "astro" || !spec.client) {
|
|
4070
|
+
return "";
|
|
4071
|
+
}
|
|
4072
|
+
return spec.client === "only" ? `client:only="${spec.framework}" ` : `client:${spec.client} `;
|
|
4073
|
+
};
|
|
4074
|
+
var exampleSlug = (path) => path.replaceAll("/", "__").replaceAll(/[^a-zA-Z0-9_]+/gu, "-");
|
|
4075
|
+
var exampleWrapperTemplate = (spec) => `---
|
|
4076
|
+
// Generated by Blume. Do not edit.
|
|
4077
|
+
import Example from ${JSON.stringify(spec.file)};
|
|
4078
|
+
---
|
|
4079
|
+
<Example ${exampleDirective(spec)}{...Astro.props}><slot /></Example>
|
|
4080
|
+
`;
|
|
4081
|
+
var exampleMapTemplate = (specs) => {
|
|
4082
|
+
if (specs.length === 0) {
|
|
4083
|
+
return `// Generated by Blume. Do not edit.
|
|
4084
|
+
export const examples = {};
|
|
4085
|
+
`;
|
|
4086
|
+
}
|
|
4087
|
+
const imports = specs.map((spec, index) => `import E${index} from "./examples/${exampleSlug(spec.path)}.astro";`).join(`
|
|
4088
|
+
`);
|
|
4089
|
+
const entries = specs.map((spec, index) => ` ${JSON.stringify(spec.path)}: { Component: E${index}, code: ${JSON.stringify(spec.source)}, lang: ${JSON.stringify(spec.lang)} },`).join(`
|
|
4090
|
+
`);
|
|
4091
|
+
return `// Generated by Blume. Do not edit.
|
|
4092
|
+
${imports}
|
|
4093
|
+
export const examples = {
|
|
4094
|
+
${entries}
|
|
4095
|
+
};
|
|
4096
|
+
`;
|
|
4097
|
+
};
|
|
3878
4098
|
var envTemplate = () => `/// <reference path="../.astro/types.d.ts" />
|
|
3879
4099
|
/// <reference types="astro/client" />
|
|
4100
|
+
|
|
4101
|
+
declare module "blume:data" {
|
|
4102
|
+
const data: import("blume").BlumeData;
|
|
4103
|
+
export default data;
|
|
4104
|
+
}
|
|
3880
4105
|
`;
|
|
3881
4106
|
var runtimePackageTemplate = (dependencies = []) => `${JSON.stringify({
|
|
3882
4107
|
dependencies: Object.fromEntries([...dependencies].toSorted().map((name) => [name, "*"])),
|
|
@@ -4057,7 +4282,7 @@ var specConfiguration = async (spec, root) => {
|
|
|
4057
4282
|
if (URL_SPEC.test(spec)) {
|
|
4058
4283
|
return { config: { url: spec } };
|
|
4059
4284
|
}
|
|
4060
|
-
const absolute =
|
|
4285
|
+
const absolute = isAbsolute2(spec) ? spec : join8(root, spec);
|
|
4061
4286
|
try {
|
|
4062
4287
|
return { config: { content: await readFile4(absolute, "utf-8") } };
|
|
4063
4288
|
} catch {
|
|
@@ -4419,6 +4644,19 @@ ${options.sources.map((source) => `@source "${source}";`).join(`
|
|
|
4419
4644
|
text-decoration: var(--shiki-dark-text-decoration, inherit);
|
|
4420
4645
|
}
|
|
4421
4646
|
|
|
4647
|
+
/* The Diff component (@pierre/diffs) renders into a declarative shadow root and
|
|
4648
|
+
themes itself with light-dark(). Drive that from Blume's data-theme instead
|
|
4649
|
+
of the OS, scoped to the diff host: the custom property pierces the shadow
|
|
4650
|
+
boundary, where the appended host color-scheme rule consumes it. */
|
|
4651
|
+
blume-diff {
|
|
4652
|
+
--blume-diff-color-scheme: light;
|
|
4653
|
+
display: block;
|
|
4654
|
+
}
|
|
4655
|
+
|
|
4656
|
+
:root[data-theme="dark"] blume-diff {
|
|
4657
|
+
--blume-diff-color-scheme: dark;
|
|
4658
|
+
}
|
|
4659
|
+
|
|
4422
4660
|
.prose :where(pre[data-language]) {
|
|
4423
4661
|
padding-top: 3.75rem;
|
|
4424
4662
|
}
|
|
@@ -4492,6 +4730,22 @@ blume-tabs pre,
|
|
|
4492
4730
|
background: var(--blume-code-background);
|
|
4493
4731
|
}
|
|
4494
4732
|
|
|
4733
|
+
/* The Component source pane fills its tab's fixed height (set inline to match the
|
|
4734
|
+
preview tab) and scrolls the inner code element, leaving the pre static so the
|
|
4735
|
+
copy button — absolute, pinned to the pre — doesn't drift while it scrolls. */
|
|
4736
|
+
pre.blume-source {
|
|
4737
|
+
display: flex;
|
|
4738
|
+
flex-direction: column;
|
|
4739
|
+
height: 100%;
|
|
4740
|
+
overflow: hidden;
|
|
4741
|
+
}
|
|
4742
|
+
|
|
4743
|
+
pre.blume-source > code {
|
|
4744
|
+
flex: 1;
|
|
4745
|
+
min-height: 0;
|
|
4746
|
+
overflow: auto;
|
|
4747
|
+
}
|
|
4748
|
+
|
|
4495
4749
|
/* Code blocks inside tabs sit flush; the tab container owns the frame. These
|
|
4496
4750
|
rules are unlayered like the base \`pre\` styles, so they win over Tailwind's
|
|
4497
4751
|
layered utilities (which a class on the panel cannot). The second selector
|
|
@@ -4701,9 +4955,9 @@ ${options.userTheme}
|
|
|
4701
4955
|
`;
|
|
4702
4956
|
|
|
4703
4957
|
// src/theme/twoslash.ts
|
|
4704
|
-
import { readFileSync as
|
|
4705
|
-
import { createRequire as
|
|
4706
|
-
var require2 =
|
|
4958
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
4959
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
4960
|
+
var require2 = createRequire3(import.meta.url);
|
|
4707
4961
|
var OVERRIDES = `
|
|
4708
4962
|
/* Twoslash: theme the rich renderer with Blume tokens. */
|
|
4709
4963
|
:root {
|
|
@@ -4763,13 +5017,18 @@ var OVERRIDES = `
|
|
|
4763
5017
|
`;
|
|
4764
5018
|
var twoslashCss = () => {
|
|
4765
5019
|
const file = require2.resolve("@shikijs/twoslash/style-rich.css");
|
|
4766
|
-
return `${
|
|
5020
|
+
return `${readFileSync4(file, "utf-8")}
|
|
4767
5021
|
${OVERRIDES}`;
|
|
4768
5022
|
};
|
|
4769
5023
|
|
|
5024
|
+
// src/astro/examples.ts
|
|
5025
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
5026
|
+
import { join as join10, relative as relative3 } from "pathe";
|
|
5027
|
+
import { glob as glob2 } from "tinyglobby";
|
|
5028
|
+
|
|
4770
5029
|
// src/astro/islands.ts
|
|
4771
5030
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
4772
|
-
import { basename, join as
|
|
5031
|
+
import { basename, join as join9 } from "pathe";
|
|
4773
5032
|
import { glob } from "tinyglobby";
|
|
4774
5033
|
var DEFAULT_CLIENT = "visible";
|
|
4775
5034
|
var VALID_MODES = new Set([
|
|
@@ -4798,7 +5057,7 @@ var readClientMode = (source, file, warnings) => {
|
|
|
4798
5057
|
return mode;
|
|
4799
5058
|
};
|
|
4800
5059
|
var discoverIslands = async (root) => {
|
|
4801
|
-
const dir =
|
|
5060
|
+
const dir = join9(root, "islands");
|
|
4802
5061
|
const matches = await glob(["**/*.{jsx,svelte,tsx,vue}"], {
|
|
4803
5062
|
absolute: true,
|
|
4804
5063
|
cwd: dir,
|
|
@@ -4837,50 +5096,133 @@ var discoverIslands = async (root) => {
|
|
|
4837
5096
|
return { islands, warnings };
|
|
4838
5097
|
};
|
|
4839
5098
|
|
|
5099
|
+
// src/astro/examples.ts
|
|
5100
|
+
var FRAMEWORK_BY_EXT2 = {
|
|
5101
|
+
astro: "astro",
|
|
5102
|
+
jsx: "react",
|
|
5103
|
+
svelte: "svelte",
|
|
5104
|
+
tsx: "react",
|
|
5105
|
+
vue: "vue"
|
|
5106
|
+
};
|
|
5107
|
+
var EXAMPLE_FILE = /\.(?<ext>astro|jsx|svelte|tsx|vue)$/u;
|
|
5108
|
+
var discoverExamples = async (root) => {
|
|
5109
|
+
const dir = join10(root, "examples");
|
|
5110
|
+
const matches = await glob2(["**/*.{astro,jsx,svelte,tsx,vue}"], {
|
|
5111
|
+
absolute: true,
|
|
5112
|
+
cwd: dir,
|
|
5113
|
+
onlyFiles: true
|
|
5114
|
+
});
|
|
5115
|
+
const files = matches.toSorted();
|
|
5116
|
+
const sources = await Promise.all(files.map((file) => readFile6(file, "utf-8")));
|
|
5117
|
+
const examples = [];
|
|
5118
|
+
const warnings = [];
|
|
5119
|
+
const seen = new Map;
|
|
5120
|
+
for (const [index, file] of files.entries()) {
|
|
5121
|
+
const ext = file.match(EXAMPLE_FILE)?.groups?.ext;
|
|
5122
|
+
const framework = ext ? FRAMEWORK_BY_EXT2[ext] : undefined;
|
|
5123
|
+
if (!(ext && framework)) {
|
|
5124
|
+
continue;
|
|
5125
|
+
}
|
|
5126
|
+
const path = relative3(dir, file).slice(0, -(ext.length + 1));
|
|
5127
|
+
const existing = seen.get(path);
|
|
5128
|
+
if (existing) {
|
|
5129
|
+
warnings.push(`Two examples both resolve to "${path}" ("${existing}" and "${file}"); ignoring the second. Give them distinct paths.`);
|
|
5130
|
+
continue;
|
|
5131
|
+
}
|
|
5132
|
+
seen.set(path, file);
|
|
5133
|
+
const source = sources[index] ?? "";
|
|
5134
|
+
examples.push({
|
|
5135
|
+
client: framework === "astro" ? undefined : readClientMode(source, file, warnings),
|
|
5136
|
+
file,
|
|
5137
|
+
framework,
|
|
5138
|
+
lang: ext,
|
|
5139
|
+
path,
|
|
5140
|
+
source
|
|
5141
|
+
});
|
|
5142
|
+
}
|
|
5143
|
+
return { examples, warnings };
|
|
5144
|
+
};
|
|
5145
|
+
|
|
4840
5146
|
// src/astro/pages.ts
|
|
4841
|
-
import { extname, relative as
|
|
4842
|
-
import { glob as
|
|
5147
|
+
import { extname, relative as relative4 } from "pathe";
|
|
5148
|
+
import { glob as glob3 } from "tinyglobby";
|
|
4843
5149
|
var discoverPages = async (pagesRoot) => {
|
|
4844
|
-
const files = await
|
|
5150
|
+
const files = await glob3(["**/*.astro"], {
|
|
4845
5151
|
absolute: true,
|
|
4846
5152
|
cwd: pagesRoot,
|
|
4847
5153
|
onlyFiles: true
|
|
4848
5154
|
});
|
|
4849
5155
|
files.sort();
|
|
4850
5156
|
return files.map((file) => {
|
|
4851
|
-
const rel =
|
|
5157
|
+
const rel = relative4(pagesRoot, file);
|
|
4852
5158
|
const withoutExt = rel.slice(0, rel.length - extname(rel).length);
|
|
4853
5159
|
const parts = withoutExt.split("/").filter((part) => part !== "index");
|
|
4854
5160
|
const pattern = parts.length === 0 ? "/" : `/${parts.join("/")}`;
|
|
4855
5161
|
return { entrypoint: file, pattern };
|
|
4856
5162
|
});
|
|
4857
5163
|
};
|
|
5164
|
+
var PRIVATE_SEGMENT = /^[._]/u;
|
|
5165
|
+
var humanizeSegment = (segment) => segment.split(/[-_]/u).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
5166
|
+
var customOgRoutes = (pages, siteTitle, siteDescription) => {
|
|
5167
|
+
const seen = new Set;
|
|
5168
|
+
const routes = [];
|
|
5169
|
+
for (const { pattern } of pages) {
|
|
5170
|
+
const segments = pattern.split("/").filter(Boolean);
|
|
5171
|
+
if (segments.some((part) => PRIVATE_SEGMENT.test(part) || part.includes("["))) {
|
|
5172
|
+
continue;
|
|
5173
|
+
}
|
|
5174
|
+
const slug = segments.length === 0 ? "index" : segments.join("/");
|
|
5175
|
+
if (seen.has(slug)) {
|
|
5176
|
+
continue;
|
|
5177
|
+
}
|
|
5178
|
+
seen.add(slug);
|
|
5179
|
+
const last = segments.at(-1);
|
|
5180
|
+
routes.push(last ? { eyebrow: siteTitle, slug, title: humanizeSegment(last) } : { eyebrow: siteDescription, slug, title: siteTitle });
|
|
5181
|
+
}
|
|
5182
|
+
return routes;
|
|
5183
|
+
};
|
|
4858
5184
|
|
|
4859
5185
|
// src/astro/generate.ts
|
|
4860
|
-
var BLUME_SRC =
|
|
4861
|
-
var BLUME_NODE_MODULES = join9(packageRoot(), "node_modules");
|
|
5186
|
+
var BLUME_SRC = join11(packageRoot(), "src");
|
|
4862
5187
|
var canResolveFrom = (fromDir, spec) => {
|
|
4863
5188
|
try {
|
|
4864
|
-
|
|
5189
|
+
createRequire4(pathToFileURL2(join11(fromDir, "_.js")).href).resolve(spec);
|
|
4865
5190
|
return true;
|
|
4866
5191
|
} catch {
|
|
4867
5192
|
return false;
|
|
4868
5193
|
}
|
|
4869
5194
|
};
|
|
4870
|
-
var
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
return;
|
|
5195
|
+
var resolvedAstroPath = (fromDir) => {
|
|
5196
|
+
try {
|
|
5197
|
+
const pkg = createRequire4(pathToFileURL2(join11(fromDir, "_.js")).href).resolve("astro/package.json");
|
|
5198
|
+
return realpathSync(pkg);
|
|
5199
|
+
} catch {
|
|
5200
|
+
return null;
|
|
4874
5201
|
}
|
|
4875
|
-
|
|
5202
|
+
};
|
|
5203
|
+
var blumeDepsDir = (pkgDir = packageRoot()) => {
|
|
5204
|
+
const candidates = [join11(pkgDir, "node_modules"), dirname6(pkgDir)];
|
|
5205
|
+
return candidates.find((dir) => existsSync5(join11(dir, "astro"))) ?? null;
|
|
5206
|
+
};
|
|
5207
|
+
var ensureDepsLink = async (outDir, pkgDir = packageRoot()) => {
|
|
5208
|
+
const depsDir = blumeDepsDir(pkgDir);
|
|
5209
|
+
if (!depsDir || !existsSync5(join11(depsDir, "@astrojs", "mdx"))) {
|
|
4876
5210
|
return;
|
|
4877
5211
|
}
|
|
4878
|
-
const
|
|
4879
|
-
if (
|
|
5212
|
+
const blumeAstro = resolvedAstroPath(depsDir);
|
|
5213
|
+
if (blumeAstro && resolvedAstroPath(outDir) === blumeAstro) {
|
|
4880
5214
|
return;
|
|
4881
5215
|
}
|
|
5216
|
+
const link = join11(outDir, "node_modules");
|
|
5217
|
+
const existing = await lstat(link).catch(() => null);
|
|
5218
|
+
if (existing) {
|
|
5219
|
+
if (!existing.isSymbolicLink()) {
|
|
5220
|
+
return;
|
|
5221
|
+
}
|
|
5222
|
+
await rm(link, { force: true });
|
|
5223
|
+
}
|
|
4882
5224
|
await mkdir2(outDir, { recursive: true });
|
|
4883
|
-
await symlink(
|
|
5225
|
+
await symlink(depsDir, link, "junction");
|
|
4884
5226
|
};
|
|
4885
5227
|
var ISLAND_FRAMEWORK_DEPS = {
|
|
4886
5228
|
svelte: "@astrojs/svelte",
|
|
@@ -4901,13 +5243,13 @@ var readOptional = async (path) => {
|
|
|
4901
5243
|
return "";
|
|
4902
5244
|
}
|
|
4903
5245
|
try {
|
|
4904
|
-
return await
|
|
5246
|
+
return await readFile7(path, "utf-8");
|
|
4905
5247
|
} catch {
|
|
4906
5248
|
return "";
|
|
4907
5249
|
}
|
|
4908
5250
|
};
|
|
4909
5251
|
var detectNeedsReact = async (root) => {
|
|
4910
|
-
const matches = await
|
|
5252
|
+
const matches = await glob4(["**/*.{tsx,jsx}"], {
|
|
4911
5253
|
cwd: root,
|
|
4912
5254
|
ignore: ["**/node_modules/**", "**/.blume/**", "**/dist/**"],
|
|
4913
5255
|
onlyFiles: true
|
|
@@ -4917,14 +5259,14 @@ var detectNeedsReact = async (root) => {
|
|
|
4917
5259
|
var writeIfChanged = async (path, content) => {
|
|
4918
5260
|
let existing = null;
|
|
4919
5261
|
try {
|
|
4920
|
-
existing = await
|
|
5262
|
+
existing = await readFile7(path, "utf-8");
|
|
4921
5263
|
} catch {
|
|
4922
5264
|
existing = null;
|
|
4923
5265
|
}
|
|
4924
5266
|
if (existing === content) {
|
|
4925
5267
|
return false;
|
|
4926
5268
|
}
|
|
4927
|
-
await mkdir2(
|
|
5269
|
+
await mkdir2(dirname6(path), { recursive: true });
|
|
4928
5270
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
4929
5271
|
await writeFile2(tmp, content, "utf-8");
|
|
4930
5272
|
try {
|
|
@@ -4936,7 +5278,7 @@ var writeIfChanged = async (path, content) => {
|
|
|
4936
5278
|
return true;
|
|
4937
5279
|
};
|
|
4938
5280
|
var pruneOrphans = async (srcDir, written) => {
|
|
4939
|
-
const existing = await
|
|
5281
|
+
const existing = await glob4("**/*", {
|
|
4940
5282
|
absolute: true,
|
|
4941
5283
|
cwd: srcDir,
|
|
4942
5284
|
onlyFiles: true
|
|
@@ -4956,11 +5298,11 @@ var writeStagedContent = async (out, staged) => {
|
|
|
4956
5298
|
const contentDir = stagedContentDir(out);
|
|
4957
5299
|
const written = new Set;
|
|
4958
5300
|
await Promise.all([...staged].map(async ([entryId, text]) => {
|
|
4959
|
-
const path =
|
|
5301
|
+
const path = join11(contentDir, entryId);
|
|
4960
5302
|
written.add(normalize(path));
|
|
4961
5303
|
await writeIfChanged(path, text);
|
|
4962
5304
|
}));
|
|
4963
|
-
if (
|
|
5305
|
+
if (existsSync5(contentDir)) {
|
|
4964
5306
|
await pruneOrphans(contentDir, written);
|
|
4965
5307
|
}
|
|
4966
5308
|
};
|
|
@@ -4977,11 +5319,11 @@ var resolveLogo = (project) => {
|
|
|
4977
5319
|
if (light && light === dark && light.toLowerCase().endsWith(".svg")) {
|
|
4978
5320
|
const rel = light.replace(/^\//u, "");
|
|
4979
5321
|
const file = [
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
].find((path) =>
|
|
5322
|
+
join11(project.context.root, "public", rel),
|
|
5323
|
+
join11(project.context.root, rel)
|
|
5324
|
+
].find((path) => existsSync5(path));
|
|
4983
5325
|
if (file) {
|
|
4984
|
-
return { alt, href, svg:
|
|
5326
|
+
return { alt, href, svg: readFileSync5(file, "utf-8") };
|
|
4985
5327
|
}
|
|
4986
5328
|
}
|
|
4987
5329
|
return { alt, dark, href, light };
|
|
@@ -4996,6 +5338,8 @@ var FAVICON_CANDIDATES = [
|
|
|
4996
5338
|
];
|
|
4997
5339
|
var FAVICON_TYPES = {
|
|
4998
5340
|
ico: "image/x-icon",
|
|
5341
|
+
jpeg: "image/jpeg",
|
|
5342
|
+
jpg: "image/jpeg",
|
|
4999
5343
|
png: "image/png",
|
|
5000
5344
|
svg: "image/svg+xml"
|
|
5001
5345
|
};
|
|
@@ -5003,27 +5347,35 @@ var faviconType = (name) => {
|
|
|
5003
5347
|
const ext = name.split(".").pop()?.toLowerCase();
|
|
5004
5348
|
return ext ? FAVICON_TYPES[ext] : undefined;
|
|
5005
5349
|
};
|
|
5006
|
-
var inlineDataUri = (file, type) => `data:${type};base64,${
|
|
5350
|
+
var inlineDataUri = (file, type) => `data:${type};base64,${readFileSync5(file).toString("base64")}`;
|
|
5007
5351
|
var defaultFavicon = () => ({
|
|
5008
|
-
href: inlineDataUri(
|
|
5352
|
+
href: inlineDataUri(join11(BLUME_SRC, "assets", "icon.png"), "image/png"),
|
|
5009
5353
|
type: "image/png"
|
|
5010
5354
|
});
|
|
5011
|
-
var
|
|
5355
|
+
var APPLE_ICON_CANDIDATES = [
|
|
5356
|
+
"apple-icon.png",
|
|
5357
|
+
"apple-icon.jpg",
|
|
5358
|
+
"apple-icon.jpeg",
|
|
5359
|
+
"apple-touch-icon.png"
|
|
5360
|
+
];
|
|
5361
|
+
var resolveIconFile = (project, candidates) => {
|
|
5012
5362
|
const { root } = project.context;
|
|
5013
|
-
for (const name of
|
|
5014
|
-
if (
|
|
5363
|
+
for (const name of candidates) {
|
|
5364
|
+
if (existsSync5(join11(root, "public", name))) {
|
|
5015
5365
|
return { href: `/${name}`, type: faviconType(name) };
|
|
5016
5366
|
}
|
|
5017
5367
|
}
|
|
5018
|
-
for (const name of
|
|
5019
|
-
const file =
|
|
5020
|
-
if (
|
|
5368
|
+
for (const name of candidates) {
|
|
5369
|
+
const file = join11(root, name);
|
|
5370
|
+
if (existsSync5(file)) {
|
|
5021
5371
|
const type = faviconType(name);
|
|
5022
5372
|
return { href: inlineDataUri(file, type ?? "image/x-icon"), type };
|
|
5023
5373
|
}
|
|
5024
5374
|
}
|
|
5025
|
-
return
|
|
5375
|
+
return null;
|
|
5026
5376
|
};
|
|
5377
|
+
var resolveFavicon = (project) => resolveIconFile(project, FAVICON_CANDIDATES) ?? defaultFavicon();
|
|
5378
|
+
var resolveAppleIcon = (project) => resolveIconFile(project, APPLE_ICON_CANDIDATES);
|
|
5027
5379
|
var resolveBanner = (config) => {
|
|
5028
5380
|
const { banner } = config;
|
|
5029
5381
|
if (!banner) {
|
|
@@ -5048,7 +5400,7 @@ var buildRuntimeData = (project) => {
|
|
|
5048
5400
|
if (!(editBase && sourcePath)) {
|
|
5049
5401
|
return null;
|
|
5050
5402
|
}
|
|
5051
|
-
const rel =
|
|
5403
|
+
const rel = relative5(context.root, sourcePath).split("\\").join("/");
|
|
5052
5404
|
return `${editBase}/${github?.dir ? `${github.dir}/${rel}` : rel}`;
|
|
5053
5405
|
};
|
|
5054
5406
|
const { i18n } = config;
|
|
@@ -5081,6 +5433,7 @@ var buildRuntimeData = (project) => {
|
|
|
5081
5433
|
const data = {
|
|
5082
5434
|
config: {
|
|
5083
5435
|
analytics: config.analytics ?? null,
|
|
5436
|
+
appleIcon: resolveAppleIcon(project),
|
|
5084
5437
|
banner: resolveBanner(config),
|
|
5085
5438
|
codeWrap: config.markdown.code.wrap,
|
|
5086
5439
|
description: config.description,
|
|
@@ -5099,7 +5452,7 @@ var buildRuntimeData = (project) => {
|
|
|
5099
5452
|
imageZoom: config.markdown.imageZoom,
|
|
5100
5453
|
logo: resolveLogo(project),
|
|
5101
5454
|
mcp: config.mcp.enabled ? { name: config.mcp.name ?? config.title, route: config.mcp.route } : null,
|
|
5102
|
-
og: { enabled: config.seo.og.enabled },
|
|
5455
|
+
og: { enabled: config.seo.og.enabled ?? false },
|
|
5103
5456
|
repoUrl,
|
|
5104
5457
|
search: {
|
|
5105
5458
|
enabled: config.search.provider !== "none",
|
|
@@ -5141,7 +5494,7 @@ var buildRuntimeData = (project) => {
|
|
|
5141
5494
|
var planMcp = (project, srcDir) => {
|
|
5142
5495
|
const { config } = project;
|
|
5143
5496
|
const { route } = config.mcp;
|
|
5144
|
-
const dir =
|
|
5497
|
+
const dir = join11(srcDir, "blume-mcp");
|
|
5145
5498
|
const base = {
|
|
5146
5499
|
dir,
|
|
5147
5500
|
discoveryPages: [],
|
|
@@ -5165,11 +5518,11 @@ var planMcp = (project, srcDir) => {
|
|
|
5165
5518
|
...base,
|
|
5166
5519
|
discoveryPages: [
|
|
5167
5520
|
{
|
|
5168
|
-
entrypoint:
|
|
5521
|
+
entrypoint: join11(dir, "discovery.ts"),
|
|
5169
5522
|
pattern: "/.well-known/mcp.json"
|
|
5170
5523
|
},
|
|
5171
5524
|
{
|
|
5172
|
-
entrypoint:
|
|
5525
|
+
entrypoint: join11(dir, "server-card.ts"),
|
|
5173
5526
|
pattern: "/.well-known/mcp/server-card.json"
|
|
5174
5527
|
}
|
|
5175
5528
|
],
|
|
@@ -5188,20 +5541,21 @@ var writeMcpFiles = async (project, plan, write) => {
|
|
|
5188
5541
|
version: data.version
|
|
5189
5542
|
};
|
|
5190
5543
|
await Promise.all([
|
|
5191
|
-
write(
|
|
5544
|
+
write(join11(plan.srcDir, "generated", "mcp-data.json"), `${JSON.stringify(data)}
|
|
5192
5545
|
`),
|
|
5193
|
-
write(
|
|
5194
|
-
write(
|
|
5195
|
-
write(
|
|
5546
|
+
write(join11(plan.srcDir, "pages", mcpPageFile(plan.route)), mcpEndpointTemplate(plan.route)),
|
|
5547
|
+
write(join11(plan.dir, "discovery.ts"), staticJsonEndpointTemplate(buildMcpDiscovery(discoveryInput))),
|
|
5548
|
+
write(join11(plan.dir, "server-card.ts"), staticJsonEndpointTemplate(buildMcpServerCard(discoveryInput)))
|
|
5196
5549
|
]);
|
|
5197
5550
|
};
|
|
5198
5551
|
var generateRuntime = async (project) => {
|
|
5199
5552
|
const { context, config } = project;
|
|
5200
5553
|
const out = context.outDir;
|
|
5201
|
-
const srcDir =
|
|
5202
|
-
const dataPath =
|
|
5203
|
-
const themePath =
|
|
5204
|
-
const searchClientPath =
|
|
5554
|
+
const srcDir = join11(out, "src");
|
|
5555
|
+
const dataPath = join11(srcDir, "generated", "data.json");
|
|
5556
|
+
const themePath = join11(srcDir, "generated", "app.css");
|
|
5557
|
+
const searchClientPath = join11(srcDir, "generated", "search-client.ts");
|
|
5558
|
+
const examplesPath = join11(srcDir, "generated", "examples.ts");
|
|
5205
5559
|
const written = new Set;
|
|
5206
5560
|
const write = (path, content) => {
|
|
5207
5561
|
written.add(normalize(path));
|
|
@@ -5211,26 +5565,33 @@ var generateRuntime = async (project) => {
|
|
|
5211
5565
|
const askEnabled = config.ai.ask?.enabled ?? false;
|
|
5212
5566
|
const exportPdf = config.export.pdf;
|
|
5213
5567
|
const exportEpub = config.export.epub;
|
|
5214
|
-
const [pages, detectedReact, userTheme, islandDiscovery] = await Promise.all([
|
|
5568
|
+
const [pages, detectedReact, userTheme, islandDiscovery, exampleDiscovery] = await Promise.all([
|
|
5215
5569
|
context.pagesRoot ? discoverPages(context.pagesRoot) : Promise.resolve([]),
|
|
5216
5570
|
detectNeedsReact(context.root),
|
|
5217
5571
|
readOptional(context.themeFile),
|
|
5218
|
-
discoverIslands(context.root)
|
|
5572
|
+
discoverIslands(context.root),
|
|
5573
|
+
discoverExamples(context.root)
|
|
5219
5574
|
]);
|
|
5220
|
-
const
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5575
|
+
const frameworks = new Set([
|
|
5576
|
+
...islandDiscovery.islands.map((island) => island.framework),
|
|
5577
|
+
...exampleDiscovery.examples.map((example) => example.framework)
|
|
5578
|
+
]);
|
|
5579
|
+
const needsReact = detectedReact || askEnabled || frameworks.has("react");
|
|
5580
|
+
const needsVue = frameworks.has("vue");
|
|
5581
|
+
const needsSvelte = frameworks.has("svelte");
|
|
5582
|
+
const ogRoutes = customOgRoutes(pages, config.title, config.description);
|
|
5224
5583
|
const mcp = planMcp(project, srcDir);
|
|
5225
5584
|
pages.push(...mcp.discoveryPages);
|
|
5226
5585
|
const staged = collectStaged(project);
|
|
5227
5586
|
const hasStaged = staged.size > 0;
|
|
5228
5587
|
const structural = await Promise.all([
|
|
5229
|
-
write(
|
|
5588
|
+
write(join11(out, "astro.config.mjs"), astroConfigTemplate({
|
|
5589
|
+
aliases: resolveTsconfigAliases(context.root),
|
|
5230
5590
|
config,
|
|
5231
5591
|
contentRoutes: project.manifest.routes.map((route) => route.path),
|
|
5232
5592
|
context,
|
|
5233
5593
|
dataPath,
|
|
5594
|
+
examplesPath,
|
|
5234
5595
|
needsReact,
|
|
5235
5596
|
needsSvelte,
|
|
5236
5597
|
needsVue,
|
|
@@ -5238,18 +5599,19 @@ var generateRuntime = async (project) => {
|
|
|
5238
5599
|
searchClientPath,
|
|
5239
5600
|
themePath
|
|
5240
5601
|
})),
|
|
5241
|
-
write(
|
|
5242
|
-
write(
|
|
5243
|
-
write(
|
|
5244
|
-
write(
|
|
5245
|
-
write(
|
|
5602
|
+
write(join11(out, "package.json"), runtimePackageTemplate(runtimeDependencies({ config, needsReact, needsSvelte, needsVue }))),
|
|
5603
|
+
write(join11(out, "tsconfig.json"), runtimeTsconfigTemplate()),
|
|
5604
|
+
write(join11(srcDir, "env.d.ts"), envTemplate()),
|
|
5605
|
+
write(join11(srcDir, "content.config.ts"), contentConfigTemplate({ config, context, staged: hasStaged })),
|
|
5606
|
+
write(join11(srcDir, "pages", "[...slug].astro"), catchAllPageTemplate({
|
|
5246
5607
|
askEnabled,
|
|
5247
5608
|
exportEpub,
|
|
5248
5609
|
exportPdf,
|
|
5249
5610
|
mathEnabled: config.markdown.math
|
|
5250
5611
|
})),
|
|
5251
|
-
write(
|
|
5252
|
-
write(
|
|
5612
|
+
write(join11(srcDir, "generated", "components.ts"), userComponentsTemplate(context.componentsFile)),
|
|
5613
|
+
write(join11(srcDir, "generated", "islands.ts"), islandMapTemplate(islandDiscovery.islands)),
|
|
5614
|
+
write(join11(srcDir, "generated", "examples.ts"), exampleMapTemplate(exampleDiscovery.examples)),
|
|
5253
5615
|
write(themePath, tailwindEntryTemplate({
|
|
5254
5616
|
configTokens: `${buildThemeCss(config.theme)}${buildFontsCss(config.theme.fonts)}`,
|
|
5255
5617
|
sources: [
|
|
@@ -5260,52 +5622,57 @@ var generateRuntime = async (project) => {
|
|
|
5260
5622
|
userTheme
|
|
5261
5623
|
}))
|
|
5262
5624
|
]);
|
|
5263
|
-
await Promise.all(islandDiscovery.islands.map((island) => write(
|
|
5625
|
+
await Promise.all(islandDiscovery.islands.map((island) => write(join11(srcDir, "generated", "islands", `${island.name}.astro`), islandWrapperTemplate(island))));
|
|
5626
|
+
await Promise.all(exampleDiscovery.examples.map((example) => write(join11(srcDir, "generated", "examples", `${exampleSlug(example.path)}.astro`), exampleWrapperTemplate(example))));
|
|
5264
5627
|
if (askEnabled) {
|
|
5265
|
-
await write(
|
|
5628
|
+
await write(join11(srcDir, "pages", "api", "ask.ts"), askEndpointTemplate(resolveAskBackend(config.ai.ask)));
|
|
5266
5629
|
}
|
|
5267
5630
|
await writeMcpFiles(project, mcp, write);
|
|
5268
5631
|
if (config.seo.og.enabled) {
|
|
5269
|
-
await write(
|
|
5632
|
+
await write(join11(srcDir, "pages", "og", "[...slug].png.ts"), ogEndpointTemplate(ogRoutes));
|
|
5270
5633
|
}
|
|
5271
5634
|
const hasChangelog = project.graph.pages.some((page) => page.contentType === "changelog" && !(page.meta.draft || page.meta.sidebar.hidden));
|
|
5272
5635
|
const changelogRouteTaken = project.graph.pages.some((page) => page.route === "/changelog");
|
|
5273
5636
|
if (hasChangelog && !changelogRouteTaken) {
|
|
5274
|
-
await write(
|
|
5637
|
+
await write(join11(srcDir, "pages", "changelog.astro"), changelogIndexTemplate({ askEnabled, exportEpub, exportPdf }));
|
|
5275
5638
|
}
|
|
5276
5639
|
await write(searchClientPath, searchClientTemplate(config));
|
|
5277
5640
|
if (servesStaticIndex(config.search.provider)) {
|
|
5278
5641
|
const documents = await buildSearchDocuments(project);
|
|
5279
|
-
await write(
|
|
5642
|
+
await write(join11(srcDir, "generated", "search.json"), `${JSON.stringify(documents)}
|
|
5280
5643
|
`);
|
|
5281
|
-
await write(
|
|
5644
|
+
await write(join11(srcDir, "pages", "blume-search.json.ts"), searchEndpointTemplate());
|
|
5282
5645
|
}
|
|
5283
5646
|
if (config.search.provider === "mixedbread") {
|
|
5284
|
-
await write(
|
|
5647
|
+
await write(join11(srcDir, "pages", "api", "search.ts"), mixedbreadSearchEndpointTemplate(config.search.mixedbread?.storeId ?? ""));
|
|
5285
5648
|
}
|
|
5286
5649
|
const rawMarkdown = await buildRawMarkdown(project);
|
|
5287
5650
|
await Promise.all([
|
|
5288
|
-
write(
|
|
5651
|
+
write(join11(srcDir, "generated", "raw-markdown.json"), `${JSON.stringify(rawMarkdown)}
|
|
5289
5652
|
`),
|
|
5290
|
-
write(
|
|
5291
|
-
write(
|
|
5653
|
+
write(join11(srcDir, "pages", "[...slug].md.ts"), rawMarkdownEndpointTemplate()),
|
|
5654
|
+
write(join11(srcDir, "pages", "[...slug].mdx.ts"), rawMarkdownEndpointTemplate())
|
|
5292
5655
|
]);
|
|
5293
5656
|
const feeds = buildRssFeeds(project);
|
|
5294
5657
|
if (feeds.length > 0) {
|
|
5295
5658
|
const feedXml = Object.fromEntries(feeds.map((feed) => [feed.type, renderRssFeed(feed)]));
|
|
5296
5659
|
await Promise.all([
|
|
5297
|
-
write(
|
|
5660
|
+
write(join11(srcDir, "generated", "rss.json"), `${JSON.stringify(feedXml)}
|
|
5298
5661
|
`),
|
|
5299
|
-
write(
|
|
5662
|
+
write(join11(srcDir, "pages", "[section]", "rss.xml.ts"), rssEndpointTemplate())
|
|
5300
5663
|
]);
|
|
5301
5664
|
}
|
|
5302
|
-
const warnings = [
|
|
5665
|
+
const warnings = [
|
|
5666
|
+
...mcp.warnings,
|
|
5667
|
+
...islandDiscovery.warnings,
|
|
5668
|
+
...exampleDiscovery.warnings
|
|
5669
|
+
];
|
|
5303
5670
|
for (const dep of searchProviderMeta(config.search.provider).runtimeDeps) {
|
|
5304
5671
|
if (!canResolveFrom(context.root, dep)) {
|
|
5305
5672
|
warnings.push(`Search provider "${config.search.provider}" needs "${dep}", which isn't installed. Run \`npm install ${dep}\` (or your package manager's equivalent).`);
|
|
5306
5673
|
}
|
|
5307
5674
|
}
|
|
5308
|
-
warnings.push(...islandFrameworkWarnings(
|
|
5675
|
+
warnings.push(...islandFrameworkWarnings(frameworks, context.root));
|
|
5309
5676
|
if (hasReferences(config)) {
|
|
5310
5677
|
const references = await buildReferenceFiles({
|
|
5311
5678
|
config,
|
|
@@ -5313,10 +5680,10 @@ var generateRuntime = async (project) => {
|
|
|
5313
5680
|
root: context.root
|
|
5314
5681
|
});
|
|
5315
5682
|
warnings.push(...references.warnings);
|
|
5316
|
-
await Promise.all(references.files.map((file) => write(
|
|
5683
|
+
await Promise.all(references.files.map((file) => write(join11(srcDir, "pages", file.pagePath), file.content)));
|
|
5317
5684
|
}
|
|
5318
|
-
await write(
|
|
5319
|
-
await write(
|
|
5685
|
+
await write(join11(srcDir, "generated", "data.json"), buildRuntimeData(project));
|
|
5686
|
+
await write(join11(out, "blume.manifest.json"), `${JSON.stringify(project.manifest, null, 2)}
|
|
5320
5687
|
`);
|
|
5321
5688
|
await writeStagedContent(out, staged);
|
|
5322
5689
|
await pruneOrphans(srcDir, written);
|
|
@@ -5324,13 +5691,13 @@ var generateRuntime = async (project) => {
|
|
|
5324
5691
|
};
|
|
5325
5692
|
|
|
5326
5693
|
// src/core/bridge.ts
|
|
5327
|
-
import { existsSync as
|
|
5328
|
-
import { readFile as
|
|
5329
|
-
import { join as
|
|
5694
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
5695
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
5696
|
+
import { join as join12 } from "pathe";
|
|
5330
5697
|
|
|
5331
5698
|
// src/migrate/mintlify/config.ts
|
|
5332
|
-
import { readFile as
|
|
5333
|
-
import { dirname as
|
|
5699
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
5700
|
+
import { dirname as dirname7, relative as relative6, resolve as resolve3 } from "pathe";
|
|
5334
5701
|
var MINTLIFY_DEFAULT_IGNORES = [
|
|
5335
5702
|
"**/_*",
|
|
5336
5703
|
"**/.*",
|
|
@@ -5366,12 +5733,12 @@ var asDirectoryMode = (value) => value === "accordion" || value === "card" || va
|
|
|
5366
5733
|
var withoutUndefined = (value) => Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
|
|
5367
5734
|
var hasOwn = (object, key) => Object.hasOwn(object, key);
|
|
5368
5735
|
var isInsideRoot = (root, candidate) => {
|
|
5369
|
-
const rel =
|
|
5736
|
+
const rel = relative6(root, candidate);
|
|
5370
5737
|
return rel === "" || !rel.startsWith("..") && !rel.startsWith("/");
|
|
5371
5738
|
};
|
|
5372
5739
|
var readJsonFile = async (file) => {
|
|
5373
5740
|
try {
|
|
5374
|
-
return JSON.parse(await
|
|
5741
|
+
return JSON.parse(await readFile8(file, "utf-8"));
|
|
5375
5742
|
} catch (error) {
|
|
5376
5743
|
throw new BlumeError({
|
|
5377
5744
|
code: "BLUME_MINTLIFY_CONFIG_INVALID",
|
|
@@ -5391,7 +5758,7 @@ var resolveRefs = async (value, options) => {
|
|
|
5391
5758
|
}
|
|
5392
5759
|
const ref = asString(object.$ref);
|
|
5393
5760
|
if (ref) {
|
|
5394
|
-
const refFile =
|
|
5761
|
+
const refFile = resolve3(dirname7(options.file), ref);
|
|
5395
5762
|
if (!isInsideRoot(options.root, refFile)) {
|
|
5396
5763
|
throw new BlumeError({
|
|
5397
5764
|
code: "BLUME_MINTLIFY_REF_OUTSIDE_ROOT",
|
|
@@ -5791,7 +6158,7 @@ var mintlifyNavbar = (value) => {
|
|
|
5791
6158
|
};
|
|
5792
6159
|
var mintignorePatterns = async (root) => {
|
|
5793
6160
|
try {
|
|
5794
|
-
const raw = await
|
|
6161
|
+
const raw = await readFile8(resolve3(root, ".mintignore"), "utf-8");
|
|
5795
6162
|
return raw.split(`
|
|
5796
6163
|
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).filter((line) => !line.startsWith("!")).map((line) => line.endsWith("/") ? `${line}**` : line);
|
|
5797
6164
|
} catch {
|
|
@@ -6015,8 +6382,8 @@ var mintlifyIcons = (value) => {
|
|
|
6015
6382
|
});
|
|
6016
6383
|
};
|
|
6017
6384
|
var loadMintlifyConfig = async (root, file) => {
|
|
6018
|
-
const projectRoot =
|
|
6019
|
-
const configFile =
|
|
6385
|
+
const projectRoot = resolve3(root);
|
|
6386
|
+
const configFile = resolve3(file);
|
|
6020
6387
|
const spec = asObject(await resolveRefs(await readJsonFile(configFile), {
|
|
6021
6388
|
file: configFile,
|
|
6022
6389
|
root: projectRoot,
|
|
@@ -6117,12 +6484,12 @@ var mintlifyI18n = (spec) => {
|
|
|
6117
6484
|
// src/core/bridge.ts
|
|
6118
6485
|
var MINTLIFY_CONFIG_FILES = ["docs.json", "mint.json"];
|
|
6119
6486
|
var detectMintlifyBridge = async (root) => {
|
|
6120
|
-
const configFile = MINTLIFY_CONFIG_FILES.map((name) =>
|
|
6487
|
+
const configFile = MINTLIFY_CONFIG_FILES.map((name) => join12(root, name)).find((candidate) => existsSync6(candidate));
|
|
6121
6488
|
if (!configFile) {
|
|
6122
6489
|
return null;
|
|
6123
6490
|
}
|
|
6124
6491
|
const config = await loadMintlifyConfig(root, configFile);
|
|
6125
|
-
const spec = JSON.parse(await
|
|
6492
|
+
const spec = JSON.parse(await readFile9(configFile, "utf-8"));
|
|
6126
6493
|
const i18n = mintlifyI18n(spec);
|
|
6127
6494
|
if (i18n) {
|
|
6128
6495
|
config.i18n = i18n;
|
|
@@ -6206,8 +6573,8 @@ var createModuleLoader = () => {
|
|
|
6206
6573
|
};
|
|
6207
6574
|
|
|
6208
6575
|
// src/core/project.ts
|
|
6209
|
-
import { existsSync as
|
|
6210
|
-
import { isAbsolute as
|
|
6576
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
6577
|
+
import { isAbsolute as isAbsolute3, join as join13, resolve as resolve4 } from "pathe";
|
|
6211
6578
|
var CONFIG_FILENAMES = [
|
|
6212
6579
|
"blume.config.ts",
|
|
6213
6580
|
"blume.config.mjs",
|
|
@@ -6217,8 +6584,8 @@ var THEME_FILENAMES = ["theme.css"];
|
|
|
6217
6584
|
var COMPONENTS_FILENAMES = ["components.tsx", "components.ts"];
|
|
6218
6585
|
var firstExisting = (root, names) => {
|
|
6219
6586
|
for (const name of names) {
|
|
6220
|
-
const candidate =
|
|
6221
|
-
if (
|
|
6587
|
+
const candidate = join13(root, name);
|
|
6588
|
+
if (existsSync7(candidate)) {
|
|
6222
6589
|
return candidate;
|
|
6223
6590
|
}
|
|
6224
6591
|
}
|
|
@@ -6226,15 +6593,15 @@ var firstExisting = (root, names) => {
|
|
|
6226
6593
|
};
|
|
6227
6594
|
var findConfigFile = (root) => firstExisting(root, CONFIG_FILENAMES);
|
|
6228
6595
|
var resolveProjectContext = (root, config) => {
|
|
6229
|
-
const absoluteRoot =
|
|
6230
|
-
const contentRoot =
|
|
6231
|
-
const pagesPath =
|
|
6232
|
-
const pagesRoot =
|
|
6596
|
+
const absoluteRoot = resolve4(root);
|
|
6597
|
+
const contentRoot = isAbsolute3(config.content.root) ? config.content.root : join13(absoluteRoot, config.content.root);
|
|
6598
|
+
const pagesPath = join13(absoluteRoot, config.content.pages);
|
|
6599
|
+
const pagesRoot = existsSync7(pagesPath) ? pagesPath : null;
|
|
6233
6600
|
return {
|
|
6234
6601
|
componentsFile: firstExisting(absoluteRoot, COMPONENTS_FILENAMES),
|
|
6235
6602
|
configFile: findConfigFile(absoluteRoot),
|
|
6236
6603
|
contentRoot,
|
|
6237
|
-
outDir:
|
|
6604
|
+
outDir: join13(absoluteRoot, ".blume"),
|
|
6238
6605
|
pagesRoot,
|
|
6239
6606
|
root: absoluteRoot,
|
|
6240
6607
|
themeFile: firstExisting(absoluteRoot, THEME_FILENAMES)
|
|
@@ -7183,7 +7550,7 @@ var buildContentGraph = (pages, options) => {
|
|
|
7183
7550
|
|
|
7184
7551
|
// src/core/last-modified.ts
|
|
7185
7552
|
import { execFileSync } from "node:child_process";
|
|
7186
|
-
import { relative as
|
|
7553
|
+
import { relative as relative7 } from "pathe";
|
|
7187
7554
|
var resolveLastModifiedConfig = (value) => {
|
|
7188
7555
|
if (value === false) {
|
|
7189
7556
|
return { enabled: false, source: "git" };
|
|
@@ -7223,7 +7590,7 @@ var gitLastModifiedTimes = (root, contentRoot, sourcePaths) => {
|
|
|
7223
7590
|
const byRepoPath = parseGitLog(output);
|
|
7224
7591
|
const result = new Map;
|
|
7225
7592
|
for (const sourcePath of sourcePaths) {
|
|
7226
|
-
const iso = byRepoPath.get(
|
|
7593
|
+
const iso = byRepoPath.get(relative7(gitRoot, sourcePath));
|
|
7227
7594
|
if (iso) {
|
|
7228
7595
|
result.set(sourcePath, iso);
|
|
7229
7596
|
}
|
|
@@ -7235,8 +7602,8 @@ var gitLastModifiedTimes = (root, contentRoot, sourcePaths) => {
|
|
|
7235
7602
|
};
|
|
7236
7603
|
|
|
7237
7604
|
// src/core/meta.ts
|
|
7238
|
-
import { basename as basename2, dirname as
|
|
7239
|
-
import { glob as
|
|
7605
|
+
import { basename as basename2, dirname as dirname8, relative as relative8 } from "pathe";
|
|
7606
|
+
import { glob as glob5 } from "tinyglobby";
|
|
7240
7607
|
var META_FILES = [
|
|
7241
7608
|
"**/meta.ts",
|
|
7242
7609
|
"**/meta.js",
|
|
@@ -7247,16 +7614,16 @@ var META_FILES = [
|
|
|
7247
7614
|
];
|
|
7248
7615
|
var resolveMeta = async (mod) => typeof mod === "function" ? await mod() : mod;
|
|
7249
7616
|
var discoverFolderMeta = async (contentRoot) => {
|
|
7250
|
-
const files = await
|
|
7617
|
+
const files = await glob5(META_FILES, {
|
|
7251
7618
|
absolute: true,
|
|
7252
7619
|
cwd: contentRoot,
|
|
7253
7620
|
ignore: ["**/node_modules/**", "**/.blume/**", "**/dist/**"],
|
|
7254
7621
|
onlyFiles: true
|
|
7255
7622
|
});
|
|
7256
|
-
const
|
|
7623
|
+
const load2 = createModuleLoader();
|
|
7257
7624
|
const loaded = await Promise.all(files.map(async (file) => {
|
|
7258
7625
|
try {
|
|
7259
|
-
return { file, ok: true, value: await resolveMeta(await
|
|
7626
|
+
return { file, ok: true, value: await resolveMeta(await load2(file)) };
|
|
7260
7627
|
} catch (error) {
|
|
7261
7628
|
return { error, file, ok: false };
|
|
7262
7629
|
}
|
|
@@ -7265,7 +7632,7 @@ var discoverFolderMeta = async (contentRoot) => {
|
|
|
7265
7632
|
const shared = new Map;
|
|
7266
7633
|
const diagnostics = [];
|
|
7267
7634
|
for (const entry of loaded) {
|
|
7268
|
-
const dir =
|
|
7635
|
+
const dir = relative8(contentRoot, dirname8(entry.file));
|
|
7269
7636
|
if (!entry.ok) {
|
|
7270
7637
|
diagnostics.push({
|
|
7271
7638
|
code: "BLUME_META_LOAD_FAILED",
|
|
@@ -7290,6 +7657,7 @@ var discoverFolderMeta = async (contentRoot) => {
|
|
|
7290
7657
|
};
|
|
7291
7658
|
|
|
7292
7659
|
// src/core/sources/normalize.ts
|
|
7660
|
+
import GithubSlugger from "github-slugger";
|
|
7293
7661
|
import { extname as extname3 } from "pathe";
|
|
7294
7662
|
var NUMERIC_PREFIX2 = /^\d+[-_.]/u;
|
|
7295
7663
|
var GROUP_FOLDER2 = /^\((?<label>.+)\)$/u;
|
|
@@ -7322,6 +7690,7 @@ var CODE_FENCE2 = /^```/u;
|
|
|
7322
7690
|
var ATX_HEADING = /^(?<hashes>#{1,6})\s+(?<text>.+?)\s*#*$/u;
|
|
7323
7691
|
var extractHeadings = (body) => {
|
|
7324
7692
|
const headings = [];
|
|
7693
|
+
const slugger = new GithubSlugger;
|
|
7325
7694
|
let inFence = false;
|
|
7326
7695
|
for (const line of body.split(`
|
|
7327
7696
|
`)) {
|
|
@@ -7336,7 +7705,7 @@ var extractHeadings = (body) => {
|
|
|
7336
7705
|
if (match?.groups) {
|
|
7337
7706
|
const depth = match.groups.hashes?.length ?? 1;
|
|
7338
7707
|
const text = (match.groups.text ?? "").trim();
|
|
7339
|
-
headings.push({ depth, slug:
|
|
7708
|
+
headings.push({ depth, slug: slugger.slug(text), text });
|
|
7340
7709
|
}
|
|
7341
7710
|
}
|
|
7342
7711
|
return headings;
|
|
@@ -7433,18 +7802,17 @@ var normalizeEntry = (entry, ctx) => {
|
|
|
7433
7802
|
};
|
|
7434
7803
|
|
|
7435
7804
|
// src/core/sources/resolve.ts
|
|
7436
|
-
import { join as
|
|
7805
|
+
import { join as join22 } from "pathe";
|
|
7437
7806
|
|
|
7438
7807
|
// src/core/sources/filesystem.ts
|
|
7439
|
-
import { existsSync as
|
|
7440
|
-
import { readFile as
|
|
7441
|
-
import
|
|
7442
|
-
import {
|
|
7443
|
-
import { glob as glob5 } from "tinyglobby";
|
|
7808
|
+
import { existsSync as existsSync8, watch as fsWatch } from "node:fs";
|
|
7809
|
+
import { readFile as readFile10 } from "node:fs/promises";
|
|
7810
|
+
import { extname as extname4, isAbsolute as isAbsolute4, join as join14, relative as relative9, resolve as resolve5 } from "pathe";
|
|
7811
|
+
import { glob as glob6 } from "tinyglobby";
|
|
7444
7812
|
var filesystemSource = (options) => {
|
|
7445
|
-
const contentRoot =
|
|
7446
|
-
const
|
|
7447
|
-
const files = await
|
|
7813
|
+
const contentRoot = isAbsolute4(options.root) ? options.root : join14(resolve5(options.projectRoot), options.root);
|
|
7814
|
+
const load2 = async () => {
|
|
7815
|
+
const files = await glob6(options.include, {
|
|
7448
7816
|
absolute: true,
|
|
7449
7817
|
cwd: contentRoot,
|
|
7450
7818
|
ignore: options.exclude,
|
|
@@ -7452,21 +7820,21 @@ var filesystemSource = (options) => {
|
|
|
7452
7820
|
});
|
|
7453
7821
|
files.sort();
|
|
7454
7822
|
const entries = await Promise.all(files.map(async (file) => {
|
|
7455
|
-
const source = await
|
|
7823
|
+
const source = await readFile10(file, "utf-8");
|
|
7456
7824
|
const ext = extname4(file).toLowerCase();
|
|
7457
7825
|
const format = ext === ".mdx" ? "mdx" : "md";
|
|
7458
|
-
const parsed =
|
|
7826
|
+
const parsed = frontmatter_default(source);
|
|
7459
7827
|
return {
|
|
7460
7828
|
body: { format, text: parsed.content },
|
|
7461
7829
|
data: parsed.data,
|
|
7462
|
-
ref:
|
|
7830
|
+
ref: relative9(contentRoot, file),
|
|
7463
7831
|
sourcePath: file
|
|
7464
7832
|
};
|
|
7465
7833
|
}));
|
|
7466
7834
|
return { diagnostics: [], entries };
|
|
7467
7835
|
};
|
|
7468
7836
|
const validate = () => {
|
|
7469
|
-
if (!
|
|
7837
|
+
if (!existsSync8(contentRoot)) {
|
|
7470
7838
|
throw new BlumeError({
|
|
7471
7839
|
code: options.missingCode ?? "BLUME_CONTENT_ROOT_MISSING",
|
|
7472
7840
|
file: contentRoot,
|
|
@@ -7477,7 +7845,7 @@ var filesystemSource = (options) => {
|
|
|
7477
7845
|
}
|
|
7478
7846
|
};
|
|
7479
7847
|
const watch = (onChange) => {
|
|
7480
|
-
if (!
|
|
7848
|
+
if (!existsSync8(contentRoot)) {
|
|
7481
7849
|
return () => {};
|
|
7482
7850
|
}
|
|
7483
7851
|
const watcher = fsWatch(contentRoot, { recursive: true }, onChange);
|
|
@@ -7485,22 +7853,19 @@ var filesystemSource = (options) => {
|
|
|
7485
7853
|
};
|
|
7486
7854
|
return {
|
|
7487
7855
|
contentRoot,
|
|
7488
|
-
load,
|
|
7856
|
+
load: load2,
|
|
7489
7857
|
name: options.name,
|
|
7490
7858
|
prefix: options.prefix,
|
|
7491
|
-
read: (ref) =>
|
|
7859
|
+
read: (ref) => readFile10(join14(contentRoot, ref), "utf-8"),
|
|
7492
7860
|
staged: false,
|
|
7493
7861
|
validate,
|
|
7494
7862
|
watch
|
|
7495
7863
|
};
|
|
7496
7864
|
};
|
|
7497
7865
|
|
|
7498
|
-
// src/core/sources/mdx-remote.ts
|
|
7499
|
-
import matter4 from "gray-matter";
|
|
7500
|
-
|
|
7501
7866
|
// src/core/sources/cache.ts
|
|
7502
|
-
import { mkdir as mkdir3, readFile as
|
|
7503
|
-
import { join as
|
|
7867
|
+
import { mkdir as mkdir3, readFile as readFile11, writeFile as writeFile3 } from "node:fs/promises";
|
|
7868
|
+
import { join as join15 } from "pathe";
|
|
7504
7869
|
var hashText = (text) => {
|
|
7505
7870
|
let hash = 5381;
|
|
7506
7871
|
for (let i = 0;i < text.length; i += 1) {
|
|
@@ -7509,11 +7874,11 @@ var hashText = (text) => {
|
|
|
7509
7874
|
return hash.toString(36);
|
|
7510
7875
|
};
|
|
7511
7876
|
var entriesDigest = (entries) => hashText(entries.map((entry) => `${entry.ref}:${entry.hash ?? hashText(entry.body.text)}`).join("|"));
|
|
7512
|
-
var pollingWatch = (
|
|
7877
|
+
var pollingWatch = (load2, intervalSeconds) => (onChange) => {
|
|
7513
7878
|
let last = "";
|
|
7514
7879
|
const tick = async () => {
|
|
7515
7880
|
try {
|
|
7516
|
-
const { entries } = await
|
|
7881
|
+
const { entries } = await load2();
|
|
7517
7882
|
const next = entriesDigest(entries);
|
|
7518
7883
|
if (last && next !== last) {
|
|
7519
7884
|
onChange();
|
|
@@ -7527,11 +7892,11 @@ var pollingWatch = (load, intervalSeconds) => (onChange) => {
|
|
|
7527
7892
|
return () => clearInterval(timer);
|
|
7528
7893
|
};
|
|
7529
7894
|
var snapshotCache = (cacheDir) => {
|
|
7530
|
-
const file =
|
|
7895
|
+
const file = join15(cacheDir, "entries.json");
|
|
7531
7896
|
return {
|
|
7532
7897
|
read: async () => {
|
|
7533
7898
|
try {
|
|
7534
|
-
return JSON.parse(await
|
|
7899
|
+
return JSON.parse(await readFile11(file, "utf-8"));
|
|
7535
7900
|
} catch {
|
|
7536
7901
|
return [];
|
|
7537
7902
|
}
|
|
@@ -7663,7 +8028,7 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
7663
8028
|
throw new Error(`${item.fetchUrl} -> ${res.status}`);
|
|
7664
8029
|
}
|
|
7665
8030
|
const text = await res.text();
|
|
7666
|
-
const parsed =
|
|
8031
|
+
const parsed = frontmatter_default(text);
|
|
7667
8032
|
const format = item.ref.toLowerCase().endsWith(".mdx") ? "mdx" : "md";
|
|
7668
8033
|
return {
|
|
7669
8034
|
body: { format, text: parsed.content },
|
|
@@ -7674,7 +8039,7 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
7674
8039
|
ref: item.ref
|
|
7675
8040
|
};
|
|
7676
8041
|
};
|
|
7677
|
-
const
|
|
8042
|
+
const load2 = async () => {
|
|
7678
8043
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
7679
8044
|
const refs = await enumerate();
|
|
7680
8045
|
return await Promise.all(refs.map(fetchEntry));
|
|
@@ -7692,35 +8057,91 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
7692
8057
|
return entry?.raw ?? entry?.body.text ?? "";
|
|
7693
8058
|
};
|
|
7694
8059
|
return {
|
|
7695
|
-
load,
|
|
8060
|
+
load: load2,
|
|
7696
8061
|
name: options.name,
|
|
7697
8062
|
prefix: options.prefix,
|
|
7698
8063
|
read,
|
|
7699
8064
|
staged: true,
|
|
7700
|
-
watch: options.pollInterval ? pollingWatch(
|
|
8065
|
+
watch: options.pollInterval ? pollingWatch(load2, options.pollInterval) : undefined
|
|
7701
8066
|
};
|
|
7702
8067
|
};
|
|
7703
8068
|
|
|
7704
8069
|
// src/core/sources/mintlify.ts
|
|
7705
|
-
import { existsSync as
|
|
7706
|
-
import { readFile as
|
|
7707
|
-
import
|
|
7708
|
-
import {
|
|
7709
|
-
import { glob as glob6 } from "tinyglobby";
|
|
7710
|
-
|
|
7711
|
-
// src/migrate/mintlify/transform.ts
|
|
7712
|
-
import matter6 from "gray-matter";
|
|
8070
|
+
import { existsSync as existsSync10, watch as fsWatch2 } from "node:fs";
|
|
8071
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
8072
|
+
import { isAbsolute as isAbsolute5, join as join18, relative as relative12, resolve as resolve7 } from "pathe";
|
|
8073
|
+
import { glob as glob7 } from "tinyglobby";
|
|
7713
8074
|
|
|
7714
8075
|
// src/migrate/shared.ts
|
|
7715
|
-
import {
|
|
7716
|
-
import {
|
|
8076
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
8077
|
+
import { readFile as readFile12, writeFile as writeFile4 } from "node:fs/promises";
|
|
8078
|
+
import { join as join16 } from "pathe";
|
|
7717
8079
|
var writeBlumeConfig = async (root, config) => {
|
|
7718
8080
|
const body = `import { defineConfig } from "blume";
|
|
7719
8081
|
|
|
7720
8082
|
export default defineConfig(${JSON.stringify(config, null, 2)});
|
|
7721
8083
|
`;
|
|
7722
|
-
await writeFile4(
|
|
8084
|
+
await writeFile4(join16(root, "blume.config.ts"), body, "utf-8");
|
|
7723
8085
|
};
|
|
8086
|
+
var BLUME_SCRIPTS = {
|
|
8087
|
+
build: "blume build",
|
|
8088
|
+
dev: "blume dev",
|
|
8089
|
+
start: "blume preview"
|
|
8090
|
+
};
|
|
8091
|
+
var rewriteFrameworkScripts = async (root, cli, remove) => {
|
|
8092
|
+
const pkgPath = join16(root, "package.json");
|
|
8093
|
+
if (!existsSync9(pkgPath)) {
|
|
8094
|
+
return false;
|
|
8095
|
+
}
|
|
8096
|
+
let pkg;
|
|
8097
|
+
try {
|
|
8098
|
+
pkg = JSON.parse(await readFile12(pkgPath, "utf-8"));
|
|
8099
|
+
} catch {
|
|
8100
|
+
return false;
|
|
8101
|
+
}
|
|
8102
|
+
const { scripts } = pkg;
|
|
8103
|
+
if (!scripts || typeof scripts !== "object") {
|
|
8104
|
+
return false;
|
|
8105
|
+
}
|
|
8106
|
+
const next = {};
|
|
8107
|
+
let changed = false;
|
|
8108
|
+
for (const [name, command] of Object.entries(scripts)) {
|
|
8109
|
+
const blume = BLUME_SCRIPTS[name];
|
|
8110
|
+
if (typeof command === "string" && remove?.test(command)) {
|
|
8111
|
+
changed = true;
|
|
8112
|
+
} else if (typeof command === "string" && blume && cli.test(command) && command !== blume) {
|
|
8113
|
+
next[name] = blume;
|
|
8114
|
+
changed = true;
|
|
8115
|
+
} else {
|
|
8116
|
+
next[name] = command;
|
|
8117
|
+
}
|
|
8118
|
+
}
|
|
8119
|
+
if (changed) {
|
|
8120
|
+
pkg.scripts = next;
|
|
8121
|
+
await writeFile4(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
8122
|
+
`, "utf-8");
|
|
8123
|
+
}
|
|
8124
|
+
return changed;
|
|
8125
|
+
};
|
|
8126
|
+
var gitignoreKey = (line) => line.trim().replace(/\/+$/u, "");
|
|
8127
|
+
var ensureGitignore = async (root, entries) => {
|
|
8128
|
+
const path = join16(root, ".gitignore");
|
|
8129
|
+
const existing = existsSync9(path) ? await readFile12(path, "utf-8") : "";
|
|
8130
|
+
const present = new Set(existing.split(`
|
|
8131
|
+
`).map(gitignoreKey).filter(Boolean));
|
|
8132
|
+
const added = entries.filter((entry) => !present.has(gitignoreKey(entry)));
|
|
8133
|
+
if (added.length === 0) {
|
|
8134
|
+
return [];
|
|
8135
|
+
}
|
|
8136
|
+
const gap = existing.length > 0 && !existing.endsWith(`
|
|
8137
|
+
`) ? `
|
|
8138
|
+
` : "";
|
|
8139
|
+
await writeFile4(path, `${existing}${gap}${added.join(`
|
|
8140
|
+
`)}
|
|
8141
|
+
`, "utf-8");
|
|
8142
|
+
return added;
|
|
8143
|
+
};
|
|
8144
|
+
var leftoverFiles = (root, candidates) => candidates.filter((candidate) => existsSync9(join16(root, candidate)));
|
|
7724
8145
|
var attribute = (attrs, name) => {
|
|
7725
8146
|
const match = attrs.match(new RegExp(`\\b${name}=(?:"(?<dq>[^"]*)"|'(?<sq>[^']*)')`, "u"));
|
|
7726
8147
|
return match?.groups?.dq ?? match?.groups?.sq;
|
|
@@ -8117,7 +8538,7 @@ var isLiteralObject = (value) => typeof value === "object" && value !== null &&
|
|
|
8117
8538
|
var asLiteralArray = (value) => Array.isArray(value) ? value : undefined;
|
|
8118
8539
|
|
|
8119
8540
|
// src/migrate/mintlify/content.ts
|
|
8120
|
-
import { dirname as
|
|
8541
|
+
import { dirname as dirname9, join as join17, relative as relative10 } from "pathe";
|
|
8121
8542
|
var CALLOUT_DIRECTIVES = {
|
|
8122
8543
|
Check: "success",
|
|
8123
8544
|
Danger: "danger",
|
|
@@ -8153,9 +8574,9 @@ var rewriteSnippetImports = (source, options) => {
|
|
|
8153
8574
|
if (/\.mdx?$/u.test(importSource)) {
|
|
8154
8575
|
return "";
|
|
8155
8576
|
}
|
|
8156
|
-
const target =
|
|
8577
|
+
const target = join17(options.root, importSource.replace(/^\/+/u, ""));
|
|
8157
8578
|
components.push(importSource.replace(/^\/+/u, ""));
|
|
8158
|
-
let rel =
|
|
8579
|
+
let rel = relative10(dirname9(options.filePath), target);
|
|
8159
8580
|
if (!rel.startsWith(".")) {
|
|
8160
8581
|
rel = `./${rel}`;
|
|
8161
8582
|
}
|
|
@@ -8345,8 +8766,7 @@ var rewriteMintlifySvgIconProps = (source) => {
|
|
|
8345
8766
|
|
|
8346
8767
|
// src/migrate/mintlify/snippets.ts
|
|
8347
8768
|
import { readFile as readFileFromDisk } from "node:fs/promises";
|
|
8348
|
-
import
|
|
8349
|
-
import { dirname as dirname9, relative as relative10, resolve as resolve5 } from "pathe";
|
|
8769
|
+
import { dirname as dirname10, relative as relative11, resolve as resolve6 } from "pathe";
|
|
8350
8770
|
var MARKDOWN_SNIPPET_IMPORT = /^import\s+(?<name>[$A-Z_a-z][$\w]*)\s+from\s+["'](?<source>[^"']+\.mdx?)["'];?\s*$/gmu;
|
|
8351
8771
|
var NAMED_SNIPPET_IMPORT = /^import\s+\{(?<names>[^}]+)\}\s+from\s+["'](?<source>[^"']+\.mdx?)["'];?\s*$/gmu;
|
|
8352
8772
|
var EXPORTED_STRING_CONST = /^export\s+const\s+(?<name>[$A-Z_a-z][$\w]*)\s*=\s*(?:"(?<double>(?:\\.|[^"\\])*)"|'(?<single>(?:\\.|[^'\\])*)'|`(?<template>(?:\\.|[^`\\])*)`)\s*;?\s*$/gmu;
|
|
@@ -8356,14 +8776,14 @@ var GLOBAL_VARIABLE = /\{\{\s*(?<name>[A-Za-z0-9-]+)\s*\}\}/gu;
|
|
|
8356
8776
|
var FRONTMATTER_BLOCK = /^---\r?\n[\s\S]*?\r?\n---\r?\n?/u;
|
|
8357
8777
|
var USER_EXPORT = /^(?:export\s+)?(?:const|let|var)\s+user\s*=|^import\s+\{\s*user\s*\}/mu;
|
|
8358
8778
|
var isInsideRoot2 = (root, candidate) => {
|
|
8359
|
-
const rel =
|
|
8779
|
+
const rel = relative11(root, candidate);
|
|
8360
8780
|
return rel === "" || !rel.startsWith("..") && !rel.startsWith("/");
|
|
8361
8781
|
};
|
|
8362
8782
|
var escapeRegExp = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
8363
8783
|
var snippetSelfClosingTagPattern = (name) => new RegExp(`<${escapeRegExp(name)}(?<attrs>[^>]*?)\\s*/>`, "gu");
|
|
8364
8784
|
var snippetPairedTagPattern = (name) => new RegExp(`<${escapeRegExp(name)}(?<attrs>[^>]*?)>[\\s\\S]*?</${escapeRegExp(name)}>`, "gu");
|
|
8365
8785
|
var rootRelativePath = (root, file) => {
|
|
8366
|
-
const rel =
|
|
8786
|
+
const rel = relative11(root, file);
|
|
8367
8787
|
return rel ? `/${rel}` : "/";
|
|
8368
8788
|
};
|
|
8369
8789
|
var snippetCycleMessage = (root, file, trail) => {
|
|
@@ -8372,7 +8792,7 @@ var snippetCycleMessage = (root, file, trail) => {
|
|
|
8372
8792
|
return `Circular Mintlify snippet import detected: ${cycle}`;
|
|
8373
8793
|
};
|
|
8374
8794
|
var resolveSnippetPath = (options) => {
|
|
8375
|
-
const target = options.source.startsWith("/") ?
|
|
8795
|
+
const target = options.source.startsWith("/") ? resolve6(options.root, options.source.slice(1)) : resolve6(dirname10(options.filePath), options.source);
|
|
8376
8796
|
return isInsideRoot2(options.root, target) ? target : null;
|
|
8377
8797
|
};
|
|
8378
8798
|
var collectImports = (source) => [...source.matchAll(MARKDOWN_SNIPPET_IMPORT)].flatMap((match) => {
|
|
@@ -8435,10 +8855,10 @@ var rewriteMintlifyMarkdownSnippets = async (source, options) => {
|
|
|
8435
8855
|
throw new Error(snippetCycleMessage(options.root, file, options.trail ?? []));
|
|
8436
8856
|
}
|
|
8437
8857
|
seen.add(file);
|
|
8438
|
-
const
|
|
8858
|
+
const readFile13 = options.readFile ?? readFileFromDisk;
|
|
8439
8859
|
try {
|
|
8440
|
-
const raw = await
|
|
8441
|
-
const content =
|
|
8860
|
+
const raw = await readFile13(file);
|
|
8861
|
+
const content = frontmatter_default(raw).content.trim();
|
|
8442
8862
|
const transformed = await rewriteMintlifyMarkdownSnippets(content, {
|
|
8443
8863
|
...options,
|
|
8444
8864
|
filePath: file,
|
|
@@ -8478,7 +8898,7 @@ var rewriteMintlifyMarkdownSnippets = async (source, options) => {
|
|
|
8478
8898
|
return await inlineAt(0, source);
|
|
8479
8899
|
};
|
|
8480
8900
|
var rewriteMintlifySnippetVariables = async (source, options) => {
|
|
8481
|
-
const
|
|
8901
|
+
const readFile13 = options.readFile ?? readFileFromDisk;
|
|
8482
8902
|
const inlineImport = async (current, variableImport) => {
|
|
8483
8903
|
const file = resolveSnippetPath({
|
|
8484
8904
|
filePath: options.filePath,
|
|
@@ -8488,7 +8908,7 @@ var rewriteMintlifySnippetVariables = async (source, options) => {
|
|
|
8488
8908
|
if (!file) {
|
|
8489
8909
|
return current;
|
|
8490
8910
|
}
|
|
8491
|
-
const exports = collectStringExports(
|
|
8911
|
+
const exports = collectStringExports(frontmatter_default(await readFile13(file)).content);
|
|
8492
8912
|
let next = current;
|
|
8493
8913
|
for (const name of variableImport.names) {
|
|
8494
8914
|
const value = exports.get(name.imported);
|
|
@@ -8544,10 +8964,10 @@ var transformMintlifyContent = async (raw, options) => {
|
|
|
8544
8964
|
text = rewriteMintlifyExampleBlocks(text);
|
|
8545
8965
|
text = rewriteMintlifyCallouts(text);
|
|
8546
8966
|
const unsupported = unsupportedMintlifyComponents(text);
|
|
8547
|
-
const parsed =
|
|
8967
|
+
const parsed = frontmatter_default(text);
|
|
8548
8968
|
const mapped = normalizeMintlifyPageMeta(parsed.data);
|
|
8549
8969
|
const { data, removed } = stripUnknownPageMeta(mapped);
|
|
8550
|
-
const content = Object.keys(data).length > 0 ?
|
|
8970
|
+
const content = Object.keys(data).length > 0 ? frontmatter_default.stringify(parsed.content, data) : parsed.content;
|
|
8551
8971
|
return {
|
|
8552
8972
|
components: snippetImports.components,
|
|
8553
8973
|
content,
|
|
@@ -8566,15 +8986,15 @@ var MINTLIFY_SOURCE_IGNORES = [
|
|
|
8566
8986
|
"snippets/**"
|
|
8567
8987
|
];
|
|
8568
8988
|
var mintlifySource = (options) => {
|
|
8569
|
-
const contentRoot =
|
|
8989
|
+
const contentRoot = isAbsolute5(options.root) ? options.root : join18(resolve7(options.projectRoot), options.root);
|
|
8570
8990
|
const ignore = [...new Set([...options.exclude, ...MINTLIFY_SOURCE_IGNORES])];
|
|
8571
8991
|
const transform = (raw, file) => transformMintlifyContent(raw, {
|
|
8572
8992
|
filePath: file,
|
|
8573
|
-
root:
|
|
8993
|
+
root: resolve7(options.projectRoot),
|
|
8574
8994
|
variables: options.variables
|
|
8575
8995
|
});
|
|
8576
|
-
const
|
|
8577
|
-
const files = await
|
|
8996
|
+
const load2 = async () => {
|
|
8997
|
+
const files = await glob7(options.include, {
|
|
8578
8998
|
absolute: true,
|
|
8579
8999
|
cwd: contentRoot,
|
|
8580
9000
|
ignore,
|
|
@@ -8583,16 +9003,16 @@ var mintlifySource = (options) => {
|
|
|
8583
9003
|
files.sort();
|
|
8584
9004
|
const unsupported = new Set;
|
|
8585
9005
|
const entries = await Promise.all(files.map(async (file) => {
|
|
8586
|
-
const result = await transform(await
|
|
9006
|
+
const result = await transform(await readFile13(file, "utf-8"), file);
|
|
8587
9007
|
for (const name of result.unsupported) {
|
|
8588
9008
|
unsupported.add(name);
|
|
8589
9009
|
}
|
|
8590
|
-
const parsed =
|
|
9010
|
+
const parsed = frontmatter_default(result.content);
|
|
8591
9011
|
return {
|
|
8592
9012
|
body: { format: "mdx", text: parsed.content },
|
|
8593
9013
|
data: parsed.data,
|
|
8594
9014
|
raw: result.content,
|
|
8595
|
-
ref:
|
|
9015
|
+
ref: relative12(contentRoot, file),
|
|
8596
9016
|
sourcePath: file
|
|
8597
9017
|
};
|
|
8598
9018
|
}));
|
|
@@ -8606,7 +9026,7 @@ var mintlifySource = (options) => {
|
|
|
8606
9026
|
return { diagnostics, entries };
|
|
8607
9027
|
};
|
|
8608
9028
|
const validate = () => {
|
|
8609
|
-
if (!
|
|
9029
|
+
if (!existsSync10(contentRoot)) {
|
|
8610
9030
|
throw new BlumeError({
|
|
8611
9031
|
code: "BLUME_CONTENT_ROOT_MISSING",
|
|
8612
9032
|
file: contentRoot,
|
|
@@ -8618,11 +9038,11 @@ var mintlifySource = (options) => {
|
|
|
8618
9038
|
};
|
|
8619
9039
|
const watch = (onChange) => {
|
|
8620
9040
|
const disposers = [];
|
|
8621
|
-
if (
|
|
9041
|
+
if (existsSync10(contentRoot)) {
|
|
8622
9042
|
const watcher = fsWatch2(contentRoot, { recursive: true }, onChange);
|
|
8623
9043
|
disposers.push(() => watcher.close());
|
|
8624
9044
|
}
|
|
8625
|
-
if (options.configFile &&
|
|
9045
|
+
if (options.configFile && existsSync10(options.configFile)) {
|
|
8626
9046
|
const watcher = fsWatch2(options.configFile, onChange);
|
|
8627
9047
|
disposers.push(() => watcher.close());
|
|
8628
9048
|
}
|
|
@@ -8633,13 +9053,13 @@ var mintlifySource = (options) => {
|
|
|
8633
9053
|
};
|
|
8634
9054
|
};
|
|
8635
9055
|
const read = async (ref) => {
|
|
8636
|
-
const file =
|
|
8637
|
-
const result = await transform(await
|
|
9056
|
+
const file = join18(contentRoot, ref);
|
|
9057
|
+
const result = await transform(await readFile13(file, "utf-8"), file);
|
|
8638
9058
|
return result.content;
|
|
8639
9059
|
};
|
|
8640
9060
|
return {
|
|
8641
9061
|
contentRoot,
|
|
8642
|
-
load,
|
|
9062
|
+
load: load2,
|
|
8643
9063
|
name: options.name,
|
|
8644
9064
|
prefix: options.prefix,
|
|
8645
9065
|
read,
|
|
@@ -8650,12 +9070,11 @@ var mintlifySource = (options) => {
|
|
|
8650
9070
|
};
|
|
8651
9071
|
|
|
8652
9072
|
// src/core/sources/notion.ts
|
|
8653
|
-
import
|
|
8654
|
-
import { join as join18 } from "pathe";
|
|
9073
|
+
import { join as join20 } from "pathe";
|
|
8655
9074
|
|
|
8656
9075
|
// src/core/sources/assets.ts
|
|
8657
9076
|
import { mkdir as mkdir4, writeFile as writeFile5 } from "node:fs/promises";
|
|
8658
|
-
import { extname as extname5, join as
|
|
9077
|
+
import { extname as extname5, join as join19 } from "pathe";
|
|
8659
9078
|
var MD_IMAGE = /!\[(?<alt>[^\]]*)\]\((?<url>[^)\s]+)\)/gu;
|
|
8660
9079
|
var REMOTE = /^https?:\/\//u;
|
|
8661
9080
|
var SAFE_EXT = /^\.[a-z0-9]+$/iu;
|
|
@@ -8684,7 +9103,7 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
8684
9103
|
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
8685
9104
|
const file = `${hashText(url)}${extFor(url)}`;
|
|
8686
9105
|
await mkdir4(ctx.assetsDir, { recursive: true });
|
|
8687
|
-
await writeFile5(
|
|
9106
|
+
await writeFile5(join19(ctx.assetsDir, file), bytes);
|
|
8688
9107
|
rewrites.set(url, `${ctx.assetsBaseUrl}/${file}`);
|
|
8689
9108
|
} catch (error) {
|
|
8690
9109
|
diagnostics.push({
|
|
@@ -8778,8 +9197,8 @@ ${text}
|
|
|
8778
9197
|
};
|
|
8779
9198
|
var notionSource = (options, ctx) => {
|
|
8780
9199
|
const props = options.properties ?? {};
|
|
8781
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
8782
|
-
const assetsDir = ctx?.assetsDir ??
|
|
9200
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join20(".blume", "cache", options.name));
|
|
9201
|
+
const assetsDir = ctx?.assetsDir ?? join20(".blume", "public", "blume-assets", options.name);
|
|
8783
9202
|
const assetsBaseUrl = ctx?.assetsBaseUrl ?? `/blume-assets/${options.name}`;
|
|
8784
9203
|
let snapshot = new Map;
|
|
8785
9204
|
const resolveClient = async () => {
|
|
@@ -8895,7 +9314,7 @@ ${rendered.join(`
|
|
|
8895
9314
|
assetsDir,
|
|
8896
9315
|
fetchImpl: options.fetchImpl
|
|
8897
9316
|
});
|
|
8898
|
-
const raw =
|
|
9317
|
+
const raw = frontmatter_default.stringify(assets.markdown, data);
|
|
8899
9318
|
return {
|
|
8900
9319
|
diagnostics: assets.diagnostics,
|
|
8901
9320
|
entry: {
|
|
@@ -8908,7 +9327,7 @@ ${rendered.join(`
|
|
|
8908
9327
|
}
|
|
8909
9328
|
};
|
|
8910
9329
|
};
|
|
8911
|
-
const
|
|
9330
|
+
const load2 = async () => {
|
|
8912
9331
|
const assetDiagnostics = [];
|
|
8913
9332
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
8914
9333
|
const client = await resolveClient();
|
|
@@ -8937,18 +9356,17 @@ ${rendered.join(`
|
|
|
8937
9356
|
return all.find((e) => e.ref === ref)?.raw ?? "";
|
|
8938
9357
|
};
|
|
8939
9358
|
return {
|
|
8940
|
-
load,
|
|
9359
|
+
load: load2,
|
|
8941
9360
|
name: options.name,
|
|
8942
9361
|
prefix: options.prefix,
|
|
8943
9362
|
read,
|
|
8944
9363
|
staged: true,
|
|
8945
|
-
watch: options.pollInterval ? pollingWatch(
|
|
9364
|
+
watch: options.pollInterval ? pollingWatch(load2, options.pollInterval) : undefined
|
|
8946
9365
|
};
|
|
8947
9366
|
};
|
|
8948
9367
|
|
|
8949
9368
|
// src/core/sources/sanity.ts
|
|
8950
|
-
import
|
|
8951
|
-
import { join as join19 } from "pathe";
|
|
9369
|
+
import { join as join21 } from "pathe";
|
|
8952
9370
|
|
|
8953
9371
|
// src/core/sources/portable-text.ts
|
|
8954
9372
|
var HEADING_STYLES = {
|
|
@@ -9087,7 +9505,7 @@ var resolveClient = async (options, preview) => {
|
|
|
9087
9505
|
};
|
|
9088
9506
|
var sanitySource = (options, ctx) => {
|
|
9089
9507
|
const fields = options.fields ?? {};
|
|
9090
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
9508
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join21(".blume", "cache", options.name));
|
|
9091
9509
|
let snapshot = new Map;
|
|
9092
9510
|
const toEntry = (doc) => {
|
|
9093
9511
|
const slugValue = asString2(getPath(doc, fields.slug ?? "slug.current")) ?? asString2(doc._id) ?? "untitled";
|
|
@@ -9109,7 +9527,7 @@ var sanitySource = (options, ctx) => {
|
|
|
9109
9527
|
},
|
|
9110
9528
|
serializers: options.serializers
|
|
9111
9529
|
}) : "";
|
|
9112
|
-
const raw =
|
|
9530
|
+
const raw = frontmatter_default.stringify(markdown, data);
|
|
9113
9531
|
return {
|
|
9114
9532
|
body: { format: "md", text: markdown },
|
|
9115
9533
|
data,
|
|
@@ -9119,7 +9537,7 @@ var sanitySource = (options, ctx) => {
|
|
|
9119
9537
|
ref: `${slug}.md`
|
|
9120
9538
|
};
|
|
9121
9539
|
};
|
|
9122
|
-
const
|
|
9540
|
+
const load2 = async () => {
|
|
9123
9541
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
9124
9542
|
const client = await resolveClient(options, ctx?.preview ?? false);
|
|
9125
9543
|
const docs = await client.fetch(options.query);
|
|
@@ -9137,12 +9555,12 @@ var sanitySource = (options, ctx) => {
|
|
|
9137
9555
|
return all.find((e) => e.ref === ref)?.raw ?? "";
|
|
9138
9556
|
};
|
|
9139
9557
|
return {
|
|
9140
|
-
load,
|
|
9558
|
+
load: load2,
|
|
9141
9559
|
name: options.name,
|
|
9142
9560
|
prefix: options.prefix,
|
|
9143
9561
|
read,
|
|
9144
9562
|
staged: true,
|
|
9145
|
-
watch: options.pollInterval ? pollingWatch(
|
|
9563
|
+
watch: options.pollInterval ? pollingWatch(load2, options.pollInterval) : undefined
|
|
9146
9564
|
};
|
|
9147
9565
|
};
|
|
9148
9566
|
|
|
@@ -9162,8 +9580,8 @@ var uniqueNamer = () => {
|
|
|
9162
9580
|
};
|
|
9163
9581
|
var sourceContext = (context, name, runtime) => ({
|
|
9164
9582
|
assetsBaseUrl: `/blume-assets/${name}`,
|
|
9165
|
-
assetsDir:
|
|
9166
|
-
cacheDir:
|
|
9583
|
+
assetsDir: join22(context.outDir, "public", "blume-assets", name),
|
|
9584
|
+
cacheDir: join22(context.outDir, "cache", name),
|
|
9167
9585
|
mode: runtime.mode,
|
|
9168
9586
|
preview: runtime.preview,
|
|
9169
9587
|
projectRoot: context.root,
|
|
@@ -9396,7 +9814,7 @@ var buildCommand = defineCommand2({
|
|
|
9396
9814
|
logLevel: "info",
|
|
9397
9815
|
root: project.context.outDir
|
|
9398
9816
|
});
|
|
9399
|
-
const distDir =
|
|
9817
|
+
const distDir = join23(root, "dist");
|
|
9400
9818
|
if (project.config.search.provider === "pagefind") {
|
|
9401
9819
|
logger.start("Building search index");
|
|
9402
9820
|
const indexed = await buildSearchIndex(distDir);
|
|
@@ -9410,19 +9828,19 @@ var buildCommand = defineCommand2({
|
|
|
9410
9828
|
if (project.config.ai.llmsTxt) {
|
|
9411
9829
|
const { index, full } = await buildLlmsFiles(project);
|
|
9412
9830
|
await Promise.all([
|
|
9413
|
-
writeFile6(
|
|
9414
|
-
writeFile6(
|
|
9831
|
+
writeFile6(join23(distDir, "llms.txt"), index, "utf-8"),
|
|
9832
|
+
writeFile6(join23(distDir, "llms-full.txt"), full, "utf-8")
|
|
9415
9833
|
]);
|
|
9416
9834
|
logger.success("Generated llms.txt and llms-full.txt");
|
|
9417
9835
|
}
|
|
9418
9836
|
const sitemap = buildSitemap(project);
|
|
9419
|
-
if (sitemap && !
|
|
9420
|
-
await writeFile6(
|
|
9837
|
+
if (sitemap && !existsSync11(join23(distDir, "sitemap.xml"))) {
|
|
9838
|
+
await writeFile6(join23(distDir, "sitemap.xml"), sitemap, "utf-8");
|
|
9421
9839
|
logger.success("Generated sitemap.xml");
|
|
9422
9840
|
}
|
|
9423
9841
|
const robots = buildRobots(project);
|
|
9424
|
-
if (robots && !
|
|
9425
|
-
await writeFile6(
|
|
9842
|
+
if (robots && !existsSync11(join23(distDir, "robots.txt"))) {
|
|
9843
|
+
await writeFile6(join23(distDir, "robots.txt"), robots, "utf-8");
|
|
9426
9844
|
logger.success("Generated robots.txt");
|
|
9427
9845
|
}
|
|
9428
9846
|
const { config } = project;
|
|
@@ -9590,39 +10008,47 @@ var doctorCommand = defineCommand4({
|
|
|
9590
10008
|
});
|
|
9591
10009
|
|
|
9592
10010
|
// src/cli/commands/eject.ts
|
|
9593
|
-
import { readFile as
|
|
10011
|
+
import { readFile as readFile15, writeFile as writeFile8 } from "node:fs/promises";
|
|
9594
10012
|
import { defineCommand as defineCommand5 } from "citty";
|
|
9595
|
-
import { join as
|
|
10013
|
+
import { join as join25, relative as relative14 } from "pathe";
|
|
9596
10014
|
|
|
9597
10015
|
// src/registry/eject.ts
|
|
9598
|
-
import { existsSync as
|
|
9599
|
-
import { cp, mkdir as mkdir5, readFile as
|
|
9600
|
-
import { join as
|
|
10016
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
10017
|
+
import { cp, mkdir as mkdir5, readFile as readFile14, rm as rm2, writeFile as writeFile7 } from "node:fs/promises";
|
|
10018
|
+
import { join as join24, relative as relative13 } from "pathe";
|
|
9601
10019
|
var POSIX = (path) => path.split("\\").join("/");
|
|
9602
10020
|
var eject = async (root) => {
|
|
9603
10021
|
const project = await scanProject(root, { mode: "build" });
|
|
9604
10022
|
const { context, config } = project;
|
|
9605
|
-
const srcDir =
|
|
9606
|
-
const genDir =
|
|
10023
|
+
const srcDir = join24(root, "src");
|
|
10024
|
+
const genDir = join24(srcDir, "generated");
|
|
9607
10025
|
const askEnabled = config.ai.ask?.enabled ?? false;
|
|
9608
10026
|
const exportPdf = config.export.pdf;
|
|
9609
10027
|
const exportEpub = config.export.epub;
|
|
9610
|
-
const [pages, needsReactRaw, userTheme, rawMarkdown] = await Promise.all([
|
|
10028
|
+
const [pages, needsReactRaw, userTheme, rawMarkdown, islands, examples] = await Promise.all([
|
|
9611
10029
|
context.pagesRoot ? discoverPages(context.pagesRoot) : Promise.resolve([]),
|
|
9612
10030
|
detectNeedsReact(root),
|
|
9613
|
-
context.themeFile ?
|
|
9614
|
-
buildRawMarkdown(project)
|
|
10031
|
+
context.themeFile ? readFile14(context.themeFile, "utf-8") : Promise.resolve(""),
|
|
10032
|
+
buildRawMarkdown(project),
|
|
10033
|
+
discoverIslands(root),
|
|
10034
|
+
discoverExamples(root)
|
|
10035
|
+
]);
|
|
10036
|
+
const frameworks = new Set([
|
|
10037
|
+
...islands.islands.map((island) => island.framework),
|
|
10038
|
+
...examples.examples.map((example) => example.framework)
|
|
9615
10039
|
]);
|
|
9616
|
-
const needsReact = needsReactRaw || askEnabled;
|
|
10040
|
+
const needsReact = needsReactRaw || askEnabled || frameworks.has("react");
|
|
10041
|
+
const needsVue = frameworks.has("vue");
|
|
10042
|
+
const needsSvelte = frameworks.has("svelte");
|
|
9617
10043
|
const relContext = {
|
|
9618
10044
|
...context,
|
|
9619
|
-
contentRoot: POSIX(
|
|
10045
|
+
contentRoot: POSIX(relative13(root, context.contentRoot)),
|
|
9620
10046
|
outDir: ".",
|
|
9621
10047
|
root: "."
|
|
9622
10048
|
};
|
|
9623
|
-
const componentsImport = context.componentsFile ? `../../${POSIX(
|
|
10049
|
+
const componentsImport = context.componentsFile ? `../../${POSIX(relative13(root, context.componentsFile))}` : null;
|
|
9624
10050
|
const relPages = pages.map((page) => ({
|
|
9625
|
-
entrypoint: POSIX(
|
|
10051
|
+
entrypoint: POSIX(relative13(root, page.entrypoint)),
|
|
9626
10052
|
pattern: page.pattern
|
|
9627
10053
|
}));
|
|
9628
10054
|
const staged = collectStaged(project);
|
|
@@ -9635,18 +10061,21 @@ var eject = async (root) => {
|
|
|
9635
10061
|
contentRoutes: project.manifest.routes.map((route) => route.path),
|
|
9636
10062
|
context: relContext,
|
|
9637
10063
|
dataPath: "./src/generated/data.json",
|
|
10064
|
+
examplesPath: "./src/generated/examples.ts",
|
|
9638
10065
|
needsReact,
|
|
10066
|
+
needsSvelte,
|
|
10067
|
+
needsVue,
|
|
9639
10068
|
pages: relPages,
|
|
9640
10069
|
searchClientPath: "./src/generated/search-client.ts",
|
|
9641
10070
|
themePath: "./src/generated/app.css"
|
|
9642
10071
|
}),
|
|
9643
|
-
path:
|
|
10072
|
+
path: join24(root, "astro.config.mjs")
|
|
9644
10073
|
},
|
|
9645
10074
|
{
|
|
9646
10075
|
content: runtimeTsconfigTemplate(),
|
|
9647
|
-
path:
|
|
10076
|
+
path: join24(root, "tsconfig.json")
|
|
9648
10077
|
},
|
|
9649
|
-
{ content: envTemplate(), path:
|
|
10078
|
+
{ content: envTemplate(), path: join24(srcDir, "env.d.ts") },
|
|
9650
10079
|
{
|
|
9651
10080
|
content: contentConfigTemplate({
|
|
9652
10081
|
config,
|
|
@@ -9654,7 +10083,7 @@ var eject = async (root) => {
|
|
|
9654
10083
|
staged: hasStaged,
|
|
9655
10084
|
stagedBase: stagedDir
|
|
9656
10085
|
}),
|
|
9657
|
-
path:
|
|
10086
|
+
path: join24(srcDir, "content.config.ts")
|
|
9658
10087
|
},
|
|
9659
10088
|
{
|
|
9660
10089
|
content: catchAllPageTemplate({
|
|
@@ -9663,11 +10092,19 @@ var eject = async (root) => {
|
|
|
9663
10092
|
exportPdf,
|
|
9664
10093
|
mathEnabled: config.markdown.math
|
|
9665
10094
|
}),
|
|
9666
|
-
path:
|
|
10095
|
+
path: join24(srcDir, "pages", "[...slug].astro")
|
|
9667
10096
|
},
|
|
9668
10097
|
{
|
|
9669
10098
|
content: userComponentsTemplate(componentsImport),
|
|
9670
|
-
path:
|
|
10099
|
+
path: join24(genDir, "components.ts")
|
|
10100
|
+
},
|
|
10101
|
+
{
|
|
10102
|
+
content: islandMapTemplate(islands.islands),
|
|
10103
|
+
path: join24(genDir, "islands.ts")
|
|
10104
|
+
},
|
|
10105
|
+
{
|
|
10106
|
+
content: exampleMapTemplate(examples.examples),
|
|
10107
|
+
path: join24(genDir, "examples.ts")
|
|
9671
10108
|
},
|
|
9672
10109
|
{
|
|
9673
10110
|
content: tailwindEntryTemplate({
|
|
@@ -9679,54 +10116,54 @@ var eject = async (root) => {
|
|
|
9679
10116
|
twoslashCss: twoslashCss(),
|
|
9680
10117
|
userTheme
|
|
9681
10118
|
}),
|
|
9682
|
-
path:
|
|
10119
|
+
path: join24(genDir, "app.css")
|
|
9683
10120
|
},
|
|
9684
|
-
{ content: buildRuntimeData(project), path:
|
|
10121
|
+
{ content: buildRuntimeData(project), path: join24(genDir, "data.json") },
|
|
9685
10122
|
{
|
|
9686
10123
|
content: `${JSON.stringify(rawMarkdown)}
|
|
9687
10124
|
`,
|
|
9688
|
-
path:
|
|
10125
|
+
path: join24(genDir, "raw-markdown.json")
|
|
9689
10126
|
},
|
|
9690
10127
|
{
|
|
9691
10128
|
content: rawMarkdownEndpointTemplate(),
|
|
9692
|
-
path:
|
|
10129
|
+
path: join24(srcDir, "pages", "[...slug].md.ts")
|
|
9693
10130
|
},
|
|
9694
10131
|
{
|
|
9695
10132
|
content: rawMarkdownEndpointTemplate(),
|
|
9696
|
-
path:
|
|
10133
|
+
path: join24(srcDir, "pages", "[...slug].mdx.ts")
|
|
9697
10134
|
}
|
|
9698
10135
|
];
|
|
9699
10136
|
if (askEnabled) {
|
|
9700
10137
|
files.push({
|
|
9701
10138
|
content: askEndpointTemplate(resolveAskBackend(config.ai.ask)),
|
|
9702
|
-
path:
|
|
10139
|
+
path: join24(srcDir, "pages", "api", "ask.ts")
|
|
9703
10140
|
});
|
|
9704
10141
|
}
|
|
9705
10142
|
if (config.seo.og.enabled) {
|
|
9706
10143
|
files.push({
|
|
9707
|
-
content: ogEndpointTemplate(),
|
|
9708
|
-
path:
|
|
10144
|
+
content: ogEndpointTemplate(customOgRoutes(pages, config.title, config.description)),
|
|
10145
|
+
path: join24(srcDir, "pages", "og", "[...slug].png.ts")
|
|
9709
10146
|
});
|
|
9710
10147
|
}
|
|
9711
10148
|
files.push({
|
|
9712
10149
|
content: searchClientTemplate(config),
|
|
9713
|
-
path:
|
|
10150
|
+
path: join24(genDir, "search-client.ts")
|
|
9714
10151
|
});
|
|
9715
10152
|
if (servesStaticIndex(config.search.provider)) {
|
|
9716
10153
|
const documents = await buildSearchDocuments(project);
|
|
9717
10154
|
files.push({
|
|
9718
10155
|
content: `${JSON.stringify(documents)}
|
|
9719
10156
|
`,
|
|
9720
|
-
path:
|
|
10157
|
+
path: join24(genDir, "search.json")
|
|
9721
10158
|
}, {
|
|
9722
10159
|
content: searchEndpointTemplate(),
|
|
9723
|
-
path:
|
|
10160
|
+
path: join24(srcDir, "pages", "blume-search.json.ts")
|
|
9724
10161
|
});
|
|
9725
10162
|
}
|
|
9726
10163
|
if (config.search.provider === "mixedbread") {
|
|
9727
10164
|
files.push({
|
|
9728
10165
|
content: mixedbreadSearchEndpointTemplate(config.search.mixedbread?.storeId ?? ""),
|
|
9729
|
-
path:
|
|
10166
|
+
path: join24(srcDir, "pages", "api", "search.ts")
|
|
9730
10167
|
});
|
|
9731
10168
|
}
|
|
9732
10169
|
const feeds = buildRssFeeds(project);
|
|
@@ -9735,10 +10172,10 @@ var eject = async (root) => {
|
|
|
9735
10172
|
files.push({
|
|
9736
10173
|
content: `${JSON.stringify(feedXml)}
|
|
9737
10174
|
`,
|
|
9738
|
-
path:
|
|
10175
|
+
path: join24(genDir, "rss.json")
|
|
9739
10176
|
}, {
|
|
9740
10177
|
content: rssEndpointTemplate(),
|
|
9741
|
-
path:
|
|
10178
|
+
path: join24(srcDir, "pages", "[section]", "rss.xml.ts")
|
|
9742
10179
|
});
|
|
9743
10180
|
}
|
|
9744
10181
|
if (hasReferences(config)) {
|
|
@@ -9750,20 +10187,27 @@ var eject = async (root) => {
|
|
|
9750
10187
|
for (const file of references.files) {
|
|
9751
10188
|
files.push({
|
|
9752
10189
|
content: file.content,
|
|
9753
|
-
path:
|
|
10190
|
+
path: join24(srcDir, "pages", file.pagePath)
|
|
9754
10191
|
});
|
|
9755
10192
|
}
|
|
9756
10193
|
}
|
|
10194
|
+
files.push(...islands.islands.map((island) => ({
|
|
10195
|
+
content: islandWrapperTemplate(island),
|
|
10196
|
+
path: join24(genDir, "islands", `${island.name}.astro`)
|
|
10197
|
+
})), ...examples.examples.map((example) => ({
|
|
10198
|
+
content: exampleWrapperTemplate(example),
|
|
10199
|
+
path: join24(genDir, "examples", `${exampleSlug(example.path)}.astro`)
|
|
10200
|
+
})));
|
|
9757
10201
|
for (const [entryId, content] of staged) {
|
|
9758
|
-
files.push({ content, path:
|
|
10202
|
+
files.push({ content, path: join24(root, stagedDir, entryId) });
|
|
9759
10203
|
}
|
|
9760
10204
|
await Promise.all(files.map(async (file) => {
|
|
9761
|
-
await mkdir5(
|
|
10205
|
+
await mkdir5(join24(file.path, ".."), { recursive: true });
|
|
9762
10206
|
await writeFile7(file.path, file.content, "utf-8");
|
|
9763
10207
|
}));
|
|
9764
|
-
const assetsSrc =
|
|
9765
|
-
if (
|
|
9766
|
-
await cp(assetsSrc,
|
|
10208
|
+
const assetsSrc = join24(context.outDir, "public", "blume-assets");
|
|
10209
|
+
if (existsSync12(assetsSrc)) {
|
|
10210
|
+
await cp(assetsSrc, join24(root, "public", "blume-assets"), {
|
|
9767
10211
|
recursive: true
|
|
9768
10212
|
});
|
|
9769
10213
|
}
|
|
@@ -9773,10 +10217,10 @@ var eject = async (root) => {
|
|
|
9773
10217
|
|
|
9774
10218
|
// src/cli/commands/eject.ts
|
|
9775
10219
|
var updatePackageScripts = async (root) => {
|
|
9776
|
-
const pkgPath =
|
|
10220
|
+
const pkgPath = join25(root, "package.json");
|
|
9777
10221
|
let pkg;
|
|
9778
10222
|
try {
|
|
9779
|
-
pkg = JSON.parse(await
|
|
10223
|
+
pkg = JSON.parse(await readFile15(pkgPath, "utf-8"));
|
|
9780
10224
|
} catch {
|
|
9781
10225
|
return;
|
|
9782
10226
|
}
|
|
@@ -9809,7 +10253,7 @@ var ejectCommand = defineCommand5({
|
|
|
9809
10253
|
await updatePackageScripts(root);
|
|
9810
10254
|
logger.success(`Ejected ${files.length} file(s):`);
|
|
9811
10255
|
for (const file of files) {
|
|
9812
|
-
process.stdout.write(` ${
|
|
10256
|
+
process.stdout.write(` ${relative14(root, file)}
|
|
9813
10257
|
`);
|
|
9814
10258
|
}
|
|
9815
10259
|
logger.box(`Your project is now a standalone Astro app.
|
|
@@ -9822,10 +10266,10 @@ The blume package remains importable.`);
|
|
|
9822
10266
|
});
|
|
9823
10267
|
|
|
9824
10268
|
// src/cli/commands/init.ts
|
|
9825
|
-
import { existsSync as
|
|
10269
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
9826
10270
|
import { mkdir as mkdir6, writeFile as writeFile9 } from "node:fs/promises";
|
|
9827
10271
|
import { defineCommand as defineCommand6 } from "citty";
|
|
9828
|
-
import { basename as basename3, dirname as
|
|
10272
|
+
import { basename as basename3, dirname as dirname11, join as join26 } from "pathe";
|
|
9829
10273
|
var toPackageName = (raw) => raw.toLowerCase().replaceAll(/[^a-z0-9._-]+/gu, "-").replaceAll(/^[-_.]+|[-_.]+$/gu, "") || "docs";
|
|
9830
10274
|
var packageTemplate = (name, version) => `{
|
|
9831
10275
|
"name": ${JSON.stringify(name)},
|
|
@@ -9860,11 +10304,11 @@ Welcome to **Blume** — markdown-first docs powered by Astro and Vite.
|
|
|
9860
10304
|
Edit \`docs/index.mdx\` to get started, then run \`blume dev\`.
|
|
9861
10305
|
`;
|
|
9862
10306
|
var writeFileSafe = async (path, content) => {
|
|
9863
|
-
if (
|
|
10307
|
+
if (existsSync13(path)) {
|
|
9864
10308
|
logger.info(`Skipped existing ${path}`);
|
|
9865
10309
|
return false;
|
|
9866
10310
|
}
|
|
9867
|
-
await mkdir6(
|
|
10311
|
+
await mkdir6(dirname11(path), { recursive: true });
|
|
9868
10312
|
await writeFile9(path, content, "utf-8");
|
|
9869
10313
|
logger.success(`Created ${path}`);
|
|
9870
10314
|
return true;
|
|
@@ -9885,9 +10329,9 @@ var initCommand = defineCommand6({
|
|
|
9885
10329
|
async run({ args }) {
|
|
9886
10330
|
const root = process.cwd();
|
|
9887
10331
|
const contentDir = args["content-dir"] ?? "docs";
|
|
9888
|
-
const createdPackage = await writeFileSafe(
|
|
9889
|
-
await writeFileSafe(
|
|
9890
|
-
await writeFileSafe(
|
|
10332
|
+
const createdPackage = await writeFileSafe(join26(root, "package.json"), packageTemplate(toPackageName(basename3(root)), getBlumeVersion()));
|
|
10333
|
+
await writeFileSafe(join26(root, "blume.config.ts"), CONFIG_TEMPLATE);
|
|
10334
|
+
await writeFileSafe(join26(root, contentDir, "index.mdx"), INDEX_TEMPLATE);
|
|
9891
10335
|
const nextSteps = createdPackage ? `Next steps:
|
|
9892
10336
|
|
|
9893
10337
|
npm install
|
|
@@ -9904,16 +10348,15 @@ var initCommand = defineCommand6({
|
|
|
9904
10348
|
import { defineCommand as defineCommand7 } from "citty";
|
|
9905
10349
|
|
|
9906
10350
|
// src/migrate/fumadocs/index.ts
|
|
9907
|
-
import { existsSync as
|
|
9908
|
-
import { mkdir as
|
|
9909
|
-
import
|
|
9910
|
-
import {
|
|
9911
|
-
import { glob as glob7 } from "tinyglobby";
|
|
10351
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
10352
|
+
import { mkdir as mkdir8, readFile as readFile17, rename as rename3, rm as rm3, writeFile as writeFile11 } from "node:fs/promises";
|
|
10353
|
+
import { dirname as dirname14, join as join29, relative as relative15 } from "pathe";
|
|
10354
|
+
import { glob as glob8 } from "tinyglobby";
|
|
9912
10355
|
|
|
9913
10356
|
// src/migrate/fumadocs/config.ts
|
|
9914
|
-
import { existsSync as
|
|
9915
|
-
import { readFile as
|
|
9916
|
-
import { join as
|
|
10357
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
10358
|
+
import { readFile as readFile16 } from "node:fs/promises";
|
|
10359
|
+
import { basename as basename4, dirname as dirname12, join as join27 } from "pathe";
|
|
9917
10360
|
var SOURCE_FILES = [
|
|
9918
10361
|
"lib/source.ts",
|
|
9919
10362
|
"app/source.ts",
|
|
@@ -9930,25 +10373,62 @@ var prettifyTitle = (name) => {
|
|
|
9930
10373
|
}
|
|
9931
10374
|
return words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
9932
10375
|
};
|
|
10376
|
+
var GENERIC_NAMES = new Set([
|
|
10377
|
+
"api",
|
|
10378
|
+
"app",
|
|
10379
|
+
"client",
|
|
10380
|
+
"frontend",
|
|
10381
|
+
"server",
|
|
10382
|
+
"site",
|
|
10383
|
+
"web",
|
|
10384
|
+
"www"
|
|
10385
|
+
]);
|
|
10386
|
+
var gitRepoRoot = (start) => {
|
|
10387
|
+
let dir = start;
|
|
10388
|
+
for (;; ) {
|
|
10389
|
+
if (existsSync14(join27(dir, ".git"))) {
|
|
10390
|
+
return dir;
|
|
10391
|
+
}
|
|
10392
|
+
const parent = dirname12(dir);
|
|
10393
|
+
if (parent === dir) {
|
|
10394
|
+
return null;
|
|
10395
|
+
}
|
|
10396
|
+
dir = parent;
|
|
10397
|
+
}
|
|
10398
|
+
};
|
|
10399
|
+
var bareName = (name) => name.includes("/") ? name.slice(name.lastIndexOf("/") + 1) : name;
|
|
9933
10400
|
var readTitle = async (root) => {
|
|
9934
|
-
const packageJson =
|
|
9935
|
-
if (!
|
|
10401
|
+
const packageJson = join27(root, "package.json");
|
|
10402
|
+
if (!existsSync14(packageJson)) {
|
|
9936
10403
|
return "Documentation";
|
|
9937
10404
|
}
|
|
9938
10405
|
try {
|
|
9939
|
-
const parsed = JSON.parse(await
|
|
9940
|
-
|
|
10406
|
+
const parsed = JSON.parse(await readFile16(packageJson, "utf-8"));
|
|
10407
|
+
const { name } = parsed;
|
|
10408
|
+
if (typeof name !== "string" || !name.trim()) {
|
|
10409
|
+
return "Documentation";
|
|
10410
|
+
}
|
|
10411
|
+
if (GENERIC_NAMES.has(bareName(name).toLowerCase())) {
|
|
10412
|
+
const repoRoot = gitRepoRoot(root);
|
|
10413
|
+
if (repoRoot && repoRoot !== root) {
|
|
10414
|
+
const repoTitle = prettifyTitle(basename4(repoRoot));
|
|
10415
|
+
if (repoTitle !== "Documentation") {
|
|
10416
|
+
return repoTitle;
|
|
10417
|
+
}
|
|
10418
|
+
}
|
|
10419
|
+
}
|
|
10420
|
+
return prettifyTitle(name);
|
|
9941
10421
|
} catch {
|
|
9942
10422
|
return "Documentation";
|
|
9943
10423
|
}
|
|
9944
10424
|
};
|
|
9945
10425
|
var scrapeBaseUrl = async (root) => {
|
|
9946
10426
|
for (const candidate of SOURCE_FILES) {
|
|
9947
|
-
const file =
|
|
9948
|
-
if (!
|
|
10427
|
+
const file = join27(root, candidate);
|
|
10428
|
+
if (!existsSync14(file)) {
|
|
9949
10429
|
continue;
|
|
9950
10430
|
}
|
|
9951
|
-
const base = BASE_URL.exec(await
|
|
10431
|
+
const base = BASE_URL.exec(await readFile16(file, "utf-8"))?.groups?.base;
|
|
9952
10432
|
if (base) {
|
|
9953
10433
|
return base;
|
|
9954
10434
|
}
|
|
@@ -9977,10 +10457,9 @@ var loadFumadocsConfig = async (root) => {
|
|
|
9977
10457
|
};
|
|
9978
10458
|
|
|
9979
10459
|
// src/migrate/fumadocs/content.ts
|
|
9980
|
-
import { existsSync as
|
|
10460
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
9981
10461
|
import { readFile as readFileFromDisk2 } from "node:fs/promises";
|
|
9982
|
-
import
|
|
9983
|
-
import { dirname as dirname11, resolve as resolve7 } from "pathe";
|
|
10462
|
+
import { dirname as dirname13, resolve as resolve8 } from "pathe";
|
|
9984
10463
|
var FUMADOCS_IMPORT = /^import\s+[\s\S]*?\s+from\s+["']fumadocs-(?:ui|core|mdx)(?:\/[^"']*)?["'];?[ \t]*\n?/gmu;
|
|
9985
10464
|
var stripFumadocsImports = (source) => {
|
|
9986
10465
|
const stripped = source.replace(FUMADOCS_IMPORT, "");
|
|
@@ -10181,18 +10660,18 @@ var inlineFumadocsIncludes = async (source, options) => {
|
|
|
10181
10660
|
if (!rawPath) {
|
|
10182
10661
|
continue;
|
|
10183
10662
|
}
|
|
10184
|
-
const target =
|
|
10663
|
+
const target = resolve8(dirname13(options.filePath), rawPath);
|
|
10185
10664
|
if (seen.has(target)) {
|
|
10186
10665
|
warnings.push(`Circular <include> "${rawPath}" — left as-is.`);
|
|
10187
10666
|
continue;
|
|
10188
10667
|
}
|
|
10189
|
-
if (!
|
|
10668
|
+
if (!existsSync15(target)) {
|
|
10190
10669
|
warnings.push(`<include> target "${rawPath}" not found — left as-is.`);
|
|
10191
10670
|
continue;
|
|
10192
10671
|
}
|
|
10193
10672
|
seen.add(target);
|
|
10194
10673
|
const raw = await read(target);
|
|
10195
|
-
const nested = await inlineFumadocsIncludes(
|
|
10674
|
+
const nested = await inlineFumadocsIncludes(frontmatter_default(raw).content.trim(), {
|
|
10196
10675
|
...options,
|
|
10197
10676
|
filePath: target,
|
|
10198
10677
|
seen
|
|
@@ -10217,10 +10696,16 @@ var normalizeFumadocsPageMeta = (value) => {
|
|
|
10217
10696
|
return stripUnknownPageMeta(data);
|
|
10218
10697
|
};
|
|
10219
10698
|
|
|
10699
|
+
// src/migrate/fumadocs/groups.ts
|
|
10700
|
+
import { existsSync as existsSync16, statSync as statSync2 } from "node:fs";
|
|
10701
|
+
import { mkdir as mkdir7, rename as rename2, writeFile as writeFile10 } from "node:fs/promises";
|
|
10702
|
+
import { basename as basename5, join as join28 } from "pathe";
|
|
10703
|
+
|
|
10220
10704
|
// src/migrate/fumadocs/meta.ts
|
|
10221
10705
|
var SEPARATOR = /^---(?<label>.*)---$/u;
|
|
10222
10706
|
var LINK2 = /^(?:\[[^\]]*\])?\[(?<text>[^\]]*)\]\((?<href>[^)]*)\)$/u;
|
|
10223
10707
|
var REST = "...";
|
|
10708
|
+
var EXTRACT = /^\.\.\.(?<folder>.+)$/u;
|
|
10224
10709
|
var filterPages = (raw) => {
|
|
10225
10710
|
if (!Array.isArray(raw)) {
|
|
10226
10711
|
return { pages: [], warnings: [] };
|
|
@@ -10235,6 +10720,15 @@ var filterPages = (raw) => {
|
|
|
10235
10720
|
if (value === REST || value === "") {
|
|
10236
10721
|
continue;
|
|
10237
10722
|
}
|
|
10723
|
+
const extract = EXTRACT.exec(value);
|
|
10724
|
+
if (extract) {
|
|
10725
|
+
const folder = extract.groups?.folder?.trim() ?? "";
|
|
10726
|
+
if (folder) {
|
|
10727
|
+
pages.push(folder);
|
|
10728
|
+
warnings.push(`Sidebar extract "...${folder}" became a normal "${folder}" group (its pages are not flattened into the parent).`);
|
|
10729
|
+
}
|
|
10730
|
+
continue;
|
|
10731
|
+
}
|
|
10238
10732
|
const separator = SEPARATOR.exec(value);
|
|
10239
10733
|
if (separator) {
|
|
10240
10734
|
const label = separator.groups?.label?.trim();
|
|
@@ -10250,7 +10744,11 @@ var filterPages = (raw) => {
|
|
|
10250
10744
|
}
|
|
10251
10745
|
return { pages, warnings };
|
|
10252
10746
|
};
|
|
10253
|
-
var
|
|
10747
|
+
var renderMetaModule = (meta) => `import { defineMeta } from "blume";
|
|
10748
|
+
|
|
10749
|
+
export default defineMeta(${JSON.stringify(meta, null, 2)});
|
|
10750
|
+
`;
|
|
10751
|
+
var translateFumadocsSelfMeta = (value) => {
|
|
10254
10752
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
10255
10753
|
return { meta: {}, warnings: [] };
|
|
10256
10754
|
}
|
|
@@ -10272,23 +10770,197 @@ var translateFumadocsMeta = (value) => {
|
|
|
10272
10770
|
if (typeof source.description === "string") {
|
|
10273
10771
|
warnings.push("Dropped folder `description` — Blume folders have no description field.");
|
|
10274
10772
|
}
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10773
|
+
return { meta, warnings };
|
|
10774
|
+
};
|
|
10775
|
+
var translateFumadocsMeta = (value) => {
|
|
10776
|
+
const { meta, warnings } = translateFumadocsSelfMeta(value);
|
|
10777
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
10778
|
+
const { pages, warnings: pageWarnings } = filterPages(value.pages);
|
|
10779
|
+
if (pages.length > 0) {
|
|
10780
|
+
meta.pages = pages;
|
|
10781
|
+
}
|
|
10782
|
+
warnings.push(...pageWarnings);
|
|
10278
10783
|
}
|
|
10279
|
-
warnings.push(...pageWarnings);
|
|
10280
10784
|
return { meta, warnings };
|
|
10281
10785
|
};
|
|
10786
|
+
var parseFumadocsPages = (raw) => {
|
|
10787
|
+
const lead = [];
|
|
10788
|
+
const sections = [];
|
|
10789
|
+
if (!Array.isArray(raw)) {
|
|
10790
|
+
return { hasSections: false, lead, sections };
|
|
10791
|
+
}
|
|
10792
|
+
let current = null;
|
|
10793
|
+
const push = (item) => {
|
|
10794
|
+
(current ? current.items : lead).push(item);
|
|
10795
|
+
};
|
|
10796
|
+
for (const entry of raw) {
|
|
10797
|
+
if (typeof entry !== "string") {
|
|
10798
|
+
continue;
|
|
10799
|
+
}
|
|
10800
|
+
const value = entry.trim();
|
|
10801
|
+
if (value === REST || value === "") {
|
|
10802
|
+
continue;
|
|
10803
|
+
}
|
|
10804
|
+
const separator = SEPARATOR.exec(value);
|
|
10805
|
+
if (separator) {
|
|
10806
|
+
current = {
|
|
10807
|
+
items: [],
|
|
10808
|
+
label: separator.groups?.label?.trim() || "Section"
|
|
10809
|
+
};
|
|
10810
|
+
sections.push(current);
|
|
10811
|
+
continue;
|
|
10812
|
+
}
|
|
10813
|
+
const extract = EXTRACT.exec(value);
|
|
10814
|
+
if (extract) {
|
|
10815
|
+
const name = extract.groups?.folder?.trim();
|
|
10816
|
+
if (name) {
|
|
10817
|
+
push({ kind: "extract", name });
|
|
10818
|
+
}
|
|
10819
|
+
continue;
|
|
10820
|
+
}
|
|
10821
|
+
const link = LINK2.exec(value);
|
|
10822
|
+
if (link) {
|
|
10823
|
+
push({
|
|
10824
|
+
href: link.groups?.href ?? "",
|
|
10825
|
+
kind: "link",
|
|
10826
|
+
text: link.groups?.text ?? ""
|
|
10827
|
+
});
|
|
10828
|
+
continue;
|
|
10829
|
+
}
|
|
10830
|
+
push({ kind: "ref", name: value });
|
|
10831
|
+
}
|
|
10832
|
+
return { hasSections: sections.length > 0, lead, sections };
|
|
10833
|
+
};
|
|
10834
|
+
|
|
10835
|
+
// src/migrate/fumadocs/groups.ts
|
|
10836
|
+
var PAGE_EXTS = [".mdx", ".md"];
|
|
10837
|
+
var WORD_SPLIT3 = /[-_]/u;
|
|
10838
|
+
var PATH_SEP = /[/\\]/u;
|
|
10839
|
+
var isDirectory = (path) => {
|
|
10840
|
+
try {
|
|
10841
|
+
return statSync2(path).isDirectory();
|
|
10842
|
+
} catch {
|
|
10843
|
+
return false;
|
|
10844
|
+
}
|
|
10845
|
+
};
|
|
10846
|
+
var resolveEntry = (docsDir, name) => {
|
|
10847
|
+
for (const ext of PAGE_EXTS) {
|
|
10848
|
+
const file = join28(docsDir, `${name}${ext}`);
|
|
10849
|
+
if (existsSync16(file)) {
|
|
10850
|
+
return { kind: "file", path: file };
|
|
10851
|
+
}
|
|
10852
|
+
}
|
|
10853
|
+
const folder = join28(docsDir, name);
|
|
10854
|
+
return isDirectory(folder) ? { kind: "folder", path: folder } : null;
|
|
10855
|
+
};
|
|
10856
|
+
var humanize2 = (name) => name.split(WORD_SPLIT3).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
10857
|
+
var linkWarning = (item) => `Dropped sidebar link "${item.text}" (${item.href}) — add it to navbar.links manually.`;
|
|
10858
|
+
var extractWarning = (name) => `Sidebar extract "...${name}" became a normal "${name}" group (its pages are not flattened into the parent).`;
|
|
10859
|
+
var addUngroupedItem = (item, order, warnings) => {
|
|
10860
|
+
if (item.kind === "link") {
|
|
10861
|
+
warnings.push(linkWarning(item));
|
|
10862
|
+
return;
|
|
10863
|
+
}
|
|
10864
|
+
if (item.kind === "extract") {
|
|
10865
|
+
warnings.push(extractWarning(item.name));
|
|
10866
|
+
}
|
|
10867
|
+
order.push(item.name);
|
|
10868
|
+
};
|
|
10869
|
+
var reshapeSingleFolderSection = (section, only, order, warnings) => {
|
|
10870
|
+
order.push(only.name);
|
|
10871
|
+
if (humanize2(only.name).toLowerCase() !== section.label.toLowerCase()) {
|
|
10872
|
+
warnings.push(`Section "${section.label}" wraps folder "${only.name}"; set that folder's meta title to "${section.label}" to make the heading match.`);
|
|
10873
|
+
}
|
|
10874
|
+
if (only.kind === "extract") {
|
|
10875
|
+
warnings.push(extractWarning(only.name));
|
|
10876
|
+
}
|
|
10877
|
+
};
|
|
10878
|
+
var moveItemIntoGroup = async (item, docsDir, groupDir, label, warnings) => {
|
|
10879
|
+
if (item.kind === "link") {
|
|
10880
|
+
warnings.push(linkWarning(item));
|
|
10881
|
+
return null;
|
|
10882
|
+
}
|
|
10883
|
+
const resolved = resolveEntry(docsDir, item.name);
|
|
10884
|
+
if (!resolved) {
|
|
10885
|
+
warnings.push(`Sidebar entry "${item.name}" in section "${label}" matched no page or folder; skipped.`);
|
|
10886
|
+
return null;
|
|
10887
|
+
}
|
|
10888
|
+
const dest = join28(groupDir, basename5(resolved.path));
|
|
10889
|
+
if (existsSync16(dest)) {
|
|
10890
|
+
warnings.push(`Skipped moving "${item.name}" into section "${label}" (target already exists).`);
|
|
10891
|
+
return null;
|
|
10892
|
+
}
|
|
10893
|
+
await mkdir7(groupDir, { recursive: true });
|
|
10894
|
+
await rename2(resolved.path, dest);
|
|
10895
|
+
if (item.kind === "extract") {
|
|
10896
|
+
warnings.push(extractWarning(item.name));
|
|
10897
|
+
}
|
|
10898
|
+
return item.name;
|
|
10899
|
+
};
|
|
10900
|
+
var reshapeSection = async (section, docsDir, order, warnings) => {
|
|
10901
|
+
const movable = section.items.filter((item) => item.kind !== "link");
|
|
10902
|
+
if (movable.length === 1) {
|
|
10903
|
+
const [only] = movable;
|
|
10904
|
+
if (resolveEntry(docsDir, only.name)?.kind === "folder") {
|
|
10905
|
+
reshapeSingleFolderSection(section, only, order, warnings);
|
|
10906
|
+
return;
|
|
10907
|
+
}
|
|
10908
|
+
}
|
|
10909
|
+
if (PATH_SEP.test(section.label)) {
|
|
10910
|
+
warnings.push(`Section "${section.label}" has a slash in its name and can't become a group folder; its pages stay ungrouped.`);
|
|
10911
|
+
for (const item of section.items) {
|
|
10912
|
+
addUngroupedItem(item, order, warnings);
|
|
10913
|
+
}
|
|
10914
|
+
return;
|
|
10915
|
+
}
|
|
10916
|
+
const groupDir = join28(docsDir, `(${section.label})`);
|
|
10917
|
+
const sectionKeys = [];
|
|
10918
|
+
for (const item of section.items) {
|
|
10919
|
+
const key = await moveItemIntoGroup(item, docsDir, groupDir, section.label, warnings);
|
|
10920
|
+
if (key) {
|
|
10921
|
+
sectionKeys.push(key);
|
|
10922
|
+
}
|
|
10923
|
+
}
|
|
10924
|
+
if (sectionKeys.length === 0) {
|
|
10925
|
+
return;
|
|
10926
|
+
}
|
|
10927
|
+
order.push(section.label);
|
|
10928
|
+
if (sectionKeys.length > 1) {
|
|
10929
|
+
await writeFile10(join28(groupDir, "meta.ts"), renderMetaModule({ pages: sectionKeys }), "utf-8");
|
|
10930
|
+
}
|
|
10931
|
+
};
|
|
10932
|
+
var reshapeFumadocsGroups = async (structure, docsDir) => {
|
|
10933
|
+
const order = [];
|
|
10934
|
+
const warnings = [];
|
|
10935
|
+
for (const item of structure.lead) {
|
|
10936
|
+
addUngroupedItem(item, order, warnings);
|
|
10937
|
+
}
|
|
10938
|
+
for (const section of structure.sections) {
|
|
10939
|
+
await reshapeSection(section, docsDir, order, warnings);
|
|
10940
|
+
}
|
|
10941
|
+
return { order, warnings };
|
|
10942
|
+
};
|
|
10282
10943
|
|
|
10283
10944
|
// src/migrate/fumadocs/index.ts
|
|
10284
10945
|
var SOURCE_DIR = "content/docs";
|
|
10285
10946
|
var PAGE_GLOB = "**/*.{md,mdx}";
|
|
10286
10947
|
var META_GLOB = "**/meta.json";
|
|
10287
10948
|
var IGNORE = ["**/node_modules/**"];
|
|
10949
|
+
var FUMADOCS_LEFTOVERS = [
|
|
10950
|
+
"next.config.ts",
|
|
10951
|
+
"next.config.mjs",
|
|
10952
|
+
"next.config.js",
|
|
10953
|
+
"source.config.ts",
|
|
10954
|
+
"source.config.mjs",
|
|
10955
|
+
"source.config.js",
|
|
10956
|
+
"mdx-components.tsx",
|
|
10957
|
+
"next-env.d.ts",
|
|
10958
|
+
"app"
|
|
10959
|
+
];
|
|
10288
10960
|
var movePage = async (abs, base, root) => {
|
|
10289
|
-
const rel =
|
|
10290
|
-
const dest =
|
|
10291
|
-
if (
|
|
10961
|
+
const rel = relative15(base, abs);
|
|
10962
|
+
const dest = join29(root, "docs", rel);
|
|
10963
|
+
if (existsSync17(dest)) {
|
|
10292
10964
|
return {
|
|
10293
10965
|
includeWarnings: [],
|
|
10294
10966
|
moved: 0,
|
|
@@ -10297,18 +10969,18 @@ var movePage = async (abs, base, root) => {
|
|
|
10297
10969
|
unsupported: []
|
|
10298
10970
|
};
|
|
10299
10971
|
}
|
|
10300
|
-
const raw = await
|
|
10972
|
+
const raw = await readFile17(abs, "utf-8");
|
|
10301
10973
|
const included = await inlineFumadocsIncludes(raw, { filePath: abs });
|
|
10302
10974
|
let text = stripFumadocsImports(included.content);
|
|
10303
10975
|
text = rewriteFumadocsCallouts(text);
|
|
10304
10976
|
text = rewriteFumadocsContainers(text);
|
|
10305
10977
|
text = rewriteFumadocsTabs(text);
|
|
10306
10978
|
const unsupported = unsupportedFumadocsComponents(text);
|
|
10307
|
-
const parsed =
|
|
10979
|
+
const parsed = frontmatter_default(text);
|
|
10308
10980
|
const { data, removed } = normalizeFumadocsPageMeta(parsed.data);
|
|
10309
|
-
const content = Object.keys(data).length > 0 ?
|
|
10310
|
-
await
|
|
10311
|
-
await
|
|
10981
|
+
const content = Object.keys(data).length > 0 ? frontmatter_default.stringify(parsed.content, data) : parsed.content;
|
|
10982
|
+
await mkdir8(dirname14(dest), { recursive: true });
|
|
10983
|
+
await writeFile11(dest, content, "utf-8");
|
|
10312
10984
|
await rm3(abs, { force: true });
|
|
10313
10985
|
return {
|
|
10314
10986
|
includeWarnings: included.warnings,
|
|
@@ -10318,39 +10990,56 @@ var movePage = async (abs, base, root) => {
|
|
|
10318
10990
|
unsupported
|
|
10319
10991
|
};
|
|
10320
10992
|
};
|
|
10993
|
+
var writeMeta = async (dest, meta, rel, warnings) => {
|
|
10994
|
+
if (Object.keys(meta).length === 0) {
|
|
10995
|
+
return warnings;
|
|
10996
|
+
}
|
|
10997
|
+
if (existsSync17(dest)) {
|
|
10998
|
+
return [...warnings, `Skipped ${rel} (target already exists)`];
|
|
10999
|
+
}
|
|
11000
|
+
await mkdir8(dirname14(dest), { recursive: true });
|
|
11001
|
+
await writeFile11(dest, renderMetaModule(meta), "utf-8");
|
|
11002
|
+
return warnings;
|
|
11003
|
+
};
|
|
10321
11004
|
var convertMeta = async (abs, base, root) => {
|
|
10322
|
-
const rel =
|
|
10323
|
-
const raw = await
|
|
11005
|
+
const rel = relative15(base, abs);
|
|
11006
|
+
const raw = await readFile17(abs, "utf-8");
|
|
10324
11007
|
let parsed;
|
|
10325
11008
|
try {
|
|
10326
11009
|
parsed = JSON.parse(raw);
|
|
10327
11010
|
} catch {
|
|
10328
|
-
const
|
|
10329
|
-
if (
|
|
11011
|
+
const dest2 = join29(root, "docs", rel);
|
|
11012
|
+
if (existsSync17(dest2)) {
|
|
10330
11013
|
return [`Skipped ${rel} (target already exists)`];
|
|
10331
11014
|
}
|
|
10332
|
-
await
|
|
10333
|
-
await
|
|
11015
|
+
await mkdir8(dirname14(dest2), { recursive: true });
|
|
11016
|
+
await rename3(abs, dest2);
|
|
10334
11017
|
return [
|
|
10335
11018
|
`Could not parse ${rel}; moved as-is — convert it to meta.ts by hand.`
|
|
10336
11019
|
];
|
|
10337
11020
|
}
|
|
10338
|
-
const
|
|
10339
|
-
const
|
|
10340
|
-
|
|
10341
|
-
|
|
10342
|
-
|
|
10343
|
-
|
|
10344
|
-
|
|
10345
|
-
}
|
|
10346
|
-
|
|
10347
|
-
|
|
10348
|
-
|
|
10349
|
-
|
|
10350
|
-
|
|
11021
|
+
const dir = dirname14(rel) === "." ? "" : dirname14(rel);
|
|
11022
|
+
const docsDir = join29(root, "docs", dir);
|
|
11023
|
+
const dest = join29(docsDir, "meta.ts");
|
|
11024
|
+
const structure = parseFumadocsPages(parsed.pages);
|
|
11025
|
+
if (structure.hasSections && !existsSync17(dest)) {
|
|
11026
|
+
const self = translateFumadocsSelfMeta(parsed);
|
|
11027
|
+
const reshape = await reshapeFumadocsGroups(structure, docsDir);
|
|
11028
|
+
const meta2 = { ...self.meta };
|
|
11029
|
+
if (reshape.order.length > 0) {
|
|
11030
|
+
meta2.pages = reshape.order;
|
|
11031
|
+
}
|
|
11032
|
+
const result2 = await writeMeta(dest, meta2, rel, [
|
|
11033
|
+
...self.warnings,
|
|
11034
|
+
...reshape.warnings
|
|
11035
|
+
]);
|
|
11036
|
+
await rm3(abs, { force: true });
|
|
11037
|
+
return result2;
|
|
10351
11038
|
}
|
|
11039
|
+
const { meta, warnings } = translateFumadocsMeta(parsed);
|
|
11040
|
+
const result = await writeMeta(dest, meta, rel, warnings);
|
|
10352
11041
|
await rm3(abs, { force: true });
|
|
10353
|
-
return
|
|
11042
|
+
return result;
|
|
10354
11043
|
};
|
|
10355
11044
|
var summarizePages = (results) => {
|
|
10356
11045
|
let moved = 0;
|
|
@@ -10380,9 +11069,9 @@ var summarizePages = (results) => {
|
|
|
10380
11069
|
};
|
|
10381
11070
|
};
|
|
10382
11071
|
var cleanupSourceDirs = async (root) => {
|
|
10383
|
-
const docs =
|
|
10384
|
-
if (
|
|
10385
|
-
const remaining = await
|
|
11072
|
+
const docs = join29(root, "content", "docs");
|
|
11073
|
+
if (existsSync17(docs)) {
|
|
11074
|
+
const remaining = await glob8(["**/*"], { cwd: docs, dot: true });
|
|
10386
11075
|
if (remaining.length > 0) {
|
|
10387
11076
|
return [
|
|
10388
11077
|
`Kept ${remaining.length} non-page file(s) under content/docs; move them into docs/ manually.`
|
|
@@ -10390,9 +11079,9 @@ var cleanupSourceDirs = async (root) => {
|
|
|
10390
11079
|
}
|
|
10391
11080
|
await rm3(docs, { force: true, recursive: true });
|
|
10392
11081
|
}
|
|
10393
|
-
const content =
|
|
10394
|
-
if (
|
|
10395
|
-
const remaining = await
|
|
11082
|
+
const content = join29(root, "content");
|
|
11083
|
+
if (existsSync17(content)) {
|
|
11084
|
+
const remaining = await glob8(["**/*"], { cwd: content, dot: true });
|
|
10396
11085
|
if (remaining.length === 0) {
|
|
10397
11086
|
await rm3(content, { force: true, recursive: true });
|
|
10398
11087
|
}
|
|
@@ -10401,8 +11090,8 @@ var cleanupSourceDirs = async (root) => {
|
|
|
10401
11090
|
};
|
|
10402
11091
|
var migrateFumadocsProject = async (root) => {
|
|
10403
11092
|
const { config, warnings: configWarnings } = await loadFumadocsConfig(root);
|
|
10404
|
-
const base =
|
|
10405
|
-
if (!
|
|
11093
|
+
const base = join29(root, SOURCE_DIR);
|
|
11094
|
+
if (!existsSync17(base)) {
|
|
10406
11095
|
await writeBlumeConfig(root, config);
|
|
10407
11096
|
return {
|
|
10408
11097
|
moved: 0,
|
|
@@ -10411,22 +11100,28 @@ var migrateFumadocsProject = async (root) => {
|
|
|
10411
11100
|
]
|
|
10412
11101
|
};
|
|
10413
11102
|
}
|
|
10414
|
-
const pageFiles = await
|
|
11103
|
+
const pageFiles = await glob8([PAGE_GLOB], {
|
|
10415
11104
|
absolute: true,
|
|
10416
11105
|
cwd: base,
|
|
10417
11106
|
ignore: IGNORE
|
|
10418
11107
|
});
|
|
10419
|
-
const metaFiles = await
|
|
11108
|
+
const metaFiles = await glob8([META_GLOB], {
|
|
10420
11109
|
absolute: true,
|
|
10421
11110
|
cwd: base,
|
|
10422
11111
|
ignore: IGNORE
|
|
10423
11112
|
});
|
|
10424
11113
|
const pageResults = await Promise.all(pageFiles.map((abs) => movePage(abs, base, root)));
|
|
10425
11114
|
const pages = summarizePages(pageResults);
|
|
10426
|
-
const
|
|
10427
|
-
const metaWarnings =
|
|
11115
|
+
const orderedMetas = metaFiles.toSorted((a, b) => b.split("/").length - a.split("/").length);
|
|
11116
|
+
const metaWarnings = [];
|
|
11117
|
+
for (const abs of orderedMetas) {
|
|
11118
|
+
metaWarnings.push(...await convertMeta(abs, base, root));
|
|
11119
|
+
}
|
|
10428
11120
|
await writeBlumeConfig(root, config);
|
|
10429
11121
|
const cleanupWarnings = await cleanupSourceDirs(root);
|
|
11122
|
+
const scriptsRewritten = await rewriteFrameworkScripts(root, /\bnext\b/u, /fumadocs/u);
|
|
11123
|
+
const gitignoreAdded = await ensureGitignore(root, [".blume/", "dist/"]);
|
|
11124
|
+
const leftovers = leftoverFiles(root, FUMADOCS_LEFTOVERS);
|
|
10430
11125
|
const warnings = [
|
|
10431
11126
|
...configWarnings,
|
|
10432
11127
|
...metaWarnings,
|
|
@@ -10440,15 +11135,24 @@ var migrateFumadocsProject = async (root) => {
|
|
|
10440
11135
|
if (pages.unsupported.length > 0) {
|
|
10441
11136
|
warnings.push(`Components without a drop-in Blume equivalent need manual review: ${pages.unsupported.join(", ")}.`);
|
|
10442
11137
|
}
|
|
11138
|
+
if (scriptsRewritten) {
|
|
11139
|
+
warnings.push("Repointed the dev/build/start scripts at the Blume CLI.");
|
|
11140
|
+
}
|
|
11141
|
+
if (gitignoreAdded.length > 0) {
|
|
11142
|
+
warnings.push(`Added ${gitignoreAdded.join(", ")} to .gitignore.`);
|
|
11143
|
+
}
|
|
11144
|
+
if (leftovers.length > 0) {
|
|
11145
|
+
warnings.push(`Safe to delete once the migration looks right: ${leftovers.join(", ")}. Also drop the \`next\` plugin from tsconfig.json and the \`.next\`/\`.source\` lines from .gitignore.`);
|
|
11146
|
+
}
|
|
10443
11147
|
warnings.push("Review blume.config.ts and the generated meta.ts files.");
|
|
10444
11148
|
return { moved: pages.moved, warnings };
|
|
10445
11149
|
};
|
|
10446
11150
|
|
|
10447
11151
|
// src/migrate/mintlify/index.ts
|
|
10448
|
-
import { existsSync as
|
|
10449
|
-
import { mkdir as
|
|
10450
|
-
import { dirname as
|
|
10451
|
-
import { glob as
|
|
11152
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
11153
|
+
import { mkdir as mkdir9, readFile as readFile18, rename as rename4, rm as rm4, writeFile as writeFile12 } from "node:fs/promises";
|
|
11154
|
+
import { dirname as dirname15, join as join30 } from "pathe";
|
|
11155
|
+
import { glob as glob9 } from "tinyglobby";
|
|
10452
11156
|
var prune = (value) => {
|
|
10453
11157
|
if (Array.isArray(value)) {
|
|
10454
11158
|
return value.map(prune);
|
|
@@ -10477,7 +11181,7 @@ var writeBlumeConfig2 = async (root, config) => {
|
|
|
10477
11181
|
|
|
10478
11182
|
export default defineConfig(${JSON.stringify(prune(config), null, 2)});
|
|
10479
11183
|
`;
|
|
10480
|
-
await
|
|
11184
|
+
await writeFile12(join30(root, "blume.config.ts"), body, "utf-8");
|
|
10481
11185
|
};
|
|
10482
11186
|
var relocateAssets = async (root, refs) => {
|
|
10483
11187
|
const segments = new Set;
|
|
@@ -10492,30 +11196,30 @@ var relocateAssets = async (root, refs) => {
|
|
|
10492
11196
|
}
|
|
10493
11197
|
const moved = [];
|
|
10494
11198
|
for (const segment of segments) {
|
|
10495
|
-
const source =
|
|
10496
|
-
if (!
|
|
11199
|
+
const source = join30(root, segment);
|
|
11200
|
+
if (!existsSync18(source) || segment === "public") {
|
|
10497
11201
|
continue;
|
|
10498
11202
|
}
|
|
10499
|
-
const dest =
|
|
10500
|
-
if (
|
|
11203
|
+
const dest = join30(root, "public", segment);
|
|
11204
|
+
if (existsSync18(dest)) {
|
|
10501
11205
|
continue;
|
|
10502
11206
|
}
|
|
10503
|
-
await
|
|
10504
|
-
await
|
|
11207
|
+
await mkdir9(join30(root, "public"), { recursive: true });
|
|
11208
|
+
await rename4(source, dest);
|
|
10505
11209
|
moved.push(segment);
|
|
10506
11210
|
}
|
|
10507
11211
|
return moved;
|
|
10508
11212
|
};
|
|
10509
11213
|
var cleanupSnippets = async (root, kept, warnings) => {
|
|
10510
|
-
const dir =
|
|
10511
|
-
if (!
|
|
11214
|
+
const dir = join30(root, "snippets");
|
|
11215
|
+
if (!existsSync18(dir)) {
|
|
10512
11216
|
return;
|
|
10513
11217
|
}
|
|
10514
|
-
const markdown = await
|
|
11218
|
+
const markdown = await glob9(["**/*.{md,mdx}"], { absolute: true, cwd: dir });
|
|
10515
11219
|
for (const file of markdown) {
|
|
10516
11220
|
await rm4(file, { force: true });
|
|
10517
11221
|
}
|
|
10518
|
-
const remaining = await
|
|
11222
|
+
const remaining = await glob9(["**/*"], { cwd: dir, dot: true });
|
|
10519
11223
|
if (remaining.length === 0) {
|
|
10520
11224
|
await rm4(dir, { force: true, recursive: true });
|
|
10521
11225
|
warnings.push("Inlined and removed the /snippets directory.");
|
|
@@ -10545,11 +11249,11 @@ var assetRefs = (config) => {
|
|
|
10545
11249
|
};
|
|
10546
11250
|
var migrateMintlifyProject = async (root) => {
|
|
10547
11251
|
const warnings = [];
|
|
10548
|
-
const configFile =
|
|
11252
|
+
const configFile = existsSync18(join30(root, "docs.json")) ? join30(root, "docs.json") : join30(root, "mint.json");
|
|
10549
11253
|
let config;
|
|
10550
|
-
if (
|
|
11254
|
+
if (existsSync18(configFile)) {
|
|
10551
11255
|
config = await loadMintlifyConfig(root, configFile);
|
|
10552
|
-
const spec = JSON.parse(await
|
|
11256
|
+
const spec = JSON.parse(await readFile18(configFile, "utf-8"));
|
|
10553
11257
|
const i18n = mintlifyI18n(spec);
|
|
10554
11258
|
if (i18n) {
|
|
10555
11259
|
config.i18n = i18n;
|
|
@@ -10564,7 +11268,7 @@ var migrateMintlifyProject = async (root) => {
|
|
|
10564
11268
|
}
|
|
10565
11269
|
const variables = config.variables ?? {};
|
|
10566
11270
|
config.variables = undefined;
|
|
10567
|
-
const files = await
|
|
11271
|
+
const files = await glob9(["**/*.{md,mdx}"], {
|
|
10568
11272
|
absolute: true,
|
|
10569
11273
|
cwd: root,
|
|
10570
11274
|
ignore: [
|
|
@@ -10580,15 +11284,15 @@ var migrateMintlifyProject = async (root) => {
|
|
|
10580
11284
|
const unsupported = new Set;
|
|
10581
11285
|
const keptComponents = new Set;
|
|
10582
11286
|
for (const file of files) {
|
|
10583
|
-
const raw = await
|
|
11287
|
+
const raw = await readFile18(file, "utf-8");
|
|
10584
11288
|
const result = await transformMintlifyContent(raw, {
|
|
10585
11289
|
filePath: file,
|
|
10586
11290
|
root,
|
|
10587
11291
|
variables
|
|
10588
11292
|
});
|
|
10589
11293
|
if (result.content !== raw) {
|
|
10590
|
-
await
|
|
10591
|
-
await
|
|
11294
|
+
await mkdir9(dirname15(file), { recursive: true });
|
|
11295
|
+
await writeFile12(file, result.content, "utf-8");
|
|
10592
11296
|
}
|
|
10593
11297
|
for (const key of result.removed) {
|
|
10594
11298
|
removedKeys.add(key);
|
|
@@ -10624,11 +11328,10 @@ var migrateMintlifyProject = async (root) => {
|
|
|
10624
11328
|
};
|
|
10625
11329
|
|
|
10626
11330
|
// src/migrate/nextra/index.ts
|
|
10627
|
-
import { existsSync as
|
|
10628
|
-
import { mkdir as
|
|
10629
|
-
import
|
|
10630
|
-
import {
|
|
10631
|
-
import { glob as glob9 } from "tinyglobby";
|
|
11331
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
11332
|
+
import { mkdir as mkdir10, readFile as readFile19, rename as rename5, rm as rm5, writeFile as writeFile13 } from "node:fs/promises";
|
|
11333
|
+
import { basename as basename6, dirname as dirname16, extname as extname6, join as join31, relative as relative16 } from "pathe";
|
|
11334
|
+
import { glob as glob10 } from "tinyglobby";
|
|
10632
11335
|
|
|
10633
11336
|
// src/migrate/nextra/content.ts
|
|
10634
11337
|
var CALLOUT_TYPE_DIRECTIVES3 = {
|
|
@@ -10857,30 +11560,30 @@ var indexFolders = (base, pageFiles, metaFiles) => {
|
|
|
10857
11560
|
let current = normalizeDir(dir);
|
|
10858
11561
|
allDirs.add(current);
|
|
10859
11562
|
while (current !== "") {
|
|
10860
|
-
current = normalizeDir(
|
|
11563
|
+
current = normalizeDir(dirname16(current));
|
|
10861
11564
|
allDirs.add(current);
|
|
10862
11565
|
}
|
|
10863
11566
|
};
|
|
10864
11567
|
for (const abs of pageFiles) {
|
|
10865
|
-
const rel =
|
|
10866
|
-
const dir = normalizeDir(
|
|
10867
|
-
const slug =
|
|
11568
|
+
const rel = relative16(base, abs);
|
|
11569
|
+
const dir = normalizeDir(dirname16(rel));
|
|
11570
|
+
const slug = basename6(rel).replace(/\.mdx?$/u, "");
|
|
10868
11571
|
const folder = pagesByDir.get(dir) ?? new Map;
|
|
10869
11572
|
folder.set(slug, abs);
|
|
10870
11573
|
pagesByDir.set(dir, folder);
|
|
10871
11574
|
registerDir(dir);
|
|
10872
11575
|
}
|
|
10873
11576
|
for (const abs of metaFiles) {
|
|
10874
|
-
registerDir(normalizeDir(
|
|
11577
|
+
registerDir(normalizeDir(dirname16(relative16(base, abs))));
|
|
10875
11578
|
}
|
|
10876
11579
|
const childDirs = new Map;
|
|
10877
11580
|
for (const dir of allDirs) {
|
|
10878
11581
|
if (dir === "") {
|
|
10879
11582
|
continue;
|
|
10880
11583
|
}
|
|
10881
|
-
const parent = normalizeDir(
|
|
11584
|
+
const parent = normalizeDir(dirname16(dir));
|
|
10882
11585
|
const children = childDirs.get(parent) ?? new Set;
|
|
10883
|
-
children.add(
|
|
11586
|
+
children.add(basename6(dir));
|
|
10884
11587
|
childDirs.set(parent, children);
|
|
10885
11588
|
}
|
|
10886
11589
|
return { childDirs, pagesByDir };
|
|
@@ -10896,7 +11599,7 @@ var planMetas = (metas, index) => {
|
|
|
10896
11599
|
warnings: []
|
|
10897
11600
|
};
|
|
10898
11601
|
for (const meta of metas) {
|
|
10899
|
-
const dir = normalizeDir(
|
|
11602
|
+
const dir = normalizeDir(dirname16(meta.rel));
|
|
10900
11603
|
const entries = parseNextraMeta(meta.raw, meta.ext);
|
|
10901
11604
|
if (!entries) {
|
|
10902
11605
|
plan.unparseableMetas.push({ abs: meta.abs, rel: meta.rel });
|
|
@@ -10909,7 +11612,7 @@ var planMetas = (metas, index) => {
|
|
|
10909
11612
|
plan.metaByDir.set(dir, conversion.folderMeta);
|
|
10910
11613
|
plan.consumedMetas.push(meta.abs);
|
|
10911
11614
|
for (const [slug, title] of Object.entries(conversion.folderTitles)) {
|
|
10912
|
-
plan.folderTitleByDir.set(normalizeDir(
|
|
11615
|
+
plan.folderTitleByDir.set(normalizeDir(join31(dir, slug)), title);
|
|
10913
11616
|
}
|
|
10914
11617
|
for (const [slug, label] of Object.entries(conversion.pageLabels)) {
|
|
10915
11618
|
const pageAbs = index.pagesByDir.get(dir)?.get(slug);
|
|
@@ -10933,19 +11636,19 @@ var planMetas = (metas, index) => {
|
|
|
10933
11636
|
return plan;
|
|
10934
11637
|
};
|
|
10935
11638
|
var movePage2 = async (abs, options) => {
|
|
10936
|
-
const rel =
|
|
10937
|
-
const dest =
|
|
10938
|
-
if (
|
|
11639
|
+
const rel = relative16(options.base, abs);
|
|
11640
|
+
const dest = join31(options.root, "docs", rel);
|
|
11641
|
+
if (existsSync19(dest)) {
|
|
10939
11642
|
return { moved: 0, removed: [], skipped: rel, unsupported: [] };
|
|
10940
11643
|
}
|
|
10941
|
-
const raw = await
|
|
11644
|
+
const raw = await readFile19(abs, "utf-8");
|
|
10942
11645
|
const text = rewriteNextraCallouts(stripNextraImports(raw));
|
|
10943
11646
|
const unsupported = unsupportedNextraComponents(text);
|
|
10944
|
-
const parsed =
|
|
11647
|
+
const parsed = frontmatter_default(text);
|
|
10945
11648
|
const { data, removed } = normalizeNextraPageMeta(parsed.data, options.overrides.get(abs) ?? {});
|
|
10946
|
-
const content = Object.keys(data).length > 0 ?
|
|
10947
|
-
await
|
|
10948
|
-
await
|
|
11649
|
+
const content = Object.keys(data).length > 0 ? frontmatter_default.stringify(parsed.content, data) : parsed.content;
|
|
11650
|
+
await mkdir10(dirname16(dest), { recursive: true });
|
|
11651
|
+
await writeFile13(dest, content, "utf-8");
|
|
10949
11652
|
await rm5(abs, { force: true });
|
|
10950
11653
|
return { moved: 1, removed, skipped: null, unsupported };
|
|
10951
11654
|
};
|
|
@@ -10987,9 +11690,9 @@ var writeFolderMetas = async (root, plan) => {
|
|
|
10987
11690
|
if (Object.keys(finalMeta).length === 0) {
|
|
10988
11691
|
return;
|
|
10989
11692
|
}
|
|
10990
|
-
const dest =
|
|
10991
|
-
await
|
|
10992
|
-
await
|
|
11693
|
+
const dest = join31(root, "docs", dir, "meta.ts");
|
|
11694
|
+
await mkdir10(dirname16(dest), { recursive: true });
|
|
11695
|
+
await writeFile13(dest, `import { defineMeta } from "blume";
|
|
10993
11696
|
|
|
10994
11697
|
export default defineMeta(${JSON.stringify(finalMeta, null, 2)});
|
|
10995
11698
|
`, "utf-8");
|
|
@@ -10998,20 +11701,20 @@ export default defineMeta(${JSON.stringify(finalMeta, null, 2)});
|
|
|
10998
11701
|
var relocateUnparseableMetas = async (root, metas) => {
|
|
10999
11702
|
const warnings = [];
|
|
11000
11703
|
await Promise.all(metas.map(async ({ abs, rel }) => {
|
|
11001
|
-
const dest =
|
|
11002
|
-
if (
|
|
11704
|
+
const dest = join31(root, "docs", rel);
|
|
11705
|
+
if (existsSync19(dest)) {
|
|
11003
11706
|
warnings.push(`Skipped ${rel} (target already exists)`);
|
|
11004
11707
|
return;
|
|
11005
11708
|
}
|
|
11006
|
-
await
|
|
11007
|
-
await
|
|
11709
|
+
await mkdir10(dirname16(dest), { recursive: true });
|
|
11710
|
+
await rename5(abs, dest);
|
|
11008
11711
|
warnings.push(`Could not parse ${rel}; moved as-is — convert it to meta.ts by hand.`);
|
|
11009
11712
|
}));
|
|
11010
11713
|
return warnings;
|
|
11011
11714
|
};
|
|
11012
11715
|
var buildConfig = (tabs) => tabs.length > 0 ? { navigation: { tabs }, title: "Documentation" } : { title: "Documentation" };
|
|
11013
11716
|
var migrateNextraProject = async (root) => {
|
|
11014
|
-
const sourceDir = SOURCE_DIRS.find((dir) =>
|
|
11717
|
+
const sourceDir = SOURCE_DIRS.find((dir) => existsSync19(join31(root, dir)));
|
|
11015
11718
|
if (!sourceDir) {
|
|
11016
11719
|
await writeBlumeConfig(root, { title: "Documentation" });
|
|
11017
11720
|
return {
|
|
@@ -11021,13 +11724,13 @@ var migrateNextraProject = async (root) => {
|
|
|
11021
11724
|
]
|
|
11022
11725
|
};
|
|
11023
11726
|
}
|
|
11024
|
-
const base =
|
|
11025
|
-
const pageFiles = await
|
|
11727
|
+
const base = join31(root, sourceDir);
|
|
11728
|
+
const pageFiles = await glob10([PAGE_GLOB2], {
|
|
11026
11729
|
absolute: true,
|
|
11027
11730
|
cwd: base,
|
|
11028
11731
|
ignore: IGNORE2
|
|
11029
11732
|
});
|
|
11030
|
-
const metaFiles = await
|
|
11733
|
+
const metaFiles = await glob10([META_GLOB2], {
|
|
11031
11734
|
absolute: true,
|
|
11032
11735
|
cwd: base,
|
|
11033
11736
|
ignore: IGNORE2
|
|
@@ -11036,8 +11739,8 @@ var migrateNextraProject = async (root) => {
|
|
|
11036
11739
|
const metas = await Promise.all(metaFiles.map(async (abs) => ({
|
|
11037
11740
|
abs,
|
|
11038
11741
|
ext: extname6(abs),
|
|
11039
|
-
raw: await
|
|
11040
|
-
rel:
|
|
11742
|
+
raw: await readFile19(abs, "utf-8"),
|
|
11743
|
+
rel: relative16(base, abs)
|
|
11041
11744
|
})));
|
|
11042
11745
|
const plan = planMetas(metas, index);
|
|
11043
11746
|
const moves = await Promise.all(pageFiles.map((abs) => movePage2(abs, { base, overrides: plan.pageOverrides, root })));
|
|
@@ -11062,16 +11765,15 @@ var migrateNextraProject = async (root) => {
|
|
|
11062
11765
|
};
|
|
11063
11766
|
|
|
11064
11767
|
// src/migrate/starlight/index.ts
|
|
11065
|
-
import { existsSync as
|
|
11066
|
-
import { readFile as
|
|
11067
|
-
import
|
|
11068
|
-
import {
|
|
11069
|
-
import { glob as glob10 } from "tinyglobby";
|
|
11768
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
11769
|
+
import { readFile as readFile21, writeFile as writeFile14 } from "node:fs/promises";
|
|
11770
|
+
import { join as join33 } from "pathe";
|
|
11771
|
+
import { glob as glob11 } from "tinyglobby";
|
|
11070
11772
|
|
|
11071
11773
|
// src/migrate/starlight/config.ts
|
|
11072
|
-
import { existsSync as
|
|
11073
|
-
import { readFile as
|
|
11074
|
-
import { join as
|
|
11774
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
11775
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
11776
|
+
import { join as join32 } from "pathe";
|
|
11075
11777
|
var CONFIG_FILES = [
|
|
11076
11778
|
"astro.config.mjs",
|
|
11077
11779
|
"astro.config.mts",
|
|
@@ -11102,7 +11804,7 @@ var extractStarlightOptions = (source) => {
|
|
|
11102
11804
|
return isLiteralObject(parsed) ? parsed : "unparseable";
|
|
11103
11805
|
};
|
|
11104
11806
|
var loadStarlightConfig = async (root) => {
|
|
11105
|
-
const file = CONFIG_FILES.map((name) =>
|
|
11807
|
+
const file = CONFIG_FILES.map((name) => join32(root, name)).find((path) => existsSync20(path));
|
|
11106
11808
|
if (!file) {
|
|
11107
11809
|
return {
|
|
11108
11810
|
options: {},
|
|
@@ -11111,7 +11813,7 @@ var loadStarlightConfig = async (root) => {
|
|
|
11111
11813
|
]
|
|
11112
11814
|
};
|
|
11113
11815
|
}
|
|
11114
|
-
const source = await
|
|
11816
|
+
const source = await readFile20(file, "utf-8");
|
|
11115
11817
|
const result = extractStarlightOptions(source);
|
|
11116
11818
|
if (result === "missing") {
|
|
11117
11819
|
return {
|
|
@@ -11512,17 +12214,17 @@ var starlightI18n = (options) => {
|
|
|
11512
12214
|
// src/migrate/starlight/index.ts
|
|
11513
12215
|
var CONTENT_DIR = "src/content/docs";
|
|
11514
12216
|
var transformPage = async (file) => {
|
|
11515
|
-
const raw = await
|
|
12217
|
+
const raw = await readFile21(file, "utf-8");
|
|
11516
12218
|
let text = stripStarlightImports(raw);
|
|
11517
12219
|
text = rewriteStarlightAsides(text);
|
|
11518
12220
|
text = rewriteStarlightComponents(text);
|
|
11519
12221
|
const unsupported = unsupportedStarlightComponents(text);
|
|
11520
12222
|
const aliased = hasAliasedAssets(text);
|
|
11521
|
-
const parsed =
|
|
12223
|
+
const parsed = frontmatter_default(text);
|
|
11522
12224
|
const { data, removed } = normalizeStarlightPageMeta(parsed.data);
|
|
11523
|
-
const content = Object.keys(data).length > 0 ?
|
|
12225
|
+
const content = Object.keys(data).length > 0 ? frontmatter_default.stringify(parsed.content, data) : parsed.content;
|
|
11524
12226
|
if (content !== raw) {
|
|
11525
|
-
await
|
|
12227
|
+
await writeFile14(file, content, "utf-8");
|
|
11526
12228
|
}
|
|
11527
12229
|
return { aliased, removed, unsupported };
|
|
11528
12230
|
};
|
|
@@ -11534,8 +12236,8 @@ var migrateStarlightProject = async (root) => {
|
|
|
11534
12236
|
config.i18n = i18n;
|
|
11535
12237
|
warnings.push(`Mapped ${i18n.locales.length} locale(s) to i18n (default: ${i18n.defaultLocale}); review the locale labels.`);
|
|
11536
12238
|
}
|
|
11537
|
-
const base =
|
|
11538
|
-
if (!
|
|
12239
|
+
const base = join33(root, CONTENT_DIR);
|
|
12240
|
+
if (!existsSync21(base)) {
|
|
11539
12241
|
await writeBlumeConfig(root, config);
|
|
11540
12242
|
return {
|
|
11541
12243
|
moved: 0,
|
|
@@ -11545,7 +12247,7 @@ var migrateStarlightProject = async (root) => {
|
|
|
11545
12247
|
]
|
|
11546
12248
|
};
|
|
11547
12249
|
}
|
|
11548
|
-
const files = await
|
|
12250
|
+
const files = await glob11(["**/*.{md,mdx}"], { absolute: true, cwd: base });
|
|
11549
12251
|
const results = await Promise.all(files.map(transformPage));
|
|
11550
12252
|
await writeBlumeConfig(root, config);
|
|
11551
12253
|
const removedKeys = new Set;
|
|
@@ -11623,10 +12325,10 @@ var migrateCommand = defineCommand7({
|
|
|
11623
12325
|
});
|
|
11624
12326
|
|
|
11625
12327
|
// src/cli/commands/preview.ts
|
|
11626
|
-
import { existsSync as
|
|
12328
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
11627
12329
|
import { preview } from "astro";
|
|
11628
12330
|
import { defineCommand as defineCommand8 } from "citty";
|
|
11629
|
-
import { join as
|
|
12331
|
+
import { join as join34 } from "pathe";
|
|
11630
12332
|
var previewCommand = defineCommand8({
|
|
11631
12333
|
args: {
|
|
11632
12334
|
host: { description: "Network host to bind.", type: "string" },
|
|
@@ -11640,7 +12342,7 @@ var previewCommand = defineCommand8({
|
|
|
11640
12342
|
const root = process.cwd();
|
|
11641
12343
|
const { config } = await loadConfig(root);
|
|
11642
12344
|
const context = resolveProjectContext(root, config);
|
|
11643
|
-
if (!
|
|
12345
|
+
if (!existsSync22(join34(context.outDir, "astro.config.mjs"))) {
|
|
11644
12346
|
logger.error("No build found. Run `blume build` first.");
|
|
11645
12347
|
process.exit(1);
|
|
11646
12348
|
}
|
|
@@ -11658,7 +12360,7 @@ var previewCommand = defineCommand8({
|
|
|
11658
12360
|
// src/cli/commands/sync.ts
|
|
11659
12361
|
import { rm as rm6 } from "node:fs/promises";
|
|
11660
12362
|
import { defineCommand as defineCommand9 } from "citty";
|
|
11661
|
-
import { join as
|
|
12363
|
+
import { join as join35 } from "pathe";
|
|
11662
12364
|
var syncCommand = defineCommand9({
|
|
11663
12365
|
args: {
|
|
11664
12366
|
force: {
|
|
@@ -11680,7 +12382,7 @@ var syncCommand = defineCommand9({
|
|
|
11680
12382
|
if (args.force) {
|
|
11681
12383
|
const { config } = await loadConfig(root);
|
|
11682
12384
|
const context = resolveProjectContext(root, config);
|
|
11683
|
-
await rm6(
|
|
12385
|
+
await rm6(join35(context.outDir, "cache"), { force: true, recursive: true });
|
|
11684
12386
|
logger.info("Cleared source cache.");
|
|
11685
12387
|
}
|
|
11686
12388
|
await prepareProject({
|
|
@@ -11695,13 +12397,13 @@ var syncCommand = defineCommand9({
|
|
|
11695
12397
|
});
|
|
11696
12398
|
|
|
11697
12399
|
// src/cli/commands/validate.ts
|
|
11698
|
-
import { existsSync as
|
|
12400
|
+
import { existsSync as existsSync24 } from "node:fs";
|
|
11699
12401
|
import { defineCommand as defineCommand10 } from "citty";
|
|
11700
|
-
import { join as
|
|
12402
|
+
import { join as join37 } from "pathe";
|
|
11701
12403
|
|
|
11702
12404
|
// src/core/links.ts
|
|
11703
|
-
import { existsSync as
|
|
11704
|
-
import { join as
|
|
12405
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
12406
|
+
import { join as join36 } from "pathe";
|
|
11705
12407
|
var HTTP = /^https?:\/\//iu;
|
|
11706
12408
|
var PROTOCOL_RELATIVE = /^\/\//u;
|
|
11707
12409
|
var SCHEME = /^[a-z][a-z0-9+.-]*:/iu;
|
|
@@ -11761,7 +12463,7 @@ var checkPathLink = (resolved, fragment, target, site, ctx) => {
|
|
|
11761
12463
|
if (ctx.publicDir === null) {
|
|
11762
12464
|
return "asset-unchecked";
|
|
11763
12465
|
}
|
|
11764
|
-
if (
|
|
12466
|
+
if (existsSync23(join36(ctx.publicDir, resolved))) {
|
|
11765
12467
|
return null;
|
|
11766
12468
|
}
|
|
11767
12469
|
return {
|
|
@@ -11773,16 +12475,19 @@ var checkPathLink = (resolved, fragment, target, site, ctx) => {
|
|
|
11773
12475
|
};
|
|
11774
12476
|
}
|
|
11775
12477
|
const route = toRoute(resolved);
|
|
11776
|
-
if (
|
|
11777
|
-
return
|
|
11778
|
-
|
|
11779
|
-
|
|
11780
|
-
|
|
11781
|
-
severity: "error",
|
|
11782
|
-
suggestion: "Check the path, or create the target page."
|
|
11783
|
-
};
|
|
12478
|
+
if (ctx.routes.has(route)) {
|
|
12479
|
+
return fragment ? checkAnchor(route, fragment, site, ctx) : null;
|
|
12480
|
+
}
|
|
12481
|
+
if (ctx.redirects.has(route)) {
|
|
12482
|
+
return null;
|
|
11784
12483
|
}
|
|
11785
|
-
return
|
|
12484
|
+
return {
|
|
12485
|
+
...site,
|
|
12486
|
+
code: "BLUME_BROKEN_LINK",
|
|
12487
|
+
message: `Broken link to ${target}: no page resolves to ${route}.`,
|
|
12488
|
+
severity: "error",
|
|
12489
|
+
suggestion: "Check the path, or create the target page."
|
|
12490
|
+
};
|
|
11786
12491
|
};
|
|
11787
12492
|
var request = async (url, method) => {
|
|
11788
12493
|
const controller = new AbortController;
|
|
@@ -11891,6 +12596,7 @@ var validateLinks = async (graph, options) => {
|
|
|
11891
12596
|
const ctx = {
|
|
11892
12597
|
anchors: buildAnchorIndex(graph.pages),
|
|
11893
12598
|
publicDir: options.publicDir,
|
|
12599
|
+
redirects: new Set((options.redirects ?? []).map((redirect) => toRoute(redirect.from))),
|
|
11894
12600
|
routes: new Set(graph.routes.keys())
|
|
11895
12601
|
};
|
|
11896
12602
|
const diagnostics = [];
|
|
@@ -11941,10 +12647,11 @@ var validateCommand = defineCommand10({
|
|
|
11941
12647
|
try {
|
|
11942
12648
|
const project = await scanProject(root, { mode: "build" });
|
|
11943
12649
|
diagnostics.push(...project.diagnostics);
|
|
11944
|
-
const publicDir =
|
|
12650
|
+
const publicDir = join37(root, "public");
|
|
11945
12651
|
diagnostics.push(...await validateLinks(project.graph, {
|
|
11946
12652
|
checkExternal: Boolean(args.external),
|
|
11947
|
-
publicDir:
|
|
12653
|
+
publicDir: existsSync24(publicDir) ? publicDir : null,
|
|
12654
|
+
redirects: project.config.redirects
|
|
11948
12655
|
}));
|
|
11949
12656
|
} catch (error) {
|
|
11950
12657
|
if (error instanceof BlumeError) {
|
|
@@ -11985,5 +12692,5 @@ var main = defineCommand11({
|
|
|
11985
12692
|
});
|
|
11986
12693
|
runMain(main);
|
|
11987
12694
|
|
|
11988
|
-
//# debugId=
|
|
12695
|
+
//# debugId=37F2F7467962582064756E2164756E21
|
|
11989
12696
|
//# sourceMappingURL=index.js.map
|