blume 1.4.2 → 1.5.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.
Files changed (227) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/dist/cli/index.js +2260 -1100
  3. package/dist/cli/index.js.map +123 -117
  4. package/dist/types/ai/component-markdown.d.ts +14 -4
  5. package/dist/types/core/base-path.d.ts +8 -0
  6. package/dist/types/core/config-input.d.ts +87 -27
  7. package/dist/types/core/config.d.ts +2 -1
  8. package/dist/types/core/data.d.ts +16 -1
  9. package/dist/types/core/diagnostics.d.ts +5 -1
  10. package/dist/types/core/i18n-ui.d.ts +12 -0
  11. package/dist/types/core/schema.d.ts +116 -15
  12. package/dist/types/core/sources/types.d.ts +11 -1
  13. package/dist/types/core/standard-schema.d.ts +7 -3
  14. package/dist/types/core/types.d.ts +43 -2
  15. package/dist/types/core/ui-packs/index.d.ts +9 -1
  16. package/dist/types/openapi/references.d.ts +14 -7
  17. package/dist/types/seo/x-handle.d.ts +3 -2
  18. package/docs/advanced/api-reference.mdx +8 -6
  19. package/docs/configuration/ai.mdx +26 -8
  20. package/docs/configuration/search.mdx +2 -0
  21. package/docs/configuration/seo.mdx +1 -1
  22. package/docs/content/i18n.mdx +1 -1
  23. package/docs/content/meta.mdx +2 -1
  24. package/docs/content/meta.ts +1 -0
  25. package/docs/content/navigation.mdx +35 -1
  26. package/docs/content/sources.mdx +1 -1
  27. package/docs/content/versioning.mdx +106 -0
  28. package/docs/reference/cli.mdx +1 -0
  29. package/docs/reference/frontmatter.mdx +3 -0
  30. package/package.json +13 -1
  31. package/skills/blume-migrate/SKILL.md +2 -2
  32. package/skills/blume-migrate/references/docusaurus.md +1 -1
  33. package/skills/blume-migrate/references/fumadocs.md +1 -1
  34. package/skills/blume-migrate/references/mintlify.md +1 -1
  35. package/src/ai/agent-readability.ts +40 -12
  36. package/src/ai/api-catalog.ts +2 -2
  37. package/src/ai/ask-context.ts +49 -12
  38. package/src/ai/ask.ts +10 -1
  39. package/src/ai/component-markdown.ts +80 -43
  40. package/src/ai/llms.ts +42 -17
  41. package/src/ai/mcp/data.ts +48 -12
  42. package/src/ai/mcp/discovery.ts +52 -16
  43. package/src/ai/mcp/server.ts +280 -125
  44. package/src/ai/mcp/tools.ts +3 -3
  45. package/src/ai/skills.ts +32 -9
  46. package/src/ai/tar.ts +29 -70
  47. package/src/ai/visibility.ts +2 -2
  48. package/src/astro/component-slots.ts +2 -0
  49. package/src/astro/examples.ts +13 -5
  50. package/src/astro/generate.ts +113 -63
  51. package/src/astro/integration.ts +13 -2
  52. package/src/astro/islands.ts +23 -12
  53. package/src/astro/templates.ts +185 -41
  54. package/src/audit/agent.ts +16 -31
  55. package/src/audit/checks/content.ts +26 -11
  56. package/src/audit/checks/dns-aid.ts +3 -0
  57. package/src/audit/checks/indexability.ts +24 -6
  58. package/src/audit/checks/llms.ts +9 -4
  59. package/src/audit/checks/network.ts +2 -0
  60. package/src/audit/checks/social.ts +18 -10
  61. package/src/audit/crawl.ts +78 -25
  62. package/src/audit/report.ts +20 -19
  63. package/src/audit/run.ts +15 -5
  64. package/src/audit/snapshot.ts +29 -6
  65. package/src/audit/types.ts +25 -3
  66. package/src/blume-modules.d.ts +5 -1
  67. package/src/cli/commands/audit.ts +21 -21
  68. package/src/cli/commands/build.ts +30 -16
  69. package/src/cli/commands/dev.ts +15 -15
  70. package/src/cli/commands/doctor.ts +2 -0
  71. package/src/cli/commands/eject.ts +4 -4
  72. package/src/cli/commands/eval.ts +24 -30
  73. package/src/cli/commands/init.ts +9 -9
  74. package/src/cli/commands/mcp-stdio.ts +3 -0
  75. package/src/cli/commands/translate.ts +14 -3
  76. package/src/cli/commands/version.ts +85 -0
  77. package/src/cli/dev-lock.ts +31 -10
  78. package/src/cli/eject-scripts.ts +17 -2
  79. package/src/cli/env.ts +13 -30
  80. package/src/cli/index.ts +2 -0
  81. package/src/cli/init/questions.ts +1 -1
  82. package/src/cli/init/scaffold.ts +41 -13
  83. package/src/cli/internal-error.ts +1 -0
  84. package/src/cli/report-format.ts +22 -0
  85. package/src/components/content/AccordionItem.astro +2 -9
  86. package/src/components/content/ColorItem.astro +5 -13
  87. package/src/components/content/Component.astro +12 -8
  88. package/src/components/content/Frame.astro +2 -12
  89. package/src/components/content/Prompt.astro +12 -31
  90. package/src/components/content/Tab.astro +2 -9
  91. package/src/components/content/Tooltip.astro +1 -9
  92. package/src/components/content/Update.astro +2 -9
  93. package/src/components/content/auto-type-table.ts +3 -0
  94. package/src/components/content/diff.ts +9 -5
  95. package/src/components/content/github-info.ts +2 -0
  96. package/src/components/content/inline-markdown.ts +28 -0
  97. package/src/components/copy-feedback.ts +96 -0
  98. package/src/components/islands/ask-ai.tsx +111 -34
  99. package/src/components/islands/hooks.ts +5 -1
  100. package/src/components/islands/webmcp.ts +49 -12
  101. package/src/components/layout/Header.astro +25 -1
  102. package/src/components/layout/NavSelector.astro +11 -2
  103. package/src/components/layout/NavTree.astro +4 -2
  104. package/src/components/layout/PageActions.astro +20 -32
  105. package/src/components/layout/PageLayout.astro +8 -28
  106. package/src/components/layout/RootLayout.astro +24 -48
  107. package/src/components/layout/Search.astro +133 -22
  108. package/src/components/layout/VersionBanner.astro +39 -0
  109. package/src/components/layout/analytics-client.ts +8 -5
  110. package/src/components/layout/drawer-inert.ts +31 -0
  111. package/src/components/layout/hydration-hint.ts +1 -1
  112. package/src/components/layout/nav-utils.ts +1 -4
  113. package/src/components/layout/overrides.ts +25 -12
  114. package/src/components/layout/search/algolia.ts +18 -5
  115. package/src/components/layout/search/endpoint.ts +3 -0
  116. package/src/components/layout/search/flexsearch.ts +23 -7
  117. package/src/components/layout/search/orama-cloud.ts +1 -1
  118. package/src/components/layout/search/orama.ts +4 -1
  119. package/src/components/layout/search/pagefind.ts +8 -5
  120. package/src/components/layout/search/types.ts +45 -1
  121. package/src/components/layout/search/typesense.ts +19 -3
  122. package/src/components/openapi/ApiOverview.astro +32 -6
  123. package/src/components/openapi/AsyncApiOperation.astro +237 -0
  124. package/src/components/openapi/Bindings.astro +89 -0
  125. package/src/components/openapi/MethodBadge.astro +3 -0
  126. package/src/components/openapi/Operation.astro +7 -2
  127. package/src/components/openapi/PanelTabs.astro +131 -0
  128. package/src/components/openapi/ParametersTable.astro +2 -0
  129. package/src/components/openapi/RequestPanel.astro +12 -119
  130. package/src/components/openapi/async-snippets.ts +174 -0
  131. package/src/components/openapi/async.ts +348 -0
  132. package/src/components/openapi/helpers.ts +52 -20
  133. package/src/components/openapi/panel.ts +11 -8
  134. package/src/components/openapi/security.ts +102 -29
  135. package/src/components/openapi/snippets.ts +11 -11
  136. package/src/components/raf-throttle.ts +21 -0
  137. package/src/components/slug.ts +14 -0
  138. package/src/core/base-path.ts +18 -1
  139. package/src/core/component-overrides.ts +28 -23
  140. package/src/core/config-input.ts +96 -27
  141. package/src/core/config.ts +20 -7
  142. package/src/core/content.ts +3 -1
  143. package/src/core/data.ts +16 -1
  144. package/src/core/define-components.ts +5 -0
  145. package/src/core/diagnostics.ts +46 -38
  146. package/src/core/frontmatter.ts +74 -4
  147. package/src/core/graph.ts +137 -53
  148. package/src/core/i18n-ui.ts +15 -0
  149. package/src/core/i18n.ts +16 -8
  150. package/src/core/load-module.ts +1 -0
  151. package/src/core/manifest.ts +92 -3
  152. package/src/core/meta.ts +44 -14
  153. package/src/core/nav-diagnostics.ts +3 -3
  154. package/src/core/navigation.ts +247 -67
  155. package/src/core/probe.ts +7 -19
  156. package/src/core/project-graph.ts +27 -4
  157. package/src/core/schema.ts +219 -67
  158. package/src/core/site-url.ts +27 -0
  159. package/src/core/sources/assets.ts +2 -0
  160. package/src/core/sources/cache.ts +16 -8
  161. package/src/core/sources/github-releases.ts +39 -11
  162. package/src/core/sources/mdx-remote.ts +4 -0
  163. package/src/core/sources/normalize.ts +93 -22
  164. package/src/core/sources/notion.ts +76 -22
  165. package/src/core/sources/portable-text.ts +48 -12
  166. package/src/core/sources/resolve.ts +1 -0
  167. package/src/core/sources/sanity.ts +68 -14
  168. package/src/core/sources/types.ts +17 -1
  169. package/src/core/sources/watch.ts +1 -1
  170. package/src/core/standard-schema.ts +9 -3
  171. package/src/core/text-width.ts +26 -0
  172. package/src/core/tsconfig-aliases.ts +9 -5
  173. package/src/core/types.ts +45 -2
  174. package/src/core/ui-packs/index.ts +9 -1
  175. package/src/core/version-cut.ts +301 -0
  176. package/src/core/version.ts +2 -0
  177. package/src/core/versions.ts +170 -0
  178. package/src/deploy/adapter-output.ts +5 -2
  179. package/src/deploy/cloudflare-negotiation.ts +40 -11
  180. package/src/deploy/robots.ts +2 -1
  181. package/src/deploy/rss.ts +2 -1
  182. package/src/deploy/sitemap.ts +89 -8
  183. package/src/deploy/vercel-negotiation.ts +11 -4
  184. package/src/eval/agents.ts +13 -10
  185. package/src/eval/report.ts +5 -18
  186. package/src/eval/run.ts +2 -2
  187. package/src/eval/schema.ts +1 -1
  188. package/src/markdown/base-links.ts +6 -6
  189. package/src/markdown/directives.ts +7 -1
  190. package/src/markdown/heading-anchors.ts +17 -6
  191. package/src/markdown/index.ts +73 -24
  192. package/src/markdown/inline-code.ts +14 -2
  193. package/src/markdown/language-icon.ts +6 -2
  194. package/src/markdown/mdast.ts +18 -4
  195. package/src/markdown/package-commands.ts +63 -58
  196. package/src/markdown/table-wrap.ts +4 -1
  197. package/src/markdown/twoslash.ts +2 -0
  198. package/src/og/card.ts +50 -33
  199. package/src/og/derive.ts +43 -27
  200. package/src/openapi/asyncapi.ts +366 -0
  201. package/src/openapi/model.ts +135 -66
  202. package/src/openapi/parse.ts +166 -33
  203. package/src/openapi/references.ts +47 -22
  204. package/src/openapi/render-mdx.ts +137 -59
  205. package/src/openapi/scalar.ts +8 -10
  206. package/src/openapi/source.ts +126 -29
  207. package/src/registry/eject.ts +7 -2
  208. package/src/search/documents.ts +103 -39
  209. package/src/search/facets.ts +7 -5
  210. package/src/search/orama-index.ts +117 -32
  211. package/src/search/popular.ts +10 -5
  212. package/src/search/providers.ts +2 -2
  213. package/src/search/sync/index.ts +2 -0
  214. package/src/search/sync/typesense.ts +4 -2
  215. package/src/seo/jsonld.ts +24 -6
  216. package/src/seo/x-handle.ts +8 -3
  217. package/src/theme/chrome-icons.ts +7 -2
  218. package/src/theme/fonts.ts +8 -4
  219. package/src/theme/icons.ts +4 -2
  220. package/src/theme/palette.ts +27 -15
  221. package/src/translate/ledger.ts +4 -2
  222. package/src/translate/meta.ts +15 -6
  223. package/src/translate/report.ts +10 -19
  224. package/src/translate/run.ts +29 -38
  225. package/src/translate/validate.ts +52 -17
  226. package/src/translate/work-list.ts +0 -0
  227. package/src/cli/coalesce.ts +0 -43
@@ -14,8 +14,12 @@ export interface McpRoute {
14
14
  facets?: Record<string, string>;
15
15
  indexable: boolean;
16
16
  lastModified: string | null;
17
+ /** Resolved locale code (the default locale when not under i18n). */
18
+ locale: string;
17
19
  route: string;
18
20
  title: string;
21
+ /** Docs version (`""` for the current docs). */
22
+ version: string;
19
23
  }
20
24
 
21
25
  /**
@@ -37,10 +41,20 @@ export interface McpData {
37
41
  * `search_docs` can match CJK/Thai content.
38
42
  */
39
43
  defaultLocale?: string;
44
+ /**
45
+ * Archived docs version ids, in configured order. Present only on a
46
+ * versioned site; its presence is what makes `search_docs`/`list_pages`
47
+ * default to the current docs.
48
+ */
49
+ archivedVersions?: string[];
40
50
  documents: OramaDoc[];
41
51
  instructions?: string;
42
52
  name: string;
43
53
  navigation: Navigation;
54
+ /** Per-locale trees for a locale-aware `get_navigation` (i18n sites only). */
55
+ navigationByLocale?: Record<string, Navigation>;
56
+ /** Per-archived-version trees, keyed by version id then locale code. */
57
+ navigationByVersion?: Record<string, Record<string, Navigation>>;
44
58
  pages: Record<string, string>;
45
59
  routes: McpRoute[];
46
60
  site: string | null;
@@ -79,28 +93,40 @@ export const buildMcpData = async (project: BlumeProject): Promise<McpData> => {
79
93
  }
80
94
  const page = pageById.get(route.id);
81
95
  const facets = page ? pageFacets(page, config) : undefined;
82
- routes.push({
96
+ const entry: McpRoute = {
83
97
  contentType: route.contentType,
84
98
  description: page?.description,
85
- ...(facets ? { facets } : {}),
86
99
  indexable: route.indexable,
87
100
  lastModified: route.lastModified ?? null,
101
+ locale: route.locale,
88
102
  route: route.path,
89
103
  title: route.title,
90
- });
104
+ version: route.version,
105
+ };
106
+ if (facets) {
107
+ entry.facets = facets;
108
+ }
109
+ routes.push(entry);
91
110
  }
92
111
 
93
- return {
112
+ const data: McpData = {
94
113
  base: normalizeBasePath(config.deployment.base),
95
114
  defaultLocale: config.i18n?.defaultLocale,
96
- documents: documents.map((doc) => ({
97
- content: doc.content,
98
- contentType: doc.contentType,
99
- description: doc.description,
100
- ...(doc.facets ? { facets: doc.facets } : {}),
101
- route: doc.route,
102
- title: doc.title,
103
- })),
115
+ documents: documents.map((doc) => {
116
+ const document: OramaDoc = {
117
+ content: doc.content,
118
+ contentType: doc.contentType,
119
+ description: doc.description,
120
+ locale: doc.locale,
121
+ route: doc.route,
122
+ title: doc.title,
123
+ version: doc.version,
124
+ };
125
+ if (doc.facets) {
126
+ document.facets = doc.facets;
127
+ }
128
+ return document;
129
+ }),
104
130
  instructions: config.ai.mcp.instructions,
105
131
  name: config.ai.mcp.name ?? config.title,
106
132
  navigation: graph.navigation,
@@ -109,4 +135,14 @@ export const buildMcpData = async (project: BlumeProject): Promise<McpData> => {
109
135
  site: config.deployment.site ?? null,
110
136
  version: manifest.blumeVersion,
111
137
  };
138
+ if (config.versions) {
139
+ data.archivedVersions = config.versions.archived.map(
140
+ (version) => version.id
141
+ );
142
+ data.navigationByVersion = graph.navigationByVersion;
143
+ }
144
+ if (config.i18n) {
145
+ data.navigationByLocale = graph.navigationByLocale;
146
+ }
147
+ return data;
112
148
  };
@@ -1,7 +1,8 @@
1
1
  import { withBasePath } from "../../core/base-path.ts";
2
- import { trimEnd } from "../../core/trim.ts";
3
- import { slugify } from "../../openapi/references.ts";
2
+ import { absoluteUrl, siteRoot } from "../../core/site-url.ts";
3
+ import { trimChar } from "../../core/trim.ts";
4
4
  import { MCP_TOOLS } from "./tools.ts";
5
+ import type { McpToolMeta } from "./tools.ts";
5
6
 
6
7
  /** Inputs needed to describe the MCP server in discovery documents. */
7
8
  export interface McpDiscoveryInput {
@@ -20,16 +21,14 @@ const serverUrl = (input: McpDiscoveryInput): string => {
20
21
  const path = withBasePath(input.base, input.route);
21
22
  // Concatenate rather than `new URL(path, site)` — a root-absolute path
22
23
  // would drop the base path of a subpath deployment (`acme.com/docs`).
23
- return input.site ? `${trimEnd(input.site, "/")}${path}` : path;
24
+ return input.site ? absoluteUrl(input.site, path) : path;
24
25
  };
25
26
 
26
27
  /**
27
28
  * The `/.well-known/mcp.json` discovery document: the minimal pointer agents use
28
29
  * to find the server and its transport.
29
30
  */
30
- export const buildMcpDiscovery = (
31
- input: McpDiscoveryInput
32
- ): Record<string, unknown> => ({
31
+ export const buildMcpDiscovery = (input: McpDiscoveryInput) => ({
33
32
  servers: [
34
33
  {
35
34
  name: input.name,
@@ -49,10 +48,29 @@ const CARD_TEXT_MAX = 100;
49
48
  const truncate = (text: string): string =>
50
49
  text.length > CARD_TEXT_MAX ? `${text.slice(0, CARD_TEXT_MAX - 1)}…` : text;
51
50
 
51
+ // The server-card schema constrains `name` to `namespace/server` in ASCII
52
+ // (`^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$`), so the display name cannot reuse the
53
+ // route slugifier, which keeps Unicode letters. Decompose (NFKD) and drop
54
+ // combining marks first so an accented name transliterates (`Café` → `cafe`)
55
+ // instead of losing the letter.
56
+ const NON_ASCII_SLUG = /[^a-z0-9]+/gu;
57
+ const COMBINING_MARKS = /\p{M}+/gu;
58
+
59
+ const asciiSlugify = (text: string): string =>
60
+ trimChar(
61
+ text
62
+ .normalize("NFKD")
63
+ .replace(COMBINING_MARKS, "")
64
+ .toLowerCase()
65
+ .replace(NON_ASCII_SLUG, "-"),
66
+ "-"
67
+ );
68
+
52
69
  /**
53
70
  * The card's identity in the schema's reverse-DNS `namespace/server` form:
54
71
  * the site hostname reversed (`useblume.dev` → `dev.useblume`), or
55
- * `localhost` when no site is configured, plus the slugged display name.
72
+ * `localhost` when no site is configured, plus the slugged display name (an
73
+ * entirely non-ASCII name falls back to `docs`).
56
74
  */
57
75
  const reverseDnsName = (input: McpDiscoveryInput): string => {
58
76
  let namespace = "localhost";
@@ -66,7 +84,7 @@ const reverseDnsName = (input: McpDiscoveryInput): string => {
66
84
  // Not a parsable URL; the local namespace is honest enough.
67
85
  }
68
86
  }
69
- return `${namespace}/${slugify(input.name) || "docs"}`;
87
+ return `${namespace}/${asciiSlugify(input.name) || "docs"}`;
70
88
  };
71
89
 
72
90
  const HTTP_URL = /^https?:\/\//u;
@@ -83,20 +101,32 @@ const HTTP_URL = /^https?:\/\//u;
83
101
  * excludes primitives for. Full input schemas are served live via
84
102
  * `tools/list`.
85
103
  */
86
- export const buildMcpServerCard = (
87
- input: McpDiscoveryInput
88
- ): Record<string, unknown> => {
104
+ export interface McpServerCard {
105
+ $schema: string;
106
+ capabilities: { tools: { listChanged: boolean } };
107
+ description: string;
108
+ name: string;
109
+ /** Absolute endpoints only — present when a `site` is configured. */
110
+ remotes?: { type: string; url: string }[];
111
+ serverInfo: { name: string; version: string };
112
+ title: string;
113
+ tools: McpToolMeta[];
114
+ transport: string;
115
+ transports: { endpoint: string; type: string }[];
116
+ url: string;
117
+ version: string;
118
+ websiteUrl?: string;
119
+ }
120
+
121
+ export const buildMcpServerCard = (input: McpDiscoveryInput): McpServerCard => {
89
122
  const url = serverUrl(input);
90
- return {
123
+ const card: McpServerCard = {
91
124
  $schema: SERVER_CARD_SCHEMA,
92
125
  capabilities: { tools: { listChanged: false } },
93
126
  description: truncate(
94
127
  `Model Context Protocol server for the ${input.name} documentation.`
95
128
  ),
96
129
  name: reverseDnsName(input),
97
- ...(HTTP_URL.test(url)
98
- ? { remotes: [{ type: "streamable-http", url }] }
99
- : {}),
100
130
  serverInfo: { name: input.name, version: input.version },
101
131
  title: truncate(input.name),
102
132
  tools: MCP_TOOLS.map((tool) => ({
@@ -109,6 +139,12 @@ export const buildMcpServerCard = (
109
139
  transports: [{ endpoint: url, type: "streamable-http" }],
110
140
  url,
111
141
  version: input.version,
112
- ...(input.site ? { websiteUrl: trimEnd(input.site, "/") } : {}),
113
142
  };
143
+ if (HTTP_URL.test(url)) {
144
+ card.remotes = [{ type: "streamable-http", url }];
145
+ }
146
+ if (input.site) {
147
+ card.websiteUrl = siteRoot(input.site);
148
+ }
149
+ return card;
114
150
  };