blume 1.6.5 → 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 +22 -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 -27597
- 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/package-root.d.ts +1 -1
- package/dist/types/core/schema.d.ts +70 -0
- package/docs/02-deployment.mdx +1 -1
- package/docs/configuration/ask-ai.mdx +1 -1
- package/docs/configuration/customization.mdx +2 -9
- package/docs/reference/cli.mdx +1 -1
- package/package.json +4 -2
- 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 +20 -23
- 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/layout/PageLayout.astro +14 -3
- package/src/components/layout/ReferenceLayout.astro +14 -4
- package/src/components/layout/RootLayout.astro +14 -4
- package/src/components/layout/page-locale.ts +29 -0
- package/src/core/api-name.ts +18 -0
- package/src/core/code-fences.ts +48 -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 +19 -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
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/registry/registry.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { join } from \"pathe\";\n\nimport { packageRoot } from \"../core/package-root.ts\";\n\n/** A file copied into the user's project by `blume add`. */\nexport interface RegistryFile {\n /** Path to the source file, relative to the blume package `src` directory. */\n source: string;\n /** Destination path relative to the project root. */\n target: string;\n /** Rewrite the file's relative imports to `blume/*` specifiers on copy. */\n rewrite?: boolean;\n}\n\nexport interface RegistryItem {\n name: string;\n description: string;\n files: RegistryFile[];\n /** Lines printed after install to guide the user. */\n postInstall: string[];\n}\n\n/** Absolute path to the blume package `src` directory (the copy source root). */\nexport const packageSrc = join(packageRoot(), \"src\");\n\n/**\n * A built-in layout component offered as editable source. `blume add` rewrites\n * its relative imports to `blume/*`, so it renders identically to the built-in\n * until the user changes it, then registers under the matching `layout` slot.\n */\nconst layoutComponent = (config: {\n name: string;\n description: string;\n /** Source basename under `src/components/layout`. */\n file: string;\n /** Layout slot key, also the import name in the post-install hint. */\n slot: string;\n}): RegistryItem => {\n const target = `components/blume/${config.file}`;\n return {\n description: config.description,\n files: [\n {\n rewrite: true,\n source: `components/layout/${config.file}`,\n target,\n },\n ],\n name: config.name,\n postInstall: [\n \"Register it in components.ts:\",\n ' import { defineComponents } from \"blume\";',\n ` import ${config.slot} from \"./${target}\";`,\n \"\",\n ` export default defineComponents({ layout: { ${config.slot} } });`,\n \"\",\n \"It imports the rest from `blume/*`, so it matches the built-in until you edit it.\",\n ],\n };\n};\n\n/**\n * A built-in MDX content component offered as editable source. Like\n * {@link layoutComponent}, but registered under the `mdx` map (the tag you write\n * in `.mdx`) rather than a `layout` slot.\n */\nconst contentComponent = (config: {\n name: string;\n description: string;\n /** Source basename under `src/components/content`. */\n file: string;\n /** MDX tag / component name, also the import name in the post-install hint. */\n tag: string;\n}): RegistryItem => {\n const target = `components/blume/${config.file}`;\n return {\n description: config.description,\n files: [\n {\n rewrite: true,\n source: `components/content/${config.file}`,\n target,\n },\n ],\n name: config.name,\n postInstall: [\n \"Register it in components.ts:\",\n ' import { defineComponents } from \"blume\";',\n ` import ${config.tag} from \"./${target}\";`,\n \"\",\n ` export default defineComponents({ mdx: { ${config.tag} } });`,\n \"\",\n \"It imports the rest from `blume/*`, so it matches the built-in until you edit it.\",\n ],\n };\n};\n\n/** Every user-facing content component, by `blume add` name → source basename. */\nconst CONTENT_COMPONENTS: {\n name: string;\n description: string;\n file: string;\n tag: string;\n}[] = [\n {\n description: \"Aside for notes, tips, and warnings.\",\n file: \"Callout.astro\",\n name: \"callout\",\n tag: \"Callout\",\n },\n {\n description: \"A linkable card with icon, title, and body.\",\n file: \"Card.astro\",\n name: \"card\",\n tag: \"Card\",\n },\n {\n description: \"A responsive grid of cards.\",\n file: \"CardGroup.astro\",\n name: \"card-group\",\n tag: \"CardGroup\",\n },\n {\n description: \"Tabbed code blocks for multiple languages.\",\n file: \"CodeGroup.astro\",\n name: \"code-group\",\n tag: \"CodeGroup\",\n },\n {\n description: \"A small status/label badge.\",\n file: \"Badge.astro\",\n name: \"badge\",\n tag: \"Badge\",\n },\n {\n description: \"A numbered list of steps.\",\n file: \"Steps.astro\",\n name: \"steps\",\n tag: \"Steps\",\n },\n {\n description: \"A single step within Steps.\",\n file: \"Step.astro\",\n name: \"step\",\n tag: \"Step\",\n },\n {\n description: \"A tabbed content panel.\",\n file: \"Tabs.astro\",\n name: \"tabs\",\n tag: \"Tabs\",\n },\n {\n description: \"A single tab within Tabs.\",\n file: \"Tab.astro\",\n name: \"tab\",\n tag: \"Tab\",\n },\n {\n description: \"A collapsible accordion group.\",\n file: \"Accordion.astro\",\n name: \"accordion\",\n tag: \"Accordion\",\n },\n {\n description: \"A single item within an Accordion.\",\n file: \"AccordionItem.astro\",\n name: \"accordion-item\",\n tag: \"AccordionItem\",\n },\n {\n description: \"A multi-column layout.\",\n file: \"Columns.astro\",\n name: \"columns\",\n tag: \"Columns\",\n },\n {\n description: \"A single column within Columns.\",\n file: \"Column.astro\",\n name: \"column\",\n tag: \"Column\",\n },\n {\n description: \"A bordered frame around an image or embed.\",\n file: \"Frame.astro\",\n name: \"frame\",\n tag: \"Frame\",\n },\n {\n description: \"An inline expand/collapse disclosure.\",\n file: \"Expandable.astro\",\n name: \"expandable\",\n tag: \"Expandable\",\n },\n {\n description: \"A titled content panel.\",\n file: \"Panel.astro\",\n name: \"panel\",\n tag: \"Panel\",\n },\n {\n description: \"A hover tooltip.\",\n file: \"Tooltip.astro\",\n name: \"tooltip\",\n tag: \"Tooltip\",\n },\n {\n description: \"A compact linkable tile.\",\n file: \"Tile.astro\",\n name: \"tile\",\n tag: \"Tile\",\n },\n {\n description: \"A styled prompt / terminal block.\",\n file: \"Prompt.astro\",\n name: \"prompt\",\n tag: \"Prompt\",\n },\n {\n description: \"A responsive, privacy-friendly YouTube embed.\",\n file: \"YouTube.astro\",\n name: \"youtube\",\n tag: \"YouTube\",\n },\n];\n\n/** The built-in, Blume-owned source registry. */\nexport const registry: RegistryItem[] = [\n layoutComponent({\n description: \"The top navigation bar (logo, search, nav links).\",\n file: \"Header.astro\",\n name: \"header\",\n slot: \"Header\",\n }),\n layoutComponent({\n description: \"The sidebar navigation tree.\",\n file: \"NavTree.astro\",\n name: \"sidebar\",\n slot: \"Sidebar\",\n }),\n layoutComponent({\n description: \"The breadcrumb trail shown above page content.\",\n file: \"Breadcrumbs.astro\",\n name: \"breadcrumbs\",\n slot: \"Breadcrumbs\",\n }),\n layoutComponent({\n description: \"The on-this-page table of contents.\",\n file: \"TableOfContents.astro\",\n name: \"table-of-contents\",\n slot: \"TableOfContents\",\n }),\n layoutComponent({\n description: \"The previous/next pagination footer.\",\n file: \"Pagination.astro\",\n name: \"pagination\",\n slot: \"Pagination\",\n }),\n layoutComponent({\n description: 'The \"Was this page helpful?\" feedback rating.',\n file: \"PageFeedback.astro\",\n name: \"feedback\",\n slot: \"Feedback\",\n }),\n ...CONTENT_COMPONENTS.map(contentComponent),\n];\n\nexport const findItem = (name: string): RegistryItem | undefined =>\n registry.find((item) => item.name === name);\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "2BDCE672B82B453C64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
findItem,
|
|
4
|
+
packageSrc,
|
|
5
|
+
registry
|
|
6
|
+
} from "./chunk-3r94j3tc.js";
|
|
7
|
+
import"./chunk-6kzzpsx8.js";
|
|
8
|
+
import {
|
|
9
|
+
logger
|
|
10
|
+
} from "./chunk-ey89bjj1.js";
|
|
11
|
+
import {
|
|
12
|
+
commandMeta
|
|
13
|
+
} from "./chunk-2aj8ddew.js";
|
|
14
|
+
|
|
15
|
+
// src/cli/commands/add.ts
|
|
16
|
+
import { existsSync } from "node:fs";
|
|
17
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
18
|
+
import { defineCommand } from "citty";
|
|
19
|
+
import { dirname as dirname2, join } from "pathe";
|
|
20
|
+
|
|
21
|
+
// src/registry/rewrite-imports.ts
|
|
22
|
+
import { dirname, relative, resolve } from "pathe";
|
|
23
|
+
var FROM_IMPORT = /(?<prefix>^[ \t]*(?:import|export)\b[^;]*?\bfrom[ \t]*)(?<quote>["'])(?<spec>\.[^"']*)\k<quote>/gmu;
|
|
24
|
+
var SIDE_EFFECT_IMPORT = /(?<prefix>^[ \t]*import[ \t]+)(?<quote>["'])(?<spec>\.[^"']*)\k<quote>/gmu;
|
|
25
|
+
var rewriteImports = (content, sourceFile, srcRoot) => {
|
|
26
|
+
const rewrite = (match, prefix, quote, spec) => {
|
|
27
|
+
const resolved = resolve(dirname(sourceFile), spec);
|
|
28
|
+
if (resolved === sourceFile) {
|
|
29
|
+
return match;
|
|
30
|
+
}
|
|
31
|
+
const rel = relative(srcRoot, resolved);
|
|
32
|
+
if (rel.startsWith("..")) {
|
|
33
|
+
return match;
|
|
34
|
+
}
|
|
35
|
+
return `${prefix}${quote}blume/${rel}${quote}`;
|
|
36
|
+
};
|
|
37
|
+
return content.replaceAll(FROM_IMPORT, rewrite).replaceAll(SIDE_EFFECT_IMPORT, rewrite);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// src/cli/commands/add.ts
|
|
41
|
+
var addCommand = defineCommand({
|
|
42
|
+
args: {
|
|
43
|
+
force: { description: "Overwrite existing files.", type: "boolean" },
|
|
44
|
+
name: {
|
|
45
|
+
description: "Registry item to install.",
|
|
46
|
+
required: false,
|
|
47
|
+
type: "positional"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
meta: commandMeta.add,
|
|
51
|
+
async run({ args }) {
|
|
52
|
+
const root = process.cwd();
|
|
53
|
+
if (!args.name) {
|
|
54
|
+
logger.info("Available registry items:");
|
|
55
|
+
for (const item2 of registry) {
|
|
56
|
+
process.stdout.write(` ${item2.name} — ${item2.description}
|
|
57
|
+
`);
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const item = findItem(args.name);
|
|
62
|
+
if (!item) {
|
|
63
|
+
logger.error(`Unknown registry item: ${args.name}`);
|
|
64
|
+
logger.info(`Run \`blume add\` to list available items.`);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
const plan = item.files.map((file) => ({
|
|
68
|
+
file,
|
|
69
|
+
skip: existsSync(join(root, file.target)) && !args.force,
|
|
70
|
+
target: join(root, file.target)
|
|
71
|
+
}));
|
|
72
|
+
await Promise.all(plan.filter((entry) => !entry.skip).map(async (entry) => {
|
|
73
|
+
const source = join(packageSrc, entry.file.source);
|
|
74
|
+
const raw = await readFile(source, "utf-8");
|
|
75
|
+
const content = entry.file.rewrite ? rewriteImports(raw, source, packageSrc) : raw;
|
|
76
|
+
await mkdir(dirname2(entry.target), { recursive: true });
|
|
77
|
+
await writeFile(entry.target, content, "utf-8");
|
|
78
|
+
}));
|
|
79
|
+
for (const entry of plan) {
|
|
80
|
+
if (entry.skip) {
|
|
81
|
+
logger.warn(`Skipped existing ${entry.file.target} (use --force to overwrite)`);
|
|
82
|
+
} else {
|
|
83
|
+
logger.success(`Added ${entry.file.target}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (item.postInstall.length > 0) {
|
|
87
|
+
process.stdout.write(`
|
|
88
|
+
Next steps:
|
|
89
|
+
`);
|
|
90
|
+
for (const line of item.postInstall) {
|
|
91
|
+
process.stdout.write(` ${line}
|
|
92
|
+
`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
export {
|
|
98
|
+
addCommand
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
//# debugId=2570752CA48BB3F964756E2164756E21
|
|
102
|
+
//# sourceMappingURL=chunk-4trphnvy.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/cli/commands/add.ts", "../src/registry/rewrite-imports.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { existsSync } from \"node:fs\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\n\nimport { defineCommand } from \"citty\";\nimport { dirname, join } from \"pathe\";\n\nimport { findItem, packageSrc, registry } from \"../../registry/registry.ts\";\nimport { rewriteImports } from \"../../registry/rewrite-imports.ts\";\nimport { commandMeta } from \"../command-meta.ts\";\nimport { logger } from \"../log.ts\";\n\nexport const addCommand = defineCommand({\n args: {\n force: { description: \"Overwrite existing files.\", type: \"boolean\" },\n name: {\n description: \"Registry item to install.\",\n required: false,\n type: \"positional\",\n },\n },\n meta: commandMeta.add,\n async run({ args }) {\n const root = process.cwd();\n\n if (!args.name) {\n logger.info(\"Available registry items:\");\n for (const item of registry) {\n process.stdout.write(` ${item.name} — ${item.description}\\n`);\n }\n return;\n }\n\n const item = findItem(args.name);\n if (!item) {\n logger.error(`Unknown registry item: ${args.name}`);\n logger.info(`Run \\`blume add\\` to list available items.`);\n process.exit(1);\n }\n\n const plan = item.files.map((file) => ({\n file,\n skip: existsSync(join(root, file.target)) && !args.force,\n target: join(root, file.target),\n }));\n\n await Promise.all(\n plan\n .filter((entry) => !entry.skip)\n .map(async (entry) => {\n const source = join(packageSrc, entry.file.source);\n const raw = await readFile(source, \"utf-8\");\n // Built-in components carry relative imports into the package; rewrite\n // them to `blume/*` so the installed copy resolves them.\n const content = entry.file.rewrite\n ? rewriteImports(raw, source, packageSrc)\n : raw;\n await mkdir(dirname(entry.target), { recursive: true });\n await writeFile(entry.target, content, \"utf-8\");\n })\n );\n\n for (const entry of plan) {\n if (entry.skip) {\n logger.warn(\n `Skipped existing ${entry.file.target} (use --force to overwrite)`\n );\n } else {\n logger.success(`Added ${entry.file.target}`);\n }\n }\n\n if (item.postInstall.length > 0) {\n process.stdout.write(`\\nNext steps:\\n`);\n for (const line of item.postInstall) {\n process.stdout.write(` ${line}\\n`);\n }\n }\n },\n});\n",
|
|
6
|
+
"import { dirname, relative, resolve } from \"pathe\";\n\n// A relative specifier (starting with `.`) in an `import … from \"…\"` or\n// `export … from \"…\"` statement. Anchored to the start of a line (`m` flag) and\n// bounded by `[^;]` so it only matches a real statement — not a `from \"./…\"`\n// that happens to appear inside a string or JSX text — while still allowing a\n// multiline import body between the keyword and `from`.\nconst FROM_IMPORT =\n /(?<prefix>^[ \\t]*(?:import|export)\\b[^;]*?\\bfrom[ \\t]*)(?<quote>[\"'])(?<spec>\\.[^\"']*)\\k<quote>/gmu;\n\n// A side-effect `import \"./…\"` at the start of a line.\nconst SIDE_EFFECT_IMPORT =\n /(?<prefix>^[ \\t]*import[ \\t]+)(?<quote>[\"'])(?<spec>\\.[^\"']*)\\k<quote>/gmu;\n\n/**\n * Rewrite a built-in component's relative imports to `blume/*` package\n * specifiers, so a copy installed by `blume add` resolves the rest of the\n * framework from the package instead of broken relative paths.\n *\n * `sourceFile` is the original file's absolute path and `srcRoot` the package\n * `src` directory; a relative import is resolved against the source, mapped to\n * its path under `src`, and re-emitted as `blume/<that path>`. Two specifiers\n * are left untouched: a self-reference (a component importing itself, e.g. the\n * recursive nav tree) stays relative so the copy recurses into the copy, and\n * anything resolving outside `src` is left as-is.\n */\nexport const rewriteImports = (\n content: string,\n sourceFile: string,\n srcRoot: string\n): string => {\n const rewrite = (\n match: string,\n prefix: string,\n quote: string,\n spec: string\n ): string => {\n const resolved = resolve(dirname(sourceFile), spec);\n if (resolved === sourceFile) {\n return match;\n }\n const rel = relative(srcRoot, resolved);\n if (rel.startsWith(\"..\")) {\n return match;\n }\n return `${prefix}${quote}blume/${rel}${quote}`;\n };\n return content\n .replaceAll(FROM_IMPORT, rewrite)\n .replaceAll(SIDE_EFFECT_IMPORT, rewrite);\n};\n"
|
|
7
|
+
],
|
|
8
|
+
"mappings": ";;;;;;;;;;;;;;;AAAA;AACA;AAEA;AACA,oBAAS;;;ACJT;AAOA,IAAM,cACJ;AAGF,IAAM,qBACJ;AAcK,IAAM,iBAAiB,CAC5B,SACA,YACA,YACW;AAAA,EACX,MAAM,UAAU,CACd,OACA,QACA,OACA,SACW;AAAA,IACX,MAAM,WAAW,QAAQ,QAAQ,UAAU,GAAG,IAAI;AAAA,IAClD,IAAI,aAAa,YAAY;AAAA,MAC3B,OAAO;AAAA,IACT;AAAA,IACA,MAAM,MAAM,SAAS,SAAS,QAAQ;AAAA,IACtC,IAAI,IAAI,WAAW,IAAI,GAAG;AAAA,MACxB,OAAO;AAAA,IACT;AAAA,IACA,OAAO,GAAG,SAAS,cAAc,MAAM;AAAA;AAAA,EAEzC,OAAO,QACJ,WAAW,aAAa,OAAO,EAC/B,WAAW,oBAAoB,OAAO;AAAA;;;ADtCpC,IAAM,aAAa,cAAc;AAAA,EACtC,MAAM;AAAA,IACJ,OAAO,EAAE,aAAa,6BAA6B,MAAM,UAAU;AAAA,IACnE,MAAM;AAAA,MACJ,aAAa;AAAA,MACb,UAAU;AAAA,MACV,MAAM;AAAA,IACR;AAAA,EACF;AAAA,EACA,MAAM,YAAY;AAAA,OACZ,IAAG,GAAG,QAAQ;AAAA,IAClB,MAAM,OAAO,QAAQ,IAAI;AAAA,IAEzB,IAAI,CAAC,KAAK,MAAM;AAAA,MACd,OAAO,KAAK,2BAA2B;AAAA,MACvC,WAAW,SAAQ,UAAU;AAAA,QAC3B,QAAQ,OAAO,MAAM,KAAK,MAAK,UAAU,MAAK;AAAA,CAAe;AAAA,MAC/D;AAAA,MACA;AAAA,IACF;AAAA,IAEA,MAAM,OAAO,SAAS,KAAK,IAAI;AAAA,IAC/B,IAAI,CAAC,MAAM;AAAA,MACT,OAAO,MAAM,0BAA0B,KAAK,MAAM;AAAA,MAClD,OAAO,KAAK,4CAA4C;AAAA,MACxD,QAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,IAEA,MAAM,OAAO,KAAK,MAAM,IAAI,CAAC,UAAU;AAAA,MACrC;AAAA,MACA,MAAM,WAAW,KAAK,MAAM,KAAK,MAAM,CAAC,KAAK,CAAC,KAAK;AAAA,MACnD,QAAQ,KAAK,MAAM,KAAK,MAAM;AAAA,IAChC,EAAE;AAAA,IAEF,MAAM,QAAQ,IACZ,KACG,OAAO,CAAC,UAAU,CAAC,MAAM,IAAI,EAC7B,IAAI,OAAO,UAAU;AAAA,MACpB,MAAM,SAAS,KAAK,YAAY,MAAM,KAAK,MAAM;AAAA,MACjD,MAAM,MAAM,MAAM,SAAS,QAAQ,OAAO;AAAA,MAG1C,MAAM,UAAU,MAAM,KAAK,UACvB,eAAe,KAAK,QAAQ,UAAU,IACtC;AAAA,MACJ,MAAM,MAAM,SAAQ,MAAM,MAAM,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,MACtD,MAAM,UAAU,MAAM,QAAQ,SAAS,OAAO;AAAA,KAC/C,CACL;AAAA,IAEA,WAAW,SAAS,MAAM;AAAA,MACxB,IAAI,MAAM,MAAM;AAAA,QACd,OAAO,KACL,oBAAoB,MAAM,KAAK,mCACjC;AAAA,MACF,EAAO;AAAA,QACL,OAAO,QAAQ,SAAS,MAAM,KAAK,QAAQ;AAAA;AAAA,IAE/C;AAAA,IAEA,IAAI,KAAK,YAAY,SAAS,GAAG;AAAA,MAC/B,QAAQ,OAAO,MAAM;AAAA;AAAA,CAAiB;AAAA,MACtC,WAAW,QAAQ,KAAK,aAAa;AAAA,QACnC,QAAQ,OAAO,MAAM,KAAK;AAAA,CAAQ;AAAA,MACpC;AAAA,IACF;AAAA;AAEJ,CAAC;",
|
|
9
|
+
"debugId": "2570752CA48BB3F964756E2164756E21",
|
|
10
|
+
"names": []
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
packageRoot
|
|
4
|
+
} from "./chunk-6kzzpsx8.js";
|
|
5
|
+
|
|
6
|
+
// src/core/version.ts
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "pathe";
|
|
9
|
+
var cached;
|
|
10
|
+
var getBlumeVersion = () => {
|
|
11
|
+
if (cached === undefined) {
|
|
12
|
+
const pkgPath = join(packageRoot(), "package.json");
|
|
13
|
+
cached = JSON.parse(readFileSync(pkgPath, "utf-8")).version;
|
|
14
|
+
}
|
|
15
|
+
return cached;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { getBlumeVersion };
|
|
19
|
+
|
|
20
|
+
//# debugId=C3D76F992F5A14AE64756E2164756E21
|
|
21
|
+
//# sourceMappingURL=chunk-4xyggvgf.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/core/version.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { readFileSync } from \"node:fs\";\n\nimport { join } from \"pathe\";\n\nimport { packageRoot } from \"./package-root.ts\";\n\nlet cached: string | undefined;\n\n/**\n * The installed Blume package version, read lazily from its `package.json`.\n *\n * Computed on demand (not at module load) so importing the `blume` barrel has no\n * filesystem side effect, and anchored at the package root so it resolves the\n * same whether running from source or the bundled CLI.\n */\nexport const getBlumeVersion = (): string => {\n if (cached === undefined) {\n const pkgPath = join(packageRoot(), \"package.json\");\n // SAFETY: this reads blume's own package.json, which always declares a\n // `version` (publishing requires it).\n cached = (JSON.parse(readFileSync(pkgPath, \"utf-8\")) as { version: string })\n .version;\n }\n return cached;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;;;;AAAA;AAEA;AAIA,IAAI;AASG,IAAM,kBAAkB,MAAc;AAAA,EAC3C,IAAI,WAAW,WAAW;AAAA,IACxB,MAAM,UAAU,KAAK,YAAY,GAAG,cAAc;AAAA,IAGlD,SAAU,KAAK,MAAM,aAAa,SAAS,OAAO,CAAC,EAChD;AAAA,EACL;AAAA,EACA,OAAO;AAAA;",
|
|
8
|
+
"debugId": "C3D76F992F5A14AE64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/core/gitignore.ts
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
6
|
+
import { join } from "pathe";
|
|
7
|
+
var gitignoreKey = (line) => line.trim().replace(/\/+$/u, "");
|
|
8
|
+
var ensureGitignore = async (root, entries) => {
|
|
9
|
+
const path = join(root, ".gitignore");
|
|
10
|
+
const existing = existsSync(path) ? await readFile(path, "utf-8") : "";
|
|
11
|
+
const present = new Set(existing.split(`
|
|
12
|
+
`).flatMap((line) => {
|
|
13
|
+
const key = gitignoreKey(line);
|
|
14
|
+
return key ? [key] : [];
|
|
15
|
+
}));
|
|
16
|
+
const added = entries.filter((entry) => !present.has(gitignoreKey(entry)));
|
|
17
|
+
if (added.length === 0) {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
const gap = existing.length > 0 && !existing.endsWith(`
|
|
21
|
+
`) ? `
|
|
22
|
+
` : "";
|
|
23
|
+
await writeFile(path, `${existing}${gap}${added.join(`
|
|
24
|
+
`)}
|
|
25
|
+
`, "utf-8");
|
|
26
|
+
return added;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export { ensureGitignore };
|
|
30
|
+
|
|
31
|
+
//# debugId=70BE1E0F7334EDD064756E2164756E21
|
|
32
|
+
//# sourceMappingURL=chunk-5hs6gb7n.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/core/gitignore.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { existsSync } from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\n\nimport { join } from \"pathe\";\n\n/** A `.gitignore` line, normalized for comparison (trailing slashes dropped). */\nconst gitignoreKey = (line: string): string => line.trim().replace(/\\/+$/u, \"\");\n\n/**\n * Ensure `.gitignore` ignores each of `entries`, appending any that are missing\n * (creating the file when absent). Trailing-slash differences (`dist` vs\n * `dist/`) count as already present. Returns the entries actually added.\n */\nexport const ensureGitignore = async (\n root: string,\n entries: string[]\n): Promise<string[]> => {\n const path = join(root, \".gitignore\");\n const existing = existsSync(path) ? await readFile(path, \"utf-8\") : \"\";\n const present = new Set(\n existing.split(\"\\n\").flatMap((line) => {\n const key = gitignoreKey(line);\n return key ? [key] : [];\n })\n );\n const added = entries.filter((entry) => !present.has(gitignoreKey(entry)));\n if (added.length === 0) {\n return [];\n }\n const gap = existing.length > 0 && !existing.endsWith(\"\\n\") ? \"\\n\" : \"\";\n await writeFile(path, `${existing}${gap}${added.join(\"\\n\")}\\n`, \"utf-8\");\n return added;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": ";;;AAAA;AACA;AAEA;AAGA,IAAM,eAAe,CAAC,SAAyB,KAAK,KAAK,EAAE,QAAQ,SAAS,EAAE;AAOvE,IAAM,kBAAkB,OAC7B,MACA,YACsB;AAAA,EACtB,MAAM,OAAO,KAAK,MAAM,YAAY;AAAA,EACpC,MAAM,WAAW,WAAW,IAAI,IAAI,MAAM,SAAS,MAAM,OAAO,IAAI;AAAA,EACpE,MAAM,UAAU,IAAI,IAClB,SAAS,MAAM;AAAA,CAAI,EAAE,QAAQ,CAAC,SAAS;AAAA,IACrC,MAAM,MAAM,aAAa,IAAI;AAAA,IAC7B,OAAO,MAAM,CAAC,GAAG,IAAI,CAAC;AAAA,GACvB,CACH;AAAA,EACA,MAAM,QAAQ,QAAQ,OAAO,CAAC,UAAU,CAAC,QAAQ,IAAI,aAAa,KAAK,CAAC,CAAC;AAAA,EACzE,IAAI,MAAM,WAAW,GAAG;AAAA,IACtB,OAAO,CAAC;AAAA,EACV;AAAA,EACA,MAAM,MAAM,SAAS,SAAS,KAAK,CAAC,SAAS,SAAS;AAAA,CAAI,IAAI;AAAA,IAAO;AAAA,EACrE,MAAM,UAAU,MAAM,GAAG,WAAW,MAAM,MAAM,KAAK;AAAA,CAAI;AAAA,GAAO,OAAO;AAAA,EACvE,OAAO;AAAA;",
|
|
8
|
+
"debugId": "70BE1E0F7334EDD064756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
INLINE_CODE,
|
|
4
|
+
MD_IMAGE,
|
|
5
|
+
expandIncludes,
|
|
6
|
+
hasIncludeStatements,
|
|
7
|
+
hashText,
|
|
8
|
+
nextFenceState,
|
|
9
|
+
targetOffsetIn
|
|
10
|
+
} from "./chunk-etsqspj6.js";
|
|
11
|
+
import {
|
|
12
|
+
normalizeBasePath
|
|
13
|
+
} from "./chunk-27gtm2ym.js";
|
|
14
|
+
|
|
15
|
+
// src/core/sources/read.ts
|
|
16
|
+
import { readFile } from "node:fs/promises";
|
|
17
|
+
var readEntryText = async (ctx, page) => {
|
|
18
|
+
if (page.body) {
|
|
19
|
+
return page.body.text;
|
|
20
|
+
}
|
|
21
|
+
const name = page.source?.name;
|
|
22
|
+
const source = name ? ctx.sources?.find((candidate) => candidate.name === name) : undefined;
|
|
23
|
+
if (source?.read) {
|
|
24
|
+
return await source.read(page.source.ref);
|
|
25
|
+
}
|
|
26
|
+
if (page.sourcePath) {
|
|
27
|
+
return await readFile(page.sourcePath, "utf-8");
|
|
28
|
+
}
|
|
29
|
+
return "";
|
|
30
|
+
};
|
|
31
|
+
var readExpandedEntryText = async (ctx, page) => {
|
|
32
|
+
const raw = await readEntryText(ctx, page);
|
|
33
|
+
if (!(page.sourcePath && hasIncludeStatements(raw))) {
|
|
34
|
+
return raw;
|
|
35
|
+
}
|
|
36
|
+
const source = ctx.sources?.find((candidate) => candidate.name === page.source.name);
|
|
37
|
+
if (!source || source.staged || !source.contentRoot) {
|
|
38
|
+
return raw;
|
|
39
|
+
}
|
|
40
|
+
const expansion = await expandIncludes(raw, {
|
|
41
|
+
contentRoot: source.contentRoot,
|
|
42
|
+
sourcePath: page.sourcePath
|
|
43
|
+
});
|
|
44
|
+
return expansion.text;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// src/core/content-assets.ts
|
|
48
|
+
import { readdirSync, statSync } from "node:fs";
|
|
49
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
50
|
+
import {
|
|
51
|
+
basename,
|
|
52
|
+
dirname,
|
|
53
|
+
extname,
|
|
54
|
+
normalize,
|
|
55
|
+
relative,
|
|
56
|
+
resolve
|
|
57
|
+
} from "pathe";
|
|
58
|
+
var CONTENT_ASSETS_PREFIX = "/blume-assets/content";
|
|
59
|
+
var IMAGE_EXTENSIONS = new Set([
|
|
60
|
+
".apng",
|
|
61
|
+
".avif",
|
|
62
|
+
".bmp",
|
|
63
|
+
".gif",
|
|
64
|
+
".ico",
|
|
65
|
+
".jpeg",
|
|
66
|
+
".jpg",
|
|
67
|
+
".png",
|
|
68
|
+
".svg",
|
|
69
|
+
".tiff",
|
|
70
|
+
".webp"
|
|
71
|
+
]);
|
|
72
|
+
var isRelativeTarget = (target) => !(target.startsWith("/") || target.startsWith("#")) && !URL.canParse(target);
|
|
73
|
+
var contentAssetParam = (projectRoot, absPath) => {
|
|
74
|
+
const rel = relative(projectRoot, absPath);
|
|
75
|
+
if (rel.startsWith("..")) {
|
|
76
|
+
return `_/${hashText(absPath)}${extname(absPath)}`;
|
|
77
|
+
}
|
|
78
|
+
return rel;
|
|
79
|
+
};
|
|
80
|
+
var decodeTarget = (target) => {
|
|
81
|
+
try {
|
|
82
|
+
return decodeURI(target);
|
|
83
|
+
} catch {
|
|
84
|
+
return target;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var isRelativeImageTarget = (target) => isRelativeTarget(target) && IMAGE_EXTENSIONS.has(extname(decodeTarget(target)).toLowerCase());
|
|
88
|
+
var existsAsWritten = (abs, segments) => {
|
|
89
|
+
let current = abs;
|
|
90
|
+
for (let i = 0;i < segments; i += 1) {
|
|
91
|
+
const parent = dirname(current);
|
|
92
|
+
let entries;
|
|
93
|
+
try {
|
|
94
|
+
entries = readdirSync(parent);
|
|
95
|
+
} catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
if (!entries.includes(basename(current))) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
current = parent;
|
|
102
|
+
}
|
|
103
|
+
const stat = statSync(abs, { throwIfNoEntry: false });
|
|
104
|
+
return stat !== undefined && stat.isFile();
|
|
105
|
+
};
|
|
106
|
+
var resolveRelativeImage = (sourceDir, target) => {
|
|
107
|
+
if (!isRelativeImageTarget(target)) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
const decoded = decodeTarget(target);
|
|
111
|
+
const segments = normalize(decoded).split("/").filter((part) => part !== "" && part !== "..").length;
|
|
112
|
+
const abs = resolve(sourceDir, decoded);
|
|
113
|
+
return existsAsWritten(abs, segments) ? abs : null;
|
|
114
|
+
};
|
|
115
|
+
var encodedParam = (param) => param.split("/").map(encodeURIComponent).join("/");
|
|
116
|
+
var rewriteLine = (line, toUrl) => {
|
|
117
|
+
const masked = line.replaceAll(INLINE_CODE, (span) => " ".repeat(span.length));
|
|
118
|
+
let out = "";
|
|
119
|
+
let cursor = 0;
|
|
120
|
+
for (const match of masked.matchAll(MD_IMAGE)) {
|
|
121
|
+
const target = match.groups?.target ?? "";
|
|
122
|
+
const url = toUrl(target);
|
|
123
|
+
if (url === null) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
const offset = (match.index ?? 0) + targetOffsetIn(match[0], target, match.groups?.title);
|
|
127
|
+
out += line.slice(cursor, offset) + url;
|
|
128
|
+
cursor = offset + target.length;
|
|
129
|
+
}
|
|
130
|
+
return out + line.slice(cursor);
|
|
131
|
+
};
|
|
132
|
+
var rewriteRelativeImages = (options) => {
|
|
133
|
+
const { source, sourcePath, projectRoot, deployBase, register } = options;
|
|
134
|
+
const sourceDir = dirname(sourcePath);
|
|
135
|
+
const prefix = `${normalizeBasePath(deployBase)}${CONTENT_ASSETS_PREFIX}`;
|
|
136
|
+
const toUrl = (target) => {
|
|
137
|
+
const abs = resolveRelativeImage(sourceDir, target);
|
|
138
|
+
if (abs === null) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
const param = contentAssetParam(projectRoot, abs);
|
|
142
|
+
register?.(param, abs);
|
|
143
|
+
return `${prefix}/${encodedParam(param)}`;
|
|
144
|
+
};
|
|
145
|
+
let fence = null;
|
|
146
|
+
const lines = source.split(`
|
|
147
|
+
`).map((line) => {
|
|
148
|
+
const next = nextFenceState(line, fence);
|
|
149
|
+
const inFence = fence !== null || next !== null;
|
|
150
|
+
fence = next;
|
|
151
|
+
return inFence ? line : rewriteLine(line, toUrl);
|
|
152
|
+
});
|
|
153
|
+
return lines.join(`
|
|
154
|
+
`);
|
|
155
|
+
};
|
|
156
|
+
var collectContentAssets = async (project) => {
|
|
157
|
+
const pageById = new Map(project.graph.pages.map((page) => [page.id, page]));
|
|
158
|
+
const files = {};
|
|
159
|
+
await Promise.all(project.manifest.routes.map(async (route) => {
|
|
160
|
+
if (!route.sourcePath) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const page = pageById.get(route.id);
|
|
164
|
+
let source;
|
|
165
|
+
try {
|
|
166
|
+
source = page ? await readExpandedEntryText(project, page) : await readFile2(route.sourcePath, "utf-8");
|
|
167
|
+
} catch {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
rewriteRelativeImages({
|
|
171
|
+
projectRoot: project.context.root,
|
|
172
|
+
register: (param, abs) => {
|
|
173
|
+
files[param] = abs;
|
|
174
|
+
},
|
|
175
|
+
source,
|
|
176
|
+
sourcePath: route.sourcePath
|
|
177
|
+
});
|
|
178
|
+
}));
|
|
179
|
+
return files;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export { readExpandedEntryText, isRelativeImageTarget, resolveRelativeImage, rewriteRelativeImages, collectContentAssets };
|
|
183
|
+
|
|
184
|
+
//# debugId=2D2EF7E4F8223F9E64756E2164756E21
|
|
185
|
+
//# sourceMappingURL=chunk-5yvt556e.js.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/core/sources/read.ts", "../src/core/content-assets.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { readFile } from \"node:fs/promises\";\n\nimport { expandIncludes, hasIncludeStatements } from \"../includes.ts\";\nimport type { PageRecord } from \"../types.ts\";\nimport type { ContentSource } from \"./types.ts\";\n\n/** The subset of a scanned project the entry reader needs. */\nexport interface EntryReadContext {\n /** The instantiated sources, keyed for `read()` lookups. */\n sources?: ContentSource[];\n}\n\n/**\n * Read an entry's raw body text without assuming a filesystem path. Prefers the\n * body captured at scan time (staged sources), then the owning source's lazy\n * `read()`, then the back-compat `sourcePath` (any local file). Returns `\"\"` when an\n * entry can't be resolved, so callers degrade gracefully.\n */\nexport const readEntryText = async (\n ctx: EntryReadContext,\n page: PageRecord\n): Promise<string> => {\n if (page.body) {\n return page.body.text;\n }\n const name = page.source?.name;\n const source = name\n ? ctx.sources?.find((candidate) => candidate.name === name)\n : undefined;\n if (source?.read) {\n return await source.read(page.source.ref);\n }\n if (page.sourcePath) {\n return await readFile(page.sourcePath, \"utf-8\");\n }\n return \"\";\n};\n\n/**\n * Read an entry's raw body with `<include>` statements expanded — what search\n * indexing, the `.md`/`.mdx` mirrors, and llms-full.txt should see, matching\n * the spliced content the rendered page shows. Filesystem entries only\n * (includes resolve as filesystem paths); everything else passes through\n * verbatim. Expansion errors were already surfaced as scan diagnostics, so\n * unresolvable statements simply stay verbatim here.\n */\nexport const readExpandedEntryText = async (\n ctx: EntryReadContext,\n page: PageRecord\n): Promise<string> => {\n const raw = await readEntryText(ctx, page);\n if (!(page.sourcePath && hasIncludeStatements(raw))) {\n return raw;\n }\n const source = ctx.sources?.find(\n (candidate) => candidate.name === page.source.name\n );\n // Mirror the scan's expansion gate exactly (`!staged && contentRoot`): a\n // staged/custom source's entries were never expanded at scan time, so no\n // headings/links/diagnostics exist for the spliced content — expanding only\n // here would splice text the rest of the pipeline never validated, with no\n // content-root bound on resolution.\n if (!source || source.staged || !source.contentRoot) {\n return raw;\n }\n const expansion = await expandIncludes(raw, {\n contentRoot: source.contentRoot,\n sourcePath: page.sourcePath,\n });\n return expansion.text;\n};\n",
|
|
6
|
+
"import { readdirSync, statSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\n\nimport {\n basename,\n dirname,\n extname,\n normalize,\n relative,\n resolve,\n} from \"pathe\";\n\nimport { normalizeBasePath } from \"./base-path.ts\";\nimport { nextFenceState } from \"./code-fences.ts\";\nimport type { FenceState } from \"./code-fences.ts\";\nimport { hashText } from \"./sources/cache.ts\";\nimport { INLINE_CODE, MD_IMAGE, targetOffsetIn } from \"./sources/normalize.ts\";\nimport { readExpandedEntryText } from \"./sources/read.ts\";\nimport type { ContentSource } from \"./sources/types.ts\";\nimport type { PageRecord } from \"./types.ts\";\n\n/**\n * Colocated content images — `` next to the page that\n * references it. The HTML render optimizes these through `astro:assets` into\n * hashed `_astro/` files, but that mapping doesn't exist yet when the raw\n * agent-facing Markdown (`/<route>.md`, llms-full.txt, MCP) is snapshotted at\n * generate time — so a verbatim relative path would 404 for every agent\n * fetching the page by URL. Instead, the originals are served at\n * `/blume-assets/content/<project-relative path>` by a generated endpoint (see\n * `contentAssetsEndpointTemplate`), and these helpers rewrite the relative\n * references in agent-facing output to that URL.\n */\n\n/** The endpoint route prefix colocated content images are served under. */\nexport const CONTENT_ASSETS_PREFIX = \"/blume-assets/content\";\n\n// The formats Astro's image pipeline accepts, plus the web-safe pass-throughs;\n// anything else referenced relatively (a `.pdf`, a source file) is left alone.\nconst IMAGE_EXTENSIONS = new Set([\n \".apng\",\n \".avif\",\n \".bmp\",\n \".gif\",\n \".ico\",\n \".jpeg\",\n \".jpg\",\n \".png\",\n \".svg\",\n \".tiff\",\n \".webp\",\n]);\n\n/** Whether a link target is a relative filesystem path (not URL/absolute/hash). */\nconst isRelativeTarget = (target: string): boolean =>\n !(target.startsWith(\"/\") || target.startsWith(\"#\")) && !URL.canParse(target);\n\n/**\n * The endpoint param a colocated image is served under: its project-relative\n * path (readable, collision-free — it mirrors the source tree). A file outside\n * the project root can't be addressed that way (`..` segments don't survive a\n * URL), so it falls back to a content-addressed name.\n */\nexport const contentAssetParam = (\n projectRoot: string,\n absPath: string\n): string => {\n const rel = relative(projectRoot, absPath);\n if (rel.startsWith(\"..\")) {\n return `_/${hashText(absPath)}${extname(absPath)}`;\n }\n return rel;\n};\n\n/** Percent-decode an image target; malformed escapes stay verbatim. */\nconst decodeTarget = (target: string): string => {\n try {\n return decodeURI(target);\n } catch {\n return target;\n }\n};\n\n/**\n * Whether a target is *shaped* like a colocated image reference: a relative\n * filesystem path with an image extension. Exported so link validation can\n * tell \"not a colocated candidate\" apart from \"a candidate that resolves\n * nowhere\" — the former falls through to the public-dir probe, the latter is\n * a broken reference beside the page source.\n */\nexport const isRelativeImageTarget = (target: string): boolean =>\n isRelativeTarget(target) &&\n IMAGE_EXTENSIONS.has(extname(decodeTarget(target)).toLowerCase());\n\n/**\n * Whether `abs` is a file whose trailing `segments` names match the on-disk\n * entries exactly. A bare `existsSync` accepts `./Diagram.PNG` for\n * `diagram.png` (or a directory named like an image) on a case-insensitive\n * filesystem — the reference then validates and serves locally but breaks on\n * the case-sensitive Linux build.\n */\nconst existsAsWritten = (abs: string, segments: number): boolean => {\n let current = abs;\n for (let i = 0; i < segments; i += 1) {\n const parent = dirname(current);\n let entries: string[];\n try {\n entries = readdirSync(parent);\n } catch {\n return false;\n }\n if (!entries.includes(basename(current))) {\n return false;\n }\n current = parent;\n }\n const stat = statSync(abs, { throwIfNoEntry: false });\n return stat !== undefined && stat.isFile();\n};\n\n/**\n * Resolve one image target against its page's directory. Returns the absolute\n * file path when the target is relative, is an image, and exists on disk —\n * anything else (remote URLs, `public/` absolutes, broken refs, code-block\n * examples that happen to look like paths) is null and left untouched. Shared\n * with link validation, so what counts as a colocated image is decided once.\n */\nexport const resolveRelativeImage = (\n sourceDir: string,\n target: string\n): string | null => {\n if (!isRelativeImageTarget(target)) {\n return null;\n }\n const decoded = decodeTarget(target);\n // Only the segments the author wrote are checked against on-disk names;\n // `sourceDir`'s own casing is the filesystem's business, not the target's.\n const segments = normalize(decoded)\n .split(\"/\")\n .filter((part) => part !== \"\" && part !== \"..\").length;\n const abs = resolve(sourceDir, decoded);\n return existsAsWritten(abs, segments) ? abs : null;\n};\n\n/** Encode an endpoint param for use in a Markdown URL, keeping `/` separators. */\nconst encodedParam = (param: string): string =>\n param.split(\"/\").map(encodeURIComponent).join(\"/\");\n\n/**\n * Rewrite one line's relative image targets. Matches run on a copy with inline\n * code blanked out (a `` `` `` span is syntax being *shown*, not\n * an image), while replacements splice into the real line by index — the mask\n * preserves length, so the indices line up.\n */\nconst rewriteLine = (\n line: string,\n toUrl: (target: string) => string | null\n): string => {\n const masked = line.replaceAll(INLINE_CODE, (span) =>\n \" \".repeat(span.length)\n );\n let out = \"\";\n let cursor = 0;\n for (const match of masked.matchAll(MD_IMAGE)) {\n const target = match.groups?.target ?? \"\";\n const url = toUrl(target);\n if (url === null) {\n continue;\n }\n const offset =\n (match.index ?? 0) +\n targetOffsetIn(match[0], target, match.groups?.title);\n out += line.slice(cursor, offset) + url;\n cursor = offset + target.length;\n }\n return out + line.slice(cursor);\n};\n\n/**\n * Rewrite a page's relative image references to their served\n * `/blume-assets/content/…` URLs (under `deployment.base` when set). Fenced\n * code blocks and inline code are skipped; only references whose file actually\n * exists next to the source are touched. `register` observes each rewritten\n * asset so a caller can accumulate the files the endpoint must serve.\n */\nexport const rewriteRelativeImages = (options: {\n source: string;\n sourcePath: string;\n projectRoot: string;\n deployBase?: string;\n register?: (param: string, absPath: string) => void;\n}): string => {\n const { source, sourcePath, projectRoot, deployBase, register } = options;\n const sourceDir = dirname(sourcePath);\n const prefix = `${normalizeBasePath(deployBase)}${CONTENT_ASSETS_PREFIX}`;\n const toUrl = (target: string): string | null => {\n const abs = resolveRelativeImage(sourceDir, target);\n if (abs === null) {\n return null;\n }\n const param = contentAssetParam(projectRoot, abs);\n register?.(param, abs);\n return `${prefix}/${encodedParam(param)}`;\n };\n\n let fence: FenceState = null;\n const lines = source.split(\"\\n\").map((line) => {\n const next = nextFenceState(line, fence);\n const inFence = fence !== null || next !== null;\n fence = next;\n return inFence ? line : rewriteLine(line, toUrl);\n });\n return lines.join(\"\\n\");\n};\n\n/**\n * Every colocated image the project's pages reference, keyed by endpoint param.\n * Serialized to `generated/content-assets.json`, which the\n * `/blume-assets/[...asset]` endpoint reads to serve the original files. Runs\n * the same rewrite the agent-Markdown builders apply — over the same\n * include-expanded text, so a partial's colocated images (rebased into the\n * including page by the expander) are served too — keeping the served set and\n * the rewritten URLs from drifting apart.\n */\nexport const collectContentAssets = async (project: {\n context: { root: string };\n manifest: { routes: { id: string; sourcePath?: string }[] };\n graph: { pages: PageRecord[] };\n sources?: ContentSource[];\n}): Promise<Record<string, string>> => {\n const pageById = new Map(project.graph.pages.map((page) => [page.id, page]));\n const files: Record<string, string> = {};\n await Promise.all(\n project.manifest.routes.map(async (route) => {\n if (!route.sourcePath) {\n return;\n }\n const page = pageById.get(route.id);\n let source: string;\n try {\n source = page\n ? await readExpandedEntryText(project, page)\n : await readFile(route.sourcePath, \"utf-8\");\n } catch {\n return;\n }\n rewriteRelativeImages({\n projectRoot: project.context.root,\n register: (param, abs) => {\n files[param] = abs;\n },\n source,\n sourcePath: route.sourcePath,\n });\n })\n );\n return files;\n};\n"
|
|
7
|
+
],
|
|
8
|
+
"mappings": "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",
|
|
9
|
+
"debugId": "2D2EF7E4F8223F9E64756E2164756E21",
|
|
10
|
+
"names": []
|
|
11
|
+
}
|