blume 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1170 -820
- package/dist/cli/index.js.map +32 -27
- package/dist/types/core/data.d.ts +2 -0
- package/dist/types/core/project.d.ts +12 -2
- package/dist/types/core/schema.d.ts +154 -41
- package/dist/types/core/types.d.ts +7 -6
- package/dist/types/migrate/mintlify/config.d.ts +14 -0
- package/docs/01-quickstart.mdx +6 -2
- package/docs/02-deployment.mdx +3 -1
- package/docs/advanced/api-reference.mdx +37 -23
- package/docs/advanced/bridge.mdx +76 -0
- package/docs/advanced/custom-pages.mdx +3 -1
- package/docs/advanced/meta.ts +8 -1
- package/docs/advanced/migrate.mdx +123 -0
- package/docs/configuration/ai.mdx +3 -1
- package/docs/configuration/analytics.mdx +3 -1
- package/docs/configuration/export.mdx +6 -2
- package/docs/configuration/index.mdx +1 -1
- package/docs/configuration/seo.mdx +3 -1
- package/docs/content/components.mdx +55 -2
- package/docs/content/i18n.mdx +6 -2
- package/docs/content/islands.mdx +6 -2
- package/docs/content/meta.mdx +3 -1
- package/docs/content/syntax.mdx +40 -14
- package/docs/index.mdx +2 -2
- package/docs/reference/cli.mdx +29 -1
- package/docs/reference/frontmatter.mdx +5 -0
- package/package.json +11 -1
- package/src/astro/generate.ts +18 -9
- package/src/astro/templates.ts +28 -4
- package/src/cli/commands/build.ts +107 -63
- package/src/cli/commands/check.ts +20 -0
- package/src/cli/dev-lock.ts +13 -5
- package/src/cli/prepare.ts +3 -0
- package/src/components/BlumePage.astro +6 -0
- package/src/components/Icon.astro +13 -10
- package/src/components/content/ApiField.astro +75 -0
- package/src/components/content/ParamField.astro +39 -0
- package/src/components/content/RequestField.astro +23 -0
- package/src/components/content/ResponseField.astro +23 -0
- package/src/components/content/Step.astro +1 -1
- package/src/components/layout/Breadcrumbs.astro +7 -2
- package/src/components/layout/NavTree.astro +24 -8
- package/src/components/layout/RootLayout.astro +56 -34
- package/src/components/layout/Search.astro +1 -1
- package/src/components/openapi/ApiOverview.astro +84 -0
- package/src/components/openapi/MethodBadge.astro +28 -0
- package/src/components/openapi/Operation.astro +140 -0
- package/src/components/openapi/ParametersTable.astro +97 -0
- package/src/components/openapi/RequestBody.astro +58 -0
- package/src/components/openapi/RequestPanel.astro +169 -0
- package/src/components/openapi/Responses.astro +91 -0
- package/src/components/openapi/SchemaProperty.astro +118 -0
- package/src/components/openapi/SchemaTable.astro +86 -0
- package/src/components/openapi/helpers.ts +238 -0
- package/src/components/openapi/panel.ts +59 -0
- package/src/components/openapi/snippets.ts +201 -0
- package/src/core/builtin-tags.ts +5 -0
- package/src/core/data.ts +2 -0
- package/src/core/graph.ts +0 -3
- package/src/core/nav-diagnostics.ts +2 -12
- package/src/core/navigation.ts +0 -10
- package/src/core/project-graph.ts +5 -1
- package/src/core/project.ts +25 -3
- package/src/core/schema.ts +47 -14
- package/src/core/sources/mintlify.ts +1 -1
- package/src/core/sources/resolve.ts +28 -6
- package/src/core/types.ts +7 -7
- package/src/migrate/mintlify/config.ts +190 -97
- package/src/migrate/mintlify/content.ts +24 -2
- package/src/migrate/mintlify/index.ts +76 -2
- package/src/migrate/mintlify/transform.ts +2 -0
- package/src/openapi/model.ts +174 -0
- package/src/openapi/parse.ts +48 -0
- package/src/openapi/references.ts +164 -0
- package/src/openapi/render-mdx.ts +76 -0
- package/src/openapi/scalar.ts +15 -103
- package/src/openapi/source.ts +140 -0
- package/src/registry/eject.ts +15 -2
- package/src/theme/chrome-icons.ts +22 -0
- package/src/theme/icons.ts +151 -161
package/dist/cli/index.js
CHANGED
|
@@ -513,11 +513,11 @@ Next steps:
|
|
|
513
513
|
});
|
|
514
514
|
|
|
515
515
|
// src/cli/commands/build.ts
|
|
516
|
-
import { existsSync as
|
|
517
|
-
import { readdir, stat, writeFile as
|
|
516
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
517
|
+
import { readdir, stat, writeFile as writeFile7 } from "node:fs/promises";
|
|
518
518
|
import { build } from "astro";
|
|
519
519
|
import { defineCommand as defineCommand2 } from "citty";
|
|
520
|
-
import { join as
|
|
520
|
+
import { join as join28 } from "pathe";
|
|
521
521
|
|
|
522
522
|
// src/core/frontmatter.ts
|
|
523
523
|
import baseMatter from "gray-matter";
|
|
@@ -608,6 +608,29 @@ var buildLlmsFiles = async (project) => ({
|
|
|
608
608
|
index: buildIndex(project)
|
|
609
609
|
});
|
|
610
610
|
|
|
611
|
+
// src/core/gitignore.ts
|
|
612
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
613
|
+
import { readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
614
|
+
import { join as join5 } from "pathe";
|
|
615
|
+
var gitignoreKey = (line) => line.trim().replace(/\/+$/u, "");
|
|
616
|
+
var ensureGitignore = async (root, entries) => {
|
|
617
|
+
const path = join5(root, ".gitignore");
|
|
618
|
+
const existing = existsSync3(path) ? await readFile3(path, "utf-8") : "";
|
|
619
|
+
const present = new Set(existing.split(`
|
|
620
|
+
`).map(gitignoreKey).filter(Boolean));
|
|
621
|
+
const added = entries.filter((entry) => !present.has(gitignoreKey(entry)));
|
|
622
|
+
if (added.length === 0) {
|
|
623
|
+
return [];
|
|
624
|
+
}
|
|
625
|
+
const gap = existing.length > 0 && !existing.endsWith(`
|
|
626
|
+
`) ? `
|
|
627
|
+
` : "";
|
|
628
|
+
await writeFile2(path, `${existing}${gap}${added.join(`
|
|
629
|
+
`)}
|
|
630
|
+
`, "utf-8");
|
|
631
|
+
return added;
|
|
632
|
+
};
|
|
633
|
+
|
|
611
634
|
// src/search/providers.ts
|
|
612
635
|
var SEARCH_PROVIDERS = {
|
|
613
636
|
algolia: {
|
|
@@ -739,7 +762,7 @@ ${urls.join(`
|
|
|
739
762
|
};
|
|
740
763
|
|
|
741
764
|
// src/search/build.ts
|
|
742
|
-
import { join as
|
|
765
|
+
import { join as join6 } from "pathe";
|
|
743
766
|
var buildSearchIndex = async (outDir) => {
|
|
744
767
|
const pagefind = await import("pagefind");
|
|
745
768
|
const { index } = await pagefind.createIndex({});
|
|
@@ -747,7 +770,7 @@ var buildSearchIndex = async (outDir) => {
|
|
|
747
770
|
throw new Error("Failed to create Pagefind index.");
|
|
748
771
|
}
|
|
749
772
|
const result = await index.addDirectory({ path: outDir });
|
|
750
|
-
await index.writeFiles({ outputPath:
|
|
773
|
+
await index.writeFiles({ outputPath: join6(outDir, "pagefind") });
|
|
751
774
|
await pagefind.close();
|
|
752
775
|
return result.page_count;
|
|
753
776
|
};
|
|
@@ -2791,17 +2814,59 @@ var syncSearchProvider = async (project, reporter) => {
|
|
|
2791
2814
|
|
|
2792
2815
|
// src/cli/dev-lock.ts
|
|
2793
2816
|
import {
|
|
2794
|
-
existsSync as
|
|
2817
|
+
existsSync as existsSync5,
|
|
2795
2818
|
mkdirSync,
|
|
2796
2819
|
readFileSync as readFileSync2,
|
|
2797
2820
|
rmSync,
|
|
2798
2821
|
writeFileSync
|
|
2799
2822
|
} from "node:fs";
|
|
2800
|
-
import { join as
|
|
2801
|
-
|
|
2823
|
+
import { join as join8 } from "pathe";
|
|
2824
|
+
|
|
2825
|
+
// src/core/project.ts
|
|
2826
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
2827
|
+
import { isAbsolute, join as join7, resolve as resolve2 } from "pathe";
|
|
2828
|
+
var CONFIG_FILENAMES = [
|
|
2829
|
+
"blume.config.ts",
|
|
2830
|
+
"blume.config.mjs",
|
|
2831
|
+
"blume.config.js"
|
|
2832
|
+
];
|
|
2833
|
+
var THEME_FILENAMES = ["theme.css"];
|
|
2834
|
+
var COMPONENTS_FILENAMES = ["components.tsx", "components.ts"];
|
|
2835
|
+
var firstExisting = (root, names) => {
|
|
2836
|
+
for (const name of names) {
|
|
2837
|
+
const candidate = join7(root, name);
|
|
2838
|
+
if (existsSync4(candidate)) {
|
|
2839
|
+
return candidate;
|
|
2840
|
+
}
|
|
2841
|
+
}
|
|
2842
|
+
return null;
|
|
2843
|
+
};
|
|
2844
|
+
var findConfigFile = (root) => firstExisting(root, CONFIG_FILENAMES);
|
|
2845
|
+
var resolveRuntimeDir = (root, runtimeDir = ".blume") => isAbsolute(runtimeDir) ? runtimeDir : join7(resolve2(root), runtimeDir);
|
|
2846
|
+
var resolveProjectContext = (root, config, options) => {
|
|
2847
|
+
const absoluteRoot = resolve2(root);
|
|
2848
|
+
const contentRoot = isAbsolute(config.content.root) ? config.content.root : join7(absoluteRoot, config.content.root);
|
|
2849
|
+
const pagesPath = join7(absoluteRoot, config.content.pages);
|
|
2850
|
+
const pagesRoot = existsSync4(pagesPath) ? pagesPath : null;
|
|
2851
|
+
const outDir = resolveRuntimeDir(absoluteRoot, options?.runtimeDir);
|
|
2852
|
+
const distDir = options?.runtimeDir ? join7(outDir, "dist") : join7(absoluteRoot, "dist");
|
|
2853
|
+
return {
|
|
2854
|
+
componentsFile: firstExisting(absoluteRoot, COMPONENTS_FILENAMES),
|
|
2855
|
+
configFile: findConfigFile(absoluteRoot),
|
|
2856
|
+
contentRoot,
|
|
2857
|
+
distDir,
|
|
2858
|
+
outDir,
|
|
2859
|
+
pagesRoot,
|
|
2860
|
+
root: absoluteRoot,
|
|
2861
|
+
themeFile: firstExisting(absoluteRoot, THEME_FILENAMES)
|
|
2862
|
+
};
|
|
2863
|
+
};
|
|
2864
|
+
|
|
2865
|
+
// src/cli/dev-lock.ts
|
|
2866
|
+
var lockPath = (outDir) => join8(outDir, "dev.lock");
|
|
2802
2867
|
var isDevLocked = (outDir) => {
|
|
2803
2868
|
const path = lockPath(outDir);
|
|
2804
|
-
if (!
|
|
2869
|
+
if (!existsSync5(path)) {
|
|
2805
2870
|
return false;
|
|
2806
2871
|
}
|
|
2807
2872
|
const pid = Number.parseInt(readFileSync2(path, "utf-8").trim(), 10);
|
|
@@ -2826,33 +2891,33 @@ var acquireDevLock = (outDir) => {
|
|
|
2826
2891
|
}
|
|
2827
2892
|
released = true;
|
|
2828
2893
|
try {
|
|
2829
|
-
if (
|
|
2894
|
+
if (existsSync5(path) && readFileSync2(path, "utf-8").trim() === String(process.pid)) {
|
|
2830
2895
|
rmSync(path, { force: true });
|
|
2831
2896
|
}
|
|
2832
2897
|
} catch {}
|
|
2833
2898
|
};
|
|
2834
2899
|
};
|
|
2835
|
-
var refuseIfDevRunning = (root, action) => {
|
|
2836
|
-
if (isDevLocked(
|
|
2837
|
-
logger.error(`A \`blume dev\` server is running against .blume; ${action} would corrupt it. Stop the dev server
|
|
2900
|
+
var refuseIfDevRunning = (root, action, runtimeDir) => {
|
|
2901
|
+
if (isDevLocked(resolveRuntimeDir(root, runtimeDir))) {
|
|
2902
|
+
logger.error(`A \`blume dev\` server is running against .blume; ${action} would corrupt it. Stop the dev server, or re-run with --isolated to build/verify against .blume-verify without touching it.`);
|
|
2838
2903
|
process.exit(1);
|
|
2839
2904
|
}
|
|
2840
2905
|
};
|
|
2841
2906
|
|
|
2842
2907
|
// src/astro/generate.ts
|
|
2843
|
-
import { existsSync as
|
|
2908
|
+
import { existsSync as existsSync9, readFileSync as readFileSync6, realpathSync } from "node:fs";
|
|
2844
2909
|
import {
|
|
2845
2910
|
lstat,
|
|
2846
|
-
mkdir as
|
|
2847
|
-
readFile as
|
|
2911
|
+
mkdir as mkdir3,
|
|
2912
|
+
readFile as readFile10,
|
|
2848
2913
|
rename,
|
|
2849
2914
|
rm,
|
|
2850
2915
|
symlink,
|
|
2851
|
-
writeFile as
|
|
2916
|
+
writeFile as writeFile4
|
|
2852
2917
|
} from "node:fs/promises";
|
|
2853
|
-
import { createRequire as
|
|
2918
|
+
import { createRequire as createRequire5 } from "node:module";
|
|
2854
2919
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
2855
|
-
import { basename as basename2, dirname as dirname7, join as
|
|
2920
|
+
import { basename as basename2, dirname as dirname7, join as join17, normalize as normalize3, relative as relative6 } from "pathe";
|
|
2856
2921
|
import { glob as glob4 } from "tinyglobby";
|
|
2857
2922
|
|
|
2858
2923
|
// src/ai/ask-data.ts
|
|
@@ -2924,7 +2989,7 @@ var askBackendRuntimeDep = (ask) => {
|
|
|
2924
2989
|
};
|
|
2925
2990
|
|
|
2926
2991
|
// src/ai/markdown.ts
|
|
2927
|
-
import { readFile as
|
|
2992
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
2928
2993
|
var buildRawMarkdown = async (project) => {
|
|
2929
2994
|
const pageById = new Map(project.graph.pages.map((page) => [page.id, page]));
|
|
2930
2995
|
const readRoute = async (route) => {
|
|
@@ -2932,7 +2997,7 @@ var buildRawMarkdown = async (project) => {
|
|
|
2932
2997
|
if (page) {
|
|
2933
2998
|
return await readEntryText(project, page);
|
|
2934
2999
|
}
|
|
2935
|
-
return route.sourcePath ? await
|
|
3000
|
+
return route.sourcePath ? await readFile4(route.sourcePath, "utf-8") : "";
|
|
2936
3001
|
};
|
|
2937
3002
|
const entries = await Promise.all(project.manifest.routes.map(async (route) => [route.path, await readRoute(route)]));
|
|
2938
3003
|
return Object.fromEntries(entries);
|
|
@@ -3029,6 +3094,7 @@ var buildMcpServerCard = (input) => ({
|
|
|
3029
3094
|
var BUILTIN_MDX_TAGS = new Set([
|
|
3030
3095
|
"Accordion",
|
|
3031
3096
|
"AccordionItem",
|
|
3097
|
+
"ApiOverview",
|
|
3032
3098
|
"AutoTypeTable",
|
|
3033
3099
|
"Badge",
|
|
3034
3100
|
"Callout",
|
|
@@ -3047,8 +3113,12 @@ var BUILTIN_MDX_TAGS = new Set([
|
|
|
3047
3113
|
"GithubInfo",
|
|
3048
3114
|
"Icon",
|
|
3049
3115
|
"Math",
|
|
3116
|
+
"Operation",
|
|
3050
3117
|
"Panel",
|
|
3118
|
+
"ParamField",
|
|
3051
3119
|
"Prompt",
|
|
3120
|
+
"RequestField",
|
|
3121
|
+
"ResponseField",
|
|
3052
3122
|
"Step",
|
|
3053
3123
|
"Steps",
|
|
3054
3124
|
"Tab",
|
|
@@ -3087,8 +3157,8 @@ var validateUsedComponents = (pages, extraTags, registryNames) => {
|
|
|
3087
3157
|
};
|
|
3088
3158
|
|
|
3089
3159
|
// src/core/component-overrides.ts
|
|
3090
|
-
import { existsSync as
|
|
3091
|
-
import { dirname as dirname4, extname, isAbsolute, resolve as
|
|
3160
|
+
import { existsSync as existsSync6 } from "node:fs";
|
|
3161
|
+
import { dirname as dirname4, extname, isAbsolute as isAbsolute2, resolve as resolve3 } from "pathe";
|
|
3092
3162
|
import ts from "typescript";
|
|
3093
3163
|
var GROUPS = ["mdx", "layout", "islands"];
|
|
3094
3164
|
var FRAMEWORK_BY_EXT = {
|
|
@@ -3176,18 +3246,18 @@ var findDefaultExportObject = (sourceFile) => {
|
|
|
3176
3246
|
var probeExtension = (base) => {
|
|
3177
3247
|
for (const extension of COMPONENT_EXTS) {
|
|
3178
3248
|
const candidate = `${base}.${extension}`;
|
|
3179
|
-
if (
|
|
3249
|
+
if (existsSync6(candidate)) {
|
|
3180
3250
|
return candidate;
|
|
3181
3251
|
}
|
|
3182
3252
|
}
|
|
3183
3253
|
return null;
|
|
3184
3254
|
};
|
|
3185
3255
|
var toImport = (specifier, imported, dir) => {
|
|
3186
|
-
const relative4 = specifier.startsWith(".") ||
|
|
3256
|
+
const relative4 = specifier.startsWith(".") || isAbsolute2(specifier);
|
|
3187
3257
|
let path = specifier;
|
|
3188
3258
|
let extension = extname(specifier).slice(1).toLowerCase();
|
|
3189
3259
|
if (relative4) {
|
|
3190
|
-
const absolute =
|
|
3260
|
+
const absolute = isAbsolute2(specifier) ? specifier : resolve3(dir, specifier);
|
|
3191
3261
|
if (extension) {
|
|
3192
3262
|
path = absolute;
|
|
3193
3263
|
} else {
|
|
@@ -3435,147 +3505,104 @@ var resolveUIStrings = (locale, options) => {
|
|
|
3435
3505
|
};
|
|
3436
3506
|
|
|
3437
3507
|
// src/theme/icons.ts
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
"
|
|
3444
|
-
|
|
3445
|
-
"
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
"
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
"
|
|
3473
|
-
|
|
3474
|
-
"
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
}
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
"fa-linkedin": "linkedin",
|
|
3502
|
-
"fa-x-twitter": "brand-x",
|
|
3503
|
-
"file-lines": "file",
|
|
3504
|
-
javascript: "js",
|
|
3505
|
-
"panel-left-open": "panel-left",
|
|
3506
|
-
"panel-right-open": "panel-right",
|
|
3507
|
-
times: "x",
|
|
3508
|
-
"x-twitter": "brand-x"
|
|
3509
|
-
};
|
|
3510
|
-
var libraryPrefixes = [
|
|
3511
|
-
"fa-brands",
|
|
3512
|
-
"fa-duotone",
|
|
3513
|
-
"fa-light",
|
|
3514
|
-
"fa-regular",
|
|
3515
|
-
"fa-sharp-solid",
|
|
3516
|
-
"fa-solid",
|
|
3517
|
-
"fa-thin",
|
|
3518
|
-
"fa",
|
|
3519
|
-
"fab",
|
|
3520
|
-
"fad",
|
|
3521
|
-
"fal",
|
|
3522
|
-
"far",
|
|
3523
|
-
"fas",
|
|
3524
|
-
"fat",
|
|
3525
|
-
"lucide",
|
|
3526
|
-
"tabler",
|
|
3527
|
-
"ti"
|
|
3528
|
-
];
|
|
3529
|
-
var normalizedIconName = (name) => name.trim().toLowerCase().replaceAll(/[\s_]+/gu, "-");
|
|
3530
|
-
var isString = (value) => typeof value === "string";
|
|
3531
|
-
var withoutLibraryPrefix = (name) => {
|
|
3532
|
-
let normalized = normalizedIconName(name).replaceAll(/^icon-/gu, "");
|
|
3533
|
-
let changed = true;
|
|
3534
|
-
while (changed) {
|
|
3535
|
-
changed = false;
|
|
3536
|
-
for (const prefix of libraryPrefixes) {
|
|
3537
|
-
if (normalized.startsWith(`${prefix}-`)) {
|
|
3538
|
-
normalized = normalized.slice(prefix.length + 1);
|
|
3539
|
-
changed = true;
|
|
3540
|
-
}
|
|
3541
|
-
if (normalized.startsWith(`${prefix}:`)) {
|
|
3542
|
-
normalized = normalized.slice(prefix.length + 1);
|
|
3543
|
-
changed = true;
|
|
3544
|
-
}
|
|
3545
|
-
}
|
|
3508
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
3509
|
+
import { getIconData, iconToSVG } from "@iconify/utils";
|
|
3510
|
+
var requireJson = createRequire2(import.meta.url);
|
|
3511
|
+
var loadSet = (pkg) => requireJson(pkg);
|
|
3512
|
+
var SETS = {
|
|
3513
|
+
"fa6-brands": loadSet("@iconify-json/fa6-brands/icons.json"),
|
|
3514
|
+
"fa6-regular": loadSet("@iconify-json/fa6-regular/icons.json"),
|
|
3515
|
+
"fa6-solid": loadSet("@iconify-json/fa6-solid/icons.json"),
|
|
3516
|
+
lucide: loadSet("@iconify-json/lucide/icons.json"),
|
|
3517
|
+
tabler: loadSet("@iconify-json/tabler/icons.json")
|
|
3518
|
+
};
|
|
3519
|
+
var DEFAULT_SET = "lucide";
|
|
3520
|
+
var LIBRARY_SETS = {
|
|
3521
|
+
fa: "fa6-solid",
|
|
3522
|
+
"font-awesome": "fa6-solid",
|
|
3523
|
+
fontawesome: "fa6-solid",
|
|
3524
|
+
lucide: "lucide",
|
|
3525
|
+
tabler: "tabler"
|
|
3526
|
+
};
|
|
3527
|
+
var ICON_TYPE_SETS = {
|
|
3528
|
+
brands: "fa6-brands",
|
|
3529
|
+
duotone: "fa6-solid",
|
|
3530
|
+
light: "fa6-solid",
|
|
3531
|
+
regular: "fa6-regular",
|
|
3532
|
+
"sharp-solid": "fa6-solid",
|
|
3533
|
+
solid: "fa6-solid",
|
|
3534
|
+
thin: "fa6-solid"
|
|
3535
|
+
};
|
|
3536
|
+
var PREFIX_SETS = {
|
|
3537
|
+
...LIBRARY_SETS,
|
|
3538
|
+
fa: "fa6-solid",
|
|
3539
|
+
"fa-brands": "fa6-brands",
|
|
3540
|
+
"fa-regular": "fa6-regular",
|
|
3541
|
+
"fa-solid": "fa6-solid",
|
|
3542
|
+
"fa6-brands": "fa6-brands",
|
|
3543
|
+
"fa6-regular": "fa6-regular",
|
|
3544
|
+
"fa6-solid": "fa6-solid",
|
|
3545
|
+
fab: "fa6-brands",
|
|
3546
|
+
far: "fa6-regular",
|
|
3547
|
+
fas: "fa6-solid",
|
|
3548
|
+
ti: "tabler"
|
|
3549
|
+
};
|
|
3550
|
+
var normalize = (name) => name.trim().toLowerCase().replaceAll(/[\s_]+/gu, "-");
|
|
3551
|
+
var setFor = (options) => {
|
|
3552
|
+
if (options.iconType) {
|
|
3553
|
+
const set = ICON_TYPE_SETS[normalize(options.iconType)];
|
|
3554
|
+
if (set) {
|
|
3555
|
+
return set;
|
|
3556
|
+
}
|
|
3557
|
+
}
|
|
3558
|
+
if (options.library) {
|
|
3559
|
+
const set = LIBRARY_SETS[normalize(options.library)];
|
|
3560
|
+
if (set) {
|
|
3561
|
+
return set;
|
|
3562
|
+
}
|
|
3563
|
+
}
|
|
3564
|
+
return DEFAULT_SET;
|
|
3565
|
+
};
|
|
3566
|
+
var fromSet = (setName, iconName) => {
|
|
3567
|
+
const set = SETS[setName];
|
|
3568
|
+
const data = set && getIconData(set, iconName);
|
|
3569
|
+
if (!data) {
|
|
3570
|
+
return null;
|
|
3546
3571
|
}
|
|
3547
|
-
|
|
3572
|
+
const { attributes, body } = iconToSVG(data, { height: "auto" });
|
|
3573
|
+
return { body, name: iconName, viewBox: attributes.viewBox };
|
|
3548
3574
|
};
|
|
3549
|
-
var
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
const
|
|
3553
|
-
const
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
iconAliases[stripped]
|
|
3559
|
-
].filter(isString);
|
|
3560
|
-
for (const candidate of candidates) {
|
|
3561
|
-
const markup = icons[candidate];
|
|
3562
|
-
if (markup) {
|
|
3563
|
-
return { markup, name: candidate };
|
|
3575
|
+
var fromFaSet = (setName, name) => fromSet(setName, name) ?? fromSet("fa6-brands", name);
|
|
3576
|
+
var resolveInSet = (setName, name) => setName.startsWith("fa6-") ? fromFaSet(setName, name) : fromSet(setName, name);
|
|
3577
|
+
var resolveIcon = (name, options = {}) => {
|
|
3578
|
+
const normalized = normalize(name);
|
|
3579
|
+
const colon = normalized.indexOf(":");
|
|
3580
|
+
if (colon > 0) {
|
|
3581
|
+
const setName = PREFIX_SETS[normalized.slice(0, colon)];
|
|
3582
|
+
if (setName) {
|
|
3583
|
+
return resolveInSet(setName, normalized.slice(colon + 1));
|
|
3564
3584
|
}
|
|
3565
3585
|
}
|
|
3566
|
-
return
|
|
3586
|
+
return resolveInSet(setFor(options), normalized);
|
|
3587
|
+
};
|
|
3588
|
+
var hasIcon = (name, options = {}) => {
|
|
3589
|
+
if (resolveIcon(name, options)) {
|
|
3590
|
+
return true;
|
|
3591
|
+
}
|
|
3592
|
+
const normalized = normalize(name);
|
|
3593
|
+
const bare = normalized.includes(":") ? normalized.slice(normalized.indexOf(":") + 1) : normalized;
|
|
3594
|
+
return Object.values(SETS).some((set) => getIconData(set, bare) !== null);
|
|
3567
3595
|
};
|
|
3568
|
-
var hasIcon = (name, iconType) => resolveIcon(name, iconType) !== null;
|
|
3569
3596
|
|
|
3570
3597
|
// src/core/nav-diagnostics.ts
|
|
3571
3598
|
var IMAGE_ICON = /^(?:https?:\/\/|data:image\/|\/|\.{1,2}\/)|\.(?:avif|gif|jpe?g|png|svg|webp)$/iu;
|
|
3572
3599
|
var isAssetIcon = (value) => value.startsWith("<") || IMAGE_ICON.test(value);
|
|
3573
3600
|
var flattenNodes = (nodes) => nodes.flatMap((node) => node.kind === "group" ? [node, ...flattenNodes(node.children)] : [node]);
|
|
3574
3601
|
var collectIcons = (navigation) => {
|
|
3575
|
-
const
|
|
3602
|
+
const icons = [];
|
|
3576
3603
|
const push = (icon, where) => {
|
|
3577
3604
|
if (icon) {
|
|
3578
|
-
|
|
3605
|
+
icons.push({ icon, where });
|
|
3579
3606
|
}
|
|
3580
3607
|
};
|
|
3581
3608
|
for (const tab of navigation.tabs) {
|
|
@@ -3589,16 +3616,13 @@ var collectIcons = (navigation) => {
|
|
|
3589
3616
|
push(item.icon, `selector "${item.label}"`);
|
|
3590
3617
|
}
|
|
3591
3618
|
}
|
|
3592
|
-
const sidebars = [
|
|
3593
|
-
navigation.sidebar,
|
|
3594
|
-
...navigation.sidebarVariants.map((variant) => variant.sidebar)
|
|
3595
|
-
];
|
|
3619
|
+
const sidebars = [navigation.sidebar];
|
|
3596
3620
|
for (const sidebar of sidebars) {
|
|
3597
3621
|
for (const node of flattenNodes(sidebar)) {
|
|
3598
3622
|
push(node.icon, `"${node.label}"`);
|
|
3599
3623
|
}
|
|
3600
3624
|
}
|
|
3601
|
-
return
|
|
3625
|
+
return icons;
|
|
3602
3626
|
};
|
|
3603
3627
|
var validateNavIcons = (navigation) => {
|
|
3604
3628
|
const seen = new Set;
|
|
@@ -3665,11 +3689,7 @@ var duplicateLabelDiagnostics = (navigation) => {
|
|
|
3665
3689
|
}
|
|
3666
3690
|
};
|
|
3667
3691
|
const sidebars = [
|
|
3668
|
-
{ nodes: navigation.sidebar, where: "at the top level" }
|
|
3669
|
-
...navigation.sidebarVariants.map((variant) => ({
|
|
3670
|
-
nodes: variant.sidebar,
|
|
3671
|
-
where: `in the "${variant.path}" section`
|
|
3672
|
-
}))
|
|
3692
|
+
{ nodes: navigation.sidebar, where: "at the top level" }
|
|
3673
3693
|
];
|
|
3674
3694
|
for (const { nodes, where } of sidebars) {
|
|
3675
3695
|
checkLevel(nodes, where);
|
|
@@ -3681,10 +3701,7 @@ var hiddenInSidebarDiagnostics = (navigation, pages) => {
|
|
|
3681
3701
|
if (hidden.size === 0) {
|
|
3682
3702
|
return [];
|
|
3683
3703
|
}
|
|
3684
|
-
const sidebars = [
|
|
3685
|
-
navigation.sidebar,
|
|
3686
|
-
...navigation.sidebarVariants.map((variant) => variant.sidebar)
|
|
3687
|
-
];
|
|
3704
|
+
const sidebars = [navigation.sidebar];
|
|
3688
3705
|
const diagnostics = [];
|
|
3689
3706
|
const seen = new Set;
|
|
3690
3707
|
for (const sidebar of sidebars) {
|
|
@@ -3708,10 +3725,10 @@ var validateNavStructure = (navigation, pages) => [
|
|
|
3708
3725
|
];
|
|
3709
3726
|
|
|
3710
3727
|
// src/core/tsconfig-aliases.ts
|
|
3711
|
-
import { existsSync as
|
|
3712
|
-
import { createRequire as
|
|
3728
|
+
import { existsSync as existsSync7, readFileSync as readFileSync3, statSync } from "node:fs";
|
|
3729
|
+
import { createRequire as createRequire3 } from "node:module";
|
|
3713
3730
|
import { pathToFileURL } from "node:url";
|
|
3714
|
-
import { dirname as dirname5, isAbsolute as
|
|
3731
|
+
import { dirname as dirname5, isAbsolute as isAbsolute3, join as join9, resolve as resolve4 } from "pathe";
|
|
3715
3732
|
var stripJsonComments = (text) => {
|
|
3716
3733
|
let out = "";
|
|
3717
3734
|
let inString = false;
|
|
@@ -3765,16 +3782,16 @@ var isFile = (path) => {
|
|
|
3765
3782
|
}
|
|
3766
3783
|
};
|
|
3767
3784
|
var resolveExtends = (spec, fromDir) => {
|
|
3768
|
-
if (spec.startsWith(".") ||
|
|
3769
|
-
const candidates = spec.endsWith(".json") ? [
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3785
|
+
if (spec.startsWith(".") || isAbsolute3(spec)) {
|
|
3786
|
+
const candidates = spec.endsWith(".json") ? [resolve4(fromDir, spec)] : [
|
|
3787
|
+
resolve4(fromDir, `${spec}.json`),
|
|
3788
|
+
resolve4(fromDir, spec, "tsconfig.json"),
|
|
3789
|
+
resolve4(fromDir, spec)
|
|
3773
3790
|
];
|
|
3774
3791
|
return candidates.find(isFile) ?? null;
|
|
3775
3792
|
}
|
|
3776
3793
|
try {
|
|
3777
|
-
const require_ =
|
|
3794
|
+
const require_ = createRequire3(pathToFileURL(join9(fromDir, "_.js")).href);
|
|
3778
3795
|
for (const sub of [`${spec}/tsconfig.json`, spec]) {
|
|
3779
3796
|
try {
|
|
3780
3797
|
return require_.resolve(sub);
|
|
@@ -3784,7 +3801,7 @@ var resolveExtends = (spec, fromDir) => {
|
|
|
3784
3801
|
return null;
|
|
3785
3802
|
};
|
|
3786
3803
|
var loadPaths = (file, seen) => {
|
|
3787
|
-
if (seen.has(file) || !
|
|
3804
|
+
if (seen.has(file) || !existsSync7(file)) {
|
|
3788
3805
|
return null;
|
|
3789
3806
|
}
|
|
3790
3807
|
seen.add(file);
|
|
@@ -3796,7 +3813,7 @@ var loadPaths = (file, seen) => {
|
|
|
3796
3813
|
if (options.paths && typeof options.paths === "object") {
|
|
3797
3814
|
const baseUrl = typeof options.baseUrl === "string" ? options.baseUrl : ".";
|
|
3798
3815
|
return {
|
|
3799
|
-
baseDir:
|
|
3816
|
+
baseDir: resolve4(dirname5(file), baseUrl),
|
|
3800
3817
|
paths: options.paths
|
|
3801
3818
|
};
|
|
3802
3819
|
}
|
|
@@ -3823,10 +3840,10 @@ var toAlias = (key, value, baseDir) => {
|
|
|
3823
3840
|
if (find === "" || find === "*") {
|
|
3824
3841
|
return null;
|
|
3825
3842
|
}
|
|
3826
|
-
return { find, replacement:
|
|
3843
|
+
return { find, replacement: resolve4(baseDir, target) };
|
|
3827
3844
|
};
|
|
3828
3845
|
var resolveTsconfigAliases = (root) => {
|
|
3829
|
-
const entry = ["tsconfig.json", "jsconfig.json"].map((name) =>
|
|
3846
|
+
const entry = ["tsconfig.json", "jsconfig.json"].map((name) => join9(root, name)).find((file) => existsSync7(file));
|
|
3830
3847
|
if (!entry) {
|
|
3831
3848
|
return {};
|
|
3832
3849
|
}
|
|
@@ -3922,19 +3939,97 @@ ${items}
|
|
|
3922
3939
|
`;
|
|
3923
3940
|
};
|
|
3924
3941
|
|
|
3942
|
+
// src/openapi/references.ts
|
|
3943
|
+
var NON_SLUG = /[^a-z0-9]+/gu;
|
|
3944
|
+
var SLUG_EDGES = /^-+|-+$/gu;
|
|
3945
|
+
var ROUTE_EDGES = /^\/+|\/+$/gu;
|
|
3946
|
+
var TRAILING_SLASH = /\/+$/u;
|
|
3947
|
+
var slugify = (text) => text.toLowerCase().replace(NON_SLUG, "-").replace(SLUG_EDGES, "");
|
|
3948
|
+
var normalizeRoute = (route) => {
|
|
3949
|
+
const trimmed = route.trim();
|
|
3950
|
+
const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
3951
|
+
const noTrailing = withSlash.replace(TRAILING_SLASH, "");
|
|
3952
|
+
return noTrailing === "" ? "/" : noTrailing;
|
|
3953
|
+
};
|
|
3954
|
+
var routeSlug = (route) => slugify(route.replace(ROUTE_EDGES, "")) || "reference";
|
|
3955
|
+
var sourcesOf = (block) => {
|
|
3956
|
+
const sources = [...block.sources];
|
|
3957
|
+
if (block.spec) {
|
|
3958
|
+
sources.unshift({ spec: block.spec });
|
|
3959
|
+
}
|
|
3960
|
+
return sources;
|
|
3961
|
+
};
|
|
3962
|
+
var referencesFor = (kind, block, defaultLabel, renderer, display) => {
|
|
3963
|
+
if (!block.enabled) {
|
|
3964
|
+
return [];
|
|
3965
|
+
}
|
|
3966
|
+
const sources = sourcesOf(block);
|
|
3967
|
+
const base = normalizeRoute(block.route);
|
|
3968
|
+
return sources.map((source, index) => {
|
|
3969
|
+
const label = source.label ?? (sources.length > 1 ? `${defaultLabel} ${index + 1}` : defaultLabel);
|
|
3970
|
+
let route;
|
|
3971
|
+
if (source.route) {
|
|
3972
|
+
route = normalizeRoute(source.route);
|
|
3973
|
+
} else if (sources.length === 1) {
|
|
3974
|
+
route = base;
|
|
3975
|
+
} else {
|
|
3976
|
+
const suffix = source.label ? slugify(source.label) : "";
|
|
3977
|
+
route = normalizeRoute(`${base}/${suffix || index + 1}`);
|
|
3978
|
+
}
|
|
3979
|
+
return {
|
|
3980
|
+
display,
|
|
3981
|
+
kind,
|
|
3982
|
+
label,
|
|
3983
|
+
renderer,
|
|
3984
|
+
route,
|
|
3985
|
+
slug: routeSlug(route),
|
|
3986
|
+
spec: source.spec,
|
|
3987
|
+
theme: block.theme
|
|
3988
|
+
};
|
|
3989
|
+
});
|
|
3990
|
+
};
|
|
3991
|
+
var NO_DISPLAY = { codeSamples: [], expandSchemas: false };
|
|
3992
|
+
var resolveReferences = (config) => [
|
|
3993
|
+
...referencesFor("openapi", config.openapi, "API Reference", config.openapi.renderer, {
|
|
3994
|
+
codeSamples: config.openapi.codeSamples,
|
|
3995
|
+
expandSchemas: config.openapi.expandSchemas
|
|
3996
|
+
}),
|
|
3997
|
+
...referencesFor("asyncapi", config.asyncapi, "Events", "scalar", NO_DISPLAY)
|
|
3998
|
+
];
|
|
3999
|
+
var referenceTabs = (config) => resolveReferences(config).map((ref) => ({
|
|
4000
|
+
label: ref.label,
|
|
4001
|
+
path: ref.route
|
|
4002
|
+
}));
|
|
4003
|
+
var blumeReferences = (config) => {
|
|
4004
|
+
const seen = new Set;
|
|
4005
|
+
const result = [];
|
|
4006
|
+
for (const ref of resolveReferences(config)) {
|
|
4007
|
+
if (ref.kind !== "openapi" || ref.renderer !== "blume") {
|
|
4008
|
+
continue;
|
|
4009
|
+
}
|
|
4010
|
+
if (seen.has(ref.route)) {
|
|
4011
|
+
continue;
|
|
4012
|
+
}
|
|
4013
|
+
seen.add(ref.route);
|
|
4014
|
+
result.push(ref);
|
|
4015
|
+
}
|
|
4016
|
+
return result;
|
|
4017
|
+
};
|
|
4018
|
+
var hasScalarReferences = (config) => resolveReferences(config).some((ref) => ref.renderer === "scalar");
|
|
4019
|
+
|
|
3925
4020
|
// src/openapi/scalar.ts
|
|
3926
|
-
import { readFile as
|
|
3927
|
-
import { isAbsolute as
|
|
4021
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
4022
|
+
import { isAbsolute as isAbsolute4, join as join12 } from "pathe";
|
|
3928
4023
|
|
|
3929
4024
|
// src/astro/templates.ts
|
|
3930
|
-
import { existsSync as
|
|
3931
|
-
import { dirname as dirname6, join as
|
|
4025
|
+
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
|
|
4026
|
+
import { dirname as dirname6, join as join11 } from "pathe";
|
|
3932
4027
|
|
|
3933
4028
|
// src/core/assets.ts
|
|
3934
|
-
import { join as
|
|
4029
|
+
import { join as join10 } from "pathe";
|
|
3935
4030
|
var resolveAssetMounts = (root, assets) => assets.map((entry) => {
|
|
3936
4031
|
const rel = entry.replace(/^[./]+/u, "").replaceAll(/\.\.\/?/gu, "").replace(/\/+$/u, "");
|
|
3937
|
-
return { dir:
|
|
4032
|
+
return { dir: join10(root, rel), url: `/${rel}` };
|
|
3938
4033
|
});
|
|
3939
4034
|
|
|
3940
4035
|
// src/theme/fonts.ts
|
|
@@ -4093,7 +4188,7 @@ var WORKSPACE_MARKERS = [
|
|
|
4093
4188
|
"yarn.lock"
|
|
4094
4189
|
];
|
|
4095
4190
|
var hasWorkspacesField = (pkgPath) => {
|
|
4096
|
-
if (!
|
|
4191
|
+
if (!existsSync8(pkgPath)) {
|
|
4097
4192
|
return false;
|
|
4098
4193
|
}
|
|
4099
4194
|
try {
|
|
@@ -4103,7 +4198,7 @@ var hasWorkspacesField = (pkgPath) => {
|
|
|
4103
4198
|
return false;
|
|
4104
4199
|
}
|
|
4105
4200
|
};
|
|
4106
|
-
var hasWorkspaceMarker = (dir) => hasWorkspacesField(
|
|
4201
|
+
var hasWorkspaceMarker = (dir) => hasWorkspacesField(join11(dir, "package.json")) || WORKSPACE_MARKERS.some((marker) => existsSync8(join11(dir, marker)));
|
|
4107
4202
|
var findWorkspaceRoot = (start) => {
|
|
4108
4203
|
let dir = start;
|
|
4109
4204
|
for (;; ) {
|
|
@@ -4138,7 +4233,7 @@ var runtimeDependencies = (options) => {
|
|
|
4138
4233
|
if (needsSvelte) {
|
|
4139
4234
|
deps.push("@astrojs/svelte");
|
|
4140
4235
|
}
|
|
4141
|
-
if (config
|
|
4236
|
+
if (hasScalarReferences(config)) {
|
|
4142
4237
|
deps.push("@scalar/astro");
|
|
4143
4238
|
}
|
|
4144
4239
|
deps.push(...searchProviderMeta(config.search.provider).runtimeDeps);
|
|
@@ -4171,6 +4266,7 @@ var RENDER_EXTERNAL_DEPS = [
|
|
|
4171
4266
|
];
|
|
4172
4267
|
var renderUserAliases = (aliases) => Object.entries(aliases ?? {}).toSorted(([a], [b]) => b.length - a.length).map(([find, replacement]) => `
|
|
4173
4268
|
${JSON.stringify(find)}: ${JSON.stringify(replacement)},`).join("");
|
|
4269
|
+
var astroOutDir = (context) => context.distDir ?? `${context.root}/dist`;
|
|
4174
4270
|
var astroConfigTemplate = (options) => {
|
|
4175
4271
|
const { context, config, needsReact, pages, dataPath, themePath } = options;
|
|
4176
4272
|
const {
|
|
@@ -4178,6 +4274,7 @@ var astroConfigTemplate = (options) => {
|
|
|
4178
4274
|
examplesPath,
|
|
4179
4275
|
needsSvelte,
|
|
4180
4276
|
needsVue,
|
|
4277
|
+
openapiPath,
|
|
4181
4278
|
searchClientPath
|
|
4182
4279
|
} = options;
|
|
4183
4280
|
const { deployment } = config;
|
|
@@ -4248,7 +4345,7 @@ ${twoslashImport}${reactImport}${vueImport}${svelteImport}${blumeImport}${adapte
|
|
|
4248
4345
|
export default defineConfig({
|
|
4249
4346
|
root: ${JSON.stringify(context.outDir)},
|
|
4250
4347
|
srcDir: ${JSON.stringify(`${context.outDir}/src`)},
|
|
4251
|
-
outDir: ${JSON.stringify(
|
|
4348
|
+
outDir: ${JSON.stringify(astroOutDir(context))},
|
|
4252
4349
|
publicDir: ${JSON.stringify(`${context.root}/public`)},
|
|
4253
4350
|
output: ${JSON.stringify(deployment.output)},${adapterOption}${siteOption}${baseOption}${redirectsOption}${i18nOption}${fontsOption}
|
|
4254
4351
|
integrations: [${integrations.join(", ")}],
|
|
@@ -4281,6 +4378,7 @@ export default defineConfig({
|
|
|
4281
4378
|
alias: {
|
|
4282
4379
|
"blume:data": ${JSON.stringify(dataPath)},
|
|
4283
4380
|
"blume:examples": ${JSON.stringify(examplesPath)},
|
|
4381
|
+
"blume:openapi": ${JSON.stringify(openapiPath)},
|
|
4284
4382
|
"blume:search-client": ${JSON.stringify(searchClientPath)},
|
|
4285
4383
|
"blume:theme": ${JSON.stringify(themePath)},${userAliasLines}
|
|
4286
4384
|
},
|
|
@@ -4294,7 +4392,7 @@ export default defineConfig({
|
|
|
4294
4392
|
});
|
|
4295
4393
|
`;
|
|
4296
4394
|
};
|
|
4297
|
-
var stagedContentDir = (outDir) =>
|
|
4395
|
+
var stagedContentDir = (outDir) => join11(outDir, "content");
|
|
4298
4396
|
var contentConfigTemplate = (options) => {
|
|
4299
4397
|
const { context, config } = options;
|
|
4300
4398
|
const stagedBase = options.stagedBase ?? stagedContentDir(context.outDir);
|
|
@@ -4700,7 +4798,10 @@ import FileTree from "blume/components/content/FileTree.astro";
|
|
|
4700
4798
|
import Frame from "blume/components/content/Frame.astro";
|
|
4701
4799
|
import GithubInfo from "blume/components/content/GithubInfo.astro";
|
|
4702
4800
|
import Panel from "blume/components/content/Panel.astro";
|
|
4801
|
+
import ParamField from "blume/components/content/ParamField.astro";
|
|
4703
4802
|
import Prompt from "blume/components/content/Prompt.astro";
|
|
4803
|
+
import RequestField from "blume/components/content/RequestField.astro";
|
|
4804
|
+
import ResponseField from "blume/components/content/ResponseField.astro";
|
|
4704
4805
|
import Step from "blume/components/content/Step.astro";
|
|
4705
4806
|
import Steps from "blume/components/content/Steps.astro";
|
|
4706
4807
|
import Tab from "blume/components/content/Tab.astro";
|
|
@@ -4714,6 +4815,8 @@ import TypeTable from "blume/components/content/TypeTable.astro";
|
|
|
4714
4815
|
import Visibility from "blume/components/content/Visibility.astro";
|
|
4715
4816
|
import YouTube from "blume/components/content/YouTube.astro";
|
|
4716
4817
|
import Icon from "blume/components/Icon.astro";
|
|
4818
|
+
import ApiOverview from "blume/components/openapi/ApiOverview.astro";
|
|
4819
|
+
import Operation from "blume/components/openapi/Operation.astro";
|
|
4717
4820
|
${mathImport}import { mdxComponents as userMdx, layoutOverrides } from "../generated/components.ts";
|
|
4718
4821
|
import { islandComponents } from "../generated/islands.ts";
|
|
4719
4822
|
import data from "../generated/data.json";
|
|
@@ -4730,6 +4833,7 @@ export const prerender = true;
|
|
|
4730
4833
|
const components = {
|
|
4731
4834
|
Accordion,
|
|
4732
4835
|
AccordionItem,
|
|
4836
|
+
ApiOverview,
|
|
4733
4837
|
AutoTypeTable,
|
|
4734
4838
|
Badge,
|
|
4735
4839
|
Callout,
|
|
@@ -4747,8 +4851,12 @@ const components = {
|
|
|
4747
4851
|
Frame,
|
|
4748
4852
|
GithubInfo,
|
|
4749
4853
|
Icon,
|
|
4854
|
+
Operation,
|
|
4750
4855
|
Panel,
|
|
4856
|
+
ParamField,
|
|
4751
4857
|
Prompt,
|
|
4858
|
+
RequestField,
|
|
4859
|
+
ResponseField,
|
|
4752
4860
|
Step,
|
|
4753
4861
|
Steps,
|
|
4754
4862
|
Tab,
|
|
@@ -5148,6 +5256,11 @@ declare module "blume:data" {
|
|
|
5148
5256
|
export default data;
|
|
5149
5257
|
}
|
|
5150
5258
|
|
|
5259
|
+
declare module "blume:openapi" {
|
|
5260
|
+
const specs: import("blume/openapi/model.ts").OpenApiData;
|
|
5261
|
+
export default specs;
|
|
5262
|
+
}
|
|
5263
|
+
|
|
5151
5264
|
declare module "blume:search-client" {
|
|
5152
5265
|
export const createSearch: () =>
|
|
5153
5266
|
| import("blume/components/layout/search/types.ts").SearchFn
|
|
@@ -5262,57 +5375,11 @@ ${dark}`;
|
|
|
5262
5375
|
|
|
5263
5376
|
// src/openapi/scalar.ts
|
|
5264
5377
|
var URL_SPEC = /^https?:\/\//u;
|
|
5265
|
-
var
|
|
5266
|
-
var SLUG_EDGES = /^-+|-+$/gu;
|
|
5267
|
-
var ROUTE_EDGES = /^\/+|\/+$/gu;
|
|
5268
|
-
var TRAILING_SLASH = /\/+$/u;
|
|
5269
|
-
var slugify = (text) => text.toLowerCase().replace(NON_SLUG, "-").replace(SLUG_EDGES, "");
|
|
5270
|
-
var normalizeRoute = (route) => {
|
|
5271
|
-
const trimmed = route.trim();
|
|
5272
|
-
const withSlash = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
5273
|
-
const noTrailing = withSlash.replace(TRAILING_SLASH, "");
|
|
5274
|
-
return noTrailing === "" ? "/" : noTrailing;
|
|
5275
|
-
};
|
|
5378
|
+
var ROUTE_EDGES2 = /^\/+|\/+$/gu;
|
|
5276
5379
|
var referencePagePath = (route) => {
|
|
5277
|
-
const segments = route.replace(
|
|
5380
|
+
const segments = route.replace(ROUTE_EDGES2, "");
|
|
5278
5381
|
return `${segments === "" ? "index" : segments}.astro`;
|
|
5279
5382
|
};
|
|
5280
|
-
var sourcesOf = (block) => {
|
|
5281
|
-
const sources = [...block.sources];
|
|
5282
|
-
if (block.spec) {
|
|
5283
|
-
sources.unshift({ spec: block.spec });
|
|
5284
|
-
}
|
|
5285
|
-
return sources;
|
|
5286
|
-
};
|
|
5287
|
-
var referencesFor = (kind, block, defaultLabel) => {
|
|
5288
|
-
if (!block.enabled) {
|
|
5289
|
-
return [];
|
|
5290
|
-
}
|
|
5291
|
-
const sources = sourcesOf(block);
|
|
5292
|
-
const base = normalizeRoute(block.route);
|
|
5293
|
-
return sources.map((source, index) => {
|
|
5294
|
-
const label = source.label ?? (sources.length > 1 ? `${defaultLabel} ${index + 1}` : defaultLabel);
|
|
5295
|
-
let route;
|
|
5296
|
-
if (source.route) {
|
|
5297
|
-
route = normalizeRoute(source.route);
|
|
5298
|
-
} else if (sources.length === 1) {
|
|
5299
|
-
route = base;
|
|
5300
|
-
} else {
|
|
5301
|
-
const suffix = source.label ? slugify(source.label) : "";
|
|
5302
|
-
route = normalizeRoute(`${base}/${suffix || index + 1}`);
|
|
5303
|
-
}
|
|
5304
|
-
return { kind, label, route, spec: source.spec, theme: block.theme };
|
|
5305
|
-
});
|
|
5306
|
-
};
|
|
5307
|
-
var resolveReferences = (config) => [
|
|
5308
|
-
...referencesFor("openapi", config.openapi, "API Reference"),
|
|
5309
|
-
...referencesFor("asyncapi", config.asyncapi, "Events")
|
|
5310
|
-
];
|
|
5311
|
-
var referenceTabs = (config) => resolveReferences(config).map((ref) => ({
|
|
5312
|
-
label: ref.label,
|
|
5313
|
-
path: ref.route
|
|
5314
|
-
}));
|
|
5315
|
-
var hasReferences = (config) => config.openapi.enabled || config.asyncapi.enabled;
|
|
5316
5383
|
var darkModeConfig = (mode) => {
|
|
5317
5384
|
if (mode === "dark") {
|
|
5318
5385
|
return { darkMode: true };
|
|
@@ -5337,9 +5404,9 @@ var specConfiguration = async (spec, root) => {
|
|
|
5337
5404
|
if (URL_SPEC.test(spec)) {
|
|
5338
5405
|
return { config: { url: spec } };
|
|
5339
5406
|
}
|
|
5340
|
-
const absolute =
|
|
5407
|
+
const absolute = isAbsolute4(spec) ? spec : join12(root, spec);
|
|
5341
5408
|
try {
|
|
5342
|
-
return { config: { content: await
|
|
5409
|
+
return { config: { content: await readFile5(absolute, "utf-8") } };
|
|
5343
5410
|
} catch {
|
|
5344
5411
|
return {
|
|
5345
5412
|
config: { url: spec },
|
|
@@ -5353,6 +5420,9 @@ var buildReferenceFiles = async (options) => {
|
|
|
5353
5420
|
const seen = new Set;
|
|
5354
5421
|
const accepted = [];
|
|
5355
5422
|
for (const ref of resolveReferences(config)) {
|
|
5423
|
+
if (ref.renderer !== "scalar") {
|
|
5424
|
+
continue;
|
|
5425
|
+
}
|
|
5356
5426
|
if (seen.has(ref.route)) {
|
|
5357
5427
|
warnings.push(`Two API reference sources resolve to ${ref.route}; keeping the first.`);
|
|
5358
5428
|
continue;
|
|
@@ -5391,6 +5461,284 @@ var buildReferenceFiles = async (options) => {
|
|
|
5391
5461
|
return { files, warnings };
|
|
5392
5462
|
};
|
|
5393
5463
|
|
|
5464
|
+
// src/core/sources/cache.ts
|
|
5465
|
+
import { mkdir as mkdir2, readFile as readFile6, writeFile as writeFile3 } from "node:fs/promises";
|
|
5466
|
+
import { join as join13 } from "pathe";
|
|
5467
|
+
var hashText = (text) => {
|
|
5468
|
+
let hash = 5381;
|
|
5469
|
+
for (let i = 0;i < text.length; i += 1) {
|
|
5470
|
+
hash = (hash * 33 + (text.codePointAt(i) ?? 0)) % 2147483647;
|
|
5471
|
+
}
|
|
5472
|
+
return hash.toString(36);
|
|
5473
|
+
};
|
|
5474
|
+
var entriesDigest = (entries) => hashText(entries.map((entry) => `${entry.ref}:${entry.hash ?? hashText(entry.body.text)}`).join("|"));
|
|
5475
|
+
var pollingWatch = (load2, intervalSeconds) => (onChange) => {
|
|
5476
|
+
let last = "";
|
|
5477
|
+
const tick = async () => {
|
|
5478
|
+
try {
|
|
5479
|
+
const { entries } = await load2();
|
|
5480
|
+
const next = entriesDigest(entries);
|
|
5481
|
+
if (last && next !== last) {
|
|
5482
|
+
onChange();
|
|
5483
|
+
}
|
|
5484
|
+
last = next;
|
|
5485
|
+
} catch {}
|
|
5486
|
+
};
|
|
5487
|
+
const timer = setInterval(() => {
|
|
5488
|
+
tick();
|
|
5489
|
+
}, intervalSeconds * 1000);
|
|
5490
|
+
return () => clearInterval(timer);
|
|
5491
|
+
};
|
|
5492
|
+
var snapshotCache = (cacheDir) => {
|
|
5493
|
+
const file = join13(cacheDir, "entries.json");
|
|
5494
|
+
return {
|
|
5495
|
+
read: async () => {
|
|
5496
|
+
try {
|
|
5497
|
+
return JSON.parse(await readFile6(file, "utf-8"));
|
|
5498
|
+
} catch {
|
|
5499
|
+
return [];
|
|
5500
|
+
}
|
|
5501
|
+
},
|
|
5502
|
+
write: async (entries) => {
|
|
5503
|
+
try {
|
|
5504
|
+
await mkdir2(cacheDir, { recursive: true });
|
|
5505
|
+
await writeFile3(file, `${JSON.stringify(entries)}
|
|
5506
|
+
`, "utf-8");
|
|
5507
|
+
} catch {}
|
|
5508
|
+
}
|
|
5509
|
+
};
|
|
5510
|
+
};
|
|
5511
|
+
var loadWithCache = async (name, cache, fetchEntries, refresh = true) => {
|
|
5512
|
+
if (!refresh) {
|
|
5513
|
+
const cached3 = await cache.read();
|
|
5514
|
+
if (cached3.length > 0) {
|
|
5515
|
+
return { diagnostics: [], entries: cached3 };
|
|
5516
|
+
}
|
|
5517
|
+
}
|
|
5518
|
+
try {
|
|
5519
|
+
const entries = await fetchEntries();
|
|
5520
|
+
await cache.write(entries);
|
|
5521
|
+
return { diagnostics: [], entries };
|
|
5522
|
+
} catch (error) {
|
|
5523
|
+
const fallback = await cache.read();
|
|
5524
|
+
if (fallback.length > 0) {
|
|
5525
|
+
const diagnostic = {
|
|
5526
|
+
code: "BLUME_SOURCE_OFFLINE",
|
|
5527
|
+
message: `Source "${name}" could not be fetched (${error.message}); served ${fallback.length} cached entries.`,
|
|
5528
|
+
severity: "warning"
|
|
5529
|
+
};
|
|
5530
|
+
return { diagnostics: [diagnostic], entries: fallback };
|
|
5531
|
+
}
|
|
5532
|
+
throw new BlumeError({
|
|
5533
|
+
code: "BLUME_SOURCE_FETCH_FAILED",
|
|
5534
|
+
message: `Source "${name}" failed to load and no cache is available: ${error.message}`,
|
|
5535
|
+
severity: "error"
|
|
5536
|
+
});
|
|
5537
|
+
}
|
|
5538
|
+
};
|
|
5539
|
+
|
|
5540
|
+
// src/openapi/model.ts
|
|
5541
|
+
var NON_SLUG2 = /[^a-z0-9]+/gu;
|
|
5542
|
+
var SLUG_EDGES2 = /^-+|-+$/gu;
|
|
5543
|
+
var slugify2 = (text) => text.toLowerCase().replace(NON_SLUG2, "-").replace(SLUG_EDGES2, "");
|
|
5544
|
+
var HTTP_METHODS = [
|
|
5545
|
+
"get",
|
|
5546
|
+
"put",
|
|
5547
|
+
"post",
|
|
5548
|
+
"delete",
|
|
5549
|
+
"options",
|
|
5550
|
+
"head",
|
|
5551
|
+
"patch",
|
|
5552
|
+
"trace"
|
|
5553
|
+
];
|
|
5554
|
+
var UNTAGGED = "Operations";
|
|
5555
|
+
var operationKey = (method, path, operationId) => {
|
|
5556
|
+
const fromId = operationId ? slugify2(operationId) : "";
|
|
5557
|
+
return fromId || slugify2(`${method}-${path}`);
|
|
5558
|
+
};
|
|
5559
|
+
var isOperation = (value) => typeof value === "object" && value !== null;
|
|
5560
|
+
var extractOperations = (document, baseRoute) => {
|
|
5561
|
+
const operations = [];
|
|
5562
|
+
const tagOrder = [];
|
|
5563
|
+
const tagMeta = new Map((document.tags ?? []).map((tag) => [tag.name, tag.description ?? ""]));
|
|
5564
|
+
const seen = new Set;
|
|
5565
|
+
for (const [path, rawItem] of Object.entries(document.paths ?? {})) {
|
|
5566
|
+
const item = rawItem;
|
|
5567
|
+
if (!item || "$ref" in item) {
|
|
5568
|
+
continue;
|
|
5569
|
+
}
|
|
5570
|
+
for (const method of HTTP_METHODS) {
|
|
5571
|
+
const operation = item[method];
|
|
5572
|
+
if (!isOperation(operation)) {
|
|
5573
|
+
continue;
|
|
5574
|
+
}
|
|
5575
|
+
const tag = operation.tags?.[0] ?? UNTAGGED;
|
|
5576
|
+
const tagSlug = slugify2(tag) || "operations";
|
|
5577
|
+
if (!tagOrder.includes(tag)) {
|
|
5578
|
+
tagOrder.push(tag);
|
|
5579
|
+
}
|
|
5580
|
+
let key = operationKey(method, path, operation.operationId);
|
|
5581
|
+
while (seen.has(key)) {
|
|
5582
|
+
key = `${key}-${method}`;
|
|
5583
|
+
}
|
|
5584
|
+
seen.add(key);
|
|
5585
|
+
operations.push({
|
|
5586
|
+
deprecated: operation.deprecated ?? false,
|
|
5587
|
+
description: operation.description ?? "",
|
|
5588
|
+
key,
|
|
5589
|
+
method,
|
|
5590
|
+
operationId: operation.operationId,
|
|
5591
|
+
path,
|
|
5592
|
+
route: `${baseRoute}/${tagSlug}/${key}`,
|
|
5593
|
+
summary: operation.summary ?? "",
|
|
5594
|
+
tag,
|
|
5595
|
+
tagSlug
|
|
5596
|
+
});
|
|
5597
|
+
}
|
|
5598
|
+
}
|
|
5599
|
+
const tags = tagOrder.map((name) => ({
|
|
5600
|
+
description: tagMeta.get(name) ?? "",
|
|
5601
|
+
name,
|
|
5602
|
+
slug: slugify2(name) || "operations"
|
|
5603
|
+
}));
|
|
5604
|
+
return { operations, tags };
|
|
5605
|
+
};
|
|
5606
|
+
|
|
5607
|
+
// src/openapi/parse.ts
|
|
5608
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
5609
|
+
import { normalize as normalize2, upgrade } from "@scalar/openapi-parser";
|
|
5610
|
+
import { isAbsolute as isAbsolute5, join as join14 } from "pathe";
|
|
5611
|
+
var URL_SPEC2 = /^https?:\/\//u;
|
|
5612
|
+
var readSpecText = async (spec, root) => {
|
|
5613
|
+
if (URL_SPEC2.test(spec)) {
|
|
5614
|
+
const response = await fetch(spec);
|
|
5615
|
+
if (!response.ok) {
|
|
5616
|
+
throw new Error(`${spec} -> ${response.status} ${response.statusText}`);
|
|
5617
|
+
}
|
|
5618
|
+
return await response.text();
|
|
5619
|
+
}
|
|
5620
|
+
const absolute = isAbsolute5(spec) ? spec : join14(root, spec);
|
|
5621
|
+
return await readFile7(absolute, "utf-8");
|
|
5622
|
+
};
|
|
5623
|
+
var parseSpec = async (spec, root) => {
|
|
5624
|
+
const text = await readSpecText(spec, root);
|
|
5625
|
+
const normalized = normalize2(text);
|
|
5626
|
+
const { specification } = upgrade(normalized);
|
|
5627
|
+
return { document: specification, warnings: [] };
|
|
5628
|
+
};
|
|
5629
|
+
|
|
5630
|
+
// src/openapi/render-mdx.ts
|
|
5631
|
+
var MDX_UNSAFE = /[<>{}]/gu;
|
|
5632
|
+
var ENTITIES = {
|
|
5633
|
+
"<": "<",
|
|
5634
|
+
">": ">",
|
|
5635
|
+
"{": "{",
|
|
5636
|
+
"}": "}"
|
|
5637
|
+
};
|
|
5638
|
+
var mdxSafe = (text) => text.replace(MDX_UNSAFE, (char) => ENTITIES[char] ?? char);
|
|
5639
|
+
var withDescription = (description, component) => description.trim() ? `${mdxSafe(description.trim())}
|
|
5640
|
+
|
|
5641
|
+
${component}` : component;
|
|
5642
|
+
var operationMdx = (spec, operation) => {
|
|
5643
|
+
const method = operation.method.toUpperCase();
|
|
5644
|
+
const title = operation.summary || `${method} ${operation.path}`;
|
|
5645
|
+
const description = operation.description.trim() === operation.summary.trim() ? "" : operation.description;
|
|
5646
|
+
return {
|
|
5647
|
+
body: withDescription(description, `<Operation source="${spec.slug}" id="${operation.key}" />`),
|
|
5648
|
+
data: {
|
|
5649
|
+
...operation.deprecated ? { deprecated: true } : {},
|
|
5650
|
+
search: { tags: [operation.tag, method] },
|
|
5651
|
+
sidebar: { badge: method, label: operation.summary || operation.path },
|
|
5652
|
+
title,
|
|
5653
|
+
type: "openapi-operation"
|
|
5654
|
+
}
|
|
5655
|
+
};
|
|
5656
|
+
};
|
|
5657
|
+
var overviewMdx = (spec) => ({
|
|
5658
|
+
body: withDescription(spec.description, `<ApiOverview source="${spec.slug}" />`),
|
|
5659
|
+
data: {
|
|
5660
|
+
sidebar: { label: "Overview" },
|
|
5661
|
+
title: spec.title || spec.label
|
|
5662
|
+
}
|
|
5663
|
+
});
|
|
5664
|
+
|
|
5665
|
+
// src/openapi/source.ts
|
|
5666
|
+
var isOpenApiSource = (source) => source.kind === "openapi-source";
|
|
5667
|
+
var routeToRef = (route) => route.replace(/^\/+/u, "");
|
|
5668
|
+
var toEntry = (rendered, ref) => {
|
|
5669
|
+
const raw = frontmatter_default.stringify(`${rendered.body}
|
|
5670
|
+
`, rendered.data);
|
|
5671
|
+
return {
|
|
5672
|
+
body: { format: "mdx", text: rendered.body },
|
|
5673
|
+
data: rendered.data,
|
|
5674
|
+
hash: hashText(raw),
|
|
5675
|
+
raw,
|
|
5676
|
+
ref
|
|
5677
|
+
};
|
|
5678
|
+
};
|
|
5679
|
+
var specEntries = (spec, operations) => {
|
|
5680
|
+
const entries = operations.map((operation) => toEntry(operationMdx(spec, operation), `${routeToRef(operation.route)}.mdx`));
|
|
5681
|
+
entries.push(toEntry(overviewMdx(spec), `${routeToRef(spec.route)}/index.mdx`));
|
|
5682
|
+
return entries;
|
|
5683
|
+
};
|
|
5684
|
+
var openApiSource = (references, ctx) => {
|
|
5685
|
+
let parsed = {};
|
|
5686
|
+
const loadReference = async (reference) => {
|
|
5687
|
+
try {
|
|
5688
|
+
const { document } = await parseSpec(reference.spec, ctx.projectRoot);
|
|
5689
|
+
const { operations, tags } = extractOperations(document, reference.route);
|
|
5690
|
+
const info = document.info ?? { title: reference.label, version: "" };
|
|
5691
|
+
const spec = {
|
|
5692
|
+
codeSamples: reference.display.codeSamples,
|
|
5693
|
+
description: info.description ?? "",
|
|
5694
|
+
document,
|
|
5695
|
+
expandSchemas: reference.display.expandSchemas,
|
|
5696
|
+
label: reference.label,
|
|
5697
|
+
operations: Object.fromEntries(operations.map((operation) => [operation.key, operation])),
|
|
5698
|
+
route: reference.route,
|
|
5699
|
+
slug: reference.slug,
|
|
5700
|
+
tags,
|
|
5701
|
+
title: info.title ?? reference.label,
|
|
5702
|
+
version: info.version ?? ""
|
|
5703
|
+
};
|
|
5704
|
+
return {
|
|
5705
|
+
entries: specEntries(spec, operations),
|
|
5706
|
+
slug: reference.slug,
|
|
5707
|
+
spec
|
|
5708
|
+
};
|
|
5709
|
+
} catch (error) {
|
|
5710
|
+
return {
|
|
5711
|
+
code: "BLUME_OPENAPI_UNAVAILABLE",
|
|
5712
|
+
message: `Could not load OpenAPI spec "${reference.spec}" for ${reference.route} (${error.message}); its reference pages were skipped.`,
|
|
5713
|
+
severity: "warning"
|
|
5714
|
+
};
|
|
5715
|
+
}
|
|
5716
|
+
};
|
|
5717
|
+
const load2 = async () => {
|
|
5718
|
+
const results = await Promise.all(references.map(loadReference));
|
|
5719
|
+
const entries = [];
|
|
5720
|
+
const diagnostics = [];
|
|
5721
|
+
const data = {};
|
|
5722
|
+
for (const result of results) {
|
|
5723
|
+
if ("severity" in result) {
|
|
5724
|
+
diagnostics.push(result);
|
|
5725
|
+
continue;
|
|
5726
|
+
}
|
|
5727
|
+
data[result.slug] = result.spec;
|
|
5728
|
+
entries.push(...result.entries);
|
|
5729
|
+
}
|
|
5730
|
+
parsed = data;
|
|
5731
|
+
return { diagnostics, entries };
|
|
5732
|
+
};
|
|
5733
|
+
return {
|
|
5734
|
+
kind: "openapi-source",
|
|
5735
|
+
load: load2,
|
|
5736
|
+
name: "openapi",
|
|
5737
|
+
openApiData: () => parsed,
|
|
5738
|
+
staged: true
|
|
5739
|
+
};
|
|
5740
|
+
};
|
|
5741
|
+
|
|
5394
5742
|
// src/theme/entry.ts
|
|
5395
5743
|
var tailwindEntryTemplate = (options) => `/* Generated by Blume. Do not edit. */
|
|
5396
5744
|
@import "tailwindcss";
|
|
@@ -6011,8 +6359,8 @@ ${options.userTheme}
|
|
|
6011
6359
|
|
|
6012
6360
|
// src/theme/twoslash.ts
|
|
6013
6361
|
import { readFileSync as readFileSync5 } from "node:fs";
|
|
6014
|
-
import { createRequire as
|
|
6015
|
-
var require2 =
|
|
6362
|
+
import { createRequire as createRequire4 } from "node:module";
|
|
6363
|
+
var require2 = createRequire4(import.meta.url);
|
|
6016
6364
|
var OVERRIDES = `
|
|
6017
6365
|
/* Twoslash: theme the rich renderer with Blume tokens. */
|
|
6018
6366
|
:root {
|
|
@@ -6174,13 +6522,13 @@ export const layoutOverrides = { ...(overrides.layout ?? {})${layoutEntries.leng
|
|
|
6174
6522
|
};
|
|
6175
6523
|
|
|
6176
6524
|
// src/astro/examples.ts
|
|
6177
|
-
import { readFile as
|
|
6178
|
-
import { join as
|
|
6525
|
+
import { readFile as readFile9 } from "node:fs/promises";
|
|
6526
|
+
import { join as join16, relative as relative4 } from "pathe";
|
|
6179
6527
|
import { glob as glob2 } from "tinyglobby";
|
|
6180
6528
|
|
|
6181
6529
|
// src/astro/islands.ts
|
|
6182
|
-
import { readFile as
|
|
6183
|
-
import { basename, join as
|
|
6530
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
6531
|
+
import { basename, join as join15 } from "pathe";
|
|
6184
6532
|
import { glob } from "tinyglobby";
|
|
6185
6533
|
var DEFAULT_CLIENT = "visible";
|
|
6186
6534
|
var VALID_MODES = new Set([
|
|
@@ -6209,14 +6557,14 @@ var readClientMode = (source, file, warnings) => {
|
|
|
6209
6557
|
return mode;
|
|
6210
6558
|
};
|
|
6211
6559
|
var discoverIslands = async (root) => {
|
|
6212
|
-
const dir =
|
|
6560
|
+
const dir = join15(root, "islands");
|
|
6213
6561
|
const matches = await glob(["**/*.{jsx,svelte,tsx,vue}"], {
|
|
6214
6562
|
absolute: true,
|
|
6215
6563
|
cwd: dir,
|
|
6216
6564
|
onlyFiles: true
|
|
6217
6565
|
});
|
|
6218
6566
|
const files = matches.toSorted();
|
|
6219
|
-
const sources = await Promise.all(files.map((file) =>
|
|
6567
|
+
const sources = await Promise.all(files.map((file) => readFile8(file, "utf-8")));
|
|
6220
6568
|
const islands = [];
|
|
6221
6569
|
const warnings = [];
|
|
6222
6570
|
const seen = new Map;
|
|
@@ -6272,14 +6620,14 @@ var splitGlobBase = (pattern) => {
|
|
|
6272
6620
|
};
|
|
6273
6621
|
var discoverExamples = async (root, pattern = "examples") => {
|
|
6274
6622
|
const { base, rest } = GLOB_MAGIC.test(pattern) ? splitGlobBase(pattern) : { base: pattern, rest: DEFAULT_EXAMPLE_GLOB };
|
|
6275
|
-
const dir =
|
|
6623
|
+
const dir = join16(root, base);
|
|
6276
6624
|
const matches = await glob2([rest], {
|
|
6277
6625
|
absolute: true,
|
|
6278
6626
|
cwd: dir,
|
|
6279
6627
|
onlyFiles: true
|
|
6280
6628
|
});
|
|
6281
6629
|
const files = matches.toSorted();
|
|
6282
|
-
const sources = await Promise.all(files.map((file) =>
|
|
6630
|
+
const sources = await Promise.all(files.map((file) => readFile9(file, "utf-8")));
|
|
6283
6631
|
const examples = [];
|
|
6284
6632
|
const warnings = [];
|
|
6285
6633
|
const seen = new Map;
|
|
@@ -6353,10 +6701,10 @@ var customOgRoutes = (pages, siteTitle) => {
|
|
|
6353
6701
|
};
|
|
6354
6702
|
|
|
6355
6703
|
// src/astro/generate.ts
|
|
6356
|
-
var BLUME_SRC =
|
|
6704
|
+
var BLUME_SRC = join17(packageRoot(), "src");
|
|
6357
6705
|
var canResolveFrom = (fromDir, spec) => {
|
|
6358
6706
|
try {
|
|
6359
|
-
|
|
6707
|
+
createRequire5(pathToFileURL2(join17(fromDir, "_.js")).href).resolve(spec);
|
|
6360
6708
|
return true;
|
|
6361
6709
|
} catch {
|
|
6362
6710
|
return false;
|
|
@@ -6364,15 +6712,15 @@ var canResolveFrom = (fromDir, spec) => {
|
|
|
6364
6712
|
};
|
|
6365
6713
|
var resolvedAstroPath = (fromDir) => {
|
|
6366
6714
|
try {
|
|
6367
|
-
const pkg =
|
|
6715
|
+
const pkg = createRequire5(pathToFileURL2(join17(fromDir, "_.js")).href).resolve("astro/package.json");
|
|
6368
6716
|
return realpathSync(pkg);
|
|
6369
6717
|
} catch {
|
|
6370
6718
|
return null;
|
|
6371
6719
|
}
|
|
6372
6720
|
};
|
|
6373
6721
|
var blumeDepsDir = (pkgDir = packageRoot()) => {
|
|
6374
|
-
const candidates = [
|
|
6375
|
-
return candidates.find((dir) =>
|
|
6722
|
+
const candidates = [join17(pkgDir, "node_modules"), dirname7(pkgDir)];
|
|
6723
|
+
return candidates.find((dir) => existsSync9(join17(dir, "astro"))) ?? null;
|
|
6376
6724
|
};
|
|
6377
6725
|
var linkDepsJunction = async (link, depsDir) => {
|
|
6378
6726
|
const existing = await lstat(link).catch(() => null);
|
|
@@ -6382,7 +6730,7 @@ var linkDepsJunction = async (link, depsDir) => {
|
|
|
6382
6730
|
}
|
|
6383
6731
|
await rm(link, { force: true });
|
|
6384
6732
|
}
|
|
6385
|
-
await
|
|
6733
|
+
await mkdir3(dirname7(link), { recursive: true });
|
|
6386
6734
|
await symlink(depsDir, link, "junction");
|
|
6387
6735
|
};
|
|
6388
6736
|
var readPkgVersion = (pkgJsonPath) => {
|
|
@@ -6412,8 +6760,8 @@ var ensureDepsLink = async (outDir, pkgDir = packageRoot()) => {
|
|
|
6412
6760
|
if (blumeAstro && outDirAstro === blumeAstro) {
|
|
6413
6761
|
return null;
|
|
6414
6762
|
}
|
|
6415
|
-
if (
|
|
6416
|
-
await linkDepsJunction(
|
|
6763
|
+
if (existsSync9(join17(depsDir, "@astrojs", "mdx"))) {
|
|
6764
|
+
await linkDepsJunction(join17(outDir, "node_modules"), depsDir);
|
|
6417
6765
|
return null;
|
|
6418
6766
|
}
|
|
6419
6767
|
return astroConflictWarning(blumeAstro, outDirAstro);
|
|
@@ -6437,7 +6785,7 @@ var readOptional = async (path) => {
|
|
|
6437
6785
|
return "";
|
|
6438
6786
|
}
|
|
6439
6787
|
try {
|
|
6440
|
-
return await
|
|
6788
|
+
return await readFile10(path, "utf-8");
|
|
6441
6789
|
} catch {
|
|
6442
6790
|
return "";
|
|
6443
6791
|
}
|
|
@@ -6453,16 +6801,16 @@ var detectNeedsReact = async (root) => {
|
|
|
6453
6801
|
var writeIfChanged = async (path, content) => {
|
|
6454
6802
|
let existing = null;
|
|
6455
6803
|
try {
|
|
6456
|
-
existing = await
|
|
6804
|
+
existing = await readFile10(path, "utf-8");
|
|
6457
6805
|
} catch {
|
|
6458
6806
|
existing = null;
|
|
6459
6807
|
}
|
|
6460
6808
|
if (existing === content) {
|
|
6461
6809
|
return false;
|
|
6462
6810
|
}
|
|
6463
|
-
await
|
|
6811
|
+
await mkdir3(dirname7(path), { recursive: true });
|
|
6464
6812
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
6465
|
-
await
|
|
6813
|
+
await writeFile4(tmp, content, "utf-8");
|
|
6466
6814
|
try {
|
|
6467
6815
|
await rename(tmp, path);
|
|
6468
6816
|
} catch (error) {
|
|
@@ -6477,7 +6825,7 @@ var pruneOrphans = async (srcDir, written) => {
|
|
|
6477
6825
|
cwd: srcDir,
|
|
6478
6826
|
onlyFiles: true
|
|
6479
6827
|
});
|
|
6480
|
-
await Promise.all(existing.map((path) =>
|
|
6828
|
+
await Promise.all(existing.map((path) => normalize3(path)).filter((path) => !written.has(path)).map((path) => rm(path, { force: true })));
|
|
6481
6829
|
};
|
|
6482
6830
|
var collectStaged = (project) => {
|
|
6483
6831
|
const staged = new Map;
|
|
@@ -6492,11 +6840,11 @@ var writeStagedContent = async (out, staged) => {
|
|
|
6492
6840
|
const contentDir = stagedContentDir(out);
|
|
6493
6841
|
const written = new Set;
|
|
6494
6842
|
await Promise.all([...staged].map(async ([entryId, text]) => {
|
|
6495
|
-
const path =
|
|
6496
|
-
written.add(
|
|
6843
|
+
const path = join17(contentDir, entryId);
|
|
6844
|
+
written.add(normalize3(path));
|
|
6497
6845
|
await writeIfChanged(path, text);
|
|
6498
6846
|
}));
|
|
6499
|
-
if (
|
|
6847
|
+
if (existsSync9(contentDir)) {
|
|
6500
6848
|
await pruneOrphans(contentDir, written);
|
|
6501
6849
|
}
|
|
6502
6850
|
};
|
|
@@ -6513,9 +6861,9 @@ var resolveLogo = (project) => {
|
|
|
6513
6861
|
if (light && light === dark && light.toLowerCase().endsWith(".svg")) {
|
|
6514
6862
|
const rel = light.replace(/^\//u, "");
|
|
6515
6863
|
const file = [
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
].find((path) =>
|
|
6864
|
+
join17(project.context.root, "public", rel),
|
|
6865
|
+
join17(project.context.root, rel)
|
|
6866
|
+
].find((path) => existsSync9(path));
|
|
6519
6867
|
if (file) {
|
|
6520
6868
|
return { alt, href, svg: readFileSync6(file, "utf-8") };
|
|
6521
6869
|
}
|
|
@@ -6543,7 +6891,7 @@ var faviconType = (name) => {
|
|
|
6543
6891
|
};
|
|
6544
6892
|
var inlineDataUri = (file, type) => `data:${type};base64,${readFileSync6(file).toString("base64")}`;
|
|
6545
6893
|
var defaultFavicon = () => ({
|
|
6546
|
-
href: inlineDataUri(
|
|
6894
|
+
href: inlineDataUri(join17(BLUME_SRC, "assets", "icon.png"), "image/png"),
|
|
6547
6895
|
type: "image/png"
|
|
6548
6896
|
});
|
|
6549
6897
|
var APPLE_ICON_CANDIDATES = [
|
|
@@ -6555,13 +6903,13 @@ var APPLE_ICON_CANDIDATES = [
|
|
|
6555
6903
|
var resolveIconFile = (project, candidates) => {
|
|
6556
6904
|
const { root } = project.context;
|
|
6557
6905
|
for (const name of candidates) {
|
|
6558
|
-
if (
|
|
6906
|
+
if (existsSync9(join17(root, "public", name))) {
|
|
6559
6907
|
return { href: `/${name}`, type: faviconType(name) };
|
|
6560
6908
|
}
|
|
6561
6909
|
}
|
|
6562
6910
|
for (const name of candidates) {
|
|
6563
|
-
const file =
|
|
6564
|
-
if (
|
|
6911
|
+
const file = join17(root, name);
|
|
6912
|
+
if (existsSync9(file)) {
|
|
6565
6913
|
const type = faviconType(name);
|
|
6566
6914
|
return { href: inlineDataUri(file, type ?? "image/x-icon"), type };
|
|
6567
6915
|
}
|
|
@@ -6620,7 +6968,6 @@ var buildRuntimeData = (project) => {
|
|
|
6620
6968
|
chromeVariants: [],
|
|
6621
6969
|
selectors: [],
|
|
6622
6970
|
sidebar: [],
|
|
6623
|
-
sidebarVariants: [],
|
|
6624
6971
|
tabs: []
|
|
6625
6972
|
})
|
|
6626
6973
|
])) : {};
|
|
@@ -6643,6 +6990,7 @@ var buildRuntimeData = (project) => {
|
|
|
6643
6990
|
label
|
|
6644
6991
|
}))
|
|
6645
6992
|
} : null,
|
|
6993
|
+
icons: config.icons,
|
|
6646
6994
|
imageZoom: config.markdown.imageZoom,
|
|
6647
6995
|
logo: resolveLogo(project),
|
|
6648
6996
|
mcp: config.mcp.enabled ? { name: config.mcp.name ?? config.title, route: config.mcp.route } : null,
|
|
@@ -6689,7 +7037,7 @@ var buildRuntimeData = (project) => {
|
|
|
6689
7037
|
var planMcp = (project, srcDir) => {
|
|
6690
7038
|
const { config } = project;
|
|
6691
7039
|
const { route } = config.mcp;
|
|
6692
|
-
const dir =
|
|
7040
|
+
const dir = join17(srcDir, "blume-mcp");
|
|
6693
7041
|
const base = {
|
|
6694
7042
|
dir,
|
|
6695
7043
|
discoveryPages: [],
|
|
@@ -6713,11 +7061,11 @@ var planMcp = (project, srcDir) => {
|
|
|
6713
7061
|
...base,
|
|
6714
7062
|
discoveryPages: [
|
|
6715
7063
|
{
|
|
6716
|
-
entrypoint:
|
|
7064
|
+
entrypoint: join17(dir, "discovery.ts"),
|
|
6717
7065
|
pattern: "/.well-known/mcp.json"
|
|
6718
7066
|
},
|
|
6719
7067
|
{
|
|
6720
|
-
entrypoint:
|
|
7068
|
+
entrypoint: join17(dir, "server-card.ts"),
|
|
6721
7069
|
pattern: "/.well-known/mcp/server-card.json"
|
|
6722
7070
|
}
|
|
6723
7071
|
],
|
|
@@ -6736,11 +7084,11 @@ var writeMcpFiles = async (project, plan, write) => {
|
|
|
6736
7084
|
version: data.version
|
|
6737
7085
|
};
|
|
6738
7086
|
await Promise.all([
|
|
6739
|
-
write(
|
|
7087
|
+
write(join17(plan.srcDir, "generated", "mcp-data.json"), `${JSON.stringify(data)}
|
|
6740
7088
|
`),
|
|
6741
|
-
write(
|
|
6742
|
-
write(
|
|
6743
|
-
write(
|
|
7089
|
+
write(join17(plan.srcDir, "pages", mcpPageFile(plan.route)), mcpEndpointTemplate(plan.route)),
|
|
7090
|
+
write(join17(plan.dir, "discovery.ts"), staticJsonEndpointTemplate(buildMcpDiscovery(discoveryInput))),
|
|
7091
|
+
write(join17(plan.dir, "server-card.ts"), staticJsonEndpointTemplate(buildMcpServerCard(discoveryInput)))
|
|
6744
7092
|
]);
|
|
6745
7093
|
};
|
|
6746
7094
|
var writeAskFiles = async (project, srcDir, write) => {
|
|
@@ -6750,16 +7098,16 @@ var writeAskFiles = async (project, srcDir, write) => {
|
|
|
6750
7098
|
}
|
|
6751
7099
|
const grounded = ask.provider !== "inkeep";
|
|
6752
7100
|
if (grounded) {
|
|
6753
|
-
await write(
|
|
7101
|
+
await write(join17(srcDir, "generated", "ask-data.json"), `${JSON.stringify(await buildAskData(project))}
|
|
6754
7102
|
`);
|
|
6755
7103
|
}
|
|
6756
|
-
await write(
|
|
7104
|
+
await write(join17(srcDir, "pages", "api", "ask.ts"), askEndpointTemplate(resolveAskBackend(ask), grounded));
|
|
6757
7105
|
};
|
|
6758
7106
|
var writeNotFoundPage = async (write, srcDir, pages, contentPages) => {
|
|
6759
7107
|
if (routeIsTaken(pages, contentPages, "/404")) {
|
|
6760
7108
|
return;
|
|
6761
7109
|
}
|
|
6762
|
-
await write(
|
|
7110
|
+
await write(join17(srcDir, "pages", "404.astro"), notFoundPageTemplate());
|
|
6763
7111
|
};
|
|
6764
7112
|
var shouldGenerateChangelog = (project) => {
|
|
6765
7113
|
const hasChangelog = project.graph.pages.some((page) => page.contentType === "changelog" && !(page.meta.draft || page.meta.sidebar.hidden));
|
|
@@ -6768,7 +7116,7 @@ var shouldGenerateChangelog = (project) => {
|
|
|
6768
7116
|
return (hasChangelog || hasChangelogSource) && !changelogRouteTaken;
|
|
6769
7117
|
};
|
|
6770
7118
|
var buildComponentSlots = async (componentsFile) => {
|
|
6771
|
-
const analysis = componentsFile ? analyzeComponentOverrides(await
|
|
7119
|
+
const analysis = componentsFile ? analyzeComponentOverrides(await readFile10(componentsFile, "utf-8"), componentsFile) : null;
|
|
6772
7120
|
return {
|
|
6773
7121
|
plan: planComponentSlots(componentsFile, analysis),
|
|
6774
7122
|
tags: analysis ? [...analysis.mdx, ...analysis.islands].map((entry) => entry.key) : [],
|
|
@@ -6778,14 +7126,15 @@ var buildComponentSlots = async (componentsFile) => {
|
|
|
6778
7126
|
var generateRuntime = async (project) => {
|
|
6779
7127
|
const { context, config } = project;
|
|
6780
7128
|
const out = context.outDir;
|
|
6781
|
-
const srcDir =
|
|
6782
|
-
const dataPath =
|
|
6783
|
-
const themePath =
|
|
6784
|
-
const searchClientPath =
|
|
6785
|
-
const examplesPath =
|
|
7129
|
+
const srcDir = join17(out, "src");
|
|
7130
|
+
const dataPath = join17(srcDir, "generated", "data.json");
|
|
7131
|
+
const themePath = join17(srcDir, "generated", "app.css");
|
|
7132
|
+
const searchClientPath = join17(srcDir, "generated", "search-client.ts");
|
|
7133
|
+
const examplesPath = join17(srcDir, "generated", "examples.ts");
|
|
7134
|
+
const openapiPath = join17(srcDir, "generated", "openapi.json");
|
|
6786
7135
|
const written = new Set;
|
|
6787
7136
|
const write = (path, content) => {
|
|
6788
|
-
written.add(
|
|
7137
|
+
written.add(normalize3(path));
|
|
6789
7138
|
return writeIfChanged(path, content);
|
|
6790
7139
|
};
|
|
6791
7140
|
const depsLinkWarning = await ensureDepsLink(out);
|
|
@@ -6818,7 +7167,7 @@ var generateRuntime = async (project) => {
|
|
|
6818
7167
|
const staged = collectStaged(project);
|
|
6819
7168
|
const hasStaged = staged.size > 0;
|
|
6820
7169
|
const structural = await Promise.all([
|
|
6821
|
-
write(
|
|
7170
|
+
write(join17(out, "astro.config.mjs"), astroConfigTemplate({
|
|
6822
7171
|
aliases: resolveTsconfigAliases(context.root),
|
|
6823
7172
|
config,
|
|
6824
7173
|
contentRoutes: project.manifest.routes.map((route) => route.path),
|
|
@@ -6828,24 +7177,25 @@ var generateRuntime = async (project) => {
|
|
|
6828
7177
|
needsReact,
|
|
6829
7178
|
needsSvelte,
|
|
6830
7179
|
needsVue,
|
|
7180
|
+
openapiPath,
|
|
6831
7181
|
pages,
|
|
6832
7182
|
searchClientPath,
|
|
6833
7183
|
themePath
|
|
6834
7184
|
})),
|
|
6835
|
-
write(
|
|
6836
|
-
write(
|
|
6837
|
-
write(
|
|
6838
|
-
write(
|
|
6839
|
-
write(
|
|
7185
|
+
write(join17(out, "package.json"), runtimePackageTemplate(runtimeDependencies({ config, needsReact, needsSvelte, needsVue }))),
|
|
7186
|
+
write(join17(out, "tsconfig.json"), runtimeTsconfigTemplate()),
|
|
7187
|
+
write(join17(srcDir, "env.d.ts"), envTemplate()),
|
|
7188
|
+
write(join17(srcDir, "content.config.ts"), contentConfigTemplate({ config, context, staged: hasStaged })),
|
|
7189
|
+
write(join17(srcDir, "pages", "[...slug].astro"), catchAllPageTemplate({
|
|
6840
7190
|
askEnabled,
|
|
6841
7191
|
exportEpub,
|
|
6842
7192
|
exportPdf,
|
|
6843
7193
|
mathEnabled: config.markdown.math,
|
|
6844
7194
|
needsReact
|
|
6845
7195
|
})),
|
|
6846
|
-
write(
|
|
6847
|
-
write(
|
|
6848
|
-
write(
|
|
7196
|
+
write(join17(srcDir, "generated", "components.ts"), slotPlan.module),
|
|
7197
|
+
write(join17(srcDir, "generated", "islands.ts"), islandMapTemplate(islandDiscovery.islands)),
|
|
7198
|
+
write(join17(srcDir, "generated", "examples.ts"), exampleMapTemplate(exampleDiscovery.examples)),
|
|
6849
7199
|
write(themePath, tailwindEntryTemplate({
|
|
6850
7200
|
configTokens: `${buildThemeCss(config.theme)}${buildFontsCss(config.theme.fonts)}`,
|
|
6851
7201
|
sources: [
|
|
@@ -6856,16 +7206,16 @@ var generateRuntime = async (project) => {
|
|
|
6856
7206
|
userTheme
|
|
6857
7207
|
}))
|
|
6858
7208
|
]);
|
|
6859
|
-
await Promise.all(islandDiscovery.islands.map((island) => write(
|
|
6860
|
-
await Promise.all(slotPlan.wrappers.map((wrapper) => write(
|
|
6861
|
-
await Promise.all(exampleDiscovery.examples.map((example) => write(
|
|
7209
|
+
await Promise.all(islandDiscovery.islands.map((island) => write(join17(srcDir, "generated", "islands", `${island.name}.astro`), islandWrapperTemplate(island))));
|
|
7210
|
+
await Promise.all(slotPlan.wrappers.map((wrapper) => write(join17(srcDir, "generated", "component-slots", `${wrapper.name}.astro`), wrapper.content)));
|
|
7211
|
+
await Promise.all(exampleDiscovery.examples.map((example) => write(join17(srcDir, "generated", "examples", `${exampleSlug(example.path)}.astro`), exampleWrapperTemplate(example))));
|
|
6862
7212
|
await writeAskFiles(project, srcDir, write);
|
|
6863
7213
|
await writeMcpFiles(project, mcp, write);
|
|
6864
7214
|
if (config.seo.og.enabled) {
|
|
6865
|
-
await write(
|
|
7215
|
+
await write(join17(srcDir, "pages", "og", "[...slug].png.ts"), ogEndpointTemplate(ogRoutes));
|
|
6866
7216
|
}
|
|
6867
7217
|
if (shouldGenerateChangelog(project)) {
|
|
6868
|
-
await write(
|
|
7218
|
+
await write(join17(srcDir, "pages", "changelog.astro"), changelogIndexTemplate({
|
|
6869
7219
|
askEnabled,
|
|
6870
7220
|
exportEpub,
|
|
6871
7221
|
exportPdf,
|
|
@@ -6877,27 +7227,27 @@ var generateRuntime = async (project) => {
|
|
|
6877
7227
|
await write(searchClientPath, searchClientTemplate(config));
|
|
6878
7228
|
if (servesStaticIndex(config.search.provider)) {
|
|
6879
7229
|
const documents = await buildSearchDocuments(project);
|
|
6880
|
-
await write(
|
|
7230
|
+
await write(join17(srcDir, "generated", "search.json"), `${JSON.stringify(documents)}
|
|
6881
7231
|
`);
|
|
6882
|
-
await write(
|
|
7232
|
+
await write(join17(srcDir, "pages", "blume-search.json.ts"), searchEndpointTemplate());
|
|
6883
7233
|
}
|
|
6884
7234
|
if (config.search.provider === "mixedbread") {
|
|
6885
|
-
await write(
|
|
7235
|
+
await write(join17(srcDir, "pages", "api", "search.ts"), mixedbreadSearchEndpointTemplate(config.search.mixedbread?.storeId ?? ""));
|
|
6886
7236
|
}
|
|
6887
7237
|
const rawMarkdown = await buildRawMarkdown(project);
|
|
6888
7238
|
await Promise.all([
|
|
6889
|
-
write(
|
|
7239
|
+
write(join17(srcDir, "generated", "raw-markdown.json"), `${JSON.stringify(rawMarkdown)}
|
|
6890
7240
|
`),
|
|
6891
|
-
write(
|
|
6892
|
-
write(
|
|
7241
|
+
write(join17(srcDir, "pages", "[...slug].md.ts"), rawMarkdownEndpointTemplate()),
|
|
7242
|
+
write(join17(srcDir, "pages", "[...slug].mdx.ts"), rawMarkdownEndpointTemplate())
|
|
6893
7243
|
]);
|
|
6894
7244
|
const feeds = buildRssFeeds(project);
|
|
6895
7245
|
if (feeds.length > 0) {
|
|
6896
7246
|
const feedXml = Object.fromEntries(feeds.map((feed) => [feed.type, renderRssFeed(feed)]));
|
|
6897
7247
|
await Promise.all([
|
|
6898
|
-
write(
|
|
7248
|
+
write(join17(srcDir, "generated", "rss.json"), `${JSON.stringify(feedXml)}
|
|
6899
7249
|
`),
|
|
6900
|
-
write(
|
|
7250
|
+
write(join17(srcDir, "pages", "[section]", "rss.xml.ts"), rssEndpointTemplate())
|
|
6901
7251
|
]);
|
|
6902
7252
|
}
|
|
6903
7253
|
const warnings = [
|
|
@@ -6927,17 +7277,20 @@ var generateRuntime = async (project) => {
|
|
|
6927
7277
|
}
|
|
6928
7278
|
}
|
|
6929
7279
|
warnings.push(...islandFrameworkWarnings(frameworks, context.root));
|
|
6930
|
-
if (
|
|
7280
|
+
if (hasScalarReferences(config)) {
|
|
6931
7281
|
const references = await buildReferenceFiles({
|
|
6932
7282
|
config,
|
|
6933
7283
|
contentRoutes: new Set(project.graph.pages.map((page) => page.route)),
|
|
6934
7284
|
root: context.root
|
|
6935
7285
|
});
|
|
6936
7286
|
warnings.push(...references.warnings);
|
|
6937
|
-
await Promise.all(references.files.map((file) => write(
|
|
7287
|
+
await Promise.all(references.files.map((file) => write(join17(srcDir, "pages", file.pagePath), file.content)));
|
|
6938
7288
|
}
|
|
6939
|
-
await write(
|
|
6940
|
-
|
|
7289
|
+
await write(join17(srcDir, "generated", "data.json"), buildRuntimeData(project));
|
|
7290
|
+
const openApiSource2 = project.sources.find(isOpenApiSource);
|
|
7291
|
+
await write(openapiPath, `${JSON.stringify(openApiSource2 ? openApiSource2.openApiData() : {})}
|
|
7292
|
+
`);
|
|
7293
|
+
await write(join17(out, "blume.manifest.json"), `${JSON.stringify(project.manifest, null, 2)}
|
|
6941
7294
|
`);
|
|
6942
7295
|
await writeStagedContent(out, staged);
|
|
6943
7296
|
await pruneOrphans(srcDir, written);
|
|
@@ -6945,12 +7298,12 @@ var generateRuntime = async (project) => {
|
|
|
6945
7298
|
};
|
|
6946
7299
|
|
|
6947
7300
|
// src/core/config.ts
|
|
6948
|
-
import { existsSync as
|
|
7301
|
+
import { existsSync as existsSync11, readFileSync as readFileSync7 } from "node:fs";
|
|
6949
7302
|
|
|
6950
7303
|
// src/core/bridge.ts
|
|
6951
|
-
import { existsSync as
|
|
6952
|
-
import { readFile as
|
|
6953
|
-
import { join as
|
|
7304
|
+
import { existsSync as existsSync10 } from "node:fs";
|
|
7305
|
+
import { readFile as readFile12 } from "node:fs/promises";
|
|
7306
|
+
import { join as join18 } from "pathe";
|
|
6954
7307
|
|
|
6955
7308
|
// src/migrate/mintlify/assets.ts
|
|
6956
7309
|
var assetRefs = (config) => {
|
|
@@ -6985,8 +7338,8 @@ var assetSegments = (config) => {
|
|
|
6985
7338
|
};
|
|
6986
7339
|
|
|
6987
7340
|
// src/migrate/mintlify/config.ts
|
|
6988
|
-
import { readFile as
|
|
6989
|
-
import { dirname as dirname8, relative as relative7, resolve as
|
|
7341
|
+
import { readFile as readFile11 } from "node:fs/promises";
|
|
7342
|
+
import { dirname as dirname8, relative as relative7, resolve as resolve5 } from "pathe";
|
|
6990
7343
|
var MINTLIFY_DEFAULT_IGNORES = [
|
|
6991
7344
|
"**/_*",
|
|
6992
7345
|
"**/.*",
|
|
@@ -7027,7 +7380,7 @@ var isInsideRoot = (root, candidate) => {
|
|
|
7027
7380
|
};
|
|
7028
7381
|
var readJsonFile = async (file) => {
|
|
7029
7382
|
try {
|
|
7030
|
-
return JSON.parse(await
|
|
7383
|
+
return JSON.parse(await readFile11(file, "utf-8"));
|
|
7031
7384
|
} catch (error) {
|
|
7032
7385
|
throw new BlumeError({
|
|
7033
7386
|
code: "BLUME_MINTLIFY_CONFIG_INVALID",
|
|
@@ -7047,7 +7400,7 @@ var resolveRefs = async (value, options) => {
|
|
|
7047
7400
|
}
|
|
7048
7401
|
const ref = asString(object.$ref);
|
|
7049
7402
|
if (ref) {
|
|
7050
|
-
const refFile =
|
|
7403
|
+
const refFile = resolve5(dirname8(options.file), ref);
|
|
7051
7404
|
if (!isInsideRoot(options.root, refFile)) {
|
|
7052
7405
|
throw new BlumeError({
|
|
7053
7406
|
code: "BLUME_MINTLIFY_REF_OUTSIDE_ROOT",
|
|
@@ -7194,16 +7547,6 @@ var mintlifyBackgroundDecoration = (value) => {
|
|
|
7194
7547
|
}
|
|
7195
7548
|
return;
|
|
7196
7549
|
};
|
|
7197
|
-
var sidebarItemPaths = (items) => items.flatMap((item) => {
|
|
7198
|
-
if (typeof item === "string") {
|
|
7199
|
-
return [tabPathFromRef(item)];
|
|
7200
|
-
}
|
|
7201
|
-
if (item.href) {
|
|
7202
|
-
return [item.href];
|
|
7203
|
-
}
|
|
7204
|
-
const paths = item.root ? [tabPathFromRef(item.root)] : [];
|
|
7205
|
-
return item.items ? [...paths, ...sidebarItemPaths(item.items)] : paths;
|
|
7206
|
-
});
|
|
7207
7550
|
var collapsedFromExpanded = (value) => {
|
|
7208
7551
|
if (value === false) {
|
|
7209
7552
|
return true;
|
|
@@ -7275,72 +7618,19 @@ var selectorItemsFor = (items) => items.flatMap((item) => {
|
|
|
7275
7618
|
const label = labelForNavItem(object);
|
|
7276
7619
|
const path = navItemPath(object);
|
|
7277
7620
|
if (!label || !path) {
|
|
7278
|
-
return [];
|
|
7279
|
-
}
|
|
7280
|
-
return [
|
|
7281
|
-
withoutUndefined({
|
|
7282
|
-
description: asString(object.description),
|
|
7283
|
-
icon: asString(object.icon),
|
|
7284
|
-
label,
|
|
7285
|
-
path,
|
|
7286
|
-
tag: asString(object.tag)
|
|
7287
|
-
})
|
|
7288
|
-
];
|
|
7289
|
-
});
|
|
7290
|
-
var isExternalRoute = (path) => path.startsWith("http://") || path.startsWith("https://") || path.startsWith("mailto:") || path.startsWith("tel:");
|
|
7291
|
-
var hasOwnNavigationContent = (item) => Boolean(asString(item.root)) || childItemsFor(item).length > 0;
|
|
7292
|
-
var mintlifySidebarVariants = async (spec) => {
|
|
7293
|
-
const navigation = asObject(spec.navigation) ?? {};
|
|
7294
|
-
const global = asObject(navigation.global) ?? {};
|
|
7295
|
-
const candidates = [];
|
|
7296
|
-
const addCandidate = (item) => {
|
|
7297
|
-
const path = navItemPath(item);
|
|
7298
|
-
if (!path || isExternalRoute(path)) {
|
|
7299
|
-
return;
|
|
7300
|
-
}
|
|
7301
|
-
candidates.push({ item, path });
|
|
7302
|
-
};
|
|
7303
|
-
for (const item of [
|
|
7304
|
-
...asArray(navigation.tabs),
|
|
7305
|
-
...asArray(navigation.anchors),
|
|
7306
|
-
...asArray(global.anchors)
|
|
7307
|
-
]) {
|
|
7308
|
-
const object = asObject(item);
|
|
7309
|
-
if (!object) {
|
|
7310
|
-
addCandidate(item);
|
|
7311
|
-
continue;
|
|
7312
|
-
}
|
|
7313
|
-
for (const menuItem of asArray(object.menu)) {
|
|
7314
|
-
addCandidate(menuItem);
|
|
7315
|
-
}
|
|
7316
|
-
if (hasOwnNavigationContent(object)) {
|
|
7317
|
-
addCandidate(item);
|
|
7318
|
-
}
|
|
7319
|
-
}
|
|
7320
|
-
for (const item of [
|
|
7321
|
-
...asArray(navigation.dropdowns),
|
|
7322
|
-
...asArray(navigation.products),
|
|
7323
|
-
...asArray(navigation.versions),
|
|
7324
|
-
...asArray(navigation.languages)
|
|
7325
|
-
]) {
|
|
7326
|
-
addCandidate(item);
|
|
7327
|
-
}
|
|
7328
|
-
const resolved = await Promise.all(candidates.map(async (candidate) => {
|
|
7329
|
-
const items = await toSidebarItems([candidate.item], {});
|
|
7330
|
-
if (items.length === 0) {
|
|
7331
|
-
return [];
|
|
7332
|
-
}
|
|
7333
|
-
return [candidate.path, ...sidebarItemPaths(items)].filter((path) => !isExternalRoute(path)).map((path) => ({ items, path }));
|
|
7334
|
-
}));
|
|
7335
|
-
const seen = new Set;
|
|
7336
|
-
return resolved.flat().flatMap((variant) => {
|
|
7337
|
-
if (!variant || seen.has(variant.path)) {
|
|
7338
|
-
return [];
|
|
7339
|
-
}
|
|
7340
|
-
seen.add(variant.path);
|
|
7341
|
-
return [variant];
|
|
7342
|
-
});
|
|
7343
|
-
};
|
|
7621
|
+
return [];
|
|
7622
|
+
}
|
|
7623
|
+
return [
|
|
7624
|
+
withoutUndefined({
|
|
7625
|
+
description: asString(object.description),
|
|
7626
|
+
icon: asString(object.icon),
|
|
7627
|
+
label,
|
|
7628
|
+
path,
|
|
7629
|
+
tag: asString(object.tag)
|
|
7630
|
+
})
|
|
7631
|
+
];
|
|
7632
|
+
});
|
|
7633
|
+
var isExternalRoute = (path) => path.startsWith("http://") || path.startsWith("https://") || path.startsWith("mailto:") || path.startsWith("tel:");
|
|
7344
7634
|
var mintlifyTabs = (spec) => {
|
|
7345
7635
|
const navigation = asObject(spec.navigation) ?? {};
|
|
7346
7636
|
const global = asObject(navigation.global) ?? {};
|
|
@@ -7403,25 +7693,103 @@ var mintlifySelectors = (spec) => {
|
|
|
7403
7693
|
};
|
|
7404
7694
|
var mintignorePatterns = async (root) => {
|
|
7405
7695
|
try {
|
|
7406
|
-
const raw = await
|
|
7696
|
+
const raw = await readFile11(resolve5(root, ".mintignore"), "utf-8");
|
|
7407
7697
|
return raw.split(`
|
|
7408
7698
|
`).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).filter((line) => !line.startsWith("!")).map((line) => line.endsWith("/") ? `${line}**` : line);
|
|
7409
7699
|
} catch {
|
|
7410
7700
|
return [];
|
|
7411
7701
|
}
|
|
7412
7702
|
};
|
|
7413
|
-
var
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7703
|
+
var REDIRECT_PARAM = /:(?<name>[A-Za-z_]\w*)(?<modifier>[*+?])?/gu;
|
|
7704
|
+
var toAstroRedirectPath = (path) => path.replaceAll(REDIRECT_PARAM, (_match, name, modifier) => modifier === "*" || modifier === "+" ? `[...${name}]` : `[${name}]`);
|
|
7705
|
+
var isDynamicRedirectPath = (path) => path.includes("[");
|
|
7706
|
+
var partitionMintlifyRedirects = (spec) => {
|
|
7707
|
+
const kept = [];
|
|
7708
|
+
const dropped = [];
|
|
7709
|
+
for (const redirect of asArray(spec.redirects)) {
|
|
7710
|
+
const object = asObject(redirect);
|
|
7711
|
+
if (!object) {
|
|
7712
|
+
continue;
|
|
7713
|
+
}
|
|
7714
|
+
const source = asString(object.source) ?? asString(object.from);
|
|
7715
|
+
const destination = asString(object.destination) ?? asString(object.to) ?? asString(object.redirect);
|
|
7716
|
+
if (!source || !destination) {
|
|
7717
|
+
continue;
|
|
7718
|
+
}
|
|
7719
|
+
const from = toAstroRedirectPath(source);
|
|
7720
|
+
const to = toAstroRedirectPath(destination);
|
|
7721
|
+
if (isDynamicRedirectPath(from) || isDynamicRedirectPath(to)) {
|
|
7722
|
+
dropped.push(source);
|
|
7723
|
+
} else {
|
|
7724
|
+
kept.push({ from, to });
|
|
7725
|
+
}
|
|
7726
|
+
}
|
|
7727
|
+
return { dropped, kept };
|
|
7728
|
+
};
|
|
7729
|
+
var openapiRouteFromDirectory = (value) => {
|
|
7730
|
+
const directory = normalizeDirectory(asString(value) ?? "");
|
|
7731
|
+
return directory.length > 0 ? `/${directory}` : undefined;
|
|
7732
|
+
};
|
|
7733
|
+
var openapiSourcesFromValue = (value, context) => {
|
|
7734
|
+
if (typeof value === "string") {
|
|
7735
|
+
if (value.length === 0 || API_ENDPOINT_REF.test(value)) {
|
|
7736
|
+
return [];
|
|
7737
|
+
}
|
|
7738
|
+
return [
|
|
7739
|
+
withoutUndefined({
|
|
7740
|
+
label: context.label,
|
|
7741
|
+
route: context.route,
|
|
7742
|
+
spec: value
|
|
7743
|
+
})
|
|
7744
|
+
];
|
|
7417
7745
|
}
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7746
|
+
if (Array.isArray(value)) {
|
|
7747
|
+
return value.flatMap((item) => openapiSourcesFromValue(item, context));
|
|
7748
|
+
}
|
|
7749
|
+
const object = asObject(value);
|
|
7750
|
+
if (!object) {
|
|
7421
7751
|
return [];
|
|
7422
7752
|
}
|
|
7423
|
-
return
|
|
7424
|
-
|
|
7753
|
+
return openapiSourcesFromValue(object.source ?? object.openapi, {
|
|
7754
|
+
label: context.label,
|
|
7755
|
+
route: openapiRouteFromDirectory(object.directory) ?? context.route
|
|
7756
|
+
});
|
|
7757
|
+
};
|
|
7758
|
+
var mintlifyOpenapi = (spec) => {
|
|
7759
|
+
const drafts = [];
|
|
7760
|
+
const visit = (node) => {
|
|
7761
|
+
if (Array.isArray(node)) {
|
|
7762
|
+
for (const item of node) {
|
|
7763
|
+
visit(item);
|
|
7764
|
+
}
|
|
7765
|
+
return;
|
|
7766
|
+
}
|
|
7767
|
+
const object = asObject(node);
|
|
7768
|
+
if (!object) {
|
|
7769
|
+
return;
|
|
7770
|
+
}
|
|
7771
|
+
if (hasOwn(object, "openapi")) {
|
|
7772
|
+
drafts.push(...openapiSourcesFromValue(object.openapi, {
|
|
7773
|
+
label: labelForNavItem(object)
|
|
7774
|
+
}));
|
|
7775
|
+
}
|
|
7776
|
+
for (const children of childNavigationArrays(object)) {
|
|
7777
|
+
visit(children);
|
|
7778
|
+
}
|
|
7779
|
+
};
|
|
7780
|
+
visit(spec.navigation);
|
|
7781
|
+
drafts.push(...openapiSourcesFromValue(spec.openapi, {}));
|
|
7782
|
+
drafts.push(...openapiSourcesFromValue(asObject(spec.api)?.openapi, {}));
|
|
7783
|
+
const seen = new Set;
|
|
7784
|
+
const sources = drafts.flatMap((draft) => {
|
|
7785
|
+
if (seen.has(draft.spec)) {
|
|
7786
|
+
return [];
|
|
7787
|
+
}
|
|
7788
|
+
seen.add(draft.spec);
|
|
7789
|
+
return [draft];
|
|
7790
|
+
});
|
|
7791
|
+
return sources.length > 0 ? { enabled: true, sources } : undefined;
|
|
7792
|
+
};
|
|
7425
7793
|
var mintlifyLogo = (value) => {
|
|
7426
7794
|
if (typeof value === "string") {
|
|
7427
7795
|
return value;
|
|
@@ -7453,6 +7821,12 @@ var mintlifyFavicon = (value) => {
|
|
|
7453
7821
|
}
|
|
7454
7822
|
return withoutUndefined({ dark, light });
|
|
7455
7823
|
};
|
|
7824
|
+
var mintlifyIcons = (value) => {
|
|
7825
|
+
const library = asString(asObject(value)?.library);
|
|
7826
|
+
return {
|
|
7827
|
+
library: library === "lucide" || library === "tabler" ? library : "fontawesome"
|
|
7828
|
+
};
|
|
7829
|
+
};
|
|
7456
7830
|
var mintlifyBanner = (value) => {
|
|
7457
7831
|
const object = asObject(value);
|
|
7458
7832
|
const content = object ? asString(object.content) : undefined;
|
|
@@ -7543,6 +7917,27 @@ var mintlifyMarkdown = (value, styling) => {
|
|
|
7543
7917
|
schema: object?.schema === false ? false : undefined
|
|
7544
7918
|
});
|
|
7545
7919
|
};
|
|
7920
|
+
var FAMILY_TO_SLUG = Object.fromEntries(Object.entries(GOOGLE_FONTS).map(([slug, def]) => [
|
|
7921
|
+
def.family.toLowerCase(),
|
|
7922
|
+
slug
|
|
7923
|
+
]));
|
|
7924
|
+
var fontSlugForFamily = (value) => {
|
|
7925
|
+
const family = asString(value);
|
|
7926
|
+
return family ? FAMILY_TO_SLUG[family.toLowerCase()] : undefined;
|
|
7927
|
+
};
|
|
7928
|
+
var mintlifyFonts = (value) => {
|
|
7929
|
+
const object = asObject(value);
|
|
7930
|
+
if (!object) {
|
|
7931
|
+
return;
|
|
7932
|
+
}
|
|
7933
|
+
const heading = asObject(object.heading);
|
|
7934
|
+
const body = asObject(object.body);
|
|
7935
|
+
const fonts = withoutUndefined({
|
|
7936
|
+
body: fontSlugForFamily(body?.family) ?? fontSlugForFamily(object.family),
|
|
7937
|
+
display: fontSlugForFamily(heading?.family) ?? fontSlugForFamily(object.family)
|
|
7938
|
+
});
|
|
7939
|
+
return Object.keys(fonts).length > 0 ? fonts : undefined;
|
|
7940
|
+
};
|
|
7546
7941
|
var mintlifySeo = (value) => {
|
|
7547
7942
|
const object = asObject(value);
|
|
7548
7943
|
const metatags = asObject(object?.metatags);
|
|
@@ -7554,8 +7949,8 @@ var mintlifySeo = (value) => {
|
|
|
7554
7949
|
};
|
|
7555
7950
|
};
|
|
7556
7951
|
var loadMintlifyConfig = async (root, file) => {
|
|
7557
|
-
const projectRoot =
|
|
7558
|
-
const configFile =
|
|
7952
|
+
const projectRoot = resolve5(root);
|
|
7953
|
+
const configFile = resolve5(file);
|
|
7559
7954
|
const spec = asObject(await resolveRefs(await readJsonFile(configFile), {
|
|
7560
7955
|
file: configFile,
|
|
7561
7956
|
root: projectRoot,
|
|
@@ -7588,16 +7983,17 @@ var loadMintlifyConfig = async (root, file) => {
|
|
|
7588
7983
|
},
|
|
7589
7984
|
description: asString(spec.description),
|
|
7590
7985
|
favicon: mintlifyFavicon(spec.favicon),
|
|
7986
|
+
icons: mintlifyIcons(spec.icons),
|
|
7591
7987
|
logo: mintlifyLogo(spec.logo),
|
|
7592
7988
|
markdown: mintlifyMarkdown(spec.markdown, styling),
|
|
7593
7989
|
navigation: {
|
|
7594
7990
|
chromeVariants: mintlifyChromeVariants(spec),
|
|
7595
7991
|
selectors: mintlifySelectors(spec),
|
|
7596
7992
|
sidebar: await toSidebarItems(mintlifyNavigationItems(navigation), {}),
|
|
7597
|
-
sidebarVariants: await mintlifySidebarVariants(spec),
|
|
7598
7993
|
tabs: mintlifyTabs(spec)
|
|
7599
7994
|
},
|
|
7600
|
-
|
|
7995
|
+
openapi: mintlifyOpenapi(spec),
|
|
7996
|
+
redirects: partitionMintlifyRedirects(spec).kept,
|
|
7601
7997
|
search: {
|
|
7602
7998
|
indexing: {
|
|
7603
7999
|
includeHiddenPages: seo.indexing === "all"
|
|
@@ -7614,6 +8010,7 @@ var loadMintlifyConfig = async (root, file) => {
|
|
|
7614
8010
|
backgroundDecoration: mintlifyBackgroundDecoration(spec.background),
|
|
7615
8011
|
backgroundImage: backgroundImage.light,
|
|
7616
8012
|
backgroundImageDark: backgroundImage.dark,
|
|
8013
|
+
fonts: mintlifyFonts(spec.fonts ?? spec.font),
|
|
7617
8014
|
mode: appearance.default === "light" || appearance.default === "dark" || appearance.default === "system" ? appearance.default : "system",
|
|
7618
8015
|
strict: appearance.strict === true
|
|
7619
8016
|
},
|
|
@@ -7651,12 +8048,12 @@ var mintlifyI18n = (spec) => {
|
|
|
7651
8048
|
// src/core/bridge.ts
|
|
7652
8049
|
var MINTLIFY_CONFIG_FILES = ["docs.json", "mint.json"];
|
|
7653
8050
|
var detectMintlifyBridge = async (root) => {
|
|
7654
|
-
const configFile = MINTLIFY_CONFIG_FILES.map((name) =>
|
|
8051
|
+
const configFile = MINTLIFY_CONFIG_FILES.map((name) => join18(root, name)).find((candidate) => existsSync10(candidate));
|
|
7655
8052
|
if (!configFile) {
|
|
7656
8053
|
return null;
|
|
7657
8054
|
}
|
|
7658
8055
|
const config = await loadMintlifyConfig(root, configFile);
|
|
7659
|
-
const spec = JSON.parse(await
|
|
8056
|
+
const spec = JSON.parse(await readFile12(configFile, "utf-8"));
|
|
7660
8057
|
const i18n = mintlifyI18n(spec);
|
|
7661
8058
|
if (i18n) {
|
|
7662
8059
|
config.i18n = i18n;
|
|
@@ -7667,7 +8064,7 @@ var detectMintlifyBridge = async (root) => {
|
|
|
7667
8064
|
const variables = config.variables ?? {};
|
|
7668
8065
|
const root_ = config.content?.root ?? ".";
|
|
7669
8066
|
const exclude = config.content?.exclude ?? [];
|
|
7670
|
-
const assets = assetSegments(config).filter((segment) => segment !== "public" &&
|
|
8067
|
+
const assets = assetSegments(config).filter((segment) => segment !== "public" && existsSync10(join18(root, segment)));
|
|
7671
8068
|
return {
|
|
7672
8069
|
configFile,
|
|
7673
8070
|
raw: {
|
|
@@ -7741,42 +8138,6 @@ var createModuleLoader = () => {
|
|
|
7741
8138
|
};
|
|
7742
8139
|
};
|
|
7743
8140
|
|
|
7744
|
-
// src/core/project.ts
|
|
7745
|
-
import { existsSync as existsSync9 } from "node:fs";
|
|
7746
|
-
import { isAbsolute as isAbsolute4, join as join15, resolve as resolve5 } from "pathe";
|
|
7747
|
-
var CONFIG_FILENAMES = [
|
|
7748
|
-
"blume.config.ts",
|
|
7749
|
-
"blume.config.mjs",
|
|
7750
|
-
"blume.config.js"
|
|
7751
|
-
];
|
|
7752
|
-
var THEME_FILENAMES = ["theme.css"];
|
|
7753
|
-
var COMPONENTS_FILENAMES = ["components.tsx", "components.ts"];
|
|
7754
|
-
var firstExisting = (root, names) => {
|
|
7755
|
-
for (const name of names) {
|
|
7756
|
-
const candidate = join15(root, name);
|
|
7757
|
-
if (existsSync9(candidate)) {
|
|
7758
|
-
return candidate;
|
|
7759
|
-
}
|
|
7760
|
-
}
|
|
7761
|
-
return null;
|
|
7762
|
-
};
|
|
7763
|
-
var findConfigFile = (root) => firstExisting(root, CONFIG_FILENAMES);
|
|
7764
|
-
var resolveProjectContext = (root, config) => {
|
|
7765
|
-
const absoluteRoot = resolve5(root);
|
|
7766
|
-
const contentRoot = isAbsolute4(config.content.root) ? config.content.root : join15(absoluteRoot, config.content.root);
|
|
7767
|
-
const pagesPath = join15(absoluteRoot, config.content.pages);
|
|
7768
|
-
const pagesRoot = existsSync9(pagesPath) ? pagesPath : null;
|
|
7769
|
-
return {
|
|
7770
|
-
componentsFile: firstExisting(absoluteRoot, COMPONENTS_FILENAMES),
|
|
7771
|
-
configFile: findConfigFile(absoluteRoot),
|
|
7772
|
-
contentRoot,
|
|
7773
|
-
outDir: join15(absoluteRoot, ".blume"),
|
|
7774
|
-
pagesRoot,
|
|
7775
|
-
root: absoluteRoot,
|
|
7776
|
-
themeFile: firstExisting(absoluteRoot, THEME_FILENAMES)
|
|
7777
|
-
};
|
|
7778
|
-
};
|
|
7779
|
-
|
|
7780
8141
|
// src/core/schema.ts
|
|
7781
8142
|
import { z as z2 } from "zod";
|
|
7782
8143
|
var iconName = z2.string().min(1);
|
|
@@ -7806,7 +8167,17 @@ var changelogMetaSchema = z2.object({
|
|
|
7806
8167
|
date: dateSchema.optional(),
|
|
7807
8168
|
version: z2.string().optional()
|
|
7808
8169
|
}).strict();
|
|
8170
|
+
var authorSchema = z2.union([
|
|
8171
|
+
z2.string(),
|
|
8172
|
+
z2.object({
|
|
8173
|
+
avatar: z2.string().optional(),
|
|
8174
|
+
image: z2.string().optional(),
|
|
8175
|
+
name: z2.string(),
|
|
8176
|
+
url: z2.string().optional()
|
|
8177
|
+
}).passthrough()
|
|
8178
|
+
]);
|
|
7809
8179
|
var pageMetaBaseSchema = z2.object({
|
|
8180
|
+
authors: z2.union([authorSchema, z2.array(authorSchema)]).optional(),
|
|
7810
8181
|
changelog: changelogMetaSchema.optional(),
|
|
7811
8182
|
date: dateSchema.optional(),
|
|
7812
8183
|
deprecated: z2.boolean().default(false),
|
|
@@ -8007,10 +8378,6 @@ var sidebarItemSchema = z2.lazy(() => z2.union([
|
|
|
8007
8378
|
root: z2.string().optional()
|
|
8008
8379
|
}).strict()
|
|
8009
8380
|
]));
|
|
8010
|
-
var sidebarVariantSchema = z2.object({
|
|
8011
|
-
items: z2.array(sidebarItemSchema).default([]),
|
|
8012
|
-
path: z2.string()
|
|
8013
|
-
}).strict();
|
|
8014
8381
|
var variablesConfigSchema = z2.record(z2.string().regex(/^[A-Za-z0-9-]+$/u), z2.string()).default({});
|
|
8015
8382
|
var fontSlug = z2.string().refine(isFontSlug, (value) => ({
|
|
8016
8383
|
message: `Unknown font "${value}". Supported fonts: ${FONT_SLUGS.join(", ")}.`
|
|
@@ -8124,7 +8491,6 @@ var navigationConfigSchema = z2.object({
|
|
|
8124
8491
|
repo: z2.boolean().default(true),
|
|
8125
8492
|
selectors: z2.array(navSelectorSchema).default([]),
|
|
8126
8493
|
sidebar: z2.array(sidebarItemSchema).optional(),
|
|
8127
|
-
sidebarVariants: z2.array(sidebarVariantSchema).default([]),
|
|
8128
8494
|
tabs: z2.array(navTabSchema).optional()
|
|
8129
8495
|
}).strict();
|
|
8130
8496
|
var exportConfigSchema = z2.union([
|
|
@@ -8247,7 +8613,10 @@ var openapiSourceSchema = z2.object({
|
|
|
8247
8613
|
spec: z2.string()
|
|
8248
8614
|
}).strict();
|
|
8249
8615
|
var openapiConfigSchema = z2.object({
|
|
8616
|
+
codeSamples: z2.array(z2.string()).default(["curl", "js", "python"]),
|
|
8250
8617
|
enabled: z2.boolean().default(false),
|
|
8618
|
+
expandSchemas: z2.boolean().default(false),
|
|
8619
|
+
renderer: z2.enum(["blume", "scalar"]).default("blume"),
|
|
8251
8620
|
route: z2.string().default("/reference"),
|
|
8252
8621
|
sources: z2.array(openapiSourceSchema).default([]),
|
|
8253
8622
|
spec: z2.string().optional(),
|
|
@@ -8276,6 +8645,9 @@ var tocConfigSchema = z2.union([
|
|
|
8276
8645
|
minLevel: value.minHeadingLevel ?? 2
|
|
8277
8646
|
};
|
|
8278
8647
|
});
|
|
8648
|
+
var iconsConfigSchema = z2.object({
|
|
8649
|
+
library: z2.enum(["lucide", "fontawesome", "tabler"]).default("lucide")
|
|
8650
|
+
}).strict();
|
|
8279
8651
|
var blumeConfigSchema = z2.object({
|
|
8280
8652
|
ai: aiConfigSchema.default({}),
|
|
8281
8653
|
analytics: analyticsConfigSchema.optional(),
|
|
@@ -8290,6 +8662,7 @@ var blumeConfigSchema = z2.object({
|
|
|
8290
8662
|
feedback: z2.boolean().default(true),
|
|
8291
8663
|
github: githubConfigSchema.optional(),
|
|
8292
8664
|
i18n: i18nConfigSchema.optional(),
|
|
8665
|
+
icons: iconsConfigSchema.default({}),
|
|
8293
8666
|
lastModified: lastModifiedConfigSchema.default(false),
|
|
8294
8667
|
logo: logoConfigSchema.optional(),
|
|
8295
8668
|
markdown: markdownConfigSchema.default({}),
|
|
@@ -8331,7 +8704,7 @@ var loadConfig = async (root, options = {}) => {
|
|
|
8331
8704
|
const sourceFile = bridge?.configFile ?? configFile;
|
|
8332
8705
|
const parsed = blumeConfigSchema.safeParse(raw ?? {});
|
|
8333
8706
|
if (!parsed.success) {
|
|
8334
|
-
const source = sourceFile &&
|
|
8707
|
+
const source = sourceFile && existsSync11(sourceFile) ? readFileSync7(sourceFile, "utf-8") : undefined;
|
|
8335
8708
|
const diagnostics = diagnosticsFromZod(parsed.error, {
|
|
8336
8709
|
code: "BLUME_CONFIG_INVALID",
|
|
8337
8710
|
file: sourceFile ?? undefined,
|
|
@@ -8584,16 +8957,11 @@ var buildNavigation = (pages, options) => {
|
|
|
8584
8957
|
options.refByLogical ? page.translationKey : page.route,
|
|
8585
8958
|
page
|
|
8586
8959
|
]));
|
|
8587
|
-
const sidebarVariants = (options.sidebarVariants ?? []).map((variant) => ({
|
|
8588
|
-
path: variant.path,
|
|
8589
|
-
sidebar: buildConfigSidebar(variant.items, byRoute)
|
|
8590
|
-
}));
|
|
8591
8960
|
if (options.sidebar) {
|
|
8592
8961
|
return {
|
|
8593
8962
|
chromeVariants,
|
|
8594
8963
|
selectors,
|
|
8595
8964
|
sidebar: buildConfigSidebar(options.sidebar, byRoute),
|
|
8596
|
-
sidebarVariants,
|
|
8597
8965
|
tabs
|
|
8598
8966
|
};
|
|
8599
8967
|
}
|
|
@@ -8601,7 +8969,6 @@ var buildNavigation = (pages, options) => {
|
|
|
8601
8969
|
chromeVariants,
|
|
8602
8970
|
selectors,
|
|
8603
8971
|
sidebar: buildFileSystemSidebar(pages, options.folderMeta, sharedFolderMeta, metaPrefix),
|
|
8604
|
-
sidebarVariants,
|
|
8605
8972
|
tabs
|
|
8606
8973
|
};
|
|
8607
8974
|
};
|
|
@@ -8666,7 +9033,6 @@ var buildContentGraph = (pages, options) => {
|
|
|
8666
9033
|
selectors: options.navigation.selectors,
|
|
8667
9034
|
sharedFolderMeta: options.sharedFolderMeta,
|
|
8668
9035
|
sidebar: options.navigation.sidebar,
|
|
8669
|
-
sidebarVariants: options.navigation.sidebarVariants,
|
|
8670
9036
|
tabs
|
|
8671
9037
|
});
|
|
8672
9038
|
}
|
|
@@ -8674,7 +9040,6 @@ var buildContentGraph = (pages, options) => {
|
|
|
8674
9040
|
chromeVariants: [],
|
|
8675
9041
|
selectors: [],
|
|
8676
9042
|
sidebar: [],
|
|
8677
|
-
sidebarVariants: [],
|
|
8678
9043
|
tabs: []
|
|
8679
9044
|
};
|
|
8680
9045
|
} else {
|
|
@@ -8684,7 +9049,6 @@ var buildContentGraph = (pages, options) => {
|
|
|
8684
9049
|
selectors: options.navigation.selectors,
|
|
8685
9050
|
sharedFolderMeta: options.sharedFolderMeta,
|
|
8686
9051
|
sidebar: options.navigation.sidebar,
|
|
8687
|
-
sidebarVariants: options.navigation.sidebarVariants,
|
|
8688
9052
|
tabs: options.navigation.tabs
|
|
8689
9053
|
});
|
|
8690
9054
|
}
|
|
@@ -8808,7 +9172,7 @@ var discoverFolderMeta = async (contentRoot) => {
|
|
|
8808
9172
|
};
|
|
8809
9173
|
|
|
8810
9174
|
// src/core/sources/normalize.ts
|
|
8811
|
-
import { existsSync as
|
|
9175
|
+
import { existsSync as existsSync12, readFileSync as readFileSync8 } from "node:fs";
|
|
8812
9176
|
import GithubSlugger from "github-slugger";
|
|
8813
9177
|
import { extname as extname4 } from "pathe";
|
|
8814
9178
|
var NUMERIC_PREFIX2 = /^\d+[-_.]/u;
|
|
@@ -8816,7 +9180,7 @@ var GROUP_FOLDER2 = /^\((?<label>.+)\)$/u;
|
|
|
8816
9180
|
var WORD_SPLIT2 = /[-_]/u;
|
|
8817
9181
|
var stripNumericPrefix = (segment) => segment.replace(NUMERIC_PREFIX2, "");
|
|
8818
9182
|
var groupLabel = (segment) => segment.match(GROUP_FOLDER2)?.groups?.label ?? null;
|
|
8819
|
-
var
|
|
9183
|
+
var slugify3 = (text) => text.toLowerCase().trim().replaceAll(/[^\w\s-]/gu, "").replaceAll(/[\s_]+/gu, "-").replaceAll(/-+/gu, "-").replaceAll(/^-|-$/gu, "");
|
|
8820
9184
|
var titleCase = (value) => value.split(WORD_SPLIT2).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
8821
9185
|
var mapRoute = (relativePath) => {
|
|
8822
9186
|
const withoutExt = relativePath.slice(0, relativePath.length - extname4(relativePath).length);
|
|
@@ -8934,7 +9298,7 @@ var normalizeEntry2 = (entry, ctx) => {
|
|
|
8934
9298
|
const ext = format === "mdx" ? ".mdx" : ".md";
|
|
8935
9299
|
const result = pageMetaSchema.safeParse(entry.data);
|
|
8936
9300
|
if (!result.success) {
|
|
8937
|
-
const source = entry.raw ?? (entry.sourcePath &&
|
|
9301
|
+
const source = entry.raw ?? (entry.sourcePath && existsSync12(entry.sourcePath) ? readFileSync8(entry.sourcePath, "utf-8") : undefined);
|
|
8938
9302
|
return {
|
|
8939
9303
|
diagnostics: diagnosticsFromZod(result.error, {
|
|
8940
9304
|
code: "BLUME_FRONTMATTER_INVALID",
|
|
@@ -8983,15 +9347,15 @@ var normalizeEntry2 = (entry, ctx) => {
|
|
|
8983
9347
|
};
|
|
8984
9348
|
|
|
8985
9349
|
// src/core/sources/resolve.ts
|
|
8986
|
-
import { join as
|
|
9350
|
+
import { join as join26 } from "pathe";
|
|
8987
9351
|
|
|
8988
9352
|
// src/core/sources/filesystem.ts
|
|
8989
|
-
import { existsSync as
|
|
8990
|
-
import { readFile as
|
|
8991
|
-
import { extname as extname5, isAbsolute as
|
|
9353
|
+
import { existsSync as existsSync13, watch as fsWatch } from "node:fs";
|
|
9354
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
9355
|
+
import { extname as extname5, isAbsolute as isAbsolute6, join as join19, relative as relative10, resolve as resolve6 } from "pathe";
|
|
8992
9356
|
import { glob as glob6 } from "tinyglobby";
|
|
8993
9357
|
var filesystemSource = (options) => {
|
|
8994
|
-
const contentRoot =
|
|
9358
|
+
const contentRoot = isAbsolute6(options.root) ? options.root : join19(resolve6(options.projectRoot), options.root);
|
|
8995
9359
|
const load2 = async () => {
|
|
8996
9360
|
const files = await glob6(options.include, {
|
|
8997
9361
|
absolute: true,
|
|
@@ -9001,7 +9365,7 @@ var filesystemSource = (options) => {
|
|
|
9001
9365
|
});
|
|
9002
9366
|
files.sort();
|
|
9003
9367
|
const entries = await Promise.all(files.map(async (file) => {
|
|
9004
|
-
const source = await
|
|
9368
|
+
const source = await readFile13(file, "utf-8");
|
|
9005
9369
|
const ext = extname5(file).toLowerCase();
|
|
9006
9370
|
const format = ext === ".mdx" ? "mdx" : "md";
|
|
9007
9371
|
const parsed = frontmatter_default(source);
|
|
@@ -9015,7 +9379,7 @@ var filesystemSource = (options) => {
|
|
|
9015
9379
|
return { diagnostics: [], entries };
|
|
9016
9380
|
};
|
|
9017
9381
|
const validate = () => {
|
|
9018
|
-
if (!
|
|
9382
|
+
if (!existsSync13(contentRoot)) {
|
|
9019
9383
|
throw new BlumeError({
|
|
9020
9384
|
code: options.missingCode ?? "BLUME_CONTENT_ROOT_MISSING",
|
|
9021
9385
|
file: contentRoot,
|
|
@@ -9026,7 +9390,7 @@ var filesystemSource = (options) => {
|
|
|
9026
9390
|
}
|
|
9027
9391
|
};
|
|
9028
9392
|
const watch = (onChange) => {
|
|
9029
|
-
if (!
|
|
9393
|
+
if (!existsSync13(contentRoot)) {
|
|
9030
9394
|
return () => {};
|
|
9031
9395
|
}
|
|
9032
9396
|
const watcher = fsWatch(contentRoot, { recursive: true }, onChange);
|
|
@@ -9037,97 +9401,21 @@ var filesystemSource = (options) => {
|
|
|
9037
9401
|
load: load2,
|
|
9038
9402
|
name: options.name,
|
|
9039
9403
|
prefix: options.prefix,
|
|
9040
|
-
read: (ref) =>
|
|
9404
|
+
read: (ref) => readFile13(join19(contentRoot, ref), "utf-8"),
|
|
9041
9405
|
staged: false,
|
|
9042
9406
|
validate,
|
|
9043
9407
|
watch
|
|
9044
9408
|
};
|
|
9045
9409
|
};
|
|
9046
9410
|
|
|
9047
|
-
// src/core/sources/cache.ts
|
|
9048
|
-
import { mkdir as mkdir3, readFile as readFile11, writeFile as writeFile3 } from "node:fs/promises";
|
|
9049
|
-
import { join as join17 } from "pathe";
|
|
9050
|
-
var hashText = (text) => {
|
|
9051
|
-
let hash = 5381;
|
|
9052
|
-
for (let i = 0;i < text.length; i += 1) {
|
|
9053
|
-
hash = (hash * 33 + (text.codePointAt(i) ?? 0)) % 2147483647;
|
|
9054
|
-
}
|
|
9055
|
-
return hash.toString(36);
|
|
9056
|
-
};
|
|
9057
|
-
var entriesDigest = (entries) => hashText(entries.map((entry) => `${entry.ref}:${entry.hash ?? hashText(entry.body.text)}`).join("|"));
|
|
9058
|
-
var pollingWatch = (load2, intervalSeconds) => (onChange) => {
|
|
9059
|
-
let last = "";
|
|
9060
|
-
const tick = async () => {
|
|
9061
|
-
try {
|
|
9062
|
-
const { entries } = await load2();
|
|
9063
|
-
const next = entriesDigest(entries);
|
|
9064
|
-
if (last && next !== last) {
|
|
9065
|
-
onChange();
|
|
9066
|
-
}
|
|
9067
|
-
last = next;
|
|
9068
|
-
} catch {}
|
|
9069
|
-
};
|
|
9070
|
-
const timer = setInterval(() => {
|
|
9071
|
-
tick();
|
|
9072
|
-
}, intervalSeconds * 1000);
|
|
9073
|
-
return () => clearInterval(timer);
|
|
9074
|
-
};
|
|
9075
|
-
var snapshotCache = (cacheDir) => {
|
|
9076
|
-
const file = join17(cacheDir, "entries.json");
|
|
9077
|
-
return {
|
|
9078
|
-
read: async () => {
|
|
9079
|
-
try {
|
|
9080
|
-
return JSON.parse(await readFile11(file, "utf-8"));
|
|
9081
|
-
} catch {
|
|
9082
|
-
return [];
|
|
9083
|
-
}
|
|
9084
|
-
},
|
|
9085
|
-
write: async (entries) => {
|
|
9086
|
-
try {
|
|
9087
|
-
await mkdir3(cacheDir, { recursive: true });
|
|
9088
|
-
await writeFile3(file, `${JSON.stringify(entries)}
|
|
9089
|
-
`, "utf-8");
|
|
9090
|
-
} catch {}
|
|
9091
|
-
}
|
|
9092
|
-
};
|
|
9093
|
-
};
|
|
9094
|
-
var loadWithCache = async (name, cache, fetchEntries, refresh = true) => {
|
|
9095
|
-
if (!refresh) {
|
|
9096
|
-
const cached3 = await cache.read();
|
|
9097
|
-
if (cached3.length > 0) {
|
|
9098
|
-
return { diagnostics: [], entries: cached3 };
|
|
9099
|
-
}
|
|
9100
|
-
}
|
|
9101
|
-
try {
|
|
9102
|
-
const entries = await fetchEntries();
|
|
9103
|
-
await cache.write(entries);
|
|
9104
|
-
return { diagnostics: [], entries };
|
|
9105
|
-
} catch (error) {
|
|
9106
|
-
const fallback = await cache.read();
|
|
9107
|
-
if (fallback.length > 0) {
|
|
9108
|
-
const diagnostic = {
|
|
9109
|
-
code: "BLUME_SOURCE_OFFLINE",
|
|
9110
|
-
message: `Source "${name}" could not be fetched (${error.message}); served ${fallback.length} cached entries.`,
|
|
9111
|
-
severity: "warning"
|
|
9112
|
-
};
|
|
9113
|
-
return { diagnostics: [diagnostic], entries: fallback };
|
|
9114
|
-
}
|
|
9115
|
-
throw new BlumeError({
|
|
9116
|
-
code: "BLUME_SOURCE_FETCH_FAILED",
|
|
9117
|
-
message: `Source "${name}" failed to load and no cache is available: ${error.message}`,
|
|
9118
|
-
severity: "error"
|
|
9119
|
-
});
|
|
9120
|
-
}
|
|
9121
|
-
};
|
|
9122
|
-
|
|
9123
9411
|
// src/core/sources/github-releases.ts
|
|
9124
9412
|
var DEFAULT_BASE_URL = "https://api.github.com";
|
|
9125
9413
|
var DEFAULT_LIMIT = 100;
|
|
9126
9414
|
var PER_PAGE = 100;
|
|
9127
9415
|
var LEADING_V = /^v/iu;
|
|
9128
|
-
var
|
|
9416
|
+
var NON_SLUG3 = /[^a-z0-9]+/gu;
|
|
9129
9417
|
var EDGE_DASHES = /^-+|-+$/gu;
|
|
9130
|
-
var slugifyTag = (tag) => tag.toLowerCase().replaceAll(
|
|
9418
|
+
var slugifyTag = (tag) => tag.toLowerCase().replaceAll(NON_SLUG3, "-").replaceAll(EDGE_DASHES, "");
|
|
9131
9419
|
var githubHeaders = () => {
|
|
9132
9420
|
const headers = new Headers({ Accept: "application/vnd.github+json" });
|
|
9133
9421
|
const token = process.env.GITHUB_TOKEN;
|
|
@@ -9390,25 +9678,25 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
9390
9678
|
};
|
|
9391
9679
|
|
|
9392
9680
|
// src/core/sources/mintlify.ts
|
|
9393
|
-
import { existsSync as
|
|
9394
|
-
import { readFile as
|
|
9395
|
-
import { isAbsolute as
|
|
9681
|
+
import { existsSync as existsSync15, watch as fsWatch2 } from "node:fs";
|
|
9682
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
9683
|
+
import { isAbsolute as isAbsolute8, join as join22, relative as relative14, resolve as resolve8 } from "pathe";
|
|
9396
9684
|
import { glob as glob7 } from "tinyglobby";
|
|
9397
9685
|
|
|
9398
9686
|
// src/migrate/shared.ts
|
|
9399
|
-
import { existsSync as
|
|
9400
|
-
import { readFile as
|
|
9401
|
-
import { isAbsolute as
|
|
9687
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
9688
|
+
import { readFile as readFile14, writeFile as writeFile5 } from "node:fs/promises";
|
|
9689
|
+
import { isAbsolute as isAbsolute7, join as join20, relative as relative11 } from "pathe";
|
|
9402
9690
|
var isInsideRoot2 = (root, candidate) => {
|
|
9403
9691
|
const rel = relative11(root, candidate);
|
|
9404
|
-
return rel === "" || !rel.startsWith("..") && !
|
|
9692
|
+
return rel === "" || !rel.startsWith("..") && !isAbsolute7(rel);
|
|
9405
9693
|
};
|
|
9406
9694
|
var writeBlumeConfig = async (root, config) => {
|
|
9407
9695
|
const body = `import { defineConfig } from "blume";
|
|
9408
9696
|
|
|
9409
9697
|
export default defineConfig(${JSON.stringify(config, null, 2)});
|
|
9410
9698
|
`;
|
|
9411
|
-
await
|
|
9699
|
+
await writeFile5(join20(root, "blume.config.ts"), body, "utf-8");
|
|
9412
9700
|
};
|
|
9413
9701
|
var BLUME_SCRIPTS = {
|
|
9414
9702
|
build: "blume build",
|
|
@@ -9416,13 +9704,13 @@ var BLUME_SCRIPTS = {
|
|
|
9416
9704
|
start: "blume preview"
|
|
9417
9705
|
};
|
|
9418
9706
|
var rewriteFrameworkScripts = async (root, cli, remove) => {
|
|
9419
|
-
const pkgPath =
|
|
9420
|
-
if (!
|
|
9707
|
+
const pkgPath = join20(root, "package.json");
|
|
9708
|
+
if (!existsSync14(pkgPath)) {
|
|
9421
9709
|
return false;
|
|
9422
9710
|
}
|
|
9423
9711
|
let pkg;
|
|
9424
9712
|
try {
|
|
9425
|
-
pkg = JSON.parse(await
|
|
9713
|
+
pkg = JSON.parse(await readFile14(pkgPath, "utf-8"));
|
|
9426
9714
|
} catch {
|
|
9427
9715
|
return false;
|
|
9428
9716
|
}
|
|
@@ -9445,12 +9733,12 @@ var rewriteFrameworkScripts = async (root, cli, remove) => {
|
|
|
9445
9733
|
}
|
|
9446
9734
|
if (changed) {
|
|
9447
9735
|
pkg.scripts = next;
|
|
9448
|
-
await
|
|
9736
|
+
await writeFile5(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
9449
9737
|
`, "utf-8");
|
|
9450
9738
|
}
|
|
9451
9739
|
return changed;
|
|
9452
9740
|
};
|
|
9453
|
-
var leftoverFiles = (root, candidates) => candidates.filter((candidate) =>
|
|
9741
|
+
var leftoverFiles = (root, candidates) => candidates.filter((candidate) => existsSync14(join20(root, candidate)));
|
|
9454
9742
|
var attribute = (attrs, name) => {
|
|
9455
9743
|
const match = attrs.match(new RegExp(`\\b${name}=(?:"(?<dq>[^"]*)"|'(?<sq>[^']*)')`, "u"));
|
|
9456
9744
|
return match?.groups?.dq ?? match?.groups?.sq;
|
|
@@ -9847,7 +10135,7 @@ var isLiteralObject = (value) => typeof value === "object" && value !== null &&
|
|
|
9847
10135
|
var asLiteralArray = (value) => Array.isArray(value) ? value : undefined;
|
|
9848
10136
|
|
|
9849
10137
|
// src/migrate/mintlify/content.ts
|
|
9850
|
-
import { dirname as dirname10, join as
|
|
10138
|
+
import { dirname as dirname10, join as join21, relative as relative12 } from "pathe";
|
|
9851
10139
|
var CALLOUT_DIRECTIVES = {
|
|
9852
10140
|
Check: "success",
|
|
9853
10141
|
Danger: "danger",
|
|
@@ -9876,6 +10164,7 @@ var rewriteMintlifyCallouts = (source) => rewriteCallouts(source, {
|
|
|
9876
10164
|
typeDirectives: CALLOUT_TYPE_DIRECTIVES
|
|
9877
10165
|
});
|
|
9878
10166
|
var rewriteMintlifyExampleBlocks = (source) => source.replaceAll(/<(?<close>\/?)(?:Request|Response)Example\b/gu, "<$<close>CodeGroup");
|
|
10167
|
+
var rewriteMintlifyAccordions = (source) => source.replaceAll(/<(?<close>\/?)Accordion(?<group>Group)?\b/gu, (_match, close, group) => group ? `<${close}Accordion` : `<${close}AccordionItem`);
|
|
9879
10168
|
var SNIPPET_IMPORT = /^import\s+[\s\S]*?\s+from\s+["'](?<source>\/snippets\/[^"']+)["'];?[ \t]*\n?/gmu;
|
|
9880
10169
|
var rewriteSnippetImports = (source, options) => {
|
|
9881
10170
|
const components = [];
|
|
@@ -9883,7 +10172,7 @@ var rewriteSnippetImports = (source, options) => {
|
|
|
9883
10172
|
if (/\.mdx?$/u.test(importSource)) {
|
|
9884
10173
|
return "";
|
|
9885
10174
|
}
|
|
9886
|
-
const target =
|
|
10175
|
+
const target = join21(options.root, importSource.replace(/^\/+/u, ""));
|
|
9887
10176
|
components.push(importSource.replace(/^\/+/u, ""));
|
|
9888
10177
|
let rel = relative12(dirname10(options.filePath), target);
|
|
9889
10178
|
if (!rel.startsWith(".")) {
|
|
@@ -9893,7 +10182,7 @@ var rewriteSnippetImports = (source, options) => {
|
|
|
9893
10182
|
});
|
|
9894
10183
|
return { components, source: next };
|
|
9895
10184
|
};
|
|
9896
|
-
var UNSUPPORTED_COMPONENTS = ["
|
|
10185
|
+
var UNSUPPORTED_COMPONENTS = ["Update"];
|
|
9897
10186
|
var unsupportedMintlifyComponents = (source) => UNSUPPORTED_COMPONENTS.filter((name) => new RegExp(`<${name}\\b`, "u").test(source));
|
|
9898
10187
|
|
|
9899
10188
|
// src/migrate/mintlify/frontmatter.ts
|
|
@@ -10164,9 +10453,9 @@ var rewriteMintlifyMarkdownSnippets = async (source, options) => {
|
|
|
10164
10453
|
throw new Error(snippetCycleMessage(options.root, file, options.trail ?? []));
|
|
10165
10454
|
}
|
|
10166
10455
|
seen.add(file);
|
|
10167
|
-
const
|
|
10456
|
+
const readFile15 = options.readFile ?? readFileFromDisk;
|
|
10168
10457
|
try {
|
|
10169
|
-
const raw = await
|
|
10458
|
+
const raw = await readFile15(file);
|
|
10170
10459
|
const content = frontmatter_default(raw).content.trim();
|
|
10171
10460
|
const transformed = await rewriteMintlifyMarkdownSnippets(content, {
|
|
10172
10461
|
...options,
|
|
@@ -10207,7 +10496,7 @@ var rewriteMintlifyMarkdownSnippets = async (source, options) => {
|
|
|
10207
10496
|
return await inlineAt(0, source);
|
|
10208
10497
|
};
|
|
10209
10498
|
var rewriteMintlifySnippetVariables = async (source, options) => {
|
|
10210
|
-
const
|
|
10499
|
+
const readFile15 = options.readFile ?? readFileFromDisk;
|
|
10211
10500
|
const inlineImport = async (current, variableImport) => {
|
|
10212
10501
|
const file = resolveSnippetPath({
|
|
10213
10502
|
filePath: options.filePath,
|
|
@@ -10217,7 +10506,7 @@ var rewriteMintlifySnippetVariables = async (source, options) => {
|
|
|
10217
10506
|
if (!file) {
|
|
10218
10507
|
return current;
|
|
10219
10508
|
}
|
|
10220
|
-
const exports = collectStringExports(frontmatter_default(await
|
|
10509
|
+
const exports = collectStringExports(frontmatter_default(await readFile15(file)).content);
|
|
10221
10510
|
let next = current;
|
|
10222
10511
|
for (const name of variableImport.names) {
|
|
10223
10512
|
const value = exports.get(name.imported);
|
|
@@ -10271,6 +10560,7 @@ var transformMintlifyContent = async (raw, options) => {
|
|
|
10271
10560
|
text = snippetImports.source;
|
|
10272
10561
|
text = rewriteMintlifySvgIconProps(text);
|
|
10273
10562
|
text = rewriteMintlifyExampleBlocks(text);
|
|
10563
|
+
text = rewriteMintlifyAccordions(text);
|
|
10274
10564
|
text = rewriteMintlifyCallouts(text);
|
|
10275
10565
|
const unsupported = unsupportedMintlifyComponents(text);
|
|
10276
10566
|
const parsed = frontmatter_default(text);
|
|
@@ -10295,7 +10585,7 @@ var MINTLIFY_SOURCE_IGNORES = [
|
|
|
10295
10585
|
"snippets/**"
|
|
10296
10586
|
];
|
|
10297
10587
|
var mintlifySource = (options) => {
|
|
10298
|
-
const contentRoot =
|
|
10588
|
+
const contentRoot = isAbsolute8(options.root) ? options.root : join22(resolve8(options.projectRoot), options.root);
|
|
10299
10589
|
const ignore = [...new Set([...options.exclude, ...MINTLIFY_SOURCE_IGNORES])];
|
|
10300
10590
|
const transform = (raw, file) => transformMintlifyContent(raw, {
|
|
10301
10591
|
filePath: file,
|
|
@@ -10312,7 +10602,7 @@ var mintlifySource = (options) => {
|
|
|
10312
10602
|
files.sort();
|
|
10313
10603
|
const unsupported = new Set;
|
|
10314
10604
|
const entries = await Promise.all(files.map(async (file) => {
|
|
10315
|
-
const result = await transform(await
|
|
10605
|
+
const result = await transform(await readFile15(file, "utf-8"), file);
|
|
10316
10606
|
for (const name of result.unsupported) {
|
|
10317
10607
|
unsupported.add(name);
|
|
10318
10608
|
}
|
|
@@ -10328,14 +10618,14 @@ var mintlifySource = (options) => {
|
|
|
10328
10618
|
const diagnostics = unsupported.size > 0 ? [
|
|
10329
10619
|
{
|
|
10330
10620
|
code: "BLUME_MINTLIFY_UNSUPPORTED",
|
|
10331
|
-
message: `Mintlify components without a Blume equivalent were left as-is: ${[...unsupported].toSorted().join(", ")}.
|
|
10621
|
+
message: `Mintlify components without a Blume equivalent were left as-is: ${[...unsupported].toSorted().join(", ")}. Replace them by hand or provide a matching component.`,
|
|
10332
10622
|
severity: "warning"
|
|
10333
10623
|
}
|
|
10334
10624
|
] : [];
|
|
10335
10625
|
return { diagnostics, entries };
|
|
10336
10626
|
};
|
|
10337
10627
|
const validate = () => {
|
|
10338
|
-
if (!
|
|
10628
|
+
if (!existsSync15(contentRoot)) {
|
|
10339
10629
|
throw new BlumeError({
|
|
10340
10630
|
code: "BLUME_CONTENT_ROOT_MISSING",
|
|
10341
10631
|
file: contentRoot,
|
|
@@ -10347,11 +10637,11 @@ var mintlifySource = (options) => {
|
|
|
10347
10637
|
};
|
|
10348
10638
|
const watch = (onChange) => {
|
|
10349
10639
|
const disposers = [];
|
|
10350
|
-
if (
|
|
10640
|
+
if (existsSync15(contentRoot)) {
|
|
10351
10641
|
const watcher = fsWatch2(contentRoot, { recursive: true }, onChange);
|
|
10352
10642
|
disposers.push(() => watcher.close());
|
|
10353
10643
|
}
|
|
10354
|
-
if (options.configFile &&
|
|
10644
|
+
if (options.configFile && existsSync15(options.configFile)) {
|
|
10355
10645
|
const watcher = fsWatch2(options.configFile, onChange);
|
|
10356
10646
|
disposers.push(() => watcher.close());
|
|
10357
10647
|
}
|
|
@@ -10362,8 +10652,8 @@ var mintlifySource = (options) => {
|
|
|
10362
10652
|
};
|
|
10363
10653
|
};
|
|
10364
10654
|
const read = async (ref) => {
|
|
10365
|
-
const file =
|
|
10366
|
-
const result = await transform(await
|
|
10655
|
+
const file = join22(contentRoot, ref);
|
|
10656
|
+
const result = await transform(await readFile15(file, "utf-8"), file);
|
|
10367
10657
|
return result.content;
|
|
10368
10658
|
};
|
|
10369
10659
|
return {
|
|
@@ -10380,11 +10670,11 @@ var mintlifySource = (options) => {
|
|
|
10380
10670
|
|
|
10381
10671
|
// src/core/sources/notion.ts
|
|
10382
10672
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
10383
|
-
import { join as
|
|
10673
|
+
import { join as join24 } from "pathe";
|
|
10384
10674
|
|
|
10385
10675
|
// src/core/sources/assets.ts
|
|
10386
|
-
import { mkdir as mkdir4, writeFile as
|
|
10387
|
-
import { extname as extname6, join as
|
|
10676
|
+
import { mkdir as mkdir4, writeFile as writeFile6 } from "node:fs/promises";
|
|
10677
|
+
import { extname as extname6, join as join23 } from "pathe";
|
|
10388
10678
|
var MD_IMAGE = /!\[(?<alt>[^\]]*)\]\((?<url>[^)\s]+)\)/gu;
|
|
10389
10679
|
var REMOTE = /^https?:\/\//u;
|
|
10390
10680
|
var SAFE_EXT = /^\.[a-z0-9]+$/iu;
|
|
@@ -10413,7 +10703,7 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
10413
10703
|
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
10414
10704
|
const file = `${hashText(url)}${extFor(url)}`;
|
|
10415
10705
|
await mkdir4(ctx.assetsDir, { recursive: true });
|
|
10416
|
-
await
|
|
10706
|
+
await writeFile6(join23(ctx.assetsDir, file), bytes);
|
|
10417
10707
|
rewrites.set(url, `${ctx.assetsBaseUrl}/${file}`);
|
|
10418
10708
|
} catch (error) {
|
|
10419
10709
|
diagnostics.push({
|
|
@@ -10529,8 +10819,8 @@ ${text}
|
|
|
10529
10819
|
};
|
|
10530
10820
|
var notionSource = (options, ctx) => {
|
|
10531
10821
|
const props = options.properties ?? {};
|
|
10532
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
10533
|
-
const assetsDir = ctx?.assetsDir ??
|
|
10822
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join24(".blume", "cache", options.name));
|
|
10823
|
+
const assetsDir = ctx?.assetsDir ?? join24(".blume", "public", "blume-assets", options.name);
|
|
10534
10824
|
const assetsBaseUrl = ctx?.assetsBaseUrl ?? `/blume-assets/${options.name}`;
|
|
10535
10825
|
let snapshot = new Map;
|
|
10536
10826
|
const resolveClient = async () => {
|
|
@@ -10635,10 +10925,10 @@ ${rendered.join(`
|
|
|
10635
10925
|
data.sidebar = { order };
|
|
10636
10926
|
}
|
|
10637
10927
|
const slugProp = richToMarkdown(page.properties[props.slug ?? "Slug"]?.rich_text);
|
|
10638
|
-
const slug =
|
|
10928
|
+
const slug = slugify3(slugProp || title) || page.id;
|
|
10639
10929
|
return { data, slug };
|
|
10640
10930
|
};
|
|
10641
|
-
const
|
|
10931
|
+
const toEntry2 = async (client, page) => {
|
|
10642
10932
|
const { data, slug } = frontmatter(page);
|
|
10643
10933
|
const mdx = await renderBlocks(client, await childrenOf(client, page.id));
|
|
10644
10934
|
const assets = await materializeAssets(mdx, {
|
|
@@ -10667,7 +10957,7 @@ ${rendered.join(`
|
|
|
10667
10957
|
database_id: options.database,
|
|
10668
10958
|
start_cursor: cursor
|
|
10669
10959
|
})));
|
|
10670
|
-
const built = await Promise.all(pages.map((page) =>
|
|
10960
|
+
const built = await Promise.all(pages.map((page) => toEntry2(client, page)));
|
|
10671
10961
|
for (const item of built) {
|
|
10672
10962
|
assetDiagnostics.push(...item.diagnostics);
|
|
10673
10963
|
}
|
|
@@ -10698,7 +10988,7 @@ ${rendered.join(`
|
|
|
10698
10988
|
};
|
|
10699
10989
|
|
|
10700
10990
|
// src/core/sources/sanity.ts
|
|
10701
|
-
import { join as
|
|
10991
|
+
import { join as join25 } from "pathe";
|
|
10702
10992
|
|
|
10703
10993
|
// src/core/sources/portable-text.ts
|
|
10704
10994
|
var HEADING_STYLES = {
|
|
@@ -10837,11 +11127,11 @@ var resolveClient = async (options, preview) => {
|
|
|
10837
11127
|
};
|
|
10838
11128
|
var sanitySource = (options, ctx) => {
|
|
10839
11129
|
const fields = options.fields ?? {};
|
|
10840
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
11130
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join25(".blume", "cache", options.name));
|
|
10841
11131
|
let snapshot = new Map;
|
|
10842
|
-
const
|
|
11132
|
+
const toEntry2 = (doc) => {
|
|
10843
11133
|
const slugValue = asString2(getPath(doc, fields.slug ?? "slug.current")) ?? asString2(doc._id) ?? "untitled";
|
|
10844
|
-
const slug =
|
|
11134
|
+
const slug = slugify3(slugValue) || slugify3(asString2(doc._id) ?? "") || "untitled";
|
|
10845
11135
|
const data = {};
|
|
10846
11136
|
const title = asString2(getPath(doc, fields.title ?? "title"));
|
|
10847
11137
|
const description = asString2(getPath(doc, fields.description ?? "description"));
|
|
@@ -10873,7 +11163,7 @@ var sanitySource = (options, ctx) => {
|
|
|
10873
11163
|
const result = await loadWithCache(options.name, cache, async () => {
|
|
10874
11164
|
const client = await resolveClient(options, ctx?.preview ?? false);
|
|
10875
11165
|
const docs = await client.fetch(options.query);
|
|
10876
|
-
return docs.map(
|
|
11166
|
+
return docs.map(toEntry2);
|
|
10877
11167
|
}, ctx?.refresh ?? true);
|
|
10878
11168
|
snapshot = new Map(result.entries.map((entry) => [entry.ref, entry]));
|
|
10879
11169
|
return result;
|
|
@@ -10912,8 +11202,8 @@ var uniqueNamer = () => {
|
|
|
10912
11202
|
};
|
|
10913
11203
|
var sourceContext = (context, name, runtime) => ({
|
|
10914
11204
|
assetsBaseUrl: `/blume-assets/${name}`,
|
|
10915
|
-
assetsDir:
|
|
10916
|
-
cacheDir:
|
|
11205
|
+
assetsDir: join26(context.outDir, "public", "blume-assets", name),
|
|
11206
|
+
cacheDir: join26(context.outDir, "cache", name),
|
|
10917
11207
|
mode: runtime.mode,
|
|
10918
11208
|
preview: runtime.preview,
|
|
10919
11209
|
projectRoot: context.root,
|
|
@@ -10995,7 +11285,7 @@ var baseName = (def) => {
|
|
|
10995
11285
|
}
|
|
10996
11286
|
return def.prefix ?? def.type;
|
|
10997
11287
|
};
|
|
10998
|
-
var
|
|
11288
|
+
var contentSources = (config, context, runtime) => {
|
|
10999
11289
|
const defs = config.content.sources;
|
|
11000
11290
|
if (!defs || defs.length === 0) {
|
|
11001
11291
|
return [
|
|
@@ -11011,6 +11301,14 @@ var resolveSources = (config, context, runtime) => {
|
|
|
11011
11301
|
const nameFor = uniqueNamer();
|
|
11012
11302
|
return defs.map((def) => buildSource(def, nameFor(baseName(def)), context, runtime));
|
|
11013
11303
|
};
|
|
11304
|
+
var resolveSources = (config, context, runtime) => {
|
|
11305
|
+
const sources = contentSources(config, context, runtime);
|
|
11306
|
+
const references = blumeReferences(config);
|
|
11307
|
+
if (references.length > 0) {
|
|
11308
|
+
sources.push(openApiSource(references, sourceContext(context, "openapi", runtime)));
|
|
11309
|
+
}
|
|
11310
|
+
return sources;
|
|
11311
|
+
};
|
|
11014
11312
|
|
|
11015
11313
|
// src/core/project-graph.ts
|
|
11016
11314
|
var applyConfigOverrides = (config, overrides) => {
|
|
@@ -11039,7 +11337,9 @@ var scanProject = async (root, options = {}) => {
|
|
|
11039
11337
|
});
|
|
11040
11338
|
const { bridge } = configResult;
|
|
11041
11339
|
const config = applyConfigOverrides(configResult.config, options.overrides);
|
|
11042
|
-
const context = resolveProjectContext(root, config
|
|
11340
|
+
const context = resolveProjectContext(root, config, {
|
|
11341
|
+
runtimeDir: options.runtimeDir
|
|
11342
|
+
});
|
|
11043
11343
|
const sources = resolveSources(config, context, {
|
|
11044
11344
|
mode,
|
|
11045
11345
|
preview,
|
|
@@ -11107,8 +11407,8 @@ var scanProject = async (root, options = {}) => {
|
|
|
11107
11407
|
};
|
|
11108
11408
|
|
|
11109
11409
|
// src/cli/env.ts
|
|
11110
|
-
import { existsSync as
|
|
11111
|
-
import { dirname as dirname12, join as
|
|
11410
|
+
import { existsSync as existsSync16, readFileSync as readFileSync9 } from "node:fs";
|
|
11411
|
+
import { dirname as dirname12, join as join27, resolve as resolve9 } from "pathe";
|
|
11112
11412
|
var ENV_LINE = /^\s*(?:export\s+)?(?<key>[A-Za-z_][A-Za-z0-9_]*)\s*=\s*(?<value>.*?)\s*$/u;
|
|
11113
11413
|
var DOUBLE_QUOTED2 = /^"(?<body>[\s\S]*)"$/u;
|
|
11114
11414
|
var SINGLE_QUOTED = /^'(?<body>[\s\S]*)'$/u;
|
|
@@ -11146,7 +11446,7 @@ var applyEnv = (parsed) => {
|
|
|
11146
11446
|
};
|
|
11147
11447
|
var loadFile = (path) => {
|
|
11148
11448
|
try {
|
|
11149
|
-
if (
|
|
11449
|
+
if (existsSync16(path)) {
|
|
11150
11450
|
applyEnv(parseEnv(readFileSync9(path, "utf-8")));
|
|
11151
11451
|
}
|
|
11152
11452
|
} catch {}
|
|
@@ -11155,10 +11455,10 @@ var loadEnvFiles = (startDir) => {
|
|
|
11155
11455
|
let dir = resolve9(startDir);
|
|
11156
11456
|
let done = false;
|
|
11157
11457
|
while (!done) {
|
|
11158
|
-
loadFile(
|
|
11159
|
-
loadFile(
|
|
11458
|
+
loadFile(join27(dir, ".env.local"));
|
|
11459
|
+
loadFile(join27(dir, ".env"));
|
|
11160
11460
|
const parent = dirname12(dir);
|
|
11161
|
-
done =
|
|
11461
|
+
done = existsSync16(join27(dir, ".git")) || parent === dir;
|
|
11162
11462
|
dir = parent;
|
|
11163
11463
|
}
|
|
11164
11464
|
};
|
|
@@ -11231,7 +11531,8 @@ var prepareProject = async (options) => {
|
|
|
11231
11531
|
mode: options.mode,
|
|
11232
11532
|
overrides: options.overrides,
|
|
11233
11533
|
preview: options.preview,
|
|
11234
|
-
refresh: options.refresh
|
|
11534
|
+
refresh: options.refresh,
|
|
11535
|
+
runtimeDir: options.runtimeDir
|
|
11235
11536
|
});
|
|
11236
11537
|
} catch (error) {
|
|
11237
11538
|
if (error instanceof BlumeError) {
|
|
@@ -11287,24 +11588,24 @@ var emitRedirectFiles = async (config, distDir) => {
|
|
|
11287
11588
|
if (redirects.length === 0 || config.deployment.output !== "static") {
|
|
11288
11589
|
return;
|
|
11289
11590
|
}
|
|
11290
|
-
await
|
|
11591
|
+
await writeFile7(join28(distDir, "blume-redirects.json"), buildRedirectManifest(redirects), "utf-8");
|
|
11291
11592
|
const platformFiles = [
|
|
11292
11593
|
{ content: buildNetlifyRedirects(redirects), name: "_redirects" },
|
|
11293
11594
|
{ content: buildVercelConfig(redirects), name: "vercel.json" }
|
|
11294
11595
|
];
|
|
11295
|
-
await Promise.all(platformFiles.map((file) =>
|
|
11596
|
+
await Promise.all(platformFiles.map((file) => existsSync17(join28(distDir, file.name)) ? Promise.resolve() : writeFile7(join28(distDir, file.name), file.content, "utf-8")));
|
|
11296
11597
|
logger.success(`Emitted redirect files for ${redirects.length} redirect(s)`);
|
|
11297
11598
|
};
|
|
11298
11599
|
var formatBytes = (bytes) => bytes < 1024 ? `${bytes} B` : `${(bytes / 1024).toFixed(bytes < 1024 * 100 ? 1 : 0)} kB`;
|
|
11299
11600
|
var astroAssets = async (distDir, ext) => {
|
|
11300
|
-
const astroDir =
|
|
11301
|
-
if (!
|
|
11601
|
+
const astroDir = join28(distDir, "_astro");
|
|
11602
|
+
if (!existsSync17(astroDir)) {
|
|
11302
11603
|
return [];
|
|
11303
11604
|
}
|
|
11304
11605
|
const entries = await readdir(astroDir);
|
|
11305
11606
|
const files = entries.filter((name) => name.endsWith(`.${ext}`));
|
|
11306
11607
|
const sized = await Promise.all(files.map(async (name) => {
|
|
11307
|
-
const info = await stat(
|
|
11608
|
+
const info = await stat(join28(astroDir, name));
|
|
11308
11609
|
return { name, size: info.size };
|
|
11309
11610
|
}));
|
|
11310
11611
|
return sized.toSorted((a, b) => b.size - a.size);
|
|
@@ -11346,6 +11647,58 @@ var enforceBudget = async (distDir, args) => {
|
|
|
11346
11647
|
}
|
|
11347
11648
|
return passed ? "pass" : "fail";
|
|
11348
11649
|
};
|
|
11650
|
+
var publishBuildArtifacts = async (project, distDir, args) => {
|
|
11651
|
+
if (project.config.search.provider === "pagefind") {
|
|
11652
|
+
logger.start("Building search index");
|
|
11653
|
+
const indexed = await buildSearchIndex(distDir);
|
|
11654
|
+
logger.success(`Indexed ${indexed} page(s) for search`);
|
|
11655
|
+
}
|
|
11656
|
+
await syncSearchProvider(project, {
|
|
11657
|
+
start: (message) => logger.start(message),
|
|
11658
|
+
success: (message) => logger.success(message),
|
|
11659
|
+
warn: (message) => logger.warn(message)
|
|
11660
|
+
});
|
|
11661
|
+
if (project.config.ai.llmsTxt) {
|
|
11662
|
+
const { index, full } = await buildLlmsFiles(project);
|
|
11663
|
+
await Promise.all([
|
|
11664
|
+
writeFile7(join28(distDir, "llms.txt"), index, "utf-8"),
|
|
11665
|
+
writeFile7(join28(distDir, "llms-full.txt"), full, "utf-8")
|
|
11666
|
+
]);
|
|
11667
|
+
logger.success("Generated llms.txt and llms-full.txt");
|
|
11668
|
+
}
|
|
11669
|
+
const sitemap = buildSitemap(project);
|
|
11670
|
+
if (sitemap && !existsSync17(join28(distDir, "sitemap.xml"))) {
|
|
11671
|
+
await writeFile7(join28(distDir, "sitemap.xml"), sitemap, "utf-8");
|
|
11672
|
+
logger.success("Generated sitemap.xml");
|
|
11673
|
+
}
|
|
11674
|
+
const robots = buildRobots(project);
|
|
11675
|
+
if (robots && !existsSync17(join28(distDir, "robots.txt"))) {
|
|
11676
|
+
await writeFile7(join28(distDir, "robots.txt"), robots, "utf-8");
|
|
11677
|
+
logger.success("Generated robots.txt");
|
|
11678
|
+
}
|
|
11679
|
+
await emitRedirectFiles(project.config, distDir);
|
|
11680
|
+
const { config } = project;
|
|
11681
|
+
const features = serverFeatures(config);
|
|
11682
|
+
logger.box([
|
|
11683
|
+
`Output ${config.deployment.output}`,
|
|
11684
|
+
`Adapter ${config.deployment.adapter ?? "none"}`,
|
|
11685
|
+
`Site ${config.deployment.site ?? "not set"}`,
|
|
11686
|
+
`Search ${config.search.provider}`,
|
|
11687
|
+
`Redirects ${config.redirects.length}`,
|
|
11688
|
+
`Sitemap ${sitemap ? "yes" : "no (set deployment.site)"}`,
|
|
11689
|
+
`Robots ${robots ? "yes" : "no"}`,
|
|
11690
|
+
`LLM files ${config.ai.llmsTxt ? "yes" : "no"}`,
|
|
11691
|
+
`Server features ${features.length > 0 ? features.join(", ") : "none"}`
|
|
11692
|
+
].join(`
|
|
11693
|
+
`));
|
|
11694
|
+
if (args.analyze) {
|
|
11695
|
+
await reportBundleSizes(distDir);
|
|
11696
|
+
}
|
|
11697
|
+
if (await enforceBudget(distDir, args) === "fail") {
|
|
11698
|
+
process.exit(1);
|
|
11699
|
+
}
|
|
11700
|
+
logger.success(`Built to ${distDir}`);
|
|
11701
|
+
};
|
|
11349
11702
|
var buildCommand = defineCommand2({
|
|
11350
11703
|
args: {
|
|
11351
11704
|
adapter: {
|
|
@@ -11368,6 +11721,10 @@ var buildCommand = defineCommand2({
|
|
|
11368
11721
|
description: "Fail if total client JavaScript exceeds this many kB.",
|
|
11369
11722
|
type: "string"
|
|
11370
11723
|
},
|
|
11724
|
+
isolated: {
|
|
11725
|
+
description: "Build into an isolated .blume-verify runtime (and its own dist) so a running dev server and the real dist/ are untouched. For verifying changes while `blume dev` runs.",
|
|
11726
|
+
type: "boolean"
|
|
11727
|
+
},
|
|
11371
11728
|
output: {
|
|
11372
11729
|
description: "Output mode: static | server.",
|
|
11373
11730
|
type: "string"
|
|
@@ -11384,7 +11741,11 @@ var buildCommand = defineCommand2({
|
|
|
11384
11741
|
},
|
|
11385
11742
|
async run({ args }) {
|
|
11386
11743
|
const root = process.cwd();
|
|
11387
|
-
|
|
11744
|
+
const runtimeDir = args.isolated ? ".blume-verify" : process.env.BLUME_RUNTIME_DIR;
|
|
11745
|
+
refuseIfDevRunning(root, "building", runtimeDir);
|
|
11746
|
+
if (args.isolated) {
|
|
11747
|
+
await ensureGitignore(root, [".blume-verify/"]);
|
|
11748
|
+
}
|
|
11388
11749
|
if (args.output && args.output !== "static" && args.output !== "server") {
|
|
11389
11750
|
logger.error(`Invalid --output "${args.output}" (use static | server).`);
|
|
11390
11751
|
process.exit(1);
|
|
@@ -11403,6 +11764,7 @@ var buildCommand = defineCommand2({
|
|
|
11403
11764
|
},
|
|
11404
11765
|
preview: args.preview,
|
|
11405
11766
|
root,
|
|
11767
|
+
runtimeDir,
|
|
11406
11768
|
strict: args.strict
|
|
11407
11769
|
});
|
|
11408
11770
|
logger.start(`Building ${project.graph.pages.length} page(s) (${project.config.deployment.output} output)`);
|
|
@@ -11410,68 +11772,27 @@ var buildCommand = defineCommand2({
|
|
|
11410
11772
|
logLevel: "info",
|
|
11411
11773
|
root: project.context.outDir
|
|
11412
11774
|
});
|
|
11413
|
-
const distDir =
|
|
11414
|
-
if (
|
|
11415
|
-
logger.
|
|
11416
|
-
|
|
11417
|
-
logger.success(`Indexed ${indexed} page(s) for search`);
|
|
11418
|
-
}
|
|
11419
|
-
await syncSearchProvider(project, {
|
|
11420
|
-
start: (message) => logger.start(message),
|
|
11421
|
-
success: (message) => logger.success(message),
|
|
11422
|
-
warn: (message) => logger.warn(message)
|
|
11423
|
-
});
|
|
11424
|
-
if (project.config.ai.llmsTxt) {
|
|
11425
|
-
const { index, full } = await buildLlmsFiles(project);
|
|
11426
|
-
await Promise.all([
|
|
11427
|
-
writeFile6(join26(distDir, "llms.txt"), index, "utf-8"),
|
|
11428
|
-
writeFile6(join26(distDir, "llms-full.txt"), full, "utf-8")
|
|
11429
|
-
]);
|
|
11430
|
-
logger.success("Generated llms.txt and llms-full.txt");
|
|
11431
|
-
}
|
|
11432
|
-
const sitemap = buildSitemap(project);
|
|
11433
|
-
if (sitemap && !existsSync16(join26(distDir, "sitemap.xml"))) {
|
|
11434
|
-
await writeFile6(join26(distDir, "sitemap.xml"), sitemap, "utf-8");
|
|
11435
|
-
logger.success("Generated sitemap.xml");
|
|
11436
|
-
}
|
|
11437
|
-
const robots = buildRobots(project);
|
|
11438
|
-
if (robots && !existsSync16(join26(distDir, "robots.txt"))) {
|
|
11439
|
-
await writeFile6(join26(distDir, "robots.txt"), robots, "utf-8");
|
|
11440
|
-
logger.success("Generated robots.txt");
|
|
11441
|
-
}
|
|
11442
|
-
await emitRedirectFiles(project.config, distDir);
|
|
11443
|
-
const { config } = project;
|
|
11444
|
-
const features = serverFeatures(config);
|
|
11445
|
-
logger.box([
|
|
11446
|
-
`Output ${config.deployment.output}`,
|
|
11447
|
-
`Adapter ${config.deployment.adapter ?? "none"}`,
|
|
11448
|
-
`Site ${config.deployment.site ?? "not set"}`,
|
|
11449
|
-
`Search ${config.search.provider}`,
|
|
11450
|
-
`Redirects ${config.redirects.length}`,
|
|
11451
|
-
`Sitemap ${sitemap ? "yes" : "no (set deployment.site)"}`,
|
|
11452
|
-
`Robots ${robots ? "yes" : "no"}`,
|
|
11453
|
-
`LLM files ${config.ai.llmsTxt ? "yes" : "no"}`,
|
|
11454
|
-
`Server features ${features.length > 0 ? features.join(", ") : "none"}`
|
|
11455
|
-
].join(`
|
|
11456
|
-
`));
|
|
11457
|
-
if (args.analyze) {
|
|
11458
|
-
await reportBundleSizes(distDir);
|
|
11459
|
-
}
|
|
11460
|
-
if (await enforceBudget(distDir, args) === "fail") {
|
|
11461
|
-
process.exit(1);
|
|
11775
|
+
const distDir = project.context.distDir ?? join28(root, "dist");
|
|
11776
|
+
if (runtimeDir) {
|
|
11777
|
+
logger.success(`Isolated build OK — output at ${distDir} (not published).`);
|
|
11778
|
+
return;
|
|
11462
11779
|
}
|
|
11463
|
-
|
|
11780
|
+
await publishBuildArtifacts(project, distDir, args);
|
|
11464
11781
|
}
|
|
11465
11782
|
});
|
|
11466
11783
|
|
|
11467
11784
|
// src/cli/commands/check.ts
|
|
11468
|
-
import { existsSync as
|
|
11785
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
11469
11786
|
import { check } from "@astrojs/check";
|
|
11470
11787
|
import { sync } from "astro";
|
|
11471
11788
|
import { defineCommand as defineCommand3 } from "citty";
|
|
11472
|
-
import { join as
|
|
11789
|
+
import { join as join29 } from "pathe";
|
|
11473
11790
|
var checkCommand = defineCommand3({
|
|
11474
11791
|
args: {
|
|
11792
|
+
isolated: {
|
|
11793
|
+
description: "Type-check in an isolated .blume-verify runtime so a running dev server is untouched. For verifying changes while `blume dev` runs.",
|
|
11794
|
+
type: "boolean"
|
|
11795
|
+
},
|
|
11475
11796
|
preview: {
|
|
11476
11797
|
description: "Include drafts and unpublished CMS content.",
|
|
11477
11798
|
type: "boolean"
|
|
@@ -11487,21 +11808,27 @@ var checkCommand = defineCommand3({
|
|
|
11487
11808
|
},
|
|
11488
11809
|
async run({ args }) {
|
|
11489
11810
|
const root = process.cwd();
|
|
11811
|
+
const runtimeDir = args.isolated ? ".blume-verify" : process.env.BLUME_RUNTIME_DIR;
|
|
11812
|
+
refuseIfDevRunning(root, "checking", runtimeDir);
|
|
11813
|
+
if (args.isolated) {
|
|
11814
|
+
await ensureGitignore(root, [".blume-verify/"]);
|
|
11815
|
+
}
|
|
11490
11816
|
const project = await prepareProject({
|
|
11491
11817
|
mode: "build",
|
|
11492
11818
|
preview: args.preview,
|
|
11493
11819
|
root,
|
|
11820
|
+
runtimeDir,
|
|
11494
11821
|
strict: args.strict
|
|
11495
11822
|
});
|
|
11496
11823
|
const { outDir } = project.context;
|
|
11497
11824
|
await sync({ logLevel: "warn", root: outDir });
|
|
11498
|
-
const tsconfig =
|
|
11825
|
+
const tsconfig = join29(root, "tsconfig.json");
|
|
11499
11826
|
logger.start(`Type-checking ${project.graph.pages.length} page(s)`);
|
|
11500
11827
|
const failed = await check({
|
|
11501
11828
|
minimumFailingSeverity: "error",
|
|
11502
11829
|
minimumSeverity: "hint",
|
|
11503
11830
|
root: outDir,
|
|
11504
|
-
tsconfig:
|
|
11831
|
+
tsconfig: existsSync18(tsconfig) ? tsconfig : undefined,
|
|
11505
11832
|
watch: false
|
|
11506
11833
|
});
|
|
11507
11834
|
if (failed) {
|
|
@@ -11518,7 +11845,7 @@ import { dev } from "astro";
|
|
|
11518
11845
|
import { defineCommand as defineCommand4 } from "citty";
|
|
11519
11846
|
|
|
11520
11847
|
// src/astro/static-assets.ts
|
|
11521
|
-
import { extname as extname7, join as
|
|
11848
|
+
import { extname as extname7, join as join30, relative as relative15, resolve as resolve10, sep } from "pathe";
|
|
11522
11849
|
|
|
11523
11850
|
// src/astro/integration.ts
|
|
11524
11851
|
var overlayServer = null;
|
|
@@ -11744,15 +12071,19 @@ var doctorCommand = defineCommand5({
|
|
|
11744
12071
|
});
|
|
11745
12072
|
|
|
11746
12073
|
// src/cli/commands/eject.ts
|
|
11747
|
-
import { readFile as
|
|
12074
|
+
import { readFile as readFile17, writeFile as writeFile9 } from "node:fs/promises";
|
|
11748
12075
|
import { defineCommand as defineCommand6 } from "citty";
|
|
11749
|
-
import { join as
|
|
12076
|
+
import { join as join32, relative as relative17 } from "pathe";
|
|
11750
12077
|
|
|
11751
12078
|
// src/registry/eject.ts
|
|
11752
|
-
import { existsSync as
|
|
11753
|
-
import { cp, mkdir as mkdir5, readFile as
|
|
11754
|
-
import { join as
|
|
12079
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
12080
|
+
import { cp, mkdir as mkdir5, readFile as readFile16, rm as rm2, writeFile as writeFile8 } from "node:fs/promises";
|
|
12081
|
+
import { join as join31, relative as relative16 } from "pathe";
|
|
11755
12082
|
var POSIX = (path) => path.split("\\").join("/");
|
|
12083
|
+
var ejectOpenApiData = (project) => {
|
|
12084
|
+
const source = project.sources.find(isOpenApiSource);
|
|
12085
|
+
return source ? source.openApiData() : {};
|
|
12086
|
+
};
|
|
11756
12087
|
var askFiles = async (project, srcDir, genDir) => {
|
|
11757
12088
|
const { ask } = project.config.ai;
|
|
11758
12089
|
if (!ask?.enabled) {
|
|
@@ -11762,14 +12093,14 @@ var askFiles = async (project, srcDir, genDir) => {
|
|
|
11762
12093
|
const files = [
|
|
11763
12094
|
{
|
|
11764
12095
|
content: askEndpointTemplate(resolveAskBackend(ask), grounded),
|
|
11765
|
-
path:
|
|
12096
|
+
path: join31(srcDir, "pages", "api", "ask.ts")
|
|
11766
12097
|
}
|
|
11767
12098
|
];
|
|
11768
12099
|
if (grounded) {
|
|
11769
12100
|
files.push({
|
|
11770
12101
|
content: `${JSON.stringify(await buildAskData(project))}
|
|
11771
12102
|
`,
|
|
11772
|
-
path:
|
|
12103
|
+
path: join31(genDir, "ask-data.json")
|
|
11773
12104
|
});
|
|
11774
12105
|
}
|
|
11775
12106
|
return files;
|
|
@@ -11777,15 +12108,15 @@ var askFiles = async (project, srcDir, genDir) => {
|
|
|
11777
12108
|
var eject = async (root) => {
|
|
11778
12109
|
const project = await scanProject(root, { mode: "build" });
|
|
11779
12110
|
const { context, config } = project;
|
|
11780
|
-
const srcDir =
|
|
11781
|
-
const genDir =
|
|
12111
|
+
const srcDir = join31(root, "src");
|
|
12112
|
+
const genDir = join31(srcDir, "generated");
|
|
11782
12113
|
const askEnabled = config.ai.ask?.enabled ?? false;
|
|
11783
12114
|
const exportPdf = config.export.pdf;
|
|
11784
12115
|
const exportEpub = config.export.epub;
|
|
11785
12116
|
const [pages, needsReactRaw, userTheme, rawMarkdown, islands, examples] = await Promise.all([
|
|
11786
12117
|
context.pagesRoot ? discoverPages(context.pagesRoot) : Promise.resolve([]),
|
|
11787
12118
|
detectNeedsReact(root),
|
|
11788
|
-
context.themeFile ?
|
|
12119
|
+
context.themeFile ? readFile16(context.themeFile, "utf-8") : Promise.resolve(""),
|
|
11789
12120
|
buildRawMarkdown(project),
|
|
11790
12121
|
discoverIslands(root),
|
|
11791
12122
|
discoverExamples(root, config.examples)
|
|
@@ -11822,18 +12153,19 @@ var eject = async (root) => {
|
|
|
11822
12153
|
needsReact,
|
|
11823
12154
|
needsSvelte,
|
|
11824
12155
|
needsVue,
|
|
12156
|
+
openapiPath: "./src/generated/openapi.json",
|
|
11825
12157
|
pages: relPages,
|
|
11826
12158
|
searchClientPath: "./src/generated/search-client.ts",
|
|
11827
12159
|
themePath: "./src/generated/app.css"
|
|
11828
12160
|
}),
|
|
11829
|
-
path:
|
|
12161
|
+
path: join31(root, "astro.config.mjs")
|
|
11830
12162
|
},
|
|
11831
12163
|
{
|
|
11832
12164
|
content: runtimeTsconfigTemplate(),
|
|
11833
|
-
path:
|
|
12165
|
+
path: join31(root, "tsconfig.json"),
|
|
11834
12166
|
skipIfExists: true
|
|
11835
12167
|
},
|
|
11836
|
-
{ content: envTemplate(), path:
|
|
12168
|
+
{ content: envTemplate(), path: join31(srcDir, "env.d.ts") },
|
|
11837
12169
|
{
|
|
11838
12170
|
content: contentConfigTemplate({
|
|
11839
12171
|
config,
|
|
@@ -11841,7 +12173,7 @@ var eject = async (root) => {
|
|
|
11841
12173
|
staged: hasStaged,
|
|
11842
12174
|
stagedBase: stagedDir
|
|
11843
12175
|
}),
|
|
11844
|
-
path:
|
|
12176
|
+
path: join31(srcDir, "content.config.ts")
|
|
11845
12177
|
},
|
|
11846
12178
|
{
|
|
11847
12179
|
content: catchAllPageTemplate({
|
|
@@ -11851,19 +12183,19 @@ var eject = async (root) => {
|
|
|
11851
12183
|
mathEnabled: config.markdown.math,
|
|
11852
12184
|
needsReact
|
|
11853
12185
|
}),
|
|
11854
|
-
path:
|
|
12186
|
+
path: join31(srcDir, "pages", "[...slug].astro")
|
|
11855
12187
|
},
|
|
11856
12188
|
{
|
|
11857
12189
|
content: planComponentSlots(componentsImport, null).module,
|
|
11858
|
-
path:
|
|
12190
|
+
path: join31(genDir, "components.ts")
|
|
11859
12191
|
},
|
|
11860
12192
|
{
|
|
11861
12193
|
content: islandMapTemplate(islands.islands),
|
|
11862
|
-
path:
|
|
12194
|
+
path: join31(genDir, "islands.ts")
|
|
11863
12195
|
},
|
|
11864
12196
|
{
|
|
11865
12197
|
content: exampleMapTemplate(examples.examples),
|
|
11866
|
-
path:
|
|
12198
|
+
path: join31(genDir, "examples.ts")
|
|
11867
12199
|
},
|
|
11868
12200
|
{
|
|
11869
12201
|
content: tailwindEntryTemplate({
|
|
@@ -11875,21 +12207,26 @@ var eject = async (root) => {
|
|
|
11875
12207
|
twoslashCss: twoslashCss(),
|
|
11876
12208
|
userTheme
|
|
11877
12209
|
}),
|
|
11878
|
-
path:
|
|
12210
|
+
path: join31(genDir, "app.css")
|
|
12211
|
+
},
|
|
12212
|
+
{ content: buildRuntimeData(project), path: join31(genDir, "data.json") },
|
|
12213
|
+
{
|
|
12214
|
+
content: `${JSON.stringify(ejectOpenApiData(project))}
|
|
12215
|
+
`,
|
|
12216
|
+
path: join31(genDir, "openapi.json")
|
|
11879
12217
|
},
|
|
11880
|
-
{ content: buildRuntimeData(project), path: join29(genDir, "data.json") },
|
|
11881
12218
|
{
|
|
11882
12219
|
content: `${JSON.stringify(rawMarkdown)}
|
|
11883
12220
|
`,
|
|
11884
|
-
path:
|
|
12221
|
+
path: join31(genDir, "raw-markdown.json")
|
|
11885
12222
|
},
|
|
11886
12223
|
{
|
|
11887
12224
|
content: rawMarkdownEndpointTemplate(),
|
|
11888
|
-
path:
|
|
12225
|
+
path: join31(srcDir, "pages", "[...slug].md.ts")
|
|
11889
12226
|
},
|
|
11890
12227
|
{
|
|
11891
12228
|
content: rawMarkdownEndpointTemplate(),
|
|
11892
|
-
path:
|
|
12229
|
+
path: join31(srcDir, "pages", "[...slug].mdx.ts")
|
|
11893
12230
|
}
|
|
11894
12231
|
];
|
|
11895
12232
|
if (askEnabled) {
|
|
@@ -11898,34 +12235,34 @@ var eject = async (root) => {
|
|
|
11898
12235
|
if (config.seo.og.enabled) {
|
|
11899
12236
|
files.push({
|
|
11900
12237
|
content: ogEndpointTemplate(customOgRoutes(pages, config.title)),
|
|
11901
|
-
path:
|
|
12238
|
+
path: join31(srcDir, "pages", "og", "[...slug].png.ts")
|
|
11902
12239
|
});
|
|
11903
12240
|
}
|
|
11904
12241
|
if (!routeIsTaken(pages, project.graph.pages, "/404")) {
|
|
11905
12242
|
files.push({
|
|
11906
12243
|
content: notFoundPageTemplate(),
|
|
11907
|
-
path:
|
|
12244
|
+
path: join31(srcDir, "pages", "404.astro")
|
|
11908
12245
|
});
|
|
11909
12246
|
}
|
|
11910
12247
|
files.push({
|
|
11911
12248
|
content: searchClientTemplate(config),
|
|
11912
|
-
path:
|
|
12249
|
+
path: join31(genDir, "search-client.ts")
|
|
11913
12250
|
});
|
|
11914
12251
|
if (servesStaticIndex(config.search.provider)) {
|
|
11915
12252
|
const documents = await buildSearchDocuments(project);
|
|
11916
12253
|
files.push({
|
|
11917
12254
|
content: `${JSON.stringify(documents)}
|
|
11918
12255
|
`,
|
|
11919
|
-
path:
|
|
12256
|
+
path: join31(genDir, "search.json")
|
|
11920
12257
|
}, {
|
|
11921
12258
|
content: searchEndpointTemplate(),
|
|
11922
|
-
path:
|
|
12259
|
+
path: join31(srcDir, "pages", "blume-search.json.ts")
|
|
11923
12260
|
});
|
|
11924
12261
|
}
|
|
11925
12262
|
if (config.search.provider === "mixedbread") {
|
|
11926
12263
|
files.push({
|
|
11927
12264
|
content: mixedbreadSearchEndpointTemplate(config.search.mixedbread?.storeId ?? ""),
|
|
11928
|
-
path:
|
|
12265
|
+
path: join31(srcDir, "pages", "api", "search.ts")
|
|
11929
12266
|
});
|
|
11930
12267
|
}
|
|
11931
12268
|
const feeds = buildRssFeeds(project);
|
|
@@ -11934,13 +12271,13 @@ var eject = async (root) => {
|
|
|
11934
12271
|
files.push({
|
|
11935
12272
|
content: `${JSON.stringify(feedXml)}
|
|
11936
12273
|
`,
|
|
11937
|
-
path:
|
|
12274
|
+
path: join31(genDir, "rss.json")
|
|
11938
12275
|
}, {
|
|
11939
12276
|
content: rssEndpointTemplate(),
|
|
11940
|
-
path:
|
|
12277
|
+
path: join31(srcDir, "pages", "[section]", "rss.xml.ts")
|
|
11941
12278
|
});
|
|
11942
12279
|
}
|
|
11943
|
-
if (
|
|
12280
|
+
if (hasScalarReferences(config)) {
|
|
11944
12281
|
const references = await buildReferenceFiles({
|
|
11945
12282
|
config,
|
|
11946
12283
|
contentRoutes: new Set(project.graph.pages.map((page) => page.route)),
|
|
@@ -11949,28 +12286,28 @@ var eject = async (root) => {
|
|
|
11949
12286
|
for (const file of references.files) {
|
|
11950
12287
|
files.push({
|
|
11951
12288
|
content: file.content,
|
|
11952
|
-
path:
|
|
12289
|
+
path: join31(srcDir, "pages", file.pagePath)
|
|
11953
12290
|
});
|
|
11954
12291
|
}
|
|
11955
12292
|
}
|
|
11956
12293
|
files.push(...islands.islands.map((island) => ({
|
|
11957
12294
|
content: islandWrapperTemplate(island),
|
|
11958
|
-
path:
|
|
12295
|
+
path: join31(genDir, "islands", `${island.name}.astro`)
|
|
11959
12296
|
})), ...examples.examples.map((example) => ({
|
|
11960
12297
|
content: exampleWrapperTemplate(example),
|
|
11961
|
-
path:
|
|
12298
|
+
path: join31(genDir, "examples", `${exampleSlug(example.path)}.astro`)
|
|
11962
12299
|
})));
|
|
11963
12300
|
for (const [entryId, content] of staged) {
|
|
11964
|
-
files.push({ content, path:
|
|
12301
|
+
files.push({ content, path: join31(root, stagedDir, entryId) });
|
|
11965
12302
|
}
|
|
11966
|
-
const written = files.filter((file) => !(file.skipIfExists &&
|
|
12303
|
+
const written = files.filter((file) => !(file.skipIfExists && existsSync19(file.path)));
|
|
11967
12304
|
await Promise.all(written.map(async (file) => {
|
|
11968
|
-
await mkdir5(
|
|
11969
|
-
await
|
|
12305
|
+
await mkdir5(join31(file.path, ".."), { recursive: true });
|
|
12306
|
+
await writeFile8(file.path, file.content, "utf-8");
|
|
11970
12307
|
}));
|
|
11971
|
-
const assetsSrc =
|
|
11972
|
-
if (
|
|
11973
|
-
await cp(assetsSrc,
|
|
12308
|
+
const assetsSrc = join31(context.outDir, "public", "blume-assets");
|
|
12309
|
+
if (existsSync19(assetsSrc)) {
|
|
12310
|
+
await cp(assetsSrc, join31(root, "public", "blume-assets"), {
|
|
11974
12311
|
recursive: true
|
|
11975
12312
|
});
|
|
11976
12313
|
}
|
|
@@ -11980,10 +12317,10 @@ var eject = async (root) => {
|
|
|
11980
12317
|
|
|
11981
12318
|
// src/cli/commands/eject.ts
|
|
11982
12319
|
var updatePackageScripts = async (root) => {
|
|
11983
|
-
const pkgPath =
|
|
12320
|
+
const pkgPath = join32(root, "package.json");
|
|
11984
12321
|
let pkg;
|
|
11985
12322
|
try {
|
|
11986
|
-
pkg = JSON.parse(await
|
|
12323
|
+
pkg = JSON.parse(await readFile17(pkgPath, "utf-8"));
|
|
11987
12324
|
} catch {
|
|
11988
12325
|
return;
|
|
11989
12326
|
}
|
|
@@ -11994,7 +12331,7 @@ var updatePackageScripts = async (root) => {
|
|
|
11994
12331
|
dev: "astro dev",
|
|
11995
12332
|
preview: "astro preview"
|
|
11996
12333
|
};
|
|
11997
|
-
await
|
|
12334
|
+
await writeFile9(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
11998
12335
|
`, "utf-8");
|
|
11999
12336
|
};
|
|
12000
12337
|
var ejectCommand = defineCommand6({
|
|
@@ -12033,32 +12370,7 @@ The blume package remains importable.`);
|
|
|
12033
12370
|
import { existsSync as existsSync20 } from "node:fs";
|
|
12034
12371
|
import { mkdir as mkdir6, writeFile as writeFile10 } from "node:fs/promises";
|
|
12035
12372
|
import { defineCommand as defineCommand7 } from "citty";
|
|
12036
|
-
import { basename as basename4, dirname as dirname13, isAbsolute as
|
|
12037
|
-
|
|
12038
|
-
// src/core/gitignore.ts
|
|
12039
|
-
import { existsSync as existsSync19 } from "node:fs";
|
|
12040
|
-
import { readFile as readFile16, writeFile as writeFile9 } from "node:fs/promises";
|
|
12041
|
-
import { join as join31 } from "pathe";
|
|
12042
|
-
var gitignoreKey = (line) => line.trim().replace(/\/+$/u, "");
|
|
12043
|
-
var ensureGitignore = async (root, entries) => {
|
|
12044
|
-
const path = join31(root, ".gitignore");
|
|
12045
|
-
const existing = existsSync19(path) ? await readFile16(path, "utf-8") : "";
|
|
12046
|
-
const present = new Set(existing.split(`
|
|
12047
|
-
`).map(gitignoreKey).filter(Boolean));
|
|
12048
|
-
const added = entries.filter((entry) => !present.has(gitignoreKey(entry)));
|
|
12049
|
-
if (added.length === 0) {
|
|
12050
|
-
return [];
|
|
12051
|
-
}
|
|
12052
|
-
const gap = existing.length > 0 && !existing.endsWith(`
|
|
12053
|
-
`) ? `
|
|
12054
|
-
` : "";
|
|
12055
|
-
await writeFile9(path, `${existing}${gap}${added.join(`
|
|
12056
|
-
`)}
|
|
12057
|
-
`, "utf-8");
|
|
12058
|
-
return added;
|
|
12059
|
-
};
|
|
12060
|
-
|
|
12061
|
-
// src/cli/commands/init.ts
|
|
12373
|
+
import { basename as basename4, dirname as dirname13, isAbsolute as isAbsolute9, join as join33, relative as relative18 } from "pathe";
|
|
12062
12374
|
var toPackageName = (raw) => raw.toLowerCase().replaceAll(/[^a-z0-9._-]+/gu, "-").replaceAll(/^[-_.]+|[-_.]+$/gu, "") || "docs";
|
|
12063
12375
|
var packageTemplate = (name, version) => `{
|
|
12064
12376
|
"name": ${JSON.stringify(name)},
|
|
@@ -12106,7 +12418,7 @@ var STARTERS = {
|
|
|
12106
12418
|
files: (dir) => [
|
|
12107
12419
|
{
|
|
12108
12420
|
content: page("API Reference", "Explore the API.", "# API Reference\n\nYour OpenAPI spec renders at [`/api`](/api). Point `openapi.sources` at your own spec in `blume.config.ts`."),
|
|
12109
|
-
path:
|
|
12421
|
+
path: join33(dir, "index.mdx")
|
|
12110
12422
|
}
|
|
12111
12423
|
]
|
|
12112
12424
|
},
|
|
@@ -12121,7 +12433,7 @@ var STARTERS = {
|
|
|
12121
12433
|
files: (dir) => [
|
|
12122
12434
|
{
|
|
12123
12435
|
content: page("Introduction", "Welcome to your new Blume docs.", "# Introduction\n\nWrite your docs here, and log releases under `changelog/`."),
|
|
12124
|
-
path:
|
|
12436
|
+
path: join33(dir, "index.mdx")
|
|
12125
12437
|
},
|
|
12126
12438
|
{
|
|
12127
12439
|
content: `---
|
|
@@ -12132,7 +12444,7 @@ date: 2026-01-01
|
|
|
12132
12444
|
|
|
12133
12445
|
The first release. Edit \`${dir}/changelog/v1-0-0.mdx\` or add new entries beside it.
|
|
12134
12446
|
`,
|
|
12135
|
-
path:
|
|
12447
|
+
path: join33(dir, "changelog", "v1-0-0.mdx")
|
|
12136
12448
|
}
|
|
12137
12449
|
]
|
|
12138
12450
|
},
|
|
@@ -12145,7 +12457,7 @@ The first release. Edit \`${dir}/changelog/v1-0-0.mdx\` or add new entries besid
|
|
|
12145
12457
|
Welcome to **Blume** — markdown-first docs powered by Astro and Vite.
|
|
12146
12458
|
|
|
12147
12459
|
Edit \`${dir}/index.mdx\` to get started, then run \`blume dev\`.`),
|
|
12148
|
-
path:
|
|
12460
|
+
path: join33(dir, "index.mdx")
|
|
12149
12461
|
}
|
|
12150
12462
|
]
|
|
12151
12463
|
},
|
|
@@ -12156,11 +12468,11 @@ Edit \`${dir}/index.mdx\` to get started, then run \`blume dev\`.`),
|
|
|
12156
12468
|
content: page("Introduction", "Get started with the SDK.", `# Introduction
|
|
12157
12469
|
|
|
12158
12470
|
Install the SDK and make your first call. See [Installation](/installation).`),
|
|
12159
|
-
path:
|
|
12471
|
+
path: join33(dir, "index.mdx")
|
|
12160
12472
|
},
|
|
12161
12473
|
{
|
|
12162
12474
|
content: page("Installation", "Install the SDK.", "# Installation\n\n```package-install\nyour-sdk\n```"),
|
|
12163
|
-
path:
|
|
12475
|
+
path: join33(dir, "installation.mdx")
|
|
12164
12476
|
}
|
|
12165
12477
|
]
|
|
12166
12478
|
}
|
|
@@ -12207,7 +12519,7 @@ var initCommand = defineCommand7({
|
|
|
12207
12519
|
async run({ args }) {
|
|
12208
12520
|
const root = process.cwd();
|
|
12209
12521
|
const contentDir = args["content-dir"] ?? "docs";
|
|
12210
|
-
if (
|
|
12522
|
+
if (isAbsolute9(contentDir) || relative18(root, join33(root, contentDir)).startsWith("..")) {
|
|
12211
12523
|
logger.error(`Invalid --content-dir "${contentDir}" (must be a path inside the project).`);
|
|
12212
12524
|
process.exit(1);
|
|
12213
12525
|
}
|
|
@@ -12222,9 +12534,9 @@ var initCommand = defineCommand7({
|
|
|
12222
12534
|
process.exit(1);
|
|
12223
12535
|
}
|
|
12224
12536
|
const starter = STARTERS[template];
|
|
12225
|
-
const createdPackage = await writeFileSafe(
|
|
12226
|
-
await writeFileSafe(
|
|
12227
|
-
await Promise.all(starter.files(contentDir).map((file) => writeFileSafe(
|
|
12537
|
+
const createdPackage = await writeFileSafe(join33(root, "package.json"), packageTemplate(toPackageName(basename4(root)), getBlumeVersion()));
|
|
12538
|
+
await writeFileSafe(join33(root, "blume.config.ts"), starter.config);
|
|
12539
|
+
await Promise.all(starter.files(contentDir).map((file) => writeFileSafe(join33(root, file.path), file.content)));
|
|
12228
12540
|
const ignored = await ensureGitignore(root, [".blume/", "dist/"]);
|
|
12229
12541
|
if (ignored.length > 0) {
|
|
12230
12542
|
logger.success(`Added ${ignored.join(", ")} to .gitignore`);
|
|
@@ -12266,14 +12578,14 @@ import { defineCommand as defineCommand8 } from "citty";
|
|
|
12266
12578
|
|
|
12267
12579
|
// src/migrate/fumadocs/index.ts
|
|
12268
12580
|
import { existsSync as existsSync24 } from "node:fs";
|
|
12269
|
-
import { mkdir as mkdir8, readFile as
|
|
12270
|
-
import { dirname as dirname16, join as
|
|
12581
|
+
import { mkdir as mkdir8, readFile as readFile19, rename as rename3, rm as rm3, writeFile as writeFile12 } from "node:fs/promises";
|
|
12582
|
+
import { dirname as dirname16, join as join36, relative as relative19 } from "pathe";
|
|
12271
12583
|
import { glob as glob8 } from "tinyglobby";
|
|
12272
12584
|
|
|
12273
12585
|
// src/migrate/fumadocs/config.ts
|
|
12274
12586
|
import { existsSync as existsSync21 } from "node:fs";
|
|
12275
|
-
import { readFile as
|
|
12276
|
-
import { basename as basename5, dirname as dirname14, join as
|
|
12587
|
+
import { readFile as readFile18 } from "node:fs/promises";
|
|
12588
|
+
import { basename as basename5, dirname as dirname14, join as join34 } from "pathe";
|
|
12277
12589
|
var SOURCE_FILES = [
|
|
12278
12590
|
"lib/source.ts",
|
|
12279
12591
|
"app/source.ts",
|
|
@@ -12303,7 +12615,7 @@ var GENERIC_NAMES = new Set([
|
|
|
12303
12615
|
var gitRepoRoot = (start) => {
|
|
12304
12616
|
let dir = start;
|
|
12305
12617
|
for (;; ) {
|
|
12306
|
-
if (existsSync21(
|
|
12618
|
+
if (existsSync21(join34(dir, ".git"))) {
|
|
12307
12619
|
return dir;
|
|
12308
12620
|
}
|
|
12309
12621
|
const parent = dirname14(dir);
|
|
@@ -12315,12 +12627,12 @@ var gitRepoRoot = (start) => {
|
|
|
12315
12627
|
};
|
|
12316
12628
|
var bareName = (name) => name.includes("/") ? name.slice(name.lastIndexOf("/") + 1) : name;
|
|
12317
12629
|
var readTitle = async (root) => {
|
|
12318
|
-
const packageJson =
|
|
12630
|
+
const packageJson = join34(root, "package.json");
|
|
12319
12631
|
if (!existsSync21(packageJson)) {
|
|
12320
12632
|
return "Documentation";
|
|
12321
12633
|
}
|
|
12322
12634
|
try {
|
|
12323
|
-
const parsed = JSON.parse(await
|
|
12635
|
+
const parsed = JSON.parse(await readFile18(packageJson, "utf-8"));
|
|
12324
12636
|
const { name } = parsed;
|
|
12325
12637
|
if (typeof name !== "string" || !name.trim()) {
|
|
12326
12638
|
return "Documentation";
|
|
@@ -12341,11 +12653,11 @@ var readTitle = async (root) => {
|
|
|
12341
12653
|
};
|
|
12342
12654
|
var scrapeBaseUrl = async (root) => {
|
|
12343
12655
|
for (const candidate of SOURCE_FILES) {
|
|
12344
|
-
const file =
|
|
12656
|
+
const file = join34(root, candidate);
|
|
12345
12657
|
if (!existsSync21(file)) {
|
|
12346
12658
|
continue;
|
|
12347
12659
|
}
|
|
12348
|
-
const base = BASE_URL.exec(await
|
|
12660
|
+
const base = BASE_URL.exec(await readFile18(file, "utf-8"))?.groups?.base;
|
|
12349
12661
|
if (base) {
|
|
12350
12662
|
return base;
|
|
12351
12663
|
}
|
|
@@ -12620,7 +12932,7 @@ var normalizeFumadocsPageMeta = (value) => {
|
|
|
12620
12932
|
// src/migrate/fumadocs/groups.ts
|
|
12621
12933
|
import { existsSync as existsSync23, statSync as statSync2 } from "node:fs";
|
|
12622
12934
|
import { mkdir as mkdir7, rename as rename2, writeFile as writeFile11 } from "node:fs/promises";
|
|
12623
|
-
import { basename as basename6, join as
|
|
12935
|
+
import { basename as basename6, join as join35 } from "pathe";
|
|
12624
12936
|
|
|
12625
12937
|
// src/migrate/fumadocs/meta.ts
|
|
12626
12938
|
var SEPARATOR = /^---(?<label>.*)---$/u;
|
|
@@ -12765,16 +13077,16 @@ var isDirectory = (path) => {
|
|
|
12765
13077
|
}
|
|
12766
13078
|
};
|
|
12767
13079
|
var resolveEntry = (docsDir, name) => {
|
|
12768
|
-
if (!isInsideRoot2(docsDir,
|
|
13080
|
+
if (!isInsideRoot2(docsDir, join35(docsDir, name))) {
|
|
12769
13081
|
return null;
|
|
12770
13082
|
}
|
|
12771
13083
|
for (const ext of PAGE_EXTS) {
|
|
12772
|
-
const file =
|
|
13084
|
+
const file = join35(docsDir, `${name}${ext}`);
|
|
12773
13085
|
if (existsSync23(file)) {
|
|
12774
13086
|
return { kind: "file", path: file };
|
|
12775
13087
|
}
|
|
12776
13088
|
}
|
|
12777
|
-
const folder =
|
|
13089
|
+
const folder = join35(docsDir, name);
|
|
12778
13090
|
return isDirectory(folder) ? { kind: "folder", path: folder } : null;
|
|
12779
13091
|
};
|
|
12780
13092
|
var humanize2 = (name) => name.split(WORD_SPLIT3).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
@@ -12809,7 +13121,7 @@ var moveItemIntoGroup = async (item, docsDir, groupDir, label, warnings) => {
|
|
|
12809
13121
|
warnings.push(`Sidebar entry "${item.name}" in section "${label}" matched no page or folder; skipped.`);
|
|
12810
13122
|
return null;
|
|
12811
13123
|
}
|
|
12812
|
-
const dest =
|
|
13124
|
+
const dest = join35(groupDir, basename6(resolved.path));
|
|
12813
13125
|
if (existsSync23(dest)) {
|
|
12814
13126
|
warnings.push(`Skipped moving "${item.name}" into section "${label}" (target already exists).`);
|
|
12815
13127
|
return null;
|
|
@@ -12837,7 +13149,7 @@ var reshapeSection = async (section, docsDir, order, warnings) => {
|
|
|
12837
13149
|
}
|
|
12838
13150
|
return;
|
|
12839
13151
|
}
|
|
12840
|
-
const groupDir =
|
|
13152
|
+
const groupDir = join35(docsDir, `(${section.label})`);
|
|
12841
13153
|
const sectionKeys = [];
|
|
12842
13154
|
for (const item of section.items) {
|
|
12843
13155
|
const key = await moveItemIntoGroup(item, docsDir, groupDir, section.label, warnings);
|
|
@@ -12850,7 +13162,7 @@ var reshapeSection = async (section, docsDir, order, warnings) => {
|
|
|
12850
13162
|
}
|
|
12851
13163
|
order.push(section.label);
|
|
12852
13164
|
if (sectionKeys.length > 1) {
|
|
12853
|
-
await writeFile11(
|
|
13165
|
+
await writeFile11(join35(groupDir, "meta.ts"), renderMetaModule({ pages: sectionKeys }), "utf-8");
|
|
12854
13166
|
}
|
|
12855
13167
|
};
|
|
12856
13168
|
var reshapeFumadocsGroups = async (structure, docsDir) => {
|
|
@@ -12883,7 +13195,7 @@ var FUMADOCS_LEFTOVERS = [
|
|
|
12883
13195
|
];
|
|
12884
13196
|
var movePage = async (abs, base, root) => {
|
|
12885
13197
|
const rel = relative19(base, abs);
|
|
12886
|
-
const dest =
|
|
13198
|
+
const dest = join36(root, "docs", rel);
|
|
12887
13199
|
if (existsSync24(dest)) {
|
|
12888
13200
|
return {
|
|
12889
13201
|
includeWarnings: [],
|
|
@@ -12893,7 +13205,7 @@ var movePage = async (abs, base, root) => {
|
|
|
12893
13205
|
unsupported: []
|
|
12894
13206
|
};
|
|
12895
13207
|
}
|
|
12896
|
-
const raw = await
|
|
13208
|
+
const raw = await readFile19(abs, "utf-8");
|
|
12897
13209
|
const included = await inlineFumadocsIncludes(raw, {
|
|
12898
13210
|
filePath: abs,
|
|
12899
13211
|
root: base
|
|
@@ -12930,12 +13242,12 @@ var writeMeta = async (dest, meta, rel, warnings) => {
|
|
|
12930
13242
|
};
|
|
12931
13243
|
var convertMeta = async (abs, base, root) => {
|
|
12932
13244
|
const rel = relative19(base, abs);
|
|
12933
|
-
const raw = await
|
|
13245
|
+
const raw = await readFile19(abs, "utf-8");
|
|
12934
13246
|
let parsed;
|
|
12935
13247
|
try {
|
|
12936
13248
|
parsed = JSON.parse(raw);
|
|
12937
13249
|
} catch {
|
|
12938
|
-
const dest2 =
|
|
13250
|
+
const dest2 = join36(root, "docs", rel);
|
|
12939
13251
|
if (existsSync24(dest2)) {
|
|
12940
13252
|
return [`Skipped ${rel} (target already exists)`];
|
|
12941
13253
|
}
|
|
@@ -12946,8 +13258,8 @@ var convertMeta = async (abs, base, root) => {
|
|
|
12946
13258
|
];
|
|
12947
13259
|
}
|
|
12948
13260
|
const dir = dirname16(rel) === "." ? "" : dirname16(rel);
|
|
12949
|
-
const docsDir =
|
|
12950
|
-
const dest =
|
|
13261
|
+
const docsDir = join36(root, "docs", dir);
|
|
13262
|
+
const dest = join36(docsDir, "meta.ts");
|
|
12951
13263
|
const structure = parseFumadocsPages(parsed.pages);
|
|
12952
13264
|
if (structure.hasSections && !existsSync24(dest)) {
|
|
12953
13265
|
const self = translateFumadocsSelfMeta(parsed);
|
|
@@ -12996,7 +13308,7 @@ var summarizePages = (results) => {
|
|
|
12996
13308
|
};
|
|
12997
13309
|
};
|
|
12998
13310
|
var cleanupSourceDirs = async (root) => {
|
|
12999
|
-
const docs =
|
|
13311
|
+
const docs = join36(root, "content", "docs");
|
|
13000
13312
|
if (existsSync24(docs)) {
|
|
13001
13313
|
const remaining = await glob8(["**/*"], { cwd: docs, dot: true });
|
|
13002
13314
|
if (remaining.length > 0) {
|
|
@@ -13006,7 +13318,7 @@ var cleanupSourceDirs = async (root) => {
|
|
|
13006
13318
|
}
|
|
13007
13319
|
await rm3(docs, { force: true, recursive: true });
|
|
13008
13320
|
}
|
|
13009
|
-
const content =
|
|
13321
|
+
const content = join36(root, "content");
|
|
13010
13322
|
if (existsSync24(content)) {
|
|
13011
13323
|
const remaining = await glob8(["**/*"], { cwd: content, dot: true });
|
|
13012
13324
|
if (remaining.length === 0) {
|
|
@@ -13017,7 +13329,7 @@ var cleanupSourceDirs = async (root) => {
|
|
|
13017
13329
|
};
|
|
13018
13330
|
var migrateFumadocsProject = async (root) => {
|
|
13019
13331
|
const { config, warnings: configWarnings } = await loadFumadocsConfig(root);
|
|
13020
|
-
const base =
|
|
13332
|
+
const base = join36(root, SOURCE_DIR);
|
|
13021
13333
|
if (!existsSync24(base)) {
|
|
13022
13334
|
await writeBlumeConfig(root, config);
|
|
13023
13335
|
return {
|
|
@@ -13077,9 +13389,41 @@ var migrateFumadocsProject = async (root) => {
|
|
|
13077
13389
|
|
|
13078
13390
|
// src/migrate/mintlify/index.ts
|
|
13079
13391
|
import { existsSync as existsSync25 } from "node:fs";
|
|
13080
|
-
import { mkdir as mkdir9, readFile as
|
|
13081
|
-
import { dirname as dirname17, join as
|
|
13392
|
+
import { mkdir as mkdir9, readFile as readFile20, rename as rename4, rm as rm4, stat as stat2, writeFile as writeFile13 } from "node:fs/promises";
|
|
13393
|
+
import { dirname as dirname17, join as join37 } from "pathe";
|
|
13082
13394
|
import { glob as glob9 } from "tinyglobby";
|
|
13395
|
+
var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
13396
|
+
var hasFontFamily = (value) => {
|
|
13397
|
+
const object = asRecord(value);
|
|
13398
|
+
if (!object) {
|
|
13399
|
+
return false;
|
|
13400
|
+
}
|
|
13401
|
+
const named = (child) => typeof asRecord(child)?.family === "string";
|
|
13402
|
+
return typeof object.family === "string" || named(object.heading) || named(object.body);
|
|
13403
|
+
};
|
|
13404
|
+
var droppedChromeWarnings = (spec, config) => {
|
|
13405
|
+
const warnings = [];
|
|
13406
|
+
const navbar = asRecord(spec.navbar);
|
|
13407
|
+
if (navbar && (navbar.links || navbar.primary)) {
|
|
13408
|
+
warnings.push("Header links (navbar.links/navbar.primary) have no blume.config equivalent and were dropped; re-add them with navigation.tabs or a Header layout override.");
|
|
13409
|
+
}
|
|
13410
|
+
if (asRecord(spec.footer)?.socials) {
|
|
13411
|
+
warnings.push("Footer social links (footer.socials) have no blume.config equivalent and were dropped; add them with a Footer layout override.");
|
|
13412
|
+
}
|
|
13413
|
+
if (hasFontFamily(spec.fonts ?? spec.font) && !config.theme?.fonts) {
|
|
13414
|
+
warnings.push("docs.json font family isn't in Blume's curated Google Fonts set; set theme.fonts to a supported slug or add @font-face rules in theme.css.");
|
|
13415
|
+
}
|
|
13416
|
+
return warnings;
|
|
13417
|
+
};
|
|
13418
|
+
var droppedRedirectWarnings = (spec) => {
|
|
13419
|
+
const { dropped } = partitionMintlifyRedirects(spec);
|
|
13420
|
+
if (dropped.length === 0) {
|
|
13421
|
+
return [];
|
|
13422
|
+
}
|
|
13423
|
+
return [
|
|
13424
|
+
`Dropped ${dropped.length} dynamic redirect(s) Blume can't model as static path-to-path (${dropped.join(", ")}); re-add them as host-level rules (e.g. _redirects or vercel.json).`
|
|
13425
|
+
];
|
|
13426
|
+
};
|
|
13083
13427
|
var prune = (value) => {
|
|
13084
13428
|
if (Array.isArray(value)) {
|
|
13085
13429
|
return value.map(prune);
|
|
@@ -13108,13 +13452,13 @@ var writeBlumeConfig2 = async (root, config) => {
|
|
|
13108
13452
|
|
|
13109
13453
|
export default defineConfig(${JSON.stringify(prune(config), null, 2)});
|
|
13110
13454
|
`;
|
|
13111
|
-
await writeFile13(
|
|
13455
|
+
await writeFile13(join37(root, "blume.config.ts"), body, "utf-8");
|
|
13112
13456
|
};
|
|
13113
13457
|
var relocateAssets = async (root, segments) => {
|
|
13114
13458
|
const served = [];
|
|
13115
13459
|
const moved = [];
|
|
13116
13460
|
for (const segment of segments) {
|
|
13117
|
-
const source =
|
|
13461
|
+
const source = join37(root, segment);
|
|
13118
13462
|
if (!existsSync25(source) || segment === "public") {
|
|
13119
13463
|
continue;
|
|
13120
13464
|
}
|
|
@@ -13123,11 +13467,11 @@ var relocateAssets = async (root, segments) => {
|
|
|
13123
13467
|
served.push(segment);
|
|
13124
13468
|
continue;
|
|
13125
13469
|
}
|
|
13126
|
-
const dest =
|
|
13470
|
+
const dest = join37(root, "public", segment);
|
|
13127
13471
|
if (existsSync25(dest)) {
|
|
13128
13472
|
continue;
|
|
13129
13473
|
}
|
|
13130
|
-
await mkdir9(
|
|
13474
|
+
await mkdir9(join37(root, "public"), { recursive: true });
|
|
13131
13475
|
await rename4(source, dest);
|
|
13132
13476
|
moved.push(segment);
|
|
13133
13477
|
}
|
|
@@ -13148,7 +13492,7 @@ var applyRelocatedAssets = (config, assets, warnings) => {
|
|
|
13148
13492
|
}
|
|
13149
13493
|
};
|
|
13150
13494
|
var cleanupSnippets = async (root, kept, warnings) => {
|
|
13151
|
-
const dir =
|
|
13495
|
+
const dir = join37(root, "snippets");
|
|
13152
13496
|
if (!existsSync25(dir)) {
|
|
13153
13497
|
return;
|
|
13154
13498
|
}
|
|
@@ -13169,11 +13513,11 @@ var cleanupSnippets = async (root, kept, warnings) => {
|
|
|
13169
13513
|
};
|
|
13170
13514
|
var migrateMintlifyProject = async (root) => {
|
|
13171
13515
|
const warnings = [];
|
|
13172
|
-
const configFile = existsSync25(
|
|
13516
|
+
const configFile = existsSync25(join37(root, "docs.json")) ? join37(root, "docs.json") : join37(root, "mint.json");
|
|
13173
13517
|
let config;
|
|
13174
13518
|
if (existsSync25(configFile)) {
|
|
13175
13519
|
config = await loadMintlifyConfig(root, configFile);
|
|
13176
|
-
const spec = JSON.parse(await
|
|
13520
|
+
const spec = JSON.parse(await readFile20(configFile, "utf-8"));
|
|
13177
13521
|
const i18n = mintlifyI18n(spec);
|
|
13178
13522
|
if (i18n) {
|
|
13179
13523
|
config.i18n = i18n;
|
|
@@ -13182,6 +13526,12 @@ var migrateMintlifyProject = async (root) => {
|
|
|
13182
13526
|
}
|
|
13183
13527
|
warnings.push(`Mapped ${i18n.locales.length} languages to i18n.locales (default: ${i18n.defaultLocale}); review the locale labels.`);
|
|
13184
13528
|
}
|
|
13529
|
+
const openapiSources = config.openapi?.sources ?? [];
|
|
13530
|
+
if (openapiSources.length > 0) {
|
|
13531
|
+
warnings.push(`Mapped ${openapiSources.length} OpenAPI spec source(s) to openapi.sources (native reference renderer); verify each spec path or URL resolves.`);
|
|
13532
|
+
}
|
|
13533
|
+
warnings.push(...droppedChromeWarnings(spec, config));
|
|
13534
|
+
warnings.push(...droppedRedirectWarnings(spec));
|
|
13185
13535
|
} else {
|
|
13186
13536
|
warnings.push("No docs.json or mint.json found; writing a default config.");
|
|
13187
13537
|
config = { content: { root: "." }, title: "Documentation" };
|
|
@@ -13204,7 +13554,7 @@ var migrateMintlifyProject = async (root) => {
|
|
|
13204
13554
|
const unsupported = new Set;
|
|
13205
13555
|
const keptComponents = new Set;
|
|
13206
13556
|
for (const file of files) {
|
|
13207
|
-
const raw = await
|
|
13557
|
+
const raw = await readFile20(file, "utf-8");
|
|
13208
13558
|
const result = await transformMintlifyContent(raw, {
|
|
13209
13559
|
filePath: file,
|
|
13210
13560
|
root,
|
|
@@ -13239,7 +13589,7 @@ var migrateMintlifyProject = async (root) => {
|
|
|
13239
13589
|
warnings.push(`Dropped unsupported page frontmatter keys: ${[...removedKeys].join(", ")}.`);
|
|
13240
13590
|
}
|
|
13241
13591
|
if (unsupported.size > 0) {
|
|
13242
|
-
warnings.push(`Components without a Blume equivalent need manual review
|
|
13592
|
+
warnings.push(`Components without a Blume equivalent need manual review: ${[...unsupported].join(", ")}.`);
|
|
13243
13593
|
}
|
|
13244
13594
|
warnings.push("Review blume.config.ts; navigation, theme, and chrome were mapped from docs.json.");
|
|
13245
13595
|
return { moved, warnings };
|
|
@@ -13247,8 +13597,8 @@ var migrateMintlifyProject = async (root) => {
|
|
|
13247
13597
|
|
|
13248
13598
|
// src/migrate/nextra/index.ts
|
|
13249
13599
|
import { existsSync as existsSync26 } from "node:fs";
|
|
13250
|
-
import { mkdir as mkdir10, readFile as
|
|
13251
|
-
import { basename as basename7, dirname as dirname18, extname as extname8, join as
|
|
13600
|
+
import { mkdir as mkdir10, readFile as readFile21, rename as rename5, rm as rm5, writeFile as writeFile14 } from "node:fs/promises";
|
|
13601
|
+
import { basename as basename7, dirname as dirname18, extname as extname8, join as join38, relative as relative20 } from "pathe";
|
|
13252
13602
|
import { glob as glob10 } from "tinyglobby";
|
|
13253
13603
|
|
|
13254
13604
|
// src/migrate/nextra/content.ts
|
|
@@ -13530,7 +13880,7 @@ var planMetas = (metas, index) => {
|
|
|
13530
13880
|
plan.metaByDir.set(dir, conversion.folderMeta);
|
|
13531
13881
|
plan.consumedMetas.push(meta.abs);
|
|
13532
13882
|
for (const [slug, title] of Object.entries(conversion.folderTitles)) {
|
|
13533
|
-
plan.folderTitleByDir.set(normalizeDir(
|
|
13883
|
+
plan.folderTitleByDir.set(normalizeDir(join38(dir, slug)), title);
|
|
13534
13884
|
}
|
|
13535
13885
|
for (const [slug, label] of Object.entries(conversion.pageLabels)) {
|
|
13536
13886
|
const pageAbs = index.pagesByDir.get(dir)?.get(slug);
|
|
@@ -13555,11 +13905,11 @@ var planMetas = (metas, index) => {
|
|
|
13555
13905
|
};
|
|
13556
13906
|
var movePage2 = async (abs, options) => {
|
|
13557
13907
|
const rel = relative20(options.base, abs);
|
|
13558
|
-
const dest =
|
|
13908
|
+
const dest = join38(options.root, "docs", rel);
|
|
13559
13909
|
if (existsSync26(dest)) {
|
|
13560
13910
|
return { moved: 0, removed: [], skipped: rel, unsupported: [] };
|
|
13561
13911
|
}
|
|
13562
|
-
const raw = await
|
|
13912
|
+
const raw = await readFile21(abs, "utf-8");
|
|
13563
13913
|
const text = rewriteNextraCallouts(stripNextraImports(raw));
|
|
13564
13914
|
const unsupported = unsupportedNextraComponents(text);
|
|
13565
13915
|
const parsed = frontmatter_default(text);
|
|
@@ -13608,7 +13958,7 @@ var writeFolderMetas = async (root, plan) => {
|
|
|
13608
13958
|
if (Object.keys(finalMeta).length === 0) {
|
|
13609
13959
|
return;
|
|
13610
13960
|
}
|
|
13611
|
-
const dest =
|
|
13961
|
+
const dest = join38(root, "docs", dir, "meta.ts");
|
|
13612
13962
|
await mkdir10(dirname18(dest), { recursive: true });
|
|
13613
13963
|
await writeFile14(dest, `import { defineMeta } from "blume";
|
|
13614
13964
|
|
|
@@ -13619,7 +13969,7 @@ export default defineMeta(${JSON.stringify(finalMeta, null, 2)});
|
|
|
13619
13969
|
var relocateUnparseableMetas = async (root, metas) => {
|
|
13620
13970
|
const warnings = [];
|
|
13621
13971
|
await Promise.all(metas.map(async ({ abs, rel }) => {
|
|
13622
|
-
const dest =
|
|
13972
|
+
const dest = join38(root, "docs", rel);
|
|
13623
13973
|
if (existsSync26(dest)) {
|
|
13624
13974
|
warnings.push(`Skipped ${rel} (target already exists)`);
|
|
13625
13975
|
return;
|
|
@@ -13632,7 +13982,7 @@ var relocateUnparseableMetas = async (root, metas) => {
|
|
|
13632
13982
|
};
|
|
13633
13983
|
var buildConfig = (tabs) => tabs.length > 0 ? { navigation: { tabs }, title: "Documentation" } : { title: "Documentation" };
|
|
13634
13984
|
var migrateNextraProject = async (root) => {
|
|
13635
|
-
const sourceDir = SOURCE_DIRS.find((dir) => existsSync26(
|
|
13985
|
+
const sourceDir = SOURCE_DIRS.find((dir) => existsSync26(join38(root, dir)));
|
|
13636
13986
|
if (!sourceDir) {
|
|
13637
13987
|
await writeBlumeConfig(root, { title: "Documentation" });
|
|
13638
13988
|
return {
|
|
@@ -13642,7 +13992,7 @@ var migrateNextraProject = async (root) => {
|
|
|
13642
13992
|
]
|
|
13643
13993
|
};
|
|
13644
13994
|
}
|
|
13645
|
-
const base =
|
|
13995
|
+
const base = join38(root, sourceDir);
|
|
13646
13996
|
const pageFiles = await glob10([PAGE_GLOB2], {
|
|
13647
13997
|
absolute: true,
|
|
13648
13998
|
cwd: base,
|
|
@@ -13657,7 +14007,7 @@ var migrateNextraProject = async (root) => {
|
|
|
13657
14007
|
const metas = await Promise.all(metaFiles.map(async (abs) => ({
|
|
13658
14008
|
abs,
|
|
13659
14009
|
ext: extname8(abs),
|
|
13660
|
-
raw: await
|
|
14010
|
+
raw: await readFile21(abs, "utf-8"),
|
|
13661
14011
|
rel: relative20(base, abs)
|
|
13662
14012
|
})));
|
|
13663
14013
|
const plan = planMetas(metas, index);
|
|
@@ -13684,14 +14034,14 @@ var migrateNextraProject = async (root) => {
|
|
|
13684
14034
|
|
|
13685
14035
|
// src/migrate/starlight/index.ts
|
|
13686
14036
|
import { existsSync as existsSync28 } from "node:fs";
|
|
13687
|
-
import { readFile as
|
|
13688
|
-
import { join as
|
|
14037
|
+
import { readFile as readFile23, writeFile as writeFile15 } from "node:fs/promises";
|
|
14038
|
+
import { join as join40 } from "pathe";
|
|
13689
14039
|
import { glob as glob11 } from "tinyglobby";
|
|
13690
14040
|
|
|
13691
14041
|
// src/migrate/starlight/config.ts
|
|
13692
14042
|
import { existsSync as existsSync27 } from "node:fs";
|
|
13693
|
-
import { readFile as
|
|
13694
|
-
import { join as
|
|
14043
|
+
import { readFile as readFile22 } from "node:fs/promises";
|
|
14044
|
+
import { join as join39 } from "pathe";
|
|
13695
14045
|
var CONFIG_FILES = [
|
|
13696
14046
|
"astro.config.mjs",
|
|
13697
14047
|
"astro.config.mts",
|
|
@@ -13722,7 +14072,7 @@ var extractStarlightOptions = (source) => {
|
|
|
13722
14072
|
return isLiteralObject(parsed) ? parsed : "unparseable";
|
|
13723
14073
|
};
|
|
13724
14074
|
var loadStarlightConfig = async (root) => {
|
|
13725
|
-
const file = CONFIG_FILES.map((name) =>
|
|
14075
|
+
const file = CONFIG_FILES.map((name) => join39(root, name)).find((path) => existsSync27(path));
|
|
13726
14076
|
if (!file) {
|
|
13727
14077
|
return {
|
|
13728
14078
|
options: {},
|
|
@@ -13731,7 +14081,7 @@ var loadStarlightConfig = async (root) => {
|
|
|
13731
14081
|
]
|
|
13732
14082
|
};
|
|
13733
14083
|
}
|
|
13734
|
-
const source = await
|
|
14084
|
+
const source = await readFile22(file, "utf-8");
|
|
13735
14085
|
const result = extractStarlightOptions(source);
|
|
13736
14086
|
if (result === "missing") {
|
|
13737
14087
|
return {
|
|
@@ -14129,7 +14479,7 @@ var starlightI18n = (options) => {
|
|
|
14129
14479
|
// src/migrate/starlight/index.ts
|
|
14130
14480
|
var CONTENT_DIR = "src/content/docs";
|
|
14131
14481
|
var transformPage = async (file) => {
|
|
14132
|
-
const raw = await
|
|
14482
|
+
const raw = await readFile23(file, "utf-8");
|
|
14133
14483
|
let text = stripStarlightImports(raw);
|
|
14134
14484
|
text = rewriteStarlightAsides(text);
|
|
14135
14485
|
text = rewriteStarlightComponents(text);
|
|
@@ -14151,7 +14501,7 @@ var migrateStarlightProject = async (root) => {
|
|
|
14151
14501
|
config.i18n = i18n;
|
|
14152
14502
|
warnings.push(`Mapped ${i18n.locales.length} locale(s) to i18n (default: ${i18n.defaultLocale}); review the locale labels.`);
|
|
14153
14503
|
}
|
|
14154
|
-
const base =
|
|
14504
|
+
const base = join40(root, CONTENT_DIR);
|
|
14155
14505
|
if (!existsSync28(base)) {
|
|
14156
14506
|
await writeBlumeConfig(root, config);
|
|
14157
14507
|
return {
|
|
@@ -14243,7 +14593,7 @@ var migrateCommand = defineCommand8({
|
|
|
14243
14593
|
import { existsSync as existsSync29 } from "node:fs";
|
|
14244
14594
|
import { preview } from "astro";
|
|
14245
14595
|
import { defineCommand as defineCommand9 } from "citty";
|
|
14246
|
-
import { join as
|
|
14596
|
+
import { join as join41 } from "pathe";
|
|
14247
14597
|
var previewCommand = defineCommand9({
|
|
14248
14598
|
args: {
|
|
14249
14599
|
host: { description: "Network host to bind.", type: "string" },
|
|
@@ -14257,7 +14607,7 @@ var previewCommand = defineCommand9({
|
|
|
14257
14607
|
const root = process.cwd();
|
|
14258
14608
|
const { config } = await loadConfig(root);
|
|
14259
14609
|
const context = resolveProjectContext(root, config);
|
|
14260
|
-
if (!existsSync29(
|
|
14610
|
+
if (!existsSync29(join41(context.outDir, "astro.config.mjs"))) {
|
|
14261
14611
|
logger.error("No build found. Run `blume build` first.");
|
|
14262
14612
|
process.exit(1);
|
|
14263
14613
|
}
|
|
@@ -14275,7 +14625,7 @@ var previewCommand = defineCommand9({
|
|
|
14275
14625
|
// src/cli/commands/sync.ts
|
|
14276
14626
|
import { rm as rm6 } from "node:fs/promises";
|
|
14277
14627
|
import { defineCommand as defineCommand10 } from "citty";
|
|
14278
|
-
import { join as
|
|
14628
|
+
import { join as join42 } from "pathe";
|
|
14279
14629
|
var syncCommand = defineCommand10({
|
|
14280
14630
|
args: {
|
|
14281
14631
|
force: {
|
|
@@ -14297,7 +14647,7 @@ var syncCommand = defineCommand10({
|
|
|
14297
14647
|
if (args.force) {
|
|
14298
14648
|
const { config } = await loadConfig(root);
|
|
14299
14649
|
const context = resolveProjectContext(root, config);
|
|
14300
|
-
await rm6(
|
|
14650
|
+
await rm6(join42(context.outDir, "cache"), { force: true, recursive: true });
|
|
14301
14651
|
logger.info("Cleared source cache.");
|
|
14302
14652
|
}
|
|
14303
14653
|
await prepareProject({
|
|
@@ -14314,11 +14664,11 @@ var syncCommand = defineCommand10({
|
|
|
14314
14664
|
// src/cli/commands/validate.ts
|
|
14315
14665
|
import { existsSync as existsSync31 } from "node:fs";
|
|
14316
14666
|
import { defineCommand as defineCommand11 } from "citty";
|
|
14317
|
-
import { join as
|
|
14667
|
+
import { join as join44 } from "pathe";
|
|
14318
14668
|
|
|
14319
14669
|
// src/core/links.ts
|
|
14320
14670
|
import { existsSync as existsSync30 } from "node:fs";
|
|
14321
|
-
import { basename as basename8, join as
|
|
14671
|
+
import { basename as basename8, join as join43 } from "pathe";
|
|
14322
14672
|
var HTTP = /^https?:\/\//iu;
|
|
14323
14673
|
var PROTOCOL_RELATIVE = /^\/\//u;
|
|
14324
14674
|
var SCHEME = /^[a-z][a-z0-9+.-]*:/iu;
|
|
@@ -14331,10 +14681,10 @@ var STATUS_GONE = 410;
|
|
|
14331
14681
|
var STATUS_METHOD_NOT_ALLOWED = 405;
|
|
14332
14682
|
var STATUS_NOT_IMPLEMENTED = 501;
|
|
14333
14683
|
var assetIsPresent = (resolved, ctx) => {
|
|
14334
|
-
if (ctx.publicDir && existsSync30(
|
|
14684
|
+
if (ctx.publicDir && existsSync30(join43(ctx.publicDir, resolved))) {
|
|
14335
14685
|
return true;
|
|
14336
14686
|
}
|
|
14337
|
-
return ctx.assetMounts.some((mount) => (resolved === mount.url || resolved.startsWith(`${mount.url}/`)) && existsSync30(
|
|
14687
|
+
return ctx.assetMounts.some((mount) => (resolved === mount.url || resolved.startsWith(`${mount.url}/`)) && existsSync30(join43(mount.dir, resolved.slice(mount.url.length))));
|
|
14338
14688
|
};
|
|
14339
14689
|
var isIndexPage = (page2) => {
|
|
14340
14690
|
const ref = page2.source?.ref ?? page2.sourcePath ?? "";
|
|
@@ -14579,7 +14929,7 @@ var validateCommand = defineCommand11({
|
|
|
14579
14929
|
try {
|
|
14580
14930
|
const project = await scanProject(root, { mode: "build" });
|
|
14581
14931
|
diagnostics.push(...project.diagnostics);
|
|
14582
|
-
const publicDir =
|
|
14932
|
+
const publicDir = join44(root, "public");
|
|
14583
14933
|
diagnostics.push(...await validateLinks(project.graph, {
|
|
14584
14934
|
assetMounts: resolveAssetMounts(root, project.config.content.assets),
|
|
14585
14935
|
checkExternal: Boolean(args.external),
|
|
@@ -14644,5 +14994,5 @@ process.on("unhandledRejection", (error) => {
|
|
|
14644
14994
|
});
|
|
14645
14995
|
runMain(main);
|
|
14646
14996
|
|
|
14647
|
-
//# debugId=
|
|
14997
|
+
//# debugId=A4775073F9612C8B64756E2164756E21
|
|
14648
14998
|
//# sourceMappingURL=index.js.map
|