blume 0.6.0 → 0.6.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 +384 -254
- package/dist/cli/index.js.map +11 -10
- package/dist/types/core/config-input.d.ts +759 -0
- package/dist/types/core/config.d.ts +126 -3
- package/dist/types/core/schema.d.ts +6 -23
- package/dist/types/index.d.ts +2 -1
- package/docs/advanced/changelog.mdx +10 -2
- package/docs/configuration/index.mdx +0 -2
- package/docs/content/syntax.mdx +4 -8
- package/package.json +1 -1
- package/src/astro/generate.ts +36 -11
- package/src/astro/templates.ts +66 -5
- package/src/cli/commands/build.ts +26 -1
- package/src/components/content/Update.astro +12 -2
- package/src/components/content/changelog-element.ts +62 -0
- package/src/components/layout/RootLayout.astro +31 -8
- package/src/core/config-input.ts +933 -0
- package/src/core/config.ts +126 -3
- package/src/core/schema.ts +6 -13
- package/src/deploy/adapter-output.ts +82 -0
- package/src/index.ts +1 -1
- package/src/markdown/index.ts +28 -30
- package/src/markdown/math.ts +3 -2
- package/src/registry/eject.ts +21 -14
- package/src/theme/entry.ts +7 -3
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
|
|
516
|
+
import { existsSync as existsSync15 } from "node:fs";
|
|
517
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 join24 } from "pathe";
|
|
521
521
|
|
|
522
522
|
// src/deploy/xml.ts
|
|
523
523
|
var escapeXml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
@@ -844,6 +844,42 @@ var serverFeatures = (config) => {
|
|
|
844
844
|
return features;
|
|
845
845
|
};
|
|
846
846
|
|
|
847
|
+
// src/deploy/adapter-output.ts
|
|
848
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
849
|
+
import { cp, mkdir as mkdir2, rm } from "node:fs/promises";
|
|
850
|
+
import { dirname as dirname4, join as join6 } from "pathe";
|
|
851
|
+
var ADAPTER_OUTPUT_PATHS = {
|
|
852
|
+
netlify: ".netlify",
|
|
853
|
+
vercel: ".vercel/output"
|
|
854
|
+
};
|
|
855
|
+
var deployStaticDir = (config, context) => {
|
|
856
|
+
const { adapter, output } = config.deployment;
|
|
857
|
+
if (output === "server" && adapter === "vercel") {
|
|
858
|
+
return join6(context.root, ".vercel", "output", "static");
|
|
859
|
+
}
|
|
860
|
+
return context.distDir ?? join6(context.root, "dist");
|
|
861
|
+
};
|
|
862
|
+
var surfaceAdapterOutput = async (config, context) => {
|
|
863
|
+
const { adapter, output } = config.deployment;
|
|
864
|
+
if (output !== "server" || !adapter) {
|
|
865
|
+
return { moved: false };
|
|
866
|
+
}
|
|
867
|
+
const rel = ADAPTER_OUTPUT_PATHS[adapter];
|
|
868
|
+
if (!rel) {
|
|
869
|
+
return { moved: false };
|
|
870
|
+
}
|
|
871
|
+
const from = join6(context.outDir, rel);
|
|
872
|
+
const to = join6(context.root, rel);
|
|
873
|
+
if (!existsSync4(from)) {
|
|
874
|
+
return { moved: false };
|
|
875
|
+
}
|
|
876
|
+
await mkdir2(dirname4(to), { recursive: true });
|
|
877
|
+
await rm(to, { force: true, recursive: true });
|
|
878
|
+
await cp(from, to, { recursive: true });
|
|
879
|
+
await rm(from, { force: true, recursive: true });
|
|
880
|
+
return { from, ignore: `${rel.split("/")[0]}/`, moved: true, to };
|
|
881
|
+
};
|
|
882
|
+
|
|
847
883
|
// src/deploy/redirects.ts
|
|
848
884
|
var buildNetlifyRedirects = (redirects) => `${redirects.map((redirect) => `${redirect.from} ${redirect.to} ${redirect.status}`).join(`
|
|
849
885
|
`)}
|
|
@@ -920,7 +956,7 @@ ${urls.join(`
|
|
|
920
956
|
};
|
|
921
957
|
|
|
922
958
|
// src/search/build.ts
|
|
923
|
-
import { join as
|
|
959
|
+
import { join as join7 } from "pathe";
|
|
924
960
|
var buildSearchIndex = async (outDir) => {
|
|
925
961
|
const pagefind = await import("pagefind");
|
|
926
962
|
const { index } = await pagefind.createIndex({});
|
|
@@ -928,7 +964,7 @@ var buildSearchIndex = async (outDir) => {
|
|
|
928
964
|
throw new Error("Failed to create Pagefind index.");
|
|
929
965
|
}
|
|
930
966
|
const result = await index.addDirectory({ path: outDir });
|
|
931
|
-
await index.writeFiles({ outputPath:
|
|
967
|
+
await index.writeFiles({ outputPath: join7(outDir, "pagefind") });
|
|
932
968
|
await pagefind.close();
|
|
933
969
|
return result.page_count;
|
|
934
970
|
};
|
|
@@ -2976,17 +3012,17 @@ var syncSearchProvider = async (project, reporter) => {
|
|
|
2976
3012
|
|
|
2977
3013
|
// src/cli/dev-lock.ts
|
|
2978
3014
|
import {
|
|
2979
|
-
existsSync as
|
|
3015
|
+
existsSync as existsSync6,
|
|
2980
3016
|
mkdirSync,
|
|
2981
3017
|
readFileSync as readFileSync2,
|
|
2982
3018
|
rmSync,
|
|
2983
3019
|
writeFileSync
|
|
2984
3020
|
} from "node:fs";
|
|
2985
|
-
import { join as
|
|
3021
|
+
import { join as join9 } from "pathe";
|
|
2986
3022
|
|
|
2987
3023
|
// src/core/project.ts
|
|
2988
|
-
import { existsSync as
|
|
2989
|
-
import { isAbsolute, join as
|
|
3024
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
3025
|
+
import { isAbsolute, join as join8, resolve as resolve2 } from "pathe";
|
|
2990
3026
|
var CONFIG_FILENAMES = [
|
|
2991
3027
|
"blume.config.ts",
|
|
2992
3028
|
"blume.config.mjs",
|
|
@@ -2996,22 +3032,22 @@ var THEME_FILENAMES = ["theme.css"];
|
|
|
2996
3032
|
var COMPONENTS_FILENAMES = ["components.tsx", "components.ts"];
|
|
2997
3033
|
var firstExisting = (root, names) => {
|
|
2998
3034
|
for (const name of names) {
|
|
2999
|
-
const candidate =
|
|
3000
|
-
if (
|
|
3035
|
+
const candidate = join8(root, name);
|
|
3036
|
+
if (existsSync5(candidate)) {
|
|
3001
3037
|
return candidate;
|
|
3002
3038
|
}
|
|
3003
3039
|
}
|
|
3004
3040
|
return null;
|
|
3005
3041
|
};
|
|
3006
3042
|
var findConfigFile = (root) => firstExisting(root, CONFIG_FILENAMES);
|
|
3007
|
-
var resolveRuntimeDir = (root, runtimeDir = ".blume") => isAbsolute(runtimeDir) ? runtimeDir :
|
|
3043
|
+
var resolveRuntimeDir = (root, runtimeDir = ".blume") => isAbsolute(runtimeDir) ? runtimeDir : join8(resolve2(root), runtimeDir);
|
|
3008
3044
|
var resolveProjectContext = (root, config, options) => {
|
|
3009
3045
|
const absoluteRoot = resolve2(root);
|
|
3010
|
-
const contentRoot = isAbsolute(config.content.root) ? config.content.root :
|
|
3011
|
-
const pagesPath =
|
|
3012
|
-
const pagesRoot =
|
|
3046
|
+
const contentRoot = isAbsolute(config.content.root) ? config.content.root : join8(absoluteRoot, config.content.root);
|
|
3047
|
+
const pagesPath = join8(absoluteRoot, config.content.pages);
|
|
3048
|
+
const pagesRoot = existsSync5(pagesPath) ? pagesPath : null;
|
|
3013
3049
|
const outDir = resolveRuntimeDir(absoluteRoot, options?.runtimeDir);
|
|
3014
|
-
const distDir = options?.runtimeDir ?
|
|
3050
|
+
const distDir = options?.runtimeDir ? join8(outDir, "dist") : join8(absoluteRoot, "dist");
|
|
3015
3051
|
return {
|
|
3016
3052
|
componentsFile: firstExisting(absoluteRoot, COMPONENTS_FILENAMES),
|
|
3017
3053
|
configFile: findConfigFile(absoluteRoot),
|
|
@@ -3025,7 +3061,7 @@ var resolveProjectContext = (root, config, options) => {
|
|
|
3025
3061
|
};
|
|
3026
3062
|
|
|
3027
3063
|
// src/cli/dev-lock.ts
|
|
3028
|
-
var lockPath = (outDir) =>
|
|
3064
|
+
var lockPath = (outDir) => join9(outDir, "dev.lock");
|
|
3029
3065
|
var isValidPid = (pid) => typeof pid === "number" && Number.isInteger(pid) && pid > 0;
|
|
3030
3066
|
var parseLock = (raw) => {
|
|
3031
3067
|
let data;
|
|
@@ -3055,7 +3091,7 @@ var isProcessAlive = (pid) => {
|
|
|
3055
3091
|
};
|
|
3056
3092
|
var readDevLock = (outDir) => {
|
|
3057
3093
|
const path = lockPath(outDir);
|
|
3058
|
-
if (!
|
|
3094
|
+
if (!existsSync6(path)) {
|
|
3059
3095
|
return null;
|
|
3060
3096
|
}
|
|
3061
3097
|
const lock = parseLock(readFileSync2(path, "utf-8"));
|
|
@@ -3069,7 +3105,7 @@ var writeLock = (outDir, port) => {
|
|
|
3069
3105
|
};
|
|
3070
3106
|
var ownsLock = (outDir) => {
|
|
3071
3107
|
const path = lockPath(outDir);
|
|
3072
|
-
if (!
|
|
3108
|
+
if (!existsSync6(path)) {
|
|
3073
3109
|
return false;
|
|
3074
3110
|
}
|
|
3075
3111
|
try {
|
|
@@ -3109,19 +3145,19 @@ var refuseIfDevRunning = (root, action, runtimeDir) => {
|
|
|
3109
3145
|
};
|
|
3110
3146
|
|
|
3111
3147
|
// src/astro/generate.ts
|
|
3112
|
-
import { existsSync as
|
|
3148
|
+
import { existsSync as existsSync10, readFileSync as readFileSync6, realpathSync } from "node:fs";
|
|
3113
3149
|
import {
|
|
3114
3150
|
lstat,
|
|
3115
|
-
mkdir as
|
|
3151
|
+
mkdir as mkdir5,
|
|
3116
3152
|
readFile as readFile10,
|
|
3117
3153
|
rename,
|
|
3118
|
-
rm,
|
|
3154
|
+
rm as rm2,
|
|
3119
3155
|
symlink,
|
|
3120
3156
|
writeFile as writeFile5
|
|
3121
3157
|
} from "node:fs/promises";
|
|
3122
3158
|
import { createRequire as createRequire5 } from "node:module";
|
|
3123
3159
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
3124
|
-
import { basename as basename2, dirname as
|
|
3160
|
+
import { basename as basename2, dirname as dirname8, join as join17, normalize as normalize3, relative as relative7 } from "pathe";
|
|
3125
3161
|
import { glob as glob4 } from "tinyglobby";
|
|
3126
3162
|
|
|
3127
3163
|
// src/ai/ask-data.ts
|
|
@@ -3360,8 +3396,8 @@ var validateUsedComponents = (pages, extraTags, registryNames) => {
|
|
|
3360
3396
|
};
|
|
3361
3397
|
|
|
3362
3398
|
// src/core/component-overrides.ts
|
|
3363
|
-
import { existsSync as
|
|
3364
|
-
import { dirname as
|
|
3399
|
+
import { existsSync as existsSync7 } from "node:fs";
|
|
3400
|
+
import { dirname as dirname5, extname, isAbsolute as isAbsolute2, resolve as resolve3 } from "pathe";
|
|
3365
3401
|
import ts from "typescript";
|
|
3366
3402
|
var GROUPS = ["mdx", "layout", "islands"];
|
|
3367
3403
|
var FRAMEWORK_BY_EXT = {
|
|
@@ -3449,7 +3485,7 @@ var findDefaultExportObject = (sourceFile) => {
|
|
|
3449
3485
|
var probeExtension = (base) => {
|
|
3450
3486
|
for (const extension of COMPONENT_EXTS) {
|
|
3451
3487
|
const candidate = `${base}.${extension}`;
|
|
3452
|
-
if (
|
|
3488
|
+
if (existsSync7(candidate)) {
|
|
3453
3489
|
return candidate;
|
|
3454
3490
|
}
|
|
3455
3491
|
}
|
|
@@ -3596,7 +3632,7 @@ var analyzeComponentOverrides = (source, filePath) => {
|
|
|
3596
3632
|
return result;
|
|
3597
3633
|
}
|
|
3598
3634
|
const imports = collectImports(sourceFile);
|
|
3599
|
-
const dir =
|
|
3635
|
+
const dir = dirname5(filePath);
|
|
3600
3636
|
for (const property of object.properties) {
|
|
3601
3637
|
if (!ts.isPropertyAssignment(property)) {
|
|
3602
3638
|
continue;
|
|
@@ -3891,10 +3927,10 @@ var validateNavStructure = (navigation, pages) => [
|
|
|
3891
3927
|
];
|
|
3892
3928
|
|
|
3893
3929
|
// src/core/tsconfig-aliases.ts
|
|
3894
|
-
import { existsSync as
|
|
3930
|
+
import { existsSync as existsSync8, readFileSync as readFileSync3, statSync } from "node:fs";
|
|
3895
3931
|
import { createRequire as createRequire3 } from "node:module";
|
|
3896
3932
|
import { pathToFileURL } from "node:url";
|
|
3897
|
-
import { dirname as
|
|
3933
|
+
import { dirname as dirname6, isAbsolute as isAbsolute3, join as join10, resolve as resolve4 } from "pathe";
|
|
3898
3934
|
var stripJsonComments = (text) => {
|
|
3899
3935
|
let out = "";
|
|
3900
3936
|
let inString = false;
|
|
@@ -3957,7 +3993,7 @@ var resolveExtends = (spec, fromDir) => {
|
|
|
3957
3993
|
return candidates.find(isFile) ?? null;
|
|
3958
3994
|
}
|
|
3959
3995
|
try {
|
|
3960
|
-
const require_ = createRequire3(pathToFileURL(
|
|
3996
|
+
const require_ = createRequire3(pathToFileURL(join10(fromDir, "_.js")).href);
|
|
3961
3997
|
for (const sub of [`${spec}/tsconfig.json`, spec]) {
|
|
3962
3998
|
try {
|
|
3963
3999
|
return require_.resolve(sub);
|
|
@@ -3967,7 +4003,7 @@ var resolveExtends = (spec, fromDir) => {
|
|
|
3967
4003
|
return null;
|
|
3968
4004
|
};
|
|
3969
4005
|
var loadPaths = (file, seen) => {
|
|
3970
|
-
if (seen.has(file) || !
|
|
4006
|
+
if (seen.has(file) || !existsSync8(file)) {
|
|
3971
4007
|
return null;
|
|
3972
4008
|
}
|
|
3973
4009
|
seen.add(file);
|
|
@@ -3979,7 +4015,7 @@ var loadPaths = (file, seen) => {
|
|
|
3979
4015
|
if (options.paths && typeof options.paths === "object") {
|
|
3980
4016
|
const baseUrl = typeof options.baseUrl === "string" ? options.baseUrl : ".";
|
|
3981
4017
|
return {
|
|
3982
|
-
baseDir: resolve4(
|
|
4018
|
+
baseDir: resolve4(dirname6(file), baseUrl),
|
|
3983
4019
|
paths: options.paths
|
|
3984
4020
|
};
|
|
3985
4021
|
}
|
|
@@ -3988,7 +4024,7 @@ var loadPaths = (file, seen) => {
|
|
|
3988
4024
|
if (typeof base !== "string") {
|
|
3989
4025
|
continue;
|
|
3990
4026
|
}
|
|
3991
|
-
const resolved = resolveExtends(base,
|
|
4027
|
+
const resolved = resolveExtends(base, dirname6(file));
|
|
3992
4028
|
const found = resolved ? loadPaths(resolved, seen) : null;
|
|
3993
4029
|
if (found) {
|
|
3994
4030
|
return found;
|
|
@@ -4009,7 +4045,7 @@ var toAlias = (key, value, baseDir) => {
|
|
|
4009
4045
|
return { find, replacement: resolve4(baseDir, target) };
|
|
4010
4046
|
};
|
|
4011
4047
|
var resolveTsconfigAliases = (root) => {
|
|
4012
|
-
const entry = ["tsconfig.json", "jsconfig.json"].map((name) =>
|
|
4048
|
+
const entry = ["tsconfig.json", "jsconfig.json"].map((name) => join10(root, name)).find((file) => existsSync8(file));
|
|
4013
4049
|
if (!entry) {
|
|
4014
4050
|
return {};
|
|
4015
4051
|
}
|
|
@@ -4107,11 +4143,11 @@ var hasScalarReferences = (config) => resolveReferences(config).some((ref) => re
|
|
|
4107
4143
|
|
|
4108
4144
|
// src/openapi/scalar.ts
|
|
4109
4145
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
4110
|
-
import { isAbsolute as isAbsolute5, join as
|
|
4146
|
+
import { isAbsolute as isAbsolute5, join as join12 } from "pathe";
|
|
4111
4147
|
|
|
4112
4148
|
// src/astro/templates.ts
|
|
4113
|
-
import { existsSync as
|
|
4114
|
-
import { dirname as
|
|
4149
|
+
import { existsSync as existsSync9, readFileSync as readFileSync4 } from "node:fs";
|
|
4150
|
+
import { dirname as dirname7, isAbsolute as isAbsolute4, join as join11, relative as relative4 } from "pathe";
|
|
4115
4151
|
|
|
4116
4152
|
// src/core/sources/watch.ts
|
|
4117
4153
|
var BLUME_IGNORE_DIRS = [
|
|
@@ -4293,7 +4329,7 @@ var WORKSPACE_MARKERS = [
|
|
|
4293
4329
|
"yarn.lock"
|
|
4294
4330
|
];
|
|
4295
4331
|
var hasWorkspacesField = (pkgPath) => {
|
|
4296
|
-
if (!
|
|
4332
|
+
if (!existsSync9(pkgPath)) {
|
|
4297
4333
|
return false;
|
|
4298
4334
|
}
|
|
4299
4335
|
try {
|
|
@@ -4303,14 +4339,14 @@ var hasWorkspacesField = (pkgPath) => {
|
|
|
4303
4339
|
return false;
|
|
4304
4340
|
}
|
|
4305
4341
|
};
|
|
4306
|
-
var hasWorkspaceMarker = (dir) => hasWorkspacesField(
|
|
4342
|
+
var hasWorkspaceMarker = (dir) => hasWorkspacesField(join11(dir, "package.json")) || WORKSPACE_MARKERS.some((marker) => existsSync9(join11(dir, marker)));
|
|
4307
4343
|
var findWorkspaceRoot = (start) => {
|
|
4308
4344
|
let dir = start;
|
|
4309
4345
|
for (;; ) {
|
|
4310
4346
|
if (hasWorkspaceMarker(dir)) {
|
|
4311
4347
|
return dir;
|
|
4312
4348
|
}
|
|
4313
|
-
const parent =
|
|
4349
|
+
const parent = dirname7(dir);
|
|
4314
4350
|
if (parent === dir) {
|
|
4315
4351
|
return start;
|
|
4316
4352
|
}
|
|
@@ -4425,9 +4461,7 @@ var astroConfigTemplate = (options) => {
|
|
|
4425
4461
|
const twoslashTransformer = "transformerTwoslash({ explicitTrigger: true }), ";
|
|
4426
4462
|
const integrations = [
|
|
4427
4463
|
`mdx({ processor: blumeMdxProcessor(${JSON.stringify({
|
|
4428
|
-
headingAnchors: config.markdown.headingAnchors
|
|
4429
|
-
inline: config.markdown.code.inline,
|
|
4430
|
-
math: config.markdown.math
|
|
4464
|
+
headingAnchors: config.markdown.headingAnchors
|
|
4431
4465
|
})}) })`
|
|
4432
4466
|
];
|
|
4433
4467
|
if (needsReact) {
|
|
@@ -4455,8 +4489,7 @@ export default defineConfig({
|
|
|
4455
4489
|
integrations: [${integrations.join(", ")}],
|
|
4456
4490
|
markdown: {
|
|
4457
4491
|
processor: blumeMarkdownProcessor(${JSON.stringify({
|
|
4458
|
-
headingAnchors: config.markdown.headingAnchors
|
|
4459
|
-
inline: config.markdown.code.inline
|
|
4492
|
+
headingAnchors: config.markdown.headingAnchors
|
|
4460
4493
|
})}),
|
|
4461
4494
|
shikiConfig: {
|
|
4462
4495
|
themes: {
|
|
@@ -4506,14 +4539,14 @@ export default defineConfig({
|
|
|
4506
4539
|
// self-hosted fonts) -- pure noise the loader logs as "No entry type
|
|
4507
4540
|
// found". Vite appends this to its default ignores.
|
|
4508
4541
|
watch: {
|
|
4509
|
-
ignored: ${JSON.stringify([
|
|
4542
|
+
ignored: ${JSON.stringify([join11(context.outDir, ".astro", "**")])},
|
|
4510
4543
|
},
|
|
4511
4544
|
},
|
|
4512
4545
|
},
|
|
4513
4546
|
});
|
|
4514
4547
|
`;
|
|
4515
4548
|
};
|
|
4516
|
-
var stagedContentDir = (outDir) =>
|
|
4549
|
+
var stagedContentDir = (outDir) => join11(outDir, "content");
|
|
4517
4550
|
var contentConfigTemplate = (options) => {
|
|
4518
4551
|
const { context, config } = options;
|
|
4519
4552
|
const stagedBase = options.stagedBase ?? stagedContentDir(context.outDir);
|
|
@@ -5203,6 +5236,20 @@ const slugify = (text) =>
|
|
|
5203
5236
|
text.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") ||
|
|
5204
5237
|
"update";
|
|
5205
5238
|
|
|
5239
|
+
// The major of a version's embedded semver (\`1.2.3\` -> 1, \`pkg@2.0.0\` -> 2), or
|
|
5240
|
+
// null when there is no full major.minor.patch to key on. Drives the changelog's
|
|
5241
|
+
// group-by-major pagination, so it tolerates the scoped tags monorepos publish.
|
|
5242
|
+
const majorVersion = (version) => {
|
|
5243
|
+
const match = /(\\d+)\\.\\d+\\.\\d+/.exec(String(version ?? ""));
|
|
5244
|
+
return match ? Number(match[1]) : null;
|
|
5245
|
+
};
|
|
5246
|
+
|
|
5247
|
+
// Map each entry to its own generated page so the timeline heading can deep-link
|
|
5248
|
+
// to it. The collection entry id matches the route manifest's \`entryId\`.
|
|
5249
|
+
const routeByEntry = new Map(
|
|
5250
|
+
data.routes.map((route) => [route.entryId, route.path])
|
|
5251
|
+
);
|
|
5252
|
+
|
|
5206
5253
|
const changelogEntries = [
|
|
5207
5254
|
...(await getCollection("docs")),${stagedSpread}
|
|
5208
5255
|
]
|
|
@@ -5224,8 +5271,10 @@ const items = await Promise.all(
|
|
|
5224
5271
|
return {
|
|
5225
5272
|
Content: (await render(entry)).Content,
|
|
5226
5273
|
date: formatDate(entryDate(entry)),
|
|
5274
|
+
href: routeByEntry.get(entry.id) ?? null,
|
|
5227
5275
|
id: slugify(label),
|
|
5228
5276
|
label,
|
|
5277
|
+
major: majorVersion(entry.data.changelog?.version),
|
|
5229
5278
|
tags: entry.data.changelog?.category
|
|
5230
5279
|
? [entry.data.changelog.category]
|
|
5231
5280
|
: [],
|
|
@@ -5233,6 +5282,19 @@ const items = await Promise.all(
|
|
|
5233
5282
|
})
|
|
5234
5283
|
);
|
|
5235
5284
|
|
|
5285
|
+
// A changelog is semver-paginated only when every visible release parses as
|
|
5286
|
+
// semver and they span more than one major line. Older majors then collapse
|
|
5287
|
+
// into groups the reader reveals one at a time; otherwise the timeline is flat.
|
|
5288
|
+
const majors = items.every((item) => item.major !== null)
|
|
5289
|
+
? [...new Set(items.map((item) => item.major))].toSorted((a, b) => b - a)
|
|
5290
|
+
: [];
|
|
5291
|
+
const paginate = majors.length > 1;
|
|
5292
|
+
const majorGroups = majors.map((major) => ({
|
|
5293
|
+
items: items.filter((item) => item.major === major),
|
|
5294
|
+
label: major + ".x",
|
|
5295
|
+
major,
|
|
5296
|
+
}));
|
|
5297
|
+
|
|
5236
5298
|
const headings = items.map((item) => ({
|
|
5237
5299
|
depth: 2,
|
|
5238
5300
|
slug: item.id,
|
|
@@ -5264,6 +5326,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
5264
5326
|
}}
|
|
5265
5327
|
headings={headings}
|
|
5266
5328
|
toc={data.config.toc}
|
|
5329
|
+
contentLayout="bare"
|
|
5267
5330
|
themeMode={data.config.theme.mode}
|
|
5268
5331
|
fontCssVars={data.fontCssVars}
|
|
5269
5332
|
searchEnabled={data.config.search.enabled}
|
|
@@ -5282,16 +5345,50 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
5282
5345
|
{
|
|
5283
5346
|
items.length === 0 ? (
|
|
5284
5347
|
<p>No changelog entries yet.</p>
|
|
5348
|
+
) : paginate ? (
|
|
5349
|
+
<blume-changelog class="not-prose mt-8 block">
|
|
5350
|
+
{majorGroups[0].items.map(({ Content, href, id, label, date, tags }) => (
|
|
5351
|
+
<Update description={date} href={href} id={id} label={label} tags={tags}>
|
|
5352
|
+
<Content />
|
|
5353
|
+
</Update>
|
|
5354
|
+
))}
|
|
5355
|
+
{majorGroups.slice(1).map((group) => (
|
|
5356
|
+
<section
|
|
5357
|
+
aria-label={group.label + " releases"}
|
|
5358
|
+
data-changelog-label={group.label}
|
|
5359
|
+
data-changelog-major={group.major}
|
|
5360
|
+
>
|
|
5361
|
+
{group.items.map(({ Content, href, id, label, date, tags }) => (
|
|
5362
|
+
<Update description={date} href={href} id={id} label={label} tags={tags}>
|
|
5363
|
+
<Content />
|
|
5364
|
+
</Update>
|
|
5365
|
+
))}
|
|
5366
|
+
</section>
|
|
5367
|
+
))}
|
|
5368
|
+
<div class="mt-10 flex justify-center">
|
|
5369
|
+
<button
|
|
5370
|
+
class="inline-flex items-center gap-2 rounded-full border border-border bg-background px-4 py-2 font-medium text-muted-foreground text-sm transition-colors hover:bg-muted hover:text-foreground"
|
|
5371
|
+
data-changelog-more
|
|
5372
|
+
hidden
|
|
5373
|
+
type="button"
|
|
5374
|
+
>
|
|
5375
|
+
Show older releases
|
|
5376
|
+
</button>
|
|
5377
|
+
</div>
|
|
5378
|
+
</blume-changelog>
|
|
5285
5379
|
) : (
|
|
5286
5380
|
<div class="not-prose mt-8">
|
|
5287
|
-
{items.map(({ Content, id, label, date, tags }) => (
|
|
5288
|
-
<Update description={date} id={id} label={label} tags={tags}>
|
|
5381
|
+
{items.map(({ Content, href, id, label, date, tags }) => (
|
|
5382
|
+
<Update description={date} href={href} id={id} label={label} tags={tags}>
|
|
5289
5383
|
<Content />
|
|
5290
5384
|
</Update>
|
|
5291
5385
|
))}
|
|
5292
5386
|
</div>
|
|
5293
5387
|
)
|
|
5294
5388
|
}
|
|
5389
|
+
<script>
|
|
5390
|
+
import "blume/components/content/changelog-element.ts";
|
|
5391
|
+
</script>
|
|
5295
5392
|
</LayoutComponent>
|
|
5296
5393
|
`;
|
|
5297
5394
|
};
|
|
@@ -5525,7 +5622,7 @@ var specConfiguration = async (spec, root) => {
|
|
|
5525
5622
|
if (URL_SPEC.test(spec)) {
|
|
5526
5623
|
return { config: { url: spec } };
|
|
5527
5624
|
}
|
|
5528
|
-
const absolute = isAbsolute5(spec) ? spec :
|
|
5625
|
+
const absolute = isAbsolute5(spec) ? spec : join12(root, spec);
|
|
5529
5626
|
try {
|
|
5530
5627
|
return { config: { content: await readFile5(absolute, "utf-8") } };
|
|
5531
5628
|
} catch {
|
|
@@ -5583,8 +5680,8 @@ var buildReferenceFiles = async (options) => {
|
|
|
5583
5680
|
};
|
|
5584
5681
|
|
|
5585
5682
|
// src/core/sources/cache.ts
|
|
5586
|
-
import { mkdir as
|
|
5587
|
-
import { join as
|
|
5683
|
+
import { mkdir as mkdir3, readFile as readFile6, writeFile as writeFile3 } from "node:fs/promises";
|
|
5684
|
+
import { join as join13 } from "pathe";
|
|
5588
5685
|
var hashText = (text) => {
|
|
5589
5686
|
let hash = 5381;
|
|
5590
5687
|
for (let i = 0;i < text.length; i += 1) {
|
|
@@ -5611,7 +5708,7 @@ var pollingWatch = (load2, intervalSeconds) => (onChange) => {
|
|
|
5611
5708
|
return () => clearInterval(timer);
|
|
5612
5709
|
};
|
|
5613
5710
|
var snapshotCache = (cacheDir) => {
|
|
5614
|
-
const file =
|
|
5711
|
+
const file = join13(cacheDir, "entries.json");
|
|
5615
5712
|
return {
|
|
5616
5713
|
read: async () => {
|
|
5617
5714
|
try {
|
|
@@ -5622,7 +5719,7 @@ var snapshotCache = (cacheDir) => {
|
|
|
5622
5719
|
},
|
|
5623
5720
|
write: async (entries) => {
|
|
5624
5721
|
try {
|
|
5625
|
-
await
|
|
5722
|
+
await mkdir3(cacheDir, { recursive: true });
|
|
5626
5723
|
await writeFile3(file, `${JSON.stringify(entries)}
|
|
5627
5724
|
`, "utf-8");
|
|
5628
5725
|
} catch {}
|
|
@@ -5726,10 +5823,10 @@ var extractOperations = (document, baseRoute) => {
|
|
|
5726
5823
|
};
|
|
5727
5824
|
|
|
5728
5825
|
// src/openapi/parse.ts
|
|
5729
|
-
import { mkdir as
|
|
5826
|
+
import { mkdir as mkdir4, readFile as readFile7, writeFile as writeFile4 } from "node:fs/promises";
|
|
5730
5827
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
5731
5828
|
import { normalize as normalize2, upgrade } from "@scalar/openapi-parser";
|
|
5732
|
-
import { isAbsolute as isAbsolute6, join as
|
|
5829
|
+
import { isAbsolute as isAbsolute6, join as join14 } from "pathe";
|
|
5733
5830
|
var URL_SPEC2 = /^https?:\/\//u;
|
|
5734
5831
|
var FETCH_TIMEOUT_MS = 15000;
|
|
5735
5832
|
var MAX_ATTEMPTS = 3;
|
|
@@ -5804,7 +5901,7 @@ var fetchSpecText = async (spec) => {
|
|
|
5804
5901
|
}
|
|
5805
5902
|
throw last.error;
|
|
5806
5903
|
};
|
|
5807
|
-
var cacheFileFor = (cacheDir, spec) =>
|
|
5904
|
+
var cacheFileFor = (cacheDir, spec) => join14(cacheDir, `spec-${hashText(spec)}.cache`);
|
|
5808
5905
|
var readCache = async (file) => {
|
|
5809
5906
|
try {
|
|
5810
5907
|
return await readFile7(file, "utf-8");
|
|
@@ -5814,13 +5911,13 @@ var readCache = async (file) => {
|
|
|
5814
5911
|
};
|
|
5815
5912
|
var writeCache = async (dir, file, text) => {
|
|
5816
5913
|
try {
|
|
5817
|
-
await
|
|
5914
|
+
await mkdir4(dir, { recursive: true });
|
|
5818
5915
|
await writeFile4(file, text, "utf-8");
|
|
5819
5916
|
} catch {}
|
|
5820
5917
|
};
|
|
5821
5918
|
var readSpecText = async (spec, root, options) => {
|
|
5822
5919
|
if (!URL_SPEC2.test(spec)) {
|
|
5823
|
-
const absolute = isAbsolute6(spec) ? spec :
|
|
5920
|
+
const absolute = isAbsolute6(spec) ? spec : join14(root, spec);
|
|
5824
5921
|
return { text: await readFile7(absolute, "utf-8"), warnings: [] };
|
|
5825
5922
|
}
|
|
5826
5923
|
const cacheFile = options.cacheDir ? cacheFileFor(options.cacheDir, spec) : undefined;
|
|
@@ -6422,6 +6519,10 @@ blume-diff {
|
|
|
6422
6519
|
font-size: 0.8125rem;
|
|
6423
6520
|
}
|
|
6424
6521
|
|
|
6522
|
+
.prose :where(td, th) :not(pre) > code {
|
|
6523
|
+
white-space: nowrap;
|
|
6524
|
+
}
|
|
6525
|
+
|
|
6425
6526
|
blume-tabs pre,
|
|
6426
6527
|
.not-prose > div > pre {
|
|
6427
6528
|
background: var(--blume-code-background);
|
|
@@ -6597,9 +6698,9 @@ pre:has(.line.focused):hover .line:not(.focused) {
|
|
|
6597
6698
|
content: none;
|
|
6598
6699
|
}
|
|
6599
6700
|
|
|
6600
|
-
/* Inline code highlighting
|
|
6601
|
-
|
|
6602
|
-
|
|
6701
|
+
/* Inline code highlighting: Shiki colors the tokens of a \`code\`{:lang} snippet
|
|
6702
|
+
via the same dual-theme CSS variables as fenced blocks, keeping the inline
|
|
6703
|
+
pill background. Always on — it only fires on the trailing {:lang} marker. */
|
|
6603
6704
|
.prose code.blume-inline-code span {
|
|
6604
6705
|
color: var(--shiki-light);
|
|
6605
6706
|
}
|
|
@@ -6823,12 +6924,12 @@ export const layoutOverrides = { ...(overrides.layout ?? {})${layoutEntries.leng
|
|
|
6823
6924
|
|
|
6824
6925
|
// src/astro/examples.ts
|
|
6825
6926
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
6826
|
-
import { join as
|
|
6927
|
+
import { join as join16, relative as relative5 } from "pathe";
|
|
6827
6928
|
import { glob as glob2 } from "tinyglobby";
|
|
6828
6929
|
|
|
6829
6930
|
// src/astro/islands.ts
|
|
6830
6931
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
6831
|
-
import { basename, join as
|
|
6932
|
+
import { basename, join as join15 } from "pathe";
|
|
6832
6933
|
import { glob } from "tinyglobby";
|
|
6833
6934
|
var DEFAULT_CLIENT = "visible";
|
|
6834
6935
|
var VALID_MODES = new Set([
|
|
@@ -6857,7 +6958,7 @@ var readClientMode = (source, file, warnings) => {
|
|
|
6857
6958
|
return mode;
|
|
6858
6959
|
};
|
|
6859
6960
|
var discoverIslands = async (root) => {
|
|
6860
|
-
const dir =
|
|
6961
|
+
const dir = join15(root, "islands");
|
|
6861
6962
|
const matches = await glob(["**/*.{jsx,svelte,tsx,vue}"], {
|
|
6862
6963
|
absolute: true,
|
|
6863
6964
|
cwd: dir,
|
|
@@ -6920,7 +7021,7 @@ var splitGlobBase = (pattern) => {
|
|
|
6920
7021
|
};
|
|
6921
7022
|
var discoverExamples = async (root, pattern = "examples") => {
|
|
6922
7023
|
const { base, rest } = GLOB_MAGIC.test(pattern) ? splitGlobBase(pattern) : { base: pattern, rest: DEFAULT_EXAMPLE_GLOB };
|
|
6923
|
-
const dir =
|
|
7024
|
+
const dir = join16(root, base);
|
|
6924
7025
|
const matches = await glob2([rest], {
|
|
6925
7026
|
absolute: true,
|
|
6926
7027
|
cwd: dir,
|
|
@@ -7001,10 +7102,10 @@ var customOgRoutes = (pages, siteTitle) => {
|
|
|
7001
7102
|
};
|
|
7002
7103
|
|
|
7003
7104
|
// src/astro/generate.ts
|
|
7004
|
-
var BLUME_SRC =
|
|
7105
|
+
var BLUME_SRC = join17(packageRoot(), "src");
|
|
7005
7106
|
var canResolveFrom = (fromDir, spec) => {
|
|
7006
7107
|
try {
|
|
7007
|
-
createRequire5(pathToFileURL2(
|
|
7108
|
+
createRequire5(pathToFileURL2(join17(fromDir, "_.js")).href).resolve(spec);
|
|
7008
7109
|
return true;
|
|
7009
7110
|
} catch {
|
|
7010
7111
|
return false;
|
|
@@ -7012,15 +7113,15 @@ var canResolveFrom = (fromDir, spec) => {
|
|
|
7012
7113
|
};
|
|
7013
7114
|
var resolvedAstroPath = (fromDir) => {
|
|
7014
7115
|
try {
|
|
7015
|
-
const pkg = createRequire5(pathToFileURL2(
|
|
7116
|
+
const pkg = createRequire5(pathToFileURL2(join17(fromDir, "_.js")).href).resolve("astro/package.json");
|
|
7016
7117
|
return realpathSync(pkg);
|
|
7017
7118
|
} catch {
|
|
7018
7119
|
return null;
|
|
7019
7120
|
}
|
|
7020
7121
|
};
|
|
7021
7122
|
var blumeDepsDir = (pkgDir = packageRoot()) => {
|
|
7022
|
-
const candidates = [
|
|
7023
|
-
return candidates.find((dir) =>
|
|
7123
|
+
const candidates = [join17(pkgDir, "node_modules"), dirname8(pkgDir)];
|
|
7124
|
+
return candidates.find((dir) => existsSync10(join17(dir, "astro"))) ?? null;
|
|
7024
7125
|
};
|
|
7025
7126
|
var linkDepsJunction = async (link, depsDir) => {
|
|
7026
7127
|
const existing = await lstat(link).catch(() => null);
|
|
@@ -7028,9 +7129,9 @@ var linkDepsJunction = async (link, depsDir) => {
|
|
|
7028
7129
|
if (!existing.isSymbolicLink()) {
|
|
7029
7130
|
return;
|
|
7030
7131
|
}
|
|
7031
|
-
await
|
|
7132
|
+
await rm2(link, { force: true });
|
|
7032
7133
|
}
|
|
7033
|
-
await
|
|
7134
|
+
await mkdir5(dirname8(link), { recursive: true });
|
|
7034
7135
|
await symlink(depsDir, link, "junction");
|
|
7035
7136
|
};
|
|
7036
7137
|
var readPkgVersion = (pkgJsonPath) => {
|
|
@@ -7060,8 +7161,8 @@ var ensureDepsLink = async (outDir, pkgDir = packageRoot()) => {
|
|
|
7060
7161
|
if (blumeAstro && outDirAstro === blumeAstro) {
|
|
7061
7162
|
return null;
|
|
7062
7163
|
}
|
|
7063
|
-
if (
|
|
7064
|
-
await linkDepsJunction(
|
|
7164
|
+
if (existsSync10(join17(depsDir, "@astrojs", "mdx"))) {
|
|
7165
|
+
await linkDepsJunction(join17(outDir, "node_modules"), depsDir);
|
|
7065
7166
|
return null;
|
|
7066
7167
|
}
|
|
7067
7168
|
return astroConflictWarning(blumeAstro, outDirAstro);
|
|
@@ -7098,6 +7199,15 @@ var detectNeedsReact = async (root) => {
|
|
|
7098
7199
|
});
|
|
7099
7200
|
return matches.length > 0;
|
|
7100
7201
|
};
|
|
7202
|
+
var detectUsesMath = async (root) => {
|
|
7203
|
+
const files = await glob4(["**/*.mdx"], {
|
|
7204
|
+
cwd: root,
|
|
7205
|
+
ignore: ["**/node_modules/**", "**/.blume/**", "**/dist/**"],
|
|
7206
|
+
onlyFiles: true
|
|
7207
|
+
});
|
|
7208
|
+
const contents = await Promise.all(files.map((file) => readOptional(join17(root, file))));
|
|
7209
|
+
return contents.some((content) => content.includes("$$"));
|
|
7210
|
+
};
|
|
7101
7211
|
var writeIfChanged = async (path, content) => {
|
|
7102
7212
|
let existing = null;
|
|
7103
7213
|
try {
|
|
@@ -7108,13 +7218,13 @@ var writeIfChanged = async (path, content) => {
|
|
|
7108
7218
|
if (existing === content) {
|
|
7109
7219
|
return false;
|
|
7110
7220
|
}
|
|
7111
|
-
await
|
|
7221
|
+
await mkdir5(dirname8(path), { recursive: true });
|
|
7112
7222
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
7113
7223
|
await writeFile5(tmp, content, "utf-8");
|
|
7114
7224
|
try {
|
|
7115
7225
|
await rename(tmp, path);
|
|
7116
7226
|
} catch (error) {
|
|
7117
|
-
await
|
|
7227
|
+
await rm2(tmp, { force: true });
|
|
7118
7228
|
throw error;
|
|
7119
7229
|
}
|
|
7120
7230
|
return true;
|
|
@@ -7125,7 +7235,7 @@ var pruneOrphans = async (srcDir, written) => {
|
|
|
7125
7235
|
cwd: srcDir,
|
|
7126
7236
|
onlyFiles: true
|
|
7127
7237
|
});
|
|
7128
|
-
await Promise.all(existing.map((path) => normalize3(path)).filter((path) => !written.has(path)).map((path) =>
|
|
7238
|
+
await Promise.all(existing.map((path) => normalize3(path)).filter((path) => !written.has(path)).map((path) => rm2(path, { force: true })));
|
|
7129
7239
|
};
|
|
7130
7240
|
var collectStaged = (project) => {
|
|
7131
7241
|
const staged = new Map;
|
|
@@ -7140,11 +7250,11 @@ var writeStagedContent = async (out, staged) => {
|
|
|
7140
7250
|
const contentDir = stagedContentDir(out);
|
|
7141
7251
|
const written = new Set;
|
|
7142
7252
|
await Promise.all([...staged].map(async ([entryId, text]) => {
|
|
7143
|
-
const path =
|
|
7253
|
+
const path = join17(contentDir, entryId);
|
|
7144
7254
|
written.add(normalize3(path));
|
|
7145
7255
|
await writeIfChanged(path, text);
|
|
7146
7256
|
}));
|
|
7147
|
-
if (
|
|
7257
|
+
if (existsSync10(contentDir)) {
|
|
7148
7258
|
await pruneOrphans(contentDir, written);
|
|
7149
7259
|
}
|
|
7150
7260
|
};
|
|
@@ -7163,9 +7273,9 @@ var resolveLogo = (project) => {
|
|
|
7163
7273
|
if (light && light === dark && light.toLowerCase().endsWith(".svg")) {
|
|
7164
7274
|
const rel = light.replace(/^\//u, "");
|
|
7165
7275
|
const file = [
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
].find((path) =>
|
|
7276
|
+
join17(project.context.root, "public", rel),
|
|
7277
|
+
join17(project.context.root, rel)
|
|
7278
|
+
].find((path) => existsSync10(path));
|
|
7169
7279
|
if (file) {
|
|
7170
7280
|
return { alt, href: brandHref, svg: readFileSync6(file, "utf-8"), text };
|
|
7171
7281
|
}
|
|
@@ -7193,7 +7303,7 @@ var faviconType = (name) => {
|
|
|
7193
7303
|
};
|
|
7194
7304
|
var inlineDataUri = (file, type) => `data:${type};base64,${readFileSync6(file).toString("base64")}`;
|
|
7195
7305
|
var defaultFavicon = () => ({
|
|
7196
|
-
href: inlineDataUri(
|
|
7306
|
+
href: inlineDataUri(join17(BLUME_SRC, "assets", "icon.png"), "image/png"),
|
|
7197
7307
|
type: "image/png"
|
|
7198
7308
|
});
|
|
7199
7309
|
var APPLE_ICON_CANDIDATES = [
|
|
@@ -7205,13 +7315,13 @@ var APPLE_ICON_CANDIDATES = [
|
|
|
7205
7315
|
var resolveIconFile = (project, candidates) => {
|
|
7206
7316
|
const { root } = project.context;
|
|
7207
7317
|
for (const name of candidates) {
|
|
7208
|
-
if (
|
|
7318
|
+
if (existsSync10(join17(root, "public", name))) {
|
|
7209
7319
|
return { href: `/${name}`, type: faviconType(name) };
|
|
7210
7320
|
}
|
|
7211
7321
|
}
|
|
7212
7322
|
for (const name of candidates) {
|
|
7213
|
-
const file =
|
|
7214
|
-
if (
|
|
7323
|
+
const file = join17(root, name);
|
|
7324
|
+
if (existsSync10(file)) {
|
|
7215
7325
|
const type = faviconType(name);
|
|
7216
7326
|
return { href: inlineDataUri(file, type ?? "image/x-icon"), type };
|
|
7217
7327
|
}
|
|
@@ -7339,7 +7449,7 @@ var buildRuntimeData = (project) => {
|
|
|
7339
7449
|
var planMcp = (project, srcDir) => {
|
|
7340
7450
|
const { config } = project;
|
|
7341
7451
|
const { route } = config.mcp;
|
|
7342
|
-
const dir =
|
|
7452
|
+
const dir = join17(srcDir, "blume-mcp");
|
|
7343
7453
|
const base = {
|
|
7344
7454
|
dir,
|
|
7345
7455
|
discoveryPages: [],
|
|
@@ -7363,11 +7473,11 @@ var planMcp = (project, srcDir) => {
|
|
|
7363
7473
|
...base,
|
|
7364
7474
|
discoveryPages: [
|
|
7365
7475
|
{
|
|
7366
|
-
entrypoint:
|
|
7476
|
+
entrypoint: join17(dir, "discovery.ts"),
|
|
7367
7477
|
pattern: "/.well-known/mcp.json"
|
|
7368
7478
|
},
|
|
7369
7479
|
{
|
|
7370
|
-
entrypoint:
|
|
7480
|
+
entrypoint: join17(dir, "server-card.ts"),
|
|
7371
7481
|
pattern: "/.well-known/mcp/server-card.json"
|
|
7372
7482
|
}
|
|
7373
7483
|
],
|
|
@@ -7386,11 +7496,11 @@ var writeMcpFiles = async (project, plan, write) => {
|
|
|
7386
7496
|
version: data.version
|
|
7387
7497
|
};
|
|
7388
7498
|
await Promise.all([
|
|
7389
|
-
write(
|
|
7499
|
+
write(join17(plan.srcDir, "generated", "mcp-data.json"), `${JSON.stringify(data)}
|
|
7390
7500
|
`),
|
|
7391
|
-
write(
|
|
7392
|
-
write(
|
|
7393
|
-
write(
|
|
7501
|
+
write(join17(plan.srcDir, "pages", mcpPageFile(plan.route)), mcpEndpointTemplate(plan.route)),
|
|
7502
|
+
write(join17(plan.dir, "discovery.ts"), staticJsonEndpointTemplate(buildMcpDiscovery(discoveryInput))),
|
|
7503
|
+
write(join17(plan.dir, "server-card.ts"), staticJsonEndpointTemplate(buildMcpServerCard(discoveryInput)))
|
|
7394
7504
|
]);
|
|
7395
7505
|
};
|
|
7396
7506
|
var writeAskFiles = async (project, srcDir, write) => {
|
|
@@ -7400,16 +7510,16 @@ var writeAskFiles = async (project, srcDir, write) => {
|
|
|
7400
7510
|
}
|
|
7401
7511
|
const grounded = ask.provider !== "inkeep";
|
|
7402
7512
|
if (grounded) {
|
|
7403
|
-
await write(
|
|
7513
|
+
await write(join17(srcDir, "generated", "ask-data.json"), `${JSON.stringify(await buildAskData(project))}
|
|
7404
7514
|
`);
|
|
7405
7515
|
}
|
|
7406
|
-
await write(
|
|
7516
|
+
await write(join17(srcDir, "pages", "api", "ask.ts"), askEndpointTemplate(resolveAskBackend(ask), grounded));
|
|
7407
7517
|
};
|
|
7408
7518
|
var writeNotFoundPage = async (write, srcDir, pages, contentPages) => {
|
|
7409
7519
|
if (routeIsTaken(pages, contentPages, "/404")) {
|
|
7410
7520
|
return;
|
|
7411
7521
|
}
|
|
7412
|
-
await write(
|
|
7522
|
+
await write(join17(srcDir, "pages", "404.astro"), notFoundPageTemplate());
|
|
7413
7523
|
};
|
|
7414
7524
|
var shouldGenerateChangelog = (project) => {
|
|
7415
7525
|
const hasChangelog = project.graph.pages.some((page) => page.contentType === "changelog" && !(page.meta.draft || page.meta.sidebar.hidden));
|
|
@@ -7428,12 +7538,12 @@ var buildComponentSlots = async (componentsFile) => {
|
|
|
7428
7538
|
var generateRuntime = async (project) => {
|
|
7429
7539
|
const { context, config } = project;
|
|
7430
7540
|
const out = context.outDir;
|
|
7431
|
-
const srcDir =
|
|
7432
|
-
const dataPath =
|
|
7433
|
-
const themePath =
|
|
7434
|
-
const searchClientPath =
|
|
7435
|
-
const examplesPath =
|
|
7436
|
-
const openapiPath =
|
|
7541
|
+
const srcDir = join17(out, "src");
|
|
7542
|
+
const dataPath = join17(srcDir, "generated", "data.json");
|
|
7543
|
+
const themePath = join17(srcDir, "generated", "app.css");
|
|
7544
|
+
const searchClientPath = join17(srcDir, "generated", "search-client.ts");
|
|
7545
|
+
const examplesPath = join17(srcDir, "generated", "examples.ts");
|
|
7546
|
+
const openapiPath = join17(srcDir, "generated", "openapi.json");
|
|
7437
7547
|
const written = new Set;
|
|
7438
7548
|
const write = (path, content) => {
|
|
7439
7549
|
written.add(normalize3(path));
|
|
@@ -7443,9 +7553,17 @@ var generateRuntime = async (project) => {
|
|
|
7443
7553
|
const askEnabled = config.ai.ask?.enabled ?? false;
|
|
7444
7554
|
const exportPdf = config.export.pdf;
|
|
7445
7555
|
const exportEpub = config.export.epub;
|
|
7446
|
-
const [
|
|
7556
|
+
const [
|
|
7557
|
+
pages,
|
|
7558
|
+
detectedReact,
|
|
7559
|
+
usesMath,
|
|
7560
|
+
userTheme,
|
|
7561
|
+
islandDiscovery,
|
|
7562
|
+
exampleDiscovery
|
|
7563
|
+
] = await Promise.all([
|
|
7447
7564
|
context.pagesRoot ? discoverPages(context.pagesRoot) : Promise.resolve([]),
|
|
7448
7565
|
detectNeedsReact(context.root),
|
|
7566
|
+
detectUsesMath(context.root),
|
|
7449
7567
|
readOptional(context.themeFile),
|
|
7450
7568
|
discoverIslands(context.root),
|
|
7451
7569
|
discoverExamples(context.root, config.examples)
|
|
@@ -7470,7 +7588,7 @@ var generateRuntime = async (project) => {
|
|
|
7470
7588
|
const hasStaged = staged.size > 0;
|
|
7471
7589
|
const hasFilesystemSource = project.sources.some((source) => !source.staged);
|
|
7472
7590
|
const structural = await Promise.all([
|
|
7473
|
-
write(
|
|
7591
|
+
write(join17(out, "astro.config.mjs"), astroConfigTemplate({
|
|
7474
7592
|
aliases: resolveTsconfigAliases(context.root),
|
|
7475
7593
|
config,
|
|
7476
7594
|
contentRoutes: project.manifest.routes.map((route) => route.path),
|
|
@@ -7485,25 +7603,25 @@ var generateRuntime = async (project) => {
|
|
|
7485
7603
|
searchClientPath,
|
|
7486
7604
|
themePath
|
|
7487
7605
|
})),
|
|
7488
|
-
write(
|
|
7489
|
-
write(
|
|
7490
|
-
write(
|
|
7491
|
-
write(
|
|
7606
|
+
write(join17(out, "package.json"), runtimePackageTemplate(runtimeDependencies({ config, needsReact, needsSvelte, needsVue }))),
|
|
7607
|
+
write(join17(out, "tsconfig.json"), runtimeTsconfigTemplate()),
|
|
7608
|
+
write(join17(srcDir, "env.d.ts"), envTemplate()),
|
|
7609
|
+
write(join17(srcDir, "content.config.ts"), contentConfigTemplate({
|
|
7492
7610
|
config,
|
|
7493
7611
|
context,
|
|
7494
7612
|
filesystem: hasFilesystemSource,
|
|
7495
7613
|
staged: hasStaged
|
|
7496
7614
|
})),
|
|
7497
|
-
write(
|
|
7615
|
+
write(join17(srcDir, "pages", "[...slug].astro"), catchAllPageTemplate({
|
|
7498
7616
|
askEnabled,
|
|
7499
7617
|
exportEpub,
|
|
7500
7618
|
exportPdf,
|
|
7501
|
-
mathEnabled:
|
|
7619
|
+
mathEnabled: usesMath,
|
|
7502
7620
|
needsReact
|
|
7503
7621
|
})),
|
|
7504
|
-
write(
|
|
7505
|
-
write(
|
|
7506
|
-
write(
|
|
7622
|
+
write(join17(srcDir, "generated", "components.ts"), slotPlan.module),
|
|
7623
|
+
write(join17(srcDir, "generated", "islands.ts"), islandMapTemplate(islandDiscovery.islands)),
|
|
7624
|
+
write(join17(srcDir, "generated", "examples.ts"), exampleMapTemplate(exampleDiscovery.examples)),
|
|
7507
7625
|
write(themePath, tailwindEntryTemplate({
|
|
7508
7626
|
configTokens: `${buildThemeCss(config.theme)}${buildFontsCss(config.theme.fonts)}`,
|
|
7509
7627
|
sources: [
|
|
@@ -7514,16 +7632,16 @@ var generateRuntime = async (project) => {
|
|
|
7514
7632
|
userTheme
|
|
7515
7633
|
}))
|
|
7516
7634
|
]);
|
|
7517
|
-
await Promise.all(islandDiscovery.islands.map((island) => write(
|
|
7518
|
-
await Promise.all(slotPlan.wrappers.map((wrapper) => write(
|
|
7519
|
-
await Promise.all(exampleDiscovery.examples.map((example) => write(
|
|
7635
|
+
await Promise.all(islandDiscovery.islands.map((island) => write(join17(srcDir, "generated", "islands", `${island.name}.astro`), islandWrapperTemplate(island))));
|
|
7636
|
+
await Promise.all(slotPlan.wrappers.map((wrapper) => write(join17(srcDir, "generated", "component-slots", `${wrapper.name}.astro`), wrapper.content)));
|
|
7637
|
+
await Promise.all(exampleDiscovery.examples.map((example) => write(join17(srcDir, "generated", "examples", `${exampleSlug(example.path)}.astro`), exampleWrapperTemplate(example))));
|
|
7520
7638
|
await writeAskFiles(project, srcDir, write);
|
|
7521
7639
|
await writeMcpFiles(project, mcp, write);
|
|
7522
7640
|
if (config.seo.og.enabled) {
|
|
7523
|
-
await write(
|
|
7641
|
+
await write(join17(srcDir, "pages", "og", "[...slug].png.ts"), ogEndpointTemplate(ogRoutes));
|
|
7524
7642
|
}
|
|
7525
7643
|
if (shouldGenerateChangelog(project)) {
|
|
7526
|
-
await write(
|
|
7644
|
+
await write(join17(srcDir, "pages", "changelog.astro"), changelogIndexTemplate({
|
|
7527
7645
|
askEnabled,
|
|
7528
7646
|
exportEpub,
|
|
7529
7647
|
exportPdf,
|
|
@@ -7535,27 +7653,27 @@ var generateRuntime = async (project) => {
|
|
|
7535
7653
|
await write(searchClientPath, searchClientTemplate(config));
|
|
7536
7654
|
if (servesStaticIndex(config.search.provider)) {
|
|
7537
7655
|
const documents = await buildSearchDocuments(project);
|
|
7538
|
-
await write(
|
|
7656
|
+
await write(join17(srcDir, "generated", "search.json"), `${JSON.stringify(documents)}
|
|
7539
7657
|
`);
|
|
7540
|
-
await write(
|
|
7658
|
+
await write(join17(srcDir, "pages", "blume-search.json.ts"), searchEndpointTemplate());
|
|
7541
7659
|
}
|
|
7542
7660
|
if (config.search.provider === "mixedbread") {
|
|
7543
|
-
await write(
|
|
7661
|
+
await write(join17(srcDir, "pages", "api", "search.ts"), mixedbreadSearchEndpointTemplate(config.search.mixedbread?.storeId ?? ""));
|
|
7544
7662
|
}
|
|
7545
7663
|
const rawMarkdown = await buildRawMarkdown(project);
|
|
7546
7664
|
await Promise.all([
|
|
7547
|
-
write(
|
|
7665
|
+
write(join17(srcDir, "generated", "raw-markdown.json"), `${JSON.stringify(rawMarkdown)}
|
|
7548
7666
|
`),
|
|
7549
|
-
write(
|
|
7550
|
-
write(
|
|
7667
|
+
write(join17(srcDir, "pages", "[...slug].md.ts"), rawMarkdownEndpointTemplate()),
|
|
7668
|
+
write(join17(srcDir, "pages", "[...slug].mdx.ts"), rawMarkdownEndpointTemplate())
|
|
7551
7669
|
]);
|
|
7552
7670
|
const feeds = buildRssFeeds(project);
|
|
7553
7671
|
if (feeds.length > 0) {
|
|
7554
7672
|
const feedXml = Object.fromEntries(feeds.map((feed) => [feed.type, renderRssFeed(feed)]));
|
|
7555
7673
|
await Promise.all([
|
|
7556
|
-
write(
|
|
7674
|
+
write(join17(srcDir, "generated", "rss.json"), `${JSON.stringify(feedXml)}
|
|
7557
7675
|
`),
|
|
7558
|
-
write(
|
|
7676
|
+
write(join17(srcDir, "pages", "[section]", "rss.xml.ts"), rssEndpointTemplate())
|
|
7559
7677
|
]);
|
|
7560
7678
|
}
|
|
7561
7679
|
const warnings = [
|
|
@@ -7592,13 +7710,13 @@ var generateRuntime = async (project) => {
|
|
|
7592
7710
|
root: context.root
|
|
7593
7711
|
});
|
|
7594
7712
|
warnings.push(...references.warnings);
|
|
7595
|
-
await Promise.all(references.files.map((file) => write(
|
|
7713
|
+
await Promise.all(references.files.map((file) => write(join17(srcDir, "pages", file.pagePath), file.content)));
|
|
7596
7714
|
}
|
|
7597
|
-
await write(
|
|
7715
|
+
await write(join17(srcDir, "generated", "data.json"), buildRuntimeData(project));
|
|
7598
7716
|
const openApiSource2 = project.sources.find(isOpenApiSource);
|
|
7599
7717
|
await write(openapiPath, `${JSON.stringify(openApiSource2 ? openApiSource2.openApiData() : {})}
|
|
7600
7718
|
`);
|
|
7601
|
-
await write(
|
|
7719
|
+
await write(join17(out, "blume.manifest.json"), `${JSON.stringify(project.manifest, null, 2)}
|
|
7602
7720
|
`);
|
|
7603
7721
|
await writeStagedContent(out, staged);
|
|
7604
7722
|
await pruneOrphans(srcDir, written);
|
|
@@ -7606,7 +7724,7 @@ var generateRuntime = async (project) => {
|
|
|
7606
7724
|
};
|
|
7607
7725
|
|
|
7608
7726
|
// src/core/config.ts
|
|
7609
|
-
import { existsSync as
|
|
7727
|
+
import { existsSync as existsSync11, readFileSync as readFileSync7 } from "node:fs";
|
|
7610
7728
|
|
|
7611
7729
|
// src/core/deployment-env.ts
|
|
7612
7730
|
var toUrl = (value) => {
|
|
@@ -8113,15 +8231,13 @@ var lastModifiedConfigSchema = z2.union([
|
|
|
8113
8231
|
]);
|
|
8114
8232
|
var codeConfigSchema = z2.object({
|
|
8115
8233
|
icons: z2.boolean().default(true),
|
|
8116
|
-
inline: z2.boolean().default(false),
|
|
8117
8234
|
wrap: z2.boolean().default(false)
|
|
8118
8235
|
}).strict();
|
|
8119
8236
|
var markdownConfigSchema = z2.object({
|
|
8120
8237
|
code: codeConfigSchema.default({}),
|
|
8121
8238
|
codeBlocks: codeBlocksConfigSchema.default({}),
|
|
8122
8239
|
headingAnchors: z2.boolean().default(true),
|
|
8123
|
-
imageZoom: z2.boolean().default(true)
|
|
8124
|
-
math: z2.boolean().default(false)
|
|
8240
|
+
imageZoom: z2.boolean().default(true)
|
|
8125
8241
|
}).strict();
|
|
8126
8242
|
var openapiSourceSchema = z2.object({
|
|
8127
8243
|
label: z2.string().optional(),
|
|
@@ -8207,7 +8323,7 @@ var loadConfig = async (root, options = {}) => {
|
|
|
8207
8323
|
}
|
|
8208
8324
|
const parsed = blumeConfigSchema.safeParse(raw ?? {});
|
|
8209
8325
|
if (!parsed.success) {
|
|
8210
|
-
const source = configFile &&
|
|
8326
|
+
const source = configFile && existsSync11(configFile) ? readFileSync7(configFile, "utf-8") : undefined;
|
|
8211
8327
|
const diagnostics = diagnosticsFromZod(parsed.error, {
|
|
8212
8328
|
code: "BLUME_CONFIG_INVALID",
|
|
8213
8329
|
file: configFile ?? undefined,
|
|
@@ -8641,7 +8757,7 @@ var gitLastModifiedTimes = (root, contentRoot, sourcePaths) => {
|
|
|
8641
8757
|
};
|
|
8642
8758
|
|
|
8643
8759
|
// src/core/meta.ts
|
|
8644
|
-
import { basename as basename3, dirname as
|
|
8760
|
+
import { basename as basename3, dirname as dirname9, relative as relative9 } from "pathe";
|
|
8645
8761
|
import { glob as glob5 } from "tinyglobby";
|
|
8646
8762
|
var META_FILES = [
|
|
8647
8763
|
"**/meta.ts",
|
|
@@ -8671,7 +8787,7 @@ var discoverFolderMeta = async (contentRoot) => {
|
|
|
8671
8787
|
const shared = new Map;
|
|
8672
8788
|
const diagnostics = [];
|
|
8673
8789
|
for (const entry of loaded) {
|
|
8674
|
-
const dir = relative9(contentRoot,
|
|
8790
|
+
const dir = relative9(contentRoot, dirname9(entry.file));
|
|
8675
8791
|
if (!entry.ok) {
|
|
8676
8792
|
diagnostics.push({
|
|
8677
8793
|
code: "BLUME_META_LOAD_FAILED",
|
|
@@ -8696,7 +8812,7 @@ var discoverFolderMeta = async (contentRoot) => {
|
|
|
8696
8812
|
};
|
|
8697
8813
|
|
|
8698
8814
|
// src/core/sources/normalize.ts
|
|
8699
|
-
import { existsSync as
|
|
8815
|
+
import { existsSync as existsSync12, readFileSync as readFileSync8 } from "node:fs";
|
|
8700
8816
|
import GithubSlugger from "github-slugger";
|
|
8701
8817
|
import { extname as extname4 } from "pathe";
|
|
8702
8818
|
var NUMERIC_PREFIX2 = /^\d+[-_.]/u;
|
|
@@ -8830,7 +8946,7 @@ var normalizeEntry2 = (entry, ctx) => {
|
|
|
8830
8946
|
const ext = format === "mdx" ? ".mdx" : ".md";
|
|
8831
8947
|
const result = pageMetaSchema.safeParse(entry.data);
|
|
8832
8948
|
if (!result.success) {
|
|
8833
|
-
const source = entry.raw ?? (entry.sourcePath &&
|
|
8949
|
+
const source = entry.raw ?? (entry.sourcePath && existsSync12(entry.sourcePath) ? readFileSync8(entry.sourcePath, "utf-8") : undefined);
|
|
8834
8950
|
return {
|
|
8835
8951
|
diagnostics: diagnosticsFromZod(result.error, {
|
|
8836
8952
|
code: "BLUME_FRONTMATTER_INVALID",
|
|
@@ -8881,15 +8997,15 @@ var normalizeEntry2 = (entry, ctx) => {
|
|
|
8881
8997
|
};
|
|
8882
8998
|
|
|
8883
8999
|
// src/core/sources/resolve.ts
|
|
8884
|
-
import { join as
|
|
9000
|
+
import { join as join22 } from "pathe";
|
|
8885
9001
|
|
|
8886
9002
|
// src/core/sources/filesystem.ts
|
|
8887
|
-
import { existsSync as
|
|
9003
|
+
import { existsSync as existsSync13, watch as fsWatch } from "node:fs";
|
|
8888
9004
|
import { readFile as readFile11 } from "node:fs/promises";
|
|
8889
|
-
import { extname as extname5, isAbsolute as isAbsolute7, join as
|
|
9005
|
+
import { extname as extname5, isAbsolute as isAbsolute7, join as join18, relative as relative10, resolve as resolve5 } from "pathe";
|
|
8890
9006
|
import { glob as glob6 } from "tinyglobby";
|
|
8891
9007
|
var filesystemSource = (options) => {
|
|
8892
|
-
const contentRoot = isAbsolute7(options.root) ? options.root :
|
|
9008
|
+
const contentRoot = isAbsolute7(options.root) ? options.root : join18(resolve5(options.projectRoot), options.root);
|
|
8893
9009
|
const load2 = async () => {
|
|
8894
9010
|
const files = await glob6(options.include, {
|
|
8895
9011
|
absolute: true,
|
|
@@ -8913,7 +9029,7 @@ var filesystemSource = (options) => {
|
|
|
8913
9029
|
return { diagnostics: [], entries };
|
|
8914
9030
|
};
|
|
8915
9031
|
const validate = () => {
|
|
8916
|
-
if (!
|
|
9032
|
+
if (!existsSync13(contentRoot)) {
|
|
8917
9033
|
throw new BlumeError({
|
|
8918
9034
|
code: options.missingCode ?? "BLUME_CONTENT_ROOT_MISSING",
|
|
8919
9035
|
file: contentRoot,
|
|
@@ -8928,7 +9044,7 @@ var filesystemSource = (options) => {
|
|
|
8928
9044
|
...excludeDirSegments(options.exclude)
|
|
8929
9045
|
]);
|
|
8930
9046
|
const watch = (onChange) => {
|
|
8931
|
-
if (!
|
|
9047
|
+
if (!existsSync13(contentRoot)) {
|
|
8932
9048
|
return () => {};
|
|
8933
9049
|
}
|
|
8934
9050
|
const watcher = fsWatch(contentRoot, { recursive: true }, ignoringWatchListener(onChange, watchIgnoreDirs));
|
|
@@ -8939,7 +9055,7 @@ var filesystemSource = (options) => {
|
|
|
8939
9055
|
load: load2,
|
|
8940
9056
|
name: options.name,
|
|
8941
9057
|
prefix: options.prefix,
|
|
8942
|
-
read: (ref) => readFile11(
|
|
9058
|
+
read: (ref) => readFile11(join18(contentRoot, ref), "utf-8"),
|
|
8943
9059
|
staged: false,
|
|
8944
9060
|
validate,
|
|
8945
9061
|
watch
|
|
@@ -9229,11 +9345,11 @@ var mdxRemoteSource = (options, ctx) => {
|
|
|
9229
9345
|
|
|
9230
9346
|
// src/core/sources/notion.ts
|
|
9231
9347
|
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
9232
|
-
import { join as
|
|
9348
|
+
import { join as join20 } from "pathe";
|
|
9233
9349
|
|
|
9234
9350
|
// src/core/sources/assets.ts
|
|
9235
|
-
import { mkdir as
|
|
9236
|
-
import { extname as extname6, join as
|
|
9351
|
+
import { mkdir as mkdir6, writeFile as writeFile6 } from "node:fs/promises";
|
|
9352
|
+
import { extname as extname6, join as join19 } from "pathe";
|
|
9237
9353
|
var MD_IMAGE = /!\[(?<alt>[^\]]*)\]\((?<url>[^)\s]+)\)/gu;
|
|
9238
9354
|
var REMOTE = /^https?:\/\//u;
|
|
9239
9355
|
var SAFE_EXT = /^\.[a-z0-9]+$/iu;
|
|
@@ -9261,8 +9377,8 @@ var materializeAssets = async (markdown, ctx) => {
|
|
|
9261
9377
|
}
|
|
9262
9378
|
const bytes = new Uint8Array(await res.arrayBuffer());
|
|
9263
9379
|
const file = `${hashText(url)}${extFor(url)}`;
|
|
9264
|
-
await
|
|
9265
|
-
await writeFile6(
|
|
9380
|
+
await mkdir6(ctx.assetsDir, { recursive: true });
|
|
9381
|
+
await writeFile6(join19(ctx.assetsDir, file), bytes);
|
|
9266
9382
|
rewrites.set(url, `${ctx.assetsBaseUrl}/${file}`);
|
|
9267
9383
|
} catch (error) {
|
|
9268
9384
|
diagnostics.push({
|
|
@@ -9378,8 +9494,8 @@ ${text}
|
|
|
9378
9494
|
};
|
|
9379
9495
|
var notionSource = (options, ctx) => {
|
|
9380
9496
|
const props = options.properties ?? {};
|
|
9381
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
9382
|
-
const assetsDir = ctx?.assetsDir ??
|
|
9497
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join20(".blume", "cache", options.name));
|
|
9498
|
+
const assetsDir = ctx?.assetsDir ?? join20(".blume", "public", "blume-assets", options.name);
|
|
9383
9499
|
const assetsBaseUrl = ctx?.assetsBaseUrl ?? `/blume-assets/${options.name}`;
|
|
9384
9500
|
let snapshot = new Map;
|
|
9385
9501
|
const resolveClient = async () => {
|
|
@@ -9547,7 +9663,7 @@ ${rendered.join(`
|
|
|
9547
9663
|
};
|
|
9548
9664
|
|
|
9549
9665
|
// src/core/sources/sanity.ts
|
|
9550
|
-
import { join as
|
|
9666
|
+
import { join as join21 } from "pathe";
|
|
9551
9667
|
|
|
9552
9668
|
// src/core/sources/portable-text.ts
|
|
9553
9669
|
var HEADING_STYLES = {
|
|
@@ -9686,7 +9802,7 @@ var resolveClient = async (options, preview) => {
|
|
|
9686
9802
|
};
|
|
9687
9803
|
var sanitySource = (options, ctx) => {
|
|
9688
9804
|
const fields = options.fields ?? {};
|
|
9689
|
-
const cache = snapshotCache(ctx?.cacheDir ??
|
|
9805
|
+
const cache = snapshotCache(ctx?.cacheDir ?? join21(".blume", "cache", options.name));
|
|
9690
9806
|
let snapshot = new Map;
|
|
9691
9807
|
const toEntry2 = (doc) => {
|
|
9692
9808
|
const slugValue = asString(getPath(doc, fields.slug ?? "slug.current")) ?? asString(doc._id) ?? "untitled";
|
|
@@ -9761,8 +9877,8 @@ var uniqueNamer = () => {
|
|
|
9761
9877
|
};
|
|
9762
9878
|
var sourceContext = (context, name, runtime) => ({
|
|
9763
9879
|
assetsBaseUrl: `/blume-assets/${name}`,
|
|
9764
|
-
assetsDir:
|
|
9765
|
-
cacheDir:
|
|
9880
|
+
assetsDir: join22(context.outDir, "public", "blume-assets", name),
|
|
9881
|
+
cacheDir: join22(context.outDir, "cache", name),
|
|
9766
9882
|
mode: runtime.mode,
|
|
9767
9883
|
preview: runtime.preview,
|
|
9768
9884
|
projectRoot: context.root,
|
|
@@ -9952,8 +10068,8 @@ var scanProject = async (root, options = {}) => {
|
|
|
9952
10068
|
};
|
|
9953
10069
|
|
|
9954
10070
|
// src/cli/env.ts
|
|
9955
|
-
import { existsSync as
|
|
9956
|
-
import { dirname as
|
|
10071
|
+
import { existsSync as existsSync14, readFileSync as readFileSync9 } from "node:fs";
|
|
10072
|
+
import { dirname as dirname10, join as join23, resolve as resolve6 } from "pathe";
|
|
9957
10073
|
var ENV_LINE = /^\s*(?:export\s+)?(?<key>[A-Za-z_][A-Za-z0-9_]*)\s*=\s*(?<value>.*?)\s*$/u;
|
|
9958
10074
|
var DOUBLE_QUOTED2 = /^"(?<body>[\s\S]*)"$/u;
|
|
9959
10075
|
var SINGLE_QUOTED = /^'(?<body>[\s\S]*)'$/u;
|
|
@@ -9991,7 +10107,7 @@ var applyEnv = (parsed) => {
|
|
|
9991
10107
|
};
|
|
9992
10108
|
var loadFile = (path) => {
|
|
9993
10109
|
try {
|
|
9994
|
-
if (
|
|
10110
|
+
if (existsSync14(path)) {
|
|
9995
10111
|
applyEnv(parseEnv(readFileSync9(path, "utf-8")));
|
|
9996
10112
|
}
|
|
9997
10113
|
} catch {}
|
|
@@ -10000,10 +10116,10 @@ var loadEnvFiles = (startDir) => {
|
|
|
10000
10116
|
let dir = resolve6(startDir);
|
|
10001
10117
|
let done = false;
|
|
10002
10118
|
while (!done) {
|
|
10003
|
-
loadFile(
|
|
10004
|
-
loadFile(
|
|
10005
|
-
const parent =
|
|
10006
|
-
done =
|
|
10119
|
+
loadFile(join23(dir, ".env.local"));
|
|
10120
|
+
loadFile(join23(dir, ".env"));
|
|
10121
|
+
const parent = dirname10(dir);
|
|
10122
|
+
done = existsSync14(join23(dir, ".git")) || parent === dir;
|
|
10007
10123
|
dir = parent;
|
|
10008
10124
|
}
|
|
10009
10125
|
};
|
|
@@ -10133,24 +10249,24 @@ var emitRedirectFiles = async (config, distDir) => {
|
|
|
10133
10249
|
if (redirects.length === 0 || config.deployment.output !== "static") {
|
|
10134
10250
|
return;
|
|
10135
10251
|
}
|
|
10136
|
-
await writeFile7(
|
|
10252
|
+
await writeFile7(join24(distDir, "blume-redirects.json"), buildRedirectManifest(redirects), "utf-8");
|
|
10137
10253
|
const platformFiles = [
|
|
10138
10254
|
{ content: buildNetlifyRedirects(redirects), name: "_redirects" },
|
|
10139
10255
|
{ content: buildVercelConfig(redirects), name: "vercel.json" }
|
|
10140
10256
|
];
|
|
10141
|
-
await Promise.all(platformFiles.map((file) =>
|
|
10257
|
+
await Promise.all(platformFiles.map((file) => existsSync15(join24(distDir, file.name)) ? Promise.resolve() : writeFile7(join24(distDir, file.name), file.content, "utf-8")));
|
|
10142
10258
|
logger.success(`Emitted redirect files for ${redirects.length} redirect(s)`);
|
|
10143
10259
|
};
|
|
10144
10260
|
var formatBytes = (bytes) => bytes < 1024 ? `${bytes} B` : `${(bytes / 1024).toFixed(bytes < 1024 * 100 ? 1 : 0)} kB`;
|
|
10145
10261
|
var astroAssets = async (distDir, ext) => {
|
|
10146
|
-
const astroDir =
|
|
10147
|
-
if (!
|
|
10262
|
+
const astroDir = join24(distDir, "_astro");
|
|
10263
|
+
if (!existsSync15(astroDir)) {
|
|
10148
10264
|
return [];
|
|
10149
10265
|
}
|
|
10150
10266
|
const entries = await readdir(astroDir);
|
|
10151
10267
|
const files = entries.filter((name) => name.endsWith(`.${ext}`));
|
|
10152
10268
|
const sized = await Promise.all(files.map(async (name) => {
|
|
10153
|
-
const info = await stat(
|
|
10269
|
+
const info = await stat(join24(astroDir, name));
|
|
10154
10270
|
return { name, size: info.size };
|
|
10155
10271
|
}));
|
|
10156
10272
|
return sized.toSorted((a, b) => b.size - a.size);
|
|
@@ -10206,24 +10322,24 @@ var publishBuildArtifacts = async (project, distDir, args) => {
|
|
|
10206
10322
|
if (project.config.ai.llmsTxt) {
|
|
10207
10323
|
const { index, full } = await buildLlmsFiles(project);
|
|
10208
10324
|
await Promise.all([
|
|
10209
|
-
writeFile7(
|
|
10210
|
-
writeFile7(
|
|
10325
|
+
writeFile7(join24(distDir, "llms.txt"), index, "utf-8"),
|
|
10326
|
+
writeFile7(join24(distDir, "llms-full.txt"), full, "utf-8")
|
|
10211
10327
|
]);
|
|
10212
10328
|
logger.success("Generated llms.txt and llms-full.txt");
|
|
10213
10329
|
}
|
|
10214
10330
|
const sitemap = buildSitemap(project);
|
|
10215
|
-
if (sitemap && !
|
|
10216
|
-
await writeFile7(
|
|
10331
|
+
if (sitemap && !existsSync15(join24(distDir, "sitemap.xml"))) {
|
|
10332
|
+
await writeFile7(join24(distDir, "sitemap.xml"), sitemap, "utf-8");
|
|
10217
10333
|
logger.success("Generated sitemap.xml");
|
|
10218
10334
|
}
|
|
10219
10335
|
const robots = buildRobots(project);
|
|
10220
|
-
if (robots && !
|
|
10221
|
-
await writeFile7(
|
|
10336
|
+
if (robots && !existsSync15(join24(distDir, "robots.txt"))) {
|
|
10337
|
+
await writeFile7(join24(distDir, "robots.txt"), robots, "utf-8");
|
|
10222
10338
|
logger.success("Generated robots.txt");
|
|
10223
10339
|
}
|
|
10224
10340
|
const agentReadability = buildAgentReadability(project);
|
|
10225
|
-
if (agentReadability && !
|
|
10226
|
-
await writeFile7(
|
|
10341
|
+
if (agentReadability && !existsSync15(join24(distDir, "agent-readability.json"))) {
|
|
10342
|
+
await writeFile7(join24(distDir, "agent-readability.json"), `${JSON.stringify(agentReadability, null, 2)}
|
|
10227
10343
|
`, "utf-8");
|
|
10228
10344
|
logger.success("Generated agent-readability.json");
|
|
10229
10345
|
}
|
|
@@ -10324,21 +10440,26 @@ var buildCommand = defineCommand2({
|
|
|
10324
10440
|
logLevel: "info",
|
|
10325
10441
|
root: project.context.outDir
|
|
10326
10442
|
});
|
|
10327
|
-
const distDir = project.context.distDir ??
|
|
10443
|
+
const distDir = project.context.distDir ?? join24(root, "dist");
|
|
10328
10444
|
if (runtimeDir) {
|
|
10329
10445
|
logger.success(`Isolated build OK — output at ${distDir} (not published).`);
|
|
10330
10446
|
return;
|
|
10331
10447
|
}
|
|
10332
|
-
await
|
|
10448
|
+
const surfaced = await surfaceAdapterOutput(project.config, project.context);
|
|
10449
|
+
if (surfaced.moved) {
|
|
10450
|
+
logger.success(`Surfaced ${project.config.deployment.adapter} output to ${surfaced.to}`);
|
|
10451
|
+
await ensureGitignore(root, [surfaced.ignore]);
|
|
10452
|
+
}
|
|
10453
|
+
await publishBuildArtifacts(project, deployStaticDir(project.config, project.context), args);
|
|
10333
10454
|
}
|
|
10334
10455
|
});
|
|
10335
10456
|
|
|
10336
10457
|
// src/cli/commands/check.ts
|
|
10337
|
-
import { existsSync as
|
|
10458
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
10338
10459
|
import { check } from "@astrojs/check";
|
|
10339
10460
|
import { sync } from "astro";
|
|
10340
10461
|
import { defineCommand as defineCommand3 } from "citty";
|
|
10341
|
-
import { join as
|
|
10462
|
+
import { join as join25 } from "pathe";
|
|
10342
10463
|
var checkCommand = defineCommand3({
|
|
10343
10464
|
args: {
|
|
10344
10465
|
isolated: {
|
|
@@ -10374,13 +10495,13 @@ var checkCommand = defineCommand3({
|
|
|
10374
10495
|
});
|
|
10375
10496
|
const { outDir } = project.context;
|
|
10376
10497
|
await sync({ logLevel: "warn", root: outDir });
|
|
10377
|
-
const tsconfig =
|
|
10498
|
+
const tsconfig = join25(root, "tsconfig.json");
|
|
10378
10499
|
logger.start(`Type-checking ${project.graph.pages.length} page(s)`);
|
|
10379
10500
|
const failed = await check({
|
|
10380
10501
|
minimumFailingSeverity: "error",
|
|
10381
10502
|
minimumSeverity: "hint",
|
|
10382
10503
|
root: outDir,
|
|
10383
|
-
tsconfig:
|
|
10504
|
+
tsconfig: existsSync16(tsconfig) ? tsconfig : undefined,
|
|
10384
10505
|
watch: false
|
|
10385
10506
|
});
|
|
10386
10507
|
if (failed) {
|
|
@@ -10652,12 +10773,12 @@ var doctorCommand = defineCommand5({
|
|
|
10652
10773
|
// src/cli/commands/eject.ts
|
|
10653
10774
|
import { readFile as readFile13, writeFile as writeFile9 } from "node:fs/promises";
|
|
10654
10775
|
import { defineCommand as defineCommand6 } from "citty";
|
|
10655
|
-
import { join as
|
|
10776
|
+
import { join as join27, relative as relative12 } from "pathe";
|
|
10656
10777
|
|
|
10657
10778
|
// src/registry/eject.ts
|
|
10658
|
-
import { existsSync as
|
|
10659
|
-
import { cp, mkdir as
|
|
10660
|
-
import { join as
|
|
10779
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
10780
|
+
import { cp as cp2, mkdir as mkdir7, readFile as readFile12, rm as rm3, writeFile as writeFile8 } from "node:fs/promises";
|
|
10781
|
+
import { join as join26, relative as relative11 } from "pathe";
|
|
10661
10782
|
var POSIX = (path) => path.split("\\").join("/");
|
|
10662
10783
|
var ejectOpenApiData = (project) => {
|
|
10663
10784
|
const source = project.sources.find(isOpenApiSource);
|
|
@@ -10672,14 +10793,14 @@ var askFiles = async (project, srcDir, genDir) => {
|
|
|
10672
10793
|
const files = [
|
|
10673
10794
|
{
|
|
10674
10795
|
content: askEndpointTemplate(resolveAskBackend(ask), grounded),
|
|
10675
|
-
path:
|
|
10796
|
+
path: join26(srcDir, "pages", "api", "ask.ts")
|
|
10676
10797
|
}
|
|
10677
10798
|
];
|
|
10678
10799
|
if (grounded) {
|
|
10679
10800
|
files.push({
|
|
10680
10801
|
content: `${JSON.stringify(await buildAskData(project))}
|
|
10681
10802
|
`,
|
|
10682
|
-
path:
|
|
10803
|
+
path: join26(genDir, "ask-data.json")
|
|
10683
10804
|
});
|
|
10684
10805
|
}
|
|
10685
10806
|
return files;
|
|
@@ -10687,14 +10808,23 @@ var askFiles = async (project, srcDir, genDir) => {
|
|
|
10687
10808
|
var eject = async (root) => {
|
|
10688
10809
|
const project = await scanProject(root, { mode: "build" });
|
|
10689
10810
|
const { context, config } = project;
|
|
10690
|
-
const srcDir =
|
|
10691
|
-
const genDir =
|
|
10811
|
+
const srcDir = join26(root, "src");
|
|
10812
|
+
const genDir = join26(srcDir, "generated");
|
|
10692
10813
|
const askEnabled = config.ai.ask?.enabled ?? false;
|
|
10693
10814
|
const exportPdf = config.export.pdf;
|
|
10694
10815
|
const exportEpub = config.export.epub;
|
|
10695
|
-
const [
|
|
10816
|
+
const [
|
|
10817
|
+
pages,
|
|
10818
|
+
needsReactRaw,
|
|
10819
|
+
usesMath,
|
|
10820
|
+
userTheme,
|
|
10821
|
+
rawMarkdown,
|
|
10822
|
+
islands,
|
|
10823
|
+
examples
|
|
10824
|
+
] = await Promise.all([
|
|
10696
10825
|
context.pagesRoot ? discoverPages(context.pagesRoot) : Promise.resolve([]),
|
|
10697
10826
|
detectNeedsReact(root),
|
|
10827
|
+
detectUsesMath(root),
|
|
10698
10828
|
context.themeFile ? readFile12(context.themeFile, "utf-8") : Promise.resolve(""),
|
|
10699
10829
|
buildRawMarkdown(project),
|
|
10700
10830
|
discoverIslands(root),
|
|
@@ -10737,14 +10867,14 @@ var eject = async (root) => {
|
|
|
10737
10867
|
searchClientPath: "./src/generated/search-client.ts",
|
|
10738
10868
|
themePath: "./src/generated/app.css"
|
|
10739
10869
|
}),
|
|
10740
|
-
path:
|
|
10870
|
+
path: join26(root, "astro.config.mjs")
|
|
10741
10871
|
},
|
|
10742
10872
|
{
|
|
10743
10873
|
content: runtimeTsconfigTemplate(),
|
|
10744
|
-
path:
|
|
10874
|
+
path: join26(root, "tsconfig.json"),
|
|
10745
10875
|
skipIfExists: true
|
|
10746
10876
|
},
|
|
10747
|
-
{ content: envTemplate(), path:
|
|
10877
|
+
{ content: envTemplate(), path: join26(srcDir, "env.d.ts") },
|
|
10748
10878
|
{
|
|
10749
10879
|
content: contentConfigTemplate({
|
|
10750
10880
|
config,
|
|
@@ -10752,29 +10882,29 @@ var eject = async (root) => {
|
|
|
10752
10882
|
staged: hasStaged,
|
|
10753
10883
|
stagedBase: stagedDir
|
|
10754
10884
|
}),
|
|
10755
|
-
path:
|
|
10885
|
+
path: join26(srcDir, "content.config.ts")
|
|
10756
10886
|
},
|
|
10757
10887
|
{
|
|
10758
10888
|
content: catchAllPageTemplate({
|
|
10759
10889
|
askEnabled,
|
|
10760
10890
|
exportEpub,
|
|
10761
10891
|
exportPdf,
|
|
10762
|
-
mathEnabled:
|
|
10892
|
+
mathEnabled: usesMath,
|
|
10763
10893
|
needsReact
|
|
10764
10894
|
}),
|
|
10765
|
-
path:
|
|
10895
|
+
path: join26(srcDir, "pages", "[...slug].astro")
|
|
10766
10896
|
},
|
|
10767
10897
|
{
|
|
10768
10898
|
content: planComponentSlots(componentsImport, null).module,
|
|
10769
|
-
path:
|
|
10899
|
+
path: join26(genDir, "components.ts")
|
|
10770
10900
|
},
|
|
10771
10901
|
{
|
|
10772
10902
|
content: islandMapTemplate(islands.islands),
|
|
10773
|
-
path:
|
|
10903
|
+
path: join26(genDir, "islands.ts")
|
|
10774
10904
|
},
|
|
10775
10905
|
{
|
|
10776
10906
|
content: exampleMapTemplate(examples.examples),
|
|
10777
|
-
path:
|
|
10907
|
+
path: join26(genDir, "examples.ts")
|
|
10778
10908
|
},
|
|
10779
10909
|
{
|
|
10780
10910
|
content: tailwindEntryTemplate({
|
|
@@ -10786,26 +10916,26 @@ var eject = async (root) => {
|
|
|
10786
10916
|
twoslashCss: twoslashCss(),
|
|
10787
10917
|
userTheme
|
|
10788
10918
|
}),
|
|
10789
|
-
path:
|
|
10919
|
+
path: join26(genDir, "app.css")
|
|
10790
10920
|
},
|
|
10791
|
-
{ content: buildRuntimeData(project), path:
|
|
10921
|
+
{ content: buildRuntimeData(project), path: join26(genDir, "data.json") },
|
|
10792
10922
|
{
|
|
10793
10923
|
content: `${JSON.stringify(ejectOpenApiData(project))}
|
|
10794
10924
|
`,
|
|
10795
|
-
path:
|
|
10925
|
+
path: join26(genDir, "openapi.json")
|
|
10796
10926
|
},
|
|
10797
10927
|
{
|
|
10798
10928
|
content: `${JSON.stringify(rawMarkdown)}
|
|
10799
10929
|
`,
|
|
10800
|
-
path:
|
|
10930
|
+
path: join26(genDir, "raw-markdown.json")
|
|
10801
10931
|
},
|
|
10802
10932
|
{
|
|
10803
10933
|
content: rawMarkdownEndpointTemplate(),
|
|
10804
|
-
path:
|
|
10934
|
+
path: join26(srcDir, "pages", "[...slug].md.ts")
|
|
10805
10935
|
},
|
|
10806
10936
|
{
|
|
10807
10937
|
content: rawMarkdownEndpointTemplate(),
|
|
10808
|
-
path:
|
|
10938
|
+
path: join26(srcDir, "pages", "[...slug].mdx.ts")
|
|
10809
10939
|
}
|
|
10810
10940
|
];
|
|
10811
10941
|
if (askEnabled) {
|
|
@@ -10814,34 +10944,34 @@ var eject = async (root) => {
|
|
|
10814
10944
|
if (config.seo.og.enabled) {
|
|
10815
10945
|
files.push({
|
|
10816
10946
|
content: ogEndpointTemplate(customOgRoutes(pages, config.title)),
|
|
10817
|
-
path:
|
|
10947
|
+
path: join26(srcDir, "pages", "og", "[...slug].png.ts")
|
|
10818
10948
|
});
|
|
10819
10949
|
}
|
|
10820
10950
|
if (!routeIsTaken(pages, project.graph.pages, "/404")) {
|
|
10821
10951
|
files.push({
|
|
10822
10952
|
content: notFoundPageTemplate(),
|
|
10823
|
-
path:
|
|
10953
|
+
path: join26(srcDir, "pages", "404.astro")
|
|
10824
10954
|
});
|
|
10825
10955
|
}
|
|
10826
10956
|
files.push({
|
|
10827
10957
|
content: searchClientTemplate(config),
|
|
10828
|
-
path:
|
|
10958
|
+
path: join26(genDir, "search-client.ts")
|
|
10829
10959
|
});
|
|
10830
10960
|
if (servesStaticIndex(config.search.provider)) {
|
|
10831
10961
|
const documents = await buildSearchDocuments(project);
|
|
10832
10962
|
files.push({
|
|
10833
10963
|
content: `${JSON.stringify(documents)}
|
|
10834
10964
|
`,
|
|
10835
|
-
path:
|
|
10965
|
+
path: join26(genDir, "search.json")
|
|
10836
10966
|
}, {
|
|
10837
10967
|
content: searchEndpointTemplate(),
|
|
10838
|
-
path:
|
|
10968
|
+
path: join26(srcDir, "pages", "blume-search.json.ts")
|
|
10839
10969
|
});
|
|
10840
10970
|
}
|
|
10841
10971
|
if (config.search.provider === "mixedbread") {
|
|
10842
10972
|
files.push({
|
|
10843
10973
|
content: mixedbreadSearchEndpointTemplate(config.search.mixedbread?.storeId ?? ""),
|
|
10844
|
-
path:
|
|
10974
|
+
path: join26(srcDir, "pages", "api", "search.ts")
|
|
10845
10975
|
});
|
|
10846
10976
|
}
|
|
10847
10977
|
const feeds = buildRssFeeds(project);
|
|
@@ -10850,10 +10980,10 @@ var eject = async (root) => {
|
|
|
10850
10980
|
files.push({
|
|
10851
10981
|
content: `${JSON.stringify(feedXml)}
|
|
10852
10982
|
`,
|
|
10853
|
-
path:
|
|
10983
|
+
path: join26(genDir, "rss.json")
|
|
10854
10984
|
}, {
|
|
10855
10985
|
content: rssEndpointTemplate(),
|
|
10856
|
-
path:
|
|
10986
|
+
path: join26(srcDir, "pages", "[section]", "rss.xml.ts")
|
|
10857
10987
|
});
|
|
10858
10988
|
}
|
|
10859
10989
|
if (hasScalarReferences(config)) {
|
|
@@ -10865,38 +10995,38 @@ var eject = async (root) => {
|
|
|
10865
10995
|
for (const file of references.files) {
|
|
10866
10996
|
files.push({
|
|
10867
10997
|
content: file.content,
|
|
10868
|
-
path:
|
|
10998
|
+
path: join26(srcDir, "pages", file.pagePath)
|
|
10869
10999
|
});
|
|
10870
11000
|
}
|
|
10871
11001
|
}
|
|
10872
11002
|
files.push(...islands.islands.map((island) => ({
|
|
10873
11003
|
content: islandWrapperTemplate(island),
|
|
10874
|
-
path:
|
|
11004
|
+
path: join26(genDir, "islands", `${island.name}.astro`)
|
|
10875
11005
|
})), ...examples.examples.map((example) => ({
|
|
10876
11006
|
content: exampleWrapperTemplate(example),
|
|
10877
|
-
path:
|
|
11007
|
+
path: join26(genDir, "examples", `${exampleSlug(example.path)}.astro`)
|
|
10878
11008
|
})));
|
|
10879
11009
|
for (const [entryId, content] of staged) {
|
|
10880
|
-
files.push({ content, path:
|
|
11010
|
+
files.push({ content, path: join26(root, stagedDir, entryId) });
|
|
10881
11011
|
}
|
|
10882
|
-
const written = files.filter((file) => !(file.skipIfExists &&
|
|
11012
|
+
const written = files.filter((file) => !(file.skipIfExists && existsSync17(file.path)));
|
|
10883
11013
|
await Promise.all(written.map(async (file) => {
|
|
10884
|
-
await
|
|
11014
|
+
await mkdir7(join26(file.path, ".."), { recursive: true });
|
|
10885
11015
|
await writeFile8(file.path, file.content, "utf-8");
|
|
10886
11016
|
}));
|
|
10887
|
-
const assetsSrc =
|
|
10888
|
-
if (
|
|
10889
|
-
await
|
|
11017
|
+
const assetsSrc = join26(context.outDir, "public", "blume-assets");
|
|
11018
|
+
if (existsSync17(assetsSrc)) {
|
|
11019
|
+
await cp2(assetsSrc, join26(root, "public", "blume-assets"), {
|
|
10890
11020
|
recursive: true
|
|
10891
11021
|
});
|
|
10892
11022
|
}
|
|
10893
|
-
await
|
|
11023
|
+
await rm3(context.outDir, { force: true, recursive: true });
|
|
10894
11024
|
return written.map((file) => file.path);
|
|
10895
11025
|
};
|
|
10896
11026
|
|
|
10897
11027
|
// src/cli/commands/eject.ts
|
|
10898
11028
|
var updatePackageScripts = async (root) => {
|
|
10899
|
-
const pkgPath =
|
|
11029
|
+
const pkgPath = join27(root, "package.json");
|
|
10900
11030
|
let pkg;
|
|
10901
11031
|
try {
|
|
10902
11032
|
pkg = JSON.parse(await readFile13(pkgPath, "utf-8"));
|
|
@@ -10946,10 +11076,10 @@ The blume package remains importable.`);
|
|
|
10946
11076
|
});
|
|
10947
11077
|
|
|
10948
11078
|
// src/cli/commands/init.ts
|
|
10949
|
-
import { existsSync as
|
|
10950
|
-
import { mkdir as
|
|
11079
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
11080
|
+
import { mkdir as mkdir8, writeFile as writeFile10 } from "node:fs/promises";
|
|
10951
11081
|
import { defineCommand as defineCommand7 } from "citty";
|
|
10952
|
-
import { basename as basename4, dirname as
|
|
11082
|
+
import { basename as basename4, dirname as dirname11, isAbsolute as isAbsolute8, join as join28, relative as relative13 } from "pathe";
|
|
10953
11083
|
|
|
10954
11084
|
// src/core/package-json.ts
|
|
10955
11085
|
var toPackageName = (raw) => raw.toLowerCase().replaceAll(/[^a-z0-9._-]+/gu, "-").replaceAll(/^[-_.]+|[-_.]+$/gu, "") || "docs";
|
|
@@ -11001,7 +11131,7 @@ var STARTERS = {
|
|
|
11001
11131
|
files: (dir) => [
|
|
11002
11132
|
{
|
|
11003
11133
|
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`."),
|
|
11004
|
-
path:
|
|
11134
|
+
path: join28(dir, "index.mdx")
|
|
11005
11135
|
}
|
|
11006
11136
|
]
|
|
11007
11137
|
},
|
|
@@ -11016,7 +11146,7 @@ var STARTERS = {
|
|
|
11016
11146
|
files: (dir) => [
|
|
11017
11147
|
{
|
|
11018
11148
|
content: page("Introduction", "Welcome to your new Blume docs.", "# Introduction\n\nWrite your docs here, and log releases under `changelog/`."),
|
|
11019
|
-
path:
|
|
11149
|
+
path: join28(dir, "index.mdx")
|
|
11020
11150
|
},
|
|
11021
11151
|
{
|
|
11022
11152
|
content: `---
|
|
@@ -11027,7 +11157,7 @@ date: 2026-01-01
|
|
|
11027
11157
|
|
|
11028
11158
|
The first release. Edit \`${dir}/changelog/v1-0-0.mdx\` or add new entries beside it.
|
|
11029
11159
|
`,
|
|
11030
|
-
path:
|
|
11160
|
+
path: join28(dir, "changelog", "v1-0-0.mdx")
|
|
11031
11161
|
}
|
|
11032
11162
|
]
|
|
11033
11163
|
},
|
|
@@ -11040,7 +11170,7 @@ The first release. Edit \`${dir}/changelog/v1-0-0.mdx\` or add new entries besid
|
|
|
11040
11170
|
Welcome to **Blume** — markdown-first docs powered by Astro and Vite.
|
|
11041
11171
|
|
|
11042
11172
|
Edit \`${dir}/index.mdx\` to get started, then run \`blume dev\`.`),
|
|
11043
|
-
path:
|
|
11173
|
+
path: join28(dir, "index.mdx")
|
|
11044
11174
|
}
|
|
11045
11175
|
]
|
|
11046
11176
|
},
|
|
@@ -11051,11 +11181,11 @@ Edit \`${dir}/index.mdx\` to get started, then run \`blume dev\`.`),
|
|
|
11051
11181
|
content: page("Introduction", "Get started with the SDK.", `# Introduction
|
|
11052
11182
|
|
|
11053
11183
|
Install the SDK and make your first call. See [Installation](/installation).`),
|
|
11054
|
-
path:
|
|
11184
|
+
path: join28(dir, "index.mdx")
|
|
11055
11185
|
},
|
|
11056
11186
|
{
|
|
11057
11187
|
content: page("Installation", "Install the SDK.", "# Installation\n\n```package-install\nyour-sdk\n```"),
|
|
11058
|
-
path:
|
|
11188
|
+
path: join28(dir, "installation.mdx")
|
|
11059
11189
|
}
|
|
11060
11190
|
]
|
|
11061
11191
|
}
|
|
@@ -11065,11 +11195,11 @@ var commandsFor = (pm) => ({
|
|
|
11065
11195
|
install: `${pm} install`
|
|
11066
11196
|
});
|
|
11067
11197
|
var writeFileSafe = async (path, content) => {
|
|
11068
|
-
if (
|
|
11198
|
+
if (existsSync18(path)) {
|
|
11069
11199
|
logger.info(`Skipped existing ${path}`);
|
|
11070
11200
|
return false;
|
|
11071
11201
|
}
|
|
11072
|
-
await
|
|
11202
|
+
await mkdir8(dirname11(path), { recursive: true });
|
|
11073
11203
|
await writeFile10(path, content, "utf-8");
|
|
11074
11204
|
logger.success(`Created ${path}`);
|
|
11075
11205
|
return true;
|
|
@@ -11102,7 +11232,7 @@ var initCommand = defineCommand7({
|
|
|
11102
11232
|
async run({ args }) {
|
|
11103
11233
|
const root = process.cwd();
|
|
11104
11234
|
const contentDir = args["content-dir"] ?? "docs";
|
|
11105
|
-
if (isAbsolute8(contentDir) || relative13(root,
|
|
11235
|
+
if (isAbsolute8(contentDir) || relative13(root, join28(root, contentDir)).startsWith("..")) {
|
|
11106
11236
|
logger.error(`Invalid --content-dir "${contentDir}" (must be a path inside the project).`);
|
|
11107
11237
|
process.exit(1);
|
|
11108
11238
|
}
|
|
@@ -11117,9 +11247,9 @@ var initCommand = defineCommand7({
|
|
|
11117
11247
|
process.exit(1);
|
|
11118
11248
|
}
|
|
11119
11249
|
const starter = STARTERS[template];
|
|
11120
|
-
const createdPackage = await writeFileSafe(
|
|
11121
|
-
await writeFileSafe(
|
|
11122
|
-
await Promise.all(starter.files(contentDir).map((file) => writeFileSafe(
|
|
11250
|
+
const createdPackage = await writeFileSafe(join28(root, "package.json"), blumePackageJson(toPackageName(basename4(root))));
|
|
11251
|
+
await writeFileSafe(join28(root, "blume.config.ts"), starter.config);
|
|
11252
|
+
await Promise.all(starter.files(contentDir).map((file) => writeFileSafe(join28(root, file.path), file.content)));
|
|
11123
11253
|
const ignored = await ensureGitignore(root, [".blume/", "dist/"]);
|
|
11124
11254
|
if (ignored.length > 0) {
|
|
11125
11255
|
logger.success(`Added ${ignored.join(", ")} to .gitignore`);
|
|
@@ -11157,10 +11287,10 @@ var initCommand = defineCommand7({
|
|
|
11157
11287
|
});
|
|
11158
11288
|
|
|
11159
11289
|
// src/cli/commands/preview.ts
|
|
11160
|
-
import { existsSync as
|
|
11290
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
11161
11291
|
import { preview } from "astro";
|
|
11162
11292
|
import { defineCommand as defineCommand8 } from "citty";
|
|
11163
|
-
import { join as
|
|
11293
|
+
import { join as join29 } from "pathe";
|
|
11164
11294
|
var previewCommand = defineCommand8({
|
|
11165
11295
|
args: {
|
|
11166
11296
|
host: { description: "Network host to bind.", type: "string" },
|
|
@@ -11174,7 +11304,7 @@ var previewCommand = defineCommand8({
|
|
|
11174
11304
|
const root = process.cwd();
|
|
11175
11305
|
const { config } = await loadConfig(root);
|
|
11176
11306
|
const context = resolveProjectContext(root, config);
|
|
11177
|
-
if (!
|
|
11307
|
+
if (!existsSync19(join29(context.outDir, "astro.config.mjs"))) {
|
|
11178
11308
|
logger.error("No build found. Run `blume build` first.");
|
|
11179
11309
|
process.exit(1);
|
|
11180
11310
|
}
|
|
@@ -11190,9 +11320,9 @@ var previewCommand = defineCommand8({
|
|
|
11190
11320
|
});
|
|
11191
11321
|
|
|
11192
11322
|
// src/cli/commands/sync.ts
|
|
11193
|
-
import { rm as
|
|
11323
|
+
import { rm as rm4 } from "node:fs/promises";
|
|
11194
11324
|
import { defineCommand as defineCommand9 } from "citty";
|
|
11195
|
-
import { join as
|
|
11325
|
+
import { join as join30 } from "pathe";
|
|
11196
11326
|
var syncCommand = defineCommand9({
|
|
11197
11327
|
args: {
|
|
11198
11328
|
force: {
|
|
@@ -11214,7 +11344,7 @@ var syncCommand = defineCommand9({
|
|
|
11214
11344
|
if (args.force) {
|
|
11215
11345
|
const { config } = await loadConfig(root);
|
|
11216
11346
|
const context = resolveProjectContext(root, config);
|
|
11217
|
-
await
|
|
11347
|
+
await rm4(join30(context.outDir, "cache"), { force: true, recursive: true });
|
|
11218
11348
|
logger.info("Cleared source cache.");
|
|
11219
11349
|
}
|
|
11220
11350
|
await prepareProject({
|
|
@@ -11229,13 +11359,13 @@ var syncCommand = defineCommand9({
|
|
|
11229
11359
|
});
|
|
11230
11360
|
|
|
11231
11361
|
// src/cli/commands/validate.ts
|
|
11232
|
-
import { existsSync as
|
|
11362
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
11233
11363
|
import { defineCommand as defineCommand10 } from "citty";
|
|
11234
|
-
import { join as
|
|
11364
|
+
import { join as join32 } from "pathe";
|
|
11235
11365
|
|
|
11236
11366
|
// src/core/links.ts
|
|
11237
|
-
import { existsSync as
|
|
11238
|
-
import { basename as basename5, join as
|
|
11367
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
11368
|
+
import { basename as basename5, join as join31 } from "pathe";
|
|
11239
11369
|
var HTTP = /^https?:\/\//iu;
|
|
11240
11370
|
var PROTOCOL_RELATIVE = /^\/\//u;
|
|
11241
11371
|
var SCHEME = /^[a-z][a-z0-9+.-]*:/iu;
|
|
@@ -11247,7 +11377,7 @@ var STATUS_NOT_FOUND = 404;
|
|
|
11247
11377
|
var STATUS_GONE = 410;
|
|
11248
11378
|
var STATUS_METHOD_NOT_ALLOWED = 405;
|
|
11249
11379
|
var STATUS_NOT_IMPLEMENTED = 501;
|
|
11250
|
-
var assetIsPresent = (resolved, ctx) => ctx.publicDir !== null &&
|
|
11380
|
+
var assetIsPresent = (resolved, ctx) => ctx.publicDir !== null && existsSync20(join31(ctx.publicDir, resolved));
|
|
11251
11381
|
var isIndexPage = (page2) => {
|
|
11252
11382
|
const ref = page2.source?.ref ?? page2.sourcePath ?? "";
|
|
11253
11383
|
return /^index\.(?:md|mdx)$/iu.test(basename5(ref));
|
|
@@ -11490,10 +11620,10 @@ var validateCommand = defineCommand10({
|
|
|
11490
11620
|
try {
|
|
11491
11621
|
const project = await scanProject(root, { mode: "build" });
|
|
11492
11622
|
diagnostics.push(...project.diagnostics);
|
|
11493
|
-
const publicDir =
|
|
11623
|
+
const publicDir = join32(root, "public");
|
|
11494
11624
|
diagnostics.push(...await validateLinks(project.graph, {
|
|
11495
11625
|
checkExternal: Boolean(args.external),
|
|
11496
|
-
publicDir:
|
|
11626
|
+
publicDir: existsSync21(publicDir) ? publicDir : null,
|
|
11497
11627
|
redirects: project.config.redirects
|
|
11498
11628
|
}));
|
|
11499
11629
|
} catch (error) {
|
|
@@ -11553,5 +11683,5 @@ process.on("unhandledRejection", (error) => {
|
|
|
11553
11683
|
});
|
|
11554
11684
|
runMain(main);
|
|
11555
11685
|
|
|
11556
|
-
//# debugId=
|
|
11686
|
+
//# debugId=0628D18D87A2023564756E2164756E21
|
|
11557
11687
|
//# sourceMappingURL=index.js.map
|