blume 0.1.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +2123 -555
- package/dist/cli/index.js.map +39 -25
- package/dist/types/core/data.d.ts +16 -0
- package/dist/types/core/define-components.d.ts +9 -2
- package/dist/types/core/diagnostics.d.ts +5 -0
- package/dist/types/core/schema.d.ts +136 -508
- package/dist/types/core/types.d.ts +2 -2
- package/docs/02-deployment.mdx +21 -2
- package/docs/advanced/changelog.mdx +28 -1
- package/docs/advanced/custom-pages.mdx +63 -2
- package/docs/configuration/ai.mdx +20 -3
- package/docs/configuration/customization.mdx +103 -5
- package/docs/configuration/index.mdx +25 -11
- package/docs/configuration/search.mdx +13 -1
- package/docs/configuration/seo.mdx +5 -0
- package/docs/configuration/theming.mdx +51 -0
- package/docs/content/components.mdx +18 -0
- package/docs/content/islands.mdx +73 -0
- package/docs/content/navigation.mdx +25 -0
- package/docs/content/sources.mdx +43 -0
- package/docs/content/syntax.mdx +1 -1
- package/docs/index.mdx +3 -12
- package/docs/reference/cli.mdx +49 -1
- package/docs/reference/frontmatter.mdx +9 -1
- package/package.json +3 -1
- package/src/ai/ask-context.ts +131 -0
- package/src/ai/ask-data.ts +25 -0
- package/src/astro/component-slots.ts +165 -0
- package/src/astro/generate.ts +162 -26
- package/src/astro/integration.ts +59 -0
- package/src/astro/pages.ts +5 -12
- package/src/astro/templates.ts +102 -45
- package/src/blume-modules.d.ts +25 -0
- package/src/cli/commands/build.ts +186 -1
- package/src/cli/commands/check.ts +62 -0
- package/src/cli/commands/dev.ts +21 -1
- package/src/cli/commands/doctor.ts +23 -6
- package/src/cli/commands/init.ts +163 -15
- package/src/cli/commands/validate.ts +16 -2
- package/src/cli/env.ts +84 -0
- package/src/cli/index.ts +20 -0
- package/src/cli/internal-error.ts +63 -0
- package/src/cli/log.ts +30 -1
- package/src/cli/prepare.ts +22 -3
- package/src/cli/required-secrets.ts +44 -0
- package/src/components/BlumePage.astro +107 -0
- package/src/components/content/CodeBlock.astro +7 -2
- package/src/components/index.ts +3 -3
- package/src/components/islands/ask-ai.tsx +15 -1
- package/src/components/islands/hooks.ts +188 -0
- package/src/components/layout/Empty.astro +6 -0
- package/src/components/layout/Header.astro +24 -39
- package/src/components/layout/Logo.astro +50 -0
- package/src/components/layout/NavSelector.astro +75 -0
- package/src/components/layout/PageLayout.astro +38 -2
- package/src/components/layout/RootLayout.astro +70 -4
- package/src/components/layout/hydration-hint.ts +30 -0
- package/src/components/layout/overrides.ts +6 -4
- package/src/components/props.ts +68 -0
- package/src/core/builtin-tags.ts +39 -0
- package/src/core/component-diagnostics.ts +44 -0
- package/src/core/component-overrides.ts +478 -0
- package/src/core/config.ts +8 -0
- package/src/core/data.ts +14 -0
- package/src/core/define-components.ts +9 -2
- package/src/core/diagnostics.ts +90 -1
- package/src/core/graph.ts +7 -0
- package/src/core/nav-diagnostics.ts +205 -0
- package/src/core/project-graph.ts +40 -1
- package/src/core/schema.ts +54 -96
- package/src/core/sources/github-releases.ts +200 -0
- package/src/core/sources/normalize.ts +51 -0
- package/src/core/sources/resolve.ts +16 -0
- package/src/core/types.ts +2 -2
- package/src/deploy/redirects.ts +43 -0
- package/src/markdown/index.ts +24 -0
- package/src/migrate/mintlify/config.ts +1 -176
- package/src/migrate/starlight/config.ts +0 -4
- package/src/og/card.ts +163 -38
- package/src/registry/eject.ts +39 -9
- package/src/registry/registry.ts +166 -0
- package/src/runtime/index.ts +61 -0
- package/src/vite-env.d.ts +14 -0
- package/docs/changelog/v0-1-0.mdx +0 -12
- package/docs/changelog/v0-2-0.mdx +0 -16
package/src/registry/eject.ts
CHANGED
|
@@ -3,8 +3,10 @@ import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
|
3
3
|
|
|
4
4
|
import { join, relative } from "pathe";
|
|
5
5
|
|
|
6
|
+
import { buildAskData } from "../ai/ask-data.ts";
|
|
6
7
|
import { resolveAskBackend } from "../ai/ask.ts";
|
|
7
8
|
import { buildRawMarkdown } from "../ai/markdown.ts";
|
|
9
|
+
import { planComponentSlots } from "../astro/component-slots.ts";
|
|
8
10
|
import { discoverExamples } from "../astro/examples.ts";
|
|
9
11
|
import {
|
|
10
12
|
buildRuntimeData,
|
|
@@ -32,9 +34,9 @@ import {
|
|
|
32
34
|
runtimeTsconfigTemplate,
|
|
33
35
|
searchClientTemplate,
|
|
34
36
|
searchEndpointTemplate,
|
|
35
|
-
userComponentsTemplate,
|
|
36
37
|
} from "../astro/templates.ts";
|
|
37
38
|
import { scanProject } from "../core/project-graph.ts";
|
|
39
|
+
import type { BlumeProject } from "../core/project-graph.ts";
|
|
38
40
|
import type { ProjectContext } from "../core/types.ts";
|
|
39
41
|
import { buildRssFeeds, renderRssFeed } from "../deploy/rss.ts";
|
|
40
42
|
import { buildReferenceFiles, hasReferences } from "../openapi/scalar.ts";
|
|
@@ -46,6 +48,35 @@ import { twoslashCss } from "../theme/twoslash.ts";
|
|
|
46
48
|
|
|
47
49
|
const POSIX = (path: string): string => path.split("\\").join("/");
|
|
48
50
|
|
|
51
|
+
/**
|
|
52
|
+
* The Ask AI endpoint plus, unless the backend runs its own retrieval (Inkeep),
|
|
53
|
+
* its grounding snapshot. Empty when Ask AI is disabled.
|
|
54
|
+
*/
|
|
55
|
+
const askFiles = async (
|
|
56
|
+
project: BlumeProject,
|
|
57
|
+
srcDir: string,
|
|
58
|
+
genDir: string
|
|
59
|
+
): Promise<{ content: string; path: string }[]> => {
|
|
60
|
+
const { ask } = project.config.ai;
|
|
61
|
+
if (!ask?.enabled) {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
const grounded = ask.provider !== "inkeep";
|
|
65
|
+
const files = [
|
|
66
|
+
{
|
|
67
|
+
content: askEndpointTemplate(resolveAskBackend(ask), grounded),
|
|
68
|
+
path: join(srcDir, "pages", "api", "ask.ts"),
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
if (grounded) {
|
|
72
|
+
files.push({
|
|
73
|
+
content: `${JSON.stringify(await buildAskData(project))}\n`,
|
|
74
|
+
path: join(genDir, "ask-data.json"),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return files;
|
|
78
|
+
};
|
|
79
|
+
|
|
49
80
|
/**
|
|
50
81
|
* Promote the generated runtime into the project as an owned Astro app. After
|
|
51
82
|
* eject the project has a normal `astro.config.mjs` and `src/`, the `blume` CLI
|
|
@@ -146,11 +177,15 @@ export const eject = async (root: string): Promise<string[]> => {
|
|
|
146
177
|
exportEpub,
|
|
147
178
|
exportPdf,
|
|
148
179
|
mathEnabled: config.markdown.math,
|
|
180
|
+
needsReact,
|
|
149
181
|
}),
|
|
150
182
|
path: join(srcDir, "pages", "[...slug].astro"),
|
|
151
183
|
},
|
|
152
184
|
{
|
|
153
|
-
|
|
185
|
+
// Eject keeps the portable re-export form (relative import to the user's
|
|
186
|
+
// components file); hydration/island wrappers would need machine-specific
|
|
187
|
+
// absolute paths, so the ejected app owns and wires those itself.
|
|
188
|
+
content: planComponentSlots(componentsImport, null).module,
|
|
154
189
|
path: join(genDir, "components.ts"),
|
|
155
190
|
},
|
|
156
191
|
// Island/example maps the catch-all imports; written even when empty so the
|
|
@@ -192,17 +227,12 @@ export const eject = async (root: string): Promise<string[]> => {
|
|
|
192
227
|
];
|
|
193
228
|
|
|
194
229
|
if (askEnabled) {
|
|
195
|
-
files.push(
|
|
196
|
-
content: askEndpointTemplate(resolveAskBackend(config.ai.ask)),
|
|
197
|
-
path: join(srcDir, "pages", "api", "ask.ts"),
|
|
198
|
-
});
|
|
230
|
+
files.push(...(await askFiles(project, srcDir, genDir)));
|
|
199
231
|
}
|
|
200
232
|
|
|
201
233
|
if (config.seo.og.enabled) {
|
|
202
234
|
files.push({
|
|
203
|
-
content: ogEndpointTemplate(
|
|
204
|
-
customOgRoutes(pages, config.title, config.description)
|
|
205
|
-
),
|
|
235
|
+
content: ogEndpointTemplate(customOgRoutes(pages, config.title)),
|
|
206
236
|
path: join(srcDir, "pages", "og", "[...slug].png.ts"),
|
|
207
237
|
});
|
|
208
238
|
}
|
package/src/registry/registry.ts
CHANGED
|
@@ -62,6 +62,165 @@ const layoutComponent = (config: {
|
|
|
62
62
|
};
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
+
/**
|
|
66
|
+
* A built-in MDX content component offered as editable source. Like
|
|
67
|
+
* {@link layoutComponent}, but registered under the `mdx` map (the tag you write
|
|
68
|
+
* in `.mdx`) rather than a `layout` slot.
|
|
69
|
+
*/
|
|
70
|
+
const contentComponent = (config: {
|
|
71
|
+
name: string;
|
|
72
|
+
description: string;
|
|
73
|
+
/** Source basename under `src/components/content`. */
|
|
74
|
+
file: string;
|
|
75
|
+
/** MDX tag / component name, also the import name in the post-install hint. */
|
|
76
|
+
tag: string;
|
|
77
|
+
}): RegistryItem => {
|
|
78
|
+
const target = `components/blume/${config.file}`;
|
|
79
|
+
return {
|
|
80
|
+
description: config.description,
|
|
81
|
+
files: [
|
|
82
|
+
{
|
|
83
|
+
rewrite: true,
|
|
84
|
+
source: `components/content/${config.file}`,
|
|
85
|
+
target,
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
name: config.name,
|
|
89
|
+
postInstall: [
|
|
90
|
+
"Register it in components.ts:",
|
|
91
|
+
' import { defineComponents } from "blume";',
|
|
92
|
+
` import ${config.tag} from "./${target}";`,
|
|
93
|
+
"",
|
|
94
|
+
` export default defineComponents({ mdx: { ${config.tag} } });`,
|
|
95
|
+
"",
|
|
96
|
+
"It imports the rest from `blume/*`, so it matches the built-in until you edit it.",
|
|
97
|
+
],
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/** Every user-facing content component, by `blume add` name → source basename. */
|
|
102
|
+
const CONTENT_COMPONENTS: {
|
|
103
|
+
name: string;
|
|
104
|
+
description: string;
|
|
105
|
+
file: string;
|
|
106
|
+
tag: string;
|
|
107
|
+
}[] = [
|
|
108
|
+
{
|
|
109
|
+
description: "Aside for notes, tips, and warnings.",
|
|
110
|
+
file: "Callout.astro",
|
|
111
|
+
name: "callout",
|
|
112
|
+
tag: "Callout",
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
description: "A linkable card with icon, title, and body.",
|
|
116
|
+
file: "Card.astro",
|
|
117
|
+
name: "card",
|
|
118
|
+
tag: "Card",
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
description: "A responsive grid of cards.",
|
|
122
|
+
file: "CardGroup.astro",
|
|
123
|
+
name: "card-group",
|
|
124
|
+
tag: "CardGroup",
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
description: "Tabbed code blocks for multiple languages.",
|
|
128
|
+
file: "CodeGroup.astro",
|
|
129
|
+
name: "code-group",
|
|
130
|
+
tag: "CodeGroup",
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
description: "A small status/label badge.",
|
|
134
|
+
file: "Badge.astro",
|
|
135
|
+
name: "badge",
|
|
136
|
+
tag: "Badge",
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
description: "A numbered list of steps.",
|
|
140
|
+
file: "Steps.astro",
|
|
141
|
+
name: "steps",
|
|
142
|
+
tag: "Steps",
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
description: "A single step within Steps.",
|
|
146
|
+
file: "Step.astro",
|
|
147
|
+
name: "step",
|
|
148
|
+
tag: "Step",
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
description: "A tabbed content panel.",
|
|
152
|
+
file: "Tabs.astro",
|
|
153
|
+
name: "tabs",
|
|
154
|
+
tag: "Tabs",
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
description: "A single tab within Tabs.",
|
|
158
|
+
file: "Tab.astro",
|
|
159
|
+
name: "tab",
|
|
160
|
+
tag: "Tab",
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
description: "A collapsible accordion group.",
|
|
164
|
+
file: "Accordion.astro",
|
|
165
|
+
name: "accordion",
|
|
166
|
+
tag: "Accordion",
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
description: "A single item within an Accordion.",
|
|
170
|
+
file: "AccordionItem.astro",
|
|
171
|
+
name: "accordion-item",
|
|
172
|
+
tag: "AccordionItem",
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
description: "A multi-column layout.",
|
|
176
|
+
file: "Columns.astro",
|
|
177
|
+
name: "columns",
|
|
178
|
+
tag: "Columns",
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
description: "A single column within Columns.",
|
|
182
|
+
file: "Column.astro",
|
|
183
|
+
name: "column",
|
|
184
|
+
tag: "Column",
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
description: "A bordered frame around an image or embed.",
|
|
188
|
+
file: "Frame.astro",
|
|
189
|
+
name: "frame",
|
|
190
|
+
tag: "Frame",
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
description: "An inline expand/collapse disclosure.",
|
|
194
|
+
file: "Expandable.astro",
|
|
195
|
+
name: "expandable",
|
|
196
|
+
tag: "Expandable",
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
description: "A titled content panel.",
|
|
200
|
+
file: "Panel.astro",
|
|
201
|
+
name: "panel",
|
|
202
|
+
tag: "Panel",
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
description: "A hover tooltip.",
|
|
206
|
+
file: "Tooltip.astro",
|
|
207
|
+
name: "tooltip",
|
|
208
|
+
tag: "Tooltip",
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
description: "A compact linkable tile.",
|
|
212
|
+
file: "Tile.astro",
|
|
213
|
+
name: "tile",
|
|
214
|
+
tag: "Tile",
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
description: "A styled prompt / terminal block.",
|
|
218
|
+
file: "Prompt.astro",
|
|
219
|
+
name: "prompt",
|
|
220
|
+
tag: "Prompt",
|
|
221
|
+
},
|
|
222
|
+
];
|
|
223
|
+
|
|
65
224
|
/** The built-in, Blume-owned source registry. */
|
|
66
225
|
export const registry: RegistryItem[] = [
|
|
67
226
|
layoutComponent({
|
|
@@ -94,6 +253,13 @@ export const registry: RegistryItem[] = [
|
|
|
94
253
|
name: "pagination",
|
|
95
254
|
slot: "Pagination",
|
|
96
255
|
}),
|
|
256
|
+
layoutComponent({
|
|
257
|
+
description: 'The "Was this page helpful?" feedback rating.',
|
|
258
|
+
file: "PageFeedback.astro",
|
|
259
|
+
name: "feedback",
|
|
260
|
+
slot: "Feedback",
|
|
261
|
+
}),
|
|
262
|
+
...CONTENT_COMPONENTS.map(contentComponent),
|
|
97
263
|
];
|
|
98
264
|
|
|
99
265
|
export const findItem = (name: string): RegistryItem | undefined =>
|
package/src/runtime/index.ts
CHANGED
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
* (config, navigation, page collections) without reaching into generated
|
|
6
6
|
* runtime internals. The surface grows with the customization milestone.
|
|
7
7
|
*/
|
|
8
|
+
import type { BlumeData, BlumeRoute } from "../core/data.ts";
|
|
9
|
+
|
|
10
|
+
export type {
|
|
11
|
+
BlumeData,
|
|
12
|
+
BlumeDataConfig,
|
|
13
|
+
BlumeFeed,
|
|
14
|
+
BlumeRoute,
|
|
15
|
+
} from "../core/data.ts";
|
|
8
16
|
export type {
|
|
9
17
|
Heading,
|
|
10
18
|
NavNode,
|
|
@@ -12,3 +20,56 @@ export type {
|
|
|
12
20
|
NavTab,
|
|
13
21
|
PageRecord,
|
|
14
22
|
} from "../core/types.ts";
|
|
23
|
+
|
|
24
|
+
/** Query for {@link getBlumeCollection}. */
|
|
25
|
+
export interface BlumeCollectionQuery {
|
|
26
|
+
/** Astro collection to read from. Defaults to `"docs"`. */
|
|
27
|
+
collection?: string;
|
|
28
|
+
/** Include drafts, hidden pages, and translation fallbacks. Default `false`. */
|
|
29
|
+
includeHidden?: boolean;
|
|
30
|
+
/** Restrict to a locale code (matches `route.locale`). */
|
|
31
|
+
locale?: string;
|
|
32
|
+
/** Restrict to routes whose path starts with this prefix, e.g. `"/blog"`. */
|
|
33
|
+
prefix?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Select content routes from the `blume:data` snapshot — for building custom
|
|
38
|
+
* index pages, listings, or feeds without touching generated internals. Pass the
|
|
39
|
+
* imported `data` and an optional query; results are sorted by path.
|
|
40
|
+
*
|
|
41
|
+
* ```astro
|
|
42
|
+
* ---
|
|
43
|
+
* import data from "blume:data";
|
|
44
|
+
* import { getBlumeCollection } from "blume/runtime";
|
|
45
|
+
* const posts = getBlumeCollection(data, { prefix: "/blog" });
|
|
46
|
+
* ---
|
|
47
|
+
* <ul>{posts.map((p) => <li><a href={p.path}>{p.title}</a></li>)}</ul>
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export const getBlumeCollection = (
|
|
51
|
+
data: BlumeData,
|
|
52
|
+
query: BlumeCollectionQuery = {}
|
|
53
|
+
): BlumeRoute[] => {
|
|
54
|
+
const collection = query.collection ?? "docs";
|
|
55
|
+
return data.routes
|
|
56
|
+
.filter((route) => {
|
|
57
|
+
if (route.collection !== collection) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (query.locale && route.locale !== query.locale) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
if (query.prefix && !route.path.startsWith(query.prefix)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
if (
|
|
67
|
+
!query.includeHidden &&
|
|
68
|
+
(route.draft || route.hidden || route.fallback)
|
|
69
|
+
) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
})
|
|
74
|
+
.toSorted((a, b) => a.path.localeCompare(b.path));
|
|
75
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Ambient types for the Vite `import.meta.env` fields Blume's client islands read
|
|
2
|
+
// (`.astro` files aren't typechecked, so only real `.ts`/`.tsx` sources need this).
|
|
3
|
+
interface ImportMetaEnv {
|
|
4
|
+
/** Deployment base path, always with a trailing slash (e.g. `/` or `/docs/`). */
|
|
5
|
+
readonly BASE_URL: string;
|
|
6
|
+
readonly DEV: boolean;
|
|
7
|
+
readonly MODE: string;
|
|
8
|
+
readonly PROD: boolean;
|
|
9
|
+
readonly SSR: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface ImportMeta {
|
|
13
|
+
readonly env: ImportMetaEnv;
|
|
14
|
+
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: v0.1.0
|
|
3
|
-
type: changelog
|
|
4
|
-
date: 2026-06-01
|
|
5
|
-
changelog:
|
|
6
|
-
version: 0.1.0
|
|
7
|
-
category: Release
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
The first public release of Blume — a markdown-first docs framework on Astro and
|
|
11
|
-
Vite. Drop in Markdown or MDX, run `blume dev`, and ship a production-grade docs
|
|
12
|
-
site with search, theming, and AI-ready output.
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: v0.2.0
|
|
3
|
-
type: changelog
|
|
4
|
-
date: 2026-06-24
|
|
5
|
-
changelog:
|
|
6
|
-
version: 0.2.0
|
|
7
|
-
category: Features
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
A big batch of built-in components landed: **columns**, **frames**, **trees**,
|
|
11
|
-
**tooltips**, **code groups**, **panels**, **tiles**, and **fields**. Code groups
|
|
12
|
-
now render as proper language tabs, and the changelog gets this timeline.
|
|
13
|
-
|
|
14
|
-
- New `Accordion` / `AccordionItem`, `Expandable`, `Tooltip`, `Frame`, `Color`
|
|
15
|
-
- `CodeGroup` tabs with flush code blocks
|
|
16
|
-
- Redesigned `Prompt` with a copy-to-clipboard button
|