blume 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1213 -473
- package/dist/cli/index.js.map +33 -29
- 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 +3461 -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 +103 -1
- package/package.json +13 -3
- package/src/ai/llms.ts +1 -2
- package/src/astro/examples.ts +106 -0
- package/src/astro/generate.ts +300 -75
- package/src/astro/index.ts +1 -1
- package/src/astro/islands.ts +1 -1
- package/src/astro/pages.ts +59 -0
- package/src/astro/templates.ts +180 -22
- 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/schema.ts +8 -0
- 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 { basename as basename2, 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,31 @@ var runtimeDependencies = (options) => {
|
|
|
3061
3212
|
}
|
|
3062
3213
|
return deps;
|
|
3063
3214
|
};
|
|
3215
|
+
var RENDER_EXTERNAL_DEPS = [
|
|
3216
|
+
"@astrojs/markdown-satteri",
|
|
3217
|
+
"@pierre/diffs",
|
|
3218
|
+
"@shikijs/transformers",
|
|
3219
|
+
"@takumi-rs/core",
|
|
3220
|
+
"@takumi-rs/helpers",
|
|
3221
|
+
"github-slugger",
|
|
3222
|
+
"katex",
|
|
3223
|
+
"shiki",
|
|
3224
|
+
"simple-icons",
|
|
3225
|
+
"zod"
|
|
3226
|
+
];
|
|
3227
|
+
var renderUserAliases = (aliases) => Object.entries(aliases ?? {}).toSorted(([a], [b]) => b.length - a.length).map(([find, replacement]) => `
|
|
3228
|
+
${JSON.stringify(find)}: ${JSON.stringify(replacement)},`).join("");
|
|
3064
3229
|
var astroConfigTemplate = (options) => {
|
|
3065
3230
|
const { context, config, needsReact, pages, dataPath, themePath } = options;
|
|
3066
|
-
const {
|
|
3231
|
+
const {
|
|
3232
|
+
contentRoutes,
|
|
3233
|
+
examplesPath,
|
|
3234
|
+
needsSvelte,
|
|
3235
|
+
needsVue,
|
|
3236
|
+
searchClientPath
|
|
3237
|
+
} = options;
|
|
3067
3238
|
const { deployment } = config;
|
|
3239
|
+
const userAliasLines = renderUserAliases(options.aliases);
|
|
3068
3240
|
const server = deployment.output === "server";
|
|
3069
3241
|
const fsAllow = [...new Set([findWorkspaceRoot(context.root), context.root])];
|
|
3070
3242
|
const adapterImport = server && deployment.adapter ? `import adapter from "${ADAPTER_IMPORTS[deployment.adapter]}";
|
|
@@ -3099,7 +3271,7 @@ var astroConfigTemplate = (options) => {
|
|
|
3099
3271
|
` : "";
|
|
3100
3272
|
const svelteImport = needsSvelte ? `import svelte from "@astrojs/svelte";
|
|
3101
3273
|
` : "";
|
|
3102
|
-
const blumeImport = `import { blumeIntegration } from "blume/astro";
|
|
3274
|
+
const blumeImport = `import { blumeIntegration, prerenderDepsPlugin } from "blume/astro";
|
|
3103
3275
|
`;
|
|
3104
3276
|
const twoslashImport = `import { transformerTwoslash } from "@shikijs/twoslash";
|
|
3105
3277
|
`;
|
|
@@ -3150,25 +3322,21 @@ export default defineConfig({
|
|
|
3150
3322
|
},
|
|
3151
3323
|
devToolbar: { enabled: false },
|
|
3152
3324
|
vite: {
|
|
3153
|
-
plugins: [tailwindcss()],
|
|
3154
|
-
//
|
|
3155
|
-
//
|
|
3156
|
-
//
|
|
3157
|
-
//
|
|
3158
|
-
// native binding") on other platforms (e.g. the Linux CI runner). Astro 7
|
|
3159
|
-
// configures externalization per Vite environment, so it must be forced
|
|
3160
|
-
// external on the prerender (static) and ssr (server) environments -- a
|
|
3161
|
-
// top-level ssr.external only reaches the latter -- so the binding resolves
|
|
3162
|
-
// from node_modules at runtime instead.
|
|
3325
|
+
plugins: [tailwindcss(), prerenderDepsPlugin()],
|
|
3326
|
+
// Blume's render-time deps are forced external on both build environments so
|
|
3327
|
+
// native bindings resolve at runtime and isolated linkers don't bundle
|
|
3328
|
+
// symlinked store copies (which would surface their children as unresolvable
|
|
3329
|
+
// imports). See RENDER_EXTERNAL_DEPS / prerenderDepsPlugin.
|
|
3163
3330
|
environments: {
|
|
3164
|
-
prerender: { resolve: { external:
|
|
3165
|
-
ssr: { resolve: { external:
|
|
3331
|
+
prerender: { resolve: { external: ${JSON.stringify(RENDER_EXTERNAL_DEPS)} } },
|
|
3332
|
+
ssr: { resolve: { external: ${JSON.stringify(RENDER_EXTERNAL_DEPS)} } },
|
|
3166
3333
|
},
|
|
3167
3334
|
resolve: {
|
|
3168
3335
|
alias: {
|
|
3169
3336
|
"blume:data": ${JSON.stringify(dataPath)},
|
|
3337
|
+
"blume:examples": ${JSON.stringify(examplesPath)},
|
|
3170
3338
|
"blume:search-client": ${JSON.stringify(searchClientPath)},
|
|
3171
|
-
"blume:theme": ${JSON.stringify(themePath)}
|
|
3339
|
+
"blume:theme": ${JSON.stringify(themePath)},${userAliasLines}
|
|
3172
3340
|
},
|
|
3173
3341
|
},
|
|
3174
3342
|
server: {
|
|
@@ -3180,7 +3348,7 @@ export default defineConfig({
|
|
|
3180
3348
|
});
|
|
3181
3349
|
`;
|
|
3182
3350
|
};
|
|
3183
|
-
var stagedContentDir = (outDir) =>
|
|
3351
|
+
var stagedContentDir = (outDir) => join7(outDir, "content");
|
|
3184
3352
|
var contentConfigTemplate = (options) => {
|
|
3185
3353
|
const { context, config } = options;
|
|
3186
3354
|
const stagedBase = options.stagedBase ?? stagedContentDir(context.outDir);
|
|
@@ -3426,24 +3594,44 @@ export function GET({ props }) {
|
|
|
3426
3594
|
});
|
|
3427
3595
|
}
|
|
3428
3596
|
`;
|
|
3429
|
-
var ogEndpointTemplate = () => `// Generated by Blume. Do not edit.
|
|
3597
|
+
var ogEndpointTemplate = (customRoutes = []) => `// Generated by Blume. Do not edit.
|
|
3430
3598
|
import { renderOgImage } from "blume/og";
|
|
3431
3599
|
import data from "../../generated/data.json";
|
|
3432
3600
|
|
|
3433
3601
|
export const prerender = true;
|
|
3434
3602
|
|
|
3603
|
+
// Custom (non-content) pages opted into a generated card, baked in at build.
|
|
3604
|
+
const customRoutes = ${JSON.stringify(customRoutes)};
|
|
3605
|
+
|
|
3435
3606
|
export function getStaticPaths() {
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3607
|
+
const seen = new Set();
|
|
3608
|
+
const paths = [];
|
|
3609
|
+
const add = (slug, title, eyebrow) => {
|
|
3610
|
+
if (seen.has(slug)) {
|
|
3611
|
+
return;
|
|
3612
|
+
}
|
|
3613
|
+
seen.add(slug);
|
|
3614
|
+
paths.push({ params: { slug }, props: { eyebrow, title } });
|
|
3615
|
+
};
|
|
3616
|
+
// A custom page wins over a content route sharing its path, so add it first.
|
|
3617
|
+
for (const route of customRoutes) {
|
|
3618
|
+
add(route.slug, route.title, route.eyebrow);
|
|
3619
|
+
}
|
|
3620
|
+
for (const route of data.routes) {
|
|
3621
|
+
add(
|
|
3622
|
+
route.path === "/" ? "index" : route.path.slice(1),
|
|
3623
|
+
route.title,
|
|
3624
|
+
data.config.title
|
|
3625
|
+
);
|
|
3626
|
+
}
|
|
3627
|
+
return paths;
|
|
3440
3628
|
}
|
|
3441
3629
|
|
|
3442
3630
|
export async function GET({ props }) {
|
|
3443
3631
|
const png = await renderOgImage({
|
|
3444
|
-
title: props.title,
|
|
3445
|
-
eyebrow: data.config.title,
|
|
3446
3632
|
accent: data.config.theme.accent,
|
|
3633
|
+
eyebrow: props.eyebrow,
|
|
3634
|
+
title: props.title,
|
|
3447
3635
|
});
|
|
3448
3636
|
return new Response(png, {
|
|
3449
3637
|
headers: {
|
|
@@ -3470,6 +3658,7 @@ const configuration = ${JSON.stringify(options.configuration, null, 2)};
|
|
|
3470
3658
|
fontCssVars={data.fontCssVars}
|
|
3471
3659
|
logo={data.config.logo}
|
|
3472
3660
|
favicon={data.config.favicon}
|
|
3661
|
+
appleIcon={data.config.appleIcon}
|
|
3473
3662
|
navigation={data.navigation}
|
|
3474
3663
|
pageTitle={${JSON.stringify(options.title)}}
|
|
3475
3664
|
route={${JSON.stringify(options.route)}}
|
|
@@ -3501,12 +3690,15 @@ import Badge from "blume/components/content/Badge.astro";
|
|
|
3501
3690
|
import Callout from "blume/components/content/Callout.astro";
|
|
3502
3691
|
import Card from "blume/components/content/Card.astro";
|
|
3503
3692
|
import CardGroup from "blume/components/content/CardGroup.astro";
|
|
3693
|
+
import CodeBlock from "blume/components/content/CodeBlock.astro";
|
|
3504
3694
|
import CodeGroup from "blume/components/content/CodeGroup.astro";
|
|
3505
3695
|
import ColorRoot from "blume/components/content/Color.astro";
|
|
3506
3696
|
import ColorItem from "blume/components/content/ColorItem.astro";
|
|
3507
3697
|
import ColorRow from "blume/components/content/ColorRow.astro";
|
|
3508
3698
|
import Column from "blume/components/content/Column.astro";
|
|
3509
3699
|
import Columns from "blume/components/content/Columns.astro";
|
|
3700
|
+
import Component from "blume/components/content/Component.astro";
|
|
3701
|
+
import Diff from "blume/components/content/Diff.astro";
|
|
3510
3702
|
import Expandable from "blume/components/content/Expandable.astro";
|
|
3511
3703
|
import FileTree from "blume/components/content/FileTree.astro";
|
|
3512
3704
|
import Frame from "blume/components/content/Frame.astro";
|
|
@@ -3546,10 +3738,13 @@ const components = {
|
|
|
3546
3738
|
Callout,
|
|
3547
3739
|
Card,
|
|
3548
3740
|
CardGroup,
|
|
3741
|
+
CodeBlock,
|
|
3549
3742
|
CodeGroup,
|
|
3550
3743
|
Color,
|
|
3551
3744
|
Column,
|
|
3552
3745
|
Columns,
|
|
3746
|
+
Component,
|
|
3747
|
+
Diff,
|
|
3553
3748
|
Expandable,
|
|
3554
3749
|
FileTree,
|
|
3555
3750
|
Frame,
|
|
@@ -3670,6 +3865,7 @@ const localeSwitch = i18n
|
|
|
3670
3865
|
logo={data.config.logo}
|
|
3671
3866
|
mcp={data.config.mcp}
|
|
3672
3867
|
favicon={data.config.favicon}
|
|
3868
|
+
appleIcon={data.config.appleIcon}
|
|
3673
3869
|
banner={data.config.banner}
|
|
3674
3870
|
analytics={data.config.analytics}
|
|
3675
3871
|
imageZoom={data.config.imageZoom}
|
|
@@ -3796,6 +3992,7 @@ const canonical = base ? base + "/changelog" : null;
|
|
|
3796
3992
|
logo={data.config.logo}
|
|
3797
3993
|
mcp={data.config.mcp}
|
|
3798
3994
|
favicon={data.config.favicon}
|
|
3995
|
+
appleIcon={data.config.appleIcon}
|
|
3799
3996
|
banner={data.config.banner}
|
|
3800
3997
|
analytics={data.config.analytics}
|
|
3801
3998
|
imageZoom={data.config.imageZoom}
|
|
@@ -3875,8 +4072,43 @@ ${entries}
|
|
|
3875
4072
|
};
|
|
3876
4073
|
`;
|
|
3877
4074
|
};
|
|
4075
|
+
var exampleDirective = (spec) => {
|
|
4076
|
+
if (spec.framework === "astro" || !spec.client) {
|
|
4077
|
+
return "";
|
|
4078
|
+
}
|
|
4079
|
+
return spec.client === "only" ? `client:only="${spec.framework}" ` : `client:${spec.client} `;
|
|
4080
|
+
};
|
|
4081
|
+
var exampleSlug = (path) => path.replaceAll("/", "__").replaceAll(/[^a-zA-Z0-9_]+/gu, "-");
|
|
4082
|
+
var exampleWrapperTemplate = (spec) => `---
|
|
4083
|
+
// Generated by Blume. Do not edit.
|
|
4084
|
+
import Example from ${JSON.stringify(spec.file)};
|
|
4085
|
+
---
|
|
4086
|
+
<Example ${exampleDirective(spec)}{...Astro.props}><slot /></Example>
|
|
4087
|
+
`;
|
|
4088
|
+
var exampleMapTemplate = (specs) => {
|
|
4089
|
+
if (specs.length === 0) {
|
|
4090
|
+
return `// Generated by Blume. Do not edit.
|
|
4091
|
+
export const examples = {};
|
|
4092
|
+
`;
|
|
4093
|
+
}
|
|
4094
|
+
const imports = specs.map((spec, index) => `import E${index} from "./examples/${exampleSlug(spec.path)}.astro";`).join(`
|
|
4095
|
+
`);
|
|
4096
|
+
const entries = specs.map((spec, index) => ` ${JSON.stringify(spec.path)}: { Component: E${index}, code: ${JSON.stringify(spec.source)}, lang: ${JSON.stringify(spec.lang)} },`).join(`
|
|
4097
|
+
`);
|
|
4098
|
+
return `// Generated by Blume. Do not edit.
|
|
4099
|
+
${imports}
|
|
4100
|
+
export const examples = {
|
|
4101
|
+
${entries}
|
|
4102
|
+
};
|
|
4103
|
+
`;
|
|
4104
|
+
};
|
|
3878
4105
|
var envTemplate = () => `/// <reference path="../.astro/types.d.ts" />
|
|
3879
4106
|
/// <reference types="astro/client" />
|
|
4107
|
+
|
|
4108
|
+
declare module "blume:data" {
|
|
4109
|
+
const data: import("blume").BlumeData;
|
|
4110
|
+
export default data;
|
|
4111
|
+
}
|
|
3880
4112
|
`;
|
|
3881
4113
|
var runtimePackageTemplate = (dependencies = []) => `${JSON.stringify({
|
|
3882
4114
|
dependencies: Object.fromEntries([...dependencies].toSorted().map((name) => [name, "*"])),
|
|
@@ -4057,7 +4289,7 @@ var specConfiguration = async (spec, root) => {
|
|
|
4057
4289
|
if (URL_SPEC.test(spec)) {
|
|
4058
4290
|
return { config: { url: spec } };
|
|
4059
4291
|
}
|
|
4060
|
-
const absolute =
|
|
4292
|
+
const absolute = isAbsolute2(spec) ? spec : join8(root, spec);
|
|
4061
4293
|
try {
|
|
4062
4294
|
return { config: { content: await readFile4(absolute, "utf-8") } };
|
|
4063
4295
|
} catch {
|
|
@@ -4419,6 +4651,19 @@ ${options.sources.map((source) => `@source "${source}";`).join(`
|
|
|
4419
4651
|
text-decoration: var(--shiki-dark-text-decoration, inherit);
|
|
4420
4652
|
}
|
|
4421
4653
|
|
|
4654
|
+
/* The Diff component (@pierre/diffs) renders into a declarative shadow root and
|
|
4655
|
+
themes itself with light-dark(). Drive that from Blume's data-theme instead
|
|
4656
|
+
of the OS, scoped to the diff host: the custom property pierces the shadow
|
|
4657
|
+
boundary, where the appended host color-scheme rule consumes it. */
|
|
4658
|
+
blume-diff {
|
|
4659
|
+
--blume-diff-color-scheme: light;
|
|
4660
|
+
display: block;
|
|
4661
|
+
}
|
|
4662
|
+
|
|
4663
|
+
:root[data-theme="dark"] blume-diff {
|
|
4664
|
+
--blume-diff-color-scheme: dark;
|
|
4665
|
+
}
|
|
4666
|
+
|
|
4422
4667
|
.prose :where(pre[data-language]) {
|
|
4423
4668
|
padding-top: 3.75rem;
|
|
4424
4669
|
}
|
|
@@ -4492,6 +4737,22 @@ blume-tabs pre,
|
|
|
4492
4737
|
background: var(--blume-code-background);
|
|
4493
4738
|
}
|
|
4494
4739
|
|
|
4740
|
+
/* The Component source pane fills its tab's fixed height (set inline to match the
|
|
4741
|
+
preview tab) and scrolls the inner code element, leaving the pre static so the
|
|
4742
|
+
copy button — absolute, pinned to the pre — doesn't drift while it scrolls. */
|
|
4743
|
+
pre.blume-source {
|
|
4744
|
+
display: flex;
|
|
4745
|
+
flex-direction: column;
|
|
4746
|
+
height: 100%;
|
|
4747
|
+
overflow: hidden;
|
|
4748
|
+
}
|
|
4749
|
+
|
|
4750
|
+
pre.blume-source > code {
|
|
4751
|
+
flex: 1;
|
|
4752
|
+
min-height: 0;
|
|
4753
|
+
overflow: auto;
|
|
4754
|
+
}
|
|
4755
|
+
|
|
4495
4756
|
/* Code blocks inside tabs sit flush; the tab container owns the frame. These
|
|
4496
4757
|
rules are unlayered like the base \`pre\` styles, so they win over Tailwind's
|
|
4497
4758
|
layered utilities (which a class on the panel cannot). The second selector
|
|
@@ -4701,9 +4962,9 @@ ${options.userTheme}
|
|
|
4701
4962
|
`;
|
|
4702
4963
|
|
|
4703
4964
|
// src/theme/twoslash.ts
|
|
4704
|
-
import { readFileSync as
|
|
4705
|
-
import { createRequire as
|
|
4706
|
-
var require2 =
|
|
4965
|
+
import { readFileSync as readFileSync4 } from "node:fs";
|
|
4966
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
4967
|
+
var require2 = createRequire3(import.meta.url);
|
|
4707
4968
|
var OVERRIDES = `
|
|
4708
4969
|
/* Twoslash: theme the rich renderer with Blume tokens. */
|
|
4709
4970
|
:root {
|
|
@@ -4763,13 +5024,18 @@ var OVERRIDES = `
|
|
|
4763
5024
|
`;
|
|
4764
5025
|
var twoslashCss = () => {
|
|
4765
5026
|
const file = require2.resolve("@shikijs/twoslash/style-rich.css");
|
|
4766
|
-
return `${
|
|
5027
|
+
return `${readFileSync4(file, "utf-8")}
|
|
4767
5028
|
${OVERRIDES}`;
|
|
4768
5029
|
};
|
|
4769
5030
|
|
|
5031
|
+
// src/astro/examples.ts
|
|
5032
|
+
import { readFile as readFile6 } from "node:fs/promises";
|
|
5033
|
+
import { join as join10, relative as relative3 } from "pathe";
|
|
5034
|
+
import { glob as glob2 } from "tinyglobby";
|
|
5035
|
+
|
|
4770
5036
|
// src/astro/islands.ts
|
|
4771
5037
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
4772
|
-
import { basename, join as
|
|
5038
|
+
import { basename, join as join9 } from "pathe";
|
|
4773
5039
|
import { glob } from "tinyglobby";
|
|
4774
5040
|
var DEFAULT_CLIENT = "visible";
|
|
4775
5041
|
var VALID_MODES = new Set([
|
|
@@ -4798,7 +5064,7 @@ var readClientMode = (source, file, warnings) => {
|
|
|
4798
5064
|
return mode;
|
|
4799
5065
|
};
|
|
4800
5066
|
var discoverIslands = async (root) => {
|
|
4801
|
-
const dir =
|
|
5067
|
+
const dir = join9(root, "islands");
|
|
4802
5068
|
const matches = await glob(["**/*.{jsx,svelte,tsx,vue}"], {
|
|
4803
5069
|
absolute: true,
|
|
4804
5070
|
cwd: dir,
|
|
@@ -4837,50 +5103,157 @@ var discoverIslands = async (root) => {
|
|
|
4837
5103
|
return { islands, warnings };
|
|
4838
5104
|
};
|
|
4839
5105
|
|
|
5106
|
+
// src/astro/examples.ts
|
|
5107
|
+
var FRAMEWORK_BY_EXT2 = {
|
|
5108
|
+
astro: "astro",
|
|
5109
|
+
jsx: "react",
|
|
5110
|
+
svelte: "svelte",
|
|
5111
|
+
tsx: "react",
|
|
5112
|
+
vue: "vue"
|
|
5113
|
+
};
|
|
5114
|
+
var EXAMPLE_FILE = /\.(?<ext>astro|jsx|svelte|tsx|vue)$/u;
|
|
5115
|
+
var discoverExamples = async (root, subdir = "examples") => {
|
|
5116
|
+
const dir = join10(root, subdir);
|
|
5117
|
+
const matches = await glob2(["**/*.{astro,jsx,svelte,tsx,vue}"], {
|
|
5118
|
+
absolute: true,
|
|
5119
|
+
cwd: dir,
|
|
5120
|
+
onlyFiles: true
|
|
5121
|
+
});
|
|
5122
|
+
const files = matches.toSorted();
|
|
5123
|
+
const sources = await Promise.all(files.map((file) => readFile6(file, "utf-8")));
|
|
5124
|
+
const examples = [];
|
|
5125
|
+
const warnings = [];
|
|
5126
|
+
const seen = new Map;
|
|
5127
|
+
for (const [index, file] of files.entries()) {
|
|
5128
|
+
const ext = file.match(EXAMPLE_FILE)?.groups?.ext;
|
|
5129
|
+
const framework = ext ? FRAMEWORK_BY_EXT2[ext] : undefined;
|
|
5130
|
+
if (!(ext && framework)) {
|
|
5131
|
+
continue;
|
|
5132
|
+
}
|
|
5133
|
+
const path = relative3(dir, file).slice(0, -(ext.length + 1));
|
|
5134
|
+
const existing = seen.get(path);
|
|
5135
|
+
if (existing) {
|
|
5136
|
+
warnings.push(`Two examples both resolve to "${path}" ("${existing}" and "${file}"); ignoring the second. Give them distinct paths.`);
|
|
5137
|
+
continue;
|
|
5138
|
+
}
|
|
5139
|
+
seen.set(path, file);
|
|
5140
|
+
const source = sources[index] ?? "";
|
|
5141
|
+
examples.push({
|
|
5142
|
+
client: framework === "astro" ? undefined : readClientMode(source, file, warnings),
|
|
5143
|
+
file,
|
|
5144
|
+
framework,
|
|
5145
|
+
lang: ext,
|
|
5146
|
+
path,
|
|
5147
|
+
source
|
|
5148
|
+
});
|
|
5149
|
+
}
|
|
5150
|
+
return { examples, warnings };
|
|
5151
|
+
};
|
|
5152
|
+
|
|
4840
5153
|
// src/astro/pages.ts
|
|
4841
|
-
import { extname, relative as
|
|
4842
|
-
import { glob as
|
|
5154
|
+
import { extname, relative as relative4 } from "pathe";
|
|
5155
|
+
import { glob as glob3 } from "tinyglobby";
|
|
4843
5156
|
var discoverPages = async (pagesRoot) => {
|
|
4844
|
-
const files = await
|
|
5157
|
+
const files = await glob3(["**/*.astro"], {
|
|
4845
5158
|
absolute: true,
|
|
4846
5159
|
cwd: pagesRoot,
|
|
4847
5160
|
onlyFiles: true
|
|
4848
5161
|
});
|
|
4849
5162
|
files.sort();
|
|
4850
5163
|
return files.map((file) => {
|
|
4851
|
-
const rel =
|
|
5164
|
+
const rel = relative4(pagesRoot, file);
|
|
4852
5165
|
const withoutExt = rel.slice(0, rel.length - extname(rel).length);
|
|
4853
5166
|
const parts = withoutExt.split("/").filter((part) => part !== "index");
|
|
4854
5167
|
const pattern = parts.length === 0 ? "/" : `/${parts.join("/")}`;
|
|
4855
5168
|
return { entrypoint: file, pattern };
|
|
4856
5169
|
});
|
|
4857
5170
|
};
|
|
5171
|
+
var PRIVATE_SEGMENT = /^[._]/u;
|
|
5172
|
+
var humanizeSegment = (segment) => segment.split(/[-_]/u).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
5173
|
+
var customOgRoutes = (pages, siteTitle, siteDescription) => {
|
|
5174
|
+
const seen = new Set;
|
|
5175
|
+
const routes = [];
|
|
5176
|
+
for (const { pattern } of pages) {
|
|
5177
|
+
const segments = pattern.split("/").filter(Boolean);
|
|
5178
|
+
if (segments.some((part) => PRIVATE_SEGMENT.test(part) || part.includes("["))) {
|
|
5179
|
+
continue;
|
|
5180
|
+
}
|
|
5181
|
+
const slug = segments.length === 0 ? "index" : segments.join("/");
|
|
5182
|
+
if (seen.has(slug)) {
|
|
5183
|
+
continue;
|
|
5184
|
+
}
|
|
5185
|
+
seen.add(slug);
|
|
5186
|
+
const last = segments.at(-1);
|
|
5187
|
+
routes.push(last ? { eyebrow: siteTitle, slug, title: humanizeSegment(last) } : { eyebrow: siteDescription, slug, title: siteTitle });
|
|
5188
|
+
}
|
|
5189
|
+
return routes;
|
|
5190
|
+
};
|
|
4858
5191
|
|
|
4859
5192
|
// src/astro/generate.ts
|
|
4860
|
-
var BLUME_SRC =
|
|
4861
|
-
var BLUME_NODE_MODULES = join9(packageRoot(), "node_modules");
|
|
5193
|
+
var BLUME_SRC = join11(packageRoot(), "src");
|
|
4862
5194
|
var canResolveFrom = (fromDir, spec) => {
|
|
4863
5195
|
try {
|
|
4864
|
-
|
|
5196
|
+
createRequire4(pathToFileURL2(join11(fromDir, "_.js")).href).resolve(spec);
|
|
4865
5197
|
return true;
|
|
4866
5198
|
} catch {
|
|
4867
5199
|
return false;
|
|
4868
5200
|
}
|
|
4869
5201
|
};
|
|
4870
|
-
var
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
return;
|
|
5202
|
+
var resolvedAstroPath = (fromDir) => {
|
|
5203
|
+
try {
|
|
5204
|
+
const pkg = createRequire4(pathToFileURL2(join11(fromDir, "_.js")).href).resolve("astro/package.json");
|
|
5205
|
+
return realpathSync(pkg);
|
|
5206
|
+
} catch {
|
|
5207
|
+
return null;
|
|
4874
5208
|
}
|
|
4875
|
-
|
|
4876
|
-
|
|
5209
|
+
};
|
|
5210
|
+
var blumeDepsDir = (pkgDir = packageRoot()) => {
|
|
5211
|
+
const candidates = [join11(pkgDir, "node_modules"), dirname6(pkgDir)];
|
|
5212
|
+
return candidates.find((dir) => existsSync5(join11(dir, "astro"))) ?? null;
|
|
5213
|
+
};
|
|
5214
|
+
var linkDepsJunction = async (link, depsDir) => {
|
|
5215
|
+
const existing = await lstat(link).catch(() => null);
|
|
5216
|
+
if (existing) {
|
|
5217
|
+
if (!existing.isSymbolicLink()) {
|
|
5218
|
+
return;
|
|
5219
|
+
}
|
|
5220
|
+
await rm(link, { force: true });
|
|
4877
5221
|
}
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
5222
|
+
await mkdir2(dirname6(link), { recursive: true });
|
|
5223
|
+
await symlink(depsDir, link, "junction");
|
|
5224
|
+
};
|
|
5225
|
+
var readPkgVersion = (pkgJsonPath) => {
|
|
5226
|
+
if (!pkgJsonPath) {
|
|
5227
|
+
return null;
|
|
5228
|
+
}
|
|
5229
|
+
try {
|
|
5230
|
+
return JSON.parse(readFileSync5(pkgJsonPath, "utf-8")).version ?? null;
|
|
5231
|
+
} catch {
|
|
5232
|
+
return null;
|
|
5233
|
+
}
|
|
5234
|
+
};
|
|
5235
|
+
var astroConflictWarning = (blumeAstroPkg, shadowAstroPkg) => {
|
|
5236
|
+
const blume = readPkgVersion(blumeAstroPkg);
|
|
5237
|
+
const shadow = readPkgVersion(shadowAstroPkg);
|
|
5238
|
+
const versions = blume && shadow ? `astro@${shadow} shadowing Blume's astro@${blume}` : "a second copy of Astro shadowing Blume's";
|
|
5239
|
+
const pin = blume ?? "<Blume's astro version>";
|
|
5240
|
+
return `Astro version conflict: another dependency hoisted ${versions} to the project root, so @astrojs/mdx binds to the wrong copy and the build fails on a missing export (e.g. "chunkToString"). A single symlink can't reconcile a split install — pin Blume's Astro by adding a package.json "overrides" (npm/bun/pnpm) or "resolutions" (yarn) entry { "astro": "${pin}" }, then reinstall. Run \`npm ls astro\` to find the dependency pulling the older copy.`;
|
|
5241
|
+
};
|
|
5242
|
+
var ensureDepsLink = async (outDir, pkgDir = packageRoot()) => {
|
|
5243
|
+
const depsDir = blumeDepsDir(pkgDir);
|
|
5244
|
+
if (!depsDir) {
|
|
5245
|
+
return null;
|
|
5246
|
+
}
|
|
5247
|
+
const blumeAstro = resolvedAstroPath(depsDir);
|
|
5248
|
+
const outDirAstro = resolvedAstroPath(outDir);
|
|
5249
|
+
if (blumeAstro && outDirAstro === blumeAstro) {
|
|
5250
|
+
return null;
|
|
5251
|
+
}
|
|
5252
|
+
if (existsSync5(join11(depsDir, "@astrojs", "mdx"))) {
|
|
5253
|
+
await linkDepsJunction(join11(outDir, "node_modules"), depsDir);
|
|
5254
|
+
return null;
|
|
4881
5255
|
}
|
|
4882
|
-
|
|
4883
|
-
await symlink(BLUME_NODE_MODULES, link, "junction");
|
|
5256
|
+
return astroConflictWarning(blumeAstro, outDirAstro);
|
|
4884
5257
|
};
|
|
4885
5258
|
var ISLAND_FRAMEWORK_DEPS = {
|
|
4886
5259
|
svelte: "@astrojs/svelte",
|
|
@@ -4901,13 +5274,13 @@ var readOptional = async (path) => {
|
|
|
4901
5274
|
return "";
|
|
4902
5275
|
}
|
|
4903
5276
|
try {
|
|
4904
|
-
return await
|
|
5277
|
+
return await readFile7(path, "utf-8");
|
|
4905
5278
|
} catch {
|
|
4906
5279
|
return "";
|
|
4907
5280
|
}
|
|
4908
5281
|
};
|
|
4909
5282
|
var detectNeedsReact = async (root) => {
|
|
4910
|
-
const matches = await
|
|
5283
|
+
const matches = await glob4(["**/*.{tsx,jsx}"], {
|
|
4911
5284
|
cwd: root,
|
|
4912
5285
|
ignore: ["**/node_modules/**", "**/.blume/**", "**/dist/**"],
|
|
4913
5286
|
onlyFiles: true
|
|
@@ -4917,14 +5290,14 @@ var detectNeedsReact = async (root) => {
|
|
|
4917
5290
|
var writeIfChanged = async (path, content) => {
|
|
4918
5291
|
let existing = null;
|
|
4919
5292
|
try {
|
|
4920
|
-
existing = await
|
|
5293
|
+
existing = await readFile7(path, "utf-8");
|
|
4921
5294
|
} catch {
|
|
4922
5295
|
existing = null;
|
|
4923
5296
|
}
|
|
4924
5297
|
if (existing === content) {
|
|
4925
5298
|
return false;
|
|
4926
5299
|
}
|
|
4927
|
-
await mkdir2(
|
|
5300
|
+
await mkdir2(dirname6(path), { recursive: true });
|
|
4928
5301
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
4929
5302
|
await writeFile2(tmp, content, "utf-8");
|
|
4930
5303
|
try {
|
|
@@ -4936,7 +5309,7 @@ var writeIfChanged = async (path, content) => {
|
|
|
4936
5309
|
return true;
|
|
4937
5310
|
};
|
|
4938
5311
|
var pruneOrphans = async (srcDir, written) => {
|
|
4939
|
-
const existing = await
|
|
5312
|
+
const existing = await glob4("**/*", {
|
|
4940
5313
|
absolute: true,
|
|
4941
5314
|
cwd: srcDir,
|
|
4942
5315
|
onlyFiles: true
|
|
@@ -4956,11 +5329,11 @@ var writeStagedContent = async (out, staged) => {
|
|
|
4956
5329
|
const contentDir = stagedContentDir(out);
|
|
4957
5330
|
const written = new Set;
|
|
4958
5331
|
await Promise.all([...staged].map(async ([entryId, text]) => {
|
|
4959
|
-
const path =
|
|
5332
|
+
const path = join11(contentDir, entryId);
|
|
4960
5333
|
written.add(normalize(path));
|
|
4961
5334
|
await writeIfChanged(path, text);
|
|
4962
5335
|
}));
|
|
4963
|
-
if (
|
|
5336
|
+
if (existsSync5(contentDir)) {
|
|
4964
5337
|
await pruneOrphans(contentDir, written);
|
|
4965
5338
|
}
|
|
4966
5339
|
};
|
|
@@ -4977,11 +5350,11 @@ var resolveLogo = (project) => {
|
|
|
4977
5350
|
if (light && light === dark && light.toLowerCase().endsWith(".svg")) {
|
|
4978
5351
|
const rel = light.replace(/^\//u, "");
|
|
4979
5352
|
const file = [
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
].find((path) =>
|
|
5353
|
+
join11(project.context.root, "public", rel),
|
|
5354
|
+
join11(project.context.root, rel)
|
|
5355
|
+
].find((path) => existsSync5(path));
|
|
4983
5356
|
if (file) {
|
|
4984
|
-
return { alt, href, svg:
|
|
5357
|
+
return { alt, href, svg: readFileSync5(file, "utf-8") };
|
|
4985
5358
|
}
|
|
4986
5359
|
}
|
|
4987
5360
|
return { alt, dark, href, light };
|
|
@@ -4996,6 +5369,8 @@ var FAVICON_CANDIDATES = [
|
|
|
4996
5369
|
];
|
|
4997
5370
|
var FAVICON_TYPES = {
|
|
4998
5371
|
ico: "image/x-icon",
|
|
5372
|
+
jpeg: "image/jpeg",
|
|
5373
|
+
jpg: "image/jpeg",
|
|
4999
5374
|
png: "image/png",
|
|
5000
5375
|
svg: "image/svg+xml"
|
|
5001
5376
|
};
|
|
@@ -5003,27 +5378,35 @@ var faviconType = (name) => {
|
|
|
5003
5378
|
const ext = name.split(".").pop()?.toLowerCase();
|
|
5004
5379
|
return ext ? FAVICON_TYPES[ext] : undefined;
|
|
5005
5380
|
};
|
|
5006
|
-
var inlineDataUri = (file, type) => `data:${type};base64,${
|
|
5381
|
+
var inlineDataUri = (file, type) => `data:${type};base64,${readFileSync5(file).toString("base64")}`;
|
|
5007
5382
|
var defaultFavicon = () => ({
|
|
5008
|
-
href: inlineDataUri(
|
|
5383
|
+
href: inlineDataUri(join11(BLUME_SRC, "assets", "icon.png"), "image/png"),
|
|
5009
5384
|
type: "image/png"
|
|
5010
5385
|
});
|
|
5011
|
-
var
|
|
5386
|
+
var APPLE_ICON_CANDIDATES = [
|
|
5387
|
+
"apple-icon.png",
|
|
5388
|
+
"apple-icon.jpg",
|
|
5389
|
+
"apple-icon.jpeg",
|
|
5390
|
+
"apple-touch-icon.png"
|
|
5391
|
+
];
|
|
5392
|
+
var resolveIconFile = (project, candidates) => {
|
|
5012
5393
|
const { root } = project.context;
|
|
5013
|
-
for (const name of
|
|
5014
|
-
if (
|
|
5394
|
+
for (const name of candidates) {
|
|
5395
|
+
if (existsSync5(join11(root, "public", name))) {
|
|
5015
5396
|
return { href: `/${name}`, type: faviconType(name) };
|
|
5016
5397
|
}
|
|
5017
5398
|
}
|
|
5018
|
-
for (const name of
|
|
5019
|
-
const file =
|
|
5020
|
-
if (
|
|
5399
|
+
for (const name of candidates) {
|
|
5400
|
+
const file = join11(root, name);
|
|
5401
|
+
if (existsSync5(file)) {
|
|
5021
5402
|
const type = faviconType(name);
|
|
5022
5403
|
return { href: inlineDataUri(file, type ?? "image/x-icon"), type };
|
|
5023
5404
|
}
|
|
5024
5405
|
}
|
|
5025
|
-
return
|
|
5406
|
+
return null;
|
|
5026
5407
|
};
|
|
5408
|
+
var resolveFavicon = (project) => resolveIconFile(project, FAVICON_CANDIDATES) ?? defaultFavicon();
|
|
5409
|
+
var resolveAppleIcon = (project) => resolveIconFile(project, APPLE_ICON_CANDIDATES);
|
|
5027
5410
|
var resolveBanner = (config) => {
|
|
5028
5411
|
const { banner } = config;
|
|
5029
5412
|
if (!banner) {
|
|
@@ -5048,7 +5431,7 @@ var buildRuntimeData = (project) => {
|
|
|
5048
5431
|
if (!(editBase && sourcePath)) {
|
|
5049
5432
|
return null;
|
|
5050
5433
|
}
|
|
5051
|
-
const rel =
|
|
5434
|
+
const rel = relative5(context.root, sourcePath).split("\\").join("/");
|
|
5052
5435
|
return `${editBase}/${github?.dir ? `${github.dir}/${rel}` : rel}`;
|
|
5053
5436
|
};
|
|
5054
5437
|
const { i18n } = config;
|
|
@@ -5081,6 +5464,7 @@ var buildRuntimeData = (project) => {
|
|
|
5081
5464
|
const data = {
|
|
5082
5465
|
config: {
|
|
5083
5466
|
analytics: config.analytics ?? null,
|
|
5467
|
+
appleIcon: resolveAppleIcon(project),
|
|
5084
5468
|
banner: resolveBanner(config),
|
|
5085
5469
|
codeWrap: config.markdown.code.wrap,
|
|
5086
5470
|
description: config.description,
|
|
@@ -5099,7 +5483,7 @@ var buildRuntimeData = (project) => {
|
|
|
5099
5483
|
imageZoom: config.markdown.imageZoom,
|
|
5100
5484
|
logo: resolveLogo(project),
|
|
5101
5485
|
mcp: config.mcp.enabled ? { name: config.mcp.name ?? config.title, route: config.mcp.route } : null,
|
|
5102
|
-
og: { enabled: config.seo.og.enabled },
|
|
5486
|
+
og: { enabled: config.seo.og.enabled ?? false },
|
|
5103
5487
|
repoUrl,
|
|
5104
5488
|
search: {
|
|
5105
5489
|
enabled: config.search.provider !== "none",
|
|
@@ -5141,7 +5525,7 @@ var buildRuntimeData = (project) => {
|
|
|
5141
5525
|
var planMcp = (project, srcDir) => {
|
|
5142
5526
|
const { config } = project;
|
|
5143
5527
|
const { route } = config.mcp;
|
|
5144
|
-
const dir =
|
|
5528
|
+
const dir = join11(srcDir, "blume-mcp");
|
|
5145
5529
|
const base = {
|
|
5146
5530
|
dir,
|
|
5147
5531
|
discoveryPages: [],
|
|
@@ -5165,11 +5549,11 @@ var planMcp = (project, srcDir) => {
|
|
|
5165
5549
|
...base,
|
|
5166
5550
|
discoveryPages: [
|
|
5167
5551
|
{
|
|
5168
|
-
entrypoint:
|
|
5552
|
+
entrypoint: join11(dir, "discovery.ts"),
|
|
5169
5553
|
pattern: "/.well-known/mcp.json"
|
|
5170
5554
|
},
|
|
5171
5555
|
{
|
|
5172
|
-
entrypoint:
|
|
5556
|
+
entrypoint: join11(dir, "server-card.ts"),
|
|
5173
5557
|
pattern: "/.well-known/mcp/server-card.json"
|
|
5174
5558
|
}
|
|
5175
5559
|
],
|
|
@@ -5188,49 +5572,57 @@ var writeMcpFiles = async (project, plan, write) => {
|
|
|
5188
5572
|
version: data.version
|
|
5189
5573
|
};
|
|
5190
5574
|
await Promise.all([
|
|
5191
|
-
write(
|
|
5575
|
+
write(join11(plan.srcDir, "generated", "mcp-data.json"), `${JSON.stringify(data)}
|
|
5192
5576
|
`),
|
|
5193
|
-
write(
|
|
5194
|
-
write(
|
|
5195
|
-
write(
|
|
5577
|
+
write(join11(plan.srcDir, "pages", mcpPageFile(plan.route)), mcpEndpointTemplate(plan.route)),
|
|
5578
|
+
write(join11(plan.dir, "discovery.ts"), staticJsonEndpointTemplate(buildMcpDiscovery(discoveryInput))),
|
|
5579
|
+
write(join11(plan.dir, "server-card.ts"), staticJsonEndpointTemplate(buildMcpServerCard(discoveryInput)))
|
|
5196
5580
|
]);
|
|
5197
5581
|
};
|
|
5198
5582
|
var generateRuntime = async (project) => {
|
|
5199
5583
|
const { context, config } = project;
|
|
5200
5584
|
const out = context.outDir;
|
|
5201
|
-
const srcDir =
|
|
5202
|
-
const dataPath =
|
|
5203
|
-
const themePath =
|
|
5204
|
-
const searchClientPath =
|
|
5585
|
+
const srcDir = join11(out, "src");
|
|
5586
|
+
const dataPath = join11(srcDir, "generated", "data.json");
|
|
5587
|
+
const themePath = join11(srcDir, "generated", "app.css");
|
|
5588
|
+
const searchClientPath = join11(srcDir, "generated", "search-client.ts");
|
|
5589
|
+
const examplesPath = join11(srcDir, "generated", "examples.ts");
|
|
5205
5590
|
const written = new Set;
|
|
5206
5591
|
const write = (path, content) => {
|
|
5207
5592
|
written.add(normalize(path));
|
|
5208
5593
|
return writeIfChanged(path, content);
|
|
5209
5594
|
};
|
|
5210
|
-
await ensureDepsLink(out);
|
|
5595
|
+
const depsLinkWarning = await ensureDepsLink(out);
|
|
5211
5596
|
const askEnabled = config.ai.ask?.enabled ?? false;
|
|
5212
5597
|
const exportPdf = config.export.pdf;
|
|
5213
5598
|
const exportEpub = config.export.epub;
|
|
5214
|
-
const [pages, detectedReact, userTheme, islandDiscovery] = await Promise.all([
|
|
5599
|
+
const [pages, detectedReact, userTheme, islandDiscovery, exampleDiscovery] = await Promise.all([
|
|
5215
5600
|
context.pagesRoot ? discoverPages(context.pagesRoot) : Promise.resolve([]),
|
|
5216
5601
|
detectNeedsReact(context.root),
|
|
5217
5602
|
readOptional(context.themeFile),
|
|
5218
|
-
discoverIslands(context.root)
|
|
5603
|
+
discoverIslands(context.root),
|
|
5604
|
+
discoverExamples(context.root, config.examples)
|
|
5605
|
+
]);
|
|
5606
|
+
const frameworks = new Set([
|
|
5607
|
+
...islandDiscovery.islands.map((island) => island.framework),
|
|
5608
|
+
...exampleDiscovery.examples.map((example) => example.framework)
|
|
5219
5609
|
]);
|
|
5220
|
-
const
|
|
5221
|
-
const
|
|
5222
|
-
const
|
|
5223
|
-
const
|
|
5610
|
+
const needsReact = detectedReact || askEnabled || frameworks.has("react");
|
|
5611
|
+
const needsVue = frameworks.has("vue");
|
|
5612
|
+
const needsSvelte = frameworks.has("svelte");
|
|
5613
|
+
const ogRoutes = customOgRoutes(pages, config.title, config.description);
|
|
5224
5614
|
const mcp = planMcp(project, srcDir);
|
|
5225
5615
|
pages.push(...mcp.discoveryPages);
|
|
5226
5616
|
const staged = collectStaged(project);
|
|
5227
5617
|
const hasStaged = staged.size > 0;
|
|
5228
5618
|
const structural = await Promise.all([
|
|
5229
|
-
write(
|
|
5619
|
+
write(join11(out, "astro.config.mjs"), astroConfigTemplate({
|
|
5620
|
+
aliases: resolveTsconfigAliases(context.root),
|
|
5230
5621
|
config,
|
|
5231
5622
|
contentRoutes: project.manifest.routes.map((route) => route.path),
|
|
5232
5623
|
context,
|
|
5233
5624
|
dataPath,
|
|
5625
|
+
examplesPath,
|
|
5234
5626
|
needsReact,
|
|
5235
5627
|
needsSvelte,
|
|
5236
5628
|
needsVue,
|
|
@@ -5238,18 +5630,19 @@ var generateRuntime = async (project) => {
|
|
|
5238
5630
|
searchClientPath,
|
|
5239
5631
|
themePath
|
|
5240
5632
|
})),
|
|
5241
|
-
write(
|
|
5242
|
-
write(
|
|
5243
|
-
write(
|
|
5244
|
-
write(
|
|
5245
|
-
write(
|
|
5633
|
+
write(join11(out, "package.json"), runtimePackageTemplate(runtimeDependencies({ config, needsReact, needsSvelte, needsVue }))),
|
|
5634
|
+
write(join11(out, "tsconfig.json"), runtimeTsconfigTemplate()),
|
|
5635
|
+
write(join11(srcDir, "env.d.ts"), envTemplate()),
|
|
5636
|
+
write(join11(srcDir, "content.config.ts"), contentConfigTemplate({ config, context, staged: hasStaged })),
|
|
5637
|
+
write(join11(srcDir, "pages", "[...slug].astro"), catchAllPageTemplate({
|
|
5246
5638
|
askEnabled,
|
|
5247
5639
|
exportEpub,
|
|
5248
5640
|
exportPdf,
|
|
5249
5641
|
mathEnabled: config.markdown.math
|
|
5250
5642
|
})),
|
|
5251
|
-
write(
|
|
5252
|
-
write(
|
|
5643
|
+
write(join11(srcDir, "generated", "components.ts"), userComponentsTemplate(context.componentsFile)),
|
|
5644
|
+
write(join11(srcDir, "generated", "islands.ts"), islandMapTemplate(islandDiscovery.islands)),
|
|
5645
|
+
write(join11(srcDir, "generated", "examples.ts"), exampleMapTemplate(exampleDiscovery.examples)),
|
|
5253
5646
|
write(themePath, tailwindEntryTemplate({
|
|
5254
5647
|
configTokens: `${buildThemeCss(config.theme)}${buildFontsCss(config.theme.fonts)}`,
|
|
5255
5648
|
sources: [
|
|
@@ -5260,52 +5653,58 @@ var generateRuntime = async (project) => {
|
|
|
5260
5653
|
userTheme
|
|
5261
5654
|
}))
|
|
5262
5655
|
]);
|
|
5263
|
-
await Promise.all(islandDiscovery.islands.map((island) => write(
|
|
5656
|
+
await Promise.all(islandDiscovery.islands.map((island) => write(join11(srcDir, "generated", "islands", `${island.name}.astro`), islandWrapperTemplate(island))));
|
|
5657
|
+
await Promise.all(exampleDiscovery.examples.map((example) => write(join11(srcDir, "generated", "examples", `${exampleSlug(example.path)}.astro`), exampleWrapperTemplate(example))));
|
|
5264
5658
|
if (askEnabled) {
|
|
5265
|
-
await write(
|
|
5659
|
+
await write(join11(srcDir, "pages", "api", "ask.ts"), askEndpointTemplate(resolveAskBackend(config.ai.ask)));
|
|
5266
5660
|
}
|
|
5267
5661
|
await writeMcpFiles(project, mcp, write);
|
|
5268
5662
|
if (config.seo.og.enabled) {
|
|
5269
|
-
await write(
|
|
5663
|
+
await write(join11(srcDir, "pages", "og", "[...slug].png.ts"), ogEndpointTemplate(ogRoutes));
|
|
5270
5664
|
}
|
|
5271
5665
|
const hasChangelog = project.graph.pages.some((page) => page.contentType === "changelog" && !(page.meta.draft || page.meta.sidebar.hidden));
|
|
5272
5666
|
const changelogRouteTaken = project.graph.pages.some((page) => page.route === "/changelog");
|
|
5273
5667
|
if (hasChangelog && !changelogRouteTaken) {
|
|
5274
|
-
await write(
|
|
5668
|
+
await write(join11(srcDir, "pages", "changelog.astro"), changelogIndexTemplate({ askEnabled, exportEpub, exportPdf }));
|
|
5275
5669
|
}
|
|
5276
5670
|
await write(searchClientPath, searchClientTemplate(config));
|
|
5277
5671
|
if (servesStaticIndex(config.search.provider)) {
|
|
5278
5672
|
const documents = await buildSearchDocuments(project);
|
|
5279
|
-
await write(
|
|
5673
|
+
await write(join11(srcDir, "generated", "search.json"), `${JSON.stringify(documents)}
|
|
5280
5674
|
`);
|
|
5281
|
-
await write(
|
|
5675
|
+
await write(join11(srcDir, "pages", "blume-search.json.ts"), searchEndpointTemplate());
|
|
5282
5676
|
}
|
|
5283
5677
|
if (config.search.provider === "mixedbread") {
|
|
5284
|
-
await write(
|
|
5678
|
+
await write(join11(srcDir, "pages", "api", "search.ts"), mixedbreadSearchEndpointTemplate(config.search.mixedbread?.storeId ?? ""));
|
|
5285
5679
|
}
|
|
5286
5680
|
const rawMarkdown = await buildRawMarkdown(project);
|
|
5287
5681
|
await Promise.all([
|
|
5288
|
-
write(
|
|
5682
|
+
write(join11(srcDir, "generated", "raw-markdown.json"), `${JSON.stringify(rawMarkdown)}
|
|
5289
5683
|
`),
|
|
5290
|
-
write(
|
|
5291
|
-
write(
|
|
5684
|
+
write(join11(srcDir, "pages", "[...slug].md.ts"), rawMarkdownEndpointTemplate()),
|
|
5685
|
+
write(join11(srcDir, "pages", "[...slug].mdx.ts"), rawMarkdownEndpointTemplate())
|
|
5292
5686
|
]);
|
|
5293
5687
|
const feeds = buildRssFeeds(project);
|
|
5294
5688
|
if (feeds.length > 0) {
|
|
5295
5689
|
const feedXml = Object.fromEntries(feeds.map((feed) => [feed.type, renderRssFeed(feed)]));
|
|
5296
5690
|
await Promise.all([
|
|
5297
|
-
write(
|
|
5691
|
+
write(join11(srcDir, "generated", "rss.json"), `${JSON.stringify(feedXml)}
|
|
5298
5692
|
`),
|
|
5299
|
-
write(
|
|
5693
|
+
write(join11(srcDir, "pages", "[section]", "rss.xml.ts"), rssEndpointTemplate())
|
|
5300
5694
|
]);
|
|
5301
5695
|
}
|
|
5302
|
-
const warnings = [
|
|
5696
|
+
const warnings = [
|
|
5697
|
+
...depsLinkWarning ? [depsLinkWarning] : [],
|
|
5698
|
+
...mcp.warnings,
|
|
5699
|
+
...islandDiscovery.warnings,
|
|
5700
|
+
...exampleDiscovery.warnings
|
|
5701
|
+
];
|
|
5303
5702
|
for (const dep of searchProviderMeta(config.search.provider).runtimeDeps) {
|
|
5304
5703
|
if (!canResolveFrom(context.root, dep)) {
|
|
5305
5704
|
warnings.push(`Search provider "${config.search.provider}" needs "${dep}", which isn't installed. Run \`npm install ${dep}\` (or your package manager's equivalent).`);
|
|
5306
5705
|
}
|
|
5307
5706
|
}
|
|
5308
|
-
warnings.push(...islandFrameworkWarnings(
|
|
5707
|
+
warnings.push(...islandFrameworkWarnings(frameworks, context.root));
|
|
5309
5708
|
if (hasReferences(config)) {
|
|
5310
5709
|
const references = await buildReferenceFiles({
|
|
5311
5710
|
config,
|
|
@@ -5313,10 +5712,10 @@ var generateRuntime = async (project) => {
|
|
|
5313
5712
|
root: context.root
|
|
5314
5713
|
});
|
|
5315
5714
|
warnings.push(...references.warnings);
|
|
5316
|
-
await Promise.all(references.files.map((file) => write(
|
|
5715
|
+
await Promise.all(references.files.map((file) => write(join11(srcDir, "pages", file.pagePath), file.content)));
|
|
5317
5716
|
}
|
|
5318
|
-
await write(
|
|
5319
|
-
await write(
|
|
5717
|
+
await write(join11(srcDir, "generated", "data.json"), buildRuntimeData(project));
|
|
5718
|
+
await write(join11(out, "blume.manifest.json"), `${JSON.stringify(project.manifest, null, 2)}
|
|
5320
5719
|
`);
|
|
5321
5720
|
await writeStagedContent(out, staged);
|
|
5322
5721
|
await pruneOrphans(srcDir, written);
|
|
@@ -5324,13 +5723,13 @@ var generateRuntime = async (project) => {
|
|
|
5324
5723
|
};
|
|
5325
5724
|
|
|
5326
5725
|
// src/core/bridge.ts
|
|
5327
|
-
import { existsSync as
|
|
5328
|
-
import { readFile as
|
|
5329
|
-
import { join as
|
|
5726
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
5727
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
5728
|
+
import { join as join12 } from "pathe";
|
|
5330
5729
|
|
|
5331
5730
|
// src/migrate/mintlify/config.ts
|
|
5332
|
-
import { readFile as
|
|
5333
|
-
import { dirname as
|
|
5731
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
5732
|
+
import { dirname as dirname7, relative as relative6, resolve as resolve3 } from "pathe";
|
|
5334
5733
|
var MINTLIFY_DEFAULT_IGNORES = [
|
|
5335
5734
|
"**/_*",
|
|
5336
5735
|
"**/.*",
|
|
@@ -5366,12 +5765,12 @@ var asDirectoryMode = (value) => value === "accordion" || value === "card" || va
|
|
|
5366
5765
|
var withoutUndefined = (value) => Object.fromEntries(Object.entries(value).filter(([, item]) => item !== undefined));
|
|
5367
5766
|
var hasOwn = (object, key) => Object.hasOwn(object, key);
|
|
5368
5767
|
var isInsideRoot = (root, candidate) => {
|
|
5369
|
-
const rel =
|
|
5768
|
+
const rel = relative6(root, candidate);
|
|
5370
5769
|
return rel === "" || !rel.startsWith("..") && !rel.startsWith("/");
|
|
5371
5770
|
};
|
|
5372
5771
|
var readJsonFile = async (file) => {
|
|
5373
5772
|
try {
|
|
5374
|
-
return JSON.parse(await
|
|
5773
|
+
return JSON.parse(await readFile8(file, "utf-8"));
|
|
5375
5774
|
} catch (error) {
|
|
5376
5775
|
throw new BlumeError({
|
|
5377
5776
|
code: "BLUME_MINTLIFY_CONFIG_INVALID",
|
|
@@ -5391,7 +5790,7 @@ var resolveRefs = async (value, options) => {
|
|
|
5391
5790
|
}
|
|
5392
5791
|
const ref = asString(object.$ref);
|
|
5393
5792
|
if (ref) {
|
|
5394
|
-
const refFile =
|
|
5793
|
+
const refFile = resolve3(dirname7(options.file), ref);
|
|
5395
5794
|
if (!isInsideRoot(options.root, refFile)) {
|
|
5396
5795
|
throw new BlumeError({
|
|
5397
5796
|
code: "BLUME_MINTLIFY_REF_OUTSIDE_ROOT",
|
|
@@ -5791,7 +6190,7 @@ var mintlifyNavbar = (value) => {
|
|
|
5791
6190
|
};
|
|
5792
6191
|
var mintignorePatterns = async (root) => {
|
|
5793
6192
|
try {
|
|
5794
|
-
const raw = await
|
|
6193
|
+
const raw = await readFile8(resolve3(root, ".mintignore"), "utf-8");
|
|
5795
6194
|
return raw.split(`
|
|
5796
6195
|
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).filter((line) => !line.startsWith("!")).map((line) => line.endsWith("/") ? `${line}**` : line);
|
|
5797
6196
|
} catch {
|
|
@@ -6015,8 +6414,8 @@ var mintlifyIcons = (value) => {
|
|
|
6015
6414
|
});
|
|
6016
6415
|
};
|
|
6017
6416
|
var loadMintlifyConfig = async (root, file) => {
|
|
6018
|
-
const projectRoot =
|
|
6019
|
-
const configFile =
|
|
6417
|
+
const projectRoot = resolve3(root);
|
|
6418
|
+
const configFile = resolve3(file);
|
|
6020
6419
|
const spec = asObject(await resolveRefs(await readJsonFile(configFile), {
|
|
6021
6420
|
file: configFile,
|
|
6022
6421
|
root: projectRoot,
|
|
@@ -6117,12 +6516,12 @@ var mintlifyI18n = (spec) => {
|
|
|
6117
6516
|
// src/core/bridge.ts
|
|
6118
6517
|
var MINTLIFY_CONFIG_FILES = ["docs.json", "mint.json"];
|
|
6119
6518
|
var detectMintlifyBridge = async (root) => {
|
|
6120
|
-
const configFile = MINTLIFY_CONFIG_FILES.map((name) =>
|
|
6519
|
+
const configFile = MINTLIFY_CONFIG_FILES.map((name) => join12(root, name)).find((candidate) => existsSync6(candidate));
|
|
6121
6520
|
if (!configFile) {
|
|
6122
6521
|
return null;
|
|
6123
6522
|
}
|
|
6124
6523
|
const config = await loadMintlifyConfig(root, configFile);
|
|
6125
|
-
const spec = JSON.parse(await
|
|
6524
|
+
const spec = JSON.parse(await readFile9(configFile, "utf-8"));
|
|
6126
6525
|
const i18n = mintlifyI18n(spec);
|
|
6127
6526
|
if (i18n) {
|
|
6128
6527
|
config.i18n = i18n;
|
|
@@ -6206,8 +6605,8 @@ var createModuleLoader = () => {
|
|
|
6206
6605
|
};
|
|
6207
6606
|
|
|
6208
6607
|
// src/core/project.ts
|
|
6209
|
-
import { existsSync as
|
|
6210
|
-
import { isAbsolute as
|
|
6608
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
6609
|
+
import { isAbsolute as isAbsolute3, join as join13, resolve as resolve4 } from "pathe";
|
|
6211
6610
|
var CONFIG_FILENAMES = [
|
|
6212
6611
|
"blume.config.ts",
|
|
6213
6612
|
"blume.config.mjs",
|
|
@@ -6217,8 +6616,8 @@ var THEME_FILENAMES = ["theme.css"];
|
|
|
6217
6616
|
var COMPONENTS_FILENAMES = ["components.tsx", "components.ts"];
|
|
6218
6617
|
var firstExisting = (root, names) => {
|
|
6219
6618
|
for (const name of names) {
|
|
6220
|
-
const candidate =
|
|
6221
|
-
if (
|
|
6619
|
+
const candidate = join13(root, name);
|
|
6620
|
+
if (existsSync7(candidate)) {
|
|
6222
6621
|
return candidate;
|
|
6223
6622
|
}
|
|
6224
6623
|
}
|
|
@@ -6226,15 +6625,15 @@ var firstExisting = (root, names) => {
|
|
|
6226
6625
|
};
|
|
6227
6626
|
var findConfigFile = (root) => firstExisting(root, CONFIG_FILENAMES);
|
|
6228
6627
|
var resolveProjectContext = (root, config) => {
|
|
6229
|
-
const absoluteRoot =
|
|
6230
|
-
const contentRoot =
|
|
6231
|
-
const pagesPath =
|
|
6232
|
-
const pagesRoot =
|
|
6628
|
+
const absoluteRoot = resolve4(root);
|
|
6629
|
+
const contentRoot = isAbsolute3(config.content.root) ? config.content.root : join13(absoluteRoot, config.content.root);
|
|
6630
|
+
const pagesPath = join13(absoluteRoot, config.content.pages);
|
|
6631
|
+
const pagesRoot = existsSync7(pagesPath) ? pagesPath : null;
|
|
6233
6632
|
return {
|
|
6234
6633
|
componentsFile: firstExisting(absoluteRoot, COMPONENTS_FILENAMES),
|
|
6235
6634
|
configFile: findConfigFile(absoluteRoot),
|
|
6236
6635
|
contentRoot,
|
|
6237
|
-
outDir:
|
|
6636
|
+
outDir: join13(absoluteRoot, ".blume"),
|
|
6238
6637
|
pagesRoot,
|
|
6239
6638
|
root: absoluteRoot,
|
|
6240
6639
|
themeFile: firstExisting(absoluteRoot, THEME_FILENAMES)
|
|
@@ -6772,6 +7171,7 @@ var blumeConfigSchema = z2.object({
|
|
|
6772
7171
|
contextual: contextualConfigSchema.default({}),
|
|
6773
7172
|
deployment: deploymentConfigSchema.default({}),
|
|
6774
7173
|
description: z2.string().optional(),
|
|
7174
|
+
examples: z2.string().default("examples"),
|
|
6775
7175
|
export: exportConfigSchema.default(false),
|
|
6776
7176
|
favicon: faviconConfigSchema.optional(),
|
|
6777
7177
|
feedback: z2.boolean().default(true),
|
|
@@ -7183,7 +7583,7 @@ var buildContentGraph = (pages, options) => {
|
|
|
7183
7583
|
|
|
7184
7584
|
// src/core/last-modified.ts
|
|
7185
7585
|
import { execFileSync } from "node:child_process";
|
|
7186
|
-
import { relative as
|
|
7586
|
+
import { relative as relative7 } from "pathe";
|
|
7187
7587
|
var resolveLastModifiedConfig = (value) => {
|
|
7188
7588
|
if (value === false) {
|
|
7189
7589
|
return { enabled: false, source: "git" };
|
|
@@ -7223,7 +7623,7 @@ var gitLastModifiedTimes = (root, contentRoot, sourcePaths) => {
|
|
|
7223
7623
|
const byRepoPath = parseGitLog(output);
|
|
7224
7624
|
const result = new Map;
|
|
7225
7625
|
for (const sourcePath of sourcePaths) {
|
|
7226
|
-
const iso = byRepoPath.get(
|
|
7626
|
+
const iso = byRepoPath.get(relative7(gitRoot, sourcePath));
|
|
7227
7627
|
if (iso) {
|
|
7228
7628
|
result.set(sourcePath, iso);
|
|
7229
7629
|
}
|
|
@@ -7235,8 +7635,8 @@ var gitLastModifiedTimes = (root, contentRoot, sourcePaths) => {
|
|
|
7235
7635
|
};
|
|
7236
7636
|
|
|
7237
7637
|
// src/core/meta.ts
|
|
7238
|
-
import { basename as
|
|
7239
|
-
import { glob as
|
|
7638
|
+
import { basename as basename3, dirname as dirname8, relative as relative8 } from "pathe";
|
|
7639
|
+
import { glob as glob5 } from "tinyglobby";
|
|
7240
7640
|
var META_FILES = [
|
|
7241
7641
|
"**/meta.ts",
|
|
7242
7642
|
"**/meta.js",
|
|
@@ -7247,16 +7647,16 @@ var META_FILES = [
|
|
|
7247
7647
|
];
|
|
7248
7648
|
var resolveMeta = async (mod) => typeof mod === "function" ? await mod() : mod;
|
|
7249
7649
|
var discoverFolderMeta = async (contentRoot) => {
|
|
7250
|
-
const files = await
|
|
7650
|
+
const files = await glob5(META_FILES, {
|
|
7251
7651
|
absolute: true,
|
|
7252
7652
|
cwd: contentRoot,
|
|
7253
7653
|
ignore: ["**/node_modules/**", "**/.blume/**", "**/dist/**"],
|
|
7254
7654
|
onlyFiles: true
|
|
7255
7655
|
});
|
|
7256
|
-
const
|
|
7656
|
+
const load2 = createModuleLoader();
|
|
7257
7657
|
const loaded = await Promise.all(files.map(async (file) => {
|
|
7258
7658
|
try {
|
|
7259
|
-
return { file, ok: true, value: await resolveMeta(await
|
|
7659
|
+
return { file, ok: true, value: await resolveMeta(await load2(file)) };
|
|
7260
7660
|
} catch (error) {
|
|
7261
7661
|
return { error, file, ok: false };
|
|
7262
7662
|
}
|
|
@@ -7265,7 +7665,7 @@ var discoverFolderMeta = async (contentRoot) => {
|
|
|
7265
7665
|
const shared = new Map;
|
|
7266
7666
|
const diagnostics = [];
|
|
7267
7667
|
for (const entry of loaded) {
|
|
7268
|
-
const dir =
|
|
7668
|
+
const dir = relative8(contentRoot, dirname8(entry.file));
|
|
7269
7669
|
if (!entry.ok) {
|
|
7270
7670
|
diagnostics.push({
|
|
7271
7671
|
code: "BLUME_META_LOAD_FAILED",
|
|
@@ -7277,7 +7677,7 @@ var discoverFolderMeta = async (contentRoot) => {
|
|
|
7277
7677
|
}
|
|
7278
7678
|
const result = folderMetaSchema.safeParse(entry.value);
|
|
7279
7679
|
if (result.success) {
|
|
7280
|
-
const target =
|
|
7680
|
+
const target = basename3(entry.file).startsWith("meta.$.") ? shared : meta;
|
|
7281
7681
|
target.set(dir, result.data);
|
|
7282
7682
|
} else {
|
|
7283
7683
|
diagnostics.push(...diagnosticsFromZod(result.error, {
|
|
@@ -7290,6 +7690,7 @@ var discoverFolderMeta = async (contentRoot) => {
|
|
|
7290
7690
|
};
|
|
7291
7691
|
|
|
7292
7692
|
// src/core/sources/normalize.ts
|
|
7693
|
+
import GithubSlugger from "github-slugger";
|
|
7293
7694
|
import { extname as extname3 } from "pathe";
|
|
7294
7695
|
var NUMERIC_PREFIX2 = /^\d+[-_.]/u;
|
|
7295
7696
|
var GROUP_FOLDER2 = /^\((?<label>.+)\)$/u;
|
|
@@ -7322,6 +7723,7 @@ var CODE_FENCE2 = /^```/u;
|
|
|
7322
7723
|
var ATX_HEADING = /^(?<hashes>#{1,6})\s+(?<text>.+?)\s*#*$/u;
|
|
7323
7724
|
var extractHeadings = (body) => {
|
|
7324
7725
|
const headings = [];
|
|
7726
|
+
const slugger = new GithubSlugger;
|
|
7325
7727
|
let inFence = false;
|
|
7326
7728
|
for (const line of body.split(`
|
|
7327
7729
|
`)) {
|
|
@@ -7336,7 +7738,7 @@ var extractHeadings = (body) => {
|
|
|
7336
7738
|
if (match?.groups) {
|
|
7337
7739
|
const depth = match.groups.hashes?.length ?? 1;
|
|
7338
7740
|
const text = (match.groups.text ?? "").trim();
|
|
7339
|
-
headings.push({ depth, slug:
|
|
7741
|
+
headings.push({ depth, slug: slugger.slug(text), text });
|
|
7340
7742
|
}
|
|
7341
7743
|
}
|
|
7342
7744
|
return headings;
|
|
@@ -7433,18 +7835,17 @@ var normalizeEntry = (entry, ctx) => {
|
|
|
7433
7835
|
};
|
|
7434
7836
|
|
|
7435
7837
|
// src/core/sources/resolve.ts
|
|
7436
|
-
import { join as
|
|
7838
|
+
import { join as join22 } from "pathe";
|
|
7437
7839
|
|
|
7438
7840
|
// src/core/sources/filesystem.ts
|
|
7439
|
-
import { existsSync as
|
|
7440
|
-
import { readFile as
|
|
7441
|
-
import
|
|
7442
|
-
import {
|
|
7443
|
-
import { glob as glob5 } from "tinyglobby";
|
|
7841
|
+
import { existsSync as existsSync8, watch as fsWatch } from "node:fs";
|
|
7842
|
+
import { readFile as readFile10 } from "node:fs/promises";
|
|
7843
|
+
import { extname as extname4, isAbsolute as isAbsolute4, join as join14, relative as relative9, resolve as resolve5 } from "pathe";
|
|
7844
|
+
import { glob as glob6 } from "tinyglobby";
|
|
7444
7845
|
var filesystemSource = (options) => {
|
|
7445
|
-
const contentRoot =
|
|
7446
|
-
const
|
|
7447
|
-
const files = await
|
|
7846
|
+
const contentRoot = isAbsolute4(options.root) ? options.root : join14(resolve5(options.projectRoot), options.root);
|
|
7847
|
+
const load2 = async () => {
|
|
7848
|
+
const files = await glob6(options.include, {
|
|
7448
7849
|
absolute: true,
|
|
7449
7850
|
cwd: contentRoot,
|
|
7450
7851
|
ignore: options.exclude,
|
|
@@ -7452,21 +7853,21 @@ var filesystemSource = (options) => {
|
|
|
7452
7853
|
});
|
|
7453
7854
|
files.sort();
|
|
7454
7855
|
const entries = await Promise.all(files.map(async (file) => {
|
|
7455
|
-
const source = await
|
|
7856
|
+
const source = await readFile10(file, "utf-8");
|
|
7456
7857
|
const ext = extname4(file).toLowerCase();
|
|
7457
7858
|
const format = ext === ".mdx" ? "mdx" : "md";
|
|
7458
|
-
const parsed =
|
|
7859
|
+
const parsed = frontmatter_default(source);
|
|
7459
7860
|
return {
|
|
7460
7861
|
body: { format, text: parsed.content },
|
|
7461
7862
|
data: parsed.data,
|
|
7462
|
-
ref:
|
|
7863
|
+
ref: relative9(contentRoot, file),
|
|
7463
7864
|
sourcePath: file
|
|
7464
7865
|
};
|
|
7465
7866
|
}));
|
|
7466
7867
|
return { diagnostics: [], entries };
|
|
7467
7868
|
};
|
|
7468
7869
|
const validate = () => {
|
|
7469
|
-
if (!
|
|
7870
|
+
if (!existsSync8(contentRoot)) {
|
|
7470
7871
|
throw new BlumeError({
|
|
7471
7872
|
code: options.missingCode ?? "BLUME_CONTENT_ROOT_MISSING",
|
|
7472
7873
|
file: contentRoot,
|
|
@@ -7477,7 +7878,7 @@ var filesystemSource = (options) => {
|
|
|
7477
7878
|
}
|
|
7478
7879
|
};
|
|
7479
7880
|
const watch = (onChange) => {
|
|
7480
|
-
if (!
|
|
7881
|
+
if (!existsSync8(contentRoot)) {
|
|
7481
7882
|
return () => {};
|
|
7482
7883
|
}
|
|
7483
7884
|
const watcher = fsWatch(contentRoot, { recursive: true }, onChange);
|
|
@@ -7485,22 +7886,19 @@ var filesystemSource = (options) => {
|
|
|
7485
7886
|
};
|
|
7486
7887
|
return {
|
|
7487
7888
|
contentRoot,
|
|
7488
|
-
load,
|
|
7889
|
+
load: load2,
|
|
7489
7890
|
name: options.name,
|
|
7490
7891
|
prefix: options.prefix,
|
|
7491
|
-
read: (ref) =>
|
|
7892
|
+
read: (ref) => readFile10(join14(contentRoot, ref), "utf-8"),
|
|
7492
7893
|
staged: false,
|
|
7493
7894
|
validate,
|
|
7494
7895
|
watch
|
|
7495
7896
|
};
|
|
7496
7897
|
};
|
|
7497
7898
|
|
|
7498
|
-
// src/core/sources/mdx-remote.ts
|
|
7499
|
-
import matter4 from "gray-matter";
|
|
7500
|
-
|
|
7501
7899
|
// src/core/sources/cache.ts
|
|
7502
|
-
import { mkdir as mkdir3, readFile as
|
|
7503
|
-
import { join as
|
|
7900
|
+
import { mkdir as mkdir3, readFile as readFile11, writeFile as writeFile3 } from "node:fs/promises";
|
|
7901
|
+
import { join as join15 } from "pathe";
|
|
7504
7902
|
var hashText = (text) => {
|
|
7505
7903
|
let hash = 5381;
|
|
7506
7904
|
for (let i = 0;i < text.length; i += 1) {
|
|
@@ -7509,11 +7907,11 @@ var hashText = (text) => {
|
|
|
7509
7907
|
return hash.toString(36);
|
|
7510
7908
|
};
|
|
7511
7909
|
var entriesDigest = (entries) => hashText(entries.map((entry) => `${entry.ref}:${entry.hash ?? hashText(entry.body.text)}`).join("|"));
|
|
7512
|
-
var pollingWatch = (
|
|
7910
|
+
var pollingWatch = (load2, intervalSeconds) => (onChange) => {
|
|
7513
7911
|
let last = "";
|
|
7514
7912
|
const tick = async () => {
|
|
7515
7913
|
try {
|
|
7516
|
-
const { entries } = await
|
|
7914
|
+
const { entries } = await load2();
|
|
7517
7915
|
const next = entriesDigest(entries);
|
|
7518
7916
|
if (last && next !== last) {
|
|
7519
7917
|
onChange();
|
|
@@ -7527,11 +7925,11 @@ var pollingWatch = (load, intervalSeconds) => (onChange) => {
|
|
|
7527
7925
|
return () => clearInterval(timer);
|
|
7528
7926
|
};
|
|
7529
7927
|
var snapshotCache = (cacheDir) => {
|
|
7530
|
-
const file =
|
|
7928
|
+
const file = join15(cacheDir, "entries.json");
|
|
7531
7929
|
return {
|
|
7532
7930
|
read: async () => {
|
|
7533
7931
|
try {
|
|
7534
|
-
return JSON.parse(await
|
|
7932
|
+
return JSON.parse(await readFile11(file, "utf-8"));
|
|
7535
7933
|
} catch {
|
|
7536
7934
|
return [];
|
|
7537
7935
|
}
|
|
@@ -7663,7 +8061,7 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
7663
8061
|
throw new Error(`${item.fetchUrl} -> ${res.status}`);
|
|
7664
8062
|
}
|
|
7665
8063
|
const text = await res.text();
|
|
7666
|
-
const parsed =
|
|
8064
|
+
const parsed = frontmatter_default(text);
|
|
7667
8065
|
const format = item.ref.toLowerCase().endsWith(".mdx") ? "mdx" : "md";
|
|
7668
8066
|
return {
|
|
7669
8067
|
body: { format, text: parsed.content },
|
|
@@ -7674,7 +8072,7 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
7674
8072
|
ref: item.ref
|
|
7675
8073
|
};
|
|
7676
8074
|
};
|
|
7677
|
-
const
|
|
8075
|
+
const load2 = async () => {
|
|
7678
8076
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
7679
8077
|
const refs = await enumerate();
|
|
7680
8078
|
return await Promise.all(refs.map(fetchEntry));
|
|
@@ -7692,35 +8090,91 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
7692
8090
|
return entry?.raw ?? entry?.body.text ?? "";
|
|
7693
8091
|
};
|
|
7694
8092
|
return {
|
|
7695
|
-
load,
|
|
8093
|
+
load: load2,
|
|
7696
8094
|
name: options.name,
|
|
7697
8095
|
prefix: options.prefix,
|
|
7698
8096
|
read,
|
|
7699
8097
|
staged: true,
|
|
7700
|
-
watch: options.pollInterval ? pollingWatch(
|
|
8098
|
+
watch: options.pollInterval ? pollingWatch(load2, options.pollInterval) : undefined
|
|
7701
8099
|
};
|
|
7702
8100
|
};
|
|
7703
8101
|
|
|
7704
8102
|
// 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";
|
|
8103
|
+
import { existsSync as existsSync10, watch as fsWatch2 } from "node:fs";
|
|
8104
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
8105
|
+
import { isAbsolute as isAbsolute5, join as join18, relative as relative12, resolve as resolve7 } from "pathe";
|
|
8106
|
+
import { glob as glob7 } from "tinyglobby";
|
|
7713
8107
|
|
|
7714
8108
|
// src/migrate/shared.ts
|
|
7715
|
-
import {
|
|
7716
|
-
import {
|
|
8109
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
8110
|
+
import { readFile as readFile12, writeFile as writeFile4 } from "node:fs/promises";
|
|
8111
|
+
import { join as join16 } from "pathe";
|
|
7717
8112
|
var writeBlumeConfig = async (root, config) => {
|
|
7718
8113
|
const body = `import { defineConfig } from "blume";
|
|
7719
8114
|
|
|
7720
8115
|
export default defineConfig(${JSON.stringify(config, null, 2)});
|
|
7721
8116
|
`;
|
|
7722
|
-
await writeFile4(
|
|
8117
|
+
await writeFile4(join16(root, "blume.config.ts"), body, "utf-8");
|
|
8118
|
+
};
|
|
8119
|
+
var BLUME_SCRIPTS = {
|
|
8120
|
+
build: "blume build",
|
|
8121
|
+
dev: "blume dev",
|
|
8122
|
+
start: "blume preview"
|
|
8123
|
+
};
|
|
8124
|
+
var rewriteFrameworkScripts = async (root, cli, remove) => {
|
|
8125
|
+
const pkgPath = join16(root, "package.json");
|
|
8126
|
+
if (!existsSync9(pkgPath)) {
|
|
8127
|
+
return false;
|
|
8128
|
+
}
|
|
8129
|
+
let pkg;
|
|
8130
|
+
try {
|
|
8131
|
+
pkg = JSON.parse(await readFile12(pkgPath, "utf-8"));
|
|
8132
|
+
} catch {
|
|
8133
|
+
return false;
|
|
8134
|
+
}
|
|
8135
|
+
const { scripts } = pkg;
|
|
8136
|
+
if (!scripts || typeof scripts !== "object") {
|
|
8137
|
+
return false;
|
|
8138
|
+
}
|
|
8139
|
+
const next = {};
|
|
8140
|
+
let changed = false;
|
|
8141
|
+
for (const [name, command] of Object.entries(scripts)) {
|
|
8142
|
+
const blume = BLUME_SCRIPTS[name];
|
|
8143
|
+
if (typeof command === "string" && remove?.test(command)) {
|
|
8144
|
+
changed = true;
|
|
8145
|
+
} else if (typeof command === "string" && blume && cli.test(command) && command !== blume) {
|
|
8146
|
+
next[name] = blume;
|
|
8147
|
+
changed = true;
|
|
8148
|
+
} else {
|
|
8149
|
+
next[name] = command;
|
|
8150
|
+
}
|
|
8151
|
+
}
|
|
8152
|
+
if (changed) {
|
|
8153
|
+
pkg.scripts = next;
|
|
8154
|
+
await writeFile4(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
8155
|
+
`, "utf-8");
|
|
8156
|
+
}
|
|
8157
|
+
return changed;
|
|
7723
8158
|
};
|
|
8159
|
+
var gitignoreKey = (line) => line.trim().replace(/\/+$/u, "");
|
|
8160
|
+
var ensureGitignore = async (root, entries) => {
|
|
8161
|
+
const path = join16(root, ".gitignore");
|
|
8162
|
+
const existing = existsSync9(path) ? await readFile12(path, "utf-8") : "";
|
|
8163
|
+
const present = new Set(existing.split(`
|
|
8164
|
+
`).map(gitignoreKey).filter(Boolean));
|
|
8165
|
+
const added = entries.filter((entry) => !present.has(gitignoreKey(entry)));
|
|
8166
|
+
if (added.length === 0) {
|
|
8167
|
+
return [];
|
|
8168
|
+
}
|
|
8169
|
+
const gap = existing.length > 0 && !existing.endsWith(`
|
|
8170
|
+
`) ? `
|
|
8171
|
+
` : "";
|
|
8172
|
+
await writeFile4(path, `${existing}${gap}${added.join(`
|
|
8173
|
+
`)}
|
|
8174
|
+
`, "utf-8");
|
|
8175
|
+
return added;
|
|
8176
|
+
};
|
|
8177
|
+
var leftoverFiles = (root, candidates) => candidates.filter((candidate) => existsSync9(join16(root, candidate)));
|
|
7724
8178
|
var attribute = (attrs, name) => {
|
|
7725
8179
|
const match = attrs.match(new RegExp(`\\b${name}=(?:"(?<dq>[^"]*)"|'(?<sq>[^']*)')`, "u"));
|
|
7726
8180
|
return match?.groups?.dq ?? match?.groups?.sq;
|
|
@@ -8117,7 +8571,7 @@ var isLiteralObject = (value) => typeof value === "object" && value !== null &&
|
|
|
8117
8571
|
var asLiteralArray = (value) => Array.isArray(value) ? value : undefined;
|
|
8118
8572
|
|
|
8119
8573
|
// src/migrate/mintlify/content.ts
|
|
8120
|
-
import { dirname as
|
|
8574
|
+
import { dirname as dirname9, join as join17, relative as relative10 } from "pathe";
|
|
8121
8575
|
var CALLOUT_DIRECTIVES = {
|
|
8122
8576
|
Check: "success",
|
|
8123
8577
|
Danger: "danger",
|
|
@@ -8153,9 +8607,9 @@ var rewriteSnippetImports = (source, options) => {
|
|
|
8153
8607
|
if (/\.mdx?$/u.test(importSource)) {
|
|
8154
8608
|
return "";
|
|
8155
8609
|
}
|
|
8156
|
-
const target =
|
|
8610
|
+
const target = join17(options.root, importSource.replace(/^\/+/u, ""));
|
|
8157
8611
|
components.push(importSource.replace(/^\/+/u, ""));
|
|
8158
|
-
let rel =
|
|
8612
|
+
let rel = relative10(dirname9(options.filePath), target);
|
|
8159
8613
|
if (!rel.startsWith(".")) {
|
|
8160
8614
|
rel = `./${rel}`;
|
|
8161
8615
|
}
|
|
@@ -8345,8 +8799,7 @@ var rewriteMintlifySvgIconProps = (source) => {
|
|
|
8345
8799
|
|
|
8346
8800
|
// src/migrate/mintlify/snippets.ts
|
|
8347
8801
|
import { readFile as readFileFromDisk } from "node:fs/promises";
|
|
8348
|
-
import
|
|
8349
|
-
import { dirname as dirname9, relative as relative10, resolve as resolve5 } from "pathe";
|
|
8802
|
+
import { dirname as dirname10, relative as relative11, resolve as resolve6 } from "pathe";
|
|
8350
8803
|
var MARKDOWN_SNIPPET_IMPORT = /^import\s+(?<name>[$A-Z_a-z][$\w]*)\s+from\s+["'](?<source>[^"']+\.mdx?)["'];?\s*$/gmu;
|
|
8351
8804
|
var NAMED_SNIPPET_IMPORT = /^import\s+\{(?<names>[^}]+)\}\s+from\s+["'](?<source>[^"']+\.mdx?)["'];?\s*$/gmu;
|
|
8352
8805
|
var EXPORTED_STRING_CONST = /^export\s+const\s+(?<name>[$A-Z_a-z][$\w]*)\s*=\s*(?:"(?<double>(?:\\.|[^"\\])*)"|'(?<single>(?:\\.|[^'\\])*)'|`(?<template>(?:\\.|[^`\\])*)`)\s*;?\s*$/gmu;
|
|
@@ -8356,14 +8809,14 @@ var GLOBAL_VARIABLE = /\{\{\s*(?<name>[A-Za-z0-9-]+)\s*\}\}/gu;
|
|
|
8356
8809
|
var FRONTMATTER_BLOCK = /^---\r?\n[\s\S]*?\r?\n---\r?\n?/u;
|
|
8357
8810
|
var USER_EXPORT = /^(?:export\s+)?(?:const|let|var)\s+user\s*=|^import\s+\{\s*user\s*\}/mu;
|
|
8358
8811
|
var isInsideRoot2 = (root, candidate) => {
|
|
8359
|
-
const rel =
|
|
8812
|
+
const rel = relative11(root, candidate);
|
|
8360
8813
|
return rel === "" || !rel.startsWith("..") && !rel.startsWith("/");
|
|
8361
8814
|
};
|
|
8362
8815
|
var escapeRegExp = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
8363
8816
|
var snippetSelfClosingTagPattern = (name) => new RegExp(`<${escapeRegExp(name)}(?<attrs>[^>]*?)\\s*/>`, "gu");
|
|
8364
8817
|
var snippetPairedTagPattern = (name) => new RegExp(`<${escapeRegExp(name)}(?<attrs>[^>]*?)>[\\s\\S]*?</${escapeRegExp(name)}>`, "gu");
|
|
8365
8818
|
var rootRelativePath = (root, file) => {
|
|
8366
|
-
const rel =
|
|
8819
|
+
const rel = relative11(root, file);
|
|
8367
8820
|
return rel ? `/${rel}` : "/";
|
|
8368
8821
|
};
|
|
8369
8822
|
var snippetCycleMessage = (root, file, trail) => {
|
|
@@ -8372,7 +8825,7 @@ var snippetCycleMessage = (root, file, trail) => {
|
|
|
8372
8825
|
return `Circular Mintlify snippet import detected: ${cycle}`;
|
|
8373
8826
|
};
|
|
8374
8827
|
var resolveSnippetPath = (options) => {
|
|
8375
|
-
const target = options.source.startsWith("/") ?
|
|
8828
|
+
const target = options.source.startsWith("/") ? resolve6(options.root, options.source.slice(1)) : resolve6(dirname10(options.filePath), options.source);
|
|
8376
8829
|
return isInsideRoot2(options.root, target) ? target : null;
|
|
8377
8830
|
};
|
|
8378
8831
|
var collectImports = (source) => [...source.matchAll(MARKDOWN_SNIPPET_IMPORT)].flatMap((match) => {
|
|
@@ -8435,10 +8888,10 @@ var rewriteMintlifyMarkdownSnippets = async (source, options) => {
|
|
|
8435
8888
|
throw new Error(snippetCycleMessage(options.root, file, options.trail ?? []));
|
|
8436
8889
|
}
|
|
8437
8890
|
seen.add(file);
|
|
8438
|
-
const
|
|
8891
|
+
const readFile13 = options.readFile ?? readFileFromDisk;
|
|
8439
8892
|
try {
|
|
8440
|
-
const raw = await
|
|
8441
|
-
const content =
|
|
8893
|
+
const raw = await readFile13(file);
|
|
8894
|
+
const content = frontmatter_default(raw).content.trim();
|
|
8442
8895
|
const transformed = await rewriteMintlifyMarkdownSnippets(content, {
|
|
8443
8896
|
...options,
|
|
8444
8897
|
filePath: file,
|
|
@@ -8478,7 +8931,7 @@ var rewriteMintlifyMarkdownSnippets = async (source, options) => {
|
|
|
8478
8931
|
return await inlineAt(0, source);
|
|
8479
8932
|
};
|
|
8480
8933
|
var rewriteMintlifySnippetVariables = async (source, options) => {
|
|
8481
|
-
const
|
|
8934
|
+
const readFile13 = options.readFile ?? readFileFromDisk;
|
|
8482
8935
|
const inlineImport = async (current, variableImport) => {
|
|
8483
8936
|
const file = resolveSnippetPath({
|
|
8484
8937
|
filePath: options.filePath,
|
|
@@ -8488,7 +8941,7 @@ var rewriteMintlifySnippetVariables = async (source, options) => {
|
|
|
8488
8941
|
if (!file) {
|
|
8489
8942
|
return current;
|
|
8490
8943
|
}
|
|
8491
|
-
const exports = collectStringExports(
|
|
8944
|
+
const exports = collectStringExports(frontmatter_default(await readFile13(file)).content);
|
|
8492
8945
|
let next = current;
|
|
8493
8946
|
for (const name of variableImport.names) {
|
|
8494
8947
|
const value = exports.get(name.imported);
|
|
@@ -8544,10 +8997,10 @@ var transformMintlifyContent = async (raw, options) => {
|
|
|
8544
8997
|
text = rewriteMintlifyExampleBlocks(text);
|
|
8545
8998
|
text = rewriteMintlifyCallouts(text);
|
|
8546
8999
|
const unsupported = unsupportedMintlifyComponents(text);
|
|
8547
|
-
const parsed =
|
|
9000
|
+
const parsed = frontmatter_default(text);
|
|
8548
9001
|
const mapped = normalizeMintlifyPageMeta(parsed.data);
|
|
8549
9002
|
const { data, removed } = stripUnknownPageMeta(mapped);
|
|
8550
|
-
const content = Object.keys(data).length > 0 ?
|
|
9003
|
+
const content = Object.keys(data).length > 0 ? frontmatter_default.stringify(parsed.content, data) : parsed.content;
|
|
8551
9004
|
return {
|
|
8552
9005
|
components: snippetImports.components,
|
|
8553
9006
|
content,
|
|
@@ -8566,15 +9019,15 @@ var MINTLIFY_SOURCE_IGNORES = [
|
|
|
8566
9019
|
"snippets/**"
|
|
8567
9020
|
];
|
|
8568
9021
|
var mintlifySource = (options) => {
|
|
8569
|
-
const contentRoot =
|
|
9022
|
+
const contentRoot = isAbsolute5(options.root) ? options.root : join18(resolve7(options.projectRoot), options.root);
|
|
8570
9023
|
const ignore = [...new Set([...options.exclude, ...MINTLIFY_SOURCE_IGNORES])];
|
|
8571
9024
|
const transform = (raw, file) => transformMintlifyContent(raw, {
|
|
8572
9025
|
filePath: file,
|
|
8573
|
-
root:
|
|
9026
|
+
root: resolve7(options.projectRoot),
|
|
8574
9027
|
variables: options.variables
|
|
8575
9028
|
});
|
|
8576
|
-
const
|
|
8577
|
-
const files = await
|
|
9029
|
+
const load2 = async () => {
|
|
9030
|
+
const files = await glob7(options.include, {
|
|
8578
9031
|
absolute: true,
|
|
8579
9032
|
cwd: contentRoot,
|
|
8580
9033
|
ignore,
|
|
@@ -8583,16 +9036,16 @@ var mintlifySource = (options) => {
|
|
|
8583
9036
|
files.sort();
|
|
8584
9037
|
const unsupported = new Set;
|
|
8585
9038
|
const entries = await Promise.all(files.map(async (file) => {
|
|
8586
|
-
const result = await transform(await
|
|
9039
|
+
const result = await transform(await readFile13(file, "utf-8"), file);
|
|
8587
9040
|
for (const name of result.unsupported) {
|
|
8588
9041
|
unsupported.add(name);
|
|
8589
9042
|
}
|
|
8590
|
-
const parsed =
|
|
9043
|
+
const parsed = frontmatter_default(result.content);
|
|
8591
9044
|
return {
|
|
8592
9045
|
body: { format: "mdx", text: parsed.content },
|
|
8593
9046
|
data: parsed.data,
|
|
8594
9047
|
raw: result.content,
|
|
8595
|
-
ref:
|
|
9048
|
+
ref: relative12(contentRoot, file),
|
|
8596
9049
|
sourcePath: file
|
|
8597
9050
|
};
|
|
8598
9051
|
}));
|
|
@@ -8606,7 +9059,7 @@ var mintlifySource = (options) => {
|
|
|
8606
9059
|
return { diagnostics, entries };
|
|
8607
9060
|
};
|
|
8608
9061
|
const validate = () => {
|
|
8609
|
-
if (!
|
|
9062
|
+
if (!existsSync10(contentRoot)) {
|
|
8610
9063
|
throw new BlumeError({
|
|
8611
9064
|
code: "BLUME_CONTENT_ROOT_MISSING",
|
|
8612
9065
|
file: contentRoot,
|
|
@@ -8618,11 +9071,11 @@ var mintlifySource = (options) => {
|
|
|
8618
9071
|
};
|
|
8619
9072
|
const watch = (onChange) => {
|
|
8620
9073
|
const disposers = [];
|
|
8621
|
-
if (
|
|
9074
|
+
if (existsSync10(contentRoot)) {
|
|
8622
9075
|
const watcher = fsWatch2(contentRoot, { recursive: true }, onChange);
|
|
8623
9076
|
disposers.push(() => watcher.close());
|
|
8624
9077
|
}
|
|
8625
|
-
if (options.configFile &&
|
|
9078
|
+
if (options.configFile && existsSync10(options.configFile)) {
|
|
8626
9079
|
const watcher = fsWatch2(options.configFile, onChange);
|
|
8627
9080
|
disposers.push(() => watcher.close());
|
|
8628
9081
|
}
|
|
@@ -8633,13 +9086,13 @@ var mintlifySource = (options) => {
|
|
|
8633
9086
|
};
|
|
8634
9087
|
};
|
|
8635
9088
|
const read = async (ref) => {
|
|
8636
|
-
const file =
|
|
8637
|
-
const result = await transform(await
|
|
9089
|
+
const file = join18(contentRoot, ref);
|
|
9090
|
+
const result = await transform(await readFile13(file, "utf-8"), file);
|
|
8638
9091
|
return result.content;
|
|
8639
9092
|
};
|
|
8640
9093
|
return {
|
|
8641
9094
|
contentRoot,
|
|
8642
|
-
load,
|
|
9095
|
+
load: load2,
|
|
8643
9096
|
name: options.name,
|
|
8644
9097
|
prefix: options.prefix,
|
|
8645
9098
|
read,
|
|
@@ -8650,12 +9103,11 @@ var mintlifySource = (options) => {
|
|
|
8650
9103
|
};
|
|
8651
9104
|
|
|
8652
9105
|
// src/core/sources/notion.ts
|
|
8653
|
-
import
|
|
8654
|
-
import { join as join18 } from "pathe";
|
|
9106
|
+
import { join as join20 } from "pathe";
|
|
8655
9107
|
|
|
8656
9108
|
// src/core/sources/assets.ts
|
|
8657
9109
|
import { mkdir as mkdir4, writeFile as writeFile5 } from "node:fs/promises";
|
|
8658
|
-
import { extname as extname5, join as
|
|
9110
|
+
import { extname as extname5, join as join19 } from "pathe";
|
|
8659
9111
|
var MD_IMAGE = /!\[(?<alt>[^\]]*)\]\((?<url>[^)\s]+)\)/gu;
|
|
8660
9112
|
var REMOTE = /^https?:\/\//u;
|
|
8661
9113
|
var SAFE_EXT = /^\.[a-z0-9]+$/iu;
|
|
@@ -8684,7 +9136,7 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
8684
9136
|
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
8685
9137
|
const file = `${hashText(url)}${extFor(url)}`;
|
|
8686
9138
|
await mkdir4(ctx.assetsDir, { recursive: true });
|
|
8687
|
-
await writeFile5(
|
|
9139
|
+
await writeFile5(join19(ctx.assetsDir, file), bytes);
|
|
8688
9140
|
rewrites.set(url, `${ctx.assetsBaseUrl}/${file}`);
|
|
8689
9141
|
} catch (error) {
|
|
8690
9142
|
diagnostics.push({
|
|
@@ -8778,8 +9230,8 @@ ${text}
|
|
|
8778
9230
|
};
|
|
8779
9231
|
var notionSource = (options, ctx) => {
|
|
8780
9232
|
const props = options.properties ?? {};
|
|
8781
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
8782
|
-
const assetsDir = ctx?.assetsDir ??
|
|
9233
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join20(".blume", "cache", options.name));
|
|
9234
|
+
const assetsDir = ctx?.assetsDir ?? join20(".blume", "public", "blume-assets", options.name);
|
|
8783
9235
|
const assetsBaseUrl = ctx?.assetsBaseUrl ?? `/blume-assets/${options.name}`;
|
|
8784
9236
|
let snapshot = new Map;
|
|
8785
9237
|
const resolveClient = async () => {
|
|
@@ -8895,7 +9347,7 @@ ${rendered.join(`
|
|
|
8895
9347
|
assetsDir,
|
|
8896
9348
|
fetchImpl: options.fetchImpl
|
|
8897
9349
|
});
|
|
8898
|
-
const raw =
|
|
9350
|
+
const raw = frontmatter_default.stringify(assets.markdown, data);
|
|
8899
9351
|
return {
|
|
8900
9352
|
diagnostics: assets.diagnostics,
|
|
8901
9353
|
entry: {
|
|
@@ -8908,7 +9360,7 @@ ${rendered.join(`
|
|
|
8908
9360
|
}
|
|
8909
9361
|
};
|
|
8910
9362
|
};
|
|
8911
|
-
const
|
|
9363
|
+
const load2 = async () => {
|
|
8912
9364
|
const assetDiagnostics = [];
|
|
8913
9365
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
8914
9366
|
const client = await resolveClient();
|
|
@@ -8937,18 +9389,17 @@ ${rendered.join(`
|
|
|
8937
9389
|
return all.find((e) => e.ref === ref)?.raw ?? "";
|
|
8938
9390
|
};
|
|
8939
9391
|
return {
|
|
8940
|
-
load,
|
|
9392
|
+
load: load2,
|
|
8941
9393
|
name: options.name,
|
|
8942
9394
|
prefix: options.prefix,
|
|
8943
9395
|
read,
|
|
8944
9396
|
staged: true,
|
|
8945
|
-
watch: options.pollInterval ? pollingWatch(
|
|
9397
|
+
watch: options.pollInterval ? pollingWatch(load2, options.pollInterval) : undefined
|
|
8946
9398
|
};
|
|
8947
9399
|
};
|
|
8948
9400
|
|
|
8949
9401
|
// src/core/sources/sanity.ts
|
|
8950
|
-
import
|
|
8951
|
-
import { join as join19 } from "pathe";
|
|
9402
|
+
import { join as join21 } from "pathe";
|
|
8952
9403
|
|
|
8953
9404
|
// src/core/sources/portable-text.ts
|
|
8954
9405
|
var HEADING_STYLES = {
|
|
@@ -9087,7 +9538,7 @@ var resolveClient = async (options, preview) => {
|
|
|
9087
9538
|
};
|
|
9088
9539
|
var sanitySource = (options, ctx) => {
|
|
9089
9540
|
const fields = options.fields ?? {};
|
|
9090
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
9541
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join21(".blume", "cache", options.name));
|
|
9091
9542
|
let snapshot = new Map;
|
|
9092
9543
|
const toEntry = (doc) => {
|
|
9093
9544
|
const slugValue = asString2(getPath(doc, fields.slug ?? "slug.current")) ?? asString2(doc._id) ?? "untitled";
|
|
@@ -9109,7 +9560,7 @@ var sanitySource = (options, ctx) => {
|
|
|
9109
9560
|
},
|
|
9110
9561
|
serializers: options.serializers
|
|
9111
9562
|
}) : "";
|
|
9112
|
-
const raw =
|
|
9563
|
+
const raw = frontmatter_default.stringify(markdown, data);
|
|
9113
9564
|
return {
|
|
9114
9565
|
body: { format: "md", text: markdown },
|
|
9115
9566
|
data,
|
|
@@ -9119,7 +9570,7 @@ var sanitySource = (options, ctx) => {
|
|
|
9119
9570
|
ref: `${slug}.md`
|
|
9120
9571
|
};
|
|
9121
9572
|
};
|
|
9122
|
-
const
|
|
9573
|
+
const load2 = async () => {
|
|
9123
9574
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
9124
9575
|
const client = await resolveClient(options, ctx?.preview ?? false);
|
|
9125
9576
|
const docs = await client.fetch(options.query);
|
|
@@ -9137,12 +9588,12 @@ var sanitySource = (options, ctx) => {
|
|
|
9137
9588
|
return all.find((e) => e.ref === ref)?.raw ?? "";
|
|
9138
9589
|
};
|
|
9139
9590
|
return {
|
|
9140
|
-
load,
|
|
9591
|
+
load: load2,
|
|
9141
9592
|
name: options.name,
|
|
9142
9593
|
prefix: options.prefix,
|
|
9143
9594
|
read,
|
|
9144
9595
|
staged: true,
|
|
9145
|
-
watch: options.pollInterval ? pollingWatch(
|
|
9596
|
+
watch: options.pollInterval ? pollingWatch(load2, options.pollInterval) : undefined
|
|
9146
9597
|
};
|
|
9147
9598
|
};
|
|
9148
9599
|
|
|
@@ -9162,8 +9613,8 @@ var uniqueNamer = () => {
|
|
|
9162
9613
|
};
|
|
9163
9614
|
var sourceContext = (context, name, runtime) => ({
|
|
9164
9615
|
assetsBaseUrl: `/blume-assets/${name}`,
|
|
9165
|
-
assetsDir:
|
|
9166
|
-
cacheDir:
|
|
9616
|
+
assetsDir: join22(context.outDir, "public", "blume-assets", name),
|
|
9617
|
+
cacheDir: join22(context.outDir, "cache", name),
|
|
9167
9618
|
mode: runtime.mode,
|
|
9168
9619
|
preview: runtime.preview,
|
|
9169
9620
|
projectRoot: context.root,
|
|
@@ -9396,7 +9847,7 @@ var buildCommand = defineCommand2({
|
|
|
9396
9847
|
logLevel: "info",
|
|
9397
9848
|
root: project.context.outDir
|
|
9398
9849
|
});
|
|
9399
|
-
const distDir =
|
|
9850
|
+
const distDir = join23(root, "dist");
|
|
9400
9851
|
if (project.config.search.provider === "pagefind") {
|
|
9401
9852
|
logger.start("Building search index");
|
|
9402
9853
|
const indexed = await buildSearchIndex(distDir);
|
|
@@ -9410,19 +9861,19 @@ var buildCommand = defineCommand2({
|
|
|
9410
9861
|
if (project.config.ai.llmsTxt) {
|
|
9411
9862
|
const { index, full } = await buildLlmsFiles(project);
|
|
9412
9863
|
await Promise.all([
|
|
9413
|
-
writeFile6(
|
|
9414
|
-
writeFile6(
|
|
9864
|
+
writeFile6(join23(distDir, "llms.txt"), index, "utf-8"),
|
|
9865
|
+
writeFile6(join23(distDir, "llms-full.txt"), full, "utf-8")
|
|
9415
9866
|
]);
|
|
9416
9867
|
logger.success("Generated llms.txt and llms-full.txt");
|
|
9417
9868
|
}
|
|
9418
9869
|
const sitemap = buildSitemap(project);
|
|
9419
|
-
if (sitemap && !
|
|
9420
|
-
await writeFile6(
|
|
9870
|
+
if (sitemap && !existsSync11(join23(distDir, "sitemap.xml"))) {
|
|
9871
|
+
await writeFile6(join23(distDir, "sitemap.xml"), sitemap, "utf-8");
|
|
9421
9872
|
logger.success("Generated sitemap.xml");
|
|
9422
9873
|
}
|
|
9423
9874
|
const robots = buildRobots(project);
|
|
9424
|
-
if (robots && !
|
|
9425
|
-
await writeFile6(
|
|
9875
|
+
if (robots && !existsSync11(join23(distDir, "robots.txt"))) {
|
|
9876
|
+
await writeFile6(join23(distDir, "robots.txt"), robots, "utf-8");
|
|
9426
9877
|
logger.success("Generated robots.txt");
|
|
9427
9878
|
}
|
|
9428
9879
|
const { config } = project;
|
|
@@ -9590,39 +10041,47 @@ var doctorCommand = defineCommand4({
|
|
|
9590
10041
|
});
|
|
9591
10042
|
|
|
9592
10043
|
// src/cli/commands/eject.ts
|
|
9593
|
-
import { readFile as
|
|
10044
|
+
import { readFile as readFile15, writeFile as writeFile8 } from "node:fs/promises";
|
|
9594
10045
|
import { defineCommand as defineCommand5 } from "citty";
|
|
9595
|
-
import { join as
|
|
10046
|
+
import { join as join25, relative as relative14 } from "pathe";
|
|
9596
10047
|
|
|
9597
10048
|
// src/registry/eject.ts
|
|
9598
|
-
import { existsSync as
|
|
9599
|
-
import { cp, mkdir as mkdir5, readFile as
|
|
9600
|
-
import { join as
|
|
10049
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
10050
|
+
import { cp, mkdir as mkdir5, readFile as readFile14, rm as rm2, writeFile as writeFile7 } from "node:fs/promises";
|
|
10051
|
+
import { join as join24, relative as relative13 } from "pathe";
|
|
9601
10052
|
var POSIX = (path) => path.split("\\").join("/");
|
|
9602
10053
|
var eject = async (root) => {
|
|
9603
10054
|
const project = await scanProject(root, { mode: "build" });
|
|
9604
10055
|
const { context, config } = project;
|
|
9605
|
-
const srcDir =
|
|
9606
|
-
const genDir =
|
|
10056
|
+
const srcDir = join24(root, "src");
|
|
10057
|
+
const genDir = join24(srcDir, "generated");
|
|
9607
10058
|
const askEnabled = config.ai.ask?.enabled ?? false;
|
|
9608
10059
|
const exportPdf = config.export.pdf;
|
|
9609
10060
|
const exportEpub = config.export.epub;
|
|
9610
|
-
const [pages, needsReactRaw, userTheme, rawMarkdown] = await Promise.all([
|
|
10061
|
+
const [pages, needsReactRaw, userTheme, rawMarkdown, islands, examples] = await Promise.all([
|
|
9611
10062
|
context.pagesRoot ? discoverPages(context.pagesRoot) : Promise.resolve([]),
|
|
9612
10063
|
detectNeedsReact(root),
|
|
9613
|
-
context.themeFile ?
|
|
9614
|
-
buildRawMarkdown(project)
|
|
10064
|
+
context.themeFile ? readFile14(context.themeFile, "utf-8") : Promise.resolve(""),
|
|
10065
|
+
buildRawMarkdown(project),
|
|
10066
|
+
discoverIslands(root),
|
|
10067
|
+
discoverExamples(root)
|
|
10068
|
+
]);
|
|
10069
|
+
const frameworks = new Set([
|
|
10070
|
+
...islands.islands.map((island) => island.framework),
|
|
10071
|
+
...examples.examples.map((example) => example.framework)
|
|
9615
10072
|
]);
|
|
9616
|
-
const needsReact = needsReactRaw || askEnabled;
|
|
10073
|
+
const needsReact = needsReactRaw || askEnabled || frameworks.has("react");
|
|
10074
|
+
const needsVue = frameworks.has("vue");
|
|
10075
|
+
const needsSvelte = frameworks.has("svelte");
|
|
9617
10076
|
const relContext = {
|
|
9618
10077
|
...context,
|
|
9619
|
-
contentRoot: POSIX(
|
|
10078
|
+
contentRoot: POSIX(relative13(root, context.contentRoot)),
|
|
9620
10079
|
outDir: ".",
|
|
9621
10080
|
root: "."
|
|
9622
10081
|
};
|
|
9623
|
-
const componentsImport = context.componentsFile ? `../../${POSIX(
|
|
10082
|
+
const componentsImport = context.componentsFile ? `../../${POSIX(relative13(root, context.componentsFile))}` : null;
|
|
9624
10083
|
const relPages = pages.map((page) => ({
|
|
9625
|
-
entrypoint: POSIX(
|
|
10084
|
+
entrypoint: POSIX(relative13(root, page.entrypoint)),
|
|
9626
10085
|
pattern: page.pattern
|
|
9627
10086
|
}));
|
|
9628
10087
|
const staged = collectStaged(project);
|
|
@@ -9635,18 +10094,21 @@ var eject = async (root) => {
|
|
|
9635
10094
|
contentRoutes: project.manifest.routes.map((route) => route.path),
|
|
9636
10095
|
context: relContext,
|
|
9637
10096
|
dataPath: "./src/generated/data.json",
|
|
10097
|
+
examplesPath: "./src/generated/examples.ts",
|
|
9638
10098
|
needsReact,
|
|
10099
|
+
needsSvelte,
|
|
10100
|
+
needsVue,
|
|
9639
10101
|
pages: relPages,
|
|
9640
10102
|
searchClientPath: "./src/generated/search-client.ts",
|
|
9641
10103
|
themePath: "./src/generated/app.css"
|
|
9642
10104
|
}),
|
|
9643
|
-
path:
|
|
10105
|
+
path: join24(root, "astro.config.mjs")
|
|
9644
10106
|
},
|
|
9645
10107
|
{
|
|
9646
10108
|
content: runtimeTsconfigTemplate(),
|
|
9647
|
-
path:
|
|
10109
|
+
path: join24(root, "tsconfig.json")
|
|
9648
10110
|
},
|
|
9649
|
-
{ content: envTemplate(), path:
|
|
10111
|
+
{ content: envTemplate(), path: join24(srcDir, "env.d.ts") },
|
|
9650
10112
|
{
|
|
9651
10113
|
content: contentConfigTemplate({
|
|
9652
10114
|
config,
|
|
@@ -9654,7 +10116,7 @@ var eject = async (root) => {
|
|
|
9654
10116
|
staged: hasStaged,
|
|
9655
10117
|
stagedBase: stagedDir
|
|
9656
10118
|
}),
|
|
9657
|
-
path:
|
|
10119
|
+
path: join24(srcDir, "content.config.ts")
|
|
9658
10120
|
},
|
|
9659
10121
|
{
|
|
9660
10122
|
content: catchAllPageTemplate({
|
|
@@ -9663,11 +10125,19 @@ var eject = async (root) => {
|
|
|
9663
10125
|
exportPdf,
|
|
9664
10126
|
mathEnabled: config.markdown.math
|
|
9665
10127
|
}),
|
|
9666
|
-
path:
|
|
10128
|
+
path: join24(srcDir, "pages", "[...slug].astro")
|
|
9667
10129
|
},
|
|
9668
10130
|
{
|
|
9669
10131
|
content: userComponentsTemplate(componentsImport),
|
|
9670
|
-
path:
|
|
10132
|
+
path: join24(genDir, "components.ts")
|
|
10133
|
+
},
|
|
10134
|
+
{
|
|
10135
|
+
content: islandMapTemplate(islands.islands),
|
|
10136
|
+
path: join24(genDir, "islands.ts")
|
|
10137
|
+
},
|
|
10138
|
+
{
|
|
10139
|
+
content: exampleMapTemplate(examples.examples),
|
|
10140
|
+
path: join24(genDir, "examples.ts")
|
|
9671
10141
|
},
|
|
9672
10142
|
{
|
|
9673
10143
|
content: tailwindEntryTemplate({
|
|
@@ -9679,54 +10149,54 @@ var eject = async (root) => {
|
|
|
9679
10149
|
twoslashCss: twoslashCss(),
|
|
9680
10150
|
userTheme
|
|
9681
10151
|
}),
|
|
9682
|
-
path:
|
|
10152
|
+
path: join24(genDir, "app.css")
|
|
9683
10153
|
},
|
|
9684
|
-
{ content: buildRuntimeData(project), path:
|
|
10154
|
+
{ content: buildRuntimeData(project), path: join24(genDir, "data.json") },
|
|
9685
10155
|
{
|
|
9686
10156
|
content: `${JSON.stringify(rawMarkdown)}
|
|
9687
10157
|
`,
|
|
9688
|
-
path:
|
|
10158
|
+
path: join24(genDir, "raw-markdown.json")
|
|
9689
10159
|
},
|
|
9690
10160
|
{
|
|
9691
10161
|
content: rawMarkdownEndpointTemplate(),
|
|
9692
|
-
path:
|
|
10162
|
+
path: join24(srcDir, "pages", "[...slug].md.ts")
|
|
9693
10163
|
},
|
|
9694
10164
|
{
|
|
9695
10165
|
content: rawMarkdownEndpointTemplate(),
|
|
9696
|
-
path:
|
|
10166
|
+
path: join24(srcDir, "pages", "[...slug].mdx.ts")
|
|
9697
10167
|
}
|
|
9698
10168
|
];
|
|
9699
10169
|
if (askEnabled) {
|
|
9700
10170
|
files.push({
|
|
9701
10171
|
content: askEndpointTemplate(resolveAskBackend(config.ai.ask)),
|
|
9702
|
-
path:
|
|
10172
|
+
path: join24(srcDir, "pages", "api", "ask.ts")
|
|
9703
10173
|
});
|
|
9704
10174
|
}
|
|
9705
10175
|
if (config.seo.og.enabled) {
|
|
9706
10176
|
files.push({
|
|
9707
|
-
content: ogEndpointTemplate(),
|
|
9708
|
-
path:
|
|
10177
|
+
content: ogEndpointTemplate(customOgRoutes(pages, config.title, config.description)),
|
|
10178
|
+
path: join24(srcDir, "pages", "og", "[...slug].png.ts")
|
|
9709
10179
|
});
|
|
9710
10180
|
}
|
|
9711
10181
|
files.push({
|
|
9712
10182
|
content: searchClientTemplate(config),
|
|
9713
|
-
path:
|
|
10183
|
+
path: join24(genDir, "search-client.ts")
|
|
9714
10184
|
});
|
|
9715
10185
|
if (servesStaticIndex(config.search.provider)) {
|
|
9716
10186
|
const documents = await buildSearchDocuments(project);
|
|
9717
10187
|
files.push({
|
|
9718
10188
|
content: `${JSON.stringify(documents)}
|
|
9719
10189
|
`,
|
|
9720
|
-
path:
|
|
10190
|
+
path: join24(genDir, "search.json")
|
|
9721
10191
|
}, {
|
|
9722
10192
|
content: searchEndpointTemplate(),
|
|
9723
|
-
path:
|
|
10193
|
+
path: join24(srcDir, "pages", "blume-search.json.ts")
|
|
9724
10194
|
});
|
|
9725
10195
|
}
|
|
9726
10196
|
if (config.search.provider === "mixedbread") {
|
|
9727
10197
|
files.push({
|
|
9728
10198
|
content: mixedbreadSearchEndpointTemplate(config.search.mixedbread?.storeId ?? ""),
|
|
9729
|
-
path:
|
|
10199
|
+
path: join24(srcDir, "pages", "api", "search.ts")
|
|
9730
10200
|
});
|
|
9731
10201
|
}
|
|
9732
10202
|
const feeds = buildRssFeeds(project);
|
|
@@ -9735,10 +10205,10 @@ var eject = async (root) => {
|
|
|
9735
10205
|
files.push({
|
|
9736
10206
|
content: `${JSON.stringify(feedXml)}
|
|
9737
10207
|
`,
|
|
9738
|
-
path:
|
|
10208
|
+
path: join24(genDir, "rss.json")
|
|
9739
10209
|
}, {
|
|
9740
10210
|
content: rssEndpointTemplate(),
|
|
9741
|
-
path:
|
|
10211
|
+
path: join24(srcDir, "pages", "[section]", "rss.xml.ts")
|
|
9742
10212
|
});
|
|
9743
10213
|
}
|
|
9744
10214
|
if (hasReferences(config)) {
|
|
@@ -9750,20 +10220,27 @@ var eject = async (root) => {
|
|
|
9750
10220
|
for (const file of references.files) {
|
|
9751
10221
|
files.push({
|
|
9752
10222
|
content: file.content,
|
|
9753
|
-
path:
|
|
10223
|
+
path: join24(srcDir, "pages", file.pagePath)
|
|
9754
10224
|
});
|
|
9755
10225
|
}
|
|
9756
10226
|
}
|
|
10227
|
+
files.push(...islands.islands.map((island) => ({
|
|
10228
|
+
content: islandWrapperTemplate(island),
|
|
10229
|
+
path: join24(genDir, "islands", `${island.name}.astro`)
|
|
10230
|
+
})), ...examples.examples.map((example) => ({
|
|
10231
|
+
content: exampleWrapperTemplate(example),
|
|
10232
|
+
path: join24(genDir, "examples", `${exampleSlug(example.path)}.astro`)
|
|
10233
|
+
})));
|
|
9757
10234
|
for (const [entryId, content] of staged) {
|
|
9758
|
-
files.push({ content, path:
|
|
10235
|
+
files.push({ content, path: join24(root, stagedDir, entryId) });
|
|
9759
10236
|
}
|
|
9760
10237
|
await Promise.all(files.map(async (file) => {
|
|
9761
|
-
await mkdir5(
|
|
10238
|
+
await mkdir5(join24(file.path, ".."), { recursive: true });
|
|
9762
10239
|
await writeFile7(file.path, file.content, "utf-8");
|
|
9763
10240
|
}));
|
|
9764
|
-
const assetsSrc =
|
|
9765
|
-
if (
|
|
9766
|
-
await cp(assetsSrc,
|
|
10241
|
+
const assetsSrc = join24(context.outDir, "public", "blume-assets");
|
|
10242
|
+
if (existsSync12(assetsSrc)) {
|
|
10243
|
+
await cp(assetsSrc, join24(root, "public", "blume-assets"), {
|
|
9767
10244
|
recursive: true
|
|
9768
10245
|
});
|
|
9769
10246
|
}
|
|
@@ -9773,10 +10250,10 @@ var eject = async (root) => {
|
|
|
9773
10250
|
|
|
9774
10251
|
// src/cli/commands/eject.ts
|
|
9775
10252
|
var updatePackageScripts = async (root) => {
|
|
9776
|
-
const pkgPath =
|
|
10253
|
+
const pkgPath = join25(root, "package.json");
|
|
9777
10254
|
let pkg;
|
|
9778
10255
|
try {
|
|
9779
|
-
pkg = JSON.parse(await
|
|
10256
|
+
pkg = JSON.parse(await readFile15(pkgPath, "utf-8"));
|
|
9780
10257
|
} catch {
|
|
9781
10258
|
return;
|
|
9782
10259
|
}
|
|
@@ -9809,7 +10286,7 @@ var ejectCommand = defineCommand5({
|
|
|
9809
10286
|
await updatePackageScripts(root);
|
|
9810
10287
|
logger.success(`Ejected ${files.length} file(s):`);
|
|
9811
10288
|
for (const file of files) {
|
|
9812
|
-
process.stdout.write(` ${
|
|
10289
|
+
process.stdout.write(` ${relative14(root, file)}
|
|
9813
10290
|
`);
|
|
9814
10291
|
}
|
|
9815
10292
|
logger.box(`Your project is now a standalone Astro app.
|
|
@@ -9822,10 +10299,10 @@ The blume package remains importable.`);
|
|
|
9822
10299
|
});
|
|
9823
10300
|
|
|
9824
10301
|
// src/cli/commands/init.ts
|
|
9825
|
-
import { existsSync as
|
|
10302
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
9826
10303
|
import { mkdir as mkdir6, writeFile as writeFile9 } from "node:fs/promises";
|
|
9827
10304
|
import { defineCommand as defineCommand6 } from "citty";
|
|
9828
|
-
import { basename as
|
|
10305
|
+
import { basename as basename4, dirname as dirname11, join as join26 } from "pathe";
|
|
9829
10306
|
var toPackageName = (raw) => raw.toLowerCase().replaceAll(/[^a-z0-9._-]+/gu, "-").replaceAll(/^[-_.]+|[-_.]+$/gu, "") || "docs";
|
|
9830
10307
|
var packageTemplate = (name, version) => `{
|
|
9831
10308
|
"name": ${JSON.stringify(name)},
|
|
@@ -9860,11 +10337,11 @@ Welcome to **Blume** — markdown-first docs powered by Astro and Vite.
|
|
|
9860
10337
|
Edit \`docs/index.mdx\` to get started, then run \`blume dev\`.
|
|
9861
10338
|
`;
|
|
9862
10339
|
var writeFileSafe = async (path, content) => {
|
|
9863
|
-
if (
|
|
10340
|
+
if (existsSync13(path)) {
|
|
9864
10341
|
logger.info(`Skipped existing ${path}`);
|
|
9865
10342
|
return false;
|
|
9866
10343
|
}
|
|
9867
|
-
await mkdir6(
|
|
10344
|
+
await mkdir6(dirname11(path), { recursive: true });
|
|
9868
10345
|
await writeFile9(path, content, "utf-8");
|
|
9869
10346
|
logger.success(`Created ${path}`);
|
|
9870
10347
|
return true;
|
|
@@ -9885,9 +10362,9 @@ var initCommand = defineCommand6({
|
|
|
9885
10362
|
async run({ args }) {
|
|
9886
10363
|
const root = process.cwd();
|
|
9887
10364
|
const contentDir = args["content-dir"] ?? "docs";
|
|
9888
|
-
const createdPackage = await writeFileSafe(
|
|
9889
|
-
await writeFileSafe(
|
|
9890
|
-
await writeFileSafe(
|
|
10365
|
+
const createdPackage = await writeFileSafe(join26(root, "package.json"), packageTemplate(toPackageName(basename4(root)), getBlumeVersion()));
|
|
10366
|
+
await writeFileSafe(join26(root, "blume.config.ts"), CONFIG_TEMPLATE);
|
|
10367
|
+
await writeFileSafe(join26(root, contentDir, "index.mdx"), INDEX_TEMPLATE);
|
|
9891
10368
|
const nextSteps = createdPackage ? `Next steps:
|
|
9892
10369
|
|
|
9893
10370
|
npm install
|
|
@@ -9904,16 +10381,15 @@ var initCommand = defineCommand6({
|
|
|
9904
10381
|
import { defineCommand as defineCommand7 } from "citty";
|
|
9905
10382
|
|
|
9906
10383
|
// src/migrate/fumadocs/index.ts
|
|
9907
|
-
import { existsSync as
|
|
9908
|
-
import { mkdir as
|
|
9909
|
-
import
|
|
9910
|
-
import {
|
|
9911
|
-
import { glob as glob7 } from "tinyglobby";
|
|
10384
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
10385
|
+
import { mkdir as mkdir8, readFile as readFile17, rename as rename3, rm as rm3, writeFile as writeFile11 } from "node:fs/promises";
|
|
10386
|
+
import { dirname as dirname14, join as join29, relative as relative15 } from "pathe";
|
|
10387
|
+
import { glob as glob8 } from "tinyglobby";
|
|
9912
10388
|
|
|
9913
10389
|
// src/migrate/fumadocs/config.ts
|
|
9914
|
-
import { existsSync as
|
|
9915
|
-
import { readFile as
|
|
9916
|
-
import { join as
|
|
10390
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
10391
|
+
import { readFile as readFile16 } from "node:fs/promises";
|
|
10392
|
+
import { basename as basename5, dirname as dirname12, join as join27 } from "pathe";
|
|
9917
10393
|
var SOURCE_FILES = [
|
|
9918
10394
|
"lib/source.ts",
|
|
9919
10395
|
"app/source.ts",
|
|
@@ -9930,25 +10406,62 @@ var prettifyTitle = (name) => {
|
|
|
9930
10406
|
}
|
|
9931
10407
|
return words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
9932
10408
|
};
|
|
10409
|
+
var GENERIC_NAMES = new Set([
|
|
10410
|
+
"api",
|
|
10411
|
+
"app",
|
|
10412
|
+
"client",
|
|
10413
|
+
"frontend",
|
|
10414
|
+
"server",
|
|
10415
|
+
"site",
|
|
10416
|
+
"web",
|
|
10417
|
+
"www"
|
|
10418
|
+
]);
|
|
10419
|
+
var gitRepoRoot = (start) => {
|
|
10420
|
+
let dir = start;
|
|
10421
|
+
for (;; ) {
|
|
10422
|
+
if (existsSync14(join27(dir, ".git"))) {
|
|
10423
|
+
return dir;
|
|
10424
|
+
}
|
|
10425
|
+
const parent = dirname12(dir);
|
|
10426
|
+
if (parent === dir) {
|
|
10427
|
+
return null;
|
|
10428
|
+
}
|
|
10429
|
+
dir = parent;
|
|
10430
|
+
}
|
|
10431
|
+
};
|
|
10432
|
+
var bareName = (name) => name.includes("/") ? name.slice(name.lastIndexOf("/") + 1) : name;
|
|
9933
10433
|
var readTitle = async (root) => {
|
|
9934
|
-
const packageJson =
|
|
9935
|
-
if (!
|
|
10434
|
+
const packageJson = join27(root, "package.json");
|
|
10435
|
+
if (!existsSync14(packageJson)) {
|
|
9936
10436
|
return "Documentation";
|
|
9937
10437
|
}
|
|
9938
10438
|
try {
|
|
9939
|
-
const parsed = JSON.parse(await
|
|
9940
|
-
|
|
10439
|
+
const parsed = JSON.parse(await readFile16(packageJson, "utf-8"));
|
|
10440
|
+
const { name } = parsed;
|
|
10441
|
+
if (typeof name !== "string" || !name.trim()) {
|
|
10442
|
+
return "Documentation";
|
|
10443
|
+
}
|
|
10444
|
+
if (GENERIC_NAMES.has(bareName(name).toLowerCase())) {
|
|
10445
|
+
const repoRoot = gitRepoRoot(root);
|
|
10446
|
+
if (repoRoot && repoRoot !== root) {
|
|
10447
|
+
const repoTitle = prettifyTitle(basename5(repoRoot));
|
|
10448
|
+
if (repoTitle !== "Documentation") {
|
|
10449
|
+
return repoTitle;
|
|
10450
|
+
}
|
|
10451
|
+
}
|
|
10452
|
+
}
|
|
10453
|
+
return prettifyTitle(name);
|
|
9941
10454
|
} catch {
|
|
9942
10455
|
return "Documentation";
|
|
9943
10456
|
}
|
|
9944
10457
|
};
|
|
9945
10458
|
var scrapeBaseUrl = async (root) => {
|
|
9946
10459
|
for (const candidate of SOURCE_FILES) {
|
|
9947
|
-
const file =
|
|
9948
|
-
if (!
|
|
10460
|
+
const file = join27(root, candidate);
|
|
10461
|
+
if (!existsSync14(file)) {
|
|
9949
10462
|
continue;
|
|
9950
10463
|
}
|
|
9951
|
-
const base = BASE_URL.exec(await
|
|
10464
|
+
const base = BASE_URL.exec(await readFile16(file, "utf-8"))?.groups?.base;
|
|
9952
10465
|
if (base) {
|
|
9953
10466
|
return base;
|
|
9954
10467
|
}
|
|
@@ -9977,10 +10490,9 @@ var loadFumadocsConfig = async (root) => {
|
|
|
9977
10490
|
};
|
|
9978
10491
|
|
|
9979
10492
|
// src/migrate/fumadocs/content.ts
|
|
9980
|
-
import { existsSync as
|
|
10493
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
9981
10494
|
import { readFile as readFileFromDisk2 } from "node:fs/promises";
|
|
9982
|
-
import
|
|
9983
|
-
import { dirname as dirname11, resolve as resolve7 } from "pathe";
|
|
10495
|
+
import { dirname as dirname13, resolve as resolve8 } from "pathe";
|
|
9984
10496
|
var FUMADOCS_IMPORT = /^import\s+[\s\S]*?\s+from\s+["']fumadocs-(?:ui|core|mdx)(?:\/[^"']*)?["'];?[ \t]*\n?/gmu;
|
|
9985
10497
|
var stripFumadocsImports = (source) => {
|
|
9986
10498
|
const stripped = source.replace(FUMADOCS_IMPORT, "");
|
|
@@ -10181,18 +10693,18 @@ var inlineFumadocsIncludes = async (source, options) => {
|
|
|
10181
10693
|
if (!rawPath) {
|
|
10182
10694
|
continue;
|
|
10183
10695
|
}
|
|
10184
|
-
const target =
|
|
10696
|
+
const target = resolve8(dirname13(options.filePath), rawPath);
|
|
10185
10697
|
if (seen.has(target)) {
|
|
10186
10698
|
warnings.push(`Circular <include> "${rawPath}" — left as-is.`);
|
|
10187
10699
|
continue;
|
|
10188
10700
|
}
|
|
10189
|
-
if (!
|
|
10701
|
+
if (!existsSync15(target)) {
|
|
10190
10702
|
warnings.push(`<include> target "${rawPath}" not found — left as-is.`);
|
|
10191
10703
|
continue;
|
|
10192
10704
|
}
|
|
10193
10705
|
seen.add(target);
|
|
10194
10706
|
const raw = await read(target);
|
|
10195
|
-
const nested = await inlineFumadocsIncludes(
|
|
10707
|
+
const nested = await inlineFumadocsIncludes(frontmatter_default(raw).content.trim(), {
|
|
10196
10708
|
...options,
|
|
10197
10709
|
filePath: target,
|
|
10198
10710
|
seen
|
|
@@ -10217,10 +10729,16 @@ var normalizeFumadocsPageMeta = (value) => {
|
|
|
10217
10729
|
return stripUnknownPageMeta(data);
|
|
10218
10730
|
};
|
|
10219
10731
|
|
|
10732
|
+
// src/migrate/fumadocs/groups.ts
|
|
10733
|
+
import { existsSync as existsSync16, statSync as statSync2 } from "node:fs";
|
|
10734
|
+
import { mkdir as mkdir7, rename as rename2, writeFile as writeFile10 } from "node:fs/promises";
|
|
10735
|
+
import { basename as basename6, join as join28 } from "pathe";
|
|
10736
|
+
|
|
10220
10737
|
// src/migrate/fumadocs/meta.ts
|
|
10221
10738
|
var SEPARATOR = /^---(?<label>.*)---$/u;
|
|
10222
10739
|
var LINK2 = /^(?:\[[^\]]*\])?\[(?<text>[^\]]*)\]\((?<href>[^)]*)\)$/u;
|
|
10223
10740
|
var REST = "...";
|
|
10741
|
+
var EXTRACT = /^\.\.\.(?<folder>.+)$/u;
|
|
10224
10742
|
var filterPages = (raw) => {
|
|
10225
10743
|
if (!Array.isArray(raw)) {
|
|
10226
10744
|
return { pages: [], warnings: [] };
|
|
@@ -10235,6 +10753,15 @@ var filterPages = (raw) => {
|
|
|
10235
10753
|
if (value === REST || value === "") {
|
|
10236
10754
|
continue;
|
|
10237
10755
|
}
|
|
10756
|
+
const extract = EXTRACT.exec(value);
|
|
10757
|
+
if (extract) {
|
|
10758
|
+
const folder = extract.groups?.folder?.trim() ?? "";
|
|
10759
|
+
if (folder) {
|
|
10760
|
+
pages.push(folder);
|
|
10761
|
+
warnings.push(`Sidebar extract "...${folder}" became a normal "${folder}" group (its pages are not flattened into the parent).`);
|
|
10762
|
+
}
|
|
10763
|
+
continue;
|
|
10764
|
+
}
|
|
10238
10765
|
const separator = SEPARATOR.exec(value);
|
|
10239
10766
|
if (separator) {
|
|
10240
10767
|
const label = separator.groups?.label?.trim();
|
|
@@ -10250,7 +10777,11 @@ var filterPages = (raw) => {
|
|
|
10250
10777
|
}
|
|
10251
10778
|
return { pages, warnings };
|
|
10252
10779
|
};
|
|
10253
|
-
var
|
|
10780
|
+
var renderMetaModule = (meta) => `import { defineMeta } from "blume";
|
|
10781
|
+
|
|
10782
|
+
export default defineMeta(${JSON.stringify(meta, null, 2)});
|
|
10783
|
+
`;
|
|
10784
|
+
var translateFumadocsSelfMeta = (value) => {
|
|
10254
10785
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
10255
10786
|
return { meta: {}, warnings: [] };
|
|
10256
10787
|
}
|
|
@@ -10272,23 +10803,197 @@ var translateFumadocsMeta = (value) => {
|
|
|
10272
10803
|
if (typeof source.description === "string") {
|
|
10273
10804
|
warnings.push("Dropped folder `description` — Blume folders have no description field.");
|
|
10274
10805
|
}
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10806
|
+
return { meta, warnings };
|
|
10807
|
+
};
|
|
10808
|
+
var translateFumadocsMeta = (value) => {
|
|
10809
|
+
const { meta, warnings } = translateFumadocsSelfMeta(value);
|
|
10810
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
10811
|
+
const { pages, warnings: pageWarnings } = filterPages(value.pages);
|
|
10812
|
+
if (pages.length > 0) {
|
|
10813
|
+
meta.pages = pages;
|
|
10814
|
+
}
|
|
10815
|
+
warnings.push(...pageWarnings);
|
|
10278
10816
|
}
|
|
10279
|
-
warnings.push(...pageWarnings);
|
|
10280
10817
|
return { meta, warnings };
|
|
10281
10818
|
};
|
|
10819
|
+
var parseFumadocsPages = (raw) => {
|
|
10820
|
+
const lead = [];
|
|
10821
|
+
const sections = [];
|
|
10822
|
+
if (!Array.isArray(raw)) {
|
|
10823
|
+
return { hasSections: false, lead, sections };
|
|
10824
|
+
}
|
|
10825
|
+
let current = null;
|
|
10826
|
+
const push = (item) => {
|
|
10827
|
+
(current ? current.items : lead).push(item);
|
|
10828
|
+
};
|
|
10829
|
+
for (const entry of raw) {
|
|
10830
|
+
if (typeof entry !== "string") {
|
|
10831
|
+
continue;
|
|
10832
|
+
}
|
|
10833
|
+
const value = entry.trim();
|
|
10834
|
+
if (value === REST || value === "") {
|
|
10835
|
+
continue;
|
|
10836
|
+
}
|
|
10837
|
+
const separator = SEPARATOR.exec(value);
|
|
10838
|
+
if (separator) {
|
|
10839
|
+
current = {
|
|
10840
|
+
items: [],
|
|
10841
|
+
label: separator.groups?.label?.trim() || "Section"
|
|
10842
|
+
};
|
|
10843
|
+
sections.push(current);
|
|
10844
|
+
continue;
|
|
10845
|
+
}
|
|
10846
|
+
const extract = EXTRACT.exec(value);
|
|
10847
|
+
if (extract) {
|
|
10848
|
+
const name = extract.groups?.folder?.trim();
|
|
10849
|
+
if (name) {
|
|
10850
|
+
push({ kind: "extract", name });
|
|
10851
|
+
}
|
|
10852
|
+
continue;
|
|
10853
|
+
}
|
|
10854
|
+
const link = LINK2.exec(value);
|
|
10855
|
+
if (link) {
|
|
10856
|
+
push({
|
|
10857
|
+
href: link.groups?.href ?? "",
|
|
10858
|
+
kind: "link",
|
|
10859
|
+
text: link.groups?.text ?? ""
|
|
10860
|
+
});
|
|
10861
|
+
continue;
|
|
10862
|
+
}
|
|
10863
|
+
push({ kind: "ref", name: value });
|
|
10864
|
+
}
|
|
10865
|
+
return { hasSections: sections.length > 0, lead, sections };
|
|
10866
|
+
};
|
|
10867
|
+
|
|
10868
|
+
// src/migrate/fumadocs/groups.ts
|
|
10869
|
+
var PAGE_EXTS = [".mdx", ".md"];
|
|
10870
|
+
var WORD_SPLIT3 = /[-_]/u;
|
|
10871
|
+
var PATH_SEP = /[/\\]/u;
|
|
10872
|
+
var isDirectory = (path) => {
|
|
10873
|
+
try {
|
|
10874
|
+
return statSync2(path).isDirectory();
|
|
10875
|
+
} catch {
|
|
10876
|
+
return false;
|
|
10877
|
+
}
|
|
10878
|
+
};
|
|
10879
|
+
var resolveEntry = (docsDir, name) => {
|
|
10880
|
+
for (const ext of PAGE_EXTS) {
|
|
10881
|
+
const file = join28(docsDir, `${name}${ext}`);
|
|
10882
|
+
if (existsSync16(file)) {
|
|
10883
|
+
return { kind: "file", path: file };
|
|
10884
|
+
}
|
|
10885
|
+
}
|
|
10886
|
+
const folder = join28(docsDir, name);
|
|
10887
|
+
return isDirectory(folder) ? { kind: "folder", path: folder } : null;
|
|
10888
|
+
};
|
|
10889
|
+
var humanize2 = (name) => name.split(WORD_SPLIT3).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
10890
|
+
var linkWarning = (item) => `Dropped sidebar link "${item.text}" (${item.href}) — add it to navbar.links manually.`;
|
|
10891
|
+
var extractWarning = (name) => `Sidebar extract "...${name}" became a normal "${name}" group (its pages are not flattened into the parent).`;
|
|
10892
|
+
var addUngroupedItem = (item, order, warnings) => {
|
|
10893
|
+
if (item.kind === "link") {
|
|
10894
|
+
warnings.push(linkWarning(item));
|
|
10895
|
+
return;
|
|
10896
|
+
}
|
|
10897
|
+
if (item.kind === "extract") {
|
|
10898
|
+
warnings.push(extractWarning(item.name));
|
|
10899
|
+
}
|
|
10900
|
+
order.push(item.name);
|
|
10901
|
+
};
|
|
10902
|
+
var reshapeSingleFolderSection = (section, only, order, warnings) => {
|
|
10903
|
+
order.push(only.name);
|
|
10904
|
+
if (humanize2(only.name).toLowerCase() !== section.label.toLowerCase()) {
|
|
10905
|
+
warnings.push(`Section "${section.label}" wraps folder "${only.name}"; set that folder's meta title to "${section.label}" to make the heading match.`);
|
|
10906
|
+
}
|
|
10907
|
+
if (only.kind === "extract") {
|
|
10908
|
+
warnings.push(extractWarning(only.name));
|
|
10909
|
+
}
|
|
10910
|
+
};
|
|
10911
|
+
var moveItemIntoGroup = async (item, docsDir, groupDir, label, warnings) => {
|
|
10912
|
+
if (item.kind === "link") {
|
|
10913
|
+
warnings.push(linkWarning(item));
|
|
10914
|
+
return null;
|
|
10915
|
+
}
|
|
10916
|
+
const resolved = resolveEntry(docsDir, item.name);
|
|
10917
|
+
if (!resolved) {
|
|
10918
|
+
warnings.push(`Sidebar entry "${item.name}" in section "${label}" matched no page or folder; skipped.`);
|
|
10919
|
+
return null;
|
|
10920
|
+
}
|
|
10921
|
+
const dest = join28(groupDir, basename6(resolved.path));
|
|
10922
|
+
if (existsSync16(dest)) {
|
|
10923
|
+
warnings.push(`Skipped moving "${item.name}" into section "${label}" (target already exists).`);
|
|
10924
|
+
return null;
|
|
10925
|
+
}
|
|
10926
|
+
await mkdir7(groupDir, { recursive: true });
|
|
10927
|
+
await rename2(resolved.path, dest);
|
|
10928
|
+
if (item.kind === "extract") {
|
|
10929
|
+
warnings.push(extractWarning(item.name));
|
|
10930
|
+
}
|
|
10931
|
+
return item.name;
|
|
10932
|
+
};
|
|
10933
|
+
var reshapeSection = async (section, docsDir, order, warnings) => {
|
|
10934
|
+
const movable = section.items.filter((item) => item.kind !== "link");
|
|
10935
|
+
if (movable.length === 1) {
|
|
10936
|
+
const [only] = movable;
|
|
10937
|
+
if (resolveEntry(docsDir, only.name)?.kind === "folder") {
|
|
10938
|
+
reshapeSingleFolderSection(section, only, order, warnings);
|
|
10939
|
+
return;
|
|
10940
|
+
}
|
|
10941
|
+
}
|
|
10942
|
+
if (PATH_SEP.test(section.label)) {
|
|
10943
|
+
warnings.push(`Section "${section.label}" has a slash in its name and can't become a group folder; its pages stay ungrouped.`);
|
|
10944
|
+
for (const item of section.items) {
|
|
10945
|
+
addUngroupedItem(item, order, warnings);
|
|
10946
|
+
}
|
|
10947
|
+
return;
|
|
10948
|
+
}
|
|
10949
|
+
const groupDir = join28(docsDir, `(${section.label})`);
|
|
10950
|
+
const sectionKeys = [];
|
|
10951
|
+
for (const item of section.items) {
|
|
10952
|
+
const key = await moveItemIntoGroup(item, docsDir, groupDir, section.label, warnings);
|
|
10953
|
+
if (key) {
|
|
10954
|
+
sectionKeys.push(key);
|
|
10955
|
+
}
|
|
10956
|
+
}
|
|
10957
|
+
if (sectionKeys.length === 0) {
|
|
10958
|
+
return;
|
|
10959
|
+
}
|
|
10960
|
+
order.push(section.label);
|
|
10961
|
+
if (sectionKeys.length > 1) {
|
|
10962
|
+
await writeFile10(join28(groupDir, "meta.ts"), renderMetaModule({ pages: sectionKeys }), "utf-8");
|
|
10963
|
+
}
|
|
10964
|
+
};
|
|
10965
|
+
var reshapeFumadocsGroups = async (structure, docsDir) => {
|
|
10966
|
+
const order = [];
|
|
10967
|
+
const warnings = [];
|
|
10968
|
+
for (const item of structure.lead) {
|
|
10969
|
+
addUngroupedItem(item, order, warnings);
|
|
10970
|
+
}
|
|
10971
|
+
for (const section of structure.sections) {
|
|
10972
|
+
await reshapeSection(section, docsDir, order, warnings);
|
|
10973
|
+
}
|
|
10974
|
+
return { order, warnings };
|
|
10975
|
+
};
|
|
10282
10976
|
|
|
10283
10977
|
// src/migrate/fumadocs/index.ts
|
|
10284
10978
|
var SOURCE_DIR = "content/docs";
|
|
10285
10979
|
var PAGE_GLOB = "**/*.{md,mdx}";
|
|
10286
10980
|
var META_GLOB = "**/meta.json";
|
|
10287
10981
|
var IGNORE = ["**/node_modules/**"];
|
|
10982
|
+
var FUMADOCS_LEFTOVERS = [
|
|
10983
|
+
"next.config.ts",
|
|
10984
|
+
"next.config.mjs",
|
|
10985
|
+
"next.config.js",
|
|
10986
|
+
"source.config.ts",
|
|
10987
|
+
"source.config.mjs",
|
|
10988
|
+
"source.config.js",
|
|
10989
|
+
"mdx-components.tsx",
|
|
10990
|
+
"next-env.d.ts",
|
|
10991
|
+
"app"
|
|
10992
|
+
];
|
|
10288
10993
|
var movePage = async (abs, base, root) => {
|
|
10289
|
-
const rel =
|
|
10290
|
-
const dest =
|
|
10291
|
-
if (
|
|
10994
|
+
const rel = relative15(base, abs);
|
|
10995
|
+
const dest = join29(root, "docs", rel);
|
|
10996
|
+
if (existsSync17(dest)) {
|
|
10292
10997
|
return {
|
|
10293
10998
|
includeWarnings: [],
|
|
10294
10999
|
moved: 0,
|
|
@@ -10297,18 +11002,18 @@ var movePage = async (abs, base, root) => {
|
|
|
10297
11002
|
unsupported: []
|
|
10298
11003
|
};
|
|
10299
11004
|
}
|
|
10300
|
-
const raw = await
|
|
11005
|
+
const raw = await readFile17(abs, "utf-8");
|
|
10301
11006
|
const included = await inlineFumadocsIncludes(raw, { filePath: abs });
|
|
10302
11007
|
let text = stripFumadocsImports(included.content);
|
|
10303
11008
|
text = rewriteFumadocsCallouts(text);
|
|
10304
11009
|
text = rewriteFumadocsContainers(text);
|
|
10305
11010
|
text = rewriteFumadocsTabs(text);
|
|
10306
11011
|
const unsupported = unsupportedFumadocsComponents(text);
|
|
10307
|
-
const parsed =
|
|
11012
|
+
const parsed = frontmatter_default(text);
|
|
10308
11013
|
const { data, removed } = normalizeFumadocsPageMeta(parsed.data);
|
|
10309
|
-
const content = Object.keys(data).length > 0 ?
|
|
10310
|
-
await
|
|
10311
|
-
await
|
|
11014
|
+
const content = Object.keys(data).length > 0 ? frontmatter_default.stringify(parsed.content, data) : parsed.content;
|
|
11015
|
+
await mkdir8(dirname14(dest), { recursive: true });
|
|
11016
|
+
await writeFile11(dest, content, "utf-8");
|
|
10312
11017
|
await rm3(abs, { force: true });
|
|
10313
11018
|
return {
|
|
10314
11019
|
includeWarnings: included.warnings,
|
|
@@ -10318,39 +11023,56 @@ var movePage = async (abs, base, root) => {
|
|
|
10318
11023
|
unsupported
|
|
10319
11024
|
};
|
|
10320
11025
|
};
|
|
11026
|
+
var writeMeta = async (dest, meta, rel, warnings) => {
|
|
11027
|
+
if (Object.keys(meta).length === 0) {
|
|
11028
|
+
return warnings;
|
|
11029
|
+
}
|
|
11030
|
+
if (existsSync17(dest)) {
|
|
11031
|
+
return [...warnings, `Skipped ${rel} (target already exists)`];
|
|
11032
|
+
}
|
|
11033
|
+
await mkdir8(dirname14(dest), { recursive: true });
|
|
11034
|
+
await writeFile11(dest, renderMetaModule(meta), "utf-8");
|
|
11035
|
+
return warnings;
|
|
11036
|
+
};
|
|
10321
11037
|
var convertMeta = async (abs, base, root) => {
|
|
10322
|
-
const rel =
|
|
10323
|
-
const raw = await
|
|
11038
|
+
const rel = relative15(base, abs);
|
|
11039
|
+
const raw = await readFile17(abs, "utf-8");
|
|
10324
11040
|
let parsed;
|
|
10325
11041
|
try {
|
|
10326
11042
|
parsed = JSON.parse(raw);
|
|
10327
11043
|
} catch {
|
|
10328
|
-
const
|
|
10329
|
-
if (
|
|
11044
|
+
const dest2 = join29(root, "docs", rel);
|
|
11045
|
+
if (existsSync17(dest2)) {
|
|
10330
11046
|
return [`Skipped ${rel} (target already exists)`];
|
|
10331
11047
|
}
|
|
10332
|
-
await
|
|
10333
|
-
await
|
|
11048
|
+
await mkdir8(dirname14(dest2), { recursive: true });
|
|
11049
|
+
await rename3(abs, dest2);
|
|
10334
11050
|
return [
|
|
10335
11051
|
`Could not parse ${rel}; moved as-is — convert it to meta.ts by hand.`
|
|
10336
11052
|
];
|
|
10337
11053
|
}
|
|
10338
|
-
const
|
|
10339
|
-
const
|
|
10340
|
-
|
|
10341
|
-
|
|
10342
|
-
|
|
10343
|
-
|
|
10344
|
-
|
|
10345
|
-
}
|
|
10346
|
-
|
|
10347
|
-
|
|
10348
|
-
|
|
10349
|
-
|
|
10350
|
-
|
|
11054
|
+
const dir = dirname14(rel) === "." ? "" : dirname14(rel);
|
|
11055
|
+
const docsDir = join29(root, "docs", dir);
|
|
11056
|
+
const dest = join29(docsDir, "meta.ts");
|
|
11057
|
+
const structure = parseFumadocsPages(parsed.pages);
|
|
11058
|
+
if (structure.hasSections && !existsSync17(dest)) {
|
|
11059
|
+
const self = translateFumadocsSelfMeta(parsed);
|
|
11060
|
+
const reshape = await reshapeFumadocsGroups(structure, docsDir);
|
|
11061
|
+
const meta2 = { ...self.meta };
|
|
11062
|
+
if (reshape.order.length > 0) {
|
|
11063
|
+
meta2.pages = reshape.order;
|
|
11064
|
+
}
|
|
11065
|
+
const result2 = await writeMeta(dest, meta2, rel, [
|
|
11066
|
+
...self.warnings,
|
|
11067
|
+
...reshape.warnings
|
|
11068
|
+
]);
|
|
11069
|
+
await rm3(abs, { force: true });
|
|
11070
|
+
return result2;
|
|
10351
11071
|
}
|
|
11072
|
+
const { meta, warnings } = translateFumadocsMeta(parsed);
|
|
11073
|
+
const result = await writeMeta(dest, meta, rel, warnings);
|
|
10352
11074
|
await rm3(abs, { force: true });
|
|
10353
|
-
return
|
|
11075
|
+
return result;
|
|
10354
11076
|
};
|
|
10355
11077
|
var summarizePages = (results) => {
|
|
10356
11078
|
let moved = 0;
|
|
@@ -10380,9 +11102,9 @@ var summarizePages = (results) => {
|
|
|
10380
11102
|
};
|
|
10381
11103
|
};
|
|
10382
11104
|
var cleanupSourceDirs = async (root) => {
|
|
10383
|
-
const docs =
|
|
10384
|
-
if (
|
|
10385
|
-
const remaining = await
|
|
11105
|
+
const docs = join29(root, "content", "docs");
|
|
11106
|
+
if (existsSync17(docs)) {
|
|
11107
|
+
const remaining = await glob8(["**/*"], { cwd: docs, dot: true });
|
|
10386
11108
|
if (remaining.length > 0) {
|
|
10387
11109
|
return [
|
|
10388
11110
|
`Kept ${remaining.length} non-page file(s) under content/docs; move them into docs/ manually.`
|
|
@@ -10390,9 +11112,9 @@ var cleanupSourceDirs = async (root) => {
|
|
|
10390
11112
|
}
|
|
10391
11113
|
await rm3(docs, { force: true, recursive: true });
|
|
10392
11114
|
}
|
|
10393
|
-
const content =
|
|
10394
|
-
if (
|
|
10395
|
-
const remaining = await
|
|
11115
|
+
const content = join29(root, "content");
|
|
11116
|
+
if (existsSync17(content)) {
|
|
11117
|
+
const remaining = await glob8(["**/*"], { cwd: content, dot: true });
|
|
10396
11118
|
if (remaining.length === 0) {
|
|
10397
11119
|
await rm3(content, { force: true, recursive: true });
|
|
10398
11120
|
}
|
|
@@ -10401,8 +11123,8 @@ var cleanupSourceDirs = async (root) => {
|
|
|
10401
11123
|
};
|
|
10402
11124
|
var migrateFumadocsProject = async (root) => {
|
|
10403
11125
|
const { config, warnings: configWarnings } = await loadFumadocsConfig(root);
|
|
10404
|
-
const base =
|
|
10405
|
-
if (!
|
|
11126
|
+
const base = join29(root, SOURCE_DIR);
|
|
11127
|
+
if (!existsSync17(base)) {
|
|
10406
11128
|
await writeBlumeConfig(root, config);
|
|
10407
11129
|
return {
|
|
10408
11130
|
moved: 0,
|
|
@@ -10411,22 +11133,28 @@ var migrateFumadocsProject = async (root) => {
|
|
|
10411
11133
|
]
|
|
10412
11134
|
};
|
|
10413
11135
|
}
|
|
10414
|
-
const pageFiles = await
|
|
11136
|
+
const pageFiles = await glob8([PAGE_GLOB], {
|
|
10415
11137
|
absolute: true,
|
|
10416
11138
|
cwd: base,
|
|
10417
11139
|
ignore: IGNORE
|
|
10418
11140
|
});
|
|
10419
|
-
const metaFiles = await
|
|
11141
|
+
const metaFiles = await glob8([META_GLOB], {
|
|
10420
11142
|
absolute: true,
|
|
10421
11143
|
cwd: base,
|
|
10422
11144
|
ignore: IGNORE
|
|
10423
11145
|
});
|
|
10424
11146
|
const pageResults = await Promise.all(pageFiles.map((abs) => movePage(abs, base, root)));
|
|
10425
11147
|
const pages = summarizePages(pageResults);
|
|
10426
|
-
const
|
|
10427
|
-
const metaWarnings =
|
|
11148
|
+
const orderedMetas = metaFiles.toSorted((a, b) => b.split("/").length - a.split("/").length);
|
|
11149
|
+
const metaWarnings = [];
|
|
11150
|
+
for (const abs of orderedMetas) {
|
|
11151
|
+
metaWarnings.push(...await convertMeta(abs, base, root));
|
|
11152
|
+
}
|
|
10428
11153
|
await writeBlumeConfig(root, config);
|
|
10429
11154
|
const cleanupWarnings = await cleanupSourceDirs(root);
|
|
11155
|
+
const scriptsRewritten = await rewriteFrameworkScripts(root, /\bnext\b/u, /fumadocs/u);
|
|
11156
|
+
const gitignoreAdded = await ensureGitignore(root, [".blume/", "dist/"]);
|
|
11157
|
+
const leftovers = leftoverFiles(root, FUMADOCS_LEFTOVERS);
|
|
10430
11158
|
const warnings = [
|
|
10431
11159
|
...configWarnings,
|
|
10432
11160
|
...metaWarnings,
|
|
@@ -10440,15 +11168,24 @@ var migrateFumadocsProject = async (root) => {
|
|
|
10440
11168
|
if (pages.unsupported.length > 0) {
|
|
10441
11169
|
warnings.push(`Components without a drop-in Blume equivalent need manual review: ${pages.unsupported.join(", ")}.`);
|
|
10442
11170
|
}
|
|
11171
|
+
if (scriptsRewritten) {
|
|
11172
|
+
warnings.push("Repointed the dev/build/start scripts at the Blume CLI.");
|
|
11173
|
+
}
|
|
11174
|
+
if (gitignoreAdded.length > 0) {
|
|
11175
|
+
warnings.push(`Added ${gitignoreAdded.join(", ")} to .gitignore.`);
|
|
11176
|
+
}
|
|
11177
|
+
if (leftovers.length > 0) {
|
|
11178
|
+
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.`);
|
|
11179
|
+
}
|
|
10443
11180
|
warnings.push("Review blume.config.ts and the generated meta.ts files.");
|
|
10444
11181
|
return { moved: pages.moved, warnings };
|
|
10445
11182
|
};
|
|
10446
11183
|
|
|
10447
11184
|
// src/migrate/mintlify/index.ts
|
|
10448
|
-
import { existsSync as
|
|
10449
|
-
import { mkdir as
|
|
10450
|
-
import { dirname as
|
|
10451
|
-
import { glob as
|
|
11185
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
11186
|
+
import { mkdir as mkdir9, readFile as readFile18, rename as rename4, rm as rm4, writeFile as writeFile12 } from "node:fs/promises";
|
|
11187
|
+
import { dirname as dirname15, join as join30 } from "pathe";
|
|
11188
|
+
import { glob as glob9 } from "tinyglobby";
|
|
10452
11189
|
var prune = (value) => {
|
|
10453
11190
|
if (Array.isArray(value)) {
|
|
10454
11191
|
return value.map(prune);
|
|
@@ -10477,7 +11214,7 @@ var writeBlumeConfig2 = async (root, config) => {
|
|
|
10477
11214
|
|
|
10478
11215
|
export default defineConfig(${JSON.stringify(prune(config), null, 2)});
|
|
10479
11216
|
`;
|
|
10480
|
-
await
|
|
11217
|
+
await writeFile12(join30(root, "blume.config.ts"), body, "utf-8");
|
|
10481
11218
|
};
|
|
10482
11219
|
var relocateAssets = async (root, refs) => {
|
|
10483
11220
|
const segments = new Set;
|
|
@@ -10492,30 +11229,30 @@ var relocateAssets = async (root, refs) => {
|
|
|
10492
11229
|
}
|
|
10493
11230
|
const moved = [];
|
|
10494
11231
|
for (const segment of segments) {
|
|
10495
|
-
const source =
|
|
10496
|
-
if (!
|
|
11232
|
+
const source = join30(root, segment);
|
|
11233
|
+
if (!existsSync18(source) || segment === "public") {
|
|
10497
11234
|
continue;
|
|
10498
11235
|
}
|
|
10499
|
-
const dest =
|
|
10500
|
-
if (
|
|
11236
|
+
const dest = join30(root, "public", segment);
|
|
11237
|
+
if (existsSync18(dest)) {
|
|
10501
11238
|
continue;
|
|
10502
11239
|
}
|
|
10503
|
-
await
|
|
10504
|
-
await
|
|
11240
|
+
await mkdir9(join30(root, "public"), { recursive: true });
|
|
11241
|
+
await rename4(source, dest);
|
|
10505
11242
|
moved.push(segment);
|
|
10506
11243
|
}
|
|
10507
11244
|
return moved;
|
|
10508
11245
|
};
|
|
10509
11246
|
var cleanupSnippets = async (root, kept, warnings) => {
|
|
10510
|
-
const dir =
|
|
10511
|
-
if (!
|
|
11247
|
+
const dir = join30(root, "snippets");
|
|
11248
|
+
if (!existsSync18(dir)) {
|
|
10512
11249
|
return;
|
|
10513
11250
|
}
|
|
10514
|
-
const markdown = await
|
|
11251
|
+
const markdown = await glob9(["**/*.{md,mdx}"], { absolute: true, cwd: dir });
|
|
10515
11252
|
for (const file of markdown) {
|
|
10516
11253
|
await rm4(file, { force: true });
|
|
10517
11254
|
}
|
|
10518
|
-
const remaining = await
|
|
11255
|
+
const remaining = await glob9(["**/*"], { cwd: dir, dot: true });
|
|
10519
11256
|
if (remaining.length === 0) {
|
|
10520
11257
|
await rm4(dir, { force: true, recursive: true });
|
|
10521
11258
|
warnings.push("Inlined and removed the /snippets directory.");
|
|
@@ -10545,11 +11282,11 @@ var assetRefs = (config) => {
|
|
|
10545
11282
|
};
|
|
10546
11283
|
var migrateMintlifyProject = async (root) => {
|
|
10547
11284
|
const warnings = [];
|
|
10548
|
-
const configFile =
|
|
11285
|
+
const configFile = existsSync18(join30(root, "docs.json")) ? join30(root, "docs.json") : join30(root, "mint.json");
|
|
10549
11286
|
let config;
|
|
10550
|
-
if (
|
|
11287
|
+
if (existsSync18(configFile)) {
|
|
10551
11288
|
config = await loadMintlifyConfig(root, configFile);
|
|
10552
|
-
const spec = JSON.parse(await
|
|
11289
|
+
const spec = JSON.parse(await readFile18(configFile, "utf-8"));
|
|
10553
11290
|
const i18n = mintlifyI18n(spec);
|
|
10554
11291
|
if (i18n) {
|
|
10555
11292
|
config.i18n = i18n;
|
|
@@ -10564,7 +11301,7 @@ var migrateMintlifyProject = async (root) => {
|
|
|
10564
11301
|
}
|
|
10565
11302
|
const variables = config.variables ?? {};
|
|
10566
11303
|
config.variables = undefined;
|
|
10567
|
-
const files = await
|
|
11304
|
+
const files = await glob9(["**/*.{md,mdx}"], {
|
|
10568
11305
|
absolute: true,
|
|
10569
11306
|
cwd: root,
|
|
10570
11307
|
ignore: [
|
|
@@ -10580,15 +11317,15 @@ var migrateMintlifyProject = async (root) => {
|
|
|
10580
11317
|
const unsupported = new Set;
|
|
10581
11318
|
const keptComponents = new Set;
|
|
10582
11319
|
for (const file of files) {
|
|
10583
|
-
const raw = await
|
|
11320
|
+
const raw = await readFile18(file, "utf-8");
|
|
10584
11321
|
const result = await transformMintlifyContent(raw, {
|
|
10585
11322
|
filePath: file,
|
|
10586
11323
|
root,
|
|
10587
11324
|
variables
|
|
10588
11325
|
});
|
|
10589
11326
|
if (result.content !== raw) {
|
|
10590
|
-
await
|
|
10591
|
-
await
|
|
11327
|
+
await mkdir9(dirname15(file), { recursive: true });
|
|
11328
|
+
await writeFile12(file, result.content, "utf-8");
|
|
10592
11329
|
}
|
|
10593
11330
|
for (const key of result.removed) {
|
|
10594
11331
|
removedKeys.add(key);
|
|
@@ -10624,11 +11361,10 @@ var migrateMintlifyProject = async (root) => {
|
|
|
10624
11361
|
};
|
|
10625
11362
|
|
|
10626
11363
|
// src/migrate/nextra/index.ts
|
|
10627
|
-
import { existsSync as
|
|
10628
|
-
import { mkdir as
|
|
10629
|
-
import
|
|
10630
|
-
import {
|
|
10631
|
-
import { glob as glob9 } from "tinyglobby";
|
|
11364
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
11365
|
+
import { mkdir as mkdir10, readFile as readFile19, rename as rename5, rm as rm5, writeFile as writeFile13 } from "node:fs/promises";
|
|
11366
|
+
import { basename as basename7, dirname as dirname16, extname as extname6, join as join31, relative as relative16 } from "pathe";
|
|
11367
|
+
import { glob as glob10 } from "tinyglobby";
|
|
10632
11368
|
|
|
10633
11369
|
// src/migrate/nextra/content.ts
|
|
10634
11370
|
var CALLOUT_TYPE_DIRECTIVES3 = {
|
|
@@ -10857,30 +11593,30 @@ var indexFolders = (base, pageFiles, metaFiles) => {
|
|
|
10857
11593
|
let current = normalizeDir(dir);
|
|
10858
11594
|
allDirs.add(current);
|
|
10859
11595
|
while (current !== "") {
|
|
10860
|
-
current = normalizeDir(
|
|
11596
|
+
current = normalizeDir(dirname16(current));
|
|
10861
11597
|
allDirs.add(current);
|
|
10862
11598
|
}
|
|
10863
11599
|
};
|
|
10864
11600
|
for (const abs of pageFiles) {
|
|
10865
|
-
const rel =
|
|
10866
|
-
const dir = normalizeDir(
|
|
10867
|
-
const slug =
|
|
11601
|
+
const rel = relative16(base, abs);
|
|
11602
|
+
const dir = normalizeDir(dirname16(rel));
|
|
11603
|
+
const slug = basename7(rel).replace(/\.mdx?$/u, "");
|
|
10868
11604
|
const folder = pagesByDir.get(dir) ?? new Map;
|
|
10869
11605
|
folder.set(slug, abs);
|
|
10870
11606
|
pagesByDir.set(dir, folder);
|
|
10871
11607
|
registerDir(dir);
|
|
10872
11608
|
}
|
|
10873
11609
|
for (const abs of metaFiles) {
|
|
10874
|
-
registerDir(normalizeDir(
|
|
11610
|
+
registerDir(normalizeDir(dirname16(relative16(base, abs))));
|
|
10875
11611
|
}
|
|
10876
11612
|
const childDirs = new Map;
|
|
10877
11613
|
for (const dir of allDirs) {
|
|
10878
11614
|
if (dir === "") {
|
|
10879
11615
|
continue;
|
|
10880
11616
|
}
|
|
10881
|
-
const parent = normalizeDir(
|
|
11617
|
+
const parent = normalizeDir(dirname16(dir));
|
|
10882
11618
|
const children = childDirs.get(parent) ?? new Set;
|
|
10883
|
-
children.add(
|
|
11619
|
+
children.add(basename7(dir));
|
|
10884
11620
|
childDirs.set(parent, children);
|
|
10885
11621
|
}
|
|
10886
11622
|
return { childDirs, pagesByDir };
|
|
@@ -10896,7 +11632,7 @@ var planMetas = (metas, index) => {
|
|
|
10896
11632
|
warnings: []
|
|
10897
11633
|
};
|
|
10898
11634
|
for (const meta of metas) {
|
|
10899
|
-
const dir = normalizeDir(
|
|
11635
|
+
const dir = normalizeDir(dirname16(meta.rel));
|
|
10900
11636
|
const entries = parseNextraMeta(meta.raw, meta.ext);
|
|
10901
11637
|
if (!entries) {
|
|
10902
11638
|
plan.unparseableMetas.push({ abs: meta.abs, rel: meta.rel });
|
|
@@ -10909,7 +11645,7 @@ var planMetas = (metas, index) => {
|
|
|
10909
11645
|
plan.metaByDir.set(dir, conversion.folderMeta);
|
|
10910
11646
|
plan.consumedMetas.push(meta.abs);
|
|
10911
11647
|
for (const [slug, title] of Object.entries(conversion.folderTitles)) {
|
|
10912
|
-
plan.folderTitleByDir.set(normalizeDir(
|
|
11648
|
+
plan.folderTitleByDir.set(normalizeDir(join31(dir, slug)), title);
|
|
10913
11649
|
}
|
|
10914
11650
|
for (const [slug, label] of Object.entries(conversion.pageLabels)) {
|
|
10915
11651
|
const pageAbs = index.pagesByDir.get(dir)?.get(slug);
|
|
@@ -10933,19 +11669,19 @@ var planMetas = (metas, index) => {
|
|
|
10933
11669
|
return plan;
|
|
10934
11670
|
};
|
|
10935
11671
|
var movePage2 = async (abs, options) => {
|
|
10936
|
-
const rel =
|
|
10937
|
-
const dest =
|
|
10938
|
-
if (
|
|
11672
|
+
const rel = relative16(options.base, abs);
|
|
11673
|
+
const dest = join31(options.root, "docs", rel);
|
|
11674
|
+
if (existsSync19(dest)) {
|
|
10939
11675
|
return { moved: 0, removed: [], skipped: rel, unsupported: [] };
|
|
10940
11676
|
}
|
|
10941
|
-
const raw = await
|
|
11677
|
+
const raw = await readFile19(abs, "utf-8");
|
|
10942
11678
|
const text = rewriteNextraCallouts(stripNextraImports(raw));
|
|
10943
11679
|
const unsupported = unsupportedNextraComponents(text);
|
|
10944
|
-
const parsed =
|
|
11680
|
+
const parsed = frontmatter_default(text);
|
|
10945
11681
|
const { data, removed } = normalizeNextraPageMeta(parsed.data, options.overrides.get(abs) ?? {});
|
|
10946
|
-
const content = Object.keys(data).length > 0 ?
|
|
10947
|
-
await
|
|
10948
|
-
await
|
|
11682
|
+
const content = Object.keys(data).length > 0 ? frontmatter_default.stringify(parsed.content, data) : parsed.content;
|
|
11683
|
+
await mkdir10(dirname16(dest), { recursive: true });
|
|
11684
|
+
await writeFile13(dest, content, "utf-8");
|
|
10949
11685
|
await rm5(abs, { force: true });
|
|
10950
11686
|
return { moved: 1, removed, skipped: null, unsupported };
|
|
10951
11687
|
};
|
|
@@ -10987,9 +11723,9 @@ var writeFolderMetas = async (root, plan) => {
|
|
|
10987
11723
|
if (Object.keys(finalMeta).length === 0) {
|
|
10988
11724
|
return;
|
|
10989
11725
|
}
|
|
10990
|
-
const dest =
|
|
10991
|
-
await
|
|
10992
|
-
await
|
|
11726
|
+
const dest = join31(root, "docs", dir, "meta.ts");
|
|
11727
|
+
await mkdir10(dirname16(dest), { recursive: true });
|
|
11728
|
+
await writeFile13(dest, `import { defineMeta } from "blume";
|
|
10993
11729
|
|
|
10994
11730
|
export default defineMeta(${JSON.stringify(finalMeta, null, 2)});
|
|
10995
11731
|
`, "utf-8");
|
|
@@ -10998,20 +11734,20 @@ export default defineMeta(${JSON.stringify(finalMeta, null, 2)});
|
|
|
10998
11734
|
var relocateUnparseableMetas = async (root, metas) => {
|
|
10999
11735
|
const warnings = [];
|
|
11000
11736
|
await Promise.all(metas.map(async ({ abs, rel }) => {
|
|
11001
|
-
const dest =
|
|
11002
|
-
if (
|
|
11737
|
+
const dest = join31(root, "docs", rel);
|
|
11738
|
+
if (existsSync19(dest)) {
|
|
11003
11739
|
warnings.push(`Skipped ${rel} (target already exists)`);
|
|
11004
11740
|
return;
|
|
11005
11741
|
}
|
|
11006
|
-
await
|
|
11007
|
-
await
|
|
11742
|
+
await mkdir10(dirname16(dest), { recursive: true });
|
|
11743
|
+
await rename5(abs, dest);
|
|
11008
11744
|
warnings.push(`Could not parse ${rel}; moved as-is — convert it to meta.ts by hand.`);
|
|
11009
11745
|
}));
|
|
11010
11746
|
return warnings;
|
|
11011
11747
|
};
|
|
11012
11748
|
var buildConfig = (tabs) => tabs.length > 0 ? { navigation: { tabs }, title: "Documentation" } : { title: "Documentation" };
|
|
11013
11749
|
var migrateNextraProject = async (root) => {
|
|
11014
|
-
const sourceDir = SOURCE_DIRS.find((dir) =>
|
|
11750
|
+
const sourceDir = SOURCE_DIRS.find((dir) => existsSync19(join31(root, dir)));
|
|
11015
11751
|
if (!sourceDir) {
|
|
11016
11752
|
await writeBlumeConfig(root, { title: "Documentation" });
|
|
11017
11753
|
return {
|
|
@@ -11021,13 +11757,13 @@ var migrateNextraProject = async (root) => {
|
|
|
11021
11757
|
]
|
|
11022
11758
|
};
|
|
11023
11759
|
}
|
|
11024
|
-
const base =
|
|
11025
|
-
const pageFiles = await
|
|
11760
|
+
const base = join31(root, sourceDir);
|
|
11761
|
+
const pageFiles = await glob10([PAGE_GLOB2], {
|
|
11026
11762
|
absolute: true,
|
|
11027
11763
|
cwd: base,
|
|
11028
11764
|
ignore: IGNORE2
|
|
11029
11765
|
});
|
|
11030
|
-
const metaFiles = await
|
|
11766
|
+
const metaFiles = await glob10([META_GLOB2], {
|
|
11031
11767
|
absolute: true,
|
|
11032
11768
|
cwd: base,
|
|
11033
11769
|
ignore: IGNORE2
|
|
@@ -11036,8 +11772,8 @@ var migrateNextraProject = async (root) => {
|
|
|
11036
11772
|
const metas = await Promise.all(metaFiles.map(async (abs) => ({
|
|
11037
11773
|
abs,
|
|
11038
11774
|
ext: extname6(abs),
|
|
11039
|
-
raw: await
|
|
11040
|
-
rel:
|
|
11775
|
+
raw: await readFile19(abs, "utf-8"),
|
|
11776
|
+
rel: relative16(base, abs)
|
|
11041
11777
|
})));
|
|
11042
11778
|
const plan = planMetas(metas, index);
|
|
11043
11779
|
const moves = await Promise.all(pageFiles.map((abs) => movePage2(abs, { base, overrides: plan.pageOverrides, root })));
|
|
@@ -11062,16 +11798,15 @@ var migrateNextraProject = async (root) => {
|
|
|
11062
11798
|
};
|
|
11063
11799
|
|
|
11064
11800
|
// src/migrate/starlight/index.ts
|
|
11065
|
-
import { existsSync as
|
|
11066
|
-
import { readFile as
|
|
11067
|
-
import
|
|
11068
|
-
import {
|
|
11069
|
-
import { glob as glob10 } from "tinyglobby";
|
|
11801
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
11802
|
+
import { readFile as readFile21, writeFile as writeFile14 } from "node:fs/promises";
|
|
11803
|
+
import { join as join33 } from "pathe";
|
|
11804
|
+
import { glob as glob11 } from "tinyglobby";
|
|
11070
11805
|
|
|
11071
11806
|
// src/migrate/starlight/config.ts
|
|
11072
|
-
import { existsSync as
|
|
11073
|
-
import { readFile as
|
|
11074
|
-
import { join as
|
|
11807
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
11808
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
11809
|
+
import { join as join32 } from "pathe";
|
|
11075
11810
|
var CONFIG_FILES = [
|
|
11076
11811
|
"astro.config.mjs",
|
|
11077
11812
|
"astro.config.mts",
|
|
@@ -11102,7 +11837,7 @@ var extractStarlightOptions = (source) => {
|
|
|
11102
11837
|
return isLiteralObject(parsed) ? parsed : "unparseable";
|
|
11103
11838
|
};
|
|
11104
11839
|
var loadStarlightConfig = async (root) => {
|
|
11105
|
-
const file = CONFIG_FILES.map((name) =>
|
|
11840
|
+
const file = CONFIG_FILES.map((name) => join32(root, name)).find((path) => existsSync20(path));
|
|
11106
11841
|
if (!file) {
|
|
11107
11842
|
return {
|
|
11108
11843
|
options: {},
|
|
@@ -11111,7 +11846,7 @@ var loadStarlightConfig = async (root) => {
|
|
|
11111
11846
|
]
|
|
11112
11847
|
};
|
|
11113
11848
|
}
|
|
11114
|
-
const source = await
|
|
11849
|
+
const source = await readFile20(file, "utf-8");
|
|
11115
11850
|
const result = extractStarlightOptions(source);
|
|
11116
11851
|
if (result === "missing") {
|
|
11117
11852
|
return {
|
|
@@ -11512,17 +12247,17 @@ var starlightI18n = (options) => {
|
|
|
11512
12247
|
// src/migrate/starlight/index.ts
|
|
11513
12248
|
var CONTENT_DIR = "src/content/docs";
|
|
11514
12249
|
var transformPage = async (file) => {
|
|
11515
|
-
const raw = await
|
|
12250
|
+
const raw = await readFile21(file, "utf-8");
|
|
11516
12251
|
let text = stripStarlightImports(raw);
|
|
11517
12252
|
text = rewriteStarlightAsides(text);
|
|
11518
12253
|
text = rewriteStarlightComponents(text);
|
|
11519
12254
|
const unsupported = unsupportedStarlightComponents(text);
|
|
11520
12255
|
const aliased = hasAliasedAssets(text);
|
|
11521
|
-
const parsed =
|
|
12256
|
+
const parsed = frontmatter_default(text);
|
|
11522
12257
|
const { data, removed } = normalizeStarlightPageMeta(parsed.data);
|
|
11523
|
-
const content = Object.keys(data).length > 0 ?
|
|
12258
|
+
const content = Object.keys(data).length > 0 ? frontmatter_default.stringify(parsed.content, data) : parsed.content;
|
|
11524
12259
|
if (content !== raw) {
|
|
11525
|
-
await
|
|
12260
|
+
await writeFile14(file, content, "utf-8");
|
|
11526
12261
|
}
|
|
11527
12262
|
return { aliased, removed, unsupported };
|
|
11528
12263
|
};
|
|
@@ -11534,8 +12269,8 @@ var migrateStarlightProject = async (root) => {
|
|
|
11534
12269
|
config.i18n = i18n;
|
|
11535
12270
|
warnings.push(`Mapped ${i18n.locales.length} locale(s) to i18n (default: ${i18n.defaultLocale}); review the locale labels.`);
|
|
11536
12271
|
}
|
|
11537
|
-
const base =
|
|
11538
|
-
if (!
|
|
12272
|
+
const base = join33(root, CONTENT_DIR);
|
|
12273
|
+
if (!existsSync21(base)) {
|
|
11539
12274
|
await writeBlumeConfig(root, config);
|
|
11540
12275
|
return {
|
|
11541
12276
|
moved: 0,
|
|
@@ -11545,7 +12280,7 @@ var migrateStarlightProject = async (root) => {
|
|
|
11545
12280
|
]
|
|
11546
12281
|
};
|
|
11547
12282
|
}
|
|
11548
|
-
const files = await
|
|
12283
|
+
const files = await glob11(["**/*.{md,mdx}"], { absolute: true, cwd: base });
|
|
11549
12284
|
const results = await Promise.all(files.map(transformPage));
|
|
11550
12285
|
await writeBlumeConfig(root, config);
|
|
11551
12286
|
const removedKeys = new Set;
|
|
@@ -11623,10 +12358,10 @@ var migrateCommand = defineCommand7({
|
|
|
11623
12358
|
});
|
|
11624
12359
|
|
|
11625
12360
|
// src/cli/commands/preview.ts
|
|
11626
|
-
import { existsSync as
|
|
12361
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
11627
12362
|
import { preview } from "astro";
|
|
11628
12363
|
import { defineCommand as defineCommand8 } from "citty";
|
|
11629
|
-
import { join as
|
|
12364
|
+
import { join as join34 } from "pathe";
|
|
11630
12365
|
var previewCommand = defineCommand8({
|
|
11631
12366
|
args: {
|
|
11632
12367
|
host: { description: "Network host to bind.", type: "string" },
|
|
@@ -11640,7 +12375,7 @@ var previewCommand = defineCommand8({
|
|
|
11640
12375
|
const root = process.cwd();
|
|
11641
12376
|
const { config } = await loadConfig(root);
|
|
11642
12377
|
const context = resolveProjectContext(root, config);
|
|
11643
|
-
if (!
|
|
12378
|
+
if (!existsSync22(join34(context.outDir, "astro.config.mjs"))) {
|
|
11644
12379
|
logger.error("No build found. Run `blume build` first.");
|
|
11645
12380
|
process.exit(1);
|
|
11646
12381
|
}
|
|
@@ -11658,7 +12393,7 @@ var previewCommand = defineCommand8({
|
|
|
11658
12393
|
// src/cli/commands/sync.ts
|
|
11659
12394
|
import { rm as rm6 } from "node:fs/promises";
|
|
11660
12395
|
import { defineCommand as defineCommand9 } from "citty";
|
|
11661
|
-
import { join as
|
|
12396
|
+
import { join as join35 } from "pathe";
|
|
11662
12397
|
var syncCommand = defineCommand9({
|
|
11663
12398
|
args: {
|
|
11664
12399
|
force: {
|
|
@@ -11680,7 +12415,7 @@ var syncCommand = defineCommand9({
|
|
|
11680
12415
|
if (args.force) {
|
|
11681
12416
|
const { config } = await loadConfig(root);
|
|
11682
12417
|
const context = resolveProjectContext(root, config);
|
|
11683
|
-
await rm6(
|
|
12418
|
+
await rm6(join35(context.outDir, "cache"), { force: true, recursive: true });
|
|
11684
12419
|
logger.info("Cleared source cache.");
|
|
11685
12420
|
}
|
|
11686
12421
|
await prepareProject({
|
|
@@ -11695,13 +12430,13 @@ var syncCommand = defineCommand9({
|
|
|
11695
12430
|
});
|
|
11696
12431
|
|
|
11697
12432
|
// src/cli/commands/validate.ts
|
|
11698
|
-
import { existsSync as
|
|
12433
|
+
import { existsSync as existsSync24 } from "node:fs";
|
|
11699
12434
|
import { defineCommand as defineCommand10 } from "citty";
|
|
11700
|
-
import { join as
|
|
12435
|
+
import { join as join37 } from "pathe";
|
|
11701
12436
|
|
|
11702
12437
|
// src/core/links.ts
|
|
11703
|
-
import { existsSync as
|
|
11704
|
-
import { join as
|
|
12438
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
12439
|
+
import { join as join36 } from "pathe";
|
|
11705
12440
|
var HTTP = /^https?:\/\//iu;
|
|
11706
12441
|
var PROTOCOL_RELATIVE = /^\/\//u;
|
|
11707
12442
|
var SCHEME = /^[a-z][a-z0-9+.-]*:/iu;
|
|
@@ -11761,7 +12496,7 @@ var checkPathLink = (resolved, fragment, target, site, ctx) => {
|
|
|
11761
12496
|
if (ctx.publicDir === null) {
|
|
11762
12497
|
return "asset-unchecked";
|
|
11763
12498
|
}
|
|
11764
|
-
if (
|
|
12499
|
+
if (existsSync23(join36(ctx.publicDir, resolved))) {
|
|
11765
12500
|
return null;
|
|
11766
12501
|
}
|
|
11767
12502
|
return {
|
|
@@ -11773,16 +12508,19 @@ var checkPathLink = (resolved, fragment, target, site, ctx) => {
|
|
|
11773
12508
|
};
|
|
11774
12509
|
}
|
|
11775
12510
|
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
|
-
};
|
|
12511
|
+
if (ctx.routes.has(route)) {
|
|
12512
|
+
return fragment ? checkAnchor(route, fragment, site, ctx) : null;
|
|
12513
|
+
}
|
|
12514
|
+
if (ctx.redirects.has(route)) {
|
|
12515
|
+
return null;
|
|
11784
12516
|
}
|
|
11785
|
-
return
|
|
12517
|
+
return {
|
|
12518
|
+
...site,
|
|
12519
|
+
code: "BLUME_BROKEN_LINK",
|
|
12520
|
+
message: `Broken link to ${target}: no page resolves to ${route}.`,
|
|
12521
|
+
severity: "error",
|
|
12522
|
+
suggestion: "Check the path, or create the target page."
|
|
12523
|
+
};
|
|
11786
12524
|
};
|
|
11787
12525
|
var request = async (url, method) => {
|
|
11788
12526
|
const controller = new AbortController;
|
|
@@ -11891,6 +12629,7 @@ var validateLinks = async (graph, options) => {
|
|
|
11891
12629
|
const ctx = {
|
|
11892
12630
|
anchors: buildAnchorIndex(graph.pages),
|
|
11893
12631
|
publicDir: options.publicDir,
|
|
12632
|
+
redirects: new Set((options.redirects ?? []).map((redirect) => toRoute(redirect.from))),
|
|
11894
12633
|
routes: new Set(graph.routes.keys())
|
|
11895
12634
|
};
|
|
11896
12635
|
const diagnostics = [];
|
|
@@ -11941,10 +12680,11 @@ var validateCommand = defineCommand10({
|
|
|
11941
12680
|
try {
|
|
11942
12681
|
const project = await scanProject(root, { mode: "build" });
|
|
11943
12682
|
diagnostics.push(...project.diagnostics);
|
|
11944
|
-
const publicDir =
|
|
12683
|
+
const publicDir = join37(root, "public");
|
|
11945
12684
|
diagnostics.push(...await validateLinks(project.graph, {
|
|
11946
12685
|
checkExternal: Boolean(args.external),
|
|
11947
|
-
publicDir:
|
|
12686
|
+
publicDir: existsSync24(publicDir) ? publicDir : null,
|
|
12687
|
+
redirects: project.config.redirects
|
|
11948
12688
|
}));
|
|
11949
12689
|
} catch (error) {
|
|
11950
12690
|
if (error instanceof BlumeError) {
|
|
@@ -11985,5 +12725,5 @@ var main = defineCommand11({
|
|
|
11985
12725
|
});
|
|
11986
12726
|
runMain(main);
|
|
11987
12727
|
|
|
11988
|
-
//# debugId=
|
|
12728
|
+
//# debugId=C5E764B7F3B6157B64756E2164756E21
|
|
11989
12729
|
//# sourceMappingURL=index.js.map
|