blume 1.5.1 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/cli/index.js +340 -132
- package/dist/cli/index.js.map +21 -20
- package/dist/types/ai/ask-context.d.ts +78 -0
- package/dist/types/core/config-input.d.ts +53 -1
- package/dist/types/core/data.d.ts +16 -0
- package/dist/types/core/open-in-chat.d.ts +9 -0
- package/dist/types/core/schema.d.ts +48 -1
- package/dist/types/core/types.d.ts +10 -3
- package/dist/types/openapi/references.d.ts +9 -0
- package/dist/types/search/orama-index.d.ts +70 -0
- package/docs/advanced/api-reference.mdx +67 -5
- package/docs/configuration/ai.mdx +35 -0
- package/docs/configuration/index.mdx +13 -1
- package/docs/configuration/search.mdx +4 -4
- package/docs/reference/cli.mdx +1 -1
- package/package.json +1 -1
- package/skills/blume-migrate/SKILL.md +1 -1
- package/skills/blume-migrate/references/mintlify.md +1 -1
- package/src/ai/ask-context.ts +51 -11
- package/src/ai/mcp/data.ts +3 -2
- package/src/ai/mcp/server.ts +3 -2
- package/src/assets/icon-dark.png +0 -0
- package/src/astro/generate.ts +162 -13
- package/src/astro/templates.ts +63 -11
- package/src/components/content/AccordionItem.astro +4 -0
- package/src/components/content/Update.astro +3 -0
- package/src/components/islands/AskAI.astro +6 -0
- package/src/components/islands/ask-ai.tsx +39 -9
- package/src/components/layout/Analytics.astro +9 -1
- package/src/components/layout/Favicon.astro +29 -8
- package/src/components/layout/Header.astro +2 -2
- package/src/components/layout/NavSelector.astro +1 -1
- package/src/components/layout/PageActions.astro +120 -78
- package/src/components/layout/PageFeedback.astro +12 -3
- package/src/components/layout/PageLayout.astro +7 -2
- package/src/components/layout/ReferenceLayout.astro +10 -8
- package/src/components/layout/RootLayout.astro +151 -120
- package/src/components/layout/Search.astro +41 -26
- package/src/components/layout/drawer-inert.ts +10 -5
- package/src/components/layout/head-scripts.ts +34 -16
- package/src/components/layout/nav-utils.ts +34 -15
- package/src/components/layout/search/orama.ts +3 -2
- package/src/components/openapi/AsyncApiOperation.astro +22 -7
- package/src/components/openapi/MessageComposer.astro +238 -0
- package/src/components/openapi/Operation.astro +26 -12
- package/src/components/openapi/PanelTabs.astro +7 -0
- package/src/components/openapi/Playground.astro +320 -0
- package/src/components/openapi/RequestPanel.astro +1 -0
- package/src/components/openapi/async-snippets.ts +20 -7
- package/src/components/openapi/async.ts +13 -2
- package/src/components/openapi/message-composer.ts +242 -0
- package/src/components/openapi/message-model.ts +108 -0
- package/src/components/openapi/message.ts +153 -0
- package/src/components/openapi/operation-model.ts +260 -0
- package/src/components/openapi/playground-client.ts +486 -0
- package/src/components/openapi/playground-schema.ts +109 -0
- package/src/components/openapi/request.ts +287 -0
- package/src/components/openapi/security.ts +0 -56
- package/src/components/openapi/snippets.ts +23 -136
- package/src/components/openapi/validate-json.ts +144 -0
- package/src/components/openapi/ws-client.ts +194 -0
- package/src/core/config-input.ts +66 -0
- package/src/core/content-assets.ts +66 -15
- package/src/core/data.ts +13 -0
- package/src/core/last-modified.ts +28 -3
- package/src/core/links.ts +30 -4
- package/src/core/navigation.ts +26 -1
- package/src/core/open-in-chat.ts +17 -0
- package/src/core/schema.ts +59 -0
- package/src/core/server-features.ts +11 -0
- package/src/core/sources/normalize.ts +10 -2
- package/src/core/types.ts +10 -3
- package/src/openapi/model.ts +7 -0
- package/src/openapi/proxy.ts +217 -0
- package/src/openapi/references.ts +8 -0
- package/src/openapi/source.ts +13 -0
- package/src/registry/eject.ts +4 -5
- package/src/search/orama-index.ts +109 -36
- package/src/theme/entry.ts +6 -15
package/dist/cli/index.js
CHANGED
|
@@ -3179,11 +3179,13 @@ var referencesFor = (kind, block, defaultLabel, renderer, display, basePath) =>
|
|
|
3179
3179
|
var resolveReferences = (config) => [
|
|
3180
3180
|
...referencesFor("openapi", config.openapi, "API Reference", config.openapi.renderer, {
|
|
3181
3181
|
codeSamples: config.openapi.codeSamples,
|
|
3182
|
-
expandSchemas: config.openapi.expandSchemas
|
|
3182
|
+
expandSchemas: config.openapi.expandSchemas,
|
|
3183
|
+
playground: config.openapi.playground
|
|
3183
3184
|
}, config.basePath),
|
|
3184
3185
|
...referencesFor("asyncapi", config.asyncapi, "Events", config.asyncapi.renderer, {
|
|
3185
3186
|
codeSamples: config.asyncapi.codeSamples,
|
|
3186
|
-
expandSchemas: config.asyncapi.expandSchemas
|
|
3187
|
+
expandSchemas: config.asyncapi.expandSchemas,
|
|
3188
|
+
playground: config.asyncapi.playground
|
|
3187
3189
|
}, config.basePath)
|
|
3188
3190
|
];
|
|
3189
3191
|
var referenceRoutes = (config) => resolveReferences(config).map((ref) => ref.renderer === "blume" ? withBasePath(config.basePath, ref.route) : ref.route);
|
|
@@ -3976,10 +3978,10 @@ ${userConfigSetup}export default defineConfig({
|
|
|
3976
3978
|
},
|
|
3977
3979
|
},
|
|
3978
3980
|
devToolbar: { enabled: false },
|
|
3979
|
-
//
|
|
3980
|
-
//
|
|
3981
|
-
// user's intent
|
|
3982
|
-
//
|
|
3981
|
+
// The layouts render Astro's <ClientRouter />, and its in-place swaps read
|
|
3982
|
+
// from the prefetch cache — fetching every link on hover/viewport hides the
|
|
3983
|
+
// request latency behind the user's intent, so most navigations swap
|
|
3984
|
+
// instantly.
|
|
3983
3985
|
prefetch: { prefetchAll: true },
|
|
3984
3986
|
vite: {
|
|
3985
3987
|
plugins: [tailwindcss(), prerenderDepsPlugin(), serverAppResolvePlugin()],
|
|
@@ -4092,7 +4094,8 @@ export const collections = { docs${options.staged ? ", staged" : ""} };
|
|
|
4092
4094
|
`;
|
|
4093
4095
|
};
|
|
4094
4096
|
var ASK_FALLBACK_PROMPT = "You are a helpful documentation assistant. Answer using the project's documentation.";
|
|
4095
|
-
var askEndpointTemplate = (backend, grounded,
|
|
4097
|
+
var askEndpointTemplate = (backend, grounded, options) => {
|
|
4098
|
+
const instructions = options?.instructions;
|
|
4096
4099
|
const fallbackPrompt = instructions ? `${ASK_FALLBACK_PROMPT}
|
|
4097
4100
|
|
|
4098
4101
|
${instructions}` : ASK_FALLBACK_PROMPT;
|
|
@@ -4121,7 +4124,14 @@ const provider = createOpenAICompatible({
|
|
|
4121
4124
|
}
|
|
4122
4125
|
if (grounded) {
|
|
4123
4126
|
imports.push('import { createAskContext } from "blume/ai/ask-context.ts";', 'import askData from "../../generated/ask-data.json";');
|
|
4124
|
-
const
|
|
4127
|
+
const groundFields = [];
|
|
4128
|
+
if (instructions) {
|
|
4129
|
+
groundFields.push(`instructions: ${JSON.stringify(instructions)}`);
|
|
4130
|
+
}
|
|
4131
|
+
if (options?.retrieval) {
|
|
4132
|
+
groundFields.push(`retrieval: ${JSON.stringify(options.retrieval)}`);
|
|
4133
|
+
}
|
|
4134
|
+
const groundOptions = groundFields.length > 0 ? `, { ${groundFields.join(", ")} }` : "";
|
|
4125
4135
|
setup += `
|
|
4126
4136
|
const ground = createAskContext(askData${groundOptions});
|
|
4127
4137
|
`;
|
|
@@ -4459,6 +4469,16 @@ const handler = createMcpFetchHandler(data as McpData);
|
|
|
4459
4469
|
export const ALL: APIRoute = ({ request }) => handler(request);
|
|
4460
4470
|
`;
|
|
4461
4471
|
};
|
|
4472
|
+
var playgroundProxyTemplate = (origins) => `// Generated by Blume. Do not edit.
|
|
4473
|
+
import type { APIRoute } from "astro";
|
|
4474
|
+
import { createPlaygroundProxyHandler } from "blume/openapi/proxy.ts";
|
|
4475
|
+
|
|
4476
|
+
export const prerender = false;
|
|
4477
|
+
|
|
4478
|
+
const handler = createPlaygroundProxyHandler(${JSON.stringify(origins)});
|
|
4479
|
+
|
|
4480
|
+
export const ALL: APIRoute = ({ request }) => handler(request);
|
|
4481
|
+
`;
|
|
4462
4482
|
var staticJsonEndpointTemplate = (payload) => `// Generated by Blume. Do not edit.
|
|
4463
4483
|
export const prerender = true;
|
|
4464
4484
|
|
|
@@ -4949,6 +4969,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
4949
4969
|
feedback={data.config.feedback}
|
|
4950
4970
|
exportPdf={${options.exportPdf}}
|
|
4951
4971
|
exportEpub={${options.exportEpub}}
|
|
4972
|
+
openInChat={data.config.openInChat}
|
|
4952
4973
|
feeds={data.feeds}
|
|
4953
4974
|
discovery={data.config.discovery}
|
|
4954
4975
|
siteUrl={data.config.site}
|
|
@@ -5162,6 +5183,7 @@ const LayoutComponent = resolveSlot(layoutOverrides.Layout, RootLayout);
|
|
|
5162
5183
|
canonical={canonical}
|
|
5163
5184
|
exportPdf={${options.exportPdf}}
|
|
5164
5185
|
exportEpub={${options.exportEpub}}
|
|
5186
|
+
openInChat={data.config.openInChat}
|
|
5165
5187
|
feeds={data.feeds}
|
|
5166
5188
|
discovery={data.config.discovery}
|
|
5167
5189
|
siteUrl={data.config.site}
|
|
@@ -9623,6 +9645,16 @@ var resolveUIStrings = (locale, options) => {
|
|
|
9623
9645
|
return dict;
|
|
9624
9646
|
};
|
|
9625
9647
|
|
|
9648
|
+
// src/core/open-in-chat.ts
|
|
9649
|
+
var openInChatProviders = [
|
|
9650
|
+
"v0",
|
|
9651
|
+
"chatgpt",
|
|
9652
|
+
"claude",
|
|
9653
|
+
"t3",
|
|
9654
|
+
"scira",
|
|
9655
|
+
"cursor"
|
|
9656
|
+
];
|
|
9657
|
+
|
|
9626
9658
|
// src/core/standard-schema.ts
|
|
9627
9659
|
var isStandardSchema = (value) => typeof value === "object" && value !== null && typeof value["~standard"]?.validate === "function";
|
|
9628
9660
|
|
|
@@ -10037,6 +10069,11 @@ var aiConfigSchema = z2.strictObject({
|
|
|
10037
10069
|
instructions: z2.string().trim().min(1).optional(),
|
|
10038
10070
|
model: z2.string().default("openai/gpt-5.5"),
|
|
10039
10071
|
provider: z2.enum(askAiProviders).default("gateway"),
|
|
10072
|
+
retrieval: z2.strictObject({
|
|
10073
|
+
contextBudget: z2.number().int().positive().optional(),
|
|
10074
|
+
excerptChars: z2.number().int().positive().optional(),
|
|
10075
|
+
maxResults: z2.number().int().positive().optional()
|
|
10076
|
+
}).optional(),
|
|
10040
10077
|
suggestions: z2.array(z2.strictObject({
|
|
10041
10078
|
icon: iconName.optional(),
|
|
10042
10079
|
label: z2.string().min(1)
|
|
@@ -10061,6 +10098,17 @@ var aiConfigSchema = z2.strictObject({
|
|
|
10061
10098
|
message: "Expected a serializer function."
|
|
10062
10099
|
})).default({}),
|
|
10063
10100
|
mcp: mcpConfigSchema.prefault({}),
|
|
10101
|
+
openInChat: z2.union([
|
|
10102
|
+
z2.boolean(),
|
|
10103
|
+
z2.array(z2.enum(openInChatProviders)).refine((value) => new Set(value).size === value.length, {
|
|
10104
|
+
message: "ai.openInChat must not repeat a provider."
|
|
10105
|
+
})
|
|
10106
|
+
]).default(true).transform((value) => {
|
|
10107
|
+
if (isBoolean(value)) {
|
|
10108
|
+
return value ? [...openInChatProviders] : [];
|
|
10109
|
+
}
|
|
10110
|
+
return value;
|
|
10111
|
+
}),
|
|
10064
10112
|
skills: z2.string().min(1).optional(),
|
|
10065
10113
|
webBotAuth: z2.strictObject({
|
|
10066
10114
|
keys: z2.array(publicJwkSchema).default([])
|
|
@@ -10336,6 +10384,13 @@ var referenceConfigSchema = (defaults) => z2.strictObject({
|
|
|
10336
10384
|
codeSamples: z2.array(z2.string()).default(defaults.codeSamples),
|
|
10337
10385
|
enabled: z2.boolean().default(false),
|
|
10338
10386
|
expandSchemas: z2.boolean().default(false),
|
|
10387
|
+
playground: z2.union([
|
|
10388
|
+
z2.boolean(),
|
|
10389
|
+
z2.strictObject({
|
|
10390
|
+
enabled: z2.boolean().default(true),
|
|
10391
|
+
proxy: z2.union([z2.boolean(), z2.string()]).default(false)
|
|
10392
|
+
})
|
|
10393
|
+
]).default(true).transform((value) => isBoolean(value) ? { enabled: value, proxy: false } : value),
|
|
10339
10394
|
renderer: z2.enum(["blume", "scalar"]).default("blume"),
|
|
10340
10395
|
route: z2.string().default(defaults.route),
|
|
10341
10396
|
scalar: scalarConfigSchema,
|
|
@@ -10775,6 +10830,8 @@ import { extname } from "pathe";
|
|
|
10775
10830
|
var NUMERIC_PREFIX = /^(?<order>\d+)[-_.]/u;
|
|
10776
10831
|
var GROUP_FOLDER = /^\((?<label>.+)\)$/u;
|
|
10777
10832
|
var WORD_SPLIT = /[-_]/u;
|
|
10833
|
+
var isUnderPath = (route, base) => base === "/" || route === base || route.startsWith(`${base}/`);
|
|
10834
|
+
var isRootTab = (tab, root) => isUnderPath(root, tab.path);
|
|
10778
10835
|
var humanize = (segment) => segment.replace(NUMERIC_PREFIX, "").split(WORD_SPLIT).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
10779
10836
|
var numericOrder = (segment) => {
|
|
10780
10837
|
const value = segment.match(NUMERIC_PREFIX)?.groups?.order;
|
|
@@ -11231,7 +11288,7 @@ var buildNavigation = (pages, options) => {
|
|
|
11231
11288
|
tabs: withTabHrefs(tabs, sidebar2)
|
|
11232
11289
|
};
|
|
11233
11290
|
}
|
|
11234
|
-
const sidebar = buildFileSystemSidebar(pages, options.folderMeta, sharedFolderMeta, metaPrefix, sharedMetaPrefix, display, new Set(tabs.flatMap((tab) => tab
|
|
11291
|
+
const sidebar = buildFileSystemSidebar(pages, options.folderMeta, sharedFolderMeta, metaPrefix, sharedMetaPrefix, display, new Set(tabs.flatMap((tab) => isRootTab(tab, rootTabPath) ? [] : [tab.path])), diagnostics);
|
|
11235
11292
|
return {
|
|
11236
11293
|
featured,
|
|
11237
11294
|
root: rootTabPath,
|
|
@@ -11463,6 +11520,15 @@ var buildContentGraph = (pages, options) => {
|
|
|
11463
11520
|
// src/core/last-modified.ts
|
|
11464
11521
|
import { execFileSync } from "node:child_process";
|
|
11465
11522
|
import { relative as relative7 } from "pathe";
|
|
11523
|
+
var GIT_LOCATION_VARS = new Set([
|
|
11524
|
+
"GIT_COMMON_DIR",
|
|
11525
|
+
"GIT_DIR",
|
|
11526
|
+
"GIT_INDEX_FILE",
|
|
11527
|
+
"GIT_OBJECT_DIRECTORY",
|
|
11528
|
+
"GIT_PREFIX",
|
|
11529
|
+
"GIT_WORK_TREE"
|
|
11530
|
+
]);
|
|
11531
|
+
var gitEnv = () => Object.fromEntries(Object.entries(process.env).filter(([key]) => !GIT_LOCATION_VARS.has(key)));
|
|
11466
11532
|
var resolveLastModifiedConfig = (value) => {
|
|
11467
11533
|
if (value === false) {
|
|
11468
11534
|
return { enabled: false, source: "git" };
|
|
@@ -11490,7 +11556,7 @@ var gitLastModifiedTimes = (root, contentRoots, sourcePaths) => {
|
|
|
11490
11556
|
return new Map;
|
|
11491
11557
|
}
|
|
11492
11558
|
try {
|
|
11493
|
-
const gitRoot = execFileSync("git", ["-C", root, "rev-parse", "--show-toplevel"], { encoding: "utf-8" }).trim();
|
|
11559
|
+
const gitRoot = execFileSync("git", ["-C", root, "rev-parse", "--show-toplevel"], { encoding: "utf-8", env: gitEnv() }).trim();
|
|
11494
11560
|
const output = execFileSync("git", [
|
|
11495
11561
|
"-C",
|
|
11496
11562
|
root,
|
|
@@ -11501,7 +11567,7 @@ var gitLastModifiedTimes = (root, contentRoots, sourcePaths) => {
|
|
|
11501
11567
|
"--name-only",
|
|
11502
11568
|
"--",
|
|
11503
11569
|
...contentRoots
|
|
11504
|
-
], { encoding: "utf-8", maxBuffer: 256 * 1024 * 1024 });
|
|
11570
|
+
], { encoding: "utf-8", env: gitEnv(), maxBuffer: 256 * 1024 * 1024 });
|
|
11505
11571
|
const byRepoPath = parseGitLog(output);
|
|
11506
11572
|
const result = new Map;
|
|
11507
11573
|
for (const sourcePath of sourcePaths) {
|
|
@@ -11517,7 +11583,11 @@ var gitLastModifiedTimes = (root, contentRoots, sourcePaths) => {
|
|
|
11517
11583
|
};
|
|
11518
11584
|
var isShallowGitRepository = (root) => {
|
|
11519
11585
|
try {
|
|
11520
|
-
return execFileSync("git", ["-C", root, "rev-parse", "--is-shallow-repository"], {
|
|
11586
|
+
return execFileSync("git", ["-C", root, "rev-parse", "--is-shallow-repository"], {
|
|
11587
|
+
encoding: "utf-8",
|
|
11588
|
+
env: gitEnv(),
|
|
11589
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
11590
|
+
}).trim() === "true";
|
|
11521
11591
|
} catch {
|
|
11522
11592
|
return false;
|
|
11523
11593
|
}
|
|
@@ -11906,11 +11976,15 @@ var scanLinkLine = (line, lineNumber, fence, links) => {
|
|
|
11906
11976
|
continue;
|
|
11907
11977
|
}
|
|
11908
11978
|
const targetOffset = targetOffsetIn(match[0], target, match.groups?.title);
|
|
11909
|
-
|
|
11979
|
+
const entry = {
|
|
11910
11980
|
column: match.index + targetOffset + 1,
|
|
11911
11981
|
line: lineNumber,
|
|
11912
11982
|
target
|
|
11913
|
-
}
|
|
11983
|
+
};
|
|
11984
|
+
if (masked[match.index - 1] === "!") {
|
|
11985
|
+
entry.image = true;
|
|
11986
|
+
}
|
|
11987
|
+
links.push(entry);
|
|
11914
11988
|
const label = match[0].slice(0, targetOffset - "](".length);
|
|
11915
11989
|
for (const image of label.matchAll(MD_IMAGE)) {
|
|
11916
11990
|
const imageTarget = image.groups?.target;
|
|
@@ -11919,6 +11993,7 @@ var scanLinkLine = (line, lineNumber, fence, links) => {
|
|
|
11919
11993
|
}
|
|
11920
11994
|
links.push({
|
|
11921
11995
|
column: match.index + image.index + targetOffsetIn(image[0], imageTarget, image.groups?.title) + 1,
|
|
11996
|
+
image: true,
|
|
11922
11997
|
line: lineNumber,
|
|
11923
11998
|
target: imageTarget
|
|
11924
11999
|
});
|
|
@@ -12867,6 +12942,13 @@ var openApiSource = (references, ctx) => {
|
|
|
12867
12942
|
try {
|
|
12868
12943
|
const { document, warnings, operations, tags, extractWarnings } = await parseReference(reference, ctx);
|
|
12869
12944
|
const info = document.info ?? { title: reference.label, version: "" };
|
|
12945
|
+
const { proxy: configuredProxy } = reference.display.playground;
|
|
12946
|
+
let proxy = false;
|
|
12947
|
+
if (configuredProxy === true) {
|
|
12948
|
+
proxy = withBasePath(reference.basePath, "/_api-proxy");
|
|
12949
|
+
} else if (configuredProxy !== false && configuredProxy !== "") {
|
|
12950
|
+
proxy = configuredProxy;
|
|
12951
|
+
}
|
|
12870
12952
|
const spec = {
|
|
12871
12953
|
codeSamples: reference.display.codeSamples,
|
|
12872
12954
|
description: info.description ?? "",
|
|
@@ -12881,6 +12963,7 @@ var openApiSource = (references, ctx) => {
|
|
|
12881
12963
|
route: withBasePath(reference.basePath, operation.route)
|
|
12882
12964
|
}
|
|
12883
12965
|
])),
|
|
12966
|
+
playground: { enabled: reference.display.playground.enabled, proxy },
|
|
12884
12967
|
route: reference.route,
|
|
12885
12968
|
slug: reference.slug,
|
|
12886
12969
|
tags,
|
|
@@ -14331,7 +14414,7 @@ var auditCommand = defineCommand2({
|
|
|
14331
14414
|
});
|
|
14332
14415
|
|
|
14333
14416
|
// src/cli/commands/build.ts
|
|
14334
|
-
import { existsSync as
|
|
14417
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
14335
14418
|
import { mkdir as mkdir8, readdir as readdir2, readFile as readFile17, stat as stat3, writeFile as writeFile7 } from "node:fs/promises";
|
|
14336
14419
|
import { build } from "astro";
|
|
14337
14420
|
import { defineCommand as defineCommand3 } from "citty";
|
|
@@ -14504,9 +14587,16 @@ var buildAgentReadability = (project) => {
|
|
|
14504
14587
|
};
|
|
14505
14588
|
|
|
14506
14589
|
// src/core/content-assets.ts
|
|
14507
|
-
import {
|
|
14590
|
+
import { readdirSync, statSync } from "node:fs";
|
|
14508
14591
|
import { readFile as readFile8 } from "node:fs/promises";
|
|
14509
|
-
import {
|
|
14592
|
+
import {
|
|
14593
|
+
basename as basename2,
|
|
14594
|
+
dirname as dirname7,
|
|
14595
|
+
extname as extname5,
|
|
14596
|
+
normalize as normalize3,
|
|
14597
|
+
relative as relative11,
|
|
14598
|
+
resolve as resolve5
|
|
14599
|
+
} from "pathe";
|
|
14510
14600
|
var CONTENT_ASSETS_PREFIX = "/blume-assets/content";
|
|
14511
14601
|
var IMAGE_EXTENSIONS = new Set([
|
|
14512
14602
|
".apng",
|
|
@@ -14529,19 +14619,40 @@ var contentAssetParam = (projectRoot, absPath) => {
|
|
|
14529
14619
|
}
|
|
14530
14620
|
return rel;
|
|
14531
14621
|
};
|
|
14532
|
-
var
|
|
14533
|
-
if (!isRelativeTarget(target)) {
|
|
14534
|
-
return null;
|
|
14535
|
-
}
|
|
14536
|
-
let decoded = target;
|
|
14622
|
+
var decodeTarget = (target) => {
|
|
14537
14623
|
try {
|
|
14538
|
-
|
|
14539
|
-
} catch {
|
|
14540
|
-
|
|
14624
|
+
return decodeURI(target);
|
|
14625
|
+
} catch {
|
|
14626
|
+
return target;
|
|
14627
|
+
}
|
|
14628
|
+
};
|
|
14629
|
+
var isRelativeImageTarget = (target) => isRelativeTarget(target) && IMAGE_EXTENSIONS.has(extname5(decodeTarget(target)).toLowerCase());
|
|
14630
|
+
var existsAsWritten = (abs, segments) => {
|
|
14631
|
+
let current = abs;
|
|
14632
|
+
for (let i = 0;i < segments; i += 1) {
|
|
14633
|
+
const parent = dirname7(current);
|
|
14634
|
+
let entries;
|
|
14635
|
+
try {
|
|
14636
|
+
entries = readdirSync(parent);
|
|
14637
|
+
} catch {
|
|
14638
|
+
return false;
|
|
14639
|
+
}
|
|
14640
|
+
if (!entries.includes(basename2(current))) {
|
|
14641
|
+
return false;
|
|
14642
|
+
}
|
|
14643
|
+
current = parent;
|
|
14644
|
+
}
|
|
14645
|
+
const stat2 = statSync(abs, { throwIfNoEntry: false });
|
|
14646
|
+
return stat2 !== undefined && stat2.isFile();
|
|
14647
|
+
};
|
|
14648
|
+
var resolveRelativeImage = (sourceDir, target) => {
|
|
14649
|
+
if (!isRelativeImageTarget(target)) {
|
|
14541
14650
|
return null;
|
|
14542
14651
|
}
|
|
14652
|
+
const decoded = decodeTarget(target);
|
|
14653
|
+
const segments = normalize3(decoded).split("/").filter((part) => part !== "" && part !== "..").length;
|
|
14543
14654
|
const abs = resolve5(sourceDir, decoded);
|
|
14544
|
-
return
|
|
14655
|
+
return existsAsWritten(abs, segments) ? abs : null;
|
|
14545
14656
|
};
|
|
14546
14657
|
var encodedParam = (param) => param.split("/").map(encodeURIComponent).join("/");
|
|
14547
14658
|
var rewriteLine = (line, toUrl2) => {
|
|
@@ -15259,13 +15370,13 @@ var buildSignaturesDirectory = (config) => {
|
|
|
15259
15370
|
};
|
|
15260
15371
|
|
|
15261
15372
|
// src/core/gitignore.ts
|
|
15262
|
-
import { existsSync as
|
|
15373
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
15263
15374
|
import { readFile as readFile12, writeFile as writeFile6 } from "node:fs/promises";
|
|
15264
15375
|
import { join as join19 } from "pathe";
|
|
15265
15376
|
var gitignoreKey = (line) => line.trim().replace(/\/+$/u, "");
|
|
15266
15377
|
var ensureGitignore = async (root, entries) => {
|
|
15267
15378
|
const path = join19(root, ".gitignore");
|
|
15268
|
-
const existing =
|
|
15379
|
+
const existing = existsSync9(path) ? await readFile12(path, "utf-8") : "";
|
|
15269
15380
|
const present = new Set(existing.split(`
|
|
15270
15381
|
`).flatMap((line) => {
|
|
15271
15382
|
const key = gitignoreKey(line);
|
|
@@ -15293,6 +15404,9 @@ var serverFeatures = (config) => {
|
|
|
15293
15404
|
if (config.ai.mcp.enabled) {
|
|
15294
15405
|
features.push("MCP server");
|
|
15295
15406
|
}
|
|
15407
|
+
if (config.openapi.enabled && config.openapi.renderer === "blume" && config.openapi.playground.enabled && config.openapi.playground.proxy === true) {
|
|
15408
|
+
features.push("API playground proxy");
|
|
15409
|
+
}
|
|
15296
15410
|
if (searchProviderMeta(config.search.provider).requiresServer) {
|
|
15297
15411
|
features.push(`Search (${config.search.provider})`);
|
|
15298
15412
|
}
|
|
@@ -16241,7 +16355,7 @@ var syncSearchProvider = async (project, reporter) => {
|
|
|
16241
16355
|
|
|
16242
16356
|
// src/cli/dev-lock.ts
|
|
16243
16357
|
import {
|
|
16244
|
-
existsSync as
|
|
16358
|
+
existsSync as existsSync10,
|
|
16245
16359
|
mkdirSync,
|
|
16246
16360
|
readFileSync as readFileSync5,
|
|
16247
16361
|
rmSync,
|
|
@@ -16280,7 +16394,7 @@ var isProcessAlive = (pid) => {
|
|
|
16280
16394
|
};
|
|
16281
16395
|
var readDevLock = (outDir) => {
|
|
16282
16396
|
const path = lockPath(outDir);
|
|
16283
|
-
if (!
|
|
16397
|
+
if (!existsSync10(path)) {
|
|
16284
16398
|
return null;
|
|
16285
16399
|
}
|
|
16286
16400
|
const lock = parseLock(readFileSync5(path, "utf-8"));
|
|
@@ -16307,7 +16421,7 @@ class DevLockHeldError extends Error {
|
|
|
16307
16421
|
}
|
|
16308
16422
|
var ownsLock = (outDir) => {
|
|
16309
16423
|
const path = lockPath(outDir);
|
|
16310
|
-
if (!
|
|
16424
|
+
if (!existsSync10(path)) {
|
|
16311
16425
|
return false;
|
|
16312
16426
|
}
|
|
16313
16427
|
try {
|
|
@@ -16365,7 +16479,7 @@ var refuseIfDevRunning = (root, action, options = {}) => {
|
|
|
16365
16479
|
|
|
16366
16480
|
// src/astro/generate.ts
|
|
16367
16481
|
import { createHash as createHash4 } from "node:crypto";
|
|
16368
|
-
import { existsSync as
|
|
16482
|
+
import { existsSync as existsSync15, readFileSync as readFileSync8, realpathSync } from "node:fs";
|
|
16369
16483
|
import {
|
|
16370
16484
|
lstat,
|
|
16371
16485
|
mkdir as mkdir7,
|
|
@@ -16379,7 +16493,7 @@ import { createRequire as createRequire4 } from "node:module";
|
|
|
16379
16493
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
16380
16494
|
import { imageSize as imageSize2 } from "image-size";
|
|
16381
16495
|
import pMap6 from "p-map";
|
|
16382
|
-
import { basename as
|
|
16496
|
+
import { basename as basename4, dirname as dirname11, join as join28, normalize as normalize4, relative as relative14, resolve as resolve8 } from "pathe";
|
|
16383
16497
|
import { glob as glob7 } from "tinyglobby";
|
|
16384
16498
|
|
|
16385
16499
|
// src/ai/ask-data.ts
|
|
@@ -16628,7 +16742,7 @@ var validateUsedComponents = (pages, extraTags, registryNames) => {
|
|
|
16628
16742
|
};
|
|
16629
16743
|
|
|
16630
16744
|
// src/core/component-overrides.ts
|
|
16631
|
-
import { existsSync as
|
|
16745
|
+
import { existsSync as existsSync11 } from "node:fs";
|
|
16632
16746
|
import { dirname as dirname8, extname as extname7, isAbsolute as isAbsolute6, resolve as resolve6 } from "pathe";
|
|
16633
16747
|
import ts from "typescript";
|
|
16634
16748
|
var GROUPS = ["mdx", "layout", "islands"];
|
|
@@ -16723,7 +16837,7 @@ var findDefaultExportObject = (sourceFile) => {
|
|
|
16723
16837
|
var probeExtension = (base) => {
|
|
16724
16838
|
for (const extension of COMPONENT_EXTS) {
|
|
16725
16839
|
const candidate = `${base}.${extension}`;
|
|
16726
|
-
if (
|
|
16840
|
+
if (existsSync11(candidate)) {
|
|
16727
16841
|
return candidate;
|
|
16728
16842
|
}
|
|
16729
16843
|
}
|
|
@@ -16902,7 +17016,7 @@ var writeTextAtomic = async (path, text) => {
|
|
|
16902
17016
|
};
|
|
16903
17017
|
|
|
16904
17018
|
// src/core/tsconfig-aliases.ts
|
|
16905
|
-
import { existsSync as
|
|
17019
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
16906
17020
|
import { parseTsconfig } from "get-tsconfig";
|
|
16907
17021
|
import { dirname as dirname10, join as join22, resolve as resolve7 } from "pathe";
|
|
16908
17022
|
var CONFIG_DIR_TEMPLATE = "${configDir}";
|
|
@@ -16924,7 +17038,7 @@ var toAlias = (key, value, baseDir, configDir) => {
|
|
|
16924
17038
|
};
|
|
16925
17039
|
};
|
|
16926
17040
|
var resolveTsconfigAliases = (root) => {
|
|
16927
|
-
const entry = ["tsconfig.json", "jsconfig.json"].map((name) => join22(root, name)).find((file) =>
|
|
17041
|
+
const entry = ["tsconfig.json", "jsconfig.json"].map((name) => join22(root, name)).find((file) => existsSync12(file));
|
|
16928
17042
|
if (!entry) {
|
|
16929
17043
|
return {};
|
|
16930
17044
|
}
|
|
@@ -16951,7 +17065,7 @@ var resolveTsconfigAliases = (root) => {
|
|
|
16951
17065
|
};
|
|
16952
17066
|
|
|
16953
17067
|
// src/og/derive.ts
|
|
16954
|
-
import { existsSync as
|
|
17068
|
+
import { existsSync as existsSync13 } from "node:fs";
|
|
16955
17069
|
import { isAbsolute as isAbsolute7, join as join23 } from "pathe";
|
|
16956
17070
|
var CARD_WEIGHTS = [400, 600];
|
|
16957
17071
|
var absoluteSrc = (root, src) => isAbsolute7(src) ? src : join23(root, src);
|
|
@@ -17055,11 +17169,11 @@ var missingFontFiles = (options, root) => {
|
|
|
17055
17169
|
sources.push(absoluteSrc(root, font.src));
|
|
17056
17170
|
}
|
|
17057
17171
|
}
|
|
17058
|
-
return [...new Set(sources)].filter((path) => !
|
|
17172
|
+
return [...new Set(sources)].filter((path) => !existsSync13(path));
|
|
17059
17173
|
};
|
|
17060
17174
|
|
|
17061
17175
|
// src/og/logo.ts
|
|
17062
|
-
import { existsSync as
|
|
17176
|
+
import { existsSync as existsSync14, readFileSync as readFileSync6 } from "node:fs";
|
|
17063
17177
|
import { join as join24 } from "pathe";
|
|
17064
17178
|
var resolveOgLogo = (project, source) => {
|
|
17065
17179
|
if (!source?.toLowerCase().endsWith(".svg")) {
|
|
@@ -17069,7 +17183,7 @@ var resolveOgLogo = (project, source) => {
|
|
|
17069
17183
|
const file = [
|
|
17070
17184
|
join24(project.context.root, "public", relative13),
|
|
17071
17185
|
join24(project.context.root, relative13)
|
|
17072
|
-
].find((path) =>
|
|
17186
|
+
].find((path) => existsSync14(path));
|
|
17073
17187
|
return file ? readFileSync6(file, "utf-8") : undefined;
|
|
17074
17188
|
};
|
|
17075
17189
|
|
|
@@ -17435,21 +17549,12 @@ ${THEME_MAPPING}
|
|
|
17435
17549
|
}
|
|
17436
17550
|
}
|
|
17437
17551
|
|
|
17438
|
-
/* Same-origin navigations
|
|
17439
|
-
|
|
17440
|
-
|
|
17441
|
-
|
|
17442
|
-
|
|
17443
|
-
|
|
17444
|
-
}
|
|
17445
|
-
|
|
17446
|
-
@media (prefers-reduced-motion: reduce) {
|
|
17447
|
-
::view-transition-group(*),
|
|
17448
|
-
::view-transition-old(*),
|
|
17449
|
-
::view-transition-new(*) {
|
|
17450
|
-
animation: none !important;
|
|
17451
|
-
}
|
|
17452
|
-
}
|
|
17552
|
+
/* Same-origin navigations ride Astro's client router (the layouts render
|
|
17553
|
+
ClientRouter), which owns the page-transition styling — including its own
|
|
17554
|
+
prefers-reduced-motion guard — so the theme declares nothing about it. The
|
|
17555
|
+
cross-document view-transition opt-in that briefly lived here is
|
|
17556
|
+
deliberately gone: mixing it with the client router double-animates the
|
|
17557
|
+
full-load navigations the router hands back to the browser. */
|
|
17453
17558
|
|
|
17454
17559
|
/* Code reads left-to-right regardless of page direction; only the surrounding
|
|
17455
17560
|
chrome mirrors for RTL. Inline code is isolated so LTR identifiers don't
|
|
@@ -18230,7 +18335,7 @@ import { glob as glob6 } from "tinyglobby";
|
|
|
18230
18335
|
// src/astro/islands.ts
|
|
18231
18336
|
import { readFile as readFile14 } from "node:fs/promises";
|
|
18232
18337
|
import pMap4 from "p-map";
|
|
18233
|
-
import { basename as
|
|
18338
|
+
import { basename as basename3, join as join26 } from "pathe";
|
|
18234
18339
|
import { glob as glob5 } from "tinyglobby";
|
|
18235
18340
|
var DEFAULT_CLIENT = "visible";
|
|
18236
18341
|
var READ_CONCURRENCY2 = 16;
|
|
@@ -18275,7 +18380,7 @@ var discoverIslands = async (root) => {
|
|
|
18275
18380
|
const warnings = [];
|
|
18276
18381
|
const seen = new Map;
|
|
18277
18382
|
const collectIsland = (file, source) => {
|
|
18278
|
-
const base =
|
|
18383
|
+
const base = basename3(file);
|
|
18279
18384
|
const ext = base.match(ISLAND_FILE)?.groups?.ext;
|
|
18280
18385
|
const framework = ext ? FRAMEWORK_BY_EXT2.get(ext) : undefined;
|
|
18281
18386
|
if (!framework) {
|
|
@@ -18403,7 +18508,7 @@ var resolveAstroPackageJson = (modulesDir) => {
|
|
|
18403
18508
|
}
|
|
18404
18509
|
};
|
|
18405
18510
|
var resolvedAstroHit = (fromDir) => {
|
|
18406
|
-
let dir =
|
|
18511
|
+
let dir = normalize4(fromDir);
|
|
18407
18512
|
while (true) {
|
|
18408
18513
|
const modulesDir = join28(dir, "node_modules");
|
|
18409
18514
|
const pkg = resolveAstroPackageJson(modulesDir);
|
|
@@ -18428,7 +18533,7 @@ var depsCandidates = (pkgDir) => [
|
|
|
18428
18533
|
join28(pkgDir, "node_modules"),
|
|
18429
18534
|
dirname11(pkgDir)
|
|
18430
18535
|
];
|
|
18431
|
-
var candidateHolding = (pkgDir, ...segments) => depsCandidates(pkgDir).find((dir) =>
|
|
18536
|
+
var candidateHolding = (pkgDir, ...segments) => depsCandidates(pkgDir).find((dir) => existsSync15(join28(dir, ...segments))) ?? null;
|
|
18432
18537
|
var linkDepsJunction = async (link, depsDir) => {
|
|
18433
18538
|
let existing;
|
|
18434
18539
|
try {
|
|
@@ -18564,7 +18669,7 @@ var writeExamplesPreview = async (options) => {
|
|
|
18564
18669
|
await write(join28(srcDir, "pages", ...config.basePath.split("/").filter(Boolean), "blume-examples", "[...path].astro"), examplesPageTemplate());
|
|
18565
18670
|
}
|
|
18566
18671
|
const cssFile = examplesCssFile(root, config);
|
|
18567
|
-
return cssFile && !
|
|
18672
|
+
return cssFile && !existsSync15(cssFile) ? [
|
|
18568
18673
|
`examples.css points at "${config.examples.css}", which doesn't exist; previews render without it.`
|
|
18569
18674
|
] : [];
|
|
18570
18675
|
};
|
|
@@ -18630,7 +18735,7 @@ var pruneOrphans = async (srcDir, written) => {
|
|
|
18630
18735
|
});
|
|
18631
18736
|
const removals = [];
|
|
18632
18737
|
for (const path of existing) {
|
|
18633
|
-
const normalized =
|
|
18738
|
+
const normalized = normalize4(path);
|
|
18634
18739
|
if (!written.has(normalized)) {
|
|
18635
18740
|
removals.push(rm2(normalized, { force: true }));
|
|
18636
18741
|
}
|
|
@@ -18651,10 +18756,10 @@ var writeStagedContent = async (out, staged) => {
|
|
|
18651
18756
|
const written = new Set;
|
|
18652
18757
|
await Promise.all([...staged].map(async ([entryId, text]) => {
|
|
18653
18758
|
const path = join28(contentDir, entryId);
|
|
18654
|
-
written.add(
|
|
18759
|
+
written.add(normalize4(path));
|
|
18655
18760
|
await writeIfChanged(path, text);
|
|
18656
18761
|
}));
|
|
18657
|
-
if (
|
|
18762
|
+
if (existsSync15(contentDir)) {
|
|
18658
18763
|
await pruneOrphans(contentDir, written);
|
|
18659
18764
|
}
|
|
18660
18765
|
};
|
|
@@ -18677,7 +18782,7 @@ var readLogoSvg = (project, source) => {
|
|
|
18677
18782
|
const file = [
|
|
18678
18783
|
join28(project.context.root, "public", rel),
|
|
18679
18784
|
join28(project.context.root, rel)
|
|
18680
|
-
].find((path) =>
|
|
18785
|
+
].find((path) => existsSync15(path));
|
|
18681
18786
|
return file ? readFileSync8(file, "utf-8") : undefined;
|
|
18682
18787
|
};
|
|
18683
18788
|
var isStringShorthand = (value) => typeof value === "string";
|
|
@@ -18711,6 +18816,7 @@ var FAVICON_CANDIDATES = [
|
|
|
18711
18816
|
"favicon.ico",
|
|
18712
18817
|
"icon.ico"
|
|
18713
18818
|
];
|
|
18819
|
+
var darkSibling = (name) => name.replace(/\.(?=[^.]+$)/u, "-dark.");
|
|
18714
18820
|
var FAVICON_TYPES = new Map([
|
|
18715
18821
|
["ico", "image/x-icon"],
|
|
18716
18822
|
["jpeg", "image/jpeg"],
|
|
@@ -18724,6 +18830,10 @@ var faviconType = (name) => {
|
|
|
18724
18830
|
};
|
|
18725
18831
|
var inlineDataUri = (file, type) => `data:${type};base64,${readFileSync8(file).toString("base64")}`;
|
|
18726
18832
|
var defaultFavicon = () => ({
|
|
18833
|
+
dark: {
|
|
18834
|
+
href: inlineDataUri(join28(BLUME_SRC, "assets", "icon-dark.png"), "image/png"),
|
|
18835
|
+
type: "image/png"
|
|
18836
|
+
},
|
|
18727
18837
|
href: inlineDataUri(join28(BLUME_SRC, "assets", "icon.png"), "image/png"),
|
|
18728
18838
|
type: "image/png"
|
|
18729
18839
|
});
|
|
@@ -18736,20 +18846,43 @@ var APPLE_ICON_CANDIDATES = [
|
|
|
18736
18846
|
var resolveIconFile = (project, candidates) => {
|
|
18737
18847
|
const { root } = project.context;
|
|
18738
18848
|
for (const name of candidates) {
|
|
18739
|
-
if (
|
|
18849
|
+
if (existsSync15(join28(root, "public", name))) {
|
|
18740
18850
|
return { href: `/${name}`, type: faviconType(name) };
|
|
18741
18851
|
}
|
|
18742
18852
|
}
|
|
18743
18853
|
for (const name of candidates) {
|
|
18744
18854
|
const file = join28(root, name);
|
|
18745
|
-
if (
|
|
18855
|
+
if (existsSync15(file)) {
|
|
18746
18856
|
const type = faviconType(name);
|
|
18747
18857
|
return { href: inlineDataUri(file, type ?? "image/x-icon"), type };
|
|
18748
18858
|
}
|
|
18749
18859
|
}
|
|
18750
18860
|
return null;
|
|
18751
18861
|
};
|
|
18752
|
-
var resolveFavicon = (project) =>
|
|
18862
|
+
var resolveFavicon = (project) => {
|
|
18863
|
+
const { root } = project.context;
|
|
18864
|
+
for (const name of FAVICON_CANDIDATES) {
|
|
18865
|
+
if (existsSync15(join28(root, "public", name))) {
|
|
18866
|
+
const type = faviconType(name);
|
|
18867
|
+
const sibling = darkSibling(name);
|
|
18868
|
+
return existsSync15(join28(root, "public", sibling)) ? { dark: { href: `/${sibling}`, type }, href: `/${name}`, type } : { href: `/${name}`, type };
|
|
18869
|
+
}
|
|
18870
|
+
}
|
|
18871
|
+
for (const name of FAVICON_CANDIDATES) {
|
|
18872
|
+
const file = join28(root, name);
|
|
18873
|
+
if (existsSync15(file)) {
|
|
18874
|
+
const type = faviconType(name);
|
|
18875
|
+
const mime = type ?? "image/x-icon";
|
|
18876
|
+
const siblingFile = join28(root, darkSibling(name));
|
|
18877
|
+
return existsSync15(siblingFile) ? {
|
|
18878
|
+
dark: { href: inlineDataUri(siblingFile, mime), type },
|
|
18879
|
+
href: inlineDataUri(file, mime),
|
|
18880
|
+
type
|
|
18881
|
+
} : { href: inlineDataUri(file, mime), type };
|
|
18882
|
+
}
|
|
18883
|
+
}
|
|
18884
|
+
return resolveIconFile(project, FAVICON_CANDIDATES.map(darkSibling)) ?? defaultFavicon();
|
|
18885
|
+
};
|
|
18753
18886
|
var resolveAppleIcon = (project) => resolveIconFile(project, APPLE_ICON_CANDIDATES);
|
|
18754
18887
|
var resolveBanner = (config) => {
|
|
18755
18888
|
const { banner } = config;
|
|
@@ -18876,6 +19009,7 @@ var buildRuntimeData = (project) => {
|
|
|
18876
19009
|
palette: config.seo.og.palette,
|
|
18877
19010
|
site: resolveOgSite(config)
|
|
18878
19011
|
},
|
|
19012
|
+
openInChat: config.ai.openInChat,
|
|
18879
19013
|
repoUrl,
|
|
18880
19014
|
search: {
|
|
18881
19015
|
enabled: config.search.provider !== "none",
|
|
@@ -18989,6 +19123,30 @@ var writeMcpFiles = async (project, plan, write) => {
|
|
|
18989
19123
|
write(join28(plan.dir, "server-card.ts"), staticJsonEndpointTemplate(buildMcpServerCard(discoveryInput)))
|
|
18990
19124
|
]);
|
|
18991
19125
|
};
|
|
19126
|
+
var planPlaygroundProxy = (config, srcDir) => ({
|
|
19127
|
+
enabled: config.openapi.enabled && config.openapi.renderer === "blume" && config.openapi.playground.enabled && config.openapi.playground.proxy === true,
|
|
19128
|
+
entrypoint: join28(srcDir, "blume-openapi", "api-proxy.ts"),
|
|
19129
|
+
pattern: "/_api-proxy"
|
|
19130
|
+
});
|
|
19131
|
+
var specOrigins = (data) => {
|
|
19132
|
+
const origins = new Set;
|
|
19133
|
+
for (const spec of Object.values(data)) {
|
|
19134
|
+
const { servers } = spec.document;
|
|
19135
|
+
for (const server of Array.isArray(servers) ? servers : []) {
|
|
19136
|
+
const url = server.url ?? "";
|
|
19137
|
+
if (url.includes("{")) {
|
|
19138
|
+
continue;
|
|
19139
|
+
}
|
|
19140
|
+
try {
|
|
19141
|
+
origins.add(new URL(url).origin);
|
|
19142
|
+
} catch {}
|
|
19143
|
+
}
|
|
19144
|
+
}
|
|
19145
|
+
return [...origins].toSorted();
|
|
19146
|
+
};
|
|
19147
|
+
var proxyAllowlistWarnings = (enabled, origins) => enabled && origins.length === 0 ? [
|
|
19148
|
+
"openapi.playground.proxy is enabled, but no spec declares an absolute servers[].url (relative and templated URLs carry no origin), so the proxy's allowlist is empty and it will refuse every request. Add an absolute server URL to the spec, or point playground.proxy at an external proxy URL."
|
|
19149
|
+
] : [];
|
|
18992
19150
|
var writeAskFiles = async (project, srcDir, write) => {
|
|
18993
19151
|
const { ask } = project.config.ai;
|
|
18994
19152
|
if (!(ask?.enabled && !ask.endpoint)) {
|
|
@@ -18999,7 +19157,10 @@ var writeAskFiles = async (project, srcDir, write) => {
|
|
|
18999
19157
|
await write(join28(srcDir, "generated", "ask-data.json"), `${JSON.stringify(await buildAskData(project))}
|
|
19000
19158
|
`);
|
|
19001
19159
|
}
|
|
19002
|
-
await write(join28(srcDir, "pages", "api", "ask.ts"), askEndpointTemplate(resolveAskBackend(ask), grounded,
|
|
19160
|
+
await write(join28(srcDir, "pages", "api", "ask.ts"), askEndpointTemplate(resolveAskBackend(ask), grounded, {
|
|
19161
|
+
instructions: ask.instructions,
|
|
19162
|
+
retrieval: ask.retrieval
|
|
19163
|
+
}));
|
|
19003
19164
|
};
|
|
19004
19165
|
var writeNotFoundPage = async (write, srcDir, pages, contentPages) => {
|
|
19005
19166
|
if (routeIsTaken(pages, contentPages, "/404")) {
|
|
@@ -19047,7 +19208,7 @@ var generateRuntime = async (project) => {
|
|
|
19047
19208
|
const openapiPath = join28(srcDir, "generated", "openapi.json");
|
|
19048
19209
|
const written = new Set;
|
|
19049
19210
|
const write = (path, content) => {
|
|
19050
|
-
written.add(
|
|
19211
|
+
written.add(normalize4(path));
|
|
19051
19212
|
return writeIfChanged(path, content);
|
|
19052
19213
|
};
|
|
19053
19214
|
const depsLinkWarning = await ensureDepsLink(out);
|
|
@@ -19095,6 +19256,16 @@ var generateRuntime = async (project) => {
|
|
|
19095
19256
|
const changelogIndex = hasGeneratedChangelog(project, pages);
|
|
19096
19257
|
const mcp = planMcp(project, srcDir, pages);
|
|
19097
19258
|
pages.push(...mcp.discoveryPages);
|
|
19259
|
+
const openApiSource2 = project.sources.find(isOpenApiSource);
|
|
19260
|
+
const openApiData = openApiSource2 ? openApiSource2.openApiData() : {};
|
|
19261
|
+
const playgroundProxy = planPlaygroundProxy(config, srcDir);
|
|
19262
|
+
if (playgroundProxy.enabled) {
|
|
19263
|
+
pages.push({
|
|
19264
|
+
entrypoint: playgroundProxy.entrypoint,
|
|
19265
|
+
pattern: playgroundProxy.pattern
|
|
19266
|
+
});
|
|
19267
|
+
}
|
|
19268
|
+
const proxyOrigins = specOrigins(openApiData);
|
|
19098
19269
|
const hasStaged = staged.size > 0;
|
|
19099
19270
|
const hasFilesystemSource = project.sources.some((source) => !source.staged);
|
|
19100
19271
|
const docsCollection = resolveDocsCollection(config, context);
|
|
@@ -19159,7 +19330,8 @@ var generateRuntime = async (project) => {
|
|
|
19159
19330
|
Promise.all(slotPlan.wrappers.map((wrapper) => write(join28(srcDir, "generated", "component-slots", `${wrapper.name}.astro`), wrapper.content))),
|
|
19160
19331
|
Promise.all(exampleDiscovery.examples.map((example) => write(join28(srcDir, "generated", "examples", `${exampleSlug(example.path)}.astro`), exampleWrapperTemplate(example)))),
|
|
19161
19332
|
writeAskFiles(project, srcDir, write),
|
|
19162
|
-
writeMcpFiles(project, mcp, write)
|
|
19333
|
+
writeMcpFiles(project, mcp, write),
|
|
19334
|
+
playgroundProxy.enabled ? write(playgroundProxy.entrypoint, playgroundProxyTemplate(proxyOrigins)) : Promise.resolve(false)
|
|
19163
19335
|
]);
|
|
19164
19336
|
if (config.seo.og.enabled) {
|
|
19165
19337
|
await write(join28(srcDir, "pages", "og", "[...slug].png.ts"), ogEndpointTemplate(ogRoutes, projectOgFonts(project), changelogIndex));
|
|
@@ -19214,6 +19386,7 @@ var generateRuntime = async (project) => {
|
|
|
19214
19386
|
}
|
|
19215
19387
|
const warnings = [
|
|
19216
19388
|
...depsLinkWarning ? [depsLinkWarning] : [],
|
|
19389
|
+
...proxyAllowlistWarnings(playgroundProxy.enabled, proxyOrigins),
|
|
19217
19390
|
...reactCompilerWarnings(config, needsReact, reactCompilerPath),
|
|
19218
19391
|
...mcp.warnings,
|
|
19219
19392
|
...islandDiscovery.warnings,
|
|
@@ -19247,10 +19420,9 @@ var generateRuntime = async (project) => {
|
|
|
19247
19420
|
warnings.push(...references.warnings);
|
|
19248
19421
|
await Promise.all(references.files.map((file) => write(join28(srcDir, "pages", file.pagePath), file.content)));
|
|
19249
19422
|
}
|
|
19250
|
-
const openApiSource2 = project.sources.find(isOpenApiSource);
|
|
19251
19423
|
await Promise.all([
|
|
19252
19424
|
write(join28(srcDir, "generated", "data.json"), buildRuntimeData(project)),
|
|
19253
|
-
write(openapiPath, `${JSON.stringify(
|
|
19425
|
+
write(openapiPath, `${JSON.stringify(openApiData)}
|
|
19254
19426
|
`),
|
|
19255
19427
|
write(join28(out, "blume.manifest.json"), `${JSON.stringify(project.manifest, null, 2)}
|
|
19256
19428
|
`),
|
|
@@ -19261,7 +19433,7 @@ var generateRuntime = async (project) => {
|
|
|
19261
19433
|
};
|
|
19262
19434
|
|
|
19263
19435
|
// src/cli/env.ts
|
|
19264
|
-
import { existsSync as
|
|
19436
|
+
import { existsSync as existsSync16 } from "node:fs";
|
|
19265
19437
|
import { config } from "dotenv";
|
|
19266
19438
|
import { dirname as dirname12, join as join29, resolve as resolve9 } from "pathe";
|
|
19267
19439
|
var loadEnvFiles = (startDir) => {
|
|
@@ -19271,7 +19443,7 @@ var loadEnvFiles = (startDir) => {
|
|
|
19271
19443
|
while (!done) {
|
|
19272
19444
|
paths.push(join29(dir, ".env.local"), join29(dir, ".env"));
|
|
19273
19445
|
const parent = dirname12(dir);
|
|
19274
|
-
done =
|
|
19446
|
+
done = existsSync16(join29(dir, ".git")) || parent === dir;
|
|
19275
19447
|
dir = parent;
|
|
19276
19448
|
}
|
|
19277
19449
|
config({ path: paths, quiet: true });
|
|
@@ -19383,17 +19555,17 @@ var emitRedirectFiles = async (config2, distDir) => {
|
|
|
19383
19555
|
{ content: buildNetlifyRedirects(redirects), name: "_redirects" },
|
|
19384
19556
|
{ content: buildVercelConfig(redirects), name: "vercel.json" }
|
|
19385
19557
|
];
|
|
19386
|
-
await Promise.all(platformFiles.map((file) =>
|
|
19558
|
+
await Promise.all(platformFiles.map((file) => existsSync17(join30(distDir, file.name)) ? Promise.resolve() : writeFile7(join30(distDir, file.name), file.content, "utf-8")));
|
|
19387
19559
|
logger.success(`Emitted redirect files for ${redirects.length} redirect(s)`);
|
|
19388
19560
|
};
|
|
19389
19561
|
var emitHeaderFiles = async (project, distDir) => {
|
|
19390
19562
|
const { config: config2 } = project;
|
|
19391
|
-
if (!readsHeaderFiles(config2.deployment) ||
|
|
19563
|
+
if (!readsHeaderFiles(config2.deployment) || existsSync17(join30(project.context.root, "public", "_headers"))) {
|
|
19392
19564
|
return;
|
|
19393
19565
|
}
|
|
19394
19566
|
const ours = buildNetlifyHeaders(config2, buildHomeLinkHeader(config2, markdownRoutePaths(project)));
|
|
19395
19567
|
const target = join30(distDir, "_headers");
|
|
19396
|
-
const existing =
|
|
19568
|
+
const existing = existsSync17(target) ? await readFile17(target, "utf-8") : "";
|
|
19397
19569
|
await writeFile7(target, existing ? `${existing.trimEnd()}
|
|
19398
19570
|
${ours}` : ours, "utf-8");
|
|
19399
19571
|
logger.success("Emitted _headers (UTF-8 Content-Type + homepage Link header)");
|
|
@@ -19404,12 +19576,12 @@ var emitAgentSkills = async (project, distDir) => {
|
|
|
19404
19576
|
return;
|
|
19405
19577
|
}
|
|
19406
19578
|
const dir = resolve10(project.context.root, configured);
|
|
19407
|
-
if (!
|
|
19579
|
+
if (!existsSync17(dir)) {
|
|
19408
19580
|
logger.warn(`ai.skills points at "${configured}" (${dir}), which does not exist; no skills published.`);
|
|
19409
19581
|
return;
|
|
19410
19582
|
}
|
|
19411
19583
|
const outDir = join30(distDir, AGENT_SKILLS_DIR.slice(1));
|
|
19412
|
-
if (
|
|
19584
|
+
if (existsSync17(join30(outDir, "index.json"))) {
|
|
19413
19585
|
return;
|
|
19414
19586
|
}
|
|
19415
19587
|
const { skills, warnings } = await collectSkills(dir);
|
|
@@ -19443,7 +19615,7 @@ var emitWellKnownFiles = async (config2, distDir) => {
|
|
|
19443
19615
|
];
|
|
19444
19616
|
for (const file of files) {
|
|
19445
19617
|
const target = join30(distDir, file.path.slice(1));
|
|
19446
|
-
if (!file.content ||
|
|
19618
|
+
if (!file.content || existsSync17(target)) {
|
|
19447
19619
|
continue;
|
|
19448
19620
|
}
|
|
19449
19621
|
await mkdir8(join30(distDir, ".well-known"), { recursive: true });
|
|
@@ -19454,7 +19626,7 @@ var emitWellKnownFiles = async (config2, distDir) => {
|
|
|
19454
19626
|
var emitVercelNegotiation = async (project, routePaths, root) => {
|
|
19455
19627
|
const { config: config2 } = project;
|
|
19456
19628
|
const configPath = join30(root, ".vercel", "output", "config.json");
|
|
19457
|
-
if (!
|
|
19629
|
+
if (!existsSync17(configPath)) {
|
|
19458
19630
|
return;
|
|
19459
19631
|
}
|
|
19460
19632
|
const overrides = {};
|
|
@@ -19479,7 +19651,7 @@ var emitCloudflareNegotiation = async (project, routePaths) => {
|
|
|
19479
19651
|
const { config: config2, context } = project;
|
|
19480
19652
|
const serverDir = join30(context.distDir ?? join30(context.root, "dist"), "server");
|
|
19481
19653
|
const wranglerPath = join30(serverDir, "wrangler.json");
|
|
19482
|
-
if (!
|
|
19654
|
+
if (!existsSync17(wranglerPath)) {
|
|
19483
19655
|
warnCloudflareNegotiationSkipped();
|
|
19484
19656
|
return;
|
|
19485
19657
|
}
|
|
@@ -19510,7 +19682,7 @@ var formatBytes2 = (bytes) => {
|
|
|
19510
19682
|
};
|
|
19511
19683
|
var astroAssets = async (distDir, ext) => {
|
|
19512
19684
|
const astroDir = join30(distDir, "_astro");
|
|
19513
|
-
if (!
|
|
19685
|
+
if (!existsSync17(astroDir)) {
|
|
19514
19686
|
return [];
|
|
19515
19687
|
}
|
|
19516
19688
|
const entries = await readdir2(astroDir);
|
|
@@ -19587,8 +19759,8 @@ var isolatedStaticDir = (config2, context) => {
|
|
|
19587
19759
|
var publishLlmsFiles = async (project, distDir) => {
|
|
19588
19760
|
const indexPath = join30(distDir, "llms.txt");
|
|
19589
19761
|
const fullPath = join30(distDir, "llms-full.txt");
|
|
19590
|
-
const writeIndex = !
|
|
19591
|
-
const writeFull = !
|
|
19762
|
+
const writeIndex = !existsSync17(indexPath);
|
|
19763
|
+
const writeFull = !existsSync17(fullPath);
|
|
19592
19764
|
if (!(writeIndex || writeFull)) {
|
|
19593
19765
|
return;
|
|
19594
19766
|
}
|
|
@@ -19621,17 +19793,17 @@ var publishBuildArtifacts = async (project, distDir, args) => {
|
|
|
19621
19793
|
await publishLlmsFiles(project, distDir);
|
|
19622
19794
|
}
|
|
19623
19795
|
const sitemapFiles = buildSitemapFiles(project);
|
|
19624
|
-
if (sitemapFiles && !
|
|
19796
|
+
if (sitemapFiles && !existsSync17(join30(distDir, "sitemap.xml"))) {
|
|
19625
19797
|
await Promise.all(sitemapFiles.map((file) => writeFile7(join30(distDir, file.name), file.xml, "utf-8")));
|
|
19626
19798
|
logger.success(sitemapFiles.length === 1 ? "Generated sitemap.xml" : `Generated sitemap.xml (index of ${sitemapFiles.length - 1} sitemap files)`);
|
|
19627
19799
|
}
|
|
19628
19800
|
const robots = buildRobots(project);
|
|
19629
|
-
if (robots && !
|
|
19801
|
+
if (robots && !existsSync17(join30(distDir, "robots.txt"))) {
|
|
19630
19802
|
await writeFile7(join30(distDir, "robots.txt"), robots, "utf-8");
|
|
19631
19803
|
logger.success("Generated robots.txt");
|
|
19632
19804
|
}
|
|
19633
19805
|
const agentReadability = buildAgentReadability(project);
|
|
19634
|
-
if (agentReadability && !
|
|
19806
|
+
if (agentReadability && !existsSync17(join30(distDir, "agent-readability.json"))) {
|
|
19635
19807
|
await writeFile7(join30(distDir, "agent-readability.json"), `${JSON.stringify(agentReadability, null, 2)}
|
|
19636
19808
|
`, "utf-8");
|
|
19637
19809
|
logger.success("Generated agent-readability.json");
|
|
@@ -19764,7 +19936,7 @@ var buildCommand = defineCommand3({
|
|
|
19764
19936
|
});
|
|
19765
19937
|
|
|
19766
19938
|
// src/cli/commands/check.ts
|
|
19767
|
-
import { existsSync as
|
|
19939
|
+
import { existsSync as existsSync18 } from "node:fs";
|
|
19768
19940
|
import { check } from "@astrojs/check";
|
|
19769
19941
|
import { sync } from "astro";
|
|
19770
19942
|
import { defineCommand as defineCommand4 } from "citty";
|
|
@@ -19810,7 +19982,7 @@ var checkCommand = defineCommand4({
|
|
|
19810
19982
|
minimumFailingSeverity: "error",
|
|
19811
19983
|
minimumSeverity: "hint",
|
|
19812
19984
|
root: outDir,
|
|
19813
|
-
tsconfig:
|
|
19985
|
+
tsconfig: existsSync18(tsconfig) ? tsconfig : undefined,
|
|
19814
19986
|
watch: false
|
|
19815
19987
|
});
|
|
19816
19988
|
if (failed) {
|
|
@@ -20092,13 +20264,13 @@ import { defineCommand as defineCommand7 } from "citty";
|
|
|
20092
20264
|
import { relative as relative17 } from "pathe";
|
|
20093
20265
|
|
|
20094
20266
|
// src/registry/eject.ts
|
|
20095
|
-
import { existsSync as
|
|
20267
|
+
import { existsSync as existsSync19 } from "node:fs";
|
|
20096
20268
|
import { cp as cp2, mkdir as mkdir9, readFile as readFile18, rm as rm3, writeFile as writeFile8 } from "node:fs/promises";
|
|
20097
20269
|
import { join as join33, relative as relative15 } from "pathe";
|
|
20098
20270
|
var toPosix = (path) => path.split("\\").join("/");
|
|
20099
20271
|
var LOCAL_BLUME_SOURCE = "../../node_modules/blume/src/**/*.{astro,ts,tsx}";
|
|
20100
20272
|
var blumeSourceGlob = (root, genDir, resolveBlumeRoot = packageRoot) => {
|
|
20101
|
-
if (
|
|
20273
|
+
if (existsSync19(join33(root, "node_modules", "blume"))) {
|
|
20102
20274
|
return LOCAL_BLUME_SOURCE;
|
|
20103
20275
|
}
|
|
20104
20276
|
try {
|
|
@@ -20117,7 +20289,7 @@ var askFiles = async (project, srcDir, genDir) => {
|
|
|
20117
20289
|
const { ask } = project.config.ai;
|
|
20118
20290
|
if (!(ask?.enabled && !ask.endpoint)) {
|
|
20119
20291
|
const endpointPath = join33(srcDir, "pages", "api", "ask.ts");
|
|
20120
|
-
if (
|
|
20292
|
+
if (existsSync19(endpointPath)) {
|
|
20121
20293
|
const content = await readFile18(endpointPath, "utf-8");
|
|
20122
20294
|
if (content.startsWith("// Generated by Blume. Do not edit.")) {
|
|
20123
20295
|
await rm3(endpointPath, { force: true });
|
|
@@ -20129,7 +20301,10 @@ var askFiles = async (project, srcDir, genDir) => {
|
|
|
20129
20301
|
const grounded = ask.provider !== "inkeep";
|
|
20130
20302
|
const files = [
|
|
20131
20303
|
{
|
|
20132
|
-
content: askEndpointTemplate(resolveAskBackend(ask), grounded,
|
|
20304
|
+
content: askEndpointTemplate(resolveAskBackend(ask), grounded, {
|
|
20305
|
+
instructions: ask.instructions,
|
|
20306
|
+
retrieval: ask.retrieval
|
|
20307
|
+
}),
|
|
20133
20308
|
path: join33(srcDir, "pages", "api", "ask.ts")
|
|
20134
20309
|
}
|
|
20135
20310
|
];
|
|
@@ -20199,7 +20374,7 @@ var changelogFiles = (project, userPages, srcDir, options) => {
|
|
|
20199
20374
|
}
|
|
20200
20375
|
];
|
|
20201
20376
|
};
|
|
20202
|
-
var readExamplesCss = (root, css) => css &&
|
|
20377
|
+
var readExamplesCss = (root, css) => css && existsSync19(join33(root, css)) ? readFile18(join33(root, css), "utf-8") : Promise.resolve("");
|
|
20203
20378
|
var examplesPreviewFiles = (srcDir, basePath, hasExamples) => hasExamples ? [
|
|
20204
20379
|
{
|
|
20205
20380
|
content: examplesPageTemplate(),
|
|
@@ -20438,13 +20613,13 @@ var eject = async (root) => {
|
|
|
20438
20613
|
for (const [entryId, content] of staged) {
|
|
20439
20614
|
files.push({ content, path: join33(root, stagedDir, entryId) });
|
|
20440
20615
|
}
|
|
20441
|
-
const written = files.filter((file) => !(file.skipIfExists &&
|
|
20616
|
+
const written = files.filter((file) => !(file.skipIfExists && existsSync19(file.path)));
|
|
20442
20617
|
await Promise.all(written.map(async (file) => {
|
|
20443
20618
|
await mkdir9(join33(file.path, ".."), { recursive: true });
|
|
20444
20619
|
await writeFile8(file.path, file.content, "utf-8");
|
|
20445
20620
|
}));
|
|
20446
20621
|
const assetsSrc = join33(context.outDir, "public", "blume-assets");
|
|
20447
|
-
if (
|
|
20622
|
+
if (existsSync19(assetsSrc)) {
|
|
20448
20623
|
await cp2(assetsSrc, join33(root, "public", "blume-assets"), {
|
|
20449
20624
|
recursive: true
|
|
20450
20625
|
});
|
|
@@ -20501,10 +20676,10 @@ var updatePackageScripts = async (root) => {
|
|
|
20501
20676
|
};
|
|
20502
20677
|
|
|
20503
20678
|
// src/cli/init/scaffold.ts
|
|
20504
|
-
import { existsSync as
|
|
20679
|
+
import { existsSync as existsSync20 } from "node:fs";
|
|
20505
20680
|
import { mkdir as mkdir10, writeFile as writeFile10 } from "node:fs/promises";
|
|
20506
20681
|
import { detect } from "package-manager-detector/detect";
|
|
20507
|
-
import { basename as
|
|
20682
|
+
import { basename as basename5, dirname as dirname14, isAbsolute as isAbsolute9, join as join35, relative as relative16 } from "pathe";
|
|
20508
20683
|
|
|
20509
20684
|
// src/core/package-json.ts
|
|
20510
20685
|
var toPackageName = (raw) => raw.toLowerCase().replaceAll(/[^a-z0-9._-]+/gu, "-").replaceAll(/^[-_.]+|[-_.]+$/gu, "") || "docs";
|
|
@@ -20713,7 +20888,7 @@ var extraDepsFor = (sources) => {
|
|
|
20713
20888
|
var buildPlan = (root, answers) => {
|
|
20714
20889
|
const files = [
|
|
20715
20890
|
{
|
|
20716
|
-
content: blumePackageJson(toPackageName(
|
|
20891
|
+
content: blumePackageJson(toPackageName(basename5(root)), extraDepsFor(answers.sources)),
|
|
20717
20892
|
path: join35(root, "package.json")
|
|
20718
20893
|
},
|
|
20719
20894
|
{ content: buildConfig(answers), path: join35(root, "blume.config.ts") }
|
|
@@ -20724,7 +20899,7 @@ var buildPlan = (root, answers) => {
|
|
|
20724
20899
|
return files;
|
|
20725
20900
|
};
|
|
20726
20901
|
var writeFileSafe = async (file, log) => {
|
|
20727
|
-
if (
|
|
20902
|
+
if (existsSync20(file.path)) {
|
|
20728
20903
|
log.info(`Skipped existing ${file.path}`);
|
|
20729
20904
|
return false;
|
|
20730
20905
|
}
|
|
@@ -20735,7 +20910,7 @@ var writeFileSafe = async (file, log) => {
|
|
|
20735
20910
|
};
|
|
20736
20911
|
var applyPlan = async (files, log) => {
|
|
20737
20912
|
const created = await Promise.all(files.map((file) => writeFileSafe(file, log)));
|
|
20738
|
-
const createdPackage = files.some((file, index) => created[index] &&
|
|
20913
|
+
const createdPackage = files.some((file, index) => created[index] && basename5(file.path) === "package.json");
|
|
20739
20914
|
return { createdPackage };
|
|
20740
20915
|
};
|
|
20741
20916
|
var envVarsFor = (sources) => [
|
|
@@ -20820,7 +20995,7 @@ The blume package remains importable.`);
|
|
|
20820
20995
|
});
|
|
20821
20996
|
|
|
20822
20997
|
// src/cli/commands/eval.ts
|
|
20823
|
-
import { existsSync as
|
|
20998
|
+
import { existsSync as existsSync21 } from "node:fs";
|
|
20824
20999
|
import { defineCommand as defineCommand8 } from "citty";
|
|
20825
21000
|
import { join as join39 } from "pathe";
|
|
20826
21001
|
|
|
@@ -21544,7 +21719,7 @@ var runFixHandoff = async (agent, result, root, threshold) => {
|
|
|
21544
21719
|
};
|
|
21545
21720
|
var runInit = async (agent, file) => {
|
|
21546
21721
|
const path = join39(process.cwd(), file);
|
|
21547
|
-
if (
|
|
21722
|
+
if (existsSync21(path)) {
|
|
21548
21723
|
logger.error(`${file} already exists — edit it directly, or pass --file to draft elsewhere.`);
|
|
21549
21724
|
process.exit(1);
|
|
21550
21725
|
}
|
|
@@ -21682,7 +21857,7 @@ import { defineCommand as defineCommand9 } from "citty";
|
|
|
21682
21857
|
import { resolve as resolve12 } from "pathe";
|
|
21683
21858
|
|
|
21684
21859
|
// src/cli/init/questions.ts
|
|
21685
|
-
import { basename as
|
|
21860
|
+
import { basename as basename6, resolve as resolve11 } from "pathe";
|
|
21686
21861
|
var cancelled = (value) => typeof value === "symbol";
|
|
21687
21862
|
var collectAnswers = async (prompter, flags, defaults) => {
|
|
21688
21863
|
const directory = flags.directory ?? await prompter.text({
|
|
@@ -21695,7 +21870,7 @@ var collectAnswers = async (prompter, flags, defaults) => {
|
|
|
21695
21870
|
}
|
|
21696
21871
|
const root = resolve11(defaults.cwd, directory);
|
|
21697
21872
|
const title = await prompter.text({
|
|
21698
|
-
initialValue: titleize(
|
|
21873
|
+
initialValue: titleize(basename6(root)),
|
|
21699
21874
|
message: "What's your docs site called?",
|
|
21700
21875
|
validate: (value) => value?.trim() ? undefined : "Give your docs site a name."
|
|
21701
21876
|
});
|
|
@@ -21922,10 +22097,30 @@ var SCHEMA = {
|
|
|
21922
22097
|
};
|
|
21923
22098
|
var toFacetTerms = (facets) => Object.entries(facets).map(([key, value]) => `${key}:${value}`);
|
|
21924
22099
|
var BOOST = { description: 2, title: 3 };
|
|
21925
|
-
var
|
|
21926
|
-
var
|
|
22100
|
+
var LATIN_SCRIPT = "Latn";
|
|
22101
|
+
var parseLocale = (tag) => {
|
|
22102
|
+
const hyphenated = tag.replaceAll("_", "-");
|
|
22103
|
+
try {
|
|
22104
|
+
return new Intl.Locale(hyphenated);
|
|
22105
|
+
} catch {}
|
|
22106
|
+
const [primary = ""] = hyphenated.split("-");
|
|
22107
|
+
try {
|
|
22108
|
+
return new Intl.Locale(primary);
|
|
22109
|
+
} catch {
|
|
22110
|
+
return;
|
|
22111
|
+
}
|
|
22112
|
+
};
|
|
22113
|
+
var resolveLocale = (tag) => parseLocale(tag)?.maximize();
|
|
22114
|
+
var BIGRAM_INDEX_SCRIPTS = new Set(["Hans", "Hant", "Jpan"]);
|
|
22115
|
+
var isBigramLanguage = (language) => {
|
|
22116
|
+
const script = resolveLocale(language)?.script;
|
|
22117
|
+
return script !== undefined && BIGRAM_INDEX_SCRIPTS.has(script);
|
|
22118
|
+
};
|
|
21927
22119
|
var BIGRAM_SCRIPTS = /^[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}々〆〇ー゙゚]+$/u;
|
|
21928
22120
|
var TERM = /[\p{L}\p{M}\p{N}]+(?:(?:['’](?=\p{L})|(?<=\p{N})[.,](?=\p{N}))[\p{L}\p{M}\p{N}]+)*/gu;
|
|
22121
|
+
var LATIN_TERM = /^[\p{Script=Latin}\p{N}'’.,]+$/u;
|
|
22122
|
+
var MARKS = /\p{M}+/gu;
|
|
22123
|
+
var foldDiacritics = (term) => LATIN_TERM.test(term) ? term.normalize("NFD").replace(MARKS, "") : term;
|
|
21929
22124
|
var addBigrams = (run, tokens) => {
|
|
21930
22125
|
const characters = [...run];
|
|
21931
22126
|
if (characters.length === 1) {
|
|
@@ -21942,15 +22137,16 @@ var addBigrams = (run, tokens) => {
|
|
|
21942
22137
|
};
|
|
21943
22138
|
var hasSegmenter = (segmenter) => typeof segmenter === "function";
|
|
21944
22139
|
var segmentingTokenizer = (locale) => {
|
|
21945
|
-
const
|
|
21946
|
-
if (!
|
|
22140
|
+
const resolved = resolveLocale(locale ?? "");
|
|
22141
|
+
if (!resolved?.script || resolved.script === LATIN_SCRIPT) {
|
|
21947
22142
|
return;
|
|
21948
22143
|
}
|
|
21949
22144
|
if (!hasSegmenter(Intl.Segmenter)) {
|
|
21950
22145
|
return;
|
|
21951
22146
|
}
|
|
22147
|
+
const { language } = resolved;
|
|
21952
22148
|
const segmenter = new Intl.Segmenter(language, { granularity: "word" });
|
|
21953
|
-
const bigram =
|
|
22149
|
+
const bigram = isBigramLanguage(language);
|
|
21954
22150
|
return {
|
|
21955
22151
|
language,
|
|
21956
22152
|
normalizationCache: new Map,
|
|
@@ -21969,7 +22165,7 @@ var segmentingTokenizer = (locale) => {
|
|
|
21969
22165
|
return;
|
|
21970
22166
|
}
|
|
21971
22167
|
flush();
|
|
21972
|
-
tokens.add(term);
|
|
22168
|
+
tokens.add(foldDiacritics(term));
|
|
21973
22169
|
};
|
|
21974
22170
|
for (const segment of segmenter.segment(raw.normalize("NFC").toLowerCase())) {
|
|
21975
22171
|
if (!segment.isWordLike) {
|
|
@@ -22022,7 +22218,7 @@ var queryOramaIndex = async (db, term, limit, filters) => {
|
|
|
22022
22218
|
term
|
|
22023
22219
|
};
|
|
22024
22220
|
const params = Object.keys(where).length > 0 ? { ...unfiltered, where } : unfiltered;
|
|
22025
|
-
const bigrammed =
|
|
22221
|
+
const bigrammed = isBigramLanguage(db.tokenizer?.language ?? "");
|
|
22026
22222
|
const strict = bigrammed ? await search(db, { ...params, threshold: ALL_TOKENS }) : undefined;
|
|
22027
22223
|
const found = strict && strict.hits.length > 0 ? strict : await search(db, params);
|
|
22028
22224
|
return found.hits.map((hit) => hit.document);
|
|
@@ -22269,7 +22465,7 @@ var mcpStdioCommand = defineCommand10({
|
|
|
22269
22465
|
});
|
|
22270
22466
|
|
|
22271
22467
|
// src/cli/commands/preview.ts
|
|
22272
|
-
import { existsSync as
|
|
22468
|
+
import { existsSync as existsSync22 } from "node:fs";
|
|
22273
22469
|
import { preview } from "astro";
|
|
22274
22470
|
import { defineCommand as defineCommand11 } from "citty";
|
|
22275
22471
|
import { join as join40 } from "pathe";
|
|
@@ -22286,7 +22482,7 @@ var previewCommand = defineCommand11({
|
|
|
22286
22482
|
const root = process.cwd();
|
|
22287
22483
|
const { config: config2 } = await loadConfig(root);
|
|
22288
22484
|
const context = resolveProjectContext(root, config2);
|
|
22289
|
-
if (!
|
|
22485
|
+
if (!existsSync22(join40(context.outDir, "astro.config.mjs"))) {
|
|
22290
22486
|
logger.error("No build found. Run `blume build` first.");
|
|
22291
22487
|
process.exit(1);
|
|
22292
22488
|
}
|
|
@@ -22637,7 +22833,7 @@ var createProgressRenderer = (options) => {
|
|
|
22637
22833
|
};
|
|
22638
22834
|
|
|
22639
22835
|
// src/translate/run.ts
|
|
22640
|
-
import { existsSync as
|
|
22836
|
+
import { existsSync as existsSync23 } from "node:fs";
|
|
22641
22837
|
import { mkdtemp as mkdtemp4, readFile as readFile25 } from "node:fs/promises";
|
|
22642
22838
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
22643
22839
|
import pLimit2 from "p-limit";
|
|
@@ -22882,7 +23078,7 @@ var runPageItem = async (item, index, context, ledger) => {
|
|
|
22882
23078
|
});
|
|
22883
23079
|
const sourceText = await readFile25(item.sourcePath, "utf-8");
|
|
22884
23080
|
const target = context.targets.get(item.locale);
|
|
22885
|
-
const previousTranslation =
|
|
23081
|
+
const previousTranslation = existsSync23(item.targetPath) ? await readFile25(item.targetPath, "utf-8") : undefined;
|
|
22886
23082
|
const output = await invokeAgent(context, pagePrompt(sourceText, target, context.source, previousTranslation), index);
|
|
22887
23083
|
if (output.isError) {
|
|
22888
23084
|
return done("failed", output.detail ?? "agent failed", output.costUsd);
|
|
@@ -23003,7 +23199,7 @@ var runTranslate = async (options) => {
|
|
|
23003
23199
|
};
|
|
23004
23200
|
|
|
23005
23201
|
// src/translate/work-list.ts
|
|
23006
|
-
import { existsSync as
|
|
23202
|
+
import { existsSync as existsSync24 } from "node:fs";
|
|
23007
23203
|
import { readFile as readFile26 } from "node:fs/promises";
|
|
23008
23204
|
import { dirname as dirname16, extname as extname8, join as join45, relative as relative20 } from "pathe";
|
|
23009
23205
|
var PAGE_EXTENSIONS = new Set([".md", ".mdx"]);
|
|
@@ -23085,7 +23281,7 @@ var computeWorkList = async (project, ledger, options = {}) => {
|
|
|
23085
23281
|
for (const source of meta.metas) {
|
|
23086
23282
|
knownSources.add(source.sourceRel);
|
|
23087
23283
|
const targetDir = dirname16(metaTargetPath(source, locale));
|
|
23088
|
-
const exists = ["meta.ts", "meta.js", "meta.mjs"].some((name) =>
|
|
23284
|
+
const exists = ["meta.ts", "meta.js", "meta.mjs"].some((name) => existsSync24(join45(targetDir, name)));
|
|
23089
23285
|
const hash = hashSource(source.raw);
|
|
23090
23286
|
const stamp = ledger.files[source.sourceRel]?.[locale];
|
|
23091
23287
|
const entry = (status) => ({
|
|
@@ -23317,13 +23513,13 @@ var translateCommand = defineCommand13({
|
|
|
23317
23513
|
});
|
|
23318
23514
|
|
|
23319
23515
|
// src/cli/commands/validate.ts
|
|
23320
|
-
import { existsSync as
|
|
23516
|
+
import { existsSync as existsSync26 } from "node:fs";
|
|
23321
23517
|
import { defineCommand as defineCommand14 } from "citty";
|
|
23322
23518
|
import { join as join47 } from "pathe";
|
|
23323
23519
|
|
|
23324
23520
|
// src/core/links.ts
|
|
23325
|
-
import { existsSync as
|
|
23326
|
-
import { basename as
|
|
23521
|
+
import { existsSync as existsSync25 } from "node:fs";
|
|
23522
|
+
import { basename as basename7, dirname as dirname17, join as join46 } from "pathe";
|
|
23327
23523
|
var HTTP = /^https?:\/\//iu;
|
|
23328
23524
|
var PROTOCOL_RELATIVE = /^\/\//u;
|
|
23329
23525
|
var SCHEME = /^[a-z][a-z0-9+.-]*:/iu;
|
|
@@ -23336,9 +23532,9 @@ var decodePercent = (value) => {
|
|
|
23336
23532
|
};
|
|
23337
23533
|
var DOC_EXT = /\.(?:md|mdx)$/iu;
|
|
23338
23534
|
var FILE_EXT = /\.[a-z0-9]+$/iu;
|
|
23339
|
-
var assetIsPresent = (resolved, ctx) => ctx.publicDir !== null &&
|
|
23535
|
+
var assetIsPresent = (resolved, ctx) => ctx.publicDir !== null && existsSync25(join46(ctx.publicDir, resolved));
|
|
23340
23536
|
var NUMERIC_PREFIX3 = /^\d+[-_.]/u;
|
|
23341
|
-
var isIndexPage = (page2) => /^index\.(?:md|mdx)$/iu.test(
|
|
23537
|
+
var isIndexPage = (page2) => /^index\.(?:md|mdx)$/iu.test(basename7(page2.navPath).replace(NUMERIC_PREFIX3, ""));
|
|
23342
23538
|
var applyRelativePart = (segments, part) => {
|
|
23343
23539
|
if (part === "" || part === ".") {
|
|
23344
23540
|
return;
|
|
@@ -23387,7 +23583,7 @@ var checkAnchor = (route, fragment, site, ctx) => {
|
|
|
23387
23583
|
severity: "warning"
|
|
23388
23584
|
};
|
|
23389
23585
|
};
|
|
23390
|
-
var checkPathLink = (resolved, fragment,
|
|
23586
|
+
var checkPathLink = (resolved, fragment, page2, link, site, ctx) => {
|
|
23391
23587
|
const route = toRoute(withBasePath(ctx.basePath, resolved));
|
|
23392
23588
|
if (ctx.routes.has(route)) {
|
|
23393
23589
|
return fragment ? checkAnchor(route, fragment, site, ctx) : null;
|
|
@@ -23403,6 +23599,18 @@ var checkPathLink = (resolved, fragment, target, site, ctx) => {
|
|
|
23403
23599
|
if (assetIsPresent(assetPath, ctx)) {
|
|
23404
23600
|
return null;
|
|
23405
23601
|
}
|
|
23602
|
+
if (link.image && page2.sourcePath && isRelativeImageTarget(link.target)) {
|
|
23603
|
+
if (resolveRelativeImage(dirname17(page2.sourcePath), link.target)) {
|
|
23604
|
+
return null;
|
|
23605
|
+
}
|
|
23606
|
+
return {
|
|
23607
|
+
...site,
|
|
23608
|
+
code: "BLUME_BROKEN_ASSET",
|
|
23609
|
+
message: `Image ${link.target} was not found next to ${basename7(page2.sourcePath)}.`,
|
|
23610
|
+
severity: "warning",
|
|
23611
|
+
suggestion: "Add the file next to the page source or fix the reference."
|
|
23612
|
+
};
|
|
23613
|
+
}
|
|
23406
23614
|
if (ctx.publicDir === null) {
|
|
23407
23615
|
return "asset-unchecked";
|
|
23408
23616
|
}
|
|
@@ -23417,7 +23625,7 @@ var checkPathLink = (resolved, fragment, target, site, ctx) => {
|
|
|
23417
23625
|
return {
|
|
23418
23626
|
...site,
|
|
23419
23627
|
code: "BLUME_BROKEN_LINK",
|
|
23420
|
-
message: `Broken link to ${target}: no page resolves to ${route}.`,
|
|
23628
|
+
message: `Broken link to ${link.target}: no page resolves to ${route}.`,
|
|
23421
23629
|
severity: "error",
|
|
23422
23630
|
suggestion: "Check the path, or create the target page."
|
|
23423
23631
|
};
|
|
@@ -23470,7 +23678,7 @@ var classifyLink = (page2, link, ctx, onExternal) => {
|
|
|
23470
23678
|
return fragment ? checkAnchor(page2.route, fragment, site, ctx) : null;
|
|
23471
23679
|
}
|
|
23472
23680
|
const resolved = rawPath.startsWith("/") ? rawPath : resolveRelative(page2.route, rawPath, isIndexPage(page2));
|
|
23473
|
-
return checkPathLink(resolved, fragment,
|
|
23681
|
+
return checkPathLink(resolved, fragment, page2, link, site, ctx);
|
|
23474
23682
|
};
|
|
23475
23683
|
var validateLinks = async (graph, options) => {
|
|
23476
23684
|
const basePath = options.basePath ?? "";
|
|
@@ -23552,7 +23760,7 @@ var validateCommand = defineCommand14({
|
|
|
23552
23760
|
basePath: project.config.basePath,
|
|
23553
23761
|
checkExternal: Boolean(args.external),
|
|
23554
23762
|
extraRoutes,
|
|
23555
|
-
publicDir:
|
|
23763
|
+
publicDir: existsSync26(publicDir) ? publicDir : null,
|
|
23556
23764
|
redirects: project.config.redirects
|
|
23557
23765
|
}));
|
|
23558
23766
|
} catch (error) {
|
|
@@ -23586,7 +23794,7 @@ var validateCommand = defineCommand14({
|
|
|
23586
23794
|
import { defineCommand as defineCommand15 } from "citty";
|
|
23587
23795
|
|
|
23588
23796
|
// src/core/version-cut.ts
|
|
23589
|
-
import { existsSync as
|
|
23797
|
+
import { existsSync as existsSync27 } from "node:fs";
|
|
23590
23798
|
import { cp as cp3, readdir as readdir3, readFile as readFile27, rm as rm5 } from "node:fs/promises";
|
|
23591
23799
|
import { join as join48, relative as relative21 } from "pathe";
|
|
23592
23800
|
class CutError extends Error {
|
|
@@ -23706,7 +23914,7 @@ var cutVersion = async (root, id2, options = {}) => {
|
|
|
23706
23914
|
throw new CutError(`Version "${id2}" is already registered in versions.archived.`);
|
|
23707
23915
|
}
|
|
23708
23916
|
const dir = join48(contentRoot2, id2);
|
|
23709
|
-
if (
|
|
23917
|
+
if (existsSync27(dir)) {
|
|
23710
23918
|
if (!options.force) {
|
|
23711
23919
|
throw new CutError(`${dir} already exists — pass --force to overwrite the snapshot.`);
|
|
23712
23920
|
}
|
|
@@ -23859,5 +24067,5 @@ process.on("unhandledRejection", (error) => {
|
|
|
23859
24067
|
});
|
|
23860
24068
|
runMain(main);
|
|
23861
24069
|
|
|
23862
|
-
//# debugId=
|
|
24070
|
+
//# debugId=94497B7DFC770E9664756E2164756E21
|
|
23863
24071
|
//# sourceMappingURL=index.js.map
|