blume 1.5.2 → 1.6.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 (194) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/dist/cli/index.js +3639 -1377
  3. package/dist/cli/index.js.map +103 -91
  4. package/dist/types/ai/component-markdown.d.ts +79 -0
  5. package/dist/types/components/layout/nav-utils.d.ts +60 -0
  6. package/dist/types/core/base-path.d.ts +9 -0
  7. package/dist/types/core/config-input.d.ts +206 -4
  8. package/dist/types/core/config.d.ts +6 -4
  9. package/dist/types/core/data.d.ts +23 -1
  10. package/dist/types/core/github.d.ts +35 -0
  11. package/dist/types/core/i18n-ui.d.ts +8 -0
  12. package/dist/types/core/navigation.d.ts +69 -0
  13. package/dist/types/core/schema.d.ts +117 -1
  14. package/dist/types/core/sources/types.d.ts +31 -6
  15. package/dist/types/core/types.d.ts +23 -2
  16. package/dist/types/markdown/features.d.ts +21 -0
  17. package/dist/types/openapi/references.d.ts +21 -1
  18. package/dist/types/seo/jsonld.d.ts +105 -0
  19. package/dist/types/theme/fonts.d.ts +34 -4
  20. package/docs/_snippets/include-demo.mdx +7 -0
  21. package/docs/advanced/api-reference.mdx +3 -3
  22. package/docs/advanced/custom-pages.mdx +1 -1
  23. package/docs/advanced/graphql.mdx +84 -0
  24. package/docs/advanced/meta.ts +8 -1
  25. package/docs/configuration/ai.mdx +21 -3
  26. package/docs/configuration/index.mdx +24 -0
  27. package/docs/configuration/search.mdx +13 -1
  28. package/docs/configuration/seo.mdx +27 -0
  29. package/docs/configuration/theming.mdx +17 -0
  30. package/docs/content/components.mdx +7 -0
  31. package/docs/content/includes.mdx +68 -0
  32. package/docs/content/meta.ts +1 -0
  33. package/docs/content/navigation.mdx +25 -0
  34. package/docs/content/sources.mdx +42 -1
  35. package/docs/content/syntax.mdx +69 -1
  36. package/docs/content/versioning.mdx +15 -9
  37. package/docs/reference/cli.mdx +2 -1
  38. package/package.json +23 -14
  39. package/skills/blume-migrate/SKILL.md +16 -7
  40. package/skills/blume-migrate/references/docusaurus.md +5 -3
  41. package/skills/blume-migrate/references/fumadocs.md +10 -2
  42. package/skills/blume-migrate/references/mintlify.md +3 -2
  43. package/skills/blume-migrate/references/nextra.md +2 -2
  44. package/skills/blume-migrate/references/starlight.md +1 -1
  45. package/src/ai/agent-readability.ts +2 -1
  46. package/src/ai/ask-data.ts +2 -1
  47. package/src/ai/component-markdown.ts +199 -36
  48. package/src/ai/llms.ts +93 -6
  49. package/src/ai/markdown.ts +2 -2
  50. package/src/ai/mcp/discovery.ts +10 -2
  51. package/src/ai/mcp/server.ts +74 -2
  52. package/src/astro/generate.ts +183 -116
  53. package/src/astro/include-hmr.ts +81 -0
  54. package/src/astro/include-refresh.ts +0 -0
  55. package/src/astro/index.ts +3 -5
  56. package/src/astro/templates.ts +125 -76
  57. package/src/cli/commands/build.ts +84 -15
  58. package/src/cli/init/questions.ts +1 -0
  59. package/src/cli/init/scaffold.ts +27 -4
  60. package/src/components/colors.ts +142 -0
  61. package/src/components/content/Badge.astro +5 -12
  62. package/src/components/content/Callout.astro +19 -36
  63. package/src/components/content/Card.astro +15 -21
  64. package/src/components/content/Component.astro +10 -1
  65. package/src/components/content/GithubInfo.astro +28 -9
  66. package/src/components/content/Tabs.astro +27 -5
  67. package/src/components/content/github-info.ts +20 -5
  68. package/src/components/dropdown-dismiss.ts +122 -0
  69. package/src/components/layout/Fonts.astro +15 -8
  70. package/src/components/layout/Header.astro +44 -0
  71. package/src/components/layout/LanguageSwitcher.astro +9 -1
  72. package/src/components/layout/NavSelector.astro +12 -3
  73. package/src/components/layout/NavTree.astro +6 -18
  74. package/src/components/layout/PageActions.astro +29 -8
  75. package/src/components/layout/PageLayout.astro +10 -1
  76. package/src/components/layout/ReferenceLayout.astro +6 -1
  77. package/src/components/layout/RootLayout.astro +46 -15
  78. package/src/components/layout/Search.astro +36 -4
  79. package/src/components/layout/TableOfContents.astro +8 -2
  80. package/src/components/layout/head-scripts.ts +53 -1
  81. package/src/components/openapi/ApiOverview.astro +13 -3
  82. package/src/components/openapi/AsyncApiOperation.astro +7 -14
  83. package/src/components/openapi/GraphqlChip.astro +33 -0
  84. package/src/components/openapi/GraphqlFieldsTable.astro +111 -0
  85. package/src/components/openapi/GraphqlOperation.astro +186 -0
  86. package/src/components/openapi/GraphqlType.astro +154 -0
  87. package/src/components/openapi/MethodBadge.astro +3 -14
  88. package/src/components/openapi/Operation.astro +12 -5
  89. package/src/components/openapi/OperationPanel.astro +43 -0
  90. package/src/components/openapi/RequestPanel.astro +5 -10
  91. package/src/components/openapi/Responses.astro +1 -16
  92. package/src/components/openapi/graphql-helpers.ts +466 -0
  93. package/src/components/openapi/playground-client.ts +15 -0
  94. package/src/components/openapi/sample-panels.ts +45 -0
  95. package/src/components/openapi/snippets.ts +13 -35
  96. package/src/core/base-path.ts +11 -0
  97. package/src/core/config-input.ts +209 -2
  98. package/src/core/config.ts +6 -4
  99. package/src/core/content-assets.ts +15 -4
  100. package/src/core/data.ts +18 -2
  101. package/src/core/diagnostics.ts +8 -0
  102. package/src/core/frontmatter.ts +20 -8
  103. package/src/core/github.ts +71 -0
  104. package/src/core/graph.ts +22 -8
  105. package/src/core/heading-markers.ts +96 -0
  106. package/src/core/i18n-ui.ts +11 -0
  107. package/src/core/includes.ts +632 -0
  108. package/src/core/last-modified.ts +36 -11
  109. package/src/core/links.ts +79 -13
  110. package/src/core/meta.ts +2 -1
  111. package/src/core/nav-diagnostics.ts +11 -2
  112. package/src/core/navigation.ts +27 -6
  113. package/src/core/project-graph.ts +61 -9
  114. package/src/core/schema.ts +226 -35
  115. package/src/core/server-features.ts +5 -9
  116. package/src/core/sources/github-releases.ts +2 -2
  117. package/src/core/sources/normalize.ts +502 -115
  118. package/src/core/sources/notion.ts +43 -8
  119. package/src/core/sources/obsidian.ts +1038 -0
  120. package/src/core/sources/read.ts +36 -1
  121. package/src/core/sources/resolve.ts +34 -1
  122. package/src/core/sources/types.ts +28 -6
  123. package/src/core/sources/watch.ts +12 -8
  124. package/src/core/tsconfig-aliases.ts +48 -35
  125. package/src/core/types.ts +25 -2
  126. package/src/core/ui-packs/ar.ts +1 -0
  127. package/src/core/ui-packs/bg.ts +2 -0
  128. package/src/core/ui-packs/bn.ts +1 -0
  129. package/src/core/ui-packs/ca.ts +2 -0
  130. package/src/core/ui-packs/cs.ts +1 -0
  131. package/src/core/ui-packs/da.ts +1 -0
  132. package/src/core/ui-packs/de.ts +2 -0
  133. package/src/core/ui-packs/el.ts +2 -0
  134. package/src/core/ui-packs/es.ts +2 -0
  135. package/src/core/ui-packs/fa.ts +1 -0
  136. package/src/core/ui-packs/fi.ts +1 -0
  137. package/src/core/ui-packs/fr.ts +2 -0
  138. package/src/core/ui-packs/he.ts +1 -0
  139. package/src/core/ui-packs/hi.ts +1 -0
  140. package/src/core/ui-packs/hr.ts +2 -0
  141. package/src/core/ui-packs/hu.ts +2 -0
  142. package/src/core/ui-packs/id.ts +2 -0
  143. package/src/core/ui-packs/it.ts +1 -0
  144. package/src/core/ui-packs/ja.ts +2 -0
  145. package/src/core/ui-packs/ko.ts +2 -0
  146. package/src/core/ui-packs/nl.ts +2 -0
  147. package/src/core/ui-packs/no.ts +2 -0
  148. package/src/core/ui-packs/pl.ts +2 -0
  149. package/src/core/ui-packs/pt-br.ts +2 -0
  150. package/src/core/ui-packs/pt.ts +2 -0
  151. package/src/core/ui-packs/ro.ts +2 -0
  152. package/src/core/ui-packs/ru.ts +2 -0
  153. package/src/core/ui-packs/sk.ts +1 -0
  154. package/src/core/ui-packs/sr.ts +1 -0
  155. package/src/core/ui-packs/sv.ts +2 -0
  156. package/src/core/ui-packs/th.ts +1 -0
  157. package/src/core/ui-packs/tr.ts +2 -0
  158. package/src/core/ui-packs/uk.ts +2 -0
  159. package/src/core/ui-packs/vi.ts +1 -0
  160. package/src/core/ui-packs/zh-tw.ts +1 -0
  161. package/src/core/ui-packs/zh.ts +1 -0
  162. package/src/core/version-cut.ts +21 -3
  163. package/src/core/yaml.ts +26 -0
  164. package/src/deploy/function-bundle.ts +251 -0
  165. package/src/eval/schema.ts +3 -1
  166. package/src/markdown/code-title.ts +22 -16
  167. package/src/markdown/features.ts +21 -0
  168. package/src/markdown/fence-meta.ts +50 -0
  169. package/src/markdown/heading-anchors.ts +198 -37
  170. package/src/markdown/include.ts +247 -0
  171. package/src/markdown/index.ts +43 -34
  172. package/src/markdown/language-icon.ts +2 -2
  173. package/src/markdown/mdast.ts +7 -3
  174. package/src/markdown/ts2js.ts +264 -0
  175. package/src/openapi/asyncapi.ts +4 -1
  176. package/src/openapi/graphql-build.ts +293 -0
  177. package/src/openapi/graphql.ts +212 -0
  178. package/src/openapi/model.ts +38 -5
  179. package/src/openapi/parse.ts +34 -0
  180. package/src/openapi/proxy.ts +30 -5
  181. package/src/openapi/references.ts +89 -13
  182. package/src/openapi/render-mdx.ts +48 -8
  183. package/src/openapi/scalar.ts +5 -12
  184. package/src/openapi/source.ts +91 -23
  185. package/src/registry/eject.ts +11 -0
  186. package/src/search/documents.ts +229 -37
  187. package/src/search/orama-index.ts +9 -5
  188. package/src/seo/jsonld.ts +293 -51
  189. package/src/theme/code-block-padding.ts +16 -0
  190. package/src/theme/entry.ts +65 -11
  191. package/src/theme/fonts.ts +189 -16
  192. package/src/translate/prompts.ts +2 -0
  193. package/src/translate/run.ts +7 -0
  194. package/src/translate/work-list.ts +0 -0
@@ -0,0 +1,69 @@
1
+ import type { FolderMeta, SidebarDisplay, SidebarItemConfig } from "./schema.ts";
2
+ import type { Diagnostic, FeaturedLink, HeaderAction, Navigation, NavSelector, NavTab, PageRecord } from "./types.ts";
3
+ /**
4
+ * Whether `route` is the section root `base` or nested beneath it. Requires a
5
+ * path boundary, so `/api-reference` is not under `/api`. The root `/` spans
6
+ * every route.
7
+ */
8
+ export declare const isUnderPath: (route: string, base: string) => boolean;
9
+ /**
10
+ * Whether `tab` is the root tab of the tree rooted at `root` — the tab that
11
+ * spans the whole sidebar rather than one section. Tab paths and the root
12
+ * normally share one path space, so the root tab sits at `root` exactly (`/`,
13
+ * `/en`, `/docs`); in an archived version tree the root is versionized
14
+ * (`/v1.0`, `/docs/v1.0`) while tab paths stay in current-docs space, so the
15
+ * root tab is any tab the whole root sits under. The one definition shared by
16
+ * sidebar scoping, tab-section hoisting, and the header's current-tab state —
17
+ * consumers that disagree on which tab is the root tab prune an archived
18
+ * sidebar or highlight the wrong tab over it.
19
+ */
20
+ export declare const isRootTab: (tab: NavTab, root: string) => boolean;
21
+ /** Build the complete navigation model from pages, meta, and config. */
22
+ export declare const buildNavigation: (pages: PageRecord[], options: {
23
+ /** Plain links in the header, left of the icon buttons. */
24
+ actions?: HeaderAction[];
25
+ /** Site-wide route mount point (`""` or `/seg`); applied to config paths. */
26
+ basePath?: string;
27
+ /** The single primary call to action in the header. */
28
+ cta?: HeaderAction | null;
29
+ folderMeta: Map<string, FolderMeta>;
30
+ /** Global display mode for every sidebar group (default `flat`). */
31
+ display?: SidebarDisplay;
32
+ featured?: FeaturedLink[];
33
+ selectors?: NavSelector[];
34
+ tabs?: NavTab[];
35
+ sidebar?: SidebarItemConfig[];
36
+ /**
37
+ * Folder-meta lookup prefix (`""` for the default locale of the current
38
+ * version): the version dir and/or locale dir hoisted in front of the
39
+ * group path, e.g. `fr`, `v1.0`, or `v1.0/fr`.
40
+ */
41
+ metaPrefix?: string;
42
+ /**
43
+ * Prefix for shared `meta.$.*` lookups — the version dir inside a
44
+ * snapshot (`v1.0`), since shared meta is locale-agnostic but still
45
+ * version-specific. `""` for the current version.
46
+ */
47
+ sharedMetaPrefix?: string;
48
+ /**
49
+ * Resolve explicit-sidebar references against each page's locale-agnostic
50
+ * `translationKey` instead of its localized `route`. Used under i18n so a
51
+ * single authored sidebar maps onto every locale's pages.
52
+ */
53
+ refByLogical?: boolean;
54
+ /** Shared `meta.$.*` meta, keyed by locale-stripped dir path. */
55
+ sharedFolderMeta?: Map<string, FolderMeta>;
56
+ /**
57
+ * The tree's root route before `basePath` (`"/"`, or the locale prefix
58
+ * under i18n, e.g. `/fr` — tab paths arrive already localized). The tab
59
+ * pointing here spans the whole tree, so it is excluded from tab-section
60
+ * scoping.
61
+ */
62
+ localizedRoot?: string;
63
+ /**
64
+ * Sink for diagnostics produced while building the tree (duplicate sidebar
65
+ * `order` values, index-page title/folder-meta-title mismatches). Pushed
66
+ * into in place; omit to discard.
67
+ */
68
+ diagnostics?: Diagnostic[];
69
+ }) => Navigation;
@@ -218,6 +218,11 @@ declare const contentSourceSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
218
218
  publishedValue: z.ZodOptional<z.ZodString>;
219
219
  type: z.ZodLiteral<"notion">;
220
220
  }, z.core.$strip>, z.ZodObject<{
221
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
222
+ prefix: z.ZodOptional<z.ZodString>;
223
+ type: z.ZodLiteral<"obsidian">;
224
+ vault: z.ZodString;
225
+ }, z.core.$strict>, z.ZodObject<{
221
226
  source: z.ZodCustom<ContentSource, ContentSource>;
222
227
  type: z.ZodLiteral<"custom">;
223
228
  }, z.core.$strip>], "type">;
@@ -280,14 +285,17 @@ declare const aiConfigSchema: z.ZodObject<{
280
285
  }, z.core.$strict>>>;
281
286
  }, z.core.$strict>>;
282
287
  llmsTxt: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
288
+ details: z.ZodOptional<z.ZodString>;
283
289
  enabled: z.ZodDefault<z.ZodBoolean>;
284
290
  openapi: z.ZodDefault<z.ZodBoolean>;
285
291
  }, z.core.$strict>]>>, z.ZodTransform<{
286
292
  enabled: boolean;
287
293
  openapi: boolean;
294
+ details?: string | undefined;
288
295
  }, boolean | {
289
296
  enabled: boolean;
290
297
  openapi: boolean;
298
+ details?: string | undefined;
291
299
  }>>;
292
300
  markdownComponents: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodCustom<ComponentMarkdown, ComponentMarkdown>>>;
293
301
  mcp: z.ZodPrefault<z.ZodObject<{
@@ -472,6 +480,22 @@ declare const openapiSourceSchema: z.ZodObject<{
472
480
  spec: z.ZodString;
473
481
  }, z.core.$strict>;
474
482
  export type OpenApiSource = z.input<typeof openapiSourceSchema>;
483
+ /**
484
+ * A single GraphQL schema rendered by the reference. `spec` is a local path or
485
+ * an `http(s)` URL to SDL text or an introspection JSON result; `endpoint` is
486
+ * the live GraphQL API URL the playground and code samples target (a schema,
487
+ * unlike an OpenAPI document, names no server).
488
+ */
489
+ declare const graphqlSourceSchema: z.ZodObject<{
490
+ includeInLlms: z.ZodDefault<z.ZodBoolean>;
491
+ includeInSearch: z.ZodDefault<z.ZodBoolean>;
492
+ label: z.ZodOptional<z.ZodString>;
493
+ noindex: z.ZodDefault<z.ZodBoolean>;
494
+ route: z.ZodOptional<z.ZodString>;
495
+ spec: z.ZodString;
496
+ endpoint: z.ZodOptional<z.ZodString>;
497
+ }, z.core.$strict>;
498
+ export type GraphqlSource = z.input<typeof graphqlSourceSchema>;
475
499
  export declare const blumeConfigSchema: z.ZodObject<{
476
500
  ai: z.ZodPrefault<z.ZodObject<{
477
501
  ask: z.ZodOptional<z.ZodObject<{
@@ -499,14 +523,17 @@ export declare const blumeConfigSchema: z.ZodObject<{
499
523
  }, z.core.$strict>>>;
500
524
  }, z.core.$strict>>;
501
525
  llmsTxt: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
526
+ details: z.ZodOptional<z.ZodString>;
502
527
  enabled: z.ZodDefault<z.ZodBoolean>;
503
528
  openapi: z.ZodDefault<z.ZodBoolean>;
504
529
  }, z.core.$strict>]>>, z.ZodTransform<{
505
530
  enabled: boolean;
506
531
  openapi: boolean;
532
+ details?: string | undefined;
507
533
  }, boolean | {
508
534
  enabled: boolean;
509
535
  openapi: boolean;
536
+ details?: string | undefined;
510
537
  }>>;
511
538
  markdownComponents: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodCustom<ComponentMarkdown, ComponentMarkdown>>>;
512
539
  mcp: z.ZodPrefault<z.ZodObject<{
@@ -650,6 +677,11 @@ export declare const blumeConfigSchema: z.ZodObject<{
650
677
  publishedValue: z.ZodOptional<z.ZodString>;
651
678
  type: z.ZodLiteral<"notion">;
652
679
  }, z.core.$strip>, z.ZodObject<{
680
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString>>;
681
+ prefix: z.ZodOptional<z.ZodString>;
682
+ type: z.ZodLiteral<"obsidian">;
683
+ vault: z.ZodString;
684
+ }, z.core.$strict>, z.ZodObject<{
653
685
  source: z.ZodCustom<ContentSource, ContentSource>;
654
686
  type: z.ZodLiteral<"custom">;
655
687
  }, z.core.$strip>], "type">>>;
@@ -734,11 +766,39 @@ export declare const blumeConfigSchema: z.ZodObject<{
734
766
  extend: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodCustom<StandardSchema<unknown, unknown>, StandardSchema<unknown, unknown>>>>;
735
767
  }, z.core.$strict>>;
736
768
  github: z.ZodOptional<z.ZodObject<{
769
+ api: z.ZodOptional<z.ZodPipe<z.ZodURL, z.ZodTransform<string, string>>>;
737
770
  branch: z.ZodDefault<z.ZodString>;
738
771
  dir: z.ZodOptional<z.ZodString>;
772
+ host: z.ZodDefault<z.ZodPipe<z.ZodURL, z.ZodTransform<string, string>>>;
739
773
  owner: z.ZodString;
740
774
  repo: z.ZodString;
741
775
  }, z.core.$strict>>;
776
+ graphql: z.ZodPrefault<z.ZodObject<{
777
+ enabled: z.ZodDefault<z.ZodBoolean>;
778
+ route: z.ZodDefault<z.ZodString>;
779
+ codeSamples: z.ZodDefault<z.ZodArray<z.ZodString>>;
780
+ playground: z.ZodPipe<z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
781
+ enabled: z.ZodDefault<z.ZodBoolean>;
782
+ proxy: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>;
783
+ }, z.core.$strict>]>>, z.ZodTransform<{
784
+ enabled: boolean;
785
+ proxy: string | boolean;
786
+ }, boolean | {
787
+ enabled: boolean;
788
+ proxy: string | boolean;
789
+ }>>;
790
+ spec: z.ZodOptional<z.ZodString>;
791
+ endpoint: z.ZodOptional<z.ZodString>;
792
+ sources: z.ZodDefault<z.ZodArray<z.ZodObject<{
793
+ includeInLlms: z.ZodDefault<z.ZodBoolean>;
794
+ includeInSearch: z.ZodDefault<z.ZodBoolean>;
795
+ label: z.ZodOptional<z.ZodString>;
796
+ noindex: z.ZodDefault<z.ZodBoolean>;
797
+ route: z.ZodOptional<z.ZodString>;
798
+ spec: z.ZodString;
799
+ endpoint: z.ZodOptional<z.ZodString>;
800
+ }, z.core.$strict>>>;
801
+ }, z.core.$strict>>;
742
802
  i18n: z.ZodOptional<z.ZodObject<{
743
803
  defaultLocale: z.ZodDefault<z.ZodString>;
744
804
  fallbackLocale: z.ZodOptional<z.ZodNullable<z.ZodString>>;
@@ -798,12 +858,20 @@ export declare const blumeConfigSchema: z.ZodObject<{
798
858
  imageZoom: z.ZodDefault<z.ZodBoolean>;
799
859
  }, z.core.$strict>>;
800
860
  navigation: z.ZodPrefault<z.ZodObject<{
861
+ actions: z.ZodDefault<z.ZodArray<z.ZodObject<{
862
+ href: z.ZodString;
863
+ label: z.ZodString;
864
+ }, z.core.$strict>>>;
865
+ cta: z.ZodOptional<z.ZodObject<{
866
+ href: z.ZodString;
867
+ label: z.ZodString;
868
+ }, z.core.$strict>>;
801
869
  featured: z.ZodDefault<z.ZodArray<z.ZodObject<{
802
870
  href: z.ZodString;
803
871
  icon: z.ZodOptional<z.ZodString>;
804
872
  label: z.ZodString;
805
873
  }, z.core.$strict>>>;
806
- repo: z.ZodDefault<z.ZodBoolean>;
874
+ repo: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodURL]>>;
807
875
  selectors: z.ZodDefault<z.ZodArray<z.ZodObject<{
808
876
  items: z.ZodDefault<z.ZodArray<z.ZodObject<{
809
877
  description: z.ZodOptional<z.ZodString>;
@@ -894,6 +962,7 @@ export declare const blumeConfigSchema: z.ZodObject<{
894
962
  searchApiKey: z.ZodString;
895
963
  }, z.core.$strict>>;
896
964
  indexing: z.ZodPrefault<z.ZodObject<{
965
+ includeCodeBlocks: z.ZodDefault<z.ZodBoolean>;
897
966
  includeHiddenPages: z.ZodDefault<z.ZodBoolean>;
898
967
  }, z.core.$strict>>;
899
968
  mixedbread: z.ZodOptional<z.ZodObject<{
@@ -978,6 +1047,22 @@ export declare const blumeConfigSchema: z.ZodObject<{
978
1047
  site: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodLiteral<false>]>>;
979
1048
  titles: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
980
1049
  }, z.core.$strict>>;
1050
+ organization: z.ZodOptional<z.ZodObject<{
1051
+ address: z.ZodOptional<z.ZodObject<{
1052
+ addressCountry: z.ZodOptional<z.ZodString>;
1053
+ addressLocality: z.ZodOptional<z.ZodString>;
1054
+ addressRegion: z.ZodOptional<z.ZodString>;
1055
+ postalCode: z.ZodOptional<z.ZodString>;
1056
+ streetAddress: z.ZodOptional<z.ZodString>;
1057
+ }, z.core.$strict>>;
1058
+ contactType: z.ZodDefault<z.ZodString>;
1059
+ email: z.ZodOptional<z.ZodEmail>;
1060
+ logo: z.ZodOptional<z.ZodString>;
1061
+ name: z.ZodOptional<z.ZodString>;
1062
+ sameAs: z.ZodDefault<z.ZodArray<z.ZodURL>>;
1063
+ telephone: z.ZodOptional<z.ZodString>;
1064
+ url: z.ZodOptional<z.ZodURL>;
1065
+ }, z.core.$strict>>;
981
1066
  robots: z.ZodDefault<z.ZodBoolean>;
982
1067
  rss: z.ZodPrefault<z.ZodObject<{
983
1068
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -985,6 +1070,34 @@ export declare const blumeConfigSchema: z.ZodObject<{
985
1070
  types: z.ZodDefault<z.ZodArray<z.ZodString>>;
986
1071
  }, z.core.$strict>>;
987
1072
  sitemap: z.ZodDefault<z.ZodBoolean>;
1073
+ software: z.ZodPipe<z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
1074
+ applicationCategory: z.ZodDefault<z.ZodString>;
1075
+ description: z.ZodOptional<z.ZodString>;
1076
+ license: z.ZodOptional<z.ZodString>;
1077
+ name: z.ZodOptional<z.ZodString>;
1078
+ operatingSystem: z.ZodOptional<z.ZodString>;
1079
+ price: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>;
1080
+ priceCurrency: z.ZodDefault<z.ZodString>;
1081
+ sameAs: z.ZodDefault<z.ZodArray<z.ZodURL>>;
1082
+ }, z.core.$strict>]>>, z.ZodTransform<{
1083
+ applicationCategory: string;
1084
+ priceCurrency: string;
1085
+ sameAs: string[];
1086
+ description?: string | undefined;
1087
+ license?: string | undefined;
1088
+ name?: string | undefined;
1089
+ operatingSystem?: string | undefined;
1090
+ price?: string | number | undefined;
1091
+ } | undefined, boolean | {
1092
+ applicationCategory: string;
1093
+ priceCurrency: string;
1094
+ sameAs: string[];
1095
+ description?: string | undefined;
1096
+ license?: string | undefined;
1097
+ name?: string | undefined;
1098
+ operatingSystem?: string | undefined;
1099
+ price?: string | number | undefined;
1100
+ } | undefined>>;
988
1101
  structuredData: z.ZodDefault<z.ZodBoolean>;
989
1102
  x: z.ZodDefault<z.ZodObject<{
990
1103
  creator: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string | undefined, string>>>;
@@ -1037,6 +1150,7 @@ export declare const blumeConfigSchema: z.ZodObject<{
1037
1150
  bunny: "bunny";
1038
1151
  fontshare: "fontshare";
1039
1152
  }>>;
1153
+ subsets: z.ZodOptional<z.ZodArray<z.ZodString>>;
1040
1154
  weights: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
1041
1155
  }, z.core.$strict>, z.ZodObject<{
1042
1156
  fallback: z.ZodOptional<z.ZodEnum<{
@@ -1068,6 +1182,7 @@ export declare const blumeConfigSchema: z.ZodObject<{
1068
1182
  bunny: "bunny";
1069
1183
  fontshare: "fontshare";
1070
1184
  }>>;
1185
+ subsets: z.ZodOptional<z.ZodArray<z.ZodString>>;
1071
1186
  weights: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
1072
1187
  }, z.core.$strict>, z.ZodObject<{
1073
1188
  fallback: z.ZodOptional<z.ZodEnum<{
@@ -1099,6 +1214,7 @@ export declare const blumeConfigSchema: z.ZodObject<{
1099
1214
  bunny: "bunny";
1100
1215
  fontshare: "fontshare";
1101
1216
  }>>;
1217
+ subsets: z.ZodOptional<z.ZodArray<z.ZodString>>;
1102
1218
  weights: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodNumber, z.ZodString]>>>;
1103
1219
  }, z.core.$strict>, z.ZodObject<{
1104
1220
  fallback: z.ZodOptional<z.ZodEnum<{
@@ -24,9 +24,15 @@ export interface SourceEntry {
24
24
  */
25
25
  raw?: string;
26
26
  /**
27
- * Absolute filesystem path when the entry originates from disk. Populated by
28
- * the filesystem adapter only; powers git last-modified and edit URLs and the
29
- * `sourcePath` back-compat window. Omitted by remote/CMS adapters.
27
+ * Absolute filesystem path when the entry originates from disk. Set by any
28
+ * local-file adapter the filesystem source, and staged local sources such
29
+ * as Obsidian, whose bodies are rewritten but whose notes are still real
30
+ * files. It gives diagnostics a path the author recognizes and lets relative
31
+ * image checks resolve next to the file. Omitted by remote/CMS adapters.
32
+ *
33
+ * It does *not* imply the entry renders through the docs glob collection —
34
+ * read `source.staged` for that — and git last-modified additionally needs
35
+ * the owning source to expose a `contentRoot` to bound the log's pathspec.
30
36
  */
31
37
  sourcePath?: string;
32
38
  /** Optional provenance for "edit this page". */
@@ -35,6 +41,22 @@ export interface SourceEntry {
35
41
  lastModified?: string;
36
42
  /** Content hash for cache invalidation / HMR; adapter-computed when cheap. */
37
43
  hash?: string;
44
+ /**
45
+ * The body with `<include>` statements expanded, set by the scan's expansion
46
+ * pass (filesystem entries whose body contains a statement). `normalizeEntry`
47
+ * extracts headings/links/components from this text so a partial's content
48
+ * counts toward the including page, with `origins` mapping each expanded
49
+ * line back to the file and raw line it came from for diagnostics.
50
+ */
51
+ expanded?: {
52
+ text: string;
53
+ origins: {
54
+ file: string;
55
+ line: number;
56
+ }[];
57
+ /** Absolute paths of every file included, transitively. */
58
+ includes: string[];
59
+ };
38
60
  }
39
61
  /** The result of a single `ContentSource.load()` call. */
40
62
  export interface SourceLoadResult {
@@ -92,9 +114,12 @@ export interface ContentSource {
92
114
  /** Optional route prefix; the source's routes namespace under `/<prefix>/`. */
93
115
  readonly prefix?: string;
94
116
  /**
95
- * Resolved on-disk root, set by filesystem-backed sources only. Drives
96
- * folder-meta discovery (scan under this root) and the docs-collection base;
97
- * omitted by remote/CMS/staged sources that have no local tree.
117
+ * Resolved on-disk root, set by sources whose entries live on disk. For
118
+ * filesystem sources it drives folder-meta discovery (scan under this root)
119
+ * and the docs-collection base; for staged local sources (an Obsidian
120
+ * vault) it only bounds the git last-modified pathspec — folder-meta
121
+ * discovery is guarded on `staged`. Omitted by remote/CMS sources that have
122
+ * no local tree.
98
123
  */
99
124
  readonly contentRoot?: string;
100
125
  /** Pull every entry. Called once per scan. */
@@ -55,6 +55,10 @@ export interface PageLink {
55
55
  line: number;
56
56
  /** 1-based column of the target within the line. */
57
57
  column: number;
58
+ /** Absolute path of the file the link was written in, when that isn't the
59
+ * page's own source — a link inside an included partial. Diagnostics point
60
+ * here so authors fix the partial, not the page that spliced it. */
61
+ file?: string;
58
62
  }
59
63
  /**
60
64
  * Resolved project paths. Computed once per CLI invocation and threaded
@@ -95,7 +99,7 @@ export interface PageRecord {
95
99
  name: string;
96
100
  ref: string;
97
101
  };
98
- /** Absolute source path. Populated by the filesystem adapter only (back-compat). */
102
+ /** Absolute source path. Populated by any local-file adapter (back-compat). */
99
103
  sourcePath?: string;
100
104
  /**
101
105
  * Renderable body captured at scan time. Set for staged (non-filesystem)
@@ -165,6 +169,11 @@ export interface PageRecord {
165
169
  */
166
170
  custom?: Record<string, unknown>;
167
171
  headings: Heading[];
172
+ /**
173
+ * Raw HTML element ids (`<a id="…">`) outside headings, deduplicated —
174
+ * fragment-link targets `blume validate` accepts alongside heading slugs.
175
+ */
176
+ anchors: string[];
168
177
  /** Whether the file is `.md`/`.mdx`. */
169
178
  format: "md" | "mdx";
170
179
  /** Internal/asset links discovered in the page (for validation). */
@@ -173,6 +182,9 @@ export interface PageRecord {
173
182
  componentsUsed?: string[];
174
183
  /** Resolved "last updated" ISO date, when the feature is enabled. */
175
184
  lastModified?: string;
185
+ /** Absolute paths of files this page `<include>`s, transitively. Drives the
186
+ * dev-server invalidation edge from a partial to the pages that splice it. */
187
+ includes?: string[];
176
188
  }
177
189
  /** A node in the generated navigation tree. */
178
190
  export type NavNode = {
@@ -249,6 +261,11 @@ export interface FeaturedLink {
249
261
  href: string;
250
262
  icon?: string;
251
263
  }
264
+ /** A plain header link, or the header's single call to action. */
265
+ export interface HeaderAction {
266
+ href: string;
267
+ label: string;
268
+ }
252
269
  /** The complete navigation model derived from the content graph. */
253
270
  export interface Navigation {
254
271
  tabs: NavTab[];
@@ -264,6 +281,10 @@ export interface Navigation {
264
281
  * graphs; treat as `/`.
265
282
  */
266
283
  root?: string;
284
+ /** Plain links in the header, left of the icon buttons. */
285
+ actions?: HeaderAction[];
286
+ /** The single primary call to action in the header. */
287
+ cta?: HeaderAction | null;
267
288
  /** Pinned links shown above the sidebar sections, unscoped by tab. */
268
289
  featured: FeaturedLink[];
269
290
  /** Repo URL for the header link, or null when hidden (`navigation.repo`). */
@@ -321,7 +342,7 @@ export interface RouteManifestEntry {
321
342
  /** Astro collection-relative entry id, passed to `getEntry`. */
322
343
  entryId: string;
323
344
  path: string;
324
- /** Absolute source path; populated for filesystem entries only (back-compat). */
345
+ /** Absolute source path; populated for local-file entries only (back-compat). */
325
346
  sourcePath?: string;
326
347
  /** Adapter-supplied "edit this page" URL (non-filesystem sources). */
327
348
  editUrl?: string;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Sätteri's feature set for plain `.md` pages. Shared by the renderer and the
3
+ * search extractor so the index reads the same grammar the page renders.
4
+ */
5
+ export declare const MARKDOWN_FEATURES: {
6
+ subscript: true;
7
+ superscript: true;
8
+ };
9
+ /**
10
+ * The `.mdx` feature set: Markdown's plus `:::` directives (→ `<Callout>`) and
11
+ * block-only math — `singleDollarTextMath: false` keeps a bare `$` (currency,
12
+ * shell, code) as literal text and only parses `$$…$$`.
13
+ */
14
+ export declare const MDX_FEATURES: {
15
+ directive: true;
16
+ math: {
17
+ singleDollarTextMath: false;
18
+ };
19
+ subscript: true;
20
+ superscript: true;
21
+ };
@@ -7,7 +7,7 @@ export { normalizeRoute } from "../core/base-path.ts";
7
7
  * data module all share one source of truth. Kept free of any Astro/template
8
8
  * imports so `core` can depend on it without a cycle.
9
9
  */
10
- export type ReferenceKind = "openapi" | "asyncapi";
10
+ export type ReferenceKind = "openapi" | "asyncapi" | "graphql";
11
11
  /** Who renders a reference: Blume's own UI, or the embedded Scalar SPA. */
12
12
  export type ReferenceRenderer = "blume" | "scalar";
13
13
  /** Per-block display options for the Blume renderer. */
@@ -49,6 +49,11 @@ export interface ReferenceSource {
49
49
  noindex: boolean;
50
50
  /** Local path or `http(s)` URL, verbatim from config. */
51
51
  spec: string;
52
+ /**
53
+ * URL of the live GraphQL endpoint the playground and code samples target
54
+ * (GraphQL only — a schema, unlike an OpenAPI document, names no server).
55
+ */
56
+ endpoint?: string;
52
57
  /** Per-block Scalar theme name override, if any (Scalar renderer only). */
53
58
  theme?: string;
54
59
  /**
@@ -90,3 +95,18 @@ export declare const referenceRoutes: (config: ResolvedConfig) => string[];
90
95
  export declare const blumeReferences: (config: ResolvedConfig) => ReferenceSource[];
91
96
  /** Whether any reference is Scalar-rendered (gates the `@scalar/astro` dep + pages). */
92
97
  export declare const hasScalarReferences: (config: ResolvedConfig) => boolean;
98
+ /**
99
+ * The reference kinds whose enabled, Blume-rendered playground opted into the
100
+ * built-in CORS proxy with `proxy: true`. A proxy URL string points at an
101
+ * external service, and `false` sends requests directly — neither routes
102
+ * through the endpoint. The generator's per-spec allowlist diagnostics key on
103
+ * this, so it shares one definition with {@link needsPlaygroundProxy}.
104
+ */
105
+ export declare const builtinProxyKinds: (config: ResolvedConfig) => ReferenceKind[];
106
+ /**
107
+ * Whether the built-in playground CORS proxy endpoint (`/_api-proxy`) must be
108
+ * generated: some enabled Blume-rendered block's playground opted into it with
109
+ * `proxy: true`. Shared by the server feature gate and the generator so the
110
+ * two can never disagree.
111
+ */
112
+ export declare const needsPlaygroundProxy: (config: ResolvedConfig) => boolean;
@@ -0,0 +1,105 @@
1
+ import type { Crumb } from "../components/layout/nav-utils.ts";
2
+ /** A date-ish value carried through frontmatter (string, YAML Date, or unset). */
3
+ type DateInput = string | Date | null;
4
+ /** A schema.org `PostalAddress`; every part optional. */
5
+ export interface PostalAddressIdentity {
6
+ addressCountry?: string;
7
+ addressLocality?: string;
8
+ addressRegion?: string;
9
+ postalCode?: string;
10
+ streetAddress?: string;
11
+ }
12
+ /**
13
+ * `seo.organization`: the organization behind the site, emitted on every page
14
+ * as an `Organization` node the WebSite and article nodes cite as publisher.
15
+ */
16
+ export interface OrganizationIdentity {
17
+ address?: PostalAddressIdentity;
18
+ /** `ContactPoint.contactType`; only emitted with an email or telephone. */
19
+ contactType: string;
20
+ email?: string;
21
+ /** Absolute URL or root-relative path (absolutized like page URLs). */
22
+ logo?: string;
23
+ /** Defaults to the site title. */
24
+ name?: string;
25
+ /** Profile URLs (GitHub, X, LinkedIn, …) that identify the organization. */
26
+ sameAs: string[];
27
+ telephone?: string;
28
+ /** Defaults to the site origin. */
29
+ url?: string;
30
+ }
31
+ /**
32
+ * `seo.software`: the product the site documents, emitted on the homepage as
33
+ * a `SoftwareApplication` node — the identity type agents use to tell what a
34
+ * docs site is about.
35
+ */
36
+ export interface SoftwareIdentity {
37
+ applicationCategory: string;
38
+ /** Defaults to the site description. */
39
+ description?: string;
40
+ /** License URL or SPDX identifier. */
41
+ license?: string;
42
+ /** Defaults to the site title. */
43
+ name?: string;
44
+ operatingSystem?: string;
45
+ /** Emitted as an `Offer` when set; `0` marks the software free. */
46
+ price?: number | string;
47
+ priceCurrency: string;
48
+ /** Package registry, repository, and profile URLs for the product. */
49
+ sameAs: string[];
50
+ }
51
+ /** The site-level identity nodes, from `seo.organization`/`seo.software`. */
52
+ export interface StructuredDataIdentity {
53
+ organization?: OrganizationIdentity;
54
+ software?: SoftwareIdentity;
55
+ }
56
+ /** Inputs for a page's JSON-LD, all known at render time in RootLayout. */
57
+ export interface StructuredDataInput {
58
+ siteName: string;
59
+ /** Absolute site origin, or null when `deployment.site` is unset. */
60
+ siteUrl: string | null;
61
+ title: string;
62
+ description?: string;
63
+ /** Page route, e.g. `/blog/post`. */
64
+ route: string;
65
+ /** Deployment base (`import.meta.env.BASE_URL`); prefixed onto absolute URLs. */
66
+ base?: string;
67
+ /** Content type — `blog` and `changelog` map to richer article types. */
68
+ pageType?: string;
69
+ /** Publish date (string or YAML Date); emitted as ISO `datePublished`. */
70
+ published?: DateInput;
71
+ /** Last-modified date; emitted as ISO `dateModified`. */
72
+ modified?: DateInput;
73
+ /** BCP-47 language tag for `inLanguage`; defaults to `en`. */
74
+ locale?: string;
75
+ breadcrumbs: Crumb[];
76
+ /**
77
+ * Site identity (`seo.organization`, `seo.software`). Both nodes need an
78
+ * absolute `@id`, so they are emitted only when `siteUrl` is set — like the
79
+ * WebSite node.
80
+ */
81
+ identity?: StructuredDataIdentity | null;
82
+ }
83
+ /** A value a schema.org node property can hold. */
84
+ type JsonLdValue = string | number | JsonLdValue[] | JsonLdNode;
85
+ /** A schema.org node: JSON-LD keys to concrete JSON values. */
86
+ export interface JsonLdNode {
87
+ [key: string]: JsonLdValue;
88
+ }
89
+ /**
90
+ * Frontmatter date → ISO 8601, or undefined when absent/unparseable. Shared with
91
+ * the layout's `article:published_time`/`article:modified_time` so both date
92
+ * surfaces treat a malformed date the same way: omit it rather than emit
93
+ * "Invalid Date".
94
+ */
95
+ export declare const toIso: (value: DateInput | undefined) => string | undefined;
96
+ /**
97
+ * Build a schema.org JSON-LD `@graph` for a page: site identity (the WebSite,
98
+ * plus the configured Organization everywhere and the SoftwareApplication on
99
+ * the homepage), the page as an article, and its breadcrumb trail. Returns
100
+ * null when there is nothing useful to emit (e.g. the homepage without a
101
+ * configured site). URLs are absolute when `siteUrl` is set, otherwise
102
+ * route-relative.
103
+ */
104
+ export declare const buildStructuredData: (input: StructuredDataInput) => JsonLdNode | null;
105
+ export {};
@@ -20,6 +20,11 @@ export interface RemoteFontConfig {
20
20
  provider?: RemoteFontProvider;
21
21
  /** Weights (or variable ranges like `"100..900"`) to load. Defaults to `[400, 500, 600, 700]`. */
22
22
  weights?: (number | string)[];
23
+ /**
24
+ * Character subsets to load (`"latin"`, `"vietnamese"`, `"cyrillic"`, …).
25
+ * Defaults to `latin` plus whatever the site's configured locales need.
26
+ */
27
+ subsets?: string[];
23
28
  /** Fallback stack category. Defaults to `"mono"` for the mono role, `"sans"` otherwise. */
24
29
  fallback?: FontCategory;
25
30
  }
@@ -52,6 +57,7 @@ export type FontEntry = {
52
57
  cssVariable: string;
53
58
  fallbacks: string[];
54
59
  name: string;
60
+ subsets: string[];
55
61
  weights: (number | string)[];
56
62
  } | {
57
63
  kind: "local";
@@ -193,19 +199,43 @@ export type FontSlug = keyof typeof GOOGLE_FONTS;
193
199
  export declare const FONT_SLUGS: string[];
194
200
  /** Type guard: is `value` a supported font slug? */
195
201
  export declare const isFontSlug: (value: string) => value is FontSlug;
202
+ /** The shape of a config's `i18n` block the font builders read. */
203
+ export interface FontLocaleSource {
204
+ locales: {
205
+ code: string;
206
+ }[];
207
+ }
208
+ /** The locale codes an optional `i18n` block declares (none when absent). */
209
+ export declare const fontLocaleCodes: (i18n: FontLocaleSource | undefined) => string[];
210
+ /**
211
+ * The subsets the site's locales need: `latin` always, plus each locale's
212
+ * script. A site with no `i18n` block (or only Latin-1 languages) gets just
213
+ * `latin` — Astro's own default — so its CSS and preloads don't change.
214
+ */
215
+ export declare const localeFontSubsets: (locales: string[]) => string[];
196
216
  /** Kebab-case a family name into a slug (`"Noto Sans JP"` -> `"noto-sans-jp"`). */
197
217
  export declare const slugifyFontName: (name: string) => string;
198
- /** The unique Astro `fonts:` entries for the configured roles (deduped). */
199
- export declare const buildFontEntries: (fonts: FontsConfig) => FontEntry[];
218
+ /**
219
+ * The unique Astro `fonts:` entries for the configured roles (deduped).
220
+ * `locales` are the site's configured locale codes; they pick the subsets a
221
+ * remote family loads unless its config pins `subsets` itself.
222
+ */
223
+ export declare const buildFontEntries: (fonts: FontsConfig, locales?: string[]) => FontEntry[];
200
224
  /**
201
225
  * The config-token CSS that points each role's `--blume-font-<role>-src` at the
202
226
  * Astro-populated family variable. Concatenated into the generated entry's
203
227
  * config tokens; empty when no fonts are set so defaults stay the system stacks.
204
228
  */
205
229
  export declare const buildFontsCss: (fonts: FontsConfig) => string;
206
- /** One `<Font>` render in the head: its CSS variable + weights to preload. */
230
+ /**
231
+ * One `<Font>` render in the head: its CSS variable + the weights (and, for
232
+ * providers that split faces by subset, the subsets) to preload. Local and
233
+ * Fontshare faces carry no subset, so those entries leave `preloadSubsets`
234
+ * unset and preload by weight alone.
235
+ */
207
236
  export interface FontHead {
208
237
  cssVariable: string;
238
+ preloadSubsets?: string[];
209
239
  preloadWeights: number[];
210
240
  }
211
241
  /**
@@ -213,4 +243,4 @@ export interface FontHead {
213
243
  * by CSS variable with preload weights unioned across the roles that share a
214
244
  * family (so `display` and `body` both set to Inter preload 400/500/600 once).
215
245
  */
216
- export declare const configuredFonts: (fonts: FontsConfig) => FontHead[];
246
+ export declare const configuredFonts: (fonts: FontsConfig, locales?: string[]) => FontHead[];