blume 1.6.4 → 1.6.6
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 +41 -0
- package/bin/blume.mjs +3 -2
- package/dist/cli/chunk-0ewz4trd.js +679 -0
- package/dist/cli/chunk-0ewz4trd.js.map +15 -0
- package/dist/cli/chunk-27gtm2ym.js +69 -0
- package/dist/cli/chunk-27gtm2ym.js.map +11 -0
- package/dist/cli/chunk-2aj8ddew.js +72 -0
- package/dist/cli/chunk-2aj8ddew.js.map +10 -0
- package/dist/cli/chunk-3k0kzs6d.js +69 -0
- package/dist/cli/chunk-3k0kzs6d.js.map +11 -0
- package/dist/cli/chunk-3r94j3tc.js +221 -0
- package/dist/cli/chunk-3r94j3tc.js.map +10 -0
- package/dist/cli/chunk-4trphnvy.js +102 -0
- package/dist/cli/chunk-4trphnvy.js.map +11 -0
- package/dist/cli/chunk-4xyggvgf.js +21 -0
- package/dist/cli/chunk-4xyggvgf.js.map +10 -0
- package/dist/cli/chunk-5hs6gb7n.js +32 -0
- package/dist/cli/chunk-5hs6gb7n.js.map +10 -0
- package/dist/cli/chunk-5yvt556e.js +185 -0
- package/dist/cli/chunk-5yvt556e.js.map +11 -0
- package/dist/cli/chunk-62qsssnh.js +3808 -0
- package/dist/cli/chunk-62qsssnh.js.map +36 -0
- package/dist/cli/chunk-6kzzpsx8.js +26 -0
- package/dist/cli/chunk-6kzzpsx8.js.map +10 -0
- package/dist/cli/chunk-8gnpdsn1.js +952 -0
- package/dist/cli/chunk-8gnpdsn1.js.map +12 -0
- package/dist/cli/chunk-9sh49q0h.js +30 -0
- package/dist/cli/chunk-9sh49q0h.js.map +10 -0
- package/dist/cli/chunk-aerwpe14.js +2370 -0
- package/dist/cli/chunk-aerwpe14.js.map +15 -0
- package/dist/cli/chunk-ag1zyr5x.js +176 -0
- package/dist/cli/chunk-ag1zyr5x.js.map +10 -0
- package/dist/cli/chunk-bawgnt8x.js +277 -0
- package/dist/cli/chunk-bawgnt8x.js.map +11 -0
- package/dist/cli/chunk-bcy492zc.js +16 -0
- package/dist/cli/chunk-bcy492zc.js.map +10 -0
- package/dist/cli/chunk-btfr9yvw.js +41 -0
- package/dist/cli/chunk-btfr9yvw.js.map +10 -0
- package/dist/cli/chunk-cbjnx4s8.js +73 -0
- package/dist/cli/chunk-cbjnx4s8.js.map +10 -0
- package/dist/cli/chunk-cnvm6k3e.js +96 -0
- package/dist/cli/chunk-cnvm6k3e.js.map +10 -0
- package/dist/cli/chunk-etsqspj6.js +5170 -0
- package/dist/cli/chunk-etsqspj6.js.map +47 -0
- package/dist/cli/chunk-ev67ycx0.js +15 -0
- package/dist/cli/chunk-ev67ycx0.js.map +10 -0
- package/dist/cli/chunk-ey89bjj1.js +209 -0
- package/dist/cli/chunk-ey89bjj1.js.map +11 -0
- package/dist/cli/chunk-f75cqye8.js +76 -0
- package/dist/cli/chunk-f75cqye8.js.map +10 -0
- package/dist/cli/chunk-j00ezcg5.js +259 -0
- package/dist/cli/chunk-j00ezcg5.js.map +11 -0
- package/dist/cli/chunk-jtb45atp.js +467 -0
- package/dist/cli/chunk-jtb45atp.js.map +14 -0
- package/dist/cli/chunk-m3p3wahd.js +117 -0
- package/dist/cli/chunk-m3p3wahd.js.map +10 -0
- package/dist/cli/chunk-n0y172hf.js +387 -0
- package/dist/cli/chunk-n0y172hf.js.map +12 -0
- package/dist/cli/chunk-n4qjabmt.js +1062 -0
- package/dist/cli/chunk-n4qjabmt.js.map +25 -0
- package/dist/cli/chunk-nyqzjdhj.js +111 -0
- package/dist/cli/chunk-nyqzjdhj.js.map +11 -0
- package/dist/cli/chunk-pxj10x8y.js +35 -0
- package/dist/cli/chunk-pxj10x8y.js.map +10 -0
- package/dist/cli/chunk-s4jn7f1q.js +54 -0
- package/dist/cli/chunk-s4jn7f1q.js.map +10 -0
- package/dist/cli/chunk-s4k1pnvf.js +81 -0
- package/dist/cli/chunk-s4k1pnvf.js.map +10 -0
- package/dist/cli/chunk-s5e5jt53.js +227 -0
- package/dist/cli/chunk-s5e5jt53.js.map +11 -0
- package/dist/cli/chunk-sbdqrjbb.js +81 -0
- package/dist/cli/chunk-sbdqrjbb.js.map +10 -0
- package/dist/cli/chunk-tc89yh2r.js +136 -0
- package/dist/cli/chunk-tc89yh2r.js.map +10 -0
- package/dist/cli/chunk-vt8fgygt.js +23 -0
- package/dist/cli/chunk-vt8fgygt.js.map +10 -0
- package/dist/cli/chunk-vv237fp3.js +1002 -0
- package/dist/cli/chunk-vv237fp3.js.map +13 -0
- package/dist/cli/chunk-vv3f8mb6.js +5314 -0
- package/dist/cli/chunk-vv3f8mb6.js.map +58 -0
- package/dist/cli/chunk-vxv4x1n8.js +17 -0
- package/dist/cli/chunk-vxv4x1n8.js.map +10 -0
- package/dist/cli/chunk-wb067mv3.js +758 -0
- package/dist/cli/chunk-wb067mv3.js.map +13 -0
- package/dist/cli/chunk-wd27zjcz.js +60 -0
- package/dist/cli/chunk-wd27zjcz.js.map +10 -0
- package/dist/cli/chunk-wkq5tbtq.js +1141 -0
- package/dist/cli/chunk-wkq5tbtq.js.map +19 -0
- package/dist/cli/chunk-x1vrdjyk.js +1967 -0
- package/dist/cli/chunk-x1vrdjyk.js.map +34 -0
- package/dist/cli/chunk-x66c5yjn.js +23 -0
- package/dist/cli/chunk-x66c5yjn.js.map +10 -0
- package/dist/cli/index.js +55 -27587
- package/dist/cli/index.js.map +5 -243
- package/dist/types/ai/ask-context.d.ts +26 -0
- package/dist/types/core/code-fences.d.ts +11 -0
- package/dist/types/core/config-input.d.ts +10 -0
- package/dist/types/core/package-root.d.ts +1 -1
- package/dist/types/core/schema.d.ts +74 -1
- package/docs/02-deployment.mdx +1 -1
- package/docs/configuration/analytics.mdx +21 -2
- package/docs/configuration/ask-ai.mdx +1 -1
- package/docs/configuration/customization.mdx +2 -9
- package/docs/content/syntax.mdx +1 -1
- package/docs/reference/cli.mdx +1 -1
- package/package.json +16 -14
- package/src/ai/api/handlers.ts +4 -7
- package/src/ai/api/paths.ts +8 -0
- package/src/ai/api/spec.ts +2 -1
- package/src/ai/ask-context.ts +378 -22
- package/src/astro/generate.ts +25 -29
- package/src/astro/include-hmr.ts +10 -13
- package/src/astro/include-refresh.ts +0 -0
- package/src/astro/index.ts +6 -1
- package/src/astro/integration.ts +269 -53
- package/src/astro/module-types.ts +74 -0
- package/src/astro/templates.ts +85 -97
- package/src/audit/image-size.ts +10 -8
- package/src/cli/command-meta.ts +77 -0
- package/src/cli/commands/add.ts +2 -4
- package/src/cli/commands/audit.ts +2 -4
- package/src/cli/commands/build.ts +42 -346
- package/src/cli/commands/check.ts +2 -4
- package/src/cli/commands/dev.ts +31 -42
- package/src/cli/commands/doctor.ts +2 -4
- package/src/cli/commands/eject.ts +3 -41
- package/src/cli/commands/eval.ts +2 -5
- package/src/cli/commands/init.ts +2 -4
- package/src/cli/commands/mcp-stdio.ts +2 -5
- package/src/cli/commands/preview.ts +3 -5
- package/src/cli/commands/sync.ts +2 -4
- package/src/cli/commands/translate.ts +2 -5
- package/src/cli/commands/validate.ts +2 -4
- package/src/cli/commands/version.ts +2 -4
- package/src/cli/eject-scripts.ts +0 -45
- package/src/cli/host-args.ts +16 -0
- package/src/cli/index.ts +84 -35
- package/src/cli/lazy-command.ts +47 -0
- package/src/components/content/GithubInfo.astro +4 -1
- package/src/components/content/mermaid-element.ts +8 -0
- package/src/components/layout/Analytics.astro +20 -1
- package/src/components/layout/PageLayout.astro +14 -3
- package/src/components/layout/ReferenceLayout.astro +15 -4
- package/src/components/layout/RootLayout.astro +15 -4
- package/src/components/layout/analytics-client.ts +2 -1
- package/src/components/layout/page-locale.ts +29 -0
- package/src/components/openapi/AsyncApiOperation.astro +5 -3
- package/src/components/openapi/Authorization.astro +4 -6
- package/src/components/openapi/Bindings.astro +2 -2
- package/src/components/openapi/Description.astro +109 -0
- package/src/components/openapi/GraphqlFieldsTable.astro +5 -7
- package/src/components/openapi/GraphqlOperation.astro +4 -3
- package/src/components/openapi/GraphqlType.astro +4 -6
- package/src/components/openapi/ParametersTable.astro +5 -7
- package/src/components/openapi/RequestBody.astro +2 -4
- package/src/components/openapi/Responses.astro +4 -3
- package/src/components/openapi/SchemaProperty.astro +11 -6
- package/src/components/openapi/description.ts +91 -0
- package/src/core/api-name.ts +18 -0
- package/src/core/code-fences.ts +48 -0
- package/src/core/config-input.ts +10 -0
- package/src/core/content-assets.ts +3 -7
- package/src/core/includes.ts +3 -7
- package/src/core/package-root.ts +1 -1
- package/src/core/schema.ts +27 -0
- package/src/core/sources/normalize.ts +2 -37
- package/src/core/sources/obsidian.ts +3 -2
- package/src/core/svg-dimensions.ts +97 -0
- package/src/core/version-cut.ts +2 -2
- package/src/deploy/artifacts.ts +370 -0
- package/src/deploy/cloudflare-negotiation.ts +97 -32
- package/src/deploy/function-bundle.ts +66 -20
- package/src/deploy/sitemap.ts +6 -0
- package/src/deploy/vercel-negotiation.ts +8 -30
- package/src/og/card.ts +6 -12
- package/src/openapi/render-mdx.ts +9 -5
- package/src/registry/eject.ts +0 -2
- package/src/theme/entry.ts +9 -2
|
@@ -1,63 +1,26 @@
|
|
|
1
1
|
import { defineCommand } from "citty";
|
|
2
2
|
import { relative } from "pathe";
|
|
3
3
|
|
|
4
|
-
import { loadConfig } from "../../core/config.ts";
|
|
5
4
|
import { eject } from "../../registry/eject.ts";
|
|
5
|
+
import { commandMeta } from "../command-meta.ts";
|
|
6
6
|
import { refuseIfDevRunning } from "../dev-lock.ts";
|
|
7
|
-
import {
|
|
8
|
-
droppedArtifactNotices,
|
|
9
|
-
updatePackageScripts,
|
|
10
|
-
} from "../eject-scripts.ts";
|
|
7
|
+
import { updatePackageScripts } from "../eject-scripts.ts";
|
|
11
8
|
import { commandsFor, detectProjectPackageManager } from "../init/scaffold.ts";
|
|
12
9
|
import { logger } from "../log.ts";
|
|
13
10
|
|
|
14
|
-
/**
|
|
15
|
-
* Warn which `blume build` post-build artifacts the ejected app stops
|
|
16
|
-
* producing. Printed both at the confirmation (so the decision is informed)
|
|
17
|
-
* and after `--yes` (so a direct eject still sees it). No-op when the config
|
|
18
|
-
* activates none of them.
|
|
19
|
-
*/
|
|
20
|
-
const reportDroppedArtifacts = (notices: string[]): void => {
|
|
21
|
-
if (notices.length === 0) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
logger.warn(
|
|
25
|
-
[
|
|
26
|
-
"The ejected build script runs plain `astro build`, which stops producing these `blume build` artifacts:",
|
|
27
|
-
...notices.map((notice) => ` - ${notice}`),
|
|
28
|
-
].join("\n")
|
|
29
|
-
);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
11
|
export const ejectCommand = defineCommand({
|
|
33
12
|
args: {
|
|
34
13
|
yes: { description: "Skip the confirmation prompt.", type: "boolean" },
|
|
35
14
|
},
|
|
36
|
-
meta:
|
|
37
|
-
description: "Promote the generated runtime into an owned Astro project.",
|
|
38
|
-
name: "eject",
|
|
39
|
-
},
|
|
15
|
+
meta: commandMeta.eject,
|
|
40
16
|
async run({ args }) {
|
|
41
17
|
const root = process.cwd();
|
|
42
18
|
refuseIfDevRunning(root, "ejecting");
|
|
43
19
|
|
|
44
|
-
// Config-aware drop list: only the artifacts this project actually
|
|
45
|
-
// produces are mentioned (e.g. the Pagefind index only for
|
|
46
|
-
// `search.provider: "pagefind"`).
|
|
47
|
-
let notices: string[] = [];
|
|
48
|
-
try {
|
|
49
|
-
const { config } = await loadConfig(root);
|
|
50
|
-
notices = droppedArtifactNotices(config);
|
|
51
|
-
} catch {
|
|
52
|
-
// A config that fails to load can't gate the notice; the eject itself
|
|
53
|
-
// surfaces the load error.
|
|
54
|
-
}
|
|
55
|
-
|
|
56
20
|
if (!args.yes) {
|
|
57
21
|
logger.warn(
|
|
58
22
|
"Eject is one-way: it writes astro.config.mjs, src/, and (if absent) tsconfig.json, rewrites your package.json scripts, and removes .blume. An existing tsconfig.json is left untouched."
|
|
59
23
|
);
|
|
60
|
-
reportDroppedArtifacts(notices);
|
|
61
24
|
logger.info("Re-run with --yes to proceed.");
|
|
62
25
|
return;
|
|
63
26
|
}
|
|
@@ -75,7 +38,6 @@ export const ejectCommand = defineCommand({
|
|
|
75
38
|
for (const file of files) {
|
|
76
39
|
process.stdout.write(` ${relative(root, file)}\n`);
|
|
77
40
|
}
|
|
78
|
-
reportDroppedArtifacts(notices);
|
|
79
41
|
// Print run commands matching the project's package manager (lockfile
|
|
80
42
|
// detection, since eject runs inside an existing project).
|
|
81
43
|
const pm = await detectProjectPackageManager(root);
|
package/src/cli/commands/eval.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
import { runEval } from "../../eval/run.ts";
|
|
23
23
|
import type { EvalResult } from "../../eval/run.ts";
|
|
24
24
|
import { EvalsFileError, loadEvalsFile } from "../../eval/schema.ts";
|
|
25
|
+
import { commandMeta } from "../command-meta.ts";
|
|
25
26
|
import { reportInternalError } from "../internal-error.ts";
|
|
26
27
|
import { flushStdout, logger } from "../log.ts";
|
|
27
28
|
|
|
@@ -183,11 +184,7 @@ export const evalCommand = defineCommand({
|
|
|
183
184
|
type: "boolean",
|
|
184
185
|
},
|
|
185
186
|
},
|
|
186
|
-
meta:
|
|
187
|
-
description:
|
|
188
|
-
"Test the docs: an agent answers your questions using only the documentation.",
|
|
189
|
-
name: "eval",
|
|
190
|
-
},
|
|
187
|
+
meta: commandMeta.eval,
|
|
191
188
|
async run({ args }) {
|
|
192
189
|
const root = process.cwd();
|
|
193
190
|
const { agent, threshold, timeoutS } = parseFlags(args);
|
package/src/cli/commands/init.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { resolve } from "pathe";
|
|
|
4
4
|
|
|
5
5
|
import { ensureGitignore } from "../../core/gitignore.ts";
|
|
6
6
|
import { eject } from "../../registry/eject.ts";
|
|
7
|
+
import { commandMeta } from "../command-meta.ts";
|
|
7
8
|
import { updatePackageScripts } from "../eject-scripts.ts";
|
|
8
9
|
import { collectAnswers } from "../init/questions.ts";
|
|
9
10
|
import {
|
|
@@ -84,10 +85,7 @@ export const initCommand = defineCommand({
|
|
|
84
85
|
type: "boolean",
|
|
85
86
|
},
|
|
86
87
|
},
|
|
87
|
-
meta:
|
|
88
|
-
description: "Scaffold a minimal Blume project.",
|
|
89
|
-
name: "init",
|
|
90
|
-
},
|
|
88
|
+
meta: commandMeta.init,
|
|
91
89
|
async run({ args }) {
|
|
92
90
|
const cwd = process.cwd();
|
|
93
91
|
|
|
@@ -4,6 +4,7 @@ import { defineCommand } from "citty";
|
|
|
4
4
|
|
|
5
5
|
import type { McpData } from "../../ai/mcp/data.ts";
|
|
6
6
|
import { serveMcpStdio } from "../../ai/mcp/stdio.ts";
|
|
7
|
+
import { commandMeta } from "../command-meta.ts";
|
|
7
8
|
|
|
8
9
|
export const mcpStdioCommand = defineCommand({
|
|
9
10
|
args: {
|
|
@@ -13,11 +14,7 @@ export const mcpStdioCommand = defineCommand({
|
|
|
13
14
|
type: "string",
|
|
14
15
|
},
|
|
15
16
|
},
|
|
16
|
-
meta:
|
|
17
|
-
description:
|
|
18
|
-
"Serve an MCP data snapshot over stdio (internal, used by `blume eval`).",
|
|
19
|
-
name: "mcp-stdio",
|
|
20
|
-
},
|
|
17
|
+
meta: commandMeta["mcp-stdio"],
|
|
21
18
|
async run({ args }) {
|
|
22
19
|
// stdout belongs to the JSON-RPC transport from here on; every diagnostic
|
|
23
20
|
// must go to stderr or the MCP client chokes on the stray line.
|
|
@@ -7,18 +7,16 @@ import { join } from "pathe";
|
|
|
7
7
|
import { loadConfig } from "../../core/config.ts";
|
|
8
8
|
import { resolveProjectContext } from "../../core/project.ts";
|
|
9
9
|
import { parsePort } from "../args.ts";
|
|
10
|
+
import { commandMeta } from "../command-meta.ts";
|
|
11
|
+
import { normalizeHost } from "../host-args.ts";
|
|
10
12
|
import { logger } from "../log.ts";
|
|
11
|
-
import { normalizeHost } from "./dev.ts";
|
|
12
13
|
|
|
13
14
|
export const previewCommand = defineCommand({
|
|
14
15
|
args: {
|
|
15
16
|
host: { description: "Network host to bind.", type: "string" },
|
|
16
17
|
port: { description: "Port to listen on.", type: "string" },
|
|
17
18
|
},
|
|
18
|
-
meta:
|
|
19
|
-
description: "Preview the last production build.",
|
|
20
|
-
name: "preview",
|
|
21
|
-
},
|
|
19
|
+
meta: commandMeta.preview,
|
|
22
20
|
async run({ args }) {
|
|
23
21
|
const root = process.cwd();
|
|
24
22
|
const { config } = await loadConfig(root);
|
package/src/cli/commands/sync.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
resolveProjectContext,
|
|
9
9
|
resolveRuntimeDir,
|
|
10
10
|
} from "../../core/project.ts";
|
|
11
|
+
import { commandMeta } from "../command-meta.ts";
|
|
11
12
|
import { readDevLock } from "../dev-lock.ts";
|
|
12
13
|
import { logger } from "../log.ts";
|
|
13
14
|
import { prepareProject } from "../prepare.ts";
|
|
@@ -24,10 +25,7 @@ export const syncCommand = defineCommand({
|
|
|
24
25
|
},
|
|
25
26
|
strict: { description: "Fail on diagnostics.", type: "boolean" },
|
|
26
27
|
},
|
|
27
|
-
meta:
|
|
28
|
-
description: "Re-fetch remote content sources and regenerate the runtime.",
|
|
29
|
-
name: "sync",
|
|
30
|
-
},
|
|
28
|
+
meta: commandMeta.sync,
|
|
31
29
|
async run({ args }) {
|
|
32
30
|
const root = process.cwd();
|
|
33
31
|
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
} from "../../translate/report.ts";
|
|
27
27
|
import { runTranslate } from "../../translate/run.ts";
|
|
28
28
|
import { computeWorkList } from "../../translate/work-list.ts";
|
|
29
|
+
import { commandMeta } from "../command-meta.ts";
|
|
29
30
|
import { reportInternalError } from "../internal-error.ts";
|
|
30
31
|
import { flushStdout, logger } from "../log.ts";
|
|
31
32
|
|
|
@@ -181,11 +182,7 @@ export const translateCommand = defineCommand({
|
|
|
181
182
|
type: "string",
|
|
182
183
|
},
|
|
183
184
|
},
|
|
184
|
-
meta:
|
|
185
|
-
description:
|
|
186
|
-
"Translate docs into the configured locales with a local agent CLI.",
|
|
187
|
-
name: "translate",
|
|
188
|
-
},
|
|
185
|
+
meta: commandMeta.translate,
|
|
189
186
|
async run({ args }) {
|
|
190
187
|
const root = process.cwd();
|
|
191
188
|
const { agent, concurrency, timeoutS } = parseFlags(args);
|
|
@@ -13,6 +13,7 @@ import { validateLinks } from "../../core/links.ts";
|
|
|
13
13
|
import { buildManifest } from "../../core/manifest.ts";
|
|
14
14
|
import { scanProject } from "../../core/project-graph.ts";
|
|
15
15
|
import type { Diagnostic } from "../../core/types.ts";
|
|
16
|
+
import { commandMeta } from "../command-meta.ts";
|
|
16
17
|
import { reportInternalError } from "../internal-error.ts";
|
|
17
18
|
import {
|
|
18
19
|
flushStdout,
|
|
@@ -36,10 +37,7 @@ export const validateCommand = defineCommand({
|
|
|
36
37
|
type: "boolean",
|
|
37
38
|
},
|
|
38
39
|
},
|
|
39
|
-
meta:
|
|
40
|
-
description: "Validate internal, anchor, asset, and external links.",
|
|
41
|
-
name: "validate",
|
|
42
|
-
},
|
|
40
|
+
meta: commandMeta.validate,
|
|
43
41
|
async run({ args }) {
|
|
44
42
|
const root = process.cwd();
|
|
45
43
|
const diagnostics: Diagnostic[] = [];
|
|
@@ -3,6 +3,7 @@ import { defineCommand } from "citty";
|
|
|
3
3
|
import { loadConfig } from "../../core/config.ts";
|
|
4
4
|
import { BlumeError } from "../../core/diagnostics.ts";
|
|
5
5
|
import { CutError, cutVersion } from "../../core/version-cut.ts";
|
|
6
|
+
import { commandMeta } from "../command-meta.ts";
|
|
6
7
|
import { reportInternalError } from "../internal-error.ts";
|
|
7
8
|
import { logger } from "../log.ts";
|
|
8
9
|
|
|
@@ -18,10 +19,7 @@ export const versionCommand = defineCommand({
|
|
|
18
19
|
type: "positional",
|
|
19
20
|
},
|
|
20
21
|
},
|
|
21
|
-
meta:
|
|
22
|
-
description: "Freeze the current docs as an archived version.",
|
|
23
|
-
name: "version",
|
|
24
|
-
},
|
|
22
|
+
meta: commandMeta.version,
|
|
25
23
|
async run({ args }) {
|
|
26
24
|
const root = process.cwd();
|
|
27
25
|
|
package/src/cli/eject-scripts.ts
CHANGED
|
@@ -2,9 +2,6 @@ import { readFile, writeFile } from "node:fs/promises";
|
|
|
2
2
|
|
|
3
3
|
import { join } from "pathe";
|
|
4
4
|
|
|
5
|
-
import type { ResolvedConfig } from "../core/schema.ts";
|
|
6
|
-
import { searchProviderMeta } from "../search/providers.ts";
|
|
7
|
-
|
|
8
5
|
/** A JSON value, as `JSON.parse` of a manifest can return. */
|
|
9
6
|
type JsonValue =
|
|
10
7
|
| string
|
|
@@ -20,48 +17,6 @@ interface PackageManifest {
|
|
|
20
17
|
scripts?: Record<string, string>;
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
/**
|
|
24
|
-
* The `blume build`-only artifacts this project's config actually produces, as
|
|
25
|
-
* notice lines for the eject command. After an eject the build script runs
|
|
26
|
-
* plain `astro build`, which emits none of them — printing the config-aware
|
|
27
|
-
* list makes the loss explicit instead of silent (a Pagefind site would
|
|
28
|
-
* otherwise eject into a build whose search fails at runtime). Each gate
|
|
29
|
-
* mirrors the artifact's producer in `blume build` (cli/commands/build.ts).
|
|
30
|
-
*/
|
|
31
|
-
export const droppedArtifactNotices = (config: ResolvedConfig): string[] => {
|
|
32
|
-
const notices: string[] = [];
|
|
33
|
-
if (config.search.provider === "pagefind") {
|
|
34
|
-
notices.push(
|
|
35
|
-
'the Pagefind search index — the search UI loads it from the built site, so search will break in production. Add a post-build step: `"build": "astro build && pagefind --site dist"` (with `pagefind` installed as a devDependency).'
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
if (searchProviderMeta(config.search.provider).syncs) {
|
|
39
|
-
notices.push(
|
|
40
|
-
`the hosted ${config.search.provider} index sync — new and updated pages stop being pushed; re-upload your search records after each build with the provider's API or CLI.`
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
if (config.ai.llmsTxt.enabled) {
|
|
44
|
-
notices.push("llms.txt and llms-full.txt");
|
|
45
|
-
}
|
|
46
|
-
if (config.deployment.site && config.seo.sitemap) {
|
|
47
|
-
notices.push(
|
|
48
|
-
"sitemap.xml — recreate it with the @astrojs/sitemap integration."
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
if (config.seo.robots) {
|
|
52
|
-
notices.push("robots.txt — recreate it as a public/robots.txt file.");
|
|
53
|
-
}
|
|
54
|
-
if (config.seo.agentReadability) {
|
|
55
|
-
notices.push("agent-readability.json");
|
|
56
|
-
}
|
|
57
|
-
if (config.redirects.length > 0 && config.deployment.output === "static") {
|
|
58
|
-
notices.push(
|
|
59
|
-
"the platform redirect files (_redirects, vercel.json) — your redirects still work as Astro-generated meta-refresh pages."
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
return notices;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
20
|
/**
|
|
66
21
|
* Rewrite the project's package.json scripts to run Astro directly. After an
|
|
67
22
|
* eject the Blume CLI no longer manages the runtime, so scaffolded scripts like
|
package/src/cli/host-args.ts
CHANGED
|
@@ -16,3 +16,19 @@ export const normalizeHostArgs = (rawArgs: readonly string[]): string[] =>
|
|
|
16
16
|
const next = rawArgs[index + 1];
|
|
17
17
|
return next === undefined || next.startsWith("-") ? "--host=" : arg;
|
|
18
18
|
});
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Resolve a `--host` flag value into what Astro/Vite's `server.host` expects.
|
|
22
|
+
* citty has no mixed string/boolean arg type, so `host` is declared as a
|
|
23
|
+
* string and a bare `--host` parses as `""` (`normalizeHostArgs` rewrites it
|
|
24
|
+
* to `--host=` first) — Node would bind all interfaces for `""`, but Vite's
|
|
25
|
+
* `resolveHostname` treats it as a literal hostname and prints malformed URLs
|
|
26
|
+
* like `http://:4321/`. Match Astro's own `--host` semantics instead: bare
|
|
27
|
+
* flag → `true` (bind all interfaces), `--host 10.0.0.1` → that address,
|
|
28
|
+
* absent → `false` (localhost only).
|
|
29
|
+
*
|
|
30
|
+
* Lives beside `normalizeHostArgs` rather than in `commands/dev.ts` so
|
|
31
|
+
* `preview` can share it without importing the whole dev command graph.
|
|
32
|
+
*/
|
|
33
|
+
export const normalizeHost = (host?: string): boolean | string =>
|
|
34
|
+
host === "" ? true : (host ?? false);
|
package/src/cli/index.ts
CHANGED
|
@@ -1,24 +1,18 @@
|
|
|
1
1
|
import { defineCommand, runMain } from "citty";
|
|
2
2
|
|
|
3
3
|
import { getBlumeVersion } from "../core/version.ts";
|
|
4
|
-
import {
|
|
5
|
-
import { auditCommand } from "./commands/audit.ts";
|
|
6
|
-
import { buildCommand } from "./commands/build.ts";
|
|
7
|
-
import { checkCommand } from "./commands/check.ts";
|
|
8
|
-
import { devCommand } from "./commands/dev.ts";
|
|
9
|
-
import { doctorCommand } from "./commands/doctor.ts";
|
|
10
|
-
import { ejectCommand } from "./commands/eject.ts";
|
|
11
|
-
import { evalCommand } from "./commands/eval.ts";
|
|
12
|
-
import { initCommand } from "./commands/init.ts";
|
|
13
|
-
import { mcpStdioCommand } from "./commands/mcp-stdio.ts";
|
|
14
|
-
import { previewCommand } from "./commands/preview.ts";
|
|
15
|
-
import { syncCommand } from "./commands/sync.ts";
|
|
16
|
-
import { translateCommand } from "./commands/translate.ts";
|
|
17
|
-
import { validateCommand } from "./commands/validate.ts";
|
|
18
|
-
import { versionCommand } from "./commands/version.ts";
|
|
4
|
+
import { commandMeta } from "./command-meta.ts";
|
|
19
5
|
import { loadEnvFiles } from "./env.ts";
|
|
20
6
|
import { normalizeHostArgs } from "./host-args.ts";
|
|
21
7
|
import { reportInternalError } from "./internal-error.ts";
|
|
8
|
+
import { lazyCommand } from "./lazy-command.ts";
|
|
9
|
+
// consola reads CONSOLA_LEVEL / NODE_ENV / TEST / CI / DEBUG when its module
|
|
10
|
+
// evaluates. Import the logger here, ahead of `loadEnvFiles`, so those values
|
|
11
|
+
// come from the real environment — never from a project `.env`, which would
|
|
12
|
+
// otherwise silence or restyle every command's output. The commands are loaded
|
|
13
|
+
// lazily below, so without this line consola would first evaluate after `.env`
|
|
14
|
+
// had been applied.
|
|
15
|
+
import "./log.ts";
|
|
22
16
|
|
|
23
17
|
const main = defineCommand({
|
|
24
18
|
meta: {
|
|
@@ -27,31 +21,86 @@ const main = defineCommand({
|
|
|
27
21
|
version: getBlumeVersion(),
|
|
28
22
|
},
|
|
29
23
|
subCommands: {
|
|
30
|
-
add:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
24
|
+
add: lazyCommand(
|
|
25
|
+
commandMeta.add,
|
|
26
|
+
() => import("./commands/add.ts"),
|
|
27
|
+
"addCommand"
|
|
28
|
+
),
|
|
29
|
+
audit: lazyCommand(
|
|
30
|
+
commandMeta.audit,
|
|
31
|
+
() => import("./commands/audit.ts"),
|
|
32
|
+
"auditCommand"
|
|
33
|
+
),
|
|
34
|
+
build: lazyCommand(
|
|
35
|
+
commandMeta.build,
|
|
36
|
+
() => import("./commands/build.ts"),
|
|
37
|
+
"buildCommand"
|
|
38
|
+
),
|
|
39
|
+
check: lazyCommand(
|
|
40
|
+
commandMeta.check,
|
|
41
|
+
() => import("./commands/check.ts"),
|
|
42
|
+
"checkCommand"
|
|
43
|
+
),
|
|
44
|
+
dev: lazyCommand(
|
|
45
|
+
commandMeta.dev,
|
|
46
|
+
() => import("./commands/dev.ts"),
|
|
47
|
+
"devCommand"
|
|
48
|
+
),
|
|
49
|
+
doctor: lazyCommand(
|
|
50
|
+
commandMeta.doctor,
|
|
51
|
+
() => import("./commands/doctor.ts"),
|
|
52
|
+
"doctorCommand"
|
|
53
|
+
),
|
|
54
|
+
eject: lazyCommand(
|
|
55
|
+
commandMeta.eject,
|
|
56
|
+
() => import("./commands/eject.ts"),
|
|
57
|
+
"ejectCommand"
|
|
58
|
+
),
|
|
59
|
+
eval: lazyCommand(
|
|
60
|
+
commandMeta.eval,
|
|
61
|
+
() => import("./commands/eval.ts"),
|
|
62
|
+
"evalCommand"
|
|
63
|
+
),
|
|
64
|
+
init: lazyCommand(
|
|
65
|
+
commandMeta.init,
|
|
66
|
+
() => import("./commands/init.ts"),
|
|
67
|
+
"initCommand"
|
|
68
|
+
),
|
|
69
|
+
"mcp-stdio": lazyCommand(
|
|
70
|
+
commandMeta["mcp-stdio"],
|
|
71
|
+
() => import("./commands/mcp-stdio.ts"),
|
|
72
|
+
"mcpStdioCommand"
|
|
73
|
+
),
|
|
74
|
+
preview: lazyCommand(
|
|
75
|
+
commandMeta.preview,
|
|
76
|
+
() => import("./commands/preview.ts"),
|
|
77
|
+
"previewCommand"
|
|
78
|
+
),
|
|
79
|
+
sync: lazyCommand(
|
|
80
|
+
commandMeta.sync,
|
|
81
|
+
() => import("./commands/sync.ts"),
|
|
82
|
+
"syncCommand"
|
|
83
|
+
),
|
|
84
|
+
translate: lazyCommand(
|
|
85
|
+
commandMeta.translate,
|
|
86
|
+
() => import("./commands/translate.ts"),
|
|
87
|
+
"translateCommand"
|
|
88
|
+
),
|
|
89
|
+
validate: lazyCommand(
|
|
90
|
+
commandMeta.validate,
|
|
91
|
+
() => import("./commands/validate.ts"),
|
|
92
|
+
"validateCommand"
|
|
93
|
+
),
|
|
94
|
+
version: lazyCommand(
|
|
95
|
+
commandMeta.version,
|
|
96
|
+
() => import("./commands/version.ts"),
|
|
97
|
+
"versionCommand"
|
|
98
|
+
),
|
|
45
99
|
},
|
|
46
100
|
});
|
|
47
101
|
|
|
48
|
-
// Load `.env`/`.env.local` before any command runs so remote content sources
|
|
49
|
-
// can read their tokens (e.g. `GITHUB_TOKEN`) during the content scan.
|
|
50
102
|
loadEnvFiles(process.cwd());
|
|
51
103
|
|
|
52
|
-
// Backstop for unexpected async failures that escape a command's own handling
|
|
53
|
-
// (e.g. a rejected timer/watcher in `blume dev`), so even those report through
|
|
54
|
-
// the stable internal-error contract rather than a bare stack trace.
|
|
55
104
|
process.on("uncaughtException", (error) => {
|
|
56
105
|
reportInternalError(error);
|
|
57
106
|
process.exit(1);
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ArgsDef, CommandDef, CommandMeta } from "citty";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Wrap a command so its module is imported only when citty needs its `args`
|
|
5
|
+
* or runs it. `meta` stays static (from `command-meta.ts`), so rendering root
|
|
6
|
+
* usage, matching an unknown name, and `blume <cmd> --help` for *another*
|
|
7
|
+
* command never touch this one's dependency graph.
|
|
8
|
+
*
|
|
9
|
+
* `load` imports the command's module and `key` names its export, so the call
|
|
10
|
+
* site stays a plain `() => import("./commands/x.ts")`.
|
|
11
|
+
*
|
|
12
|
+
* Only `args`, `setup`, `run`, and `cleanup` are forwarded: no Blume command
|
|
13
|
+
* declares `default`, `plugins`, or nested `subCommands`.
|
|
14
|
+
*/
|
|
15
|
+
export const lazyCommand = <Args extends ArgsDef, Key extends string>(
|
|
16
|
+
meta: CommandMeta,
|
|
17
|
+
load: () => Promise<Record<Key, CommandDef<Args>>>,
|
|
18
|
+
key: Key
|
|
19
|
+
): CommandDef<Args> => {
|
|
20
|
+
const command = async () => {
|
|
21
|
+
const module = await load();
|
|
22
|
+
return module[key];
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
args: async () => {
|
|
26
|
+
const { args } = await command();
|
|
27
|
+
// SAFETY: every Blume command passes `args` to `defineCommand` as a plain
|
|
28
|
+
// object literal (the "command registry" test checks it); citty's
|
|
29
|
+
// `Resolvable` widening is the only reason the type also admits a thunk
|
|
30
|
+
// or a promise here.
|
|
31
|
+
return args as Args;
|
|
32
|
+
},
|
|
33
|
+
cleanup: async (context) => {
|
|
34
|
+
const loaded = await command();
|
|
35
|
+
await loaded.cleanup?.(context);
|
|
36
|
+
},
|
|
37
|
+
meta,
|
|
38
|
+
run: async (context) => {
|
|
39
|
+
const loaded = await command();
|
|
40
|
+
await loaded.run?.(context);
|
|
41
|
+
},
|
|
42
|
+
setup: async (context) => {
|
|
43
|
+
const loaded = await command();
|
|
44
|
+
await loaded.setup?.(context);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
};
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// at build time (no client JS). Pass `owner`/`repo`, or omit them to use the
|
|
4
4
|
// repo from blume.config. A `GITHUB_TOKEN` env var lifts the API rate limit.
|
|
5
5
|
// If the API is unreachable the card still renders, just without counts.
|
|
6
|
+
import { getSecret } from "astro:env/server";
|
|
6
7
|
import { apiUrl, PUBLIC_HOST_URL } from "../../core/github.ts";
|
|
7
8
|
import { resolveIcon } from "../../theme/icons.ts";
|
|
8
9
|
import data from "blume:data";
|
|
@@ -38,7 +39,9 @@ interface Props {
|
|
|
38
39
|
const configured = data.config.github;
|
|
39
40
|
const owner = Astro.props.owner ?? configured?.owner;
|
|
40
41
|
const repo = Astro.props.repo ?? configured?.repo;
|
|
41
|
-
|
|
42
|
+
// Read through Astro's `getSecret` so the adapter's secret store is honored
|
|
43
|
+
// (the card renders at build time, where that is the environment).
|
|
44
|
+
const token = Astro.props.token ?? getSecret("GITHUB_TOKEN");
|
|
42
45
|
// A `host` prop is reduced to its origin, as the config field is, so a
|
|
43
46
|
// trailing slash or a path never lands mid-link.
|
|
44
47
|
const host = Astro.props.host
|
|
@@ -42,6 +42,14 @@ class BlumeMermaid extends HTMLElement {
|
|
|
42
42
|
const token = this.#renderToken;
|
|
43
43
|
const mermaid = await loadMermaid();
|
|
44
44
|
mermaid.initialize({
|
|
45
|
+
// Mermaid 12 defaults to the bundled ELK layout and the "neo" look,
|
|
46
|
+
// which re-lays out and restyles every existing diagram and pulls a
|
|
47
|
+
// ~1.4 MB ELK chunk onto any page with a flowchart. Pin the previous
|
|
48
|
+
// defaults so diagrams keep rendering as authored; a diagram opts
|
|
49
|
+
// into ELK or neo through its own front matter (`config: { layout:
|
|
50
|
+
// elk }`), which outranks these initialize() values.
|
|
51
|
+
layout: "dagre",
|
|
52
|
+
look: "classic",
|
|
45
53
|
securityLevel: "strict",
|
|
46
54
|
startOnLoad: false,
|
|
47
55
|
theme: prefersDark() ? "dark" : "default",
|
|
@@ -3,7 +3,7 @@ import VercelAnalytics from "@vercel/analytics/astro";
|
|
|
3
3
|
|
|
4
4
|
// Analytics scripts injected into <head>. PostHog and custom providers use the
|
|
5
5
|
// inline-snippet house style (banner/theme/JSON-LD); Vercel uses its official
|
|
6
|
-
// Astro component. Loads ONLY in production builds so `blume dev` stays clean
|
|
6
|
+
// Astro component; Cloudflare is its beacon script tag. Loads ONLY in production builds so `blume dev` stays clean
|
|
7
7
|
// and local traffic never reaches your analytics.
|
|
8
8
|
interface AnalyticsScript {
|
|
9
9
|
attributes?: Record<string, string>;
|
|
@@ -14,6 +14,7 @@ interface AnalyticsScript {
|
|
|
14
14
|
|
|
15
15
|
interface Props {
|
|
16
16
|
analytics?: {
|
|
17
|
+
cloudflare?: { token: string };
|
|
17
18
|
posthog?: { host?: string; key: string };
|
|
18
19
|
scripts?: AnalyticsScript[];
|
|
19
20
|
vercel?: boolean;
|
|
@@ -45,6 +46,14 @@ const posthogSnippet = posthog
|
|
|
45
46
|
? `${POSTHOG_LOADER}posthog.init(${JSON.stringify(posthog.key)},{api_host:${JSON.stringify(posthog.host ?? "https://us.i.posthog.com")}});${POSTHOG_SPA_PAGEVIEWS}`
|
|
46
47
|
: null;
|
|
47
48
|
|
|
49
|
+
// Cloudflare Web Analytics (manual setup): the beacon script keyed by the
|
|
50
|
+
// site token, exactly as the dashboard's snippet renders it. It tracks
|
|
51
|
+
// history changes itself, so client-router navigations need no extra hook.
|
|
52
|
+
const cloudflareBeacon =
|
|
53
|
+
enabled && analytics?.cloudflare
|
|
54
|
+
? JSON.stringify({ token: analytics.cloudflare.token })
|
|
55
|
+
: null;
|
|
56
|
+
|
|
48
57
|
// Custom scripts: any other provider. Each is either external (`src`) or inline
|
|
49
58
|
// (`content`). Explicit fields win over spread `attributes`.
|
|
50
59
|
const customScripts = enabled ? (analytics?.scripts ?? []) : [];
|
|
@@ -62,6 +71,16 @@ const inlineScripts = customScripts
|
|
|
62
71
|
---
|
|
63
72
|
|
|
64
73
|
{vercelEnabled && <VercelAnalytics />}
|
|
74
|
+
{
|
|
75
|
+
cloudflareBeacon && (
|
|
76
|
+
<script
|
|
77
|
+
is:inline
|
|
78
|
+
defer
|
|
79
|
+
src="https://static.cloudflareinsights.com/beacon.min.js"
|
|
80
|
+
data-cf-beacon={cloudflareBeacon}
|
|
81
|
+
/>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
65
84
|
{posthogSnippet && <script is:inline set:html={posthogSnippet} />}
|
|
66
85
|
{externalScripts.map((attrs) => <script is:inline {...attrs} />)}
|
|
67
86
|
{
|
|
@@ -35,6 +35,7 @@ import {
|
|
|
35
35
|
import { buildStructuredData } from "../../seo/jsonld.ts";
|
|
36
36
|
import { normalizeXHandle } from "../../seo/x-handle.ts";
|
|
37
37
|
import { withBase } from "../islands/base-path.ts";
|
|
38
|
+
import { pageDirection, pageLocale } from "./page-locale.ts";
|
|
38
39
|
import { searchLocaleFor } from "./search-locale.ts";
|
|
39
40
|
import "blume:theme";
|
|
40
41
|
import { ClientRouter } from "astro:transitions";
|
|
@@ -108,7 +109,11 @@ interface Props {
|
|
|
108
109
|
*/
|
|
109
110
|
x?: { creator?: string; handle?: string };
|
|
110
111
|
noindex?: boolean;
|
|
111
|
-
/**
|
|
112
|
+
/**
|
|
113
|
+
* Active locale + direction for `<html lang>`/`<html dir>`. Default to the
|
|
114
|
+
* locale Astro resolved from the URL (`Astro.currentLocale`), then the site
|
|
115
|
+
* default, and to that locale's configured direction.
|
|
116
|
+
*/
|
|
112
117
|
locale?: string;
|
|
113
118
|
dir?: "ltr" | "rtl";
|
|
114
119
|
/** Resolved UI dictionary; English baseline when omitted. */
|
|
@@ -145,13 +150,19 @@ const {
|
|
|
145
150
|
structuredDataEnabled,
|
|
146
151
|
x,
|
|
147
152
|
noindex,
|
|
148
|
-
locale
|
|
149
|
-
dir
|
|
153
|
+
locale: localeProp,
|
|
154
|
+
dir: dirProp,
|
|
150
155
|
ui,
|
|
151
156
|
localeSwitch,
|
|
152
157
|
clientData,
|
|
153
158
|
} = Astro.props;
|
|
154
159
|
|
|
160
|
+
// The locale and direction: the page's own values when it passes them (the
|
|
161
|
+
// content catch-all always does), else what Astro's i18n routing resolved for
|
|
162
|
+
// this URL, else the site default (see `page-locale.ts`).
|
|
163
|
+
const locale = pageLocale(data.config.i18n, localeProp, Astro.currentLocale);
|
|
164
|
+
const dir = dirProp ?? pageDirection(data.config.i18n, locale);
|
|
165
|
+
|
|
155
166
|
const clientDataJson = clientData
|
|
156
167
|
? JSON.stringify(clientData).replaceAll("<", "\\u003c")
|
|
157
168
|
: null;
|