blodemd 0.1.0 → 0.2.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 (289) hide show
  1. package/dist/cli.mjs +50 -174
  2. package/dist/cli.mjs.map +1 -1
  3. package/package.json +3 -36
  4. package/dev-server/app/[[...slug]]/page.tsx +0 -140
  5. package/dev-server/app/blodemd-dev/invalidate/route.ts +0 -12
  6. package/dev-server/app/blodemd-dev/static/[...path]/route.ts +0 -32
  7. package/dev-server/app/blodemd-dev/version/route.ts +0 -14
  8. package/dev-server/app/blodemd-internal/proxy/route.ts +0 -86
  9. package/dev-server/app/error.tsx +0 -24
  10. package/dev-server/app/favicon.ico +0 -0
  11. package/dev-server/app/globals.css +0 -4
  12. package/dev-server/app/layout.tsx +0 -38
  13. package/dev-server/app/not-found.tsx +0 -18
  14. package/dev-server/app/search/route.ts +0 -17
  15. package/dev-server/components/dev-reload-script.tsx +0 -86
  16. package/dev-server/components/providers.tsx +0 -15
  17. package/dev-server/lib/dev-state.ts +0 -8
  18. package/dev-server/lib/local-content-source.ts +0 -103
  19. package/dev-server/lib/local-runtime.tsx +0 -555
  20. package/dev-server/next-env.d.ts +0 -5
  21. package/dev-server/next.config.js +0 -54
  22. package/dev-server/package.json +0 -61
  23. package/dev-server/postcss.config.mjs +0 -7
  24. package/dev-server/public/glide-variable.woff2 +0 -0
  25. package/dev-server/tsconfig.json +0 -50
  26. package/docs/app/globals.css +0 -471
  27. package/docs/components/animate-ui/primitives/buttons/button.tsx +0 -14
  28. package/docs/components/api/api-playground.tsx +0 -467
  29. package/docs/components/api/api-reference.tsx +0 -157
  30. package/docs/components/content/collection-index.tsx +0 -114
  31. package/docs/components/docs/contextual-menu.tsx +0 -495
  32. package/docs/components/docs/copy-page-menu.tsx +0 -364
  33. package/docs/components/docs/doc-header.tsx +0 -223
  34. package/docs/components/docs/doc-shell.tsx +0 -355
  35. package/docs/components/docs/doc-sidebar.tsx +0 -256
  36. package/docs/components/docs/doc-toc.tsx +0 -46
  37. package/docs/components/docs/mobile-nav.tsx +0 -195
  38. package/docs/components/docs/sidebar-active-highlight.tsx +0 -34
  39. package/docs/components/docs/sidebar-scroll-area.tsx +0 -63
  40. package/docs/components/git/repo-picker.tsx +0 -529
  41. package/docs/components/icons/doc-icon.tsx +0 -96
  42. package/docs/components/mdx/accordion.tsx +0 -83
  43. package/docs/components/mdx/agent-instructions.tsx +0 -17
  44. package/docs/components/mdx/badge.tsx +0 -79
  45. package/docs/components/mdx/callout.tsx +0 -88
  46. package/docs/components/mdx/card.tsx +0 -110
  47. package/docs/components/mdx/code-block.tsx +0 -80
  48. package/docs/components/mdx/code-group.tsx +0 -203
  49. package/docs/components/mdx/color.tsx +0 -87
  50. package/docs/components/mdx/columns.tsx +0 -25
  51. package/docs/components/mdx/expandable.tsx +0 -45
  52. package/docs/components/mdx/field-layout.tsx +0 -77
  53. package/docs/components/mdx/frame.tsx +0 -23
  54. package/docs/components/mdx/get-text-content.ts +0 -18
  55. package/docs/components/mdx/icon.tsx +0 -12
  56. package/docs/components/mdx/iframe.tsx +0 -62
  57. package/docs/components/mdx/index.tsx +0 -121
  58. package/docs/components/mdx/installer.tsx +0 -20
  59. package/docs/components/mdx/panel.tsx +0 -11
  60. package/docs/components/mdx/param-field.tsx +0 -56
  61. package/docs/components/mdx/preview.tsx +0 -36
  62. package/docs/components/mdx/prompt.tsx +0 -63
  63. package/docs/components/mdx/request-example.tsx +0 -27
  64. package/docs/components/mdx/response-field.tsx +0 -42
  65. package/docs/components/mdx/steps.tsx +0 -92
  66. package/docs/components/mdx/tabs.tsx +0 -193
  67. package/docs/components/mdx/tile.tsx +0 -43
  68. package/docs/components/mdx/tooltip.tsx +0 -71
  69. package/docs/components/mdx/tree.tsx +0 -120
  70. package/docs/components/mdx/type-table.tsx +0 -71
  71. package/docs/components/mdx/update.tsx +0 -44
  72. package/docs/components/mdx/video.tsx +0 -45
  73. package/docs/components/mdx/view.tsx +0 -66
  74. package/docs/components/posthog-provider.tsx +0 -42
  75. package/docs/components/providers.tsx +0 -15
  76. package/docs/components/tenant-analytics.tsx +0 -49
  77. package/docs/components/third-parties.tsx +0 -32
  78. package/docs/components/ui/badge.tsx +0 -61
  79. package/docs/components/ui/breadcrumb.tsx +0 -112
  80. package/docs/components/ui/button-group.tsx +0 -83
  81. package/docs/components/ui/button.tsx +0 -65
  82. package/docs/components/ui/card.tsx +0 -92
  83. package/docs/components/ui/command.tsx +0 -167
  84. package/docs/components/ui/copy-button.tsx +0 -129
  85. package/docs/components/ui/dialog.tsx +0 -146
  86. package/docs/components/ui/field.tsx +0 -237
  87. package/docs/components/ui/input.tsx +0 -23
  88. package/docs/components/ui/kbd.tsx +0 -98
  89. package/docs/components/ui/label.tsx +0 -22
  90. package/docs/components/ui/morph-icon.tsx +0 -79
  91. package/docs/components/ui/popover.tsx +0 -267
  92. package/docs/components/ui/search-dialog.tsx +0 -431
  93. package/docs/components/ui/search.tsx +0 -101
  94. package/docs/components/ui/separator.tsx +0 -26
  95. package/docs/components/ui/sheet.tsx +0 -133
  96. package/docs/components/ui/sidebar.tsx +0 -758
  97. package/docs/components/ui/skeleton.tsx +0 -11
  98. package/docs/components/ui/switch.tsx +0 -32
  99. package/docs/components/ui/tabs.tsx +0 -138
  100. package/docs/components/ui/theme-toggle.tsx +0 -62
  101. package/docs/components/ui/tooltip.tsx +0 -53
  102. package/docs/components/web-mcp.tsx +0 -115
  103. package/docs/lib/agent-skills.ts +0 -48
  104. package/docs/lib/api-client.ts +0 -72
  105. package/docs/lib/config.ts +0 -6
  106. package/docs/lib/content-root.ts +0 -33
  107. package/docs/lib/content-source.ts +0 -70
  108. package/docs/lib/contextual-options.ts +0 -222
  109. package/docs/lib/dashboard-session.ts +0 -167
  110. package/docs/lib/db.ts +0 -13
  111. package/docs/lib/docs-collection.ts +0 -7
  112. package/docs/lib/docs-runtime.tsx +0 -745
  113. package/docs/lib/edge-config.ts +0 -95
  114. package/docs/lib/env.ts +0 -23
  115. package/docs/lib/etag.ts +0 -22
  116. package/docs/lib/github-install.ts +0 -33
  117. package/docs/lib/llms-full.ts +0 -82
  118. package/docs/lib/marketing-markdown.ts +0 -79
  119. package/docs/lib/marketing-site.ts +0 -31
  120. package/docs/lib/mdx.ts +0 -98
  121. package/docs/lib/navigation.ts +0 -288
  122. package/docs/lib/openapi-proxy.ts +0 -88
  123. package/docs/lib/openapi.ts +0 -158
  124. package/docs/lib/platform-config.ts +0 -6
  125. package/docs/lib/project-authz.ts +0 -46
  126. package/docs/lib/routes.ts +0 -103
  127. package/docs/lib/server-cache.ts +0 -83
  128. package/docs/lib/shiki.ts +0 -44
  129. package/docs/lib/supabase.ts +0 -37
  130. package/docs/lib/tenancy.ts +0 -364
  131. package/docs/lib/tenant-headers.ts +0 -43
  132. package/docs/lib/tenant-static.ts +0 -705
  133. package/docs/lib/tenant-utility-context.ts +0 -62
  134. package/docs/lib/tenants.ts +0 -72
  135. package/docs/lib/theme.ts +0 -29
  136. package/docs/lib/time-ago.ts +0 -24
  137. package/docs/lib/toc.ts +0 -2
  138. package/docs/lib/use-mobile.ts +0 -19
  139. package/docs/lib/use-tab-observer.ts +0 -71
  140. package/docs/lib/utils.ts +0 -5
  141. package/packages/@repo/common/dist/index.d.ts +0 -16
  142. package/packages/@repo/common/dist/index.d.ts.map +0 -1
  143. package/packages/@repo/common/dist/index.js +0 -84
  144. package/packages/@repo/common/package.json +0 -34
  145. package/packages/@repo/common/src/index.ts +0 -101
  146. package/packages/@repo/contracts/dist/analytics.d.ts +0 -21
  147. package/packages/@repo/contracts/dist/analytics.d.ts.map +0 -1
  148. package/packages/@repo/contracts/dist/analytics.js +0 -18
  149. package/packages/@repo/contracts/dist/api-key.d.ts +0 -27
  150. package/packages/@repo/contracts/dist/api-key.d.ts.map +0 -1
  151. package/packages/@repo/contracts/dist/api-key.js +0 -20
  152. package/packages/@repo/contracts/dist/dates.d.ts +0 -4
  153. package/packages/@repo/contracts/dist/dates.d.ts.map +0 -1
  154. package/packages/@repo/contracts/dist/dates.js +0 -2
  155. package/packages/@repo/contracts/dist/deployment.d.ts +0 -71
  156. package/packages/@repo/contracts/dist/deployment.d.ts.map +0 -1
  157. package/packages/@repo/contracts/dist/deployment.js +0 -46
  158. package/packages/@repo/contracts/dist/domain.d.ts +0 -94
  159. package/packages/@repo/contracts/dist/domain.d.ts.map +0 -1
  160. package/packages/@repo/contracts/dist/domain.js +0 -36
  161. package/packages/@repo/contracts/dist/git.d.ts +0 -28
  162. package/packages/@repo/contracts/dist/git.d.ts.map +0 -1
  163. package/packages/@repo/contracts/dist/git.js +0 -24
  164. package/packages/@repo/contracts/dist/ids.d.ts +0 -14
  165. package/packages/@repo/contracts/dist/ids.d.ts.map +0 -1
  166. package/packages/@repo/contracts/dist/ids.js +0 -11
  167. package/packages/@repo/contracts/dist/index.d.ts +0 -12
  168. package/packages/@repo/contracts/dist/index.d.ts.map +0 -1
  169. package/packages/@repo/contracts/dist/index.js +0 -13
  170. package/packages/@repo/contracts/dist/pagination.d.ts +0 -23
  171. package/packages/@repo/contracts/dist/pagination.d.ts.map +0 -1
  172. package/packages/@repo/contracts/dist/pagination.js +0 -15
  173. package/packages/@repo/contracts/dist/project.d.ts +0 -42
  174. package/packages/@repo/contracts/dist/project.d.ts.map +0 -1
  175. package/packages/@repo/contracts/dist/project.js +0 -25
  176. package/packages/@repo/contracts/dist/tenant.d.ts +0 -147
  177. package/packages/@repo/contracts/dist/tenant.d.ts.map +0 -1
  178. package/packages/@repo/contracts/dist/tenant.js +0 -58
  179. package/packages/@repo/contracts/dist/user.d.ts +0 -9
  180. package/packages/@repo/contracts/dist/user.d.ts.map +0 -1
  181. package/packages/@repo/contracts/dist/user.js +0 -9
  182. package/packages/@repo/contracts/package.json +0 -37
  183. package/packages/@repo/contracts/src/analytics.ts +0 -33
  184. package/packages/@repo/contracts/src/api-key.ts +0 -27
  185. package/packages/@repo/contracts/src/dates.ts +0 -4
  186. package/packages/@repo/contracts/src/deployment.ts +0 -73
  187. package/packages/@repo/contracts/src/domain.ts +0 -51
  188. package/packages/@repo/contracts/src/git.ts +0 -31
  189. package/packages/@repo/contracts/src/ids.ts +0 -23
  190. package/packages/@repo/contracts/src/index.ts +0 -13
  191. package/packages/@repo/contracts/src/pagination.ts +0 -21
  192. package/packages/@repo/contracts/src/project.ts +0 -32
  193. package/packages/@repo/contracts/src/tenant.ts +0 -94
  194. package/packages/@repo/contracts/src/user.ts +0 -12
  195. package/packages/@repo/models/dist/docs-config.d.ts +0 -961
  196. package/packages/@repo/models/dist/docs-config.d.ts.map +0 -1
  197. package/packages/@repo/models/dist/docs-config.js +0 -531
  198. package/packages/@repo/models/dist/index.d.ts +0 -3
  199. package/packages/@repo/models/dist/index.d.ts.map +0 -1
  200. package/packages/@repo/models/dist/index.js +0 -3
  201. package/packages/@repo/models/dist/tenant.d.ts +0 -37
  202. package/packages/@repo/models/dist/tenant.d.ts.map +0 -1
  203. package/packages/@repo/models/dist/tenant.js +0 -1
  204. package/packages/@repo/models/package.json +0 -37
  205. package/packages/@repo/models/src/docs-config.ts +0 -629
  206. package/packages/@repo/models/src/index.ts +0 -3
  207. package/packages/@repo/models/src/tenant.ts +0 -44
  208. package/packages/@repo/prebuild/dist/index.d.ts +0 -2
  209. package/packages/@repo/prebuild/dist/index.d.ts.map +0 -1
  210. package/packages/@repo/prebuild/dist/index.js +0 -2
  211. package/packages/@repo/prebuild/dist/openapi.d.ts +0 -43
  212. package/packages/@repo/prebuild/dist/openapi.d.ts.map +0 -1
  213. package/packages/@repo/prebuild/dist/openapi.js +0 -86
  214. package/packages/@repo/prebuild/package.json +0 -39
  215. package/packages/@repo/prebuild/src/index.ts +0 -2
  216. package/packages/@repo/prebuild/src/openapi.ts +0 -154
  217. package/packages/@repo/previewing/dist/blob-source.d.ts +0 -16
  218. package/packages/@repo/previewing/dist/blob-source.d.ts.map +0 -1
  219. package/packages/@repo/previewing/dist/blob-source.js +0 -128
  220. package/packages/@repo/previewing/dist/config-loader.d.ts +0 -134
  221. package/packages/@repo/previewing/dist/config-loader.d.ts.map +0 -1
  222. package/packages/@repo/previewing/dist/config-loader.js +0 -231
  223. package/packages/@repo/previewing/dist/constants.d.ts +0 -15
  224. package/packages/@repo/previewing/dist/constants.d.ts.map +0 -1
  225. package/packages/@repo/previewing/dist/constants.js +0 -14
  226. package/packages/@repo/previewing/dist/content-index.d.ts +0 -7
  227. package/packages/@repo/previewing/dist/content-index.d.ts.map +0 -1
  228. package/packages/@repo/previewing/dist/content-index.js +0 -291
  229. package/packages/@repo/previewing/dist/content-source.d.ts +0 -12
  230. package/packages/@repo/previewing/dist/content-source.d.ts.map +0 -1
  231. package/packages/@repo/previewing/dist/content-source.js +0 -1
  232. package/packages/@repo/previewing/dist/fs-source.d.ts +0 -11
  233. package/packages/@repo/previewing/dist/fs-source.d.ts.map +0 -1
  234. package/packages/@repo/previewing/dist/fs-source.js +0 -71
  235. package/packages/@repo/previewing/dist/index.d.ts +0 -16
  236. package/packages/@repo/previewing/dist/index.d.ts.map +0 -1
  237. package/packages/@repo/previewing/dist/index.js +0 -13
  238. package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts +0 -3
  239. package/packages/@repo/previewing/dist/markdown/agent-markdown.d.ts.map +0 -1
  240. package/packages/@repo/previewing/dist/markdown/agent-markdown.js +0 -176
  241. package/packages/@repo/previewing/dist/markdown/format.d.ts +0 -8
  242. package/packages/@repo/previewing/dist/markdown/format.d.ts.map +0 -1
  243. package/packages/@repo/previewing/dist/markdown/format.js +0 -43
  244. package/packages/@repo/previewing/dist/markdown/links.d.ts +0 -3
  245. package/packages/@repo/previewing/dist/markdown/links.d.ts.map +0 -1
  246. package/packages/@repo/previewing/dist/markdown/links.js +0 -31
  247. package/packages/@repo/previewing/dist/openapi-pages.d.ts +0 -7
  248. package/packages/@repo/previewing/dist/openapi-pages.d.ts.map +0 -1
  249. package/packages/@repo/previewing/dist/openapi-pages.js +0 -200
  250. package/packages/@repo/previewing/dist/search-index.d.ts +0 -4
  251. package/packages/@repo/previewing/dist/search-index.d.ts.map +0 -1
  252. package/packages/@repo/previewing/dist/search-index.js +0 -23
  253. package/packages/@repo/previewing/dist/serialization.d.ts +0 -13
  254. package/packages/@repo/previewing/dist/serialization.d.ts.map +0 -1
  255. package/packages/@repo/previewing/dist/serialization.js +0 -108
  256. package/packages/@repo/previewing/dist/toc-index.d.ts +0 -5
  257. package/packages/@repo/previewing/dist/toc-index.d.ts.map +0 -1
  258. package/packages/@repo/previewing/dist/toc-index.js +0 -53
  259. package/packages/@repo/previewing/dist/types.d.ts +0 -92
  260. package/packages/@repo/previewing/dist/types.d.ts.map +0 -1
  261. package/packages/@repo/previewing/dist/types.js +0 -1
  262. package/packages/@repo/previewing/dist/utility-index.d.ts +0 -7
  263. package/packages/@repo/previewing/dist/utility-index.d.ts.map +0 -1
  264. package/packages/@repo/previewing/dist/utility-index.js +0 -201
  265. package/packages/@repo/previewing/package.json +0 -41
  266. package/packages/@repo/previewing/src/blob-source.ts +0 -185
  267. package/packages/@repo/previewing/src/config-loader.ts +0 -316
  268. package/packages/@repo/previewing/src/constants.ts +0 -16
  269. package/packages/@repo/previewing/src/content-index.ts +0 -384
  270. package/packages/@repo/previewing/src/content-source.ts +0 -12
  271. package/packages/@repo/previewing/src/fs-source.ts +0 -103
  272. package/packages/@repo/previewing/src/index.ts +0 -71
  273. package/packages/@repo/previewing/src/markdown/agent-markdown.ts +0 -254
  274. package/packages/@repo/previewing/src/markdown/format.ts +0 -63
  275. package/packages/@repo/previewing/src/markdown/links.ts +0 -46
  276. package/packages/@repo/previewing/src/openapi-pages.ts +0 -319
  277. package/packages/@repo/previewing/src/search-index.ts +0 -38
  278. package/packages/@repo/previewing/src/serialization.ts +0 -191
  279. package/packages/@repo/previewing/src/toc-index.ts +0 -72
  280. package/packages/@repo/previewing/src/types.ts +0 -105
  281. package/packages/@repo/previewing/src/utility-index.ts +0 -304
  282. package/packages/@repo/validation/dist/index.d.ts +0 -12
  283. package/packages/@repo/validation/dist/index.d.ts.map +0 -1
  284. package/packages/@repo/validation/dist/index.js +0 -30
  285. package/packages/@repo/validation/package.json +0 -38
  286. package/packages/@repo/validation/src/blodemd-docs-schema.json +0 -3575
  287. package/packages/@repo/validation/src/index.ts +0 -59
  288. package/scripts/prepare-package.mjs +0 -53
  289. package/scripts/repo-packages.mjs +0 -8
@@ -1,745 +0,0 @@
1
- import { normalizePath } from "@repo/common";
2
- import type { PageMode, Tenant } from "@repo/models";
3
- import {
4
- buildContentIndex,
5
- buildPageMetadataMap,
6
- buildSearchIndex,
7
- buildUtilityIndex,
8
- loadPrebuiltContentIndex,
9
- loadPrebuiltSearchIndex,
10
- loadPrebuiltTocIndex,
11
- loadPrebuiltUtilityIndex,
12
- loadSiteConfig,
13
- } from "@repo/previewing";
14
- import type {
15
- ContentIndex,
16
- ContentSource,
17
- PageMetadata,
18
- SearchIndexItem,
19
- TocItem,
20
- UtilityIndex,
21
- } from "@repo/previewing";
22
- import { cache } from "react";
23
-
24
- import {
25
- getTenantContentSource,
26
- resolveSiteConfigAssets,
27
- } from "@/lib/content-source";
28
- import { contextualOptionsRequirePageContent } from "@/lib/contextual-options";
29
- import {
30
- getDocsCollection,
31
- getDocsCollectionWithNavigation,
32
- getDocsNavigation,
33
- } from "@/lib/docs-collection";
34
- import { renderFromCompiled, renderMdx } from "@/lib/mdx";
35
- import {
36
- buildNavigation,
37
- buildTabbedNavigation,
38
- enrichNavWithMetadata,
39
- findActiveTabIndex,
40
- findBreadcrumbs,
41
- flattenNav,
42
- getVisibleNavigation,
43
- } from "@/lib/navigation";
44
- import type { NavEntry, NavPage, NavTab } from "@/lib/navigation";
45
- import { loadOpenApiRegistry } from "@/lib/openapi";
46
- import type { OpenApiRegistry } from "@/lib/openapi";
47
- import { createTimedPromiseCache } from "@/lib/server-cache";
48
- import { getTenantBySlug } from "@/lib/tenants";
49
- import { extractToc } from "@/lib/toc";
50
-
51
- interface ConfigErrorResult {
52
- configErrors: string[];
53
- configWarnings: string[];
54
- tenant: Tenant;
55
- }
56
-
57
- interface UnpublishedTenantResult {
58
- emptyState: "unpublished";
59
- tenant: Tenant;
60
- }
61
-
62
- interface RenderedPageData {
63
- content: Awaited<ReturnType<typeof renderMdx>>["content"];
64
- frontmatter: Awaited<ReturnType<typeof renderMdx>>["frontmatter"];
65
- rawContent?: string;
66
- toc: ReturnType<typeof extractToc>;
67
- }
68
-
69
- interface TenantArtifacts {
70
- anchors: { label: string; href: string }[];
71
- config: Awaited<ReturnType<typeof resolveSiteConfigAssets>>;
72
- contentIndex: ContentIndex;
73
- contentSource: ContentSource;
74
- flatNav: NavPage[];
75
- pageMetadataMap: Map<string, PageMetadata>;
76
- registry: OpenApiRegistry;
77
- tabs: NavTab[] | null;
78
- tenant: Tenant;
79
- tocBySlug: Map<string, TocItem[]>;
80
- visibleFlatNav: NavPage[];
81
- visibleNav: NavEntry[];
82
- }
83
-
84
- type TenantArtifactsResult =
85
- | ConfigErrorResult
86
- | TenantArtifacts
87
- | UnpublishedTenantResult
88
- | null;
89
-
90
- const ARTIFACT_CACHE_TTL_MS = 30 * 60 * 1000;
91
- const PAGE_RENDER_CACHE_TTL_MS = 4 * 60 * 60 * 1000;
92
-
93
- const artifactsCache = createTimedPromiseCache<string, TenantArtifactsResult>({
94
- maxEntries: 512,
95
- ttlMs: ARTIFACT_CACHE_TTL_MS,
96
- });
97
-
98
- const searchItemsCache = createTimedPromiseCache<string, SearchIndexItem[]>({
99
- maxEntries: 512,
100
- ttlMs: ARTIFACT_CACHE_TTL_MS,
101
- });
102
-
103
- const renderedPageCache = createTimedPromiseCache<string, RenderedPageData>({
104
- maxEntries: 2048,
105
- ttlMs: PAGE_RENDER_CACHE_TTL_MS,
106
- });
107
-
108
- const isConfigErrorResult = (
109
- value: TenantArtifactsResult
110
- ): value is ConfigErrorResult => Boolean(value && "configErrors" in value);
111
-
112
- const isUnpublishedTenantResult = (
113
- value: TenantArtifactsResult
114
- ): value is UnpublishedTenantResult => Boolean(value && "emptyState" in value);
115
-
116
- const getTenantArtifactsCacheKey = (tenant: Tenant) =>
117
- [
118
- tenant.id,
119
- tenant.slug,
120
- tenant.activeDeploymentId ?? "",
121
- tenant.activeDeploymentManifestUrl ?? "",
122
- tenant.docsPath ?? "",
123
- tenant.pathPrefix ?? "",
124
- tenant.primaryDomain,
125
- ].join(":");
126
-
127
- const buildSearchItems = ({
128
- config,
129
- contentIndex,
130
- utilityIndex,
131
- }: {
132
- config: TenantArtifacts["config"];
133
- contentIndex: ContentIndex;
134
- utilityIndex?: UtilityIndex | null;
135
- }) => buildSearchIndex(contentIndex, config, utilityIndex ?? undefined);
136
-
137
- const mergeSearchItems = ({
138
- baseItems,
139
- config,
140
- flatNav,
141
- visibleFlatNav,
142
- }: {
143
- baseItems: SearchIndexItem[];
144
- config: TenantArtifacts["config"];
145
- flatNav: NavPage[];
146
- visibleFlatNav: NavPage[];
147
- }): SearchIndexItem[] => {
148
- const items = new Map<string, SearchIndexItem>(
149
- baseItems.map((item) => [item.path, item])
150
- );
151
-
152
- for (const item of visibleFlatNav) {
153
- items.set(item.path, {
154
- href: item.url,
155
- path: item.path,
156
- title: item.sidebarTitle ?? item.title,
157
- });
158
- }
159
-
160
- if (config.seo?.indexing === "all") {
161
- for (const item of flatNav) {
162
- if (!items.has(item.path)) {
163
- items.set(item.path, {
164
- href: item.url,
165
- path: item.path,
166
- title: item.sidebarTitle ?? item.title,
167
- });
168
- }
169
- }
170
- }
171
-
172
- return [...items.values()];
173
- };
174
-
175
- const getTenantArtifacts = async (tenantSlug: string) => {
176
- const tenant = await getTenantBySlug(tenantSlug);
177
- if (!tenant) {
178
- return null;
179
- }
180
-
181
- const cacheKey = getTenantArtifactsCacheKey(tenant);
182
-
183
- return await artifactsCache.getOrCreate(cacheKey, async () => {
184
- const contentSource = getTenantContentSource(tenant);
185
- const configResult = await loadSiteConfig(contentSource);
186
- if (!configResult.ok) {
187
- if (
188
- !tenant.activeDeploymentManifestUrl &&
189
- configResult.errors.length === 1 &&
190
- configResult.errors[0] === "docs.json not found."
191
- ) {
192
- return {
193
- emptyState: "unpublished" as const,
194
- tenant,
195
- };
196
- }
197
-
198
- return {
199
- configErrors: configResult.errors,
200
- configWarnings: [],
201
- tenant,
202
- };
203
- }
204
-
205
- const rawConfig = configResult.config;
206
- const docsCollection = getDocsCollection(rawConfig);
207
- const docsNavigation = getDocsNavigation(rawConfig);
208
- const docsCollectionWithNavigation =
209
- getDocsCollectionWithNavigation(rawConfig);
210
-
211
- const [config, contentIndex, registryResult, prebuiltTocIndex] =
212
- await Promise.all([
213
- resolveSiteConfigAssets(rawConfig, contentSource),
214
- loadPrebuiltContentIndex(contentSource).then(
215
- async (prebuilt) =>
216
- prebuilt ?? (await buildContentIndex(contentSource, rawConfig))
217
- ),
218
- loadOpenApiRegistry(docsCollectionWithNavigation, contentSource)
219
- .then((registry) => ({ ok: true as const, registry }))
220
- .catch((error: unknown) => ({
221
- error,
222
- ok: false as const,
223
- })),
224
- loadPrebuiltTocIndex(contentSource),
225
- ]);
226
-
227
- if (contentIndex.errors.length) {
228
- return {
229
- configErrors: contentIndex.errors,
230
- configWarnings: configResult.warnings,
231
- tenant,
232
- };
233
- }
234
-
235
- if (!registryResult.ok) {
236
- return {
237
- configErrors: [
238
- registryResult.error instanceof Error
239
- ? registryResult.error.message
240
- : "OpenAPI parsing failed",
241
- ],
242
- configWarnings: configResult.warnings,
243
- tenant,
244
- };
245
- }
246
-
247
- const pageMetadataMap = buildPageMetadataMap(contentIndex);
248
- const slugPrefix = docsCollection?.slugPrefix ?? "";
249
- const rawNav = docsNavigation
250
- ? buildNavigation(docsNavigation, registryResult.registry, slugPrefix)
251
- : [];
252
- const nav = enrichNavWithMetadata(rawNav, pageMetadataMap);
253
- const visibleNav = getVisibleNavigation(nav);
254
- const flatNav = flattenNav(nav);
255
- const visibleFlatNav = flattenNav(visibleNav);
256
- const rawTabs = buildTabbedNavigation(
257
- docsNavigation,
258
- registryResult.registry,
259
- slugPrefix
260
- );
261
- const tabs =
262
- rawTabs?.map((tab) => ({
263
- ...tab,
264
- entries: enrichNavWithMetadata(tab.entries, pageMetadataMap),
265
- })) ?? null;
266
-
267
- return {
268
- anchors: docsNavigation?.global?.anchors ?? [],
269
- config,
270
- contentIndex,
271
- contentSource,
272
- flatNav,
273
- pageMetadataMap,
274
- registry: registryResult.registry,
275
- tabs,
276
- tenant,
277
- tocBySlug: prebuiltTocIndex ?? new Map(),
278
- visibleFlatNav,
279
- visibleNav,
280
- };
281
- });
282
- };
283
-
284
- export interface TenantSidebarData {
285
- anchors: { label: string; href: string }[];
286
- entries: NavEntry[];
287
- }
288
-
289
- export const getTenantSidebarData = cache(
290
- async (
291
- tenantSlug: string,
292
- activeTabIndex: number
293
- ): Promise<TenantSidebarData | null> => {
294
- const artifacts = await getTenantArtifacts(tenantSlug);
295
- if (
296
- !artifacts ||
297
- isConfigErrorResult(artifacts) ||
298
- isUnpublishedTenantResult(artifacts)
299
- ) {
300
- return null;
301
- }
302
-
303
- const tabEntries = artifacts.tabs
304
- ? getVisibleNavigation(artifacts.tabs[activeTabIndex]?.entries ?? [])
305
- : null;
306
-
307
- return {
308
- anchors: artifacts.anchors,
309
- entries: tabEntries ?? artifacts.visibleNav,
310
- };
311
- }
312
- );
313
-
314
- export const getTenantSearchItems = cache(async (tenantSlug: string) => {
315
- const artifacts = await getTenantArtifacts(tenantSlug);
316
- if (
317
- !artifacts ||
318
- isConfigErrorResult(artifacts) ||
319
- isUnpublishedTenantResult(artifacts)
320
- ) {
321
- return null;
322
- }
323
-
324
- const cacheKey = `${getTenantArtifactsCacheKey(artifacts.tenant)}:search`;
325
-
326
- return await searchItemsCache.getOrCreate(cacheKey, async () => {
327
- const prebuiltSearchIndex = await loadPrebuiltSearchIndex(
328
- artifacts.contentSource
329
- );
330
- const utilityIndex = prebuiltSearchIndex
331
- ? null
332
- : ((await loadPrebuiltUtilityIndex(artifacts.contentSource)) ??
333
- (await buildUtilityIndex(
334
- artifacts.contentIndex,
335
- artifacts.contentSource,
336
- artifacts.config
337
- )));
338
-
339
- return mergeSearchItems({
340
- baseItems:
341
- prebuiltSearchIndex ??
342
- buildSearchItems({
343
- config: artifacts.config,
344
- contentIndex: artifacts.contentIndex,
345
- utilityIndex,
346
- }),
347
- config: artifacts.config,
348
- flatNav: artifacts.flatNav,
349
- visibleFlatNav: artifacts.visibleFlatNav,
350
- });
351
- });
352
- });
353
-
354
- const getRenderedPageData = async ({
355
- artifacts,
356
- basePath,
357
- currentPath,
358
- relativePath,
359
- rawContent: preloadedRawContent,
360
- toc: preloadedToc,
361
- useToc,
362
- }: {
363
- artifacts: TenantArtifacts;
364
- basePath?: string;
365
- currentPath: string;
366
- relativePath: string;
367
- rawContent?: string;
368
- toc?: TocItem[];
369
- useToc: boolean;
370
- }) => {
371
- const cacheKey = `${getTenantArtifactsCacheKey(artifacts.tenant)}:${basePath ?? ""}:${currentPath}`;
372
-
373
- return await renderedPageCache.getOrCreate(cacheKey, async () => {
374
- const compiled =
375
- await artifacts.contentSource.readCompiledMdx?.(relativePath);
376
- const rawContent =
377
- preloadedRawContent ??
378
- (compiled
379
- ? undefined
380
- : await artifacts.contentSource.readFile(relativePath));
381
- const rendered = compiled
382
- ? await renderFromCompiled(
383
- compiled.compiledSource,
384
- basePath,
385
- relativePath
386
- )
387
- : await renderMdx(rawContent ?? "", basePath, relativePath);
388
-
389
- return {
390
- content: rendered.content,
391
- frontmatter: rendered.frontmatter,
392
- rawContent,
393
- toc: preloadedToc ?? (useToc && rawContent ? extractToc(rawContent) : []),
394
- };
395
- });
396
- };
397
-
398
- export const clearDocsRuntimeCaches = () => {
399
- artifactsCache.clear();
400
- searchItemsCache.clear();
401
- renderedPageCache.clear();
402
- };
403
-
404
- export const clearDocsRuntimeCachesForTenant = (tenantId: string) => {
405
- artifactsCache.deleteByPrefix(tenantId);
406
- searchItemsCache.deleteByPrefix(tenantId);
407
- renderedPageCache.deleteByPrefix(tenantId);
408
- };
409
-
410
- const computePrevNext = (
411
- flatNav: NavPage[],
412
- currentPath: string
413
- ): {
414
- nextPage: { title: string; path: string } | undefined;
415
- prevPage: { title: string; path: string } | undefined;
416
- } => {
417
- const currentIndex = flatNav.findIndex((p) => p.path === currentPath);
418
- return {
419
- nextPage:
420
- currentIndex !== -1 && currentIndex < flatNav.length - 1
421
- ? flatNav[currentIndex + 1]
422
- : undefined,
423
- prevPage: currentIndex > 0 ? flatNav[currentIndex - 1] : undefined,
424
- };
425
- };
426
-
427
- const META_DESCRIPTION_MIN = 120;
428
- const META_DESCRIPTION_MAX = 160;
429
- const META_FRONTMATTER_RE = /^---\s*\n[\s\S]*?\n---\s*\n?/;
430
-
431
- /**
432
- * Reduce raw MDX/Markdown to a single line of readable prose so it can seed a
433
- * meta description when a page has no (or a too-short) frontmatter description.
434
- */
435
- const markdownToPlainText = (markdown: string): string =>
436
- markdown
437
- .replace(META_FRONTMATTER_RE, "")
438
- .replaceAll(/```[\s\S]*?```/g, " ")
439
- .replaceAll(/~~~[\s\S]*?~~~/g, " ")
440
- .replaceAll(/`[^`]*`/g, " ")
441
- .replaceAll(/!\[[^\]]*\]\([^)]*\)/g, " ")
442
- .replaceAll(/\[([^\]]+)\]\([^)]*\)/g, "$1")
443
- .replaceAll(/<[^>]+>/g, " ")
444
- .replaceAll(/^\s{0,3}#{1,6}\s+/gm, "")
445
- .replaceAll(/^\s{0,3}>\s?/gm, "")
446
- .replaceAll(/^\s{0,3}(?:[-*+]|\d+\.)\s+/gm, "")
447
- .replaceAll(/[*_~]+/g, "")
448
- .replaceAll("|", " ")
449
- .replaceAll(/\s+/g, " ")
450
- .trim();
451
-
452
- const normalizeMetaText = (value?: string) =>
453
- value ? value.replaceAll(/\s+/g, " ").trim() : "";
454
-
455
- const truncateMetaDescription = (text: string, max: number): string => {
456
- if (text.length <= max) {
457
- return text;
458
- }
459
- const slice = text.slice(0, max - 1);
460
- const lastSpace = slice.lastIndexOf(" ");
461
- const trimmed = (lastSpace > max * 0.6 ? slice.slice(0, lastSpace) : slice)
462
- .replace(/[\s.,;:–—-]+$/, "")
463
- .trim();
464
- return `${trimmed}…`;
465
- };
466
-
467
- /**
468
- * Build a 120-160 character meta description from (in order of preference) the
469
- * frontmatter description, the page body, and a site-level fallback. Keeps the
470
- * visible page subtitle untouched while giving crawlers a complete description.
471
- */
472
- const deriveMetaDescription = ({
473
- description,
474
- rawText,
475
- fallback,
476
- }: {
477
- description?: string;
478
- rawText?: string;
479
- fallback?: string;
480
- }): string | undefined => {
481
- const frontmatter = normalizeMetaText(description);
482
- if (frontmatter.length >= META_DESCRIPTION_MIN) {
483
- return truncateMetaDescription(frontmatter, META_DESCRIPTION_MAX);
484
- }
485
-
486
- let combined = frontmatter;
487
- const excerpt = rawText ? markdownToPlainText(rawText) : "";
488
- if (excerpt) {
489
- if (
490
- !frontmatter ||
491
- excerpt.toLowerCase().startsWith(frontmatter.toLowerCase())
492
- ) {
493
- combined = excerpt;
494
- } else if (combined.length < META_DESCRIPTION_MIN) {
495
- combined = `${frontmatter} ${excerpt}`;
496
- }
497
- }
498
-
499
- const fallbackText = normalizeMetaText(fallback);
500
- if (
501
- fallbackText &&
502
- normalizeMetaText(combined).length < META_DESCRIPTION_MIN
503
- ) {
504
- combined = combined ? `${combined} ${fallbackText}` : fallbackText;
505
- }
506
-
507
- combined = normalizeMetaText(combined);
508
- return combined
509
- ? truncateMetaDescription(combined, META_DESCRIPTION_MAX)
510
- : undefined;
511
- };
512
-
513
- const buildMetaDescriptionFallback = (
514
- config: { name?: string; description?: string } | undefined,
515
- title: string | undefined
516
- ): string => {
517
- const name = config?.name ?? "Docs";
518
- const lead = title
519
- ? `${title} — ${name} documentation.`
520
- : `${name} documentation.`;
521
- return config?.description ? `${lead} ${config.description}` : lead;
522
- };
523
-
524
- /**
525
- * Returns shell data (config, nav, title, breadcrumbs) from cached artifacts
526
- * without compiling MDX. Used by the page component to render the shell
527
- * immediately while streaming content.
528
- */
529
- export const getDocShellData = cache(
530
- // oxlint-disable-next-line eslint/complexity
531
- async (tenantSlug: string, slugKey: string) => {
532
- const artifacts = await getTenantArtifacts(tenantSlug);
533
- if (
534
- !artifacts ||
535
- isConfigErrorResult(artifacts) ||
536
- isUnpublishedTenantResult(artifacts)
537
- ) {
538
- return artifacts;
539
- }
540
-
541
- const currentPath = normalizePath(slugKey) || "index";
542
- const activeTabIndex = artifacts.tabs
543
- ? findActiveTabIndex(artifacts.tabs, currentPath)
544
- : 0;
545
- const activeTabNav = artifacts.tabs
546
- ? getVisibleNavigation(artifacts.tabs[activeTabIndex]?.entries ?? [])
547
- : null;
548
- const activeTabFlatNav = activeTabNav ? flattenNav(activeTabNav) : null;
549
- const effectiveFlatNav = activeTabFlatNav ?? artifacts.visibleFlatNav;
550
-
551
- const openApiEntry = artifacts.registry.bySlug.get(currentPath);
552
- if (openApiEntry) {
553
- const isHidden = artifacts.flatNav.some(
554
- (page) => page.path === currentPath && page.hidden
555
- );
556
- return {
557
- activeTabIndex,
558
- anchors: artifacts.anchors,
559
- breadcrumbs: findBreadcrumbs(
560
- activeTabNav ?? artifacts.visibleNav,
561
- currentPath
562
- ),
563
- config: artifacts.config,
564
- currentPath,
565
- deprecated: false,
566
- hidden: isHidden,
567
- hideFooterPagination: false,
568
- kind: "openapi" as const,
569
- metaDescription: deriveMetaDescription({
570
- description: openApiEntry.operation.description,
571
- fallback: buildMetaDescriptionFallback(
572
- artifacts.config,
573
- openApiEntry.operation.summary ?? openApiEntry.identifier
574
- ),
575
- }),
576
- mode: undefined as PageMode | undefined,
577
- nav: activeTabNav ?? artifacts.visibleNav,
578
- nextPage: computePrevNext(effectiveFlatNav, currentPath).nextPage,
579
- noindex: false,
580
- openApiEntry,
581
- openapiProxyEnabled: artifacts.config.openapiProxy?.enabled ?? false,
582
- pageDescription: openApiEntry.operation.description,
583
- pageTitle: openApiEntry.operation.summary ?? openApiEntry.identifier,
584
- prevPage: computePrevNext(effectiveFlatNav, currentPath).prevPage,
585
- tabs: artifacts.tabs,
586
- tenant: artifacts.tenant,
587
- };
588
- }
589
-
590
- const entry = artifacts.contentIndex.bySlug.get(currentPath) ?? null;
591
- if (!entry) {
592
- return null;
593
- }
594
-
595
- if (entry.kind === "index") {
596
- const collectionEntries =
597
- artifacts.contentIndex.byCollection
598
- .get(entry.collectionId)
599
- ?.filter(
600
- (
601
- collectionEntry
602
- ): collectionEntry is Extract<
603
- (typeof artifacts.contentIndex.entries)[number],
604
- { kind: "entry" }
605
- > =>
606
- collectionEntry.kind === "entry" &&
607
- collectionEntry.hidden !== true &&
608
- !artifacts.pageMetadataMap.get(collectionEntry.slug)?.hidden &&
609
- !artifacts.pageMetadataMap.get(collectionEntry.slug)?.noindex
610
- ) ?? [];
611
- const showDocsNav = entry.type === "docs";
612
- return {
613
- activeTabIndex,
614
- anchors: showDocsNav ? artifacts.anchors : [],
615
- breadcrumbs: [] as { label: string; path: string }[],
616
- collectionIndex: { entries: collectionEntries },
617
- config: artifacts.config,
618
- currentPath,
619
- deprecated: false,
620
- hidden: false,
621
- hideFooterPagination: false,
622
- kind: "index" as const,
623
- metaDescription: deriveMetaDescription({
624
- description: entry.description,
625
- fallback: buildMetaDescriptionFallback(artifacts.config, entry.title),
626
- }),
627
- mode: undefined as PageMode | undefined,
628
- nav: showDocsNav ? (activeTabNav ?? artifacts.visibleNav) : [],
629
- nextPage: computePrevNext(effectiveFlatNav, currentPath).nextPage,
630
- noindex: false,
631
- pageDescription: entry.description,
632
- pageTitle: entry.title,
633
- prevPage: computePrevNext(effectiveFlatNav, currentPath).prevPage,
634
- tabs: artifacts.tabs,
635
- tenant: artifacts.tenant,
636
- };
637
- }
638
-
639
- const showDocsNav = entry.type === "docs";
640
- const breadcrumbs = showDocsNav
641
- ? findBreadcrumbs(activeTabNav ?? artifacts.visibleNav, currentPath)
642
- : [];
643
- const pageMeta = artifacts.pageMetadataMap.get(currentPath);
644
- const isHiddenByNav = artifacts.flatNav.some(
645
- (page) => page.path === currentPath && page.hidden
646
- );
647
- const { nextPage, prevPage } = computePrevNext(
648
- effectiveFlatNav,
649
- currentPath
650
- );
651
- const useToc =
652
- entry.type === "docs" && artifacts.config.features?.toc !== false;
653
-
654
- const prebuiltToc = artifacts.tocBySlug.get(currentPath) ?? null;
655
- const needsRawContent = artifacts.config.contextual
656
- ? contextualOptionsRequirePageContent(artifacts.config.contextual.options)
657
- : false;
658
-
659
- // Load the body when we need a TOC, contextual content, or a body excerpt
660
- // to flesh out a short/missing frontmatter description for SEO.
661
- const needsExcerpt = (entry.description ?? "").trim().length < 120;
662
- let rawContent: string | undefined;
663
- let toc: ReturnType<typeof extractToc> = prebuiltToc ?? [];
664
- if ((!prebuiltToc && useToc) || needsRawContent || needsExcerpt) {
665
- try {
666
- rawContent = await artifacts.contentSource.readFile(entry.relativePath);
667
- if (!prebuiltToc && useToc) {
668
- toc = extractToc(rawContent);
669
- }
670
- } catch {
671
- // Content load failure is handled by the content rendering path
672
- }
673
- }
674
-
675
- return {
676
- activeTabIndex,
677
- anchors: showDocsNav ? artifacts.anchors : [],
678
- breadcrumbs,
679
- config: artifacts.config,
680
- currentPath,
681
- deprecated: pageMeta?.deprecated ?? false,
682
- hidden: isHiddenByNav || entry.hidden === true,
683
- hideFooterPagination: pageMeta?.hideFooterPagination ?? false,
684
- kind: "page" as const,
685
- metaDescription: deriveMetaDescription({
686
- description: entry.description,
687
- fallback: buildMetaDescriptionFallback(artifacts.config, entry.title),
688
- rawText: rawContent,
689
- }),
690
- mode: pageMeta?.mode,
691
- nav: showDocsNav ? (activeTabNav ?? artifacts.visibleNav) : [],
692
- nextPage,
693
- noindex: pageMeta?.noindex ?? false,
694
- pageDescription: entry.description,
695
- pageTitle: entry.title,
696
- prevPage,
697
- rawContent,
698
- tabs: artifacts.tabs,
699
- tenant: artifacts.tenant,
700
- toc,
701
- };
702
- }
703
- );
704
-
705
- /**
706
- * Compiles MDX content for a specific page. Uses pre-compiled content
707
- * from deploy when available, otherwise falls back to runtime compilation.
708
- */
709
- export const getDocPageContent = cache(
710
- async (
711
- tenantSlug: string,
712
- slugKey: string,
713
- basePath = "",
714
- rawContent?: string,
715
- toc?: TocItem[]
716
- ) => {
717
- const artifacts = await getTenantArtifacts(tenantSlug);
718
- if (
719
- !artifacts ||
720
- isConfigErrorResult(artifacts) ||
721
- isUnpublishedTenantResult(artifacts)
722
- ) {
723
- return null;
724
- }
725
-
726
- const currentPath = normalizePath(slugKey) || "index";
727
- const entry = artifacts.contentIndex.bySlug.get(currentPath) ?? null;
728
- if (!entry || entry.kind !== "entry") {
729
- return null;
730
- }
731
-
732
- const useToc =
733
- entry.type === "docs" && artifacts.config.features?.toc !== false;
734
-
735
- return await getRenderedPageData({
736
- artifacts,
737
- basePath,
738
- currentPath,
739
- rawContent,
740
- relativePath: entry.relativePath,
741
- toc,
742
- useToc,
743
- });
744
- }
745
- );